/// <summary> /// Processes a received complex ack /// </summary> /// <param name="source">The address of the device that sent the ack</param> /// <param name="message">The complex ack header</param> /// <param name="segment">The buffer segment containing the ack content</param> public void ProcessComplexAck(Address source, ComplexAckMessage message, BufferSegment segment) { ClientTransaction tx = null; lock (_lock) { tx = _getClientTransaction(source, message.InvokeId); } if(tx != null) tx.OnComplexAck(message, segment); }
/// <summary> /// Notifies the handle that a new response segment /// is available /// </summary> /// <param name="message">The complex ack message</param> /// <param name="segment">The response segment</param> public abstract void FeedComplexAck(ComplexAckMessage message, BufferSegment segment);
/// <summary> /// Notifies the handle that a new response segment /// is available /// </summary> /// <param name="message">The complex ack message</param> /// <param name="segment">The response segment</param> public override void FeedComplexAck(ComplexAckMessage message, BufferSegment segment) { _source.SetException(new AbortException(AbortReason.InvalidApduInThisState)); }
/// <summary> /// Called whenever a complex ack is received /// for this transaction /// </summary> /// <param name="message">The received message</param> /// <param name="segment">The segment</param> public void OnComplexAck(ComplexAckMessage message, BufferSegment segment) { lock(_lock) { bool dispose = false; if (_state == ClientState.AwaitConfirmation) { if(!message.Segmented) { _handle.FeedComplexAck(message, segment); dispose = true; } else if(message.SequenceNumber == 0) { _sequenceNumber = 1; _windowSize = message.ProposedWindowSize; _sendSegmentAck(); _handle.FeedComplexAck(message, segment); _transitionTo(ClientState.SegmentedConfirmation); } else { _sendAbort(AbortReason.InvalidApduInThisState); _handle.FeedAbort(AbortReason.InvalidApduInThisState); dispose = true; } } else if(_state == ClientState.SegmentedConfirmation) { int sequenceNumber; if ((sequenceNumber = _inWindow(message.SequenceNumber)) != -1 && sequenceNumber == _sequenceNumber) { _handle.FeedComplexAck(message, segment); _windowSize = message.ProposedWindowSize; _sequenceNumber++; dispose = !message.MoreFollows; if (dispose || _sequenceNumber == _windowStart + _windowSize) _sendSegmentAck(); else if (!dispose) _transitionTo(ClientState.SegmentedConfirmation); } else { _sendSegmentAck(nack:true); _transitionTo(ClientState.SegmentedConfirmation); } } if(dispose) _transitionTo(ClientState.Disposed); } }