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