Esempio n. 1
0
        protected override CustomDataFrame SubstituteIncomingInternal(CustomDataFrame packet, byte destNodeId, byte srcNodeId, byte[] cmdData, int lenIndex, out ActionBase additionalAction, out ActionBase completeAction)
        {
            CustomDataFrame ret = packet;

            additionalAction = null;
            completeAction   = null;
            if (IsActive)
            {
                if (cmdData.Length > 4 && cmdData[0] == COMMAND_CLASS_CRC_16_ENCAP.ID && cmdData[1] == COMMAND_CLASS_CRC_16_ENCAP.CRC_16_ENCAP.ID)
                {
                    COMMAND_CLASS_CRC_16_ENCAP.CRC_16_ENCAP cmd = cmdData;
                    if (Tools.CalculateCrc16Array(cmdData, 0, cmdData.Length - 2).SequenceEqual(cmd.checksum))
                    {
                        byte[] newFrameData = new byte[packet.Data.Length - 4];
                        Array.Copy(packet.Data, 0, newFrameData, 0, lenIndex);
                        newFrameData[lenIndex] = (byte)(cmdData.Length - 4);
                        Array.Copy(cmdData, 2, newFrameData, lenIndex + 1, cmdData.Length - 4);
                        Array.Copy(packet.Data, lenIndex + 1 + cmdData.Length, newFrameData, lenIndex + 1 + cmdData.Length - 4,
                                   packet.Data.Length - lenIndex - 1 - cmdData.Length);
                        ret = CreateNewFrame(packet, newFrameData);
                    }
                }
            }
            return(ret);
        }
Esempio n. 2
0
        protected override CustomDataFrame SubstituteIncomingInternal(CustomDataFrame packet, byte destNodeId, byte srcNodeId, byte[] cmdData, int lenIndex, out ActionBase additionalAction, out ActionBase completeAction)
        {
            CustomDataFrame ret = packet;

            additionalAction = null;
            completeAction   = null;
            if (IsActive)
            {
                if (cmdData.Length > 4 && cmdData[0] == COMMAND_CLASS_SUPERVISION.ID && cmdData[1] == COMMAND_CLASS_SUPERVISION.SUPERVISION_GET.ID)
                {
                    COMMAND_CLASS_SUPERVISION.SUPERVISION_GET cmd = cmdData;
                    if (cmd.encapsulatedCommand != null && cmd.encapsulatedCommand.Count > 0)
                    {
                        byte[] newFrameData = new byte[packet.Data.Length - 4];
                        Array.Copy(packet.Data, 0, newFrameData, 0, lenIndex);
                        newFrameData[lenIndex] = (byte)(cmdData.Length - 4);
                        Array.Copy(cmdData, 4, newFrameData, lenIndex + 1, cmdData.Length - 4);
                        Array.Copy(packet.Data, lenIndex + 1 + cmdData.Length, newFrameData, lenIndex + 1 + cmdData.Length - 4,
                                   packet.Data.Length - lenIndex - 1 - cmdData.Length);
                        ret = CreateNewFrame(packet, newFrameData);
                    }
                }
            }
            return(ret);
        }
Esempio n. 3
0
        private CustomDataFrame SubstituteIncoming(CustomDataFrame dataFrame, List <ActionHandlerResult> ahResults, Dictionary <SubstituteIncomingFlags, CustomDataFrame> substitutedDataFrames)
        {
            ActionBase additionalAction;
            ActionBase completeAction;

            lock (_actionStateLock)
            {
                foreach (var item in Enumerable.Reverse(_substituteManagers))
                {
                    substitutedDataFrames.Add(item.Id, dataFrame);
                    dataFrame = item.SubstituteIncoming(dataFrame, out additionalAction, out completeAction);
                    if (additionalAction != null)
                    {
                        var ahRes = new ActionHandlerResult(null);
                        ahRes.NextActions.Add(additionalAction);
                        ahResults.Add(ahRes);
                    }
                    if (completeAction != null)
                    {
                        ProcessCompleted(completeAction);
                    }
                }
                return(dataFrame);
            }
        }
