internal void NotifySender(FragmentationMessageState finalState, Status finalStatus)
        {
            byte sduHandle;

            lock (_lock)
            {
                if (_currentState == FragmentationMessageState.Disposed)
                {
                    return;
                }

                if (_senderNotified)
                {
                    return;
                }

                _senderNotified = true;
                if (_dataConfirmHandler == null)
                {
                    return;
                }

                sduHandle = _sduHandle;
            }

            if (finalState == FragmentationMessageState.Final || finalState == FragmentationMessageState.SendingImpossible)
            {
                _dataConfirmHandler(this, sduHandle, finalStatus);
            }
            else
            {
                // unexpected state.
                _dataConfirmHandler(this, sduHandle, Status.Error);
            }
        }
 protected virtual void Dispose(bool disposing)
 {
     lock (_lock)
     {
         _currentState = FragmentationMessageState.Disposed;
         if ((_timer != null) && (_timerEnabled))
         {
             _timer.UnregisterItem(this);
         }
     }
 }
 internal FragmentationMessage(
     UInt16 source,
     UInt16 destination,
     byte messageSeqNumber,
     DataRequestHandler lowerLayerRequestHandler,
     int maxPduSize,
     int reservedHeaderSize,
     int reservedTailSize,
     FragmentationMessageTimer timer)
 {
     _timer = timer;
     _lowerLayerRequestHandler = lowerLayerRequestHandler;
     _currentState             = FragmentationMessageState.Initial;
     _source                        = source;
     _destination                   = destination;
     _messageSeqNumber              = messageSeqNumber;
     _lock                          = new object();
     _timeoutTicks                  = long.MaxValue;
     _maxPduSize                    = maxPduSize;
     _reservedHeaderSize            = reservedHeaderSize;
     _reservedTailSize              = reservedTailSize;
     _lastFragmentSeqNumberReceived = 0xFF;
     _lastFragmentSeqNumberSent     = 0xFF;
 }
        internal override void HandleReceivedFragment(FragmentHeader header, ref Frame payload)
        {
            if (header.FragmentSeqNumber == _lastFragmentSeqNumberReceived)
            {
#if DEBUG
                Trace.Print("Already received this fragment. Drop.");
#endif

                Frame.Release(ref payload);
                return;
            }

            _lastFragmentSeqNumberReceived = header.FragmentSeqNumber;

            if ((header.Type != FragmentType.DATA) || (payload.LengthDataUsed < 2) || (_messageSeqNumber != header.MessageSeqNumber))
            {
                Frame.Release(ref payload);
                return;
            }

            byte  nbFragments;
            byte  fragmentIndex;
            Frame data;
            try
            {
                Fragment.DecodeDataPayload(ref payload, out nbFragments, out fragmentIndex, out data);
            }
            catch (ArgumentException)
            {
                Frame.Release(ref payload);
                return;
            }

#if PRINTALL
            Trace.Print("Receiving part  " + fragmentIndex + "/" + nbFragments + " of packet " + _messageSeqNumber);
#endif

            FragmentationMessageTerminatedEventArgs messageTerminatedHandlerArgs = null;
            bool sendAck = false;
            lock (_lock)
            {
                if (_currentState == FragmentationMessageState.Disposed)
                {
                    Frame.Release(ref data);
                    return;
                }

                if (_timerEnabled)
                {
                    _timer.UnregisterItem(this);
                    _timerEnabled = false;
                }

                if ((_fragmentMissingTable != null) && (nbFragments != _fragmentMissingTable.Length))
                {
                    // mismatch between messages: no the same number of fragments
                    Frame.Release(ref data);
                    return;
                }

                FragmentationMessageState oldState = _currentState;
                if (_sduCompleted)
                {
                    Frame.Release(ref data);
                    if (header.IsAckRequired)
                    {
                        // resend acknowlegment
                        sendAck = true;
                    }
                    else
                    {
                        // leave the state unchanged
                        return;
                    }
                }
                else
                {
                    switch (_currentState)
                    {
                    case FragmentationMessageState.Initial:
                    case FragmentationMessageState.WaitingFragments:
                    case FragmentationMessageState.WaitingSentStatus:
                    case FragmentationMessageState.WaitingTimeoutBeforeResending:
                        if (_currentState == FragmentationMessageState.Initial)
                        {
                            // first fragment received.
                            _fragmentData         = new Frame[nbFragments];
                            _fragmentMissingTable = new BitArray(nbFragments, true);
                        }

                        _fragmentMissingTable.Set(fragmentIndex, false);
                        if (_fragmentData[fragmentIndex] == null)
                        {
                            _fragmentData[fragmentIndex] = data;
                        }
                        else
                        {
                            Frame.Release(ref data);
                        }

                        _sduCompleted = _fragmentMissingTable.CheckAllSet(false);
                        if (header.IsAckRequired)
                        {
                            sendAck = true;
                        }
                        else
                        {
                            _currentState = FragmentationMessageState.WaitingFragments;
                        }

                        if (_sduCompleted)
                        {
                            _currentState = FragmentationMessageState.Final;
                            messageTerminatedHandlerArgs = new FragmentationMessageTerminatedEventArgs(_currentState, Status.Success);
                        }
                        break;

                    case FragmentationMessageState.WaitingAck:
                        Frame.Release(ref data);
                        throw new System.InvalidOperationException("Bad state.");

                    case FragmentationMessageState.Disposed:
                    case FragmentationMessageState.Final:
                    case FragmentationMessageState.Unknown:
                    default:
                        Frame.Release(ref data);
                        break;
                    }
                }
            }

            if (sendAck)
            {
                SendAcknowledgement();
            }

            if (messageTerminatedHandlerArgs != null)
            {
                OnFragmentationMessageTerminated(messageTerminatedHandlerArgs);
            }
        }
 internal FragmentationMessageTerminatedEventArgs(FragmentationMessageState finalState, Status finalStatus)
 {
     _finalState  = finalState;
     _finalStatus = finalStatus;
 }
        internal void NotifySender(FragmentationMessageState finalState, Status finalStatus)
        {
            byte sduHandle;

            lock (_lock)
            {
                if (_currentState == FragmentationMessageState.Disposed)
                {
                    return;
                }

                if (_senderNotified)
                {
                    return;
                }

                _senderNotified = true;
                if (_dataConfirmHandler == null)
                {
                    return;
                }

                sduHandle = _sduHandle;
            }

            if (finalState == FragmentationMessageState.Final || finalState == FragmentationMessageState.SendingImpossible)
            {
                _dataConfirmHandler(this, sduHandle, finalStatus);
            }
            else
            {
                // unexpected state.
                _dataConfirmHandler(this, sduHandle, Status.Error);
            }
        }
 internal FragmentationMessageTerminatedEventArgs(FragmentationMessageState finalState, Status finalStatus)
 {
     _finalState = finalState;
     _finalStatus = finalStatus;
 }
        protected virtual void Dispose(bool disposing)
        {
            lock (_lock)
            {
                _currentState = FragmentationMessageState.Disposed;
                if ((_timer != null) && (_timerEnabled))
                {
                    _timer.UnregisterItem(this);

                }
            }
        }  
 internal FragmentationMessage(
     UInt16 source,
     UInt16 destination,
     byte messageSeqNumber,
     DataRequestHandler lowerLayerRequestHandler,
     int maxPduSize,
     int reservedHeaderSize,
     int reservedTailSize,
     FragmentationMessageTimer timer)
 {
     _timer = timer;
     _lowerLayerRequestHandler = lowerLayerRequestHandler;
     _currentState = FragmentationMessageState.Initial;
     _source = source;
     _destination = destination;
     _messageSeqNumber = messageSeqNumber;
     _lock = new object();
     _timeoutTicks = long.MaxValue;
     _maxPduSize = maxPduSize;
     _reservedHeaderSize = reservedHeaderSize;
     _reservedTailSize = reservedTailSize;
     _lastFragmentSeqNumberReceived = 0xFF;
     _lastFragmentSeqNumberSent = 0xFF;
 }