Packet cast to struct with multiple dynamic arrays - c++

I'm currently working on a Client/Server application, sending packets via TCP.
To read the incoming packet, I do something like this:
struct SomeRandomStruct
{
int nVal1;
int nVal2;
};
SomeRandomStruct* pStruct = reinterpret_cast<SomeRandomStruct*>(pBuffer);
Right now there's a small problem. Let's say I have a struct like this
struct SomeNewStruct
{
int nNameLen;
int nPassLen;
char szName[];
char szPass[];
};
Since the size/length of szName & szPass is sent in the same packet, is there a way I can set its size ,,within the reinterpret_cast" or do I have to read the packet manually?

Friendly warning:
stop!
Consider something like google protocol buffers to encode messages for you in a cross-platform and safe way.
Here are some reasons why:
How big is an int? On your machine? today? tomorrow? It's undefined in the c++ standard.
What is the binary representation of an int? Is it the same on the machine sending and the machine receiving? Will it always be? (If you think 'yes' then you're wrong). Again the c++ standard has nothing to say on the matter.
What is the padding between data members in the struct? Is it the same for all compilers on all hosts? (answer: no)
ask yourself why functions like htons() exist. They are there because not all machines are the same, but the communication between them must be.
I could go on...

As your question is tagged C++, I'd propose you to do dynamic allocation in constructor and deallocation in destructor. That way, you could have simply pointers in your struct :
struct struct SomeNewStruct {
int nNameLen;
int nPassLen;
char *szName;
char *szPass;
SomeNewStruct(int nameLen , int passLen) {
// set and alloc...
}
SomeNewStruct(SomeNewStruct &src) {
// alloc and copy
}
~SomeNewStruct() {
// dealloc ...
}
}
You could even use std::string for szName and SzPass letting the STL deal with those low level allocation details :
struct struct SomeNewStruct {
int nNameLen;
int nPassLen;
std::string szName;
std::string szPass;
}

Related

Packet wrangling from C to C++ or... how Neither Variant nor Any is a Union

The problem in a nutshell: I'm considering a rewrite of some packet handling code for a UDP protocol ... from C to C++. Obviously, I can just use the structures that I had with C to model the data, but then what would be the point? So, for the sake of argument, we have:
struct { uint8:2 type; uint8:6 con_id; uint16 seq_num } packet_header;
struct { packet_header ph; uint16 command; } control_packet;
struct { packet_header ph; uchar8 data[DATASIZE]; } data_packet;
In this case, "type" is 0 for data, 1 for control, 2 for encrypted data and 3 for encrypted control. There would also be structs reprenting each of the control packets, for argument, lets say "open" and "close".
Now... I would normally have a type that the function that fetches the packet returns and the function that sends accepts:
struct {
size_t pkt_len;
union {
uchar8 raw_packet[DATASIZE];
packet_header ph;
control_packet cp;
control_open_packet cop;
control_close_packet ccp;
data_packet dp;
} p;
} packet;
... this is all simplified for argument... but the point is: when sending a packet, we want to create a packet of a certain type and send a generic packet. Conversely, when receiving a packet, you want to receive a generic packet and and cast it to more specific types as you classify it.
So where's the question? My question is: if Variant and Any are not appropriate ways to express this, what are? Am I stuck with union in this case? Certainly I don't violate the stipulation of POD types (so far) for the union. I've been scouring both C++11 and Boost (and to some extent looking at C++14 ... although I'm stuck with C++11) and I don't see offered solutions.
You can use both union as it is in your example or class hierarchy with packet_header a the top and specific derived classes for each type of the packet:
struct packet_header { uint8:2 type; uint8:6 con_id; uint16 seq_num };
struct control_packet : packet_header { uint16 command; };
struct data_packet: packet_header { uchar8 data[DATASIZE]; };
struct packet
{
size_t pkt_len;
union
{
uchar8 raw_packet[DATASIZE];
packet_header ph;
control_packet cp;
control_open_packet cop;
control_close_packet ccp;
data_packet dp;
};
};
Maybe you need to seek for elegance and flexibility in the code that handles your packets. I doubt that defining data in some other way (using boost or using C++17 features) will lead to a considerable gain.
Note the anonymous union in the struct packet. It allows accessing fields of specific packet types directly. C++ style expects the name of the struct directly after the struct keyword.

msgpage C++ : send raw pointer with MSGPACK_DEFINE

I would like to send the following struct over msgpack.
struct MyStruct {
std::string name{""};
int* val{nullptr};
MSGPACK_DEFINE( name, val );
};
Thus far in all of my projects, the only way I've streamed with msgpack is using MSGPACK_DEFINE, then writing the struct to msgpack::sbuffer (and sending it). the MSGPACK_DEFINE macro complains that that perhaps I missed the "->" so I'm guessing it doesn't detect that it's a pointer.
Smart pointers seem to work though:
struct MyStruct {
std::string name{""};
std::shared_ptr<int> val{nullptr};
MSGPACK_DEFINE( name, val );
};
The caveat is that the receiver on the other end needs val to be a raw pointer. I would like to do this without converting on the receiving side. Any ideas?
You failed to explain why you wish to do this. Pointers are never meaningful when serialized (otherwise it is in-process data and there is no need to serialize).
Just pass the value that the pointer points to. If you need to represent "a number or NULL", then pass a struct containing an integer and boolean.
struct NullableInt {
int value{0};
bool null{true};
};