Esempio n. 4
0
        protected CustomDataFrame CreateNewFrame(CustomDataFrame packet, byte[] newFrameData, int cmdLength)
        {
            var ret = new DataFrame(packet.SessionId, packet.DataFrameType, false, false, packet.SystemTimeStamp);

            byte[] buffer = DataFrame.CreateFrameBuffer(newFrameData);
            ret.SetBuffer(buffer, cmdLength);
            ret.SubstituteIncomingFlags = packet.SubstituteIncomingFlags | GetId();
            return(ret);
        }
Esempio n. 5
0
 private void ProcessSubstituteManagers(CustomDataFrame dataFrame, List <ActionHandlerResult> ahResults, Dictionary <SubstituteIncomingFlags, CustomDataFrame> substitutedDataFrames)
 {
     // 32 bits in int
     for (int i = 31; i >= 0; i--)
     {
         int mask = 1 << i;
         if ((dataFrame.SubstituteIncomingFlags & (SubstituteIncomingFlags)mask) > 0 && _substituteManagersDictionary.ContainsKey((SubstituteIncomingFlags)mask))
         {
             var smgr         = _substituteManagersDictionary[(SubstituteIncomingFlags)mask];
             var dataFrameOri = substitutedDataFrames[(SubstituteIncomingFlags)mask];
             smgr.OnIncomingSubstituted(dataFrameOri, dataFrame, ahResults);
         }
     }
 }
Esempio n. 6
0
        public CustomDataFrame SubstituteIncoming(CustomDataFrame packet, out ActionBase additionalAction, out ActionBase completeAction)
        {
            CustomDataFrame ret = packet;

            additionalAction = null;
            completeAction   = null;
            byte[] cmdData;
            byte   srcNodeId;
            byte   destNodeId;
            int    lenIndex;

            if (TryParseCommand(packet, out destNodeId, out srcNodeId, out lenIndex, out cmdData))
            {
                ret = SubstituteIncomingInternal(packet, destNodeId, srcNodeId, cmdData, lenIndex, out additionalAction, out completeAction);
            }
            return(ret);
        }
Esempio n. 7
0
 private void TryHandleDataFrame(CustomDataFrame actionCase, List <ActionHandlerResult> ahResults)
 {
     lock (_actionStateLock)
     {
         RunningActions.ForEach(x =>
         {
             if (!actionCase.IsHandled)
             {
                 var ahr = x.TryHandle(actionCase);
                 if (ahr != null)
                 {
                     ahResults.Add(ahr);
                 }
             }
             return(false);
         });
     }
 }
Esempio n. 8
0
        public override void OnIncomingSubstituted(CustomDataFrame dataFrameOri, CustomDataFrame dataFrameSub, List <ActionHandlerResult> ahResults)
        {
            if (IsActive)
            {
                bool hasSendData = ahResults.FirstOrDefault(
                    x => x.NextActions != null && x.NextActions.FirstOrDefault(
                        y => y is SendDataOperation || y is SendDataExOperation) != null) != null;
                if (!hasSendData)
                {
                    byte[] cmdData;
                    byte   srcNodeId;
                    byte   destNodeId;
                    int    lenIndex;
                    if (TryParseCommand(dataFrameOri, out destNodeId, out srcNodeId, out lenIndex, out cmdData))
                    {
                        if (cmdData[0] == COMMAND_CLASS_SUPERVISION.ID && cmdData[1] == COMMAND_CLASS_SUPERVISION.SUPERVISION_GET.ID)
                        {
                            COMMAND_CLASS_SUPERVISION.SUPERVISION_GET cmd = cmdData;
                            var data = new COMMAND_CLASS_SUPERVISION.SUPERVISION_REPORT()
                            {
                                duration    = 0,
                                properties1 = new COMMAND_CLASS_SUPERVISION.SUPERVISION_REPORT.Tproperties1()
                                {
                                    sessionId = cmd.properties1.sessionId
                                },
                                status = 0xFF
                            };

                            var tempAction = new SendDataOperation(srcNodeId, data, TxOptions);
                            if ((((SubstituteIncomingFlags)dataFrameOri.SubstituteIncomingFlags) & SubstituteIncomingFlags.Security) > 0)
                            {
                                tempAction.SubstituteSettings.SetFlag(SubstituteFlags.UseSecurity);
                            }
                            var ahRes = new ActionHandlerResult(null);
                            ahRes.NextActions.Add(tempAction);
                            ahResults.Add(ahRes);
                        }
                    }
                }
            }
        }
