diff -u -r otp_src_R12B-0-untouched/erts/emulator/drivers/common/inet_drv.c otp_src_R12B-0/erts/emulator/drivers/common/inet_drv.c --- otp_src_R12B-0-untouched/erts/emulator/drivers/common/inet_drv.c 2007-11-30 21:46:26.000000000 +0000 +++ otp_src_R12B-0/erts/emulator/drivers/common/inet_drv.c 2008-02-09 16:09:27.000000000 +0000 @@ -54,6 +54,8 @@ #define USE_HTTP /* All platforms fail on malloc errors. */ #define FATAL_MALLOC +/* use new packet-parsing extensions */ +#define USE_PB_GEN_PACKET #include "erl_driver.h" @@ -534,6 +536,7 @@ #define INET_LOPT_PACKET_SIZE 32 /* Max packet size */ #define INET_LOPT_UDP_READ_PACKETS 33 /* Number of packets to read */ #define INET_OPT_RAW 34 /* Raw socket options */ +#define INET_LOPT_GEN_PACKET 35 /* Packet header parsing options */ /* SCTP options: a separate range, from 100: */ #define SCTP_OPT_RTOINFO 100 #define SCTP_OPT_ASSOCINFO 101 @@ -575,6 +578,7 @@ #define TCP_PB_TPKT 9 #define TCP_PB_HTTP 10 #define TCP_PB_HTTPH 11 +#define TCP_PB_GEN 12 /* INET_LOPT_BIT8 options */ #define INET_BIT8_CLEAR 0 @@ -980,6 +984,11 @@ #ifdef USE_HTTP int http_state; /* 0 = response|request 1=headers fields */ #endif +#ifdef USE_PB_GEN_PACKET + int gen_packet_sizelen; + int gen_packet_sizeofs; + int gen_packet_sizedelta; +#endif inet_async_multi_op *multi_first;/* NULL == no multi-accept-queue, op is in ordinary queue */ inet_async_multi_op *multi_last; MultiTimerData *mtd; /* Timer structures for multiple accept */ @@ -5202,6 +5211,25 @@ len -= arg_sz; break; +#ifdef USE_PB_GEN_PACKET + case INET_LOPT_GEN_PACKET: + if (desc->stype == SOCK_STREAM) { + tcp_descriptor* tdesc = (tcp_descriptor*) desc; + if (len < 8) + return -1; + desc->htype = TCP_PB_GEN; + tdesc->gen_packet_sizelen = ival; + tdesc->gen_packet_sizeofs = get_int32(ptr); ptr += 4; len -= 4; + tdesc->gen_packet_sizedelta = get_int32(ptr); ptr += 4; len -= 4; + DEBUGF(("inet_set_opts(%ld): s=%d, LOPT_GEN_PACKET=%d,%d,%d\r\n", + (long)desc->port, desc->s, + tdesc->gen_packet_sizelen, + tdesc->gen_packet_sizeofs, + tdesc->gen_packet_sizedelta)); + } + continue; +#endif /* def USE_PB_GEN_PACKET */ + default: return -1; } @@ -6018,6 +6046,22 @@ put_int32(arg_sz,ptr); continue; } + +#ifdef USE_PB_GEN_PACKET + case INET_LOPT_GEN_PACKET: + if (desc->stype == SOCK_STREAM) { + tcp_descriptor* tdesc = (tcp_descriptor*) desc; + *ptr++ = opt; + put_int32(tdesc->gen_packet_sizelen, ptr); + PLACE_FOR(8,ptr); + put_int32(tdesc->gen_packet_sizeofs, ptr); + put_int32(tdesc->gen_packet_sizedelta, ptr + 4); + } else { + TRUNCATE_TO(0,ptr); + } + continue; +#endif + default: RETURN_ERROR(); } @@ -7489,6 +7533,11 @@ copy_desc->high = desc->high; copy_desc->low = desc->low; copy_desc->send_timeout = desc->send_timeout; +#ifdef USE_PB_GEN_PACKET + copy_desc->gen_packet_sizelen = desc->gen_packet_sizelen; + copy_desc->gen_packet_sizeofs = desc->gen_packet_sizeofs; + copy_desc->gen_packet_sizedelta = desc->gen_packet_sizedelta; +#endif /* The new port will be linked and connected to the original caller */ port = driver_create_port(port, owner, "tcp_inet", (ErlDrvData) copy_desc); @@ -8291,6 +8340,34 @@ goto remain; } +#ifdef USE_PB_GEN_PACKET + case TCP_PB_GEN: + /* TCP_PB_GEN: [..., ((L3,L2,)L1,)L0 | Data] + * where the count of skipped bytes is gen_packet_sizeofs + * and the number of bytes in the size is gen_packet_sizelen + * and the number of additional (or fewer!) bytes to read than + * the given size is gen_packet_sizedelta + */ + hlen = desc->gen_packet_sizelen + desc->gen_packet_sizeofs; + if (n < hlen) + goto more; + { + char *sptr = ptr + desc->gen_packet_sizeofs; + switch (desc->gen_packet_sizelen) { + case 1: plen = get_int8(sptr); break; + case 2: plen = get_int16(sptr); break; + case 3: plen = get_int24(sptr); break; + case 4: plen = get_int32(sptr); break; + default: + goto error; + } + } + plen = plen + desc->gen_packet_sizedelta - hlen; + if (plen < 0) + goto error; + goto remain; +#endif + default: /* this can not occure (make compiler happy) */ DEBUGF((" => case error\r\n")); return -1; diff -u -r otp_src_R12B-0-untouched/lib/kernel/src/inet.erl otp_src_R12B-0/lib/kernel/src/inet.erl --- otp_src_R12B-0-untouched/lib/kernel/src/inet.erl 2007-11-29 14:03:26.000000000 +0000 +++ otp_src_R12B-0/lib/kernel/src/inet.erl 2008-02-09 15:14:00.000000000 +0000 @@ -112,6 +112,7 @@ {'delay_send', bool()} | {'packet_size', non_neg_integer()} | {'read_packets', non_neg_integer()} | + {'gen_packet', {non_neg_integer(), non_neg_integer(), integer()}} | %% SCTP options {'sctp_rtoinfo', #sctp_rtoinfo{}} | {'sctp_associnfo', #sctp_assocparams{}} | @@ -140,6 +141,7 @@ 'header' | 'buffer' | 'active' | 'packet' | 'mode' | 'port' | 'exit_on_close' | 'low_watermark' | 'high_watermark' | 'bit8' | 'send_timeout' | 'delay_send' | 'packet_size' | 'read_packets' | + 'gen_packet' | %% SCTP options {'sctp_status', #sctp_status{}} | 'sctp_get_peer_addr_info' | @@ -574,7 +576,7 @@ buffer, header, active, packet, deliver, mode, multicast_if, multicast_ttl, multicast_loop, exit_on_close, high_watermark, low_watermark, - bit8, send_timeout + bit8, send_timeout, gen_packet ]. %% Return a list of statistics options @@ -592,7 +594,7 @@ [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, header, active, packet, packet_size, buffer, mode, deliver, exit_on_close, high_watermark, low_watermark, bit8, send_timeout, - delay_send,raw]. + delay_send,raw, gen_packet]. connect_options(Opts, Family) -> BaseOpts = @@ -617,6 +619,8 @@ con_opt([{raw,A,B,C}|Opts],R,As) -> con_opt([{raw,{A,B,C}}|Opts],R,As); +con_opt([{gen_packet,N,O,C}|Opts],R,As) -> + con_opt([{gen_packet,{N,O,C}}|Opts],R,As); con_opt([Opt | Opts], R, As) -> case Opt of {ip,IP} -> con_opt(Opts, R#connect_opts { ifaddr = IP }, As); @@ -648,7 +652,7 @@ [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, header, active, packet, buffer, mode, deliver, backlog, exit_on_close, high_watermark, low_watermark, bit8, send_timeout, - delay_send, packet_size,raw]. + delay_send, packet_size,raw, gen_packet]. listen_options(Opts, Family) -> BaseOpts = @@ -673,6 +677,8 @@ list_opt([{raw,A,B,C}|Opts], R, As) -> list_opt([{raw,{A,B,C}}|Opts], R, As); +list_opt([{gen_packet,N,O,C}|Opts], R, As) -> + list_opt([{gen_packet,{N,O,C}}|Opts], R, As); list_opt([Opt | Opts], R, As) -> case Opt of {ip,IP} -> list_opt(Opts, R#listen_opts { ifaddr = IP }, As); diff -u -r otp_src_R12B-0-untouched/lib/kernel/src/inet_int.hrl otp_src_R12B-0/lib/kernel/src/inet_int.hrl --- otp_src_R12B-0-untouched/lib/kernel/src/inet_int.hrl 2007-11-26 18:56:56.000000000 +0000 +++ otp_src_R12B-0/lib/kernel/src/inet_int.hrl 2008-02-09 14:39:46.000000000 +0000 @@ -133,6 +133,7 @@ -define(INET_LOPT_PACKET_SIZE, 32). -define(INET_LOPT_READ_PACKETS, 33). -define(INET_OPT_RAW, 34). +-define(INET_LOPT_GEN_PACKET, 35). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff -u -r otp_src_R12B-0-untouched/lib/kernel/src/prim_inet.erl otp_src_R12B-0/lib/kernel/src/prim_inet.erl --- otp_src_R12B-0-untouched/lib/kernel/src/prim_inet.erl 2007-11-30 14:10:12.000000000 +0000 +++ otp_src_R12B-0/lib/kernel/src/prim_inet.erl 2008-02-09 14:39:46.000000000 +0000 @@ -962,6 +962,7 @@ enc_opt(packet_size) -> ?INET_LOPT_PACKET_SIZE; enc_opt(read_packets) -> ?INET_LOPT_READ_PACKETS; enc_opt(raw) -> ?INET_OPT_RAW; +enc_opt(gen_packet) -> ?INET_LOPT_GEN_PACKET; % Names of SCTP opts: enc_opt(sctp_rtoinfo) -> ?SCTP_OPT_RTOINFO; enc_opt(sctp_associnfo) -> ?SCTP_OPT_ASSOCINFO; @@ -1015,6 +1016,7 @@ dec_opt(?INET_LOPT_PACKET_SIZE) -> packet_size; dec_opt(?INET_LOPT_READ_PACKETS) -> read_packets; dec_opt(?INET_OPT_RAW) -> raw; +dec_opt(?INET_LOPT_GEN_PACKET) -> gen_packet; dec_opt(I) when is_integer(I) -> undefined. @@ -1108,6 +1110,7 @@ type_opt_1(delay_send) -> bool; type_opt_1(packet_size) -> uint; type_opt_1(read_packets) -> uint; +type_opt_1(gen_packet) -> {uint, uint, int}; %% %% SCTP options (to be set). If the type is a record type, the corresponding %% record signature is returned, otherwise, an "elementary" type tag @@ -1513,6 +1516,8 @@ enc_opt_val([{raw,P,O,B}|Opts], Acc) -> enc_opt_val(Opts, Acc, raw, {P,O,B}); +enc_opt_val([{gen_packet,SizeLen,SizeOfs,SizeDelta}|Opts], Acc) -> + enc_opt_val(Opts, Acc, gen_packet, {SizeLen,SizeOfs,SizeDelta}); enc_opt_val([{Opt,Val}|Opts], Acc) -> enc_opt_val(Opts, Acc, Opt, Val); enc_opt_val([binary|Opts], Acc) ->