Exemplo n.º 1
0
        private void HandleFragmentationMessageTerminated(object sender, FragmentationMessageTerminatedEventArgs args)
        {
            if (sender is InboundFragmentationMessage)
            {
                if ((args.FinalState != FragmentationMessageState.Final) || (args.FinalStatus != Status.Success))
                {
                    // do nothing.
                    return;
                }

                InboundFragmentationMessage inMsg = sender as InboundFragmentationMessage;

                Frame receivedMessage = inMsg.RetrieveData();

                if (receivedMessage != null)
                {
                    DataIndicationHandler handler = _dataIndicationHandler;
                    if (handler != null)
                    {
                        handler.Invoke(this, inMsg.Source, inMsg.Destination, receivedMessage);
                    }
                    else
                    {
                        Frame.Release(ref receivedMessage);
                    }
                }
            }
            else if (sender is OutboundFragmentationMessage)
            {
                OutboundFragmentationMessage outMsg, newOutMsg;
                lock (_lock)
                {
                    outMsg = sender as OutboundFragmentationMessage;
                    ushort previousDestination = outMsg.Destination;
                    _transmissionCharacteristicStorage.UpdateTransmissionCharacteristic(outMsg.Destination, outMsg.TimeoutForResending,
                                                                                        outMsg.MaxFragmentsBeforeAck);
                    // remove active message from repository
                    _outboundAssociations.RemoveFragmentationMessage(outMsg);
                    // try to start new message (if possible)
                    DataRequestItem newItem;
                    newOutMsg = null;
                    if (_dataRequestQueueSet.Dequeue(previousDestination, out newItem))
                    {
                        newOutMsg = CreateNewOutboundMessage(newItem);
                    }
                }

                // after releasing the lock, call method in FragmentationMessage class.
                outMsg.NotifySender(args.FinalState, args.FinalStatus);
                outMsg.Dispose();

                if (newOutMsg != null)
                {
                    newOutMsg.SendNextDataFragment(true);
                }
            }
        }
Exemplo n.º 2
0
        public void HandleLowerLayerDataIndication(object sender, ushort originatorShortAddr, ushort targetShortAddr, Frame sdu)
        {
            FragmentationMessage fragMsg = null;
            FragmentHeader header;

            lock (_lock)
            {
                if ((!_started) || (sdu.LengthDataUsed < 2))
                {
                    Frame.Release(ref sdu);
                    return;
                }

                // extract fragment header.
                header = FragmentHeader.Decode(sdu.ReadUInt16(0));
                sdu.DeleteFromFront(2);
                FragmentationMessageAssociationSet associations;
                switch (header.Type)
                {
                    case FragmentType.DATA:
                        associations = _inboundAssociations;
                        if (associations == null)
                        {
                            Frame.Release(ref sdu);
                            return;
                        }

                        fragMsg = (InboundFragmentationMessage)associations.GetFragmentationMessage(originatorShortAddr, targetShortAddr);
                        if (fragMsg != null)
                        {
                            // there is already one message with this peer. Check freshness.
                            if (fragMsg.MessageNumber != header.MessageSeqNumber)
                            {
                                int sqnOld = (int)fragMsg.MessageNumber;
                                int sqnNew = (int)header.MessageSeqNumber;
                                int diff = (sqnNew > sqnOld) ? sqnNew - sqnOld : sqnNew - sqnOld + 256;
                                if ((header.MessageSeqNumber == 0) || (diff < 128))
                                {
                                    // data received is most recent.
                                    fragMsg.Dispose();
                                    fragMsg = null;
                                }
                                else
                                {
                                    // data received is old stuff.
                                    Frame.Release(ref sdu);
                                    return;
                                }
                            }
                        }

                        if (fragMsg == null)
                        {
                            // new message must be started
                            fragMsg = new InboundFragmentationMessage(originatorShortAddr, targetShortAddr,
                                header.MessageSeqNumber, _lowerLayerDataRequest, _lowerMtu, _lowerHead, _lowerTail, _timer);
                            fragMsg.FragmentationMessageTerminated += this.HandleFragmentationMessageTerminated;
                            associations.SetFragmentationMessage(originatorShortAddr, targetShortAddr, fragMsg);
                        }
                        break;
                    case FragmentType.ACK:
                        associations = _outboundAssociations;
                        if (associations == null)
                        {
                            Frame.Release(ref sdu);
                            return;
                        }

                        fragMsg = (OutboundFragmentationMessage)associations.GetFragmentationMessage(targetShortAddr, originatorShortAddr);
                        if ((fragMsg == null) || (fragMsg.MessageNumber != header.MessageSeqNumber))
                        {
                            //no one waiting for this segment. Discard.
#if DEBUG
                            Trace.Print("No one waiting for this segment. Discard.");
#endif

                            Frame.Release(ref sdu);
                            return;
                        }
                        break;
                    default:
                        break;
                }
            }

            // release the lock before calling method in FragmentMessage class
            if (fragMsg != null)
            {
                fragMsg.HandleReceivedFragment(header, ref sdu);

            }
        }