Esempio n. 9
0
        public override bool WaitingFor(IActionCase actionCase)
        {
            bool ret = false;

            if (actionCase is CustomDataFrame)
            {
                CustomDataFrame receivedValue = (CustomDataFrame)actionCase;
                if (Substituted == BoolFlag.NotSpecified ||
                    Substituted == BoolFlag.True && receivedValue.IsSubstituted ||
                    Substituted == BoolFlag.False && !receivedValue.IsSubstituted)
                {
                    byte[] payload = receivedValue.Data;
                    ret = IsExpectedData(payload);
                    if (ret)
                    {
                        DataFrame = receivedValue;
                    }
                }
            }
            //"{0}: {1} - {2}"._DLOG(ret, actionCase.ToString(), mMask.GetHex());
            return(ret);
        }
Esempio n. 10
0
        private CustomDataFrame CreateDataFrameOnReassemblingCompleted(CustomDataFrame incomePacket)
        {
            var dataHeader    = _reassemblingData.CompletedCmdHeader;
            var dataFooter    = _reassemblingData.CompletedCmdFooter;
            var reasembledCmd = _reassemblingData.SegmentsContainer.GetDatagram();
            var packetData    = new byte[_reassemblingData.CompletedCmdHeader.Length +
                                         _reassemblingData.CompletedCmdFooter.Length +
                                         reasembledCmd.Length + 1];
            int offset = 0;

            Array.Copy(dataHeader, packetData, dataHeader.Length);
            offset += dataHeader.Length;

            packetData[offset] = (byte)reasembledCmd.Length;
            offset++;

            Array.Copy(reasembledCmd, 0, packetData, offset, reasembledCmd.Length);
            offset += reasembledCmd.Length;
            Array.Copy(dataFooter, 0, packetData, offset, dataFooter.Length);

            return(CreateNewFrame(incomePacket, packetData, reasembledCmd.Length));
        }
Esempio n. 11
0
        public static bool TryParseCommand(CustomDataFrame packet, out byte destNodeId, out byte srcNodeId, out int lenIndex, out byte[] cmdData)
        {
            bool ret = false;

            cmdData    = null;
            srcNodeId  = 0;
            destNodeId = 0;
            lenIndex   = 0;
            if (packet != null && packet.Data != null && packet.Data.Length > 1 &&
                (packet.Data[1] == (byte)CommandTypes.CmdApplicationCommandHandler || packet.Data[1] == (byte)CommandTypes.CmdApplicationCommandHandler_Bridge))
            {
                int srcIndex = 3;
                lenIndex = 4;
                int    destIndex = -1;
                byte[] frameData = packet.Data;
                if (frameData[1] == (byte)CommandTypes.CmdApplicationCommandHandler_Bridge)
                {
                    destIndex = 3;
                    srcIndex  = 4;
                    lenIndex  = 5;
                }
                if (frameData.Length > lenIndex + 2)
                {
                    srcNodeId = frameData[srcIndex];
                    if (destIndex > 0)
                    {
                        destNodeId = frameData[destIndex];
                    }
                    cmdData = new byte[frameData[lenIndex]];
                    Array.Copy(frameData, lenIndex + 1, cmdData, 0, cmdData.Length);
                    if (cmdData.Length > 2)
                    {
                        ret = true;
                    }
                }
            }
            return(ret);
        }
