/// <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) { _buffers.Add(segment); if (!message.MoreFollows) { try { // TODO: Is this the best place to do this? Decoding // large requests could potentially be more time than // we want to spent in the transaction's lock using (var stream = new MultiBufferStream(_buffers)) { var tagReader = new TagReader(stream); var tagReaderStream = new TagReaderStream(tagReader, Value <TAck> .Schema); var ack = Value <TAck> .Load(tagReaderStream); _source.SetResult(ack); } } catch (Exception e) { _source.SetException(new RejectException(RejectReason.InvalidTag)); } } }
/// <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); } } }