Exemplo n.º 3
0
        public void HandleLowerLayerDataIndication(object sender, ushort originatorShortAddr, ushort targetShortAddr, Frame sdu)
        {
            FragmentationMessage fragMsg = null;
            FragmentHeader       header;

            lock (_lock)
            {
                if ((!_started) || (sdu.LengthDataUsed < 2))
                {
                    Frame.Release(ref sdu);
                    return;
                }

                // extract fragment header.
                header = FragmentHeader.Decode(sdu.ReadUInt16(0));
                sdu.DeleteFromFront(2);
                FragmentationMessageAssociationSet associations;
                switch (header.Type)
                {
                case FragmentType.DATA:
                    associations = _inboundAssociations;
                    if (associations == null)
                    {
                        Frame.Release(ref sdu);
                        return;
                    }

                    fragMsg = (InboundFragmentationMessage)associations.GetFragmentationMessage(originatorShortAddr, targetShortAddr);
                    if (fragMsg != null)
                    {
                        // there is already one message with this peer. Check freshness.
                        if (fragMsg.MessageNumber != header.MessageSeqNumber)
                        {
                            int sqnOld = (int)fragMsg.MessageNumber;
                            int sqnNew = (int)header.MessageSeqNumber;
                            int diff   = (sqnNew > sqnOld) ? sqnNew - sqnOld : sqnNew - sqnOld + 256;
                            if ((header.MessageSeqNumber == 0) || (diff < 128))
                            {
                                // data received is most recent.
                                fragMsg.Dispose();
                                fragMsg = null;
                            }
                            else
                            {
                                // data received is old stuff.
                                Frame.Release(ref sdu);
                                return;
                            }
                        }
                    }

                    if (fragMsg == null)
                    {
                        // new message must be started
                        fragMsg = new InboundFragmentationMessage(originatorShortAddr, targetShortAddr,
                                                                  header.MessageSeqNumber, _lowerLayerDataRequest, _lowerMtu, _lowerHead, _lowerTail, _timer);
                        fragMsg.FragmentationMessageTerminated += this.HandleFragmentationMessageTerminated;
                        associations.SetFragmentationMessage(originatorShortAddr, targetShortAddr, fragMsg);
                    }
                    break;

                case FragmentType.ACK:
                    associations = _outboundAssociations;
                    if (associations == null)
                    {
                        Frame.Release(ref sdu);
                        return;
                    }

                    fragMsg = (OutboundFragmentationMessage)associations.GetFragmentationMessage(targetShortAddr, originatorShortAddr);
                    if ((fragMsg == null) || (fragMsg.MessageNumber != header.MessageSeqNumber))
                    {
                        //no one waiting for this segment. Discard.
#if DEBUG
                        Trace.Print("No one waiting for this segment. Discard.");
#endif

                        Frame.Release(ref sdu);
                        return;
                    }
                    break;

                default:
                    break;
                }
            }

            // release the lock before calling method in FragmentMessage class
            if (fragMsg != null)
            {
                fragMsg.HandleReceivedFragment(header, ref sdu);
            }
        }