Casting a struct for sending to socket [Archive] - C Board

PDA

View Full Version : Casting a struct for sending to socket


chrisjmoss
04-08-2008, 07:17 AM
Hi Guys

I am trying to send a struct to a UDP socket, but I'm not entirely sure how to cast the structure.


struct CONNECT_REQUEST {
char headersize ;// = 0x06; //static EIB header size
char protocolversion;// = 0x10; //protocol version (1.0)
char servicetype[1];// = 0x0205; //service type in this case a connect_request
char totallength[1];// = 0x0018; //total length (24 byte)
char controllength;// = 0x08; //HPAI header for control endpoint
char protocoltype;// = 0x01; //0x01 UDP, 0x02 TCP
char IPcontrol[3];//; //four chars for conrtol endpoint IP
char portcontrol[1];// //two chars for control endpoint port must be gleaned during discovery
char datalength ;// = 0x08; //HPAI header length for data endpoint
char IPdata[3]; // //fours chars for data endpoint IP use same IP as control endpoint
char portdata[1];// = 0x0e57; //set data port to 3671 default for EIB
char connectheader;// = 0x02; //connection type structue length
char connecttype;// = 0x04; //connection type in this case tunnelling may need 2 extra bytes.
};

struct CONNECT_REQUEST connect; //creat struct called connect of type CONNECT_REQUEST



/* construct CONNECT_REQUEST structure */
connect.headersize = 0x06; //static EIB header size
connect.protocolversion = 0x10; //protocol version (1.0)
connect.servicetype[1] = 0x02,0x05; //service type in this case a connect_request
connect.totallength[1] = 0x00,0x18; //total length (24 byte)
connect.controllength = 0x08; //HPAI header for control endpoint
connect.protocoltype = 0x01; //0x01 UDP, 0x02 TCP
connect.IPcontrol[0] = oca, connect.IPcontrol[1] = ocb, connect.IPcontrol[2] = occ, connect.IPcontrol[2] = ocd;//set IP endpoint
connect.portcontrol[0] = recv_str[12]&255, connect.portcontrol[13]&255; //set port number for control endpoint
connect.datalength = 0x08; //HPAI header length for data endpoint
connect.IPdata[0] = oca, connect.IPdata[1] = ocb, connect.IPdata[2] = occ, connect.IPdata[3] = ocd;//set data end point IP
connect.portdata[1] = 0x0e,0x57; //set data port to 3671 default for EIB
connect.connectheader = 0x02; //connection type structue length
connect.connecttype = 0x04; //connection type in this case tunneling 04

if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) //Creat UDP socket
DieWithError("UDP socket creation failed\n");

/* construct UDP address structure */
memset(&udp_addr, 0, sizeof(udp_addr)); //set udp_addr struct to 000's using memset
udp_addr.sin_family = AF_INET; //set family type to AF_INET
udp_addr.sin_addr.s_addr = htonl((oca,'.',ocb,'.',occ,'.',ocd)); //set address as any
udp_addr.sin_port = htons(mc_port); //set the port as the same multi cast port

if ((sendto(sock, &connect, sizeof(connect), 0, (struct sockaddr *) &udp_addr, sizeof(mc_addr))) != sizeof(connect)) //send data to socket
DieWithError("sendto() sent incorrect number of bytes");

close(sock);

exit(0);
}


This code compiles, but I get the error Invalid argument when sending to the socket. I have also tried casting to a pointer, but this gives an error when comilping.

Any help would be greatly appreciated

Dino
04-08-2008, 07:26 AM
char servicetype[1];// = 0x0205; //service type in this case a connect_request
char totallength[1];// = 0x0018; //total length (24 byte)
...
char IPcontrol[3];//; //four chars for conrtol endpoint IP
...
char portcontrol[1];// //two chars for control endpoint port must be gleaned during discovery
...
char IPdata[3]; // //fours chars for data endpoint IP use same IP as control endpoint
char portdata[1];// = 0x0e57; //set data port to 3671 default for EIB


Methinks you are off in your count a few places.

chrisjmoss
04-08-2008, 07:36 AM
char IPcontrol[3]; //four chars for conrtol endpoint IP
char IPdata[3]; //fours chars for data endpoint IP use same IP as control endpoint
char portdata[1]; //set data port to 3671 default for EIB


because they are not strings i.e not terminated with \0 can I not just use the array elements [0].[1],[2] and [3]. giving me the 4 required characters.

Dino
04-08-2008, 08:01 AM
In this case,

char IPcontrol[3];

you are saying the array is 3 bytes long, plain and simple. If you want it to be 4 bytes long, code

char IPcontrol[4];

I think you are confusing array length with array indexing. The highest element when indexing a 4 byte array is 3, as in:

IPcontrol[0] (the 1st element)
IPcontrol[1] (the 2nd element)
IPcontrol[2] (the 3rd element)
IPcontrol[3] (the 4th element)

chrisjmoss
04-08-2008, 08:37 AM
Todd thanks for the help thus far, I was being a bit of a div and got confused with array size and indexing, but I have sorted that out now.


char servicetype[2];// = 0x0205; //service type in this case a connect_request
char totallength[2];// = 0x0018; //total length (24 byte)
char controllength;// = 0x08; //HPAI header for control endpoint
char protocoltype;// = 0x01; //0x01 UDP, 0x02 TCP
char IPcontrol[4];//; //four chars for conrtol endpoint IP
char portcontrol[2];// //two chars for control endpoint port must be gleaned during discovery
char datalength ;// = 0x08; //HPAI header length for data endpoint
char IPdata[4]; // //fours chars for data endpoint IP use same IP as control endpoint
char portdata[2];//


I'm still having having issues sending the structure with the sendto function do I need to cast from the structure or create a pointer to it.


struct CONNECT_REQUEST connect; //creat struct called connect of type CONNECT_REQUEST

if ((sendto(sock, &connect, sizeof(connect), 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr))) != sizeof(connect)) //send data to socket
DieWithError("sendto() sent incorrect number of bytes");

Dino
04-08-2008, 08:46 AM
"issues" is a bit vague. We have no error messages to work with here.

Salem
04-08-2008, 09:11 AM
> connect.portdata[1] = 0x0e,0x57;
Also, the comma operator does not incrementally assign each value to each successive array element.

Also, check that your struct is actually the size you want.
Using a struct like this to communicate with an external API is generally non-portable.


unsigned char message[SOME_SIZE];
message[MSG_HEADER_SIZE] = 0x06;
message[MSG_PROTOCOL] = 0x10;
message[MSG_SERVICE_LSB] = 0x05;
message[MSG_SERVICE_MSB] = 0x02;
// and so on

Tedious to be sure, but it's the only way to be sure of isolating yourself from padding, alignment and endian issues. Though TBH, a struct composed entirely of char should be OK.