Esempio n. 12
0
        public static DataFrame CreateDataFrame(CustomDataFrame packet, int lenIndex, byte[] cmd,
                                                byte lastUsedSecurityScheme,
                                                bool hasActiveKeyForNode,
                                                byte activeSecuritySchemeForNode)
        {
            byte[] frameData = packet.Data;
            byte   rssi      = 0;
            int    multiDestsOffsetNodeMaskLen = 0;

            byte[] multiDestsNodeMask = new byte[0];
            byte[] tail = new byte[2];

            if (frameData[1] == (byte)CommandTypes.CmdApplicationCommandHandler_Bridge)
            {
                int multiDestsOffsetNodeMaskLenIndex = lenIndex + 1 + frameData[lenIndex];
                if (frameData.Length > multiDestsOffsetNodeMaskLenIndex)
                {
                    multiDestsOffsetNodeMaskLen = frameData[multiDestsOffsetNodeMaskLenIndex];
                }
                if (multiDestsOffsetNodeMaskLen > 0 &&
                    frameData.Length > multiDestsOffsetNodeMaskLenIndex + 1 + multiDestsOffsetNodeMaskLen)
                {
                    multiDestsNodeMask = frameData.Skip(multiDestsOffsetNodeMaskLenIndex + 1).Take(multiDestsOffsetNodeMaskLen).ToArray();
                }
                if (frameData.Length > multiDestsOffsetNodeMaskLenIndex + 1 + multiDestsOffsetNodeMaskLen)
                {
                    rssi = frameData[multiDestsOffsetNodeMaskLenIndex + 1 + multiDestsOffsetNodeMaskLen];
                }
                if (multiDestsOffsetNodeMaskLen == 0)
                {
                    tail = new byte[3];
                }
                else
                {
                    tail = new byte[multiDestsOffsetNodeMaskLen + 1 + tail.Length];
                    Array.Copy(multiDestsNodeMask, 0, tail, 1, multiDestsOffsetNodeMaskLen);
                }
                tail[0] = (byte)multiDestsOffsetNodeMaskLen;
            }
            else
            {
                if (frameData.Length > lenIndex + 1 + frameData[lenIndex])
                {
                    rssi = frameData[lenIndex + 1 + frameData[lenIndex]];
                }
            }
            tail[tail.Length - 2] = rssi;
            tail[tail.Length - 1] = lastUsedSecurityScheme;

            "set scheme {0}"._DLOG(lastUsedSecurityScheme);

            byte[] payload = new byte[lenIndex + 1 + cmd.Length + tail.Length];
            for (int i = 0; i < lenIndex + 2; i++)
            {
                payload[i] = frameData[i];
            }
            payload[lenIndex] = (byte)cmd.Length;
            Array.Copy(cmd, 0, payload, lenIndex + 1, cmd.Length);
            Array.Copy(tail, 0, payload, lenIndex + 1 + cmd.Length, tail.Length);
            if (hasActiveKeyForNode)
            {
                payload[payload.Length - 1] = activeSecuritySchemeForNode;
            }
            DataFrame df = new DataFrame(packet.SessionId, packet.DataFrameType, packet.IsHandled, packet.IsOutcome,
                                         packet.SystemTimeStamp)
            {
                IsSubstituted = true
            };

            byte[] t = DataFrame.CreateFrameBuffer(payload);
            df.SetBuffer(t, 0, t.Length);
            var currentFlags = packet.SubstituteIncomingFlags;

            df.SubstituteIncomingFlags = (currentFlags | SubstituteIncomingFlags.Security);
            return(df);
        }
