serialize and deserialize structures in sockets - c++

I have a Struct to send over a socket to a client. Both the Client and the Server is on the same architecture so there is no endian problem. I receive the int values properly. But not able to receive the char[] values properly.
This is the structure.
struct Packet {
int id;
int number;
char data[256];
};
In the Server side I serialize the data and write to the client.
struct Packet *s = new Packet();
s->id= htonl(1000);
s->number= htonl(7788);
memcpy(s->data, "MESSAGE", 7);
n = write(NewSockFD , s ,sizeof(s) );
In the Client side I deserialize the data.
n = read(SockFD , Buffer , sizeof(Buffer));
struct Packet *s = (struct Packet*)Buffer;
char b[256];
int i = ntohl(s->id);
int j = ntohl(s->number);
memcpy(b, s->data, sizeof(s));
I receive the id and number values correctly. Problem is with the data value. What I'm doing wrong here??..

In your code, you use sizeof(s). This will be the size of a Packet*, not a Packet. Replace it with sizeof(*s) to get the correct size.
Additionally, since the values of data are not all initialised, you cause undefined behaviour by reading from it. You need to initialise all the elements one way or the other (the shortest way would be to do char data[256] { }; in the struct definition).
Also since this is C++, you don't need to say struct Packet, you can say just Packet, unless you also have a function named Packet. But it appears in your code only half the time which means you don't, so you can just drop it.
And as Chris G mentioned, you have another problem after you fix that, which is that you're copying an entire Packet into a char[] only big enough to hold a Packet's data. Change
memcpy(b, s->data, sizeof(s))
to
memcpy(b, s->data, sizeof(s->data))
And realise that this data may not be nul-terminated if the sender didn't do it for you (which you may want to take precautions against).

Related

Calling class functions that use character arrays (C++)

I mostly work with C and have not used classes in quite a while. I am trying to use some class functions that someone else has created but I cannot get the deserialize() function to work. I understand what it does, but I cannot for the life of me figure out how to call this function. I have provided functions and how I am trying to call them below.
//Creates a packet
packet::packet(int t, int s, int l, char * d){
type = t;
seqnum = s;
length = l;
data = d;
}
// This function serializes the data such that type, seqnum, length, and data values are placed
// in a char array, spacket, and separated by a single space; that is, spacket contains the serialized data
void packet::serialize(char * spacket){
cout << "data: " << endl << endl;
sprintf (spacket, "%d %d %d %s", type, seqnum, length, data);
}
// This function deserializes a char array, spacket, which is the result of a call to serialize
void packet::deserialize(char * spacket){
char * itr;
itr = strtok(spacket," ");
char * null_end;
this->type = strtol(itr, &null_end, 10);
itr = strtok(NULL, " ");
this->seqnum = strtol (itr, &null_end, 10);
itr = strtok(NULL, " ");
this->length = strtol (itr, &null_end, 10);
if(this->length == 0){
data = NULL;
}
else{
itr = strtok(NULL, "");
for(int i=0; i < this->length; i++){ // copy data into char array
this->data[i] = itr[i];
}
}
}
And here is how I am trying to get this to work:
packet *test = new packet(1, 4, 4, message); //message is a *char with the data
test->serialize(sendbuf); //this works correctly
packet *test2 = new packet(0,0,0, NULL); //I am not sure if I need to be creating a new packet for the deserialized information to get placed into
test->deserialize(sendbuf); //results in a segmentation fault currently
I just don't understand how to call deserialize(), I have created a packet and serialized it and that part works fine, but I don't understand how to reverse it. Do I need to create an empty packet object first? If so, how? I have tried doing that multiple ways but I cannot get it to work. I know this is very basic but like I said, I have not worked with classes in a couple of years. It took me quite a while just to get serialize to work but I have tried everything I can think of for deserialize and am stuck.
#Pongjazzle,
I agree with Sam that the class design needed refinement. However, I think you can figure it out. Perhaps, you might want to do it this way to test your code, assuming sendbuf can hold all the serialized packet data.
packet *test = new packet(1, 4, 4, message);
test->serialize(sendbuf);
packet *test2 = new packet(0,0,0, NULL); // results in a segmentation fault currently (which is expected as the attempts to access a location referred to by a null pointer in this->data (i.e., NULL based on the object instantiation code)
test->deserialize(sendbuf);
Change it to:
packet *test2 = new packet(0,0,0, newmessage); // assign a valid buffer
test2->deserialize(sendbuf); // Now fill's in the values and buffer from serialized content.
The class you're using is not designed very well.
For starters, the serialize() function takes a pointer to an output buffer, without having any means to specify the size of the buffer. It takes it on faith that the buffer is going to be big enough for the "serialized" data. If it's not, it will happy scribble over random memory.
Then, deserialize() is also impressive. For starters, no self-respecting deserializer requires a mutable pointer to the data being deserialized. A deserializer should only require a constant, or a read-only pointer.
Of course, the reason that this deserialize() wants a mutable buffer is because it scribbles over, and overwrites via strtok(), the buffer it's deserializing. Which means that you cannot use the serialized object to deserialize two or more instances of the object, unless you make a copy of the serialized object beforehand.
It is not actually clear, from what you've shown, where the actual bug is, but it's most likely because you did not allocate a buffer that's big enough for the serialized object. Even though you believe that "it works correctly", it didn't, and ended up corrupting memory, which didn't become evident until the code tried to deserialize the corrupted buffer, resulting in undefined behavior.
But, if you do believe that your buffer was big enough, you should be able to figure out the answer yourself by using your debugger to step through the code, and examine what it's doing. For problems involving segmentation faults at runtime, the correct answer is to always use a debugger, to examine the runtime status of the application and determine the problem.

