Example #1
0
 private void RxReset()
 {
     _nodeIdWaitResponded = 0;
     _srcNodeId           = 0;
     _reassemblingData    = null;
     _rxTimerAction       = null;
 }
Example #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 > 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);
        }