C++/Pointer to a Structure/ validate members

below is my structure which i expose to user to populate it by giving it some size using malloc.
the use passes me the pointer to this structure
typedef struct ServerConfiguration {
wchar_t *IPAddress;
USHORT PortNo;
wchar_t *Title;
int repeatCount;
int timeout;
} ServerConfig;
ServerConfig *serverconfig = (ServerConfig*)malloc(sizeof(ServerConfig));
dcmServerconfig->IPAddress = L"localhost";
dcmServerconfig->Title = L"DVTK_MW_SCP";
dcmServerconfig->PortNo = 8080;
user doe not assign repeat count//
which points to some junk address loc //example repeatCount=380090700
i have another structure which has struct,
typedef struct CommonParameters {
//other members;
int repeatCount
} commonParams;
i have to validate ServerCOnfig values and then assign it to CommonParameters as show below
if (serverConfig->opt_repeatCount > 1) {
commonParams.repeatCount = serverConfig->repeatCount;
}
The value of serverConfig->repeatCount is some junk(380090700) if not assigned by user. and which is greater than 1 in my case. I need to validate if this serverConfig->repeatCount is having a valid value then only pass the if condition
Ultimately my question is to validate a structure variable which is integer for a proper value.
Your code looks like it's written in a very C-based style (i.e. allocating a chunk of memory with malloc and then initializing the struct's fields manually). If you adopt a more common C++-based style where you use new to allocate your memory and constructors to initialize your fields you'll find these kinds of problems become easier. For example, in your case you could write CommonParameters as:
struct CommonParameters {
CommonParameters(int rc) :
repeatCount(rc)
{}
//other members;
int repeatCount
};
This way CommonParameters is initialized when it's created and you don't have to worry about its initialization status.
NOTE: Because your question is written in what looks like pure C you may have just mis-tagged the question as C++. If so, please change the tag and I'll update my answer.

converting struct to general message format to be passed to UDP

I have a C++ struct for an update packet to be exchanged between servers, and another struct to implement information about neighbors, and a vector of struct neighbor is inside update packet.
struct neighbor;
struct update_packet {
uint16_t num_update_fields;
uint16_t port;
uint32_t IP;
vector<struct neighbor> neighbors;
update_packet(char * IPstr, int port) :
num_update_fields(num_nodes),
IP(IP_to_int(IPstr)), port((uint16_t) port)
{ };
};
struct neighbor {
uint32_t IP;
uint16_t port;
int16_t nil;
uint16_t server_id;
uint16_t cost;
neighbor(char * IPstr, uint16_t port, uint16_t server_id, uint16_t cost) :
IP(IP_to_int(IPstr)), port(port), nil(0),
server_id(server_id), cost(cost) { };
};
I want to exchange this struct in general message format (like IP datagram, for example) through UDP sockets and read the information in the message on the receiving end.
How can I achieve this? Is my design for the structs a poor design for my purpose?
What you're asking about is serialization. At it's simplest, if you have a POD type and know that the machines at both ends are the same type you can just cast and send:
struct Foo {
uint32_t a;
uint16_t p;
};
Foo f { 1, 2 };
sendto(targetFD, reinterpret_cast<const char*>(&f), sizeof(f), 0);
Your structure couldn't be used this way because of the vector. The data in a vector is dynamically allocated so it isn't laid out with the rest of the structure. If you need a variable length field like this, an array (or a std::array) along with an indicator of the number of elements would be useful.
Casting structures like this is fast but not really portable. If you want to be able to pass to other languages or platforms you would prefer a serialization format. Google's Protocol Buffers (https://code.google.com/p/protobuf/) and several other serialization libraries are designed to allow this.
Slightly more c++ style serialization and deserialization is desribed in this article - https://rodgert.github.io/2014/09/09/type-driven-wire-protocols-with-boost-fusion-pt1/

C++ Struct - Define Minimum Size

Is there a C++ (or MSVC) method of automatically padding a struct to a minimum size? For example, imagine the following pseudo-code:
#pragma pad(256) // bytes
struct SETUPDATA {
int var1;
double var2;
};
where sizeof(SETUPDATA) = 256 bytes
The goal here being, during development this struct's members can change without changing the footprint size at runtime.
You can use a union
struct SETUPDATA {
union { struct your_data; char [256]; }
}
or something like this. This ensures it's at least 256 but only as long as your_data is not larger.
You can also add a simple assert after that just does a compiler check assert(sizeof(struct SETUPDATA) == 256)
One way is to inherit from your "real" structure and use sizeof() to make up the padded structure, for example:
struct blah_real
{
int a;
};
struct blah : public blah_real
{
private:
char _pad[256 - sizeof(blah_real)];
};
You could use #ifdef DEBUG to only do this in the debug build and just use the real structure in release build.
The first thing you have ot ask yourself is why your application cares if the struct size changes. That indicate fragility to future changes and your design may be better served by instead allowing the application to seamlessly work in the face of struct size changes.
Perhaps you're trying to serialize the data directly and don't want to face changes in the format, but in that case you're already tying yourself to one specific representation of the structure in memory. For example support the size of one of the builtin-type members changes due to a compiler upgrade or options.
But let's say you really do want to do this.
Just wrap the data in an impl and pad the real struct:
struct SetupData
{
struct Impl
{
int var1;
double var2;
};
Impl impl_;
unsigned char pad_[256 - sizeof(Impl)];
};