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