static ERL_NIF_TERM nif_pcap_stats(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { EWPCAP_STATE *ep = NULL; struct pcap_stat ps = {0}; if (!enif_get_resource(env, argv[0], EWPCAP_RESOURCE, (void **)&ep) || ep->p == NULL) return enif_make_badarg(env); if (pcap_stats(ep->p, &ps)) return enif_make_tuple2(env, atom_error, enif_make_string(env, pcap_geterr(ep->p), ERL_NIF_LATIN1)); return enif_make_tuple2(env, atom_ok, enif_make_tuple5(env, atom_ewpcap_stat, enif_make_uint(env, ps.ps_recv), enif_make_uint(env, ps.ps_drop), enif_make_uint(env, ps.ps_ifdrop), #ifdef WIN32 enif_make_uint(env, ps.bs_capt) #else enif_make_uint(env, 0) #endif )); }
static ERL_NIF_TERM macros(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const ERL_NIF_TERM* a; ERL_NIF_TERM lists, tuples; int arity; if (!enif_get_tuple(env, argv[0], &arity, &a) || arity != 9) { return enif_make_badarg(env); } lists = enif_make_list(env,9, enif_make_list1(env,a[0]), enif_make_list2(env,a[0],a[1]), enif_make_list3(env,a[0],a[1],a[2]), enif_make_list4(env,a[0],a[1],a[2],a[3]), enif_make_list5(env,a[0],a[1],a[2],a[3],a[4]), enif_make_list6(env,a[0],a[1],a[2],a[3],a[4],a[5]), enif_make_list7(env,a[0],a[1],a[2],a[3],a[4],a[5],a[6]), enif_make_list8(env,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]), enif_make_list9(env,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])); tuples = enif_make_list(env,9, enif_make_tuple1(env,a[0]), enif_make_tuple2(env,a[0],a[1]), enif_make_tuple3(env,a[0],a[1],a[2]), enif_make_tuple4(env,a[0],a[1],a[2],a[3]), enif_make_tuple5(env,a[0],a[1],a[2],a[3],a[4]), enif_make_tuple6(env,a[0],a[1],a[2],a[3],a[4],a[5]), enif_make_tuple7(env,a[0],a[1],a[2],a[3],a[4],a[5],a[6]), enif_make_tuple8(env,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]), enif_make_tuple9(env,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])); return enif_make_tuple2(env,lists,tuples); }
static ERL_NIF_TERM make_strings(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { const char a0string[8] = {'a','0','s','t','r','i','n','g'}; const char a0string0[9] = {'a','\0','s','t','r','i','n','g',0}; const char astringwith8bits[37] = {'E','r','l','a','n','g',' ',0xE4 /* 'ä' */,'r',' ','e','t','t',' ','g','e','n','e','r','e','l','l','t',' ','p','r','o','g','r','a','m','s','p','r', 0xE5 /* 'å' */,'k',0}; return enif_make_tuple5(env, enif_make_string(env, "a0string", ERL_NIF_LATIN1), enif_make_string_len(env, "a0string", 8, ERL_NIF_LATIN1), enif_make_string_len(env, a0string, 8, ERL_NIF_LATIN1), enif_make_string_len(env, a0string0, 9, ERL_NIF_LATIN1), enif_make_string(env, astringwith8bits, ERL_NIF_LATIN1)); }
// frame_to_tuple/1 :: (frame) -> {ok, {W, H, NChannels, ImageSize, ImageData}} static ERL_NIF_TERM frame_to_tuple(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM result; frame_t* frame; if (!enif_get_resource(env, argv[0], frame_res, (void**) &frame)) { return enif_make_badarg(env); } ERL_NIF_TERM* arr = (ERL_NIF_TERM*) malloc(sizeof(ERL_NIF_TERM) * frame->_frame->imageSize); int i; for (i = 0; i < frame->_frame->imageSize; i++) { arr[i] = enif_make_int(env, frame->_frame->imageData[i]); } ERL_NIF_TERM list = enif_make_list_from_array(env, arr, frame->_frame->imageSize); result = enif_make_tuple5(env, enif_make_int(env, frame->_frame->width), enif_make_int(env, frame->_frame->height), enif_make_int(env, frame->_frame->nChannels), enif_make_int(env, frame->_frame->imageSize), list); return result; }
ERL_NIF_TERM parse_buffer(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Parser par; Parser* parser = ∥ ErlNifBinary buffer; if(!enif_inspect_binary(env, argv[0], &buffer)) return enif_make_badarg(env); if(!init_parser(parser, env, argv[0], &buffer, argv[1])) return enif_make_badarg(env); ERL_NIF_TERM reply = argv[2]; ERL_NIF_TERM return_value; parser->remaining_length = buffer.size; parser->pointer = buffer.data + parser->frame_start; while (parser->frame_start < parser->buffer_size) { parser->frame_size = D3I(parser->pointer); parser->pointer += 3; unsigned long seg_num = D1(parser->pointer); parser->pointer += 1; parser->remaining_length -= (parser->frame_size + 4); if (parser->remaining_length < 0) { return_value = enif_make_tuple3(env, parser->atoms->atom_incomplete, reply, enif_make_sub_binary(env, parser->raw, parser->frame_start, parser->buffer_size - parser->frame_start)); break; } if (*parser->pointer == MYSQL_RESP_EOF) { ERL_NIF_TERM remaining_buffer = enif_make_sub_binary(env, parser->raw, parser->frame_start + parser->frame_size + 4, parser->remaining_length); if (parser->frame_size == 5) { unsigned long server_status = D2I(parser->pointer + 3); return_value = enif_make_tuple5(env, parser->atoms->atom_eof, enif_make_uint(env, server_status), enif_make_uint(env, seg_num), reply, remaining_buffer); } else return_value = enif_make_tuple4(env, parser->atoms->atom_eof, enif_make_uint(env, seg_num), reply, remaining_buffer); break; } parser->frame_start += 4; ERL_NIF_TERM row = parse_line(parser); reply = enif_make_list_cell(env, row, reply); parser->frame_start += parser->frame_size; parser->pointer += parser->frame_size; } if (parser->frame_start >= parser->buffer_size) return_value = enif_make_tuple3(env, parser->atoms->atom_incomplete, reply, parser->atoms->atom_empty); destroy_parser(parser); return return_value; }
static ERL_NIF_TERM nif_recvmsg(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; ErlNifBinary buf = {0}; ErlNifBinary src_addr = {0}; char *ctrldata = NULL; ERL_NIF_TERM ctrldatalist; int flags = 0; unsigned long bufsize = 0; unsigned long ctrlsize = 0; unsigned long sasize = 0; struct iovec iov[1]; struct msghdr message; struct cmsghdr *cmsg; ssize_t n = 0; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[1], &bufsize)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &flags)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[3], &ctrlsize)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[4], &sasize)) return enif_make_badarg(env); if (!enif_alloc_binary(bufsize, &buf)) return error_tuple(env, ENOMEM); if (ctrlsize > 0 && !(ctrldata = malloc(ctrlsize))) { enif_release_binary(&buf); return error_tuple(env, ENOMEM); } if (!enif_alloc_binary(sasize, &src_addr)) { enif_release_binary(&buf); free(ctrldata); return error_tuple(env, ENOMEM); } iov[0].iov_base = (buf.size == 0 ? NULL : buf.data); iov[0].iov_len=buf.size; message.msg_name = (src_addr.size == 0 ? NULL : src_addr.data); message.msg_namelen=src_addr.size; message.msg_iov=iov; message.msg_iovlen=1; message.msg_control=ctrldata; message.msg_controllen=ctrlsize; n = recvmsg(s, &message, flags); if (n < 0) { int err = errno; enif_release_binary(&buf); enif_release_binary(&src_addr); free(ctrldata); return error_tuple(env, err); } /* resize the binary to the actual size of the received packet * * XXX On error, the macro will return ENOMEM here, leaking buf, * XXX src_addr and ctrldata. Since the VM has OOM'ed, it will probably * XXX crash anyway. */ PROCKET_REALLOC(buf, n); PROCKET_REALLOC(src_addr, message.msg_namelen); ctrldatalist = enif_make_list(env, 0); for (cmsg = CMSG_FIRSTHDR(&message); cmsg != NULL; cmsg = CMSG_NXTHDR(&message, cmsg)) { size_t len = cmsg->cmsg_len - CMSG_LEN(0); ErlNifBinary cdata = {0}; if (!enif_alloc_binary(len, &cdata)) { enif_release_binary(&buf); enif_release_binary(&src_addr); free(ctrldata); return error_tuple(env, ENOMEM); } memcpy(cdata.data, CMSG_DATA(cmsg), len); ctrldatalist = enif_make_list_cell(env, enif_make_tuple3(env, enif_make_int(env, cmsg->cmsg_level), enif_make_int(env, cmsg->cmsg_type), enif_make_binary(env, &cdata)), ctrldatalist); } free(ctrldata); return enif_make_tuple5(env, atom_ok, enif_make_binary(env, &buf), /* Data packet */ enif_make_int(env, message.msg_flags), /* the message flags, eg. MSG_EOR, MSG_OOB, etc. */ ctrldatalist, /* array of 3-tuples of {cmsg->cmsg_level, cmsg->cmsg_type, cmsg->cmsg_data} */ enif_make_binary(env, &src_addr) /* source address, as a sockaddr_storage */ ); }
ERL_NIF_TERM decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Decoder* d; jiffy_st* st = (jiffy_st*) enif_priv_data(env); ErlNifBinary bin; ERL_NIF_TERM objs; ERL_NIF_TERM curr; ERL_NIF_TERM val = argv[2]; ERL_NIF_TERM trailer; ERL_NIF_TERM ret; size_t bytes_read = 0; if(argc != 5) { return enif_make_badarg(env); } else if(!enif_inspect_binary(env, argv[0], &bin)) { return enif_make_badarg(env); } else if(!enif_get_resource(env, argv[1], st->res_dec, (void**) &d)) { return enif_make_badarg(env); } else if(!enif_is_list(env, argv[3])) { return enif_make_badarg(env); } else if(!enif_is_list(env, argv[4])) { return enif_make_badarg(env); } dec_init(d, env, argv[0], &bin); objs = argv[3]; curr = argv[4]; while(d->i < bin.size) { if(should_yield(env, &bytes_read, d->bytes_per_red)) { return enif_make_tuple5( env, st->atom_iter, argv[1], val, objs, curr ); } bytes_read += 1; switch(dec_curr(d)) { case st_value: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case 'n': if(d->i + 3 >= d->len) { ret = dec_error(d, "invalid_literal"); goto done; } if(memcmp(&(d->p[d->i]), "null", 4) != 0) { ret = dec_error(d, "invalid_literal"); goto done; } val = d->null_term; dec_pop(d, st_value); d->i += 4; break; case 't': if(d->i + 3 >= d->len) { ret = dec_error(d, "invalid_literal"); goto done; } if(memcmp(&(d->p[d->i]), "true", 4) != 0) { ret = dec_error(d, "invalid_literal"); goto done; } val = d->atoms->atom_true; dec_pop(d, st_value); d->i += 4; break; case 'f': if(d->i + 4 >= bin.size) { ret = dec_error(d, "invalid_literal"); goto done; } if(memcmp(&(d->p[d->i]), "false", 5) != 0) { ret = dec_error(d, "invalid_literal"); goto done; } val = d->atoms->atom_false; dec_pop(d, st_value); d->i += 5; break; case '\"': if(!dec_string(d, &val)) { ret = dec_error(d, "invalid_string"); goto done; } dec_pop(d, st_value); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(!dec_number(d, &val)) { ret = dec_error(d, "invalid_number"); goto done; } dec_pop(d, st_value); break; case '{': dec_push(d, st_object); dec_push(d, st_key); objs = enif_make_list_cell(env, curr, objs); curr = enif_make_list(env, 0); d->i++; break; case '[': dec_push(d, st_array); dec_push(d, st_value); objs = enif_make_list_cell(env, curr, objs); curr = enif_make_list(env, 0); d->i++; break; case ']': if(!enif_is_empty_list(env, curr)) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_value); if(dec_curr(d) != st_array) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_array); dec_pop(d, st_value); val = curr; // curr is [] if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } if(dec_top(d) == 0) { dec_push(d, st_done); } else if(dec_curr(d) != st_value && dec_curr(d) != st_key) { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } break; case st_key: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case '\"': if(!dec_string(d, &val)) { ret = dec_error(d, "invalid_string"); goto done; } dec_pop(d, st_key); dec_push(d, st_colon); curr = enif_make_list_cell(env, val, curr); break; case '}': if(!enif_is_empty_list(env, curr)) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_key); dec_pop(d, st_object); dec_pop(d, st_value); val = make_empty_object(env, d->return_maps); if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } if(dec_top(d) == 0) { dec_push(d, st_done); } else { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } break; case st_colon: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case ':': dec_pop(d, st_colon); dec_push(d, st_value); d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } break; case st_comma: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case ',': dec_pop(d, st_comma); switch(dec_curr(d)) { case st_object: dec_push(d, st_key); break; case st_array: dec_push(d, st_value); break; default: ret = dec_error(d, "internal_error"); goto done; } d->i++; break; case '}': dec_pop(d, st_comma); if(dec_curr(d) != st_object) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_object); dec_pop(d, st_value); if(!make_object(env, curr, &val, d->return_maps, d->dedupe_keys)) { ret = dec_error(d, "internal_object_error"); goto done; } if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } if(dec_top(d) > 0) { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } else { dec_push(d, st_done); } d->i++; break; case ']': dec_pop(d, st_comma); if(dec_curr(d) != st_array) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_array); dec_pop(d, st_value); val = make_array(env, curr); if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } if(dec_top(d) > 0) { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } else { dec_push(d, st_done); } d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } break; case st_done: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; default: goto decode_done; } break; default: ret = dec_error(d, "invalid_internal_state"); goto done; } } decode_done: if(d->i < bin.size && d->return_trailer) { trailer = enif_make_sub_binary(env, argv[0], d->i, bin.size - d->i); val = enif_make_tuple3(env, d->atoms->atom_has_trailer, val, trailer); } else if(d->i < bin.size) { ret = dec_error(d, "invalid_trailing_data"); goto done; } if(dec_curr(d) != st_done) { ret = dec_error(d, "truncated_json"); } else if(d->is_partial) { ret = enif_make_tuple2(env, d->atoms->atom_partial, val); } else { ret = val; } done: return ret; }