Re: [dev] network protocol packing

From: Markus Wichmann <nullplan_AT_gmx.net>
Date: Wed, 2 Jul 2014 06:34:01 +0200

On Mon, Jun 30, 2014 at 08:54:52PM +0200, Markus Teich wrote:
> Heyho,
>
> since I did not find any suckless project regarding this issue, I would like to
> ask you guys for some feedback:
>
>
> unsigned char *msg;
> size_t msg_size;
> struct foo *msg_data;
> struct bar *msg_signature;
>
> msg_size = sizeof(unsigned char) // op
> + sizeof(struct foo) // data
> + sizeof(struct bar) // signature
> msg = malloc(msg_size);
>
> *msg = MSG_OP_SIGNED_DATA;
>
> msg_data = (struct foo *)(msg + 1);
> msg_data->field0 = bla;
> msg_data->field1 = blub;
>
> msg_signature = (struct bar *)(msg_data + 1);
> create_signature(msg, msg_signature);
>
> sendmsg(msg);
>
> free(msg);
>
>
> I feel it is pretty good already compared to other message packing I've seen,
> but do you know a way to make it suck even less?
>
> --Markus
>

The alignment issue was already mentioned (there's nothing like your
program working at home and then suddenly dying of SIGBUS in the field
to hammer that point home), but unless all your data is single bytes,
you also have byte order problems. Solving these requires some suck.

There are basically only two ways to resolve these problems: Either copy
the data into the buffer and flip it later, or flip it on the way. I'd
personally go with flipping on the way:

unsigned char *p = msg;
*p++ = MSG_OP_SIGNED_DATA;
align32(&p, msg);
write_be32(&p, bla);
write_be16(&p, blub);
/* and so on */

Then implement them like:

void write_be32(unsigned char **p, uint32_t i)
{
    *(*p)++ = i >> 24;
    *(*p)++ = i >> 16;
    *(*p)++ = i >> 8;
    *(*p)++ = i;
}

Then you are even independent of the host processor's byte order.

HTH,
Markus
Received on Wed Jul 02 2014 - 06:34:01 CEST

This archive was generated by hypermail 2.3.0 : Wed Jul 02 2014 - 06:36:11 CEST