crash after memcpy: access violation reading location

if (m_Connections[t].socket != INVALID_SOCKET)
{
m_TCPResult = recv(m_Connections[t].socket, m_TCPRecvbuf, m_TCPRecvbuflen, 0);
if (m_TCPResult > 0)
{
printf("[TCPReceive] Bytes (m_TCPResult) received from %d: %d\n", m_Connections[t].socket, m_TCPResult);
// Deserialize the data
Packets::MainPacket receivedData;
memcpy(&receivedData, m_TCPRecvbuf, sizeof(receivedData));
// Check the type and do something with the data
CheckType(m_Connections[t].socket, receivedData);
}
else
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
printf("TCPReceive error: %d\n", WSAGetLastError());
}
}
So I have this piece of code. I need to do a memcpy() to convert the incoming data from winsock to a struct that can be read by the application. However, after the CheckType() method is done the application crashes giving me an Access Violation Reading Location error. I removed the memcpy() method once to check and then it worked fine (no crashes).
I have no idea what the problem might be. I've been searching on Google but haven't found anything useful that seems to be a solution to my problem
EDIT:
Some more info:
// in the header
char m_TCPRecvbuf[DEFAULT_BUFLEN];
// receivedData struct
struct MainPacket
{
char type;
int id;
LoginData loginData;
vector<PlayerData> playerData;
};
You're writing over the vector when you do your memcpy. It's not a POD you can't initialize it via a memcpy, but instead have to use it's member functions to initialize it.
Think of it this way, the vector will have a pointer to the data it manages and a size_t indicating the size, at a minimum. You can't just initialize the pointer by memcpying a value you've received over the network. The pointer may make sense to the sender, but when you receive it all you've got is a pointer that's valid on the server, not in your application. Because of this the moment you try to use the vector you'll get undefined behaviour and will probably crash (if you're lucky).
Also, as a result of this sizeof doesn't work in the way you'd expect when applied to classes. For example, if you've got vector with 1,000 items in it then sizeof won't reflect this. What sizeof tells you is the combined size of all the member variables in the class definition (subject to padding). If our vector implementaton is just a pointer and a size_t then it'll probably be around 8 bytes on a 32bit platform, and 16 on a 64bit platform, regardless of how many items are in the vector.
What you need to do is encode information in the packet so that you can decode it. For example, rather than send a vector your packet should contain a field indicating the number of PlayerData instances, followed by the data for each player.

Is it possible to write in input buffer passed into function more than was expected? (no stack overflow)

