Little-Endian Active Mode Tcp ?

Kent Boortz kent@REDACTED
Wed May 28 22:53:27 CEST 2003


Eric Newhuis <enewhuis@REDACTED> writes:
> The active-mode {packet, 4} socket is AMAZING.  This is what one
> needs.  Beautiful.  But...
> 
> I'd love to get rid of the binary continuation fragments in my
> recursive feed parsers.  I could do it if Erlang would parse the
> little-endian header.  My messages originate from an Intel box and the
> 4-byte size header is little-endian.  I want Erlang to handle those
> headers so I can simplify my parser code to focus on the message
> content instead of content + framing.
> 
> 1. Is there a way to do this without hacking the Erlang source?
> 2. If not then is there a way to do this by hacking the Erlang source?

If you don't have control of the originating side (no source) you
could hack the emulator to handle these packets. But a nicer way is
probably to do it all in Erlang using two reads with gen_tcp:recv()
for each packet, first read the four length bytes, calculate the size
from the bytes and read the exact packet body with a new
gen_tcp:recv().

If you want to hack the emulator for the fun of it you have to define
a constant in "lib/kernel/src/inet_int.hrl" and add your packet type
in "lib/kernel/src/prim_inet.erl" in the function type_opt().

  -define(TCP_PB_R4,   15).  % Reverse byte order

Then add code in "erts/emulator/drivers/common/inet_drv.c" for
handling the header. Define

  #define TCP_PB_R4    15

and duplicate all code handling TCP_PB_4 and change TCP_PB_4 to 
TCP_PB_R4. Finally add the small change for reading the size

    case TCP_PB_R4:
        /* TCP_PB_R4:    [L0,L1,L2,L3 | Data] */
        hlen = 4;
        if (n < hlen) goto more;
        plen = get_int32_le(ptr);
        goto remain;
    .
    .
    case TCP_PB_R4:
        put_int32_le(len, buf);
        h_len = R4;
        break;
    .
    .
    case TCP_PB_R4:
        put_int32_le(len, buf);
        h_len = R4;
        break;

Add to "erts/emulator/beam/sys.h" the macros

#define get_int32_le(s) ((((unsigned char*) (s))[3] << 24) | \
                         (((unsigned char*) (s))[2] << 16) | \
                         (((unsigned char*) (s))[1] << 8)  | \
                         (((unsigned char*) (s))[0]))

#define put_int32_le(i, s) {((char*)(s))[3] = (char)((i) >> 24) & 0xff; \
                            ((char*)(s))[2] = (char)((i) >> 16) & 0xff; \
                            ((char*)(s))[1] = (char)((i) >> 8)  & 0xff; \
                            ((char*)(s))[0] = (char)((i)        & 0xff);}

At least I think this will do it ;-)

kent



More information about the erlang-questions mailing list