Esempio n. 13
0
        private void HandleActionCaseInner(IActionCase actionCase)
        {
            var customDataFrame = actionCase as CustomDataFrame;
            var timeInterval    = actionCase as TimeInterval;
            var action          = actionCase as ActionBase;

            if (customDataFrame != null)
            {
                CustomDataFrame dataFrameOri = customDataFrame;
                var             ahResults    = new List <ActionHandlerResult>();
                Dictionary <SubstituteIncomingFlags, CustomDataFrame> substitutedDataFrames = new Dictionary <SubstituteIncomingFlags, CustomDataFrame>();
                var dataFrame = SubstituteIncoming(dataFrameOri, ahResults, substitutedDataFrames);
                if (dataFrame != null)
                {
                    TryHandleDataFrame(dataFrame, ahResults);
                    if (dataFrame.Parent != null)
                    {
                        TryHandleDataFrame(dataFrame.Parent, ahResults);
                    }
                    ProcessSubstituteManagers(dataFrame, ahResults, substitutedDataFrames);
                    foreach (var ahResult in ahResults)
                    {
                        ProcessNext(ahResult);
                        if (ahResult.Parent != null)
                        {
                            ProcessCompleted(ahResult.Parent);
                        }
                    }
                }
            }
            else if (timeInterval != null)
            {
                if (timeInterval.ParentAction != null)
                {
                    ProcessNext(timeInterval.ParentAction.TryHandle(actionCase));
                    if (timeInterval.ParentAction != null)
                    {
                        ProcessCompleted(timeInterval.ParentAction);
                    }
                }
            }
            else if (action != null)
            {
                if (action.Token.IsStateFinished)
                {
                    ProcessCompleted(action);
                    if (action.IsExclusive)
                    {
                        _isExclusiveBusy = false;
                        var pendingAction = PendingExclusiveActions.Dequeue();
                        if (pendingAction != null)
                        {
                            _actionCaseConsumer.Add(pendingAction);
                        }
                    }
                    RunningActions.ForEach(x =>
                    {
                        if (x.ParentAction == action)
                        {
                            if (x.ParentAction.Token.State == ActionStates.Expired || x.ParentAction.Token.State == ActionStates.Cancelled)
                            {
                                x.Token.SetCancelling();
                                var ahResult = x.TryHandleStopped();
                                ProcessNext(ahResult);
                                x.Token.SetCancelled();
                                ProcessCompleted(x);
                            }
                            else
                            {
                                x.Token.SetCancelled();
                                ProcessCompleted(x);
                            }
                        }
                        return(false);
                    });
                    if (action.ParentAction != null && action.ParentAction.Token.IsStateActive)
                    {
                        var ahResult = action.ParentAction.TryHandle(action);
                        ProcessNext(ahResult);
                        action.ParentAction.FixStates();
                        ProcessCompleted(action.ParentAction);
                    }
                }
                else
                {
                    if (action.Token.State == ActionStates.None)
                    {
                        var actionStartSignal = action.Token.StartSignal;
                        action.SessionId = SessionId;
                        if (action.IsSequenceNumberRequired)
                        {
                            action.SequenceNumber = NextFuncId();
                        }
                        action = SubstituteAction(action);
                        if (action.IsExclusive)
                        {
                            if (!SuppressDebugOutput)
                            {
                                "{0:X2} (W){1}"._DLOG(SessionId, action.GetName() + action.AboutMeSafe());
                            }
                            if (_isExclusiveBusy)
                            {
                                PendingExclusiveActions.Enqueue(action);
                                return;
                            }
                            else
                            {
                                _isExclusiveBusy = true;
                            }
                            //CheckPoint.Pass(action);
                        }

                        var ahResult = action.Start();

                        if (_actionChangeCallback != null)
                        {
                            _actionChangeCallback(action.Token);
                        }

                        if (action.IsFirstPriority)
                        {
                            RunningActions.AddFirst(action);
                        }
                        else
                        {
                            RunningActions.AddLast(action);
                        }
                        if (!SuppressDebugOutput)
                        {
                            "{0:X2} {1}"._DLOG(SessionId, action.GetName() + action.AboutMeSafe());
                        }

                        ProcessNext(ahResult);
                        if (action.Token.TimeoutMs > 0)
                        {
                            TimeoutManager.AddTimer(action.Token);
                        }
                        if (actionStartSignal != null && !isDisposing)
                        {
                            actionStartSignal.Set();
                        }
                    }
                    else if (action.Token.Result.State == ActionStates.Cancelling)
                    {
                        var ahResult = action.TryHandleStopped();
                        ProcessNext(ahResult);
                    }
                    else if (action.Token.Result.State == ActionStates.Expiring)
                    {
                        var ahResult = action.TryHandleStopped();
                        ProcessNext(ahResult);
                    }
                    action.FixStates();
                    ProcessCompleted(action);
                }
            }
        }
