tags:

views:

111

answers:

4

Hey everyone,

I have a class for an RDT Header that holds information for an implementation of several reliable data transfer protocols. I need to attach that information (a total of 12 bytes) to my send buffer to transfer it over the socket. I am trying to use memcpy to do this but for some reason it just leaves junk inside the buffer. Below is the line of code that isnt working. (RDT_HDR_SIZE is defined as 12).

Definition of variables that are passed to this function.

char payload[] = "sample code sample code";
int payload_size = sizeof(payload) ; 
int pktsize = payload_size + sizeof( RdtHeader )+1 ; // 1 byte for NULL-terminated
char * send_buf = new char[pktsize];

The function with memcpy that is having issues.

unsigned int Sender::CreateSegment( char * buf, 
         char payload[], int payload_size, unsigned long seqnum ) {
     RdtHeader * header = (RdtHeader *) buf; 
     // set rdt fields:
     header->ack = 0; 
     header->fin = 0; 
     header->ok = 0; 
     header->seq = seqnum; 
     header->win = 0;
     header->syn = 0;
     memcpy( buf+RDT_HDR_SIZE, payload, payload_size );

     return (payload_size + RDT_HDR_SIZE + 1);
}

If i take out RDT_HDR_SIZE, the payload is assigned properly to buf, however it wipes out all my header fields. Any idea how to get this to work?

Thanks,

Eric R.

EDIT:

Here is the code for my RdtHeader class -- perhaps it will be of use.

class RdtHeader{    // 12-byte header 
public: 
//1-byte flags field
    u_char protocol:2;      // 2 bits: protocol type = 0 for RDT3, 1 for GBN, and 2 for STCP    
    u_char syn:1;           // 1 bit: SYN = 1 for connection setup  
    u_char fin:1;           // 1 bit: FIN = 1 for termination
    u_char ok:1;            // 1 bit: OK = 1 receiver agrees, SYN_OK or FIN_OK
    u_char reserved:3;      // 3 bits: unused

    u_char unused;          // 1-byte unused filed; 

    u_short win;            // 2-byte receiver window size (the number of packets)
    u_long seq;             // 4-byte sequence number
    u_long ack;             // 4-byte ack number
}; 
A: 

Have you tried using sizeof(RdtHeader) rather than hard coding the buffer size?

Mark
+2  A: 

As Mark said, look at sizeof(RdtHeader). There might be some padding inside the struct (especially since there is a long int there) that throws the calculations off.

But other than that, I don't see an obvious problem here. I would try to add some print-outs, if you're running it in an environment where that is feasible, or try a debugger. Possibly the real problem is elsewhere in your code.

Thomas Padron-McCarthy
I tried memcpy(buf+sizeof(RdtHeader), payload, payload_size) and still doesn't copy. It just leaves junk in the buffer. I placed a printf right after the memcpy and does not have the payload in it. I edited the original post and added my class definition for RdtHeader
Eric Reynolds
A: 
memcpy(header + 1, payload, payload_size + 1);
return sizeof(*header) + payload_size + 1;
  • You're mysteriously returning an extra 1, suggesting the payload is a null-terminated string. You might want to copy that terminator, so it's included in the last memcpy parameter.
  • By using the header pointer to calculate the memcpy destination, you'll never have to cast if types change, in particular if you change the type of buf. You can rely on the fact that C++ allows X * to degrade to void * to avoid ugly casting.
Matt Joiner
Not 100% sure what you mean by this. Using the code you provided, there is no change in the output. My buffer still just holds junk. If I remove the addition on the pointers in memcpy (whether using the header, or buf), payload is copied fine, but I lose all my header information.
Eric Reynolds
+3  A: 

This may be too obvious, but exactly how are you inspecting the buffer?

Have you tried

printf( "%s\n", send_buf + sizeof(RdtHeader) );

?

If you instead are doing ...

printf( "%s\n", send_buf );

... then you should expect to see just garbage (with correct operation) since the win field acts as zero-terminator for the "string" that that latter call is printing.

Cheers & hth.,

– Alf

Alf P. Steinbach
/facepalm --- Ok, so basically the moral of the story is that I technically gave it a null terminator when assigning values to my RdtHeader. Thank you for pointing this out. I just couldn't make sense of why my memcpy wasnt working when I felt it should have been fine. Occams Razor...Wasn't the copy, but how I was seeing what was copied.
Eric Reynolds