Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 114 additions & 31 deletions erts/emulator/beam/erl_bif_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,8 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)

/* These are the defaults */
opts.packet_bytes = 0;
opts.packet_header_endianness =
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_BIG;
opts.use_stdio = 1;
opts.redir_stderr = 0;
opts.read_write = 0;
Expand Down Expand Up @@ -847,18 +849,49 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
arity = *tp++;
option = *tp++;
if (option == am_packet) {
if (is_not_small(*tp)) {
goto bad_settings;
}
opts.packet_bytes = signed_val(*tp);
switch (opts.packet_bytes) {
case 1:
case 2:
case 4:
break;
default:
goto bad_settings;
}
if (is_tuple_arity(*tp, 2)) {
Eterm *packet = tuple_val(*tp);
Sint packet_bytes;

if (is_not_small(packet[1]))
goto bad_settings;

packet_bytes = signed_val(packet[1]);
if (packet_bytes < 2 || packet_bytes > 4)
goto bad_settings;
opts.packet_bytes = (int) packet_bytes;

if (packet[2] == am_big) {
opts.packet_header_endianness =
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_BIG;
} else if (packet[2] == am_little) {
opts.packet_header_endianness =
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_LITTLE;
} else if (packet[2] == am_native) {
#if defined(WORDS_BIGENDIAN)
opts.packet_header_endianness =
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_BIG;
#else
opts.packet_header_endianness =
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_LITTLE;
#endif
} else {
goto bad_settings;
}
} else {
Sint packet_bytes;

if (is_not_small(*tp))
goto bad_settings;

packet_bytes = signed_val(*tp);
if (packet_bytes < 1 || packet_bytes > 4)
goto bad_settings;
opts.packet_bytes = (int) packet_bytes;

opts.packet_header_endianness =
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_BIG;
}
} else if (option == am_line) {
if (is_not_small(*tp)) {
goto bad_settings;
Expand Down Expand Up @@ -978,6 +1011,8 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
}
} else if (*nargs == am_stream) {
opts.packet_bytes = 0;
opts.packet_header_endianness =
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_BIG;
} else if (*nargs == am_use_stdio) {
opts.use_stdio = 1;
} else if (*nargs == am_stderr_to_stdout) {
Expand Down Expand Up @@ -1489,25 +1524,73 @@ BIF_RETTYPE decode_packet_3(BIF_ALIST_3)
int code;
char delimiter = '\n';

switch (BIF_ARG_1) {
case make_small(0): case am_raw: type = TCP_PB_RAW; break;
case make_small(1): type = TCP_PB_1; break;
case make_small(2): type = TCP_PB_2; break;
case make_small(4): type = TCP_PB_4; break;
case am_asn1: type = TCP_PB_ASN1; break;
case am_sunrm: type = TCP_PB_RM; break;
case am_cdr: type = TCP_PB_CDR; break;
case am_fcgi: type = TCP_PB_FCGI; break;
case am_line: type = TCP_PB_LINE_LF; break;
case am_tpkt: type = TCP_PB_TPKT; break;
case am_http: type = TCP_PB_HTTP; break;
case am_httph: type = TCP_PB_HTTPH; break;
case am_http_bin: type = TCP_PB_HTTP_BIN; break;
case am_httph_bin: type = TCP_PB_HTTPH_BIN; break;
case am_ssl_tls: type = TCP_PB_SSL_TLS; break;
default:
BIF_P->fvalue = am_badopt;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
if (is_tuple_arity(BIF_ARG_1, 2)) {
Eterm *packet;
Sint packet_bytes;

packet = tuple_val(BIF_ARG_1);
if (is_not_small(packet[1])) {
BIF_P->fvalue = am_badopt;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}

packet_bytes = signed_val(packet[1]);
if (packet_bytes < 2 || packet_bytes > 4) {
BIF_P->fvalue = am_badopt;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}

switch (packet[2]) {
#if defined(WORDS_BIGENDIAN)
case am_native:
#endif
case am_big:
switch (packet_bytes) {
case 2: type = TCP_PB_2_BIG; break;
case 3: type = TCP_PB_3_BIG; break;
case 4: type = TCP_PB_4_BIG; break;
default:
ERTS_UNREACHABLE;
}
break;
#if !defined(WORDS_BIGENDIAN)
case am_native:
#endif
case am_little:
switch (packet_bytes) {
case 2: type = TCP_PB_2_LITTLE; break;
case 3: type = TCP_PB_3_LITTLE; break;
case 4: type = TCP_PB_4_LITTLE; break;
default:
ERTS_UNREACHABLE;
}
break;
default:
BIF_P->fvalue = am_badopt;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}
} else {
switch (BIF_ARG_1) {
case make_small(0): case am_raw: type = TCP_PB_RAW; break;
case make_small(1): type = TCP_PB_1; break;
case make_small(2): type = TCP_PB_2_BIG; break;
case make_small(3): type = TCP_PB_3_BIG; break;
case make_small(4): type = TCP_PB_4_BIG; break;
case am_asn1: type = TCP_PB_ASN1; break;
case am_sunrm: type = TCP_PB_RM; break;
case am_cdr: type = TCP_PB_CDR; break;
case am_fcgi: type = TCP_PB_FCGI; break;
case am_line: type = TCP_PB_LINE_LF; break;
case am_tpkt: type = TCP_PB_TPKT; break;
case am_http: type = TCP_PB_HTTP; break;
case am_httph: type = TCP_PB_HTTPH; break;
case am_http_bin: type = TCP_PB_HTTP_BIN; break;
case am_httph_bin: type = TCP_PB_HTTPH_BIN; break;
case am_ssl_tls: type = TCP_PB_SSL_TLS; break;
default:
BIF_P->fvalue = am_badopt;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}
}

if (!is_bitstring(BIF_ARG_2) ||
Expand Down
10 changes: 6 additions & 4 deletions erts/emulator/beam/erl_sys_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ typedef SWord ErlDrvEvent; /* An event to be selected on. */

typedef struct _SysDriverOpts SysDriverOpts;

typedef enum {
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_BIG = 0,
ERTS_SYS_DRIVER_PACKET_HEADER_ENDIAN_LITTLE
} ErtsSysDriverPacketHeaderEndianness;

#include "erl_driver.h"

/*
Expand All @@ -48,6 +53,7 @@ struct _SysDriverOpts {
Uint ifd; /* Input file descriptor (fd driver). */
Uint ofd; /* Outputfile descriptor (fd driver). */
int packet_bytes; /* Number of bytes in packet header. */
ErtsSysDriverPacketHeaderEndianness packet_header_endianness;
int read_write; /* Read and write bits. */
int use_stdio; /* Use standard I/O: TRUE or FALSE. */
int redir_stderr; /* Redirect stderr to stdout: TRUE/FALSE. */
Expand All @@ -69,7 +75,3 @@ struct _SysDriverOpts {
};

#endif




37 changes: 32 additions & 5 deletions erts/emulator/beam/packet_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,20 +269,48 @@ int packet_get_length(enum PacketParseType htype,
plen = get_int8(ptr);
goto remain;

case TCP_PB_2:
/* TCP_PB_2: [L1,L0 | Data] */
case TCP_PB_2_BIG:
/* TCP_PB_2_BIG: [L1,L0 | Data] */
hlen = 2;
if (n < hlen) goto more;
plen = get_int16(ptr);
goto remain;

case TCP_PB_4:
/* TCP_PB_4: [L3,L2,L1,L0 | Data] */
case TCP_PB_2_LITTLE:
/* TCP_PB_2_LITTLE: [L0,L1 | Data] */
hlen = 2;
if (n < hlen) goto more;
plen = get_little_int16(ptr);
goto remain;

case TCP_PB_3_BIG:
/* TCP_PB_3_BIG: [L2,L1,L0 | Data] */
hlen = 3;
if (n < hlen) goto more;
plen = get_int24(ptr);
goto remain;

case TCP_PB_3_LITTLE:
/* TCP_PB_3_LITTLE: [L0,L1,L2 | Data] */
hlen = 3;
if (n < hlen) goto more;
plen = get_little_int24(ptr);
goto remain;

case TCP_PB_4_BIG:
/* TCP_PB_4_BIG: [L3,L2,L1,L0 | Data] */
hlen = 4;
if (n < hlen) goto more;
plen = get_int32(ptr);
goto remain;

case TCP_PB_4_LITTLE:
/* TCP_PB_4_LITTLE: [L0,L1,L2,L3 | Data] */
hlen = 4;
if (n < hlen) goto more;
plen = get_little_uint32(ptr);
goto remain;

case TCP_PB_RM:
/* TCP_PB_RM: [L3,L2,L1,L0 | Data]
** where MSB (bit) is used to signal end of record
Expand Down Expand Up @@ -882,4 +910,3 @@ int packet_parse_ssl(const char* buf, int len,
return pcb->ssl_tls(arg, type, major, minor, buf+5, len-5, NULL, 0);
}
}

20 changes: 13 additions & 7 deletions erts/emulator/beam/packet_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@
#include "sys.h"


/* INET_LOPT_PACKET options */
enum PacketParseType {
TCP_PB_RAW = 0,
TCP_PB_1 = 1,
TCP_PB_2 = 2,
TCP_PB_4 = 3,
TCP_PB_2_BIG = 2,
TCP_PB_4_BIG = 3,
TCP_PB_ASN1 = 4,
TCP_PB_RM = 5,
TCP_PB_CDR = 6,
Expand All @@ -46,7 +45,11 @@ enum PacketParseType {
TCP_PB_HTTPH = 11,
TCP_PB_SSL_TLS = 12,
TCP_PB_HTTP_BIN = 13,
TCP_PB_HTTPH_BIN = 14
TCP_PB_HTTPH_BIN = 14,
TCP_PB_2_LITTLE = 15,
TCP_PB_3_BIG = 16,
TCP_PB_3_LITTLE = 17,
TCP_PB_4_LITTLE = 18
};

typedef struct http_atom {
Expand Down Expand Up @@ -153,8 +156,12 @@ void packet_get_body(enum PacketParseType htype, const char** bufp, int* lenp)
{
switch (htype) {
case TCP_PB_1: *bufp += 1; *lenp -= 1; break;
case TCP_PB_2: *bufp += 2; *lenp -= 2; break;
case TCP_PB_4: *bufp += 4; *lenp -= 4; break;
case TCP_PB_2_BIG: *bufp += 2; *lenp -= 2; break;
case TCP_PB_2_LITTLE: *bufp += 2; *lenp -= 2; break;
case TCP_PB_3_BIG: *bufp += 3; *lenp -= 3; break;
case TCP_PB_3_LITTLE: *bufp += 3; *lenp -= 3; break;
case TCP_PB_4_BIG: *bufp += 4; *lenp -= 4; break;
case TCP_PB_4_LITTLE: *bufp += 4; *lenp -= 4; break;
case TCP_PB_FCGI:
*lenp -= ((struct fcgi_head*)*bufp)->paddingLength;
break;
Expand Down Expand Up @@ -184,4 +191,3 @@ int packet_parse(enum PacketParseType htype, const char* buf, int len,
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */

#endif /* !__PACKET_PARSER_H__ */

26 changes: 25 additions & 1 deletion erts/emulator/beam/sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,15 @@ ERTS_GLB_INLINE size_t sys_strlen(const char *s)
(((byte*) (s))[1] << 8) | \
(((byte*) (s))[0]))

#define get_uint32(s) ((Uint32)get_int32(s))
#define get_uint32(s) ((((Uint32)((byte*) (s))[0]) << 24) | \
(((Uint32)((byte*) (s))[1]) << 16) | \
(((Uint32)((byte*) (s))[2]) << 8) | \
(((Uint32)((byte*) (s))[3])))

#define get_little_uint32(s) ((((Uint32)((byte*) (s))[3]) << 24) | \
(((Uint32)((byte*) (s))[2]) << 16) | \
(((Uint32)((byte*) (s))[1]) << 8) | \
(((Uint32)((byte*) (s))[0])))

#define put_int32(i, s) do {((byte*)(s))[0] = (byte)((i) >> 24) & 0xff; \
((byte*)(s))[1] = (byte)((i) >> 16) & 0xff; \
Expand All @@ -1301,20 +1309,36 @@ ERTS_GLB_INLINE size_t sys_strlen(const char *s)
(((byte*) (s))[1] << 8) | \
(((byte*) (s))[2]))

#define get_little_int24(s) ((((byte*) (s))[2] << 16) | \
(((byte*) (s))[1] << 8) | \
(((byte*) (s))[0]))


#define put_int24(i, s) do {((byte*)(s))[0] = (byte)((i) >> 16) & 0xff; \
((byte*)(s))[1] = (byte)((i) >> 8) & 0xff; \
((byte*)(s))[2] = (byte)(i) & 0xff;} \
while (0)

#define put_little_int24(i, s) do {((byte*)(s))[2] = (byte)((i) >> 16) & 0xff; \
((byte*)(s))[1] = (byte)((i) >> 8) & 0xff; \
((byte*)(s))[0] = (byte)(i) & 0xff;} \
while (0)

#define get_int16(s) ((((byte*) (s))[0] << 8) | \
(((byte*) (s))[1]))

#define get_little_int16(s) ((((byte*) (s))[1] << 8) | \
(((byte*) (s))[0]))


#define put_int16(i, s) do {((byte*)(s))[0] = (byte)((i) >> 8) & 0xff; \
((byte*)(s))[1] = (byte)(i) & 0xff;} \
while (0)

#define put_little_int16(i, s) do {((byte*)(s))[1] = (byte)((i) >> 8) & 0xff; \
((byte*)(s))[0] = (byte)(i) & 0xff;} \
while (0)

#define get_int8(s) ((((byte*) (s))[0] ))


Expand Down
Loading