Esempio n. 14
0
 protected virtual CustomDataFrame SubstituteIncomingInternal(CustomDataFrame packet, byte destNodeId, byte srcNodeId, byte[] cmdData, int lenIndex, out ActionBase additionalAction, out ActionBase completeAction)
 {
     additionalAction = null;
     completeAction   = null;
     return(null);
 }
Esempio n. 15
0
 public virtual void OnIncomingSubstituted(CustomDataFrame dataFrameOri, CustomDataFrame dataFrameSub, List <ActionHandlerResult> ahResults)
 {
 }
Esempio n. 16
0
        protected override CustomDataFrame SubstituteIncomingInternal(CustomDataFrame packet, byte destNodeId, byte srcNodeId, byte[] cmdData, int lenIndex, out ActionBase additionalAction, out ActionBase completeAction)
        {
            CustomDataFrame ret = packet;

            additionalAction = null;
            completeAction   = null;
            if (IsActive)
            {
                if (cmdData.Length > 1 && cmdData[0] == COMMAND_CLASS_TRANSPORT_SERVICE_V2.ID && ValidateCRC16Checksum(cmdData))
                {
                    byte id = (byte)(cmdData[1] & COMMAND_CLASS_TRANSPORT_SERVICE_V2.COMMAND_FIRST_SEGMENT.ID_MASK);

                    if (id == (COMMAND_CLASS_TRANSPORT_SERVICE_V2.COMMAND_FIRST_SEGMENT.ID) &&
                        TransportServiceManagerInfo.TestNeedToIgnoreFirstSegment.CanBeUsed &&
                        TransportServiceManagerInfo.TestNeedToIgnoreFirstSegment.PullValue().Value
                        )
                    {
                        return(ret);
                    }

                    if (id == (COMMAND_CLASS_TRANSPORT_SERVICE_V2.COMMAND_SUBSEQUENT_SEGMENT.ID) &&
                        TransportServiceManagerInfo.TestNeedToIgnoreSubsequentSegment.CanBeUsed &&
                        TransportServiceManagerInfo.TestOffset.CanBeUsed
                        )
                    {
                        var datagramOffset = SegmentsContainer.GetSegmentOffset(cmdData);
                        var payloadLength  = SegmentsContainer.GetSegmentPayloadLength(cmdData);
                        if (TransportServiceManagerInfo.TestOffset.PullValue(
                                val =>
                        {
                            return(val >= datagramOffset && val <= (datagramOffset + payloadLength));
                        }) != null &&
                            TransportServiceManagerInfo.TestNeedToIgnoreSubsequentSegment.PullValue().Value
                            )
                        {
                            return(ret);
                        }
                    }

                    lock (_lockObject)
                    {
                        if (_reassemblingData == null || _reassemblingData.SegmentsContainer.IsCompleted)
                        {
                            if (id == (COMMAND_CLASS_TRANSPORT_SERVICE_V2.COMMAND_FIRST_SEGMENT.ID))
                            {
                                RxReset();
                                _srcNodeId = srcNodeId;

                                var cmdHeader = new byte[lenIndex];
                                Array.Copy(packet.Data, 0, cmdHeader, 0, cmdHeader.Length);

                                var cmdFooter = new byte[packet.Data.Length - cmdHeader.Length - cmdData.Length - 1];
                                Array.Copy(packet.Data, lenIndex + packet.Data[lenIndex] + 1, cmdFooter, 0, cmdFooter.Length);

                                _reassemblingData = new ReassemblingData
                                {
                                    SegmentsContainer  = new SegmentsContainer(cmdData),
                                    CompletedCmdHeader = cmdHeader,
                                    CompletedCmdFooter = cmdFooter
                                };

                                if (_reassemblingData.SegmentsContainer.IsCompleted)
                                {
                                    additionalAction = new SendDataOperation(srcNodeId, CreateSegmentCompletedCmd(), TransportServiceManagerInfo.TxOptions)
                                    {
                                        SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0)
                                    };
                                    ret = CreateDataFrameOnReassemblingCompleted(packet);
                                }
                                else
                                {
                                    // Start fragment rx timer.
                                    _rxTimerAction   = CreateRxTimerAction();
                                    additionalAction = _rxTimerAction;
                                }
                            }
                            else if (id == (COMMAND_CLASS_TRANSPORT_SERVICE_V2.COMMAND_SUBSEQUENT_SEGMENT.ID))
                            {
                                if (_reassemblingData != null && _reassemblingData.SegmentsContainer.CheckForLastSegment(cmdData))
                                {
                                    additionalAction = new SendDataOperation(srcNodeId, CreateSegmentCompletedCmd(), TransportServiceManagerInfo.TxOptions)
                                    {
                                        SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0)
                                    };
                                }
                                else if (srcNodeId != _nodeIdWaitResponded)
                                {
                                    _nodeIdWaitResponded = srcNodeId;
                                    additionalAction     = new SendDataOperation(srcNodeId, CreateSegmentWaitCmd(1), TransportServiceManagerInfo.TxOptions)
                                    {
                                        SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0)
                                    };
                                }
                            }
                        }
                        else if (_srcNodeId == srcNodeId && id == (COMMAND_CLASS_TRANSPORT_SERVICE_V2.COMMAND_SUBSEQUENT_SEGMENT.ID))
                        {
                            if (_rxTimerAction != null)
                            {
                                _rxTimerAction.Actions[0].Token.Reset(FRAGMENT_RX_TIMEOUT); // Reset fragment rx timer.
                            }
                            else
                            {
                                _rxTimerAction   = CreateRxTimerAction();
                                additionalAction = _rxTimerAction;
                            }

                            _reassemblingData.SegmentsContainer.AddSegment(cmdData);
                            if (_reassemblingData.SegmentsContainer.IsLastSegmentReceived)
                            {
                                if (_reassemblingData.SegmentsContainer.IsCompleted)
                                {
                                    _rxTimerAction.Token.SetCompleted(); // Complete fragment rx timer.
                                    completeAction = _rxTimerAction;
                                    _rxTimerAction = null;

                                    additionalAction = new SendDataOperation(srcNodeId, CreateSegmentCompletedCmd(), TransportServiceManagerInfo.TxOptions)
                                    {
                                        SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0)
                                    };
                                    ret = CreateDataFrameOnReassemblingCompleted(packet);
                                }
                                else
                                {
                                    ushort missingOffset = _reassemblingData.SegmentsContainer.GetFirstMissingFragmentOffset();
                                    additionalAction = new SendDataOperation(srcNodeId,
                                                                             CreateSegmentRequestCmd(missingOffset),
                                                                             TransportServiceManagerInfo.TxOptions)
                                    {
                                        SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0)
                                    };
                                }
                            }
                        }
                        else
                        {
                            if (srcNodeId != _nodeIdWaitResponded)
                            {
                                _nodeIdWaitResponded = srcNodeId;
                                additionalAction     = new SendDataOperation(srcNodeId,
                                                                             CreateSegmentWaitCmd(_reassemblingData.SegmentsContainer.PendingSegmentsCount),
                                                                             TransportServiceManagerInfo.TxOptions)
                                {
                                    SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0)
                                };
                            }
                        }
                    }
                }
            }
            return(ret);
        }