Example #1
0
 private void SendMessage(CommandEtherNetIPHeader header, CIPSerializer msg)
 {
     byte[] headerBytes = header.Serialize();
     byte[] msgBytes    = msg?.Serialize() ?? new byte[0];
     byte[] allBytes    = new byte[headerBytes.Length + msgBytes.Length];
     Array.Copy(headerBytes, allBytes, headerBytes.Length);
     Array.Copy(msgBytes, 0, allBytes, headerBytes.Length, msgBytes.Length);
     Trace(EventType.Full, string.Format("{0} - Msg. '{1}' queued to be send", LOG_TAG, header.Command));
     m_SocketClient.SendData(allBytes);
 }
Example #2
0
        public void ReceiveBytes(byte[] data)
        {
            m_ActivityTimeRef = DateTime.Now;
            Trace(EventType.Full, string.Format("{0} - {1} bytes received!", LOG_TAG, data.Length));
            m_ReceiveBuffer.Position = m_ReceiveBuffer.Length;
            m_ReceiveBuffer.Write(data, 0, data.Length);
            long pointer = 0;

            while (pointer < m_ReceiveBuffer.Length)
            {
                long msgHeaderSize = Marshal.SizeOf(typeof(CommandEtherNetIPHeader));
                if (m_ReceiveBuffer.Length - pointer >= msgHeaderSize)
                {
                    byte[] bytes = new byte[msgHeaderSize];
                    m_ReceiveBuffer.Position = pointer;
                    m_ReceiveBuffer.Read(bytes, 0, bytes.Length);
                    CommandEtherNetIPHeader headerStructObj = CommandEtherNetIPHeader.Deserialize(bytes);
                    long msgSize = msgHeaderSize + headerStructObj.Length;
                    if (m_ReceiveBuffer.Length - pointer >= msgSize)
                    {
                        byte[] bodyBytes = new byte[headerStructObj.Length];
                        m_ReceiveBuffer.Position = pointer + msgHeaderSize;
                        m_ReceiveBuffer.Read(bodyBytes, 0, bodyBytes.Length);
                        MessageFactory(headerStructObj, bodyBytes);
                        m_WaitingRemainingBytes = DateTime.MinValue;
                        pointer += msgSize;
                    }
                    else
                    {
                        Trace(EventType.Warning, string.Format("{0} - Waiting for the rest of msg. body", LOG_TAG));
                        m_WaitingRemainingBytes = DateTime.Now;
                        break;
                    }
                }
                else
                {
                    Trace(EventType.Warning, string.Format("{0} - Waiting for the rest of msg. header", LOG_TAG));
                    m_WaitingRemainingBytes = DateTime.Now;
                    break;
                }
            }
            if (pointer >= m_ReceiveBuffer.Length)
            {
                m_ReceiveBuffer.SetLength(0);
                m_ReceiveBuffer.Capacity = 0;
                m_ReceiveBuffer.Position = 0;
                Trace(EventType.Full, string.Format("{0} - Receive buffer clear!", LOG_TAG));
            }
        }
