Пример #1
0
        /// <summary>
        /// Called by the derived class when it has created a new channel to
        /// accept a message received by the base class and passed to the
        /// derived class via <see cref="OnMessageReceived" />.
        /// </summary>
        /// <param name="channel">The accepted channel.</param>
        protected void OnChannelCreated(TInternal channel)
        {
            bool abortChannel = false;

            using (TimedLock.Lock(this))
            {
                // The derived class has accepted a new channel.  If we have a
                // an AcceptChannel() or WaitFoprChannel() operation pending, complete
                // them in that order.

                if (acceptQueue.Count > 0)
                {
                    AsyncResult <TInternal, object> arAccept = acceptQueue.Dequeue();

                    arAccept.Result = channel;
                    arAccept.Notify();
                    return;
                }

                // Queue the accepted channel

                channelQueue.Enqueue(channel);

                // Complete the first queued wait operation, if there is one.

                if (waitQueue.Count > 0)
                {
                    AsyncResult <bool, object> arWait;

                    arWait        = waitQueue.Dequeue();
                    arWait.Result = true;
                    arWait.Notify();
                }
            }

            if (abortChannel)
            {
                channel.Abort();    // Do this outside of the lock to be safe
            }
        }
Пример #2
0
        /// <summary>
        /// Adds a message to the channel's receive queue, completing a
        /// pending receive related operation.
        /// </summary>
        /// <param name="message">The received message.</param>
        internal void Enqueue(Message message)
        {
            using (TimedLock.Lock(this))
            {
                if (!base.CanAcceptMessages)
                {
                    return;
                }

                // If there's a pending receive operation then have it
                // complete with the message.

                QueueArray <AsyncResult <Message, InputChannel> > receiveQueue = listener.ReceiveQueue;

                if (receiveQueue != null && receiveQueue.Count > 0)
                {
                    AsyncResult <Message, InputChannel> arReceive;

                    arReceive        = receiveQueue.Dequeue();
                    arReceive.Result = message;

                    arReceive.Notify();
                    return;
                }

                // There were no pending receive operations so queue the message.

                msgQueue.Enqueue(message);

                // Complete the first pending WaitForMessage() request,
                // if there is one queued.

                QueueArray <AsyncResult <bool, InputChannel> > waitQueue;

                waitQueue = listener.WaitForMessageQueue;
                if (waitQueue != null && waitQueue.Count > 0)
                {
                    AsyncResult <bool, InputChannel> arWait;

                    arWait        = waitQueue.Dequeue();
                    arWait.Result = true;
                    arWait.Notify();
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Called when the base class receives a LillTek envelope message with an
        /// encapsulated WCF message from the router.  Non-session oriented derived
        /// classes must implement this to accept a new channel or route the message
        /// to an existing channel.
        /// </summary>
        /// <param name="message">The decoded WCF <see cref="Message" />.</param>
        /// <param name="msg">The received LillTek <see cref="Msg" />.</param>
        /// <remarks>
        /// <para>
        /// This method takes different actions depending on whether there are
        /// any pending channel <b>WaitForMessage()</b> or <b>Receive()</b> requests.
        /// </para>
        /// <para>
        /// If there are pending message receive operations, then these will be completed
        /// and the message queued to the associated channel as is appropriate.
        /// </para>
        /// <para>
        /// Finally, if no pending message receive requests and the base class has a
        /// pending <b>WaitForChannel()</b> or <b>AcceptChannel()</b>, then the base class
        /// <see cref="LillTekChannelListener{IInputSessionChannel,InputSessionChannel}.OnChannelCreated" />
        /// method will be called so that a new channel will be accepted.
        /// </para>
        /// <para>
        /// Finally, if there are no pending message receive requests or base channel
        /// channel accept related requests, the message will be queued internally.
        /// </para>
        /// </remarks>
        protected override void OnMessageReceived(Message message, WcfEnvelopeMsg msg)
        {
            InputChannel newChannel = null;

            if (base.State != CommunicationState.Opened)
            {
                return;
            }

            if (msg._SessionID != Guid.Empty)
            {
                return;     // Reject messages that are part of a session
            }
            using (TimedLock.Lock(this))
            {
                // Handle any pending channel Receive() operations first.

                if (receiveQueue.Count > 0)
                {
                    AsyncResult <Message, InputChannel> arReceive;

                    arReceive        = receiveQueue.Dequeue();
                    arReceive.Result = message;
                    arReceive.Notify();
                    return;
                }

                // Next, handle any pending channel WaitForMessage() operations.

                if (waitQueue.Count > 0)
                {
                    AsyncResult <bool, InputChannel> arWait;

                    // Queue the message to the input channel so it will assured
                    // to be available when the WaitForMessage() completes and
                    // the application calls Receive().

                    arWait        = waitQueue.Dequeue();
                    arWait.Result = true;
                    arWait.InternalState.Enqueue(message);
                    arWait.Notify();
                    return;
                }

                // Queue the message.

                msgQueue.Enqueue(message);

                // Create new channel if there are pending channel accept
                // or wait operations.

                if (base.HasPendingChannelOperation)
                {
                    newChannel = new InputChannel(this, new EndpointAddress(this.Uri));
                    AddChannel(newChannel);
                }
            }

            // Do this outside of the lock just to be safe

            if (newChannel != null)
            {
                base.OnChannelCreated(newChannel);
            }
        }
Пример #4
0
        /// <summary>
        /// Called when the base class receives a LillTek envelope message with an
        /// encapsulated WCF message from the router.  Non-session oriented derived
        /// classes must implement this to accept a new channel or route the message
        /// to an existing channel.
        /// </summary>
        /// <param name="message">The decoded WCF <see cref="Message" />.</param>
        /// <param name="msg">The received LillTek <see cref="Msg" />.</param>
        /// <remarks>
        /// <para>
        /// This method takes different actions depending on whether there are
        /// any pending channel <b>WaitForRequest()</b> or <b>ReceiveRequest()</b> requests.
        /// </para>
        /// <para>
        /// If there are pending request receive operations, then these will be completed
        /// and the rfequest information will be queued to the associated channel as is appropriate.
        /// </para>
        /// <para>
        /// Finally, if no pending request receive requests and the base class has a
        /// pending <b>WaitForChannel()</b> or <b>AcceptChannel()</b>, then the base class
        /// <see cref="LillTekChannelListener{IInputSessionChannel,InputSessionChannel}.OnChannelCreated" />
        /// method will be called so that a new channel will be accepted.
        /// </para>
        /// <para>
        /// Finally, if there are no pending request receive requests or base channel
        /// channel accept related requests, the message will be queued internally.
        /// </para>
        /// </remarks>
        protected override void OnMessageReceived(Message message, WcfEnvelopeMsg msg)
        {
            RequestInfo  requestInfo = new RequestInfo(message, msg.CreateRequestContext(), SysTime.Now + maxRequestQueueTime);
            ReplyChannel newChannel  = null;

            if (base.State != CommunicationState.Opened)
            {
                return;
            }

            using (TimedLock.Lock(this))
            {
                // Handle any pending channel ReceiveRequest() operations first.

                if (receiveQueue.Count > 0)
                {
                    AsyncResult <RequestInfo, ReplyChannel> arReceive;

                    arReceive        = receiveQueue.Dequeue();
                    arReceive.Result = requestInfo;
                    arReceive.Notify();
                    return;
                }

                // Next, handle any pending channel WaitForRequest() operations.

                if (waitQueue.Count > 0)
                {
                    AsyncResult <bool, ReplyChannel> arWait;

                    // Queue the request information to the input channel so it will assured
                    // to be available when the WaitForRequest() completes and
                    // the application calls ReceiveRequest().

                    arWait        = waitQueue.Dequeue();
                    arWait.Result = true;
                    arWait.InternalState.Enqueue(requestInfo);
                    arWait.Notify();
                    return;
                }

                // Queue the request.

                requestQueue.Enqueue(requestInfo);

                // Create new channel if there are pending channel accept
                // or wait operations.

                if (base.HasPendingChannelOperation)
                {
                    newChannel = new ReplyChannel(this, new EndpointAddress(this.Uri), base.MessageEncoder);
                    AddChannel(newChannel);
                }
            }

            // Do this outside of the lock just to be safe

            if (newChannel != null)
            {
                base.OnChannelCreated(newChannel);
            }
        }