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); }
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, }); } }
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; } }
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); }
public AmqpSession(AmqpConnection connection, ushort channelNumber, ushort remoteChannelNumber) { this.Connection = connection; this.ChannelNumber = channelNumber; this.RemoteChannelNumber = remoteChannelNumber; State = SessionStateEnum.UNMAPPED; nextOutgoingId = InitialOutgoingId; }
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); }
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, }); } }
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; } }