Example #1
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 #2
0
        private void HandleFlowFrame(Flow flow)
        {
            if (State != LinkStateEnum.ATTACHED && State != LinkStateEnum.DETACH_SENT && State != LinkStateEnum.DESTROYED)
                throw new AmqpException(ErrorCode.IllegalState, $"Received Flow frame but link state is {State.ToString()}.");
            if (State == LinkStateEnum.DESTROYED)
                throw new AmqpException(ErrorCode.ErrantLink, $"Received Flow frame but link state is {State.ToString()}."); // TODO end session
            if (State == LinkStateEnum.DETACH_SENT)
                return; // ignore

            if (IsReceiverLink)
            {
                // flow control from sender
                if (flow.DeliveryCount.HasValue)
                    DeliveryCount = flow.DeliveryCount.Value;
                // TODO: ignoring Available field for now
                //if (flow.Available.HasValue)
                //    available = flow.Available.Value;
                // TODO: respond to new flow control
            }

            if (IsSenderLink)
            {
                // flow control from receiver
                if (flow.LinkCredit.HasValue)
                    LinkCredit = flow.LinkCredit.Value;
                drainFlag = flow.Drain ?? false;
                // TODO respond to new flow control
                var receivedFlowCallback = this.ReceivedFlow;
                if (receivedFlowCallback != null)
                    receivedFlowCallback(this, EventArgs.Empty);
            }

            if (flow.Echo)
            {
                SendFlow(drain: false, echo: false);
            }
        }
Example #3
0
        public void SendFlow(Flow flow)
        {
            incomingWindow = DefaultWindowSize; // reset window

            flow.NextIncomingId = nextIncomingId;
            flow.NextOutgoingId = nextOutgoingId;
            flow.IncomingWindow = incomingWindow;
            flow.OutgoingWindow = outgoingWindow;
            SendFrame(flow);
        }