Example #3
0
        private void ThreadTask()
        {
            try
            {
                while (!m_Terminate)
                {
                    if (m_WaitingRemainingBytes != DateTime.MinValue)
                    {
                        if (DateTime.Now.Subtract(m_WaitingRemainingBytes).TotalSeconds > 2)
                        {
                            Trace(EventType.Error, string.Format("{0} - So long time waiting the rest of message bytes. The connection will be closed. {1}", LOG_TAG, m_ScktConn.RemoteEndPoint));
                            Close();
                        }
                    }

                    lock (m_SendMsgList)
                        if (m_SendMsgList.Count > 0)
                        {
                            byte[] msgBytes = m_SendMsgList[0];
                            m_ScktConn.SendData(msgBytes);
                            Trace(EventType.Full, string.Format("{0} - {1} bytes sent !!!", LOG_TAG, msgBytes.Length));
                            m_SendMsgList.RemoveAt(0);
                        }

                    if (!m_Terminate)
                    {
                        if (!m_ThreadResetEvent.WaitOne(2000) && m_SendMsgList.Count == 0)
                        {
                            CommandEtherNetIPHeader msgListServices = new CommandEtherNetIPHeader {
                                Command = EncapsulationCommands.NOP
                            };
                            SendMessage(msgListServices, null);
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                Trace(exc);
            }
        }
Example #4
0
        private void MessageFactory(CommandEtherNetIPHeader header, byte[] bodyBytes)
        {
            int pointer = 0;

            Trace(EventType.Full, string.Format("{0} - Receive msg. '{1}' with status {2}", LOG_TAG, header.Command, header.Status));
            long headerSize = Marshal.SizeOf(typeof(CommandEtherNetIPHeader));

            switch (header.Command)
            {
            case EncapsulationCommands.ListServices:
            {
                if (bodyBytes.Length > 0)
                {
                    MsgListServiceReply msgReply = (MsgListServiceReply)MsgListServiceReply.Deserialize(typeof(MsgListServiceReply), bodyBytes, ref pointer);
                    if ((msgReply.CommandSpecificDataListServices.Items[0].CapabilityFlags & 0x20) == 0)
                    {
                        throw new Exception("The order side doesn't support TCP messages");
                    }
                    m_ClientConnStates = ClientConnStates.SendRegisterSession;
                }
                break;
            }

            case EncapsulationCommands.RegisterSession:
            {
                if (header.Status == 0 && header.SessionHandle != 0)
                {
                    MsgRegisterSessionReply msgReply = (MsgRegisterSessionReply)MsgRegisterSessionReply.Deserialize(typeof(MsgRegisterSessionReply), bodyBytes, ref pointer);
                    Trace(EventType.Info, string.Format("{0} - Registration session number: {1}", LOG_TAG, header.SessionHandle));
                    m_SessionHandle    = header.SessionHandle;
                    m_ClientConnStates = ClientConnStates.SendReceive;
                    OnRegistrationSession?.Invoke(m_SessionHandle);
                }
                else
                {
                    throw new Exception(string.Format("Error on registration session. Error: {0}", header.Status));
                }
                break;
            }

            case EncapsulationCommands.SendRRData:
            {
                MsgUnconnectedSendReply msgReply = (MsgUnconnectedSendReply)MsgUnconnectedSendReply.Deserialize(typeof(MsgUnconnectedSendReply), bodyBytes, ref pointer);
                long sendContext = BitConverter.ToInt64(header.SenderContext, 0);
                if (sendContext != 0 && sendContext == m_SenderContext)
                {
                    m_SendStatusResult = msgReply.CommonIndustrialProtocolReply.GeneralStatus;
                    m_SendResetEvent.Set();
                }
                break;
            }

            case EncapsulationCommands.UnRegisterSession:
            {
                break;
            }

            default:
            {
                throw new Exception(string.Format("Command {0} not implemented", header.Command));
            }
            }
        }
Example #5
0
        private void ThreadTask()
        {
            try
            {
                while (!m_Terminate)
                {
                    switch (m_ClientConnStates)
                    {
                    case ClientConnStates.Disconnected:
                    {
                        break;
                    }

                    case ClientConnStates.SendListServices:
                    {
                        CommandEtherNetIPHeader msgListServices = new CommandEtherNetIPHeader {
                            Command = EncapsulationCommands.ListServices
                        };
                        SendMessage(msgListServices, null);
                        m_ClientConnStates = ClientConnStates.WaitListServicesReply;
                        break;
                    }

                    case ClientConnStates.SendRegisterSession:
                    {
                        MsgRegisterSessionRequest msg    = new MsgRegisterSessionRequest();
                        CommandEtherNetIPHeader   header = new CommandEtherNetIPHeader {
                            Command = EncapsulationCommands.RegisterSession
                        };
                        msg.CommandSpecificDataRegisterSession = new CommandSpecificDataRegisterSession {
                            ProtocolVersion = 1
                        };
                        header.Length = msg.CommandSpecificDataRegisterSession.SizeOf();
                        SendMessage(header, msg);
                        m_ClientConnStates = ClientConnStates.WaitRegisterSessionReply;
                        break;
                    }

                    case ClientConnStates.SendReceive:
                    {
                        if (m_DataToSend != null)
                        {
                            CommandEtherNetIPHeader header = new CommandEtherNetIPHeader {
                                Command       = EncapsulationCommands.SendRRData,
                                SessionHandle = m_SessionHandle,
                                SenderContext = BitConverter.GetBytes(m_SenderContext)
                            };
                            MsgUnconnectedSendRequest msg = new MsgUnconnectedSendRequest {
                                CommandSpecificDataSendRRData = new CommandSpecificDataSendRRData {
                                    InterfaceHandle = 0,
                                    Timeout         = 0,
                                    ItemCount       = 2,
                                    List            = new CommandSpecificDataSendRRDataItem[] {
                                        new CommandSpecificDataSendRRDataItem {
                                            TypeID = 0,
                                            Length = 0
                                        },
                                        new CommandSpecificDataSendRRDataItem {
                                            TypeID = CommonPacketItemID.UnconnectedMessage,
                                            Length = 0
                                        }
                                    }
                                },
                                CommonIndustrialProtocolRequest = new CommonIndustrialProtocolRequest {
                                    Service         = 0x52, // Unconnected Send Service ID
                                    RequestPathSize = 2,
                                    PathSegmentList = new List <PathSegment> {
                                        new LogicalPathSegment8bits {
                                            PathSegmentType = 0x20,
                                            LogicalValue    = 0x06  // Connection Manager Class ID
                                        },
                                        new LogicalPathSegment8bits {
                                            PathSegmentType = 0x24,
                                            LogicalValue    = 0x01  // Connection Manager Instance ID
                                        }
                                    }
                                },
                                CIPConnectionManagerUnconnSnd = new CIPConnectionManagerUnconnSnd {
                                    PriorityAndPickTime             = 0x07,
                                    TimeOutTicks                    = 233,
                                    MessageRequestSize              = 0,
                                    CommonIndustrialProtocolRequest = new CommonIndustrialProtocolRequest {
                                        Service         = 0x4d, // CIP Write Data Service
                                        RequestPathSize = 0,
                                    },
                                    CIPClassGeneric = new CIPClassGeneric {
                                        DataType         = m_DataTypeToSend,
                                        SpecificDataSize = (ushort)(m_DataToSend.Length / CIPClassGeneric.GetDataTypeSize(m_DataTypeToSend)),
                                        CIPClassGenericCmdSpecificData = m_DataToSend,
                                    },
                                    Pad           = null,
                                    RoutePathSize = 0,
                                    Reserved      = 0,
                                    RoutePath     = new List <PathSegment> {
                                        new PortPathSegment {
                                            PathSegmentType                = 0x01,
                                            OptionalLinkAddressSize        = null,
                                            OptionalExtendedPortIdentifier = null,
                                            LinkAddress = new byte[] { m_LinkAddress },
                                            Pad         = null
                                        }
                                    }
                                }
                            };

                            msg.CIPConnectionManagerUnconnSnd.CommonIndustrialProtocolRequest.PathSegmentList = new List <PathSegment>();
                            string[] segs = m_Symbol.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                            foreach (string seg in segs)
                            {
                                msg.CIPConnectionManagerUnconnSnd.CommonIndustrialProtocolRequest.PathSegmentList.Add(
                                    new DataPathSegmentANSISymb {
                                        PathSegmentType = 0x91,
                                        DataSize        = (byte)seg.Length,
                                        ANSISymbol      = Encoding.ASCII.GetBytes(seg.Length % 2 == 0 ? seg : seg + "\0")
                                    });
                            }

                            msg.CIPConnectionManagerUnconnSnd.Pad           = (msg.CIPConnectionManagerUnconnSnd.SizeOf() % 2) == 0 ? null : (byte?)0;
                            msg.CIPConnectionManagerUnconnSnd.RoutePathSize = (byte)(msg.CIPConnectionManagerUnconnSnd.RoutePath.Sum(a => a.SizeOf()) / 2);
                            msg.CIPConnectionManagerUnconnSnd.CommonIndustrialProtocolRequest.RequestPathSize = (byte)(msg.CIPConnectionManagerUnconnSnd.CommonIndustrialProtocolRequest.PathSegmentList.Sum(a => a.SizeOf()) / 2);
                            msg.CIPConnectionManagerUnconnSnd.MessageRequestSize = (ushort)(msg.CIPConnectionManagerUnconnSnd.CommonIndustrialProtocolRequest.SizeOf() + msg.CIPConnectionManagerUnconnSnd.CIPClassGeneric.SizeOf());
                            msg.CommandSpecificDataSendRRData.List[1].Length     = (ushort)(msg.CommonIndustrialProtocolRequest.SizeOf() + msg.CIPConnectionManagerUnconnSnd.SizeOf());
                            header.Length = msg.SizeOf();
                            SendMessage(header, msg);
                        }
                        else
                        {
                            CommandEtherNetIPHeader msgListServices = new CommandEtherNetIPHeader {
                                Command = EncapsulationCommands.NOP
                            };
                            SendMessage(msgListServices, null);
                        }
                        break;
                    }
                    }
                    if (!m_Terminate)
                    {
                        m_ThreadResetEvent.WaitOne(2000);
                    }
                }
            }
            catch (Exception exc)
            {
                Trace(EventType.Error, string.Format("{0} - Thread exception: {1}", LOG_TAG, exc.Message));
                Trace(exc);
            }
        }
Example #6
0
        private void MessageFactory(CommandEtherNetIPHeader header, byte[] bodyBytes)
        {
            try
            {
                Trace(EventType.Full, string.Format("{0} - Receive msg. '{1}'", LOG_TAG, header.Command));
                long headerSize = Marshal.SizeOf(typeof(CommandEtherNetIPHeader));
                switch (header.Command)
                {
                case EncapsulationCommands.ListServices:
                {
                    if (bodyBytes.Length == 0)
                    {
                        MsgListServiceReply msg = new MsgListServiceReply();
                        msg.CommandSpecificDataListServices           = new CommandSpecificDataListServices();
                        msg.CommandSpecificDataListServices.ItemCount = 1;
                        msg.CommandSpecificDataListServices.Items     = new CommandSpecificDataListServicesItem[1];
                        msg.CommandSpecificDataListServices.Items[0]  = new CommandSpecificDataListServicesItem
                        {
                            TypeCode        = CommonPacketItemID.ListServicesResponse,
                            Version         = 1,
                            CapabilityFlags = Convert.ToUInt16("100100000", 2),
                            ServiceName     = Encoding.ASCII.GetBytes("Communications\0\0")
                        };
                        header.Length = msg.SizeOf();
                        msg.CommandSpecificDataListServices.Items[0].Length =
                            (ushort)(msg.CommandSpecificDataListServices.Items[0].SizeOf() - 2 - 2);
                        SendMessage(header, msg);
                    }
                    break;
                }

                case EncapsulationCommands.RegisterSession:
                {
                    int pointer = 0;
                    CommandSpecificDataRegisterSession cmdSpecData =
                        (CommandSpecificDataRegisterSession)CommandSpecificDataRegisterSession.Deserialize(
                            typeof(CommandSpecificDataRegisterSession), bodyBytes, ref pointer);
                    MsgRegisterSessionReply msg = new MsgRegisterSessionReply();
                    // TODO: check the protocol version to accept the registration
                    msg.CommandSpecificDataRegisterSession = cmdSpecData;
                    m_SessionHandle      = (uint)((DateTime.Now.Ticks / 10) & 0xFFFFFFFF);
                    header.SessionHandle = m_SessionHandle;
                    header.Length        = msg.SizeOf();
                    SendMessage(header, msg);
                    Trace(EventType.Info, string.Format("{0} - Registration session number: {1}", LOG_TAG, header.SessionHandle));
                    break;
                }

                case EncapsulationCommands.SendRRData:
                {
                    if (header.SessionHandle != m_SessionHandle)
                    {
                        throw new Exception(string.Format("Received invalid session handle (unregistred) in SendRRData message: ", header.SessionHandle));
                    }
                    int pointer = 0;
                    MsgUnconnectedSendRequest unconnSndReq = (MsgUnconnectedSendRequest)MsgUnconnectedSendRequest.Deserialize(
                        typeof(MsgUnconnectedSendRequest), bodyBytes, ref pointer);
                    string             symbol   = Encoding.ASCII.GetString(((DataPathSegmentANSISymb)unconnSndReq.CIPConnectionManagerUnconnSnd.CommonIndustrialProtocolRequest.PathSegmentList[0]).ANSISymbol);
                    ElementaryDataType dataType = unconnSndReq.CIPConnectionManagerUnconnSnd.CIPClassGeneric.DataType;
                    OnReceiveData?.Invoke(m_ScktConn.RemoteEndPoint, symbol.Replace("\0", ""), dataType, unconnSndReq.CIPConnectionManagerUnconnSnd.CIPClassGeneric.CIPClassGenericCmdSpecificData);
                    MsgUnconnectedSendReply msg = new MsgUnconnectedSendReply();
                    msg.CommandSpecificDataSendRRData = unconnSndReq.CommandSpecificDataSendRRData;
                    CommandSpecificDataSendRRDataItem item = msg.CommandSpecificDataSendRRData.List.First(
                        a => a.TypeID == CommonPacketItemID.UnconnectedMessage);
                    msg.CommonIndustrialProtocolReply = new CommonIndustrialProtocolReply {
                        Service              = 0xcd,
                        Reserved             = 0x0,
                        GeneralStatus        = 0x0, // <- success
                        AdditionalStatusSize = 0x0,
                        AdditionalStatus     = new ushort[0]
                    };
                    item.Length   = msg.CommonIndustrialProtocolReply.SizeOf();
                    header.Length = msg.SizeOf();
                    SendMessage(header, msg);
                    break;
                }

                case EncapsulationCommands.UnRegisterSession:
                {
                    break;
                }

                default:
                {
                    Trace(EventType.Error, string.Format("{0} - Command {1} not implemented", LOG_TAG, header.Command));
                    break;
                }
                }
            }
            catch (Exception e)
            {
                Trace(e);
            }
        }