private bool closed = false; // True if the transaction has completed /// <summary> /// Constructs a <see cref="MsgRequestContext" /> for transactions that are not within a session. /// </summary> /// <param name="router">The <see cref="MsgRouter" />.</param> /// <param name="requestMsg">The request <see cref="Msg" />.</param> /// <exception cref="ArgumentException">Thrown if the message passed does not have all of the headers necessary to be a request.</exception> internal MsgRequestContext(MsgRouter router, Msg requestMsg) { if (router == null) { throw new ArgumentNullException("router"); } if (requestMsg._FromEP == null) { throw new ArgumentException("Message cannot be a request: Null [_FromEP] header.", "requestMsg"); } if (requestMsg._SessionID == Guid.Empty) { throw new ArgumentException("Message cannot be a request: Empty [_SessionID] header.", "requestMsg"); } this.router = router; this.session = null; this.FromEP = requestMsg._FromEP.Clone(); this.SessionID = requestMsg._SessionID; #if TRACE this.TraceName = requestMsg.GetType().Name; #else this.TraceName = "(trace disabled)"; #endif }
/// <summary> /// Constructs a <see cref="MsgRequestContext" /> for transactions that are within a session. /// </summary> /// <param name="session">The <see cref="DuplexSession" />.</param> /// <param name="query">The request <see cref="Msg" />.</param> /// <exception cref="ArgumentException">Thrown if the message passed does not have all of the headers necessary to be a request.</exception> internal MsgRequestContext(DuplexSession session, Msg query) { if (session == null) { throw new ArgumentNullException("session"); } if (query._FromEP == null) { throw new ArgumentException("Message cannot be a request: Null [_FromEP] header.", "requestMsg"); } if (query._SessionID == Guid.Empty) { throw new ArgumentException("Message cannot be a request: Empty [_SessionID] header.", "requestMsg"); } this.Header = query._ExtensionHeaders[MsgHeaderID.DuplexSession]; if (this.Header == null) { throw new ArgumentException("Message is not a DuplexSession query.", "requestMsg"); } this.router = session.Router; this.session = session; this.FromEP = query._FromEP.Clone(); this.SessionID = query._SessionID; #if TRACE this.TraceName = query.GetType().Name; #else this.TraceName = "(trace disabled)"; #endif }
/// <summary> /// Handles remote side closure of the underlying LillTek <see cref="DuplexSession" />. /// </summary> /// <param name="session">The <see cref="DuplexSession" />.</param> /// <param name="timeout"> /// <c>true</c> if the session closed due to a keep-alive timeout, /// <c>false</c> if the remote side explicitly closed its side /// of the session. /// </param> private void OnSessionClose(DuplexSession session, bool timeout) { using (TimedLock.Lock(this)) { // Terminate any pending Wait() operations with false. if (waitQueue != null) { while (waitQueue.Count > 0) { waitQueue.Dequeue().Notify(); } } // Terminate any pending Receive() operations with null. if (receiveQueue != null) { while (receiveQueue.Count > 0) { receiveQueue.Dequeue().Notify(); } } } }
//--------------------------------------------------------------------- // DuplexSession event handlers /// <summary> /// Handles messages received on the underlying LillTek <see cref="DuplexSession" /> session. /// </summary> /// <param name="session">The <see cref="DuplexSession" />.</param> /// <param name="msg">The received LillTek message.</param> private void OnSessionReceive(DuplexSession session, Msg msg) { WcfEnvelopeMsg envelopeMsg = msg as WcfEnvelopeMsg; if (envelopeMsg == null) { return; // Discard anything but WCF messages } Enqueue(listener.DecodeMessage(envelopeMsg)); }
private DuplexSession session; // Underlying LillTek Messaging session /// <summary> /// Constructor. /// </summary> /// <param name="channelManager">The responsible channel manager.</param> /// <param name="remoteAddress">The remote <see cref="EndpointAddress" />.</param> /// <param name="via">The first transport hop <see cref="Uri" />.</param> /// <param name="encoder">The <see cref="MessageEncoder" /> for serializing messages to the wire format.</param> public OutputSessionChannel(ChannelManagerBase channelManager, EndpointAddress remoteAddress, Uri via, MessageEncoder encoder) : base(channelManager) { ServiceModelHelper.ValidateEP(remoteAddress.Uri); ServiceModelHelper.ValidateEP(via); this.ep = ServiceModelHelper.ToMsgEP(remoteAddress.Uri); if (ep.Broadcast) { throw new ArgumentException("Sessionful channels cannot accept broadcast endpoints.", "remoteAddress"); } this.remoteAddress = remoteAddress; this.via = via; this.encoder = encoder; this.payloadEstimator = new PayloadSizeEstimator(ServiceModelHelper.PayloadEstimatorSampleCount); this.session = ChannelHost.Router.CreateDuplexSession(); }
private DuplexSession session; // The underlying LillTek session /// <summary> /// Constructor. /// </summary> /// <param name="channelManager">The responsible channel manager.</param> /// <param name="localAddress">The local <see cref="EndpointAddress" /> this channel will use to receive requests.</param> /// <param name="sessionID">The globally unique session ID for this channel.</param> /// <param name="session">The underlying LillTek <see cref="DuplexSession" />.</param> public InputSessionChannel(ChannelManagerBase channelManager, EndpointAddress localAddress, string sessionID, DuplexSession session) : base(channelManager, sessionID) { this.maxReceiveQueueSize = ServiceModelHelper.MaxAcceptedMessages; // $todo(jeff.lill): Hardcoding this this.bkTaskInterval = ServiceModelHelper.DefaultBkTaskInterval; // and this this.listener = (InputSessionChannelListener)channelManager; this.localAddress = localAddress; this.msgQueue = new LimitedQueue <Message>(maxReceiveQueueSize); this.waitQueue = new QueueArray <AsyncResult <bool, object> >(); this.receiveQueue = new QueueArray <AsyncResult <Message, object> >(); this.session = session; // Initialize the underlying LillTek session event handlers session.ReceiveEvent += new DuplexReceiveDelegate(OnSessionReceive); session.QueryEvent += new DuplexQueryDelegate(OnSessionQuery); session.CloseEvent += new DuplexCloseDelegate(OnSessionClose); }
/// <summary> /// Handles querues received on the underlying LillTek <see cref="DuplexSession" /> session. /// </summary> /// <param name="session">The <see cref="DuplexSession" />.</param> /// <param name="msg">The received LillTek query message.</param> /// <param name="isAsync">Returns as <c>true</c> if the query will be completed asynchronously.</param> private Msg OnSessionQuery(DuplexSession session, Msg msg, out bool isAsync) { // This channel type does not support queries. throw new NotImplementedException(string.Format("[{0}] does not support queries.", this.GetType().FullName)); }
/// <summary> /// Handles remote side closure of the underlying LillTek <see cref="DuplexSession" />. /// </summary> /// <param name="session">The <see cref="DuplexSession" />.</param> /// <param name="timeout"> /// <c>true</c> if the session closed due to a keep-alive timeout, /// <c>false</c> if the remote side explicitly closed its side /// of the session. /// </param> private void OnSessionClose(DuplexSession session, bool timeout) { // This is a NOP for this channel type. }
//--------------------------------------------------------------------- // DuplexSession event handlers /// <summary> /// Handles messages received on the underlying LillTek <see cref="DuplexSession" /> session. /// </summary> /// <param name="session">The <see cref="DuplexSession" />.</param> /// <param name="msg">The received LillTek message.</param> private void OnSessionReceive(DuplexSession session, Msg msg) { throw new InvalidOperationException(string.Format("[{0}] does not support message reception.", this.GetType().FullName)); }