Example #1
0
        public int CompareTo(RFCSeqNum value)
        {
            int delta = this.sequenceNumber - value.sequenceNumber;

            if (delta == int.MinValue)
            {
                // Behavior of comparing 0u-2147483648u, 1u-2147483649u, ...
                // is undefined, so we do not allow it.
                throw new AmqpException(ErrorCode.NotAllowed
                                        , $"Comparison of {this.sequenceNumber.ToString()} and {value.sequenceNumber.ToString()} is invalid because the result is undefined.");
            }

            return(delta);
        }
Example #2
0
        private void InterceptFlowFrame(Flow flow)
        {
            if (!State.CanReceiveFrames())
            {
                throw new AmqpException(ErrorCode.IllegalState, $"Received Flow frame but session state is {State.ToString()}.");
            }
            if (State == SessionStateEnum.DISCARDING)
            {
                return;
            }

            nextIncomingId       = flow.NextOutgoingId; // their next id
            remoteOutgoingWindow = flow.OutgoingWindow; // their advertised outgoing window

            // recalculate the remote session's advertised incoming-window based on the difference
            // between the advertized next-incoming-id and our actual next-outgoing-id
            // our outgoing-window is synchronized with the remote-incoming-window
            if (flow.NextIncomingId.HasValue)
            {
                outgoingWindow = remoteIncomingWindow = flow.IncomingWindow + flow.NextIncomingId.Value - (uint)nextOutgoingId;
            }
            else
            {
                outgoingWindow = remoteIncomingWindow = flow.IncomingWindow + InitialOutgoingId - (uint)nextOutgoingId;
            }

            if (outgoingWindow > 0)
            {
                // TODO: flush queued outgoing transfers
            }

            if (flow.Handle != null)
            {
                var link = GetRemoteLink(flow.Handle.Value);
                if (link.State == LinkStateEnum.DESTROYED)
                {
                    throw new AmqpException(ErrorCode.ErrantLink, "If any input (other than a detach) related to the endpoint either via the input handle or delivery-ids be received, the session MUST be terminated with an errant-link session-error.");
                }
                link.HandleLinkFrame(flow);
            }
            else if (flow.Echo)
            {
                SendFlow(new Flow()
                {
                    Echo = false,
                });
            }
        }
Example #3
0
        private void HandleBeginFrame(Begin begin)
        {
            if (State != SessionStateEnum.UNMAPPED && State != SessionStateEnum.BEGIN_SENT)
            {
                throw new AmqpException(ErrorCode.IllegalState, $"Received Begin frame but session state is {State.ToString()}.");
            }

            nextOutgoingId = InitialOutgoingId;                                 // our next id
            incomingWindow = DefaultWindowSize;                                 // our incoming window

            nextIncomingId       = begin.NextOutgoingId;                        // their next id
            outgoingWindow       = remoteIncomingWindow = begin.IncomingWindow; // their incoming window (and now our outgoing window)
            remoteOutgoingWindow = begin.OutgoingWindow;                        // their advertized outgoing window

            sessionMaxHandle = Math.Min(DefaultMaxHandle, begin.HandleMax ?? DefaultMaxHandle);

            if (State == SessionStateEnum.BEGIN_SENT)
            {
                if (begin.RemoteChannel == null)
                {
                    throw new AmqpException(ErrorCode.InvalidField, "Expecting to receive RemoteChannel");
                }
                RemoteChannelNumber = begin.RemoteChannel.Value;
                State = SessionStateEnum.MAPPED;
                return;
            }
            else
            {
                State = SessionStateEnum.BEGIN_RCVD;

                // reset values and send back the frame
                begin.RemoteChannel  = RemoteChannelNumber;
                begin.NextOutgoingId = nextOutgoingId;
                begin.IncomingWindow = incomingWindow;
                begin.OutgoingWindow = outgoingWindow;
                begin.HandleMax      = sessionMaxHandle;
                Connection.SendFrame(begin, ChannelNumber);

                State = SessionStateEnum.MAPPED;
                return;
            }
        }
Example #4
0
        private void InterceptTransferFrame(Transfer transfer, ByteBuffer buffer)
        {
            if (!State.CanReceiveFrames())
            {
                throw new AmqpException(ErrorCode.IllegalState, $"Received Transfer frame but session state is {State.ToString()}.");
            }
            if (State == SessionStateEnum.DISCARDING)
            {
                return;
            }

            if (incomingWindow == 0)
            {
                // received a transfer frame when our incoming window is at zero
                throw new AmqpException(ErrorCode.WindowViolation, "incoming-window is 0");
            }

            nextIncomingId++;
            if (transfer.DeliveryId.HasValue)
            {
                nextIncomingId = transfer.DeliveryId.Value + 1;
            }

            remoteOutgoingWindow--;
            incomingWindow--; // TODO: do we want to handle flow control?
            if (incomingWindow == 0)
            {
                // TODO: ... do we just reset the window like AMQPlite?
            }

            var link = GetRemoteLink(transfer.Handle);

            if (link.State == LinkStateEnum.DESTROYED)
            {
                throw new AmqpException(ErrorCode.ErrantLink, "If any input (other than a detach) related to the endpoint either via the input handle or delivery-ids be received, the session MUST be terminated with an errant-link session-error.");
            }
            link.HandleLinkFrame(transfer, buffer);
        }
Example #5
0
        public AmqpSession(AmqpConnection connection, ushort channelNumber, ushort remoteChannelNumber)
        {
            this.Connection = connection;
            this.ChannelNumber = channelNumber;
            this.RemoteChannelNumber = remoteChannelNumber;
            State = SessionStateEnum.UNMAPPED;

            nextOutgoingId = InitialOutgoingId;
        }
Example #6
0
        private void InterceptTransferFrame(Transfer transfer, ByteBuffer buffer)
        {
            if (!State.CanReceiveFrames())
                throw new AmqpException(ErrorCode.IllegalState, $"Received Transfer frame but session state is {State.ToString()}.");
            if (State == SessionStateEnum.DISCARDING)
                return;

            if (incomingWindow == 0)
            {
                // received a transfer frame when our incoming window is at zero
                throw new AmqpException(ErrorCode.WindowViolation, "incoming-window is 0");
            }

            nextIncomingId++;
            if (transfer.DeliveryId.HasValue)
            {
                nextIncomingId = transfer.DeliveryId.Value + 1;
            }

            remoteOutgoingWindow--;
            incomingWindow--; // TODO: do we want to handle flow control?
            if (incomingWindow == 0)
            {
                // TODO: ... do we just reset the window like AMQPlite?
            }

            var link = GetRemoteLink(transfer.Handle);
            if (link.State == LinkStateEnum.DESTROYED)
                throw new AmqpException(ErrorCode.ErrantLink, "If any input (other than a detach) related to the endpoint either via the input handle or delivery-ids be received, the session MUST be terminated with an errant-link session-error.");
            link.HandleLinkFrame(transfer, buffer);
        }
Example #7
0
        private void InterceptFlowFrame(Flow flow)
        {
            if (!State.CanReceiveFrames())
                throw new AmqpException(ErrorCode.IllegalState, $"Received Flow frame but session state is {State.ToString()}.");
            if (State == SessionStateEnum.DISCARDING)
                return;

            nextIncomingId = flow.NextOutgoingId; // their next id
            remoteOutgoingWindow = flow.OutgoingWindow; // their advertised outgoing window

            // recalculate the remote session's advertised incoming-window based on the difference
            // between the advertized next-incoming-id and our actual next-outgoing-id
            // our outgoing-window is synchronized with the remote-incoming-window
            if (flow.NextIncomingId.HasValue)
                outgoingWindow = remoteIncomingWindow = flow.IncomingWindow + flow.NextIncomingId.Value - (uint)nextOutgoingId;
            else
                outgoingWindow = remoteIncomingWindow = flow.IncomingWindow + InitialOutgoingId - (uint)nextOutgoingId;

            if (outgoingWindow > 0)
            {
                // TODO: flush queued outgoing transfers
            }

            if (flow.Handle != null)
            {
                var link = GetRemoteLink(flow.Handle.Value);
                if (link.State == LinkStateEnum.DESTROYED)
                    throw new AmqpException(ErrorCode.ErrantLink, "If any input (other than a detach) related to the endpoint either via the input handle or delivery-ids be received, the session MUST be terminated with an errant-link session-error.");
                link.HandleLinkFrame(flow);
            }
            else if (flow.Echo)
            {
                SendFlow(new Flow()
                {
                    Echo = false,
                });
            }
        }
Example #8
0
        private void HandleBeginFrame(Begin begin)
        {
            if (State != SessionStateEnum.UNMAPPED && State != SessionStateEnum.BEGIN_SENT)
                throw new AmqpException(ErrorCode.IllegalState, $"Received Begin frame but session state is {State.ToString()}.");

            nextOutgoingId = InitialOutgoingId; // our next id
            incomingWindow = DefaultWindowSize; // our incoming window

            nextIncomingId = begin.NextOutgoingId; // their next id
            outgoingWindow = remoteIncomingWindow = begin.IncomingWindow; // their incoming window (and now our outgoing window)
            remoteOutgoingWindow = begin.OutgoingWindow; // their advertized outgoing window

            sessionMaxHandle = Math.Min(DefaultMaxHandle, begin.HandleMax ?? DefaultMaxHandle);

            if (State == SessionStateEnum.BEGIN_SENT)
            {
                if (begin.RemoteChannel == null)
                {
                    throw new AmqpException(ErrorCode.InvalidField, "Expecting to receive RemoteChannel");
                }
                RemoteChannelNumber = begin.RemoteChannel.Value;
                State = SessionStateEnum.MAPPED;
                return;
            }
            else
            {
                State = SessionStateEnum.BEGIN_RCVD;

                // reset values and send back the frame
                begin.RemoteChannel = RemoteChannelNumber;
                begin.NextOutgoingId = nextOutgoingId;
                begin.IncomingWindow = incomingWindow;
                begin.OutgoingWindow = outgoingWindow;
                begin.HandleMax = sessionMaxHandle;
                Connection.SendFrame(begin, ChannelNumber);

                State = SessionStateEnum.MAPPED;
                return;
            }
        }