I doing some packet translation patch.
My dll injects into Chinese game, hooks recv, listen for packets and translates strings received in Chinese.
I was coding and coding and coding... Until I found out how I supposed to write in buf more than the packet length?
int __stdcall Hooked_recv(SOCKET s, char *buf, int len, int flags)
{
h_recv.PreHook();
int ret_val = recv(s, buf, len, flags);
//ret_val is the number of bytes received. Ok, I can increase it, but...
//what to do with buf? Sure I can write there as much as no access violation appears.
//but I need a safe way.
//I guess if I do buf = new char[NEW_SIZE] then caller will fail to read buf because of pointer changed?
//what could I do to make received packet longer?
//I no want to reverse exe and increase buffer in hex editor. at least for now.
h_recv.PostHook();
return ret_val;
}
Just fill the buffer as much as you can. If you have any leftover, save it for the next call to your hooked receive function (put that first, if that fills it, repeat saving the new leftover). You will need to use a buffer, that's unavoidable.

Parsing buffer data in C++

My C++ project has a buffer which could be any size and is filled by Bluetooth. The format of the incoming messages is like 0x43 0x0B 0x00 0x06 0xA2 0x03 0x03 0x00 0x01 0x01 0x0A 0x0B 0x0B 0xE6 0x0D in which starts with 0x43 and ends with 0x0D. So, it means that each time when buffer is filled, it can have different order of contents according to the above message format.
static const int BufferSize = 1024;
byte buffer[BufferSize];
What is the best way to parse the incoming messages in this buffer?
Since I have come from Java and .NET, What is the best way to make each extracted message as an object? Class could be solution?
I have created a separate class for parsing the buffer like bellow, am I in a right direction?
#include<parsingClass.h>
class A
{
parsingClass ps;
public:
parsingClass.parse(buffer, BufferSize);
}
class ReturnMessage{
char *message;
public:
char *getMessage(unsigned char *buffer,int count){
message = new char[count];
for(int i = 1; i < count-2; i++){
message[i-1] = buffer[i];
}
message[count-2] = '\0';
return message;
}
};
class ParserToMessage{
static int BufferSize = 1024;
unsigned char buffer[BufferSize];
unsigned int counter;
public:
static char *parse_buffer()
{
ReturnMessage rm;
unsigned char buffByte;
buffByte = blueToothGetByte(); //fictional getchar() kind of function for bluetooth
if(buffByte == 0x43){
buffer[counter++] = buffByte;
//continue until you find 0x0D
while((buffByte = blueToothGetByte()) != 0x0D){
buffer[counter++] = buffByte;
}
}
return rm.getMessage(buffer,counter);
}
};
Can you have the parser as a method of a 'ProtocolUnit' class? The method could take a buffer pointer/length as a parameter and return an int that indicates how many bytes it consumed from the buffer before it correctly assembled a complete protocol unit, or -1 if it needs more bytes from the next buffer.
Once you have a complete ProtocolUnit, you can do what you wish with it, (eg. queue it off to some processing thread), and create a new one for the remaining bytes/next buffer.
My C++ project has a buffer which could be any size
The first thing I notice is that you have hard-coded the buffer size. You are in danger of buffer overflow if an attempt is made to read data bigger than the size you have specified into the buffer.
If possible keep the buffer size dynamic and create the byte array according to the size of the data to be received into the buffer. Try and inform the object where your byte array lives of the incoming buffer size, before you create the byte array.
int nBufferSize = GetBufferSize();
UCHAR* szByteArray = new UCHAR[nBufferSize];
What is the best way to parse the incoming messages in this buffer?
You are on the right lines, in that you have created and are using a parser class. I would suggest using memcpy to copy the individual data items one at a time, from the buffer to a variable of your choice. Not knowing the wider context of your intention at this point, I cannot add much to that.
Since I have come from Java and .NET, What is the best way to make
each extracted message as an object? Class could be solution?
Depending on the complexity of the data you are reading from the buffer and what your plans are, you could use a class or a struct. If you do not need to create an object with this data, which provides services to other objects, you could use a struct. Structs are great when your need isn't so complex, whereby a full class might be overkill.
I have created a separate class for parsing the buffer like bellow, am
I in a right direction?
I think so.
I hope that helps for starters!
The question "how should I parse this" depends largely on how you want to parse the data. Two things are missing from your question:
Exactly how do you receive the data? You mention Bluetooth but what is the programming medium? Are you reading from a socket? Do you have some other kind of API? Do you receive it byte at a time or in blocks?
What are the rules for dealing with the data you are receiving? Most data is delimited in some way or of fixed field length. In your case, you mention that it can be of any length but unless you explain how you want to parse it, I can't help.
One suggestion I would make is to change the type of your buffer to use std::vector :
std::vector<unsigned char> buffer(normalSize)
You should choose normalSize to be something around the most frequently observed size of your incoming message. A vector will grow as you push items onto it so, unlike the array you created, you won't need to worry about buffer overrun if you get a large message. However, if you do go above normalSize under the covers the vector will reallocate enough memory to cope with your extended requirements. This can be expensive so you don't want to do it too often.
You use a vector in pretty much the same way as your array. One key difference is that you can simply push elements onto the end of the vector, rather than having to keep a running pointer. SO imagine you received a single int at a time from the Bluetooth source, your code might look something like this:
// Clear out the previous contents of the buffer.
buffer.clear();
int elem(0);
// Find the start of your message. Throw away elements
// that we don't need.
while ( 0x43 != ( elem = getNextBluetoothInt() ) );
// Push elements of the message into the buffer until
// we hit the end.
while ( 0x0D != elem )
{
buffer.push_back( elem );
}
buffer.push_back( elem ); // Remember to add on the last one.
The key benefit is that array will automatically resize the vector without you having to do it no matter whether the amount of characters pushed on is 10 or 10,000.

Most efficient way of writing byte array for streaming

I need to create a byte array that is needed to be stream to another device through UART. There are some fixed parameters that I can fill in before hand but variables such as string is dynamically sized. Right up till now, I've been doing:
unsigned char buffer[255];
unsigned char wr_head = 0;
buffer[wr_head++] = 0x01; // and so on
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;
I've experimented with other methods like std::string and std::vector but I felt that there is much manageable way of writing byte array for streams. Suggestions?
edit: Please advice on performance as well because is threaded.
edit2: Sorry for lacking of details the first time around. The device is indeed an embedded device. Though some suggested some solution, its not really what I want. Maybe a snippet of my current implementation will clear some confusion:
unsigned char buffer[255];
unsigned char wr_head = 0;
buffer[wr_head++] = 0x01; // Set message type
buffer[wr_head++] = 0x30; // message length
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;
buffer[wr_head++] = CalChecksum;
UartSend(&buffer, wr_head); // Send array to stream out from UART
The configuration and setting value is known before hand, provided by the device documentation. This question is related to what I've asked in here
Thanks for the effort so far.
A ring buffer is a typical solution for problems like these.
I have no idea what kind of device you're on, but I'll just suppose that you're writing for some kind of embedded device. Let's assume that there's some interrupt moving data from the ring buffer to the UART. This interrupt will call getc, other code will call putc and puts.
class RingBuffer {
private:
static unsigned BUFSZ = 256;
volatile unsigned char buf[BUFSZ];
volatile unsigned char read, write;
public:
RingBuffer() : read(0), write(0) { }
// Blocks until space is available
void putc(unsigned int c) {
while (((write - read) & (BUFSZ - 1)) == 1)
sleep();
buf[write++ & (BUFSZ - 1)] = c;
}
// Returns -1 if empty
int getc() {
if (read == write)
return -1;
return buf[read++ & (BUFSZ - 1)];
}
// There are faster ways to write this.
void puts(char *str) {
for (; *str; ++str)
putc(*str);
}
};
Typically, you don't want to make the buffer dynamically grow for something like this. There's lots of room for improvement in the above code, and there are also libraries available for this kind of thing.
This particular implementation also never lets you fill the buffer completely, but the code is simpler as a result. I probably wouldn't put this code in production, but hopefully it's a step in the right direction.
If UartSend is a blocking function then you can do just this:
void UartSend(byte b) { UartSend(&b, 1); } // sends one byte
UartSend(0x01); // Set message type
UartSend(0x30); // message length
UartSend(some_chararray,sizeof(some_chararray));