/// <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);
}
}
}