884
888
erts_free(ERTS_ALC_T_TMP, temp_heap);
893
struct packet_callback_args
899
static int http_response_erl(void *arg, int major, int minor,
900
int status, const char* phrase, int phrase_len)
902
/* {http_response,{Major,Minor},Status,"Phrase"} */
903
struct packet_callback_args* pca = (struct packet_callback_args*) arg;
905
unsigned hsize = phrase_len*2 + 3 + 5;
906
Eterm* hp = HAlloc(pca->p, hsize);
908
Eterm* hend = hp + hsize;
911
list = erts_bld_string_n(&hp, NULL, phrase, phrase_len);
912
ver = TUPLE2(hp, make_small(major), make_small(minor));
914
pca->res = TUPLE4(hp, am_http_response, ver, make_small(status), list);
919
static Eterm http_bld_uri(Eterm** hpp, Uint* szp, const PacketHttpURI* uri)
922
if (uri->type == URI_STAR) {
923
return am_Times; /* '*' */
926
s1 = erts_bld_string_n(hpp, szp, uri->s1_ptr, uri->s1_len);
930
return erts_bld_tuple(hpp, szp, 2, am_abs_path, s1);
933
s2 = erts_bld_string_n(hpp, szp, uri->s2_ptr, uri->s2_len);
934
return erts_bld_tuple
935
(hpp, szp, 5, am_absoluteURI,
936
((uri->type==URI_HTTP) ? am_http : am_https),
938
((uri->port==0) ? am_undefined : make_small(uri->port)),
944
s2 = erts_bld_string_n(hpp, szp, uri->s2_ptr, uri->s2_len);
945
return erts_bld_tuple(hpp, szp, 3, am_scheme, s1, s2);
948
erl_exit(1, "%s, line %d: type=%u\n", __FILE__, __LINE__, uri->type);
952
static int http_request_erl(void* arg, const http_atom_t* meth,
953
const char* meth_ptr, int meth_len,
954
const PacketHttpURI* uri, int major, int minor)
956
struct packet_callback_args* pca = (struct packet_callback_args*) arg;
957
Eterm meth_term, uri_term, ver_term;
963
/* {http_request,Meth,Uri,Version} */
966
meth_term = (meth!=NULL) ? meth->atom :
967
erts_bld_string_n(hpp, szp, meth_ptr, meth_len);
968
uri_term = http_bld_uri(hpp, szp, uri);
969
ver_term = erts_bld_tuple(hpp, szp, 2,
970
make_small(major), make_small(minor));
971
pca->res = erts_bld_tuple(hpp, szp, 4, am_http_request, meth_term,
973
if (hpp != NULL) break;
975
hp = HAlloc(pca->p, sz);
982
http_header_erl(void* arg, const http_atom_t* name, const char* name_ptr,
983
int name_len, const char* value_ptr, int value_len)
985
struct packet_callback_args* pca = (struct packet_callback_args*) arg;
986
Eterm bit_term, name_term, val_term;
987
Uint sz = value_len*2 + 6 + (name ? 0 : name_len*2);
988
Eterm* hp = HAlloc(pca->p,sz);
990
Eterm* hend = hp + sz;
993
/* {http_header,Bit,Name,IValue,Value} */
995
bit_term = make_small(name->index+1);
996
name_term = name->atom;
999
bit_term = make_small(0);
1000
name_term = erts_bld_string_n(&hp,NULL,name_ptr,name_len);
1003
val_term = erts_bld_string_n(&hp, NULL, value_ptr, value_len);
1004
pca->res = TUPLE5(hp, am_http_header, bit_term, name_term, am_undefined, val_term);
1009
static int http_eoh_erl(void* arg)
1012
struct packet_callback_args* pca = (struct packet_callback_args*) arg;
1013
pca->res = am_http_eoh;
1017
static int http_error_erl(void* arg, const char* buf, int len)
1019
/* {http_error,Line} */
1020
struct packet_callback_args* pca = (struct packet_callback_args*) arg;
1021
unsigned hsize = len*2 + 3;
1022
Eterm* hp = HAlloc(pca->p, hsize);
1024
Eterm* hend = hp + hsize;
1028
line = erts_bld_string_n(&hp,NULL,buf,len);
1029
pca->res = erts_bld_tuple(&hp,NULL,2,am_http_error,line);
1035
int ssl_tls_erl(void* arg, unsigned type, unsigned major, unsigned minor,
1036
const char* buf, int len, const char* prefix, int plen)
1038
struct packet_callback_args* pca = (struct packet_callback_args*) arg;
1041
Eterm bin = new_binary(pca->p, NULL, plen+len);
1042
byte* bin_ptr = binary_bytes(bin);
1044
memcpy(bin_ptr+plen, buf, len);
1046
memcpy(bin_ptr, prefix, plen);
1049
/* {ssl_tls,NIL,ContentType,{Major,Minor},Bin} */
1050
hp = HAlloc(pca->p, 3+6);
1051
ver = TUPLE2(hp, make_small(major), make_small(minor));
1053
pca->res = TUPLE5(hp, am_ssl_tls, NIL, make_small(type), ver, bin);
1058
PacketCallbacks packet_callbacks_erl = {
1068
decode_packet(Type,Bin,Options)
1070
{ok, PacketBodyBin, RestBin}
1071
{more, PacketSz | undefined}
1074
BIF_RETTYPE decode_packet_3(BIF_ALIST_3)
1076
unsigned max_plen = 0; /* Packet max length, 0=no limit */
1077
unsigned trunc_len = 0; /* Truncate lines if longer, 0=no limit */
1078
int http_state = 0; /* 0=request/response 1=header */
1079
int packet_sz; /*-------Binaries involved: ------------------*/
1080
Eterm orig; /*| orig: original binary */
1081
Uint bin_offs; /*| bin: BIF_ARG_2, may be sub-binary of orig */
1082
byte* bin_ptr; /*| packet: prefix of bin */
1083
byte bin_bitoffs; /*| body: part of packet to return */
1084
byte bin_bitsz; /*| rest: bin without packet */
1088
byte* aligned_ptr; /* bin_ptr or byte aligned temp copy */
1089
struct packet_callback_args pca;
1090
enum PacketParseType type;
1098
if (!is_binary(BIF_ARG_2) ||
1099
(!is_list(BIF_ARG_3) && !is_nil(BIF_ARG_3))) {
1100
BIF_ERROR(BIF_P, BADARG);
1103
switch (BIF_ARG_1) {
1104
case make_small(0): case am_raw: type = TCP_PB_RAW; break;
1105
case make_small(1): type = TCP_PB_1; break;
1106
case make_small(2): type = TCP_PB_2; break;
1107
case make_small(4): type = TCP_PB_4; break;
1108
case am_asn1: type = TCP_PB_ASN1; break;
1109
case am_sunrm: type = TCP_PB_RM; break;
1110
case am_cdr: type = TCP_PB_CDR; break;
1111
case am_fcgi: type = TCP_PB_FCGI; break;
1112
case am_line: type = TCP_PB_LINE_LF; break;
1113
case am_tpkt: type = TCP_PB_TPKT; break;
1114
case am_http: type = TCP_PB_HTTP; break;
1115
case am_httph: type = TCP_PB_HTTPH; break;
1116
case am_ssl_tls: type = TCP_PB_SSL_TLS; break;
1118
BIF_ERROR(BIF_P, BADARG);
1121
options = BIF_ARG_3;
1122
while (!is_nil(options)) {
1123
Eterm* cons = list_val(options);
1124
if (is_tuple(CAR(cons))) {
1125
Eterm* tpl = tuple_val(CAR(cons));
1127
if (tpl[0] == make_arityval(2) &&
1128
term_to_Uint(tpl[2],&val) && val <= UINT_MAX) {
1130
case am_packet_size:
1133
case am_line_length:
1139
BIF_ERROR(BIF_P, BADARG);
1142
options = CDR(cons);
1146
bin_sz = binary_size(BIF_ARG_2);
1147
ERTS_GET_BINARY_BYTES(BIF_ARG_2, bin_ptr, bin_bitoffs, bin_bitsz);
1148
if (bin_bitoffs != 0) {
1149
aligned_ptr = erts_alloc(ERTS_ALC_T_TMP, bin_sz);
1150
erts_copy_bits(bin_ptr, bin_bitoffs, 1, aligned_ptr, 0, 1, bin_sz*8);
1153
aligned_ptr = bin_ptr;
1155
packet_sz = packet_get_length(type, (char*)aligned_ptr, bin_sz,
1156
max_plen, trunc_len, &http_state);
1157
if (!(packet_sz > 0 && packet_sz <= bin_sz)) {
1158
if (packet_sz < 0) {
1161
else { /* not enough data */
1162
Eterm plen = (packet_sz==0) ? am_undefined :
1163
erts_make_integer(packet_sz, BIF_P);
1164
Eterm* hp = HAlloc(BIF_P,3);
1165
res = TUPLE2(hp, am_more, plen);
1169
/* We got a whole packet */
1171
body_ptr = (char*) aligned_ptr;
1172
body_sz = packet_sz;
1173
packet_get_body(type, (const char**) &body_ptr, &body_sz);
1175
ERTS_GET_REAL_BIN(BIF_ARG_2, orig, bin_offs, bin_bitoffs, bin_bitsz);
1177
pca.res = THE_NON_VALUE;
1178
code = packet_parse(type, (char*)aligned_ptr, packet_sz, &http_state,
1179
&packet_callbacks_erl, &pca);
1180
if (code == 0) { /* no special packet parsing, make plain binary */
1182
Uint hsz = 2*ERL_SUB_BIN_SIZE + 4;
1183
hp = HAlloc(BIF_P, hsz);
1186
body = (ErlSubBin *) hp;
1187
body->thing_word = HEADER_SUB_BIN;
1188
body->size = body_sz;
1189
body->offs = bin_offs + (body_ptr - (char*)aligned_ptr);
1191
body->bitoffs = bin_bitoffs;
1193
body->is_writable = 0;
1194
hp += ERL_SUB_BIN_SIZE;
1195
pca.res = make_binary(body);
1197
else if (code > 0) {
1198
Uint hsz = ERL_SUB_BIN_SIZE + 4;
1199
ASSERT(pca.res != THE_NON_VALUE);
1200
hp = HAlloc(BIF_P, hsz);
1205
hp = HAlloc(BIF_P,3);
1206
res = TUPLE2(hp, am_error, am_invalid);
1210
rest = (ErlSubBin *) hp;
1211
rest->thing_word = HEADER_SUB_BIN;
1212
rest->size = bin_sz - packet_sz;
1213
rest->offs = bin_offs + packet_sz;
1215
rest->bitoffs = bin_bitoffs;
1216
rest->bitsize = bin_bitsz; /* The extra bits go into the rest. */
1217
rest->is_writable = 0;
1218
hp += ERL_SUB_BIN_SIZE;
1219
res = TUPLE3(hp, am_ok, pca.res, make_binary(rest));
1221
ASSERT(hp==hend); (void)hend;
1224
if (aligned_ptr != bin_ptr) {
1225
erts_free(ERTS_ALC_T_TMP, aligned_ptr);