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