The online racing simulator
C# Initial Packet Query
(9 posts, started )
C# Initial Packet Query
Hi all,

I am attempting to connect to the InSim on an LFS server using c#.

So far I have:


[SIZE=2][COLOR=#2b91af]TcpClient[/COLOR][/SIZE][SIZE=2] objTCPC = [/SIZE][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][SIZE=2][COLOR=#2b91af]TcpClient[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].strRemoteHost, [/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].intRemortPort);[/SIZE]
[SIZE=2][COLOR=#2b91af]NetworkStream[/COLOR][/SIZE][SIZE=2] objNS = objTCPC.GetStream();[/SIZE]
[SIZE=2][COLOR=#2b91af]Console[/COLOR][/SIZE][SIZE=2].WriteLine([/SIZE][SIZE=2][COLOR=#a31515]"TCP Connected {0}:{1}"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].strRemoteHost, [/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].intRemortPort);[/SIZE]
[SIZE=2][COLOR=#008000]//Send Connection Packet[/COLOR][/SIZE]
[SIZE=2][COLOR=#2b91af]IS_ISI[/COLOR][/SIZE][SIZE=2] connect = [/SIZE][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][SIZE=2][COLOR=#2b91af]IS_ISI[/COLOR][/SIZE][SIZE=2](0, [/SIZE][SIZE=2][COLOR=#a31515]"pass"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#a31515]"appname"[/COLOR][/SIZE][SIZE=2]);[/SIZE]

Basically the problem is I havn't used Structures before and in order to send the IS_ISI structure I created I need to convert it to a Byte array.

Can anyone help me out? The structure is defined as per the InSim specifications file;

[SIZE=2][SIZE=2][COLOR=#008000]//InSim Init - Packet to initialise the InSim System [/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]struct[/COLOR][/SIZE][SIZE=2][COLOR=#2b91af]IS_ISI[/COLOR][/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2] Size = 44;[/SIZE]
[SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2] Type = 1; [/SIZE][SIZE=2][COLOR=#008000]//ISP_ISI[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2] ReqI = 1; [/SIZE][SIZE=2][COLOR=#008000]//Requests IS_VER packet[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2][COLOR=#2b91af]UInt16[/COLOR][/SIZE][SIZE=2] UDPPort = 0; [/SIZE][SIZE=2][COLOR=#008000]//Port for UDP Replies 0 - 65535[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2][COLOR=#2b91af]UInt16[/COLOR][/SIZE][SIZE=2] Flags = 32; [/SIZE][SIZE=2][COLOR=#008000]//Bit flags for options[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2] Sp0 = 0;[/SIZE]
[SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2] Prefix = System.Text.[/SIZE][SIZE=2][COLOR=#2b91af]Encoding[/COLOR][/SIZE][SIZE=2].ASCII.GetBytes([/SIZE][SIZE=2][COLOR=#a31515]"$"[/COLOR][/SIZE][SIZE=2])[0];[/SIZE]
[SIZE=2][COLOR=#0000ff]public[/COLOR][/SIZE][SIZE=2][COLOR=#2b91af]UInt16[/COLOR][/SIZE][SIZE=2] Interval;[/SIZE]
[SIZE=2][COLOR=#0000ff]public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]char[/COLOR][/SIZE][SIZE=2][] Admin;[/SIZE]
[SIZE=2][COLOR=#0000ff]public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]char[/COLOR][/SIZE][SIZE=2][] IName;[/SIZE]
[SIZE=2][COLOR=#0000ff]public[/COLOR][/SIZE][SIZE=2] IS_ISI([/SIZE][SIZE=2][COLOR=#2b91af]UInt16[/COLOR][/SIZE][SIZE=2] Interval, [/SIZE][SIZE=2][COLOR=#0000ff]string[/COLOR][/SIZE][SIZE=2] Admin, [/SIZE][SIZE=2][COLOR=#0000ff]string[/COLOR][/SIZE][SIZE=2] IName)[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].Interval = Interval;[/SIZE]
[SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].Admin = Admin.ToCharArray();[/SIZE]
[SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].IName = IName.ToCharArray();[/SIZE]
[SIZE=2]}[/SIZE]

[SIZE=2]}[/SIZE]
[/SIZE]

using System.Runtime.InteropServices;

// Convert structure to byte array
public byte[] PacketToData(object SourceStruct)
{
int len = Marshal.SizeOf(SourceStruct); // Size of source structure
IntPtr Ptr = Marshal.AllocHGlobal(len); // Memory pointer to copy data to
byte[] data = new byte[len]; // Size of new aray
Marshal.StructureToPtr(SourceStruct, Ptr, false); // Copy struct to pointer
Marshal.Copy(Ptr, data, 0, len); // Copy pointer to byte array
Marshal.FreeHGlobal(Ptr); // Free pointer
return data; // Return byte array
}

// Convert byte array to a structure
public object DataToPacket(byte[] Data, object DestStruct)
{
int len = Marshal.SizeOf(DestStruct); // Size of destination structure
IntPtr Pointer = Marshal.AllocHGlobal(len); // Memory pointer to copy data to
Marshal.Copy(Data, 0, Pointer, Data.Length); // Copy array to pointer
DestStruct = Marshal.PtrToStructure(Pointer, DestStruct.GetType()); // Copy pointer to structure
Marshal.FreeHGlobal(Pointer); // Free pointer
return DestStruct; // Return object
}

Pass the new instance of the ISI struct in the PacketToData() method and it will return a byte array.

To reverse it:
Pass the byte array you received in the DataToPacket() method to return a struct, example:

IS_VER VER = new IS_VER();
VER = (IS_VER)DataToPacket(packet, VER);

This should work.

--- Btw, how do you color your code like that?
Cheers, i'll give that a try.

No idea, I just copied and pasted it from Visual C# 2008 and it coloured it automatically.
Ok, ive run it but I get a TypeMissMatch error at;

Marshal.StructureToPtr(SourceStruct, Ptr, false);
what parameter did you pass in PacketToData()? Can you show me the complete error message?
I hope this is what you mean;


[SIZE=2][COLOR=#2b91af]IS_ISI[/COLOR][/SIZE][SIZE=2] objConnect = [/SIZE][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][SIZE=2][COLOR=#2b91af]IS_ISI[/COLOR][/SIZE][SIZE=2](0, [/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].strLFSPass, [/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].strAppName);
[/SIZE][SIZE=2][COLOR=#2b91af]Byte[/COLOR][/SIZE][SIZE=2][] data = PacketToData( objConnect );[/SIZE]
[SIZE=2]

[/SIZE]

When the debug pauses and I inspect the objects the objConnect has the correct values (as in structure above), is it possible ive defined the structure wrong?
Ahh, I forgot to tell you something, I'm sorry. You have to change your struct layout to sequential. This is how I declaied my struct:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IS_ISI
{
public byte Size; // 44
public Enums.Packets Type; // ISP_ISI
public byte ReqI; // If non-zero LFS will send an IS_VER packet
public byte Zero; // 0

public ushort UDPPort; // Port for UDP replies from LFS (0 to 65535)
public ushort Flags; // Bit flags for options (see below)

public byte Sp0; // 0
public byte Prefix; // Special host message prefix character
public ushort Interval; // Time in ms between NLP or MCI (0 = none)

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Admin; // Admin password (if set in LFS)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string IName; // A short name for your program
}

The first line is crucial, and dont forget to make the strings a static length like I did in the struct above.
it appears to be working now, thank you so much for your help.
Great. No problem m8.

C# Initial Packet Query
(9 posts, started )
FGED GREDG RDFGDR GSFDG