src/Proton/Engine/Implementation/ProtonEngineHandlerContext.cs (148 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using Apache.Qpid.Proton.Buffer; using Apache.Qpid.Proton.Engine.Exceptions; namespace Apache.Qpid.Proton.Engine.Implementation { /// <summary> /// A context object that is assigned to each new engine handler that is inserted into an /// engine handler pipeline. /// </summary> public class ProtonEngineHandlerContext : IEngineHandlerContext { /// <summary> /// The context indicator for a handler that wants to be sent read events. /// </summary> public static readonly uint HANDLER_READS = 1 << 1; /// <summary> /// The context indicator for a handler that wants to be sent write events. /// </summary> public static readonly uint HANDLER_WRITES = 1 << 2; /// <summary> /// The context indicator for a handler that wants to be sent all read and write events. /// </summary> public static readonly uint HANDLER_ALL_EVENTS = HANDLER_READS | HANDLER_WRITES; internal ProtonEngineHandlerContext previous; internal ProtonEngineHandlerContext next; private readonly string name; private readonly IEngine engine; private readonly IEngineHandler handler; private uint interestMask = HANDLER_ALL_EVENTS; public ProtonEngineHandlerContext(string name, IEngine engine, IEngineHandler handler) { this.name = name; this.engine = engine; this.handler = handler; } public IEngineHandler Handler => handler; public IEngine Engine => engine; public string Name => name; /// <summary> /// Allows a handler to indicate if it wants to be notified of a Engine Handler events for /// specific operations or opt into all engine handler events. By opting out of the events /// that the handler does not process the call chain can be reduced when processing engine /// events. /// </summary> public uint InterestMask { get => interestMask; set => interestMask = value; } public virtual void FireEngineStarting() { next.InvokeEngineStarting(); } public virtual void FireEngineStateChanged() { next.InvokeEngineStateChanged(); } public virtual void FireFailed(EngineFailedException ex) { next.InvokeEngineFailed(ex); } public virtual void FireRead(IProtonBuffer buffer) { FindNextReadHandler().InvokeHandlerRead(buffer); } public virtual void FireRead(HeaderEnvelope header) { FindNextReadHandler().InvokeHandlerRead(header); } public virtual void FireRead(SaslEnvelope envelope) { FindNextReadHandler().InvokeHandlerRead(envelope); } public virtual void FireRead(IncomingAmqpEnvelope envelope) { FindNextReadHandler().InvokeHandlerRead(envelope); } public virtual void FireWrite(OutgoingAmqpEnvelope envelope) { FindNextWriteHandler().InvokeHandlerWrite(envelope); } public virtual void FireWrite(SaslEnvelope envelope) { FindNextWriteHandler().InvokeHandlerWrite(envelope); } public virtual void FireWrite(HeaderEnvelope envelope) { FindNextWriteHandler().InvokeHandlerWrite(envelope); } public virtual void FireWrite(IProtonBuffer buffer, Action ioComplete) { FindNextWriteHandler().InvokeHandlerWrite(buffer, ioComplete); } #region Internal invoke of Engine and Handler state methods internal void InvokeEngineStarting() { handler.EngineStarting(this); } internal void InvokeEngineStateChanged() { handler.HandleEngineStateChanged(this); } internal void InvokeEngineFailed(EngineFailedException failure) { handler.EngineFailed(this, failure); } #endregion #region Internal invoke of Read methods internal void InvokeHandlerRead(IncomingAmqpEnvelope envelope) { handler.HandleRead(this, envelope); } internal void InvokeHandlerRead(SaslEnvelope envelope) { handler.HandleRead(this, envelope); } internal void InvokeHandlerRead(HeaderEnvelope envelope) { handler.HandleRead(this, envelope); } internal void InvokeHandlerRead(IProtonBuffer buffer) { handler.HandleRead(this, buffer); } #endregion #region Internal invoke of Write methods internal void InvokeHandlerWrite(OutgoingAmqpEnvelope envelope) { handler.HandleWrite(this, envelope); } internal void InvokeHandlerWrite(SaslEnvelope envelope) { handler.HandleWrite(this, envelope); } internal void InvokeHandlerWrite(HeaderEnvelope envelope) { handler.HandleWrite(this, envelope); } internal void InvokeHandlerWrite(IProtonBuffer buffer, Action ioComplete) { next.Handler.HandleWrite(next, buffer, ioComplete); } #endregion private ProtonEngineHandlerContext FindNextReadHandler() { ProtonEngineHandlerContext ctx = this; do { ctx = ctx.previous; } while (SkipContext(ctx, HANDLER_READS)); return ctx; } private ProtonEngineHandlerContext FindNextWriteHandler() { ProtonEngineHandlerContext ctx = this; do { ctx = ctx.next; } while (SkipContext(ctx, HANDLER_WRITES)); return ctx; } private static bool SkipContext(ProtonEngineHandlerContext ctx, uint interestMask) { return (ctx.InterestMask & interestMask) == 0; } } }