1
/* ``The contents of this file are subject to the Erlang Public License,
4
* Copyright Ericsson AB 2001-2009. All Rights Reserved.
6
* The contents of this file are subject to the Erlang Public License,
2
7
* Version 1.1, (the "License"); you may not use this file except in
3
8
* compliance with the License. You should have received a copy of the
4
9
* Erlang Public License along with this software. If not, it can be
5
* retrieved via the world wide web at http://www.erlang.org/.
10
* retrieved online at http://www.erlang.org/.
7
12
* Software distributed under the License is distributed on an "AS IS"
8
13
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
14
* the License for the specific language governing rights and limitations
10
15
* under the License.
12
* The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
* Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
* AB. All Rights Reserved.''
19
20
#ifdef HAVE_CONFIG_H
888
/* ------------ decode_packet() and friends: */
893
890
struct packet_callback_args
895
892
Process* p; /* In */
896
893
Eterm res; /* Out */
894
int string_as_bin; /* return strings as binaries (http_bin): */
902
http_bld_string(struct packet_callback_args* pca, Uint **hpp, Uint *szp,
903
const char *str, Sint len)
905
Eterm res = THE_NON_VALUE;
908
if (pca->string_as_bin) {
909
size = heap_bin_size(len);
912
*szp += (size > ERL_SUB_BIN_SIZE) ? ERL_SUB_BIN_SIZE : size;
915
res = make_binary(*hpp);
916
if (size > ERL_SUB_BIN_SIZE) {
917
ErlSubBin* bin = (ErlSubBin*) *hpp;
918
bin->thing_word = HEADER_SUB_BIN;
920
bin->offs = pca->bin_offs + ((byte*)str - pca->aligned_ptr);
921
bin->orig = pca->orig;
922
bin->bitoffs = pca->bin_bitoffs;
924
bin->is_writable = 0;
925
*hpp += ERL_SUB_BIN_SIZE;
928
ErlHeapBin* bin = (ErlHeapBin*) *hpp;
929
bin->thing_word = header_heap_bin(len);
931
memcpy(bin->data, str, len);
937
res = erts_bld_string_n(hpp, szp, str, len);
899
942
static int http_response_erl(void *arg, int major, int minor,
900
943
int status, const char* phrase, int phrase_len)
902
945
/* {http_response,{Major,Minor},Status,"Phrase"} */
903
946
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);
947
Eterm phrase_term, ver;
908
Eterm* hend = hp + hsize;
911
list = erts_bld_string_n(&hp, NULL, phrase, phrase_len);
954
http_bld_string(pca, NULL, &hsize, phrase, phrase_len);
955
hp = HAlloc(pca->p, hsize);
959
phrase_term = http_bld_string(pca, &hp, NULL, phrase, phrase_len);
912
960
ver = TUPLE2(hp, make_small(major), make_small(minor));
914
pca->res = TUPLE4(hp, am_http_response, ver, make_small(status), list);
962
pca->res = TUPLE4(hp, am_http_response, ver, make_small(status), phrase_term);
915
963
ASSERT(hp+5==hend);
919
static Eterm http_bld_uri(Eterm** hpp, Uint* szp, const PacketHttpURI* uri)
967
static Eterm http_bld_uri(struct packet_callback_args* pca,
968
Eterm** hpp, Uint* szp, const PacketHttpURI* uri)
922
971
if (uri->type == URI_STAR) {
923
972
return am_Times; /* '*' */
926
s1 = erts_bld_string_n(hpp, szp, uri->s1_ptr, uri->s1_len);
975
s1 = http_bld_string(pca, hpp, szp, uri->s1_ptr, uri->s1_len);
928
977
switch (uri->type) {
929
978
case URI_ABS_PATH:
930
979
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);
982
s2 = http_bld_string(pca, hpp, szp, uri->s2_ptr, uri->s2_len);
934
983
return erts_bld_tuple
935
984
(hpp, szp, 5, am_absoluteURI,
936
985
((uri->type==URI_HTTP) ? am_http : am_https),
966
1015
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);
1016
http_bld_string(pca, hpp, szp, meth_ptr, meth_len);
1017
uri_term = http_bld_uri(pca, hpp, szp, uri);
969
1018
ver_term = erts_bld_tuple(hpp, szp, 2,
970
1019
make_small(major), make_small(minor));
971
1020
pca->res = erts_bld_tuple(hpp, szp, 4, am_http_request, meth_term,
985
1034
struct packet_callback_args* pca = (struct packet_callback_args*) arg;
986
1035
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
1042
/* {http_header,Bit,Name,IValue,Value} */
1045
http_bld_string(pca, NULL, &sz, name_ptr, name_len);
1047
http_bld_string(pca, NULL, &sz, value_ptr, value_len);
1049
hp = HAlloc(pca->p, sz);
994
1054
if (name != NULL) {
995
1055
bit_term = make_small(name->index+1);
996
1056
name_term = name->atom;
999
bit_term = make_small(0);
1000
name_term = erts_bld_string_n(&hp,NULL,name_ptr,name_len);
1059
bit_term = make_small(0);
1060
name_term = http_bld_string(pca, &hp,NULL,name_ptr,name_len);
1003
val_term = erts_bld_string_n(&hp, NULL, value_ptr, value_len);
1063
val_term = http_bld_string(pca, &hp, NULL, value_ptr, value_len);
1004
1064
pca->res = TUPLE5(hp, am_http_header, bit_term, name_term, am_undefined, val_term);
1005
1065
ASSERT(hp+6==hend);
1019
1079
/* {http_error,Line} */
1020
1080
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);
1087
http_bld_string(pca, NULL, &sz, buf, len);
1089
hp = HAlloc(pca->p, sz);
1093
pca->res = erts_bld_tuple(&hp, NULL, 2, am_http_error,
1094
http_bld_string(pca, &hp, NULL, buf, len));
1030
1095
ASSERT(hp==hend);
1077
1142
unsigned trunc_len = 0; /* Truncate lines if longer, 0=no limit */
1078
1143
int http_state = 0; /* 0=request/response 1=header */
1079
1144
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 */
1145
byte* bin_ptr; /*| orig: original binary */
1146
byte bin_bitsz; /*| bin: BIF_ARG_2, may be sub-binary of orig */
1147
Uint bin_sz; /*| packet: prefix of bin */
1148
char* body_ptr; /*| body: part of packet to return */
1149
int body_sz; /*| rest: bin without packet */
1089
1150
struct packet_callback_args pca;
1090
1151
enum PacketParseType type;
1146
1208
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);
1209
ERTS_GET_BINARY_BYTES(BIF_ARG_2, bin_ptr, pca.bin_bitoffs, bin_bitsz);
1210
if (pca.bin_bitoffs != 0) {
1211
pca.aligned_ptr = erts_alloc(ERTS_ALC_T_TMP, bin_sz);
1212
erts_copy_bits(bin_ptr, pca.bin_bitoffs, 1, pca.aligned_ptr, 0, 1, bin_sz*8);
1153
aligned_ptr = bin_ptr;
1215
pca.aligned_ptr = bin_ptr;
1155
packet_sz = packet_get_length(type, (char*)aligned_ptr, bin_sz,
1217
packet_sz = packet_get_length(type, (char*)pca.aligned_ptr, bin_sz,
1156
1218
max_plen, trunc_len, &http_state);
1157
1219
if (!(packet_sz > 0 && packet_sz <= bin_sz)) {
1158
1220
if (packet_sz < 0) {
1169
1231
/* We got a whole packet */
1171
body_ptr = (char*) aligned_ptr;
1233
body_ptr = (char*) pca.aligned_ptr;
1172
1234
body_sz = packet_sz;
1173
1235
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);
1237
ERTS_GET_REAL_BIN(BIF_ARG_2, pca.orig, pca.bin_offs, pca.bin_bitoffs, bin_bitsz);
1177
1239
pca.res = THE_NON_VALUE;
1178
code = packet_parse(type, (char*)aligned_ptr, packet_sz, &http_state,
1240
pca.string_as_bin = (type == TCP_PB_HTTP_BIN || type == TCP_PB_HTTPH_BIN);
1241
code = packet_parse(type, (char*)pca.aligned_ptr, packet_sz, &http_state,
1179
1242
&packet_callbacks_erl, &pca);
1180
1243
if (code == 0) { /* no special packet parsing, make plain binary */
1181
1244
ErlSubBin* body;