int ei_skip_term(const char* buf, int* index) { int i, n, ty; /* ASSERT(ep != NULL); */ ei_get_type_internal(buf, index, &ty, &n); switch (ty) { case ERL_ATOM_EXT: /* FIXME: what if some weird locale is in use? */ if (ei_decode_atom_as(buf, index, NULL, MAXATOMLEN_UTF8, (ERLANG_LATIN1|ERLANG_UTF8), NULL, NULL) < 0) return -1; break; case ERL_PID_EXT: if (ei_decode_pid(buf, index, NULL) < 0) return -1; break; case ERL_PORT_EXT: if (ei_decode_port(buf, index, NULL) < 0) return -1; break; case ERL_NEW_REFERENCE_EXT: case ERL_REFERENCE_EXT: if (ei_decode_ref(buf, index, NULL) < 0) return -1; break; case ERL_NIL_EXT: if (ei_decode_list_header(buf, index, &n) < 0) return -1; break; case ERL_LIST_EXT: if (ei_decode_list_header(buf, index, &n) < 0) return -1; for (i = 0; i < n; ++i) ei_skip_term(buf, index); if (ei_get_type_internal(buf, index, &ty, &n) < 0) return -1; if (ty != ERL_NIL_EXT) ei_skip_term(buf, index); else if (ei_decode_list_header(buf, index, &n) < 0) return -1; break; case ERL_STRING_EXT: if (ei_decode_string(buf, index, NULL) < 0) return -1; break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: if (ei_decode_tuple_header(buf, index, &n) < 0) return -1; for (i = 0; i < n; ++i) ei_skip_term(buf, index); break; case ERL_BINARY_EXT: if (ei_decode_binary(buf, index, NULL, NULL) < 0) return -1; break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (ei_decode_long(buf, index, NULL) < 0) return -1; break; case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: if (ei_decode_big(buf, index, NULL) < 0) return -1; break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, NULL) < 0) return -1; break; case ERL_FUN_EXT: case ERL_NEW_FUN_EXT: if (ei_decode_fun(buf, index, NULL) < 0) return -1; break; default: return -1; } return 0; }
int ei_decode_term(const char *buf, int *index, void *t) { const char *s = buf + *index; const char *s0 = s; if (t) { ETERM *tmp; /* this decodes and advances s */ if (!(tmp = erl_decode_buf((unsigned char **)&s))) return -1; *(ETERM **)t = tmp; *index += s - s0; return 0; } else { int tmpindex = *index; long ttype; int arity; int i; /* these are all the external types */ switch ((ttype = get8(s))) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: case ERL_SMALL_BIG_EXT: return ei_decode_long(buf,index,NULL); case ERL_FLOAT_EXT: return ei_decode_double(buf,index,NULL); case ERL_ATOM_EXT: return ei_decode_atom(buf,index,NULL); case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: return ei_decode_ref(buf,index,NULL); case ERL_PORT_EXT: return ei_decode_port(buf,index,NULL); case ERL_PID_EXT: return ei_decode_pid(buf,index,NULL); case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: if (ei_decode_tuple_header(buf,index,&arity) < 0) return -1; for (i=0; i<arity; i++) { if (ei_decode_term(buf,index,NULL)) { /* restore possibly changed index before returning */ *index = tmpindex; return -1; } } return 0; case ERL_STRING_EXT: return ei_decode_string(buf,index,NULL); case ERL_LIST_EXT: case ERL_NIL_EXT: if (ei_decode_list_header(buf,index,&arity) < 0) return -1; if (arity) { for (i=0; i<arity; i++) { if (ei_decode_term(buf,index,NULL) < 0) { /* restore possibly changed index before returning */ *index = tmpindex; return -1; } } if (ei_decode_list_header(buf,index,&arity) < 0) { *index = tmpindex; return -1; } } return 0; case ERL_BINARY_EXT: return ei_decode_binary(buf,index,NULL,NULL); case ERL_LARGE_BIG_EXT: default: break; } } return -1; }
int control(struct exmpp_xml_ctx *ctx, unsigned int command, const char *buf, ei_x_buff *to_return) { int index; if (ctx == NULL || buf == NULL || to_return == NULL) return (-1); switch (command) { /* * Global known lists update. */ case COMMAND_ADD_KNOWN_NSS: index = exmpp_skip_version(buf); if (add_known_nss(buf, index) != 0) { ei_x_encode_atom(to_return, "add_known_nss_failed"); return (RET_ERROR); } break; case COMMAND_ADD_KNOWN_ELEMS: index = exmpp_skip_version(buf); if (add_known_elems(buf, index) != 0) { ei_x_encode_atom(to_return, "add_known_elems_failed"); return (RET_ERROR); } break; /* * Options handling. */ case COMMAND_SET_NAMES_AS_ATOM: index = exmpp_skip_version(buf); ei_decode_boolean(buf, &index, &(ctx->names_as_atom)); break; case COMMAND_SET_CHECK_NSS: index = exmpp_skip_version(buf); if (select_known_nss(ctx, buf, index) != 0) { ei_x_encode_atom(to_return, "check_nss_failed"); return (RET_ERROR); } break; case COMMAND_SET_CHECK_ELEMS: index = exmpp_skip_version(buf); if (select_known_elems(ctx, buf, index) != 0) { ei_x_encode_atom(to_return, "check_elems_failed"); return (RET_ERROR); } break; case COMMAND_SET_ROOT_DEPTH: index = exmpp_skip_version(buf); ei_decode_long(buf, &index, &(ctx->root_depth)); break; case COMMAND_SET_EMIT_ENDTAG: index = exmpp_skip_version(buf); ei_decode_boolean(buf, &index, &(ctx->emit_endtag)); break; case COMMAND_SET_MAX_SIZE: index = exmpp_skip_version(buf); ei_decode_long(buf, &index, &(ctx->max_size)); break; default: /* Command not recognized. */ ei_x_encode_tuple_header(to_return, 2); ei_x_encode_atom(to_return, "unknown_command"); ei_x_encode_ulong(to_return, command); return (RET_ERROR); } return (RET_OK); }
void loop() { int64_t dts_shift = AV_NOPTS_VALUE; uint32_t buf_size = 10240; char *buf = (char *)malloc(buf_size); while(1) { uint32_t len; int idx = 0; int read_bytes = 0; if((read_bytes = read1(in_fd, &len, 4)) != 4) { if(read_bytes == 0) { _exit(0); } error("Can't read input length: %d", read_bytes); } len = ntohl(len); if(len > buf_size) { buf_size = len; free(buf); buf = (char *)malloc(buf_size); } if((read_bytes = read1(in_fd, buf, len)) != len) error("Can't read %d bytes from input: %d", len, read_bytes); int version = 0; ei_decode_version(buf, &idx, &version); int command_idx = idx; int arity = 0; if(ei_decode_tuple_header(buf, &idx, &arity) == -1) error("must pass tuple"); int t = 0; int size = 0; ei_get_type(buf, &idx, &t, &size); if(t != ERL_ATOM_EXT) error("first element must be atom"); char command[MAXATOMLEN+1]; ei_decode_atom(buf, &idx, command); arity--; if(!strcmp(command, "ping")) { pong(); continue; } if(!strcmp(command, "exit")) { return; } if(!strcmp(command, "init_input")) { if(arity != 3) error("Must provide 3 arguments to init_input command"); char content[1024]; char codec[1024]; if(ei_decode_atom(buf, &idx, content) == -1) error("Must provide content as an atom"); if(ei_decode_atom(buf, &idx, codec) == -1) error("Must provide codec as an atom"); int decoder_config_len = 0; ei_get_type(buf, &idx, &t, &decoder_config_len); if(t != ERL_BINARY_EXT) error("decoder config must be a binary"); uint8_t *decoder_config = av_mallocz(decoder_config_len + FF_INPUT_BUFFER_PADDING_SIZE); long bin_len = 0; ei_decode_binary(buf, &idx, decoder_config, &bin_len); Track *t = NULL; if(!strcmp(content, "video")) { t = &input_video; } else if(!strcmp(content, "audio")) { t = &input_audio; } else { error("Unknown media content: '%s'", content); } if(t->codec) error("Double initialization of media '%s'", content); t->codec = avcodec_find_decoder_by_name(codec); t->ctx = avcodec_alloc_context3(t->codec); if(!t->codec || !t->ctx) error("Unknown %s decoder '%s'", content, codec); t->ctx->time_base = (AVRational){1, 90}; t->ctx->extradata_size = decoder_config_len; t->ctx->extradata = decoder_config; if(avcodec_open2(t->ctx, t->codec, NULL) < 0) error("failed to allocate %s decoder", content); reply_atom("ready"); continue; } if(!strcmp(command, "init_output")) { if(arity != 4) error("Must provide 4 arguments to init_output command"); char content[1024]; char codec[1024]; if(ei_decode_atom(buf, &idx, content) == -1) error("Must provide content as an atom"); if(ei_decode_atom(buf, &idx, codec) == -1) error("Must provide codec as an atom"); long track_id = -1; if(ei_decode_long(buf, &idx, &track_id) == -1) error("track_id must be integer"); if(track_id < 1 || track_id > MAX_OUTPUT_TRACKS+1) error("track_id must be from 1 to %d", MAX_OUTPUT_TRACKS+1); track_id--; Track *t = NULL; if(!strcmp(content, "audio")) { t = &output_audio[out_audio_count++]; } else if(!strcmp(content, "video")) { t = &output_video[out_video_count++]; } else { error("invalid_content '%s'", content); } t->track_id = track_id; t->codec = avcodec_find_encoder_by_name(codec); t->ctx = avcodec_alloc_context3(t->codec); if(!t->codec || !t->ctx) error("Unknown encoder '%s'", codec); AVCodecContext* ctx = t->ctx; AVDictionary *opts = NULL; int options_count = 0; if(ei_decode_list_header(buf, &idx, &options_count) < 0) error("options must be a proplist"); while(options_count > 0) { int arity1 = 0; int t,s; ei_get_type(buf, &idx, &t, &s); if(t == ERL_NIL_EXT) { ei_skip_term(buf, &idx); break; } if(ei_decode_tuple_header(buf, &idx, &arity1) < 0) error("options must be a proper proplist"); if(arity1 != 2) error("tuples in options proplist must be arity 2"); char key[MAXATOMLEN]; if(ei_decode_atom(buf, &idx, key) == 0) { if(!strcmp(key, "width")) { long w = 0; if(ei_decode_long(buf, &idx, &w) < 0) error("width must be integer"); ctx->width = w; continue; } if(!strcmp(key, "height")) { long h = 0; if(ei_decode_long(buf, &idx, &h) < 0) error("height must be integer"); ctx->height = h; continue; } if(!strcmp(key, "bitrate")) { long b = 0; if(ei_decode_long(buf, &idx, &b) < 0) error("bitrate must be integer"); ctx->bit_rate = b; continue; } if(!strcmp(key, "sample_rate")) { long sr = 0; if(ei_decode_long(buf, &idx, &sr) < 0) error("sample_rate must be integer"); ctx->sample_rate = sr; continue; } if(!strcmp(key, "channels")) { long ch = 0; if(ei_decode_long(buf, &idx, &ch) < 0) error("channels must be integer"); ctx->channels = ch; continue; } fprintf(stderr, "Unknown key: '%s'\r\n", key); ei_skip_term(buf, &idx); continue; } else if(ei_decode_string(buf, &idx, key) == 0) { char value[MAXATOMLEN]; if(ei_decode_string(buf, &idx, value) < 0) error("key-value must be strings"); av_dict_set(&opts, key, value, 0); } else { error("Invalid options proplist"); } } if(!strcmp(content, "video")) { ctx->pix_fmt = AV_PIX_FMT_YUV420P; } if(!strcmp(content, "audio")) { ctx->sample_fmt = AV_SAMPLE_FMT_S16; ctx->profile = FF_PROFILE_AAC_MAIN; } ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; ctx->time_base = (AVRational){1,90}; if(avcodec_open2(ctx, t->codec, &opts) < 0) error("failed to allocate video encoder"); AVPacket config; config.dts = config.pts = 0; config.flags = CODEC_FLAG_GLOBAL_HEADER; config.data = ctx->extradata; config.size = ctx->extradata_size; reply_avframe(&config, t->codec); continue; } if(!strcmp(command, "video_frame")) { idx = command_idx; struct video_frame *fr = read_video_frame(buf, &idx); AVPacket packet; av_new_packet(&packet, fr->body.size); memcpy(packet.data, fr->body.data, fr->body.size); packet.size = fr->body.size; packet.dts = fr->dts*90; packet.pts = fr->pts*90; packet.stream_index = fr->track_id; // if(packet_size != pkt_size) error("internal error in reading frame body"); if(fr->content == frame_content_audio) { if(!input_audio.ctx) error("input audio uninitialized"); AVFrame *decoded_frame = avcodec_alloc_frame(); int got_output = 0; int ret = avcodec_decode_audio4(input_audio.ctx, decoded_frame, &got_output, &packet); if(got_output) { reply_atom("ok"); } else { error("Got: %d, %d\r\n", ret, got_output); } free(fr); continue; } if(fr->content == frame_content_video) { if(!input_video.ctx) error("input video uninitialized"); AVFrame *decoded_frame = avcodec_alloc_frame(); int could_decode = 0; int ret = avcodec_decode_video2(input_video.ctx, decoded_frame, &could_decode, &packet); if(ret < 0) { error("failed to decode video"); } if(could_decode) { decoded_frame->pts = av_frame_get_best_effort_timestamp(decoded_frame); int sent_config = 0; AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; int could_encode = 0; if(out_video_count <= 0) error("trying to transcode uninitialized video"); if(avcodec_encode_video2(output_video[0].ctx, &pkt, decoded_frame, &could_encode) != 0) error("Failed to encode h264"); if(could_encode) { if(dts_shift == AV_NOPTS_VALUE) { dts_shift = -pkt.dts; } pkt.dts += dts_shift; reply_avframe(&pkt, output_video[0].codec); } else if(!sent_config) { reply_atom("ok"); } free(fr); continue; } else { reply_atom("ok"); free(fr); continue; } } error("Unknown content"); } // AVCodecContext // AVPacket // AVFrame char *s = (char *)malloc(1024); ei_s_print_term(&s, buf, &command_idx); error("Unknown command: %s", s); } }
static int parse_option_list(const char *req, int *req_index, struct uart_config *config) { int term_type; int option_count; if (ei_get_type(req, req_index, &term_type, &option_count) < 0 || (term_type != ERL_LIST_EXT && term_type != ERL_NIL_EXT)) { debug("expecting option list"); return -1; } if (term_type == ERL_NIL_EXT) option_count = 0; else ei_decode_list_header(req, req_index, &option_count); // Go through all of the options for (int i = 0; i < option_count; i++) { int term_size; if (ei_decode_tuple_header(req, req_index, &term_size) < 0 || term_size != 2) { debug("expecting kv tuple for options"); return -1; } char key[64]; if (ei_decode_atom(req, req_index, key) < 0) { debug("expecting atoms for option keys"); return -1; } if (strcmp(key, "active") == 0) { int val; if (ei_decode_boolean(req, req_index, &val) < 0) { debug("active should be a bool"); return -1; } config->active = (val != 0); } else if (strcmp(key, "speed") == 0) { long val; if (ei_decode_long(req, req_index, &val) < 0) { debug("speed should be an integer"); return -1; } config->speed = val; } else if (strcmp(key, "data_bits") == 0) { long val; if (ei_decode_long(req, req_index, &val) < 0) { debug("data_bits should be an integer"); return -1; } config->data_bits = val; } else if (strcmp(key, "stop_bits") == 0) { long val; if (ei_decode_long(req, req_index, &val) < 0) { debug("stop_bits should be an integer"); return -1; } config->stop_bits = val; } else if (strcmp(key, "parity") == 0) { char parity[16]; if (ei_decode_atom(req, req_index, parity) < 0) { debug("parity should be an atom"); return -1; } if (strcmp(parity, "none") == 0) config->parity = UART_PARITY_NONE; else if (strcmp(parity, "even") == 0) config->parity = UART_PARITY_EVEN; else if (strcmp(parity, "odd") == 0) config->parity = UART_PARITY_ODD; else if (strcmp(parity, "space") == 0) config->parity = UART_PARITY_SPACE; else if (strcmp(parity, "mark") == 0) config->parity = UART_PARITY_MARK; else if (strcmp(parity, "ignore") == 0) config->parity = UART_PARITY_IGNORE; } else if (strcmp(key, "flow_control") == 0) { char flow_control[16]; if (ei_decode_atom(req, req_index, flow_control) < 0) { debug("flow_control should be an atom"); return -1; } if (strcmp(flow_control, "none") == 0) config->flow_control = UART_FLOWCONTROL_NONE; else if (strcmp(flow_control, "hardware") == 0) config->flow_control = UART_FLOWCONTROL_HARDWARE; else if (strcmp(flow_control, "software") == 0) config->flow_control = UART_FLOWCONTROL_SOFTWARE; } else { // unknown term ei_skip_term(req, req_index); } } return 0; }
static void process(ErlDrvData handle, ErlIOVec *ev) { lua_drv_t *driver_data = (lua_drv_t*) handle; char *buf = ev->binv[1]->orig_bytes; int index = 0; int arty, version; long command; ei_decode_version(buf, &index, &version); ei_decode_tuple_header(buf, &index, &arty); ei_decode_long(buf, &index, &command); // printf("Command: %ld\n", command); // printf("sizeof: int: %ld, long: %ld, long long: %ld\n", sizeof(int), sizeof(long), sizeof(long long)); switch(command) { case ERL_LUA_CALL: erl_lua_call(driver_data, buf, index); break; case ERL_LUA_CONCAT: erl_lua_concat(driver_data, buf, index); break; case ERL_LUA_CREATETABLE: erl_lua_createtable(driver_data, buf, index); break; case ERL_LUA_NEWTABLE: erl_lua_newtable(driver_data, buf, index); break; case ERL_LUA_NEXT: erl_lua_next(driver_data, buf, index); break; case ERL_LUA_OBJLEN: erl_lua_objlen(driver_data, buf, index); break; case ERL_LUA_GETFIELD: erl_lua_getfield(driver_data, buf, index); break; case ERL_LUA_GETGLOBAL: erl_lua_getglobal(driver_data, buf, index); break; case ERL_LUA_GETTABLE: erl_lua_gettable(driver_data, buf, index); break; case ERL_LUA_GETTOP: erl_lua_gettop(driver_data, buf, index); break; case ERL_LUA_PUSHBOOLEAN: erl_lua_pushboolean(driver_data, buf, index); break; case ERL_LUA_PUSHINTEGER: erl_lua_pushinteger(driver_data, buf, index); break; case ERL_LUA_PUSHLSTRING: erl_lua_pushlstring(driver_data, buf, index); break; case ERL_LUA_PUSHNIL: erl_lua_pushnil(driver_data, buf, index); break; case ERL_LUA_PUSHNUMBER: erl_lua_pushnumber(driver_data, buf, index); break; case ERL_LUA_REMOVE: erl_lua_remove(driver_data, buf, index); break; case ERL_LUA_SETFIELD: erl_lua_setfield(driver_data, buf, index); break; case ERL_LUA_SETGLOBAL: erl_lua_setglobal(driver_data, buf, index); break; case ERL_LUA_TOBOOLEAN: erl_lua_toboolean(driver_data, buf, index); break; case ERL_LUA_TOINTEGER: erl_lua_tointeger(driver_data, buf, index); break; case ERL_LUA_TOLSTRING: erl_lua_tolstring(driver_data, buf, index); break; case ERL_LUA_TONUMBER: erl_lua_tonumber(driver_data, buf, index); break; case ERL_LUA_SETTABLE: erl_lua_settable(driver_data, buf, index); break; case ERL_LUA_TYPE: erl_lua_type(driver_data, buf, index); break; case ERL_LUAL_DOSTRING: erl_lual_dostring(driver_data, buf, index); break; case ERL_LUAM_MULTIPCALL: erl_luam_multipcall(driver_data, buf, index); break; case ERL_LUAM_MAYBE_ATOM: erl_luam_maybe_atom(driver_data, buf, index); break; default: erl_lua_no_command(driver_data); } }
static int control(ErlDrvData handle, unsigned int command, char* buf, int count, char** res, int res_size) { tcbdb_drv_t *driver = (tcbdb_drv_t*)handle; TCBDB *bdb = driver->bdb; int index = 1, tp, sz, version; char key[MAX_KEY_SIZE], value[MAX_VALUE_SIZE]; long key_size, value_size; long long long_tmp; bool rs; const char *value_tmp = NULL; ei_x_buff x; ei_x_new_with_version(&x); if (bdb == NULL && command != OPEN) return ei_error(&x, "database_not_opened", res, res_size); ei_decode_version(buf, &index, &version); switch (command) { case OPEN: // open(Filepath::string()) if (bdb == NULL) { ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_STRING_EXT) return ei_error(&x, "invalid_argument", res, res_size); TCBDB *bdb = tcbdbnew(); tcbdbsetmutex(bdb); tcbdbsetcache(bdb, 104800, 51200); tcbdbsetxmsiz(bdb, 1048576); tcbdbtune(bdb, 0, 0, 0, 7, -1, BDBTLARGE); char *file = driver_alloc(sz + 1); ei_decode_string(buf, &index, file); rs = tcbdbopen(bdb, file, BDBOWRITER | BDBOCREAT); driver_free(file); if (!rs) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); driver->bdb = bdb; ei_x_encode_atom(&x, "ok"); } else return ei_error(&x, "database already opened", res, res_size); break; case CLOSE: tcbdbclose(bdb); tcbdbdel(bdb); driver->bdb = NULL; ei_x_encode_atom(&x, "ok"); break; case PUT: case PUTDUP: case PUTCAT: case PUTKEEP: // put({Key::binary(), Value::binary()}) ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_SMALL_TUPLE_EXT || sz != 2) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_tuple_header(buf, &index, &sz); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT) return ei_error(&x, "invalid_argument", res, res_size); if (sz <= MAX_VALUE_SIZE) { ei_decode_binary(buf, &index, &value[0], &value_size); switch (command) { case PUT: rs = tcbdbput(bdb, &key[0], key_size, &value[0], value_size); break; case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, &value[0], value_size); break; case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, &value[0], value_size); break; default: rs = tcbdbputkeep(bdb, &key[0], key_size, &value[0], value_size); } } else { void *p = driver_alloc(sz); if (p) { ei_decode_binary(buf, &index, p, &value_size); switch (command) { case PUT: rs = tcbdbput(bdb, &key[0], key_size, p, value_size); break; case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, p, value_size); break; case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, p, value_size); break; default: rs = tcbdbputkeep(bdb, &key[0], key_size, p, value_size); } driver_free(p); } else return ei_error(&x, "too long value", res, res_size); }; if (!rs) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); ei_x_encode_atom(&x, "ok"); break; case GET: // get(Key::binary()) -> {ok, Value} | {error, not_found} ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); value_tmp = tcbdbget3(bdb, &key[0], key_size, &sz); ei_x_encode_tuple_header(&x, 2); if (value_tmp != NULL) { ei_x_encode_atom(&x, "ok"); ei_x_encode_binary(&x, value_tmp, sz); } else { ei_x_encode_atom(&x, "error"); ei_x_encode_atom(&x, "not_found"); } break; case GETDUP: // get(Key::binary()) -> {ok, Values} ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); TCLIST *vals = tcbdbget4(bdb, key, key_size); if (vals) { ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); int j; for (j=0; j<tclistnum(vals); j++) { value_tmp = tclistval(vals, j, &sz); ei_x_encode_list_header(&x, 1); ei_x_encode_binary(&x, value_tmp, sz); } tclistdel(vals); ei_x_encode_empty_list(&x); } else { ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); ei_x_encode_empty_list(&x); } break; case REMOVE: // remove(Keys::list()) // remove(Key::binary()) // remove({Key::binary(), Value::binary()}) ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_LIST_EXT) { int count, j; ei_decode_list_header(buf, &index, &count); for (j=0; j<count; j++) { ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); if (!tcbdbout3(bdb, &key[0], key_size)) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); } ei_x_encode_atom(&x, "ok"); } else if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) { ei_decode_binary(buf, &index, &key[0], &key_size); tcbdbout3(bdb, &key[0], key_size); ei_x_encode_atom(&x, "ok"); } else if (tp == ERL_SMALL_TUPLE_EXT && sz == 2) { ei_decode_tuple_header(buf, &index, &sz); // get key ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); // get value ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_VALUE_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &value[0], &value_size); // remove by key&value BDBCUR *cur = tcbdbcurnew(bdb); if (!tcbdbcurjump(cur, &key[0], key_size)) return ei_error(&x, "record_not_found", res, res_size); bool removed = false, not_found = false; while (!removed && !not_found) { int cur_key_size, cur_val_size; const void *curkey = tcbdbcurkey3(cur, &cur_key_size); if (cur_key_size == key_size && memcmp(curkey, key, key_size) == 0) { const void *curval = tcbdbcurval3(cur, &cur_val_size); if (cur_val_size == value_size && memcmp(curval, value, value_size) == 0) { tcbdbcurout(cur); removed = true; } else if (!tcbdbcurnext(cur)) not_found = true; } else not_found = true; } if (not_found) ei_x_encode_atom(&x, "not_found"); else ei_x_encode_atom(&x, "ok"); } else return ei_error(&x, "invalid_argument", res, res_size); break; case RANGE: /* * range({Prefix::binary(), limit:integer()}) * range({StartKey::binary(), BeginInclusion::boolean(), EndKey::binary(), EndInclusion::binary(), limit:integer()}) */ ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_SMALL_TUPLE_EXT || sz < 2) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_tuple_header(buf, &index, &sz); ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) { char keys[MAX_KEY_SIZE], keyf[MAX_KEY_SIZE]; long keys_size, keyf_size; int keys_inc, keyf_inc; long max = -1; TCLIST *range; ei_decode_binary(buf, &index, &keys[0], &keys_size); ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_ATOM_EXT) { // range ei_decode_boolean(buf, &index, &keys_inc); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &keyf[0], &keyf_size); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_ATOM_EXT) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_boolean(buf, &index, &keyf_inc); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_INTEGER_EXT) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_long(buf, &index, &max); range = tcbdbrange(bdb, &keys[0], keys_size, keys_inc == 1, &keyf[0], keyf_size, keyf_inc == 1, max); } else if (tp == ERL_INTEGER_EXT) { // prefix ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_INTEGER_EXT) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_long(buf, &index, &max); range = tcbdbfwmkeys(bdb, &keys[0], keys_size, max); } else return ei_error(&x, "invalid_argument", res, res_size); const char *key; int key_size, value_size; int idx, cnt = 0, rcount = tclistnum(range); ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); BDBCUR *cur = tcbdbcurnew(bdb); for (idx=0; idx<rcount; idx++) { key = tclistval(range, idx, &key_size); TCLIST *vals = tcbdbget4(bdb, key, key_size); if (vals) { int j; for (j=0; j<tclistnum(vals); j++) { ei_x_encode_list_header(&x, 1); value_tmp = tclistval(vals, j, &value_size); ei_x_encode_binary(&x, value_tmp, value_size); if (max >= 0 && ++cnt >= max) break; } tclistdel(vals); } idx++; } tcbdbcurdel(cur); tclistdel(range); ei_x_encode_empty_list(&x); } else return ei_error(&x, "invalid_argument", res, res_size); break; case SYNC: // sync() if (!tcbdbsync(bdb)) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); ei_x_encode_atom(&x, "ok"); break; case INFO: // info() ei_x_encode_tuple_header(&x, 3); ei_x_encode_atom(&x, "ok"); long_tmp = tcbdbrnum(bdb); ei_x_encode_longlong(&x, long_tmp); long_tmp = tcbdbfsiz(bdb); ei_x_encode_longlong(&x, long_tmp); break; case ITERATE: // Read(none) -> {ok, Key} | {error, not_found} // Read(Key::binary()) -> {ok, Key} | {error, not_found} ei_get_type(buf, &index, &tp, &sz); BDBCUR *cur = tcbdbcurnew(bdb); if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) { ei_decode_binary(buf, &index, &key[0], &key_size); rs = tcbdbcurjump(cur, &key[0], key_size) && tcbdbcurnext(cur); } else rs = tcbdbcurfirst(cur); if (rs) { int key_size; const char *key = tcbdbcurkey3(cur, &key_size); ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); ei_x_encode_binary(&x, key, key_size); tcbdbcurdel(cur); } else { tcbdbcurdel(cur); return ei_error(&x, "not_found", res, res_size); } break; case VANISH: // vanish() -> ok if (!tcbdbvanish(bdb)) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); ei_x_encode_atom(&x, "ok"); break; case BACKUP: // backup(path::string()) -> ok | {error, Reason} ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_STRING_EXT) { char *file = driver_alloc(sz + 1); ei_decode_string(buf, &index, file); if (tcbdbcopy(driver->bdb, file)) ei_x_encode_atom(&x, "ok"); else return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); } else return ei_error(&x, "invalid_argument", res, res_size); break; default: return ei_error(&x, "invalid_command", res, res_size); } if (res_size < x.index) (*res) = (char *)driver_alloc(x.index); int n = x.index; memcpy(*res, x.buff, x.index); ei_x_free(&x); return n; };
/* * Get int parameter */ static int get_int(int *int_ptr,erl_rpc_ctx_t *ctx, int reads, int autoconvert) { int type, size; char *p; char *endptr; double d; long l; if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)) { if(ctx->optional) return 0; erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads); return -1; } switch(type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if(ei_decode_long(ctx->request->buff, &ctx->request_index, &l)) { erl_rpc_fault(ctx,400,"Bad value of parameter #%d.",reads); return -1; } *int_ptr = (int)l; break; case ERL_STRING_EXT: case ERL_LIST_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } /* allocate buffer */ p = (char*)pkg_malloc(size+1); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } ei_decode_string(ctx->request->buff, &ctx->request_index, p); *int_ptr = strtol(p,&endptr,10); if (p == endptr) { erl_rpc_fault(ctx,400,"Unable to convert %s into integer for parameter at position %d",p,reads); pkg_free(p); return -1; } pkg_free(p); break; case ERL_FLOAT_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_double(ctx->request->buff,&ctx->request_index,&d)) { erl_rpc_fault(ctx,400, "Can't read parameter #%d",reads); return -1; } *int_ptr=(int)d; break; default: LM_ERR("Unsupported type ('%c') for conversion into integer parameter #%d.\n",type,reads); erl_rpc_fault(ctx,400,"Unsupported type ('%c') for conversion into integer parameter #%d.",type,reads); return -1; } return 0; }
static int get_double(double *double_prt,erl_rpc_ctx_t *ctx, int reads, int autoconvert) { int type, size; char *p; char *endptr; long n; if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)){ erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads); return -1; } switch(type) { case ERL_FLOAT_EXT: if (ei_decode_double(ctx->request->buff,&ctx->request_index,double_prt)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } break; case ERL_STRING_EXT: case ERL_LIST_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } /* allocate buffer */ p = (char*)pkg_malloc(size+1); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } ei_decode_string(ctx->request->buff, &ctx->request_index, p); *double_prt = strtod(p,&endptr); if (p == endptr) { erl_rpc_fault(ctx,400,"Unable to convert %s into double, parameter at position #%d",p,reads); pkg_free(p); return -1; } pkg_free(p); break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if(ei_decode_long(ctx->request->buff, &ctx->request_index, &n)) { erl_rpc_fault(ctx,400,"Can't read parameter #%d",reads); return -1; } *double_prt=n; break; default: erl_rpc_fault(ctx,400,"Can't convert to double parameter #%d.",reads); return -1; } return 0; }
static void show_term(const char *termbuf, int *index, FILE *stream) { int type; char smallbuf[EISHOWBUF]; int version; long num; double fnum; erlang_pid pid; erlang_port port; erlang_ref ref; int i, len; char *s; ei_get_type(termbuf,index,&type,&len); switch (type) { case ERL_VERSION_MAGIC: /* just skip past this */ ei_decode_version(termbuf,index,&version); show_term(termbuf,index,stream); break; case ERL_ATOM_EXT: ei_decode_atom(termbuf,index,smallbuf); fprintf(stream,"%s",smallbuf); break; case ERL_STRING_EXT: /* strings can be much longer than EISHOWBUF */ if (len < EISHOWBUF) s = smallbuf; else if (!(s = malloc(len+1))) break; /* FIXME just break if can't? */ ei_decode_string(termbuf,index,s); if (printable_list_p((uint8 *)s,len)) { /* just show it as it is */ fprintf(stream,"\"%s\"",s); } else { /* show it as a list instead */ fprintf(stream,"["); for (i=0; i<len; i++) { if (i > 0) fprintf(stream,", "); fprintf(stream,"%d",s[i]); } fprintf(stream,"]"); } /* did we allocate anything? */ if (s && (s != smallbuf)) free(s); break; /* FIXME add case using ei_decode_longlong */ case ERL_SMALL_BIG_EXT: case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (ei_decode_long(termbuf,index,&num) == 0) { fprintf(stream,"%ld",num); } else { ei_decode_skip_bignum(termbuf,index,NULL); fprintf(stream,"#Bignum"); } break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: ei_decode_double(termbuf,index,&fnum); fprintf(stream,"%f",fnum); break; case ERL_PID_EXT: case ERL_NEW_PID_EXT: ei_decode_pid(termbuf,index,&pid); show_pid(stream,&pid); break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: ei_decode_tuple_header(termbuf,index,&len); fprintf(stream,"{"); for (i=0; i<len; i++) { if (i > 0) fprintf(stream,", "); show_term(termbuf,index,stream); } fprintf(stream,"}"); break; case ERL_LIST_EXT: ei_decode_list_header(termbuf,index,&len); fprintf(stream,"["); for (i=0; i<len; i++) { if (i > 0) fprintf(stream,", "); show_term(termbuf,index,stream); } /* get the empty list at the end */ ei_decode_list_header(termbuf,index,&len); fprintf(stream,"]"); break; case ERL_NIL_EXT: ei_decode_list_header(termbuf,index,&len); fprintf(stream,"[]"); break; case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: case ERL_NEWER_REFERENCE_EXT: ei_decode_ref(termbuf,index,&ref); fprintf(stream,"#Ref<%s",ref.node); for (i = 0; i < ref.len; i++) { fprintf(stream,".%u",ref.n[i]); } fprintf(stream,".%u>",ref.creation); break; case ERL_PORT_EXT: case ERL_NEW_PORT_EXT: ei_decode_port(termbuf,index,&port); fprintf(stream,"#Port<%s.%u.%u>",port.node,port.id,port.creation); break; case ERL_BINARY_EXT: ei_decode_binary(termbuf,index,NULL,&num); fprintf(stream,"#Bin<%ld>",num); break; case ERL_BIT_BINARY_EXT: { size_t bits; ei_decode_bitstring(termbuf, index, NULL, NULL, &bits); fprintf(stream, "#Bits<%lu>", (unsigned long)bits); break; } case ERL_LARGE_BIG_EXT: /* doesn't actually decode - just skip over it */ /* FIXME if GMP, what to do here?? */ ei_decode_skip_bignum(termbuf,index,NULL); fprintf(stream,"#Bignum"); break; case ERL_FUN_EXT: { char atom[MAXATOMLEN]; long idx; long uniq; const char* s = termbuf + *index, * s0 = s; int n_free; ++s; n_free = get32be(s); *index += s - s0; ei_decode_pid(termbuf, index, NULL); /* skip pid */ ei_decode_atom(termbuf, index, atom); /* get module, index, uniq */ ei_decode_long(termbuf, index, &idx); ei_decode_long(termbuf, index, &uniq); fprintf(stream,"#Fun<%s.%ld.%ld>", atom, idx, uniq); for (i = 0; i < n_free; ++i) { /* FIXME how to report error ?! */ if (ei_skip_term(termbuf, index) != 0) fprintf(stderr,"<ERROR> show_msg: unknown type of term !"); } break; } default: fprintf(stream,"#Unknown<%d.%d>",type,len); /* unfortunately we don't know how to skip over this type in * the buffer if we don't even know what it is, so we return. */ return; break; } }
int main(int argc, char **argv) { char *buf = NULL; uint32_t size = BUF_SIZE; char command[MAXATOMLEN]; int index, version; if ((buf = (char *)calloc(size, sizeof(char))) == NULL) return -1; while (read_cmd(buf, &size) > 0) { /* Reset the index, so that ei functions can decode terms from the * beginning of the buffer */ index = 0; // D("buf: %s", buf); /* Ensure that we are receiving the binary term by reading and * stripping the version byte */ check(ei_decode_version(buf, &index, &version)); /* Ici donc le code du recorder: * * if decode_atom => stop: * arreter le thread -> ok, {error, not_started} sinon * else * if decode tuple de taille 2: * starter le thread -> ok, {error, already_started} sinon */ if (!ei_decode_atom(buf, &index, command)) { // D("Got atom: %s", command); if (!strcmp(command, "stop")) { if (recording) stop_recording(); else ok(); } else check(-1); } else { int arity; // long _span; check(ei_decode_tuple_header(buf, &index, &arity)); // D("Arity: %d", arity); if (arity != 2) check(-1); check(ei_decode_atom(buf, &index, command)); // D("Got atom: %s", command); if (strcmp(command, "record")) check(-1); check(ei_decode_long(buf, &index, &frequency)); // D("Freq: %li", frequency); /* check(ei_decode_long(buf, &index, &_span)); */ /* span = _span; */ /* D("SPAN: %i", span); */ if (!recording) { start_recording(); } else error(); } memset(buf, 0, size*sizeof(char)); } free(buf); return 0; }
int ei_decode_fun(const char *buf, int *index, erlang_fun *p) { const char *s = buf + *index; const char *s0 = s; int i, ix, ix0, n; erlang_pid* p_pid; char* p_module; erlang_char_encoding* p_module_org_enc; long* p_index; long* p_uniq; long* p_old_index; if (p != NULL) { p_pid = &p->pid; p_module = &p->module[0]; p_module_org_enc = &p->module_org_enc; p_index = &p->index; p_uniq = &p->uniq; p_old_index = &p->old_index; } else { p_pid = NULL; p_module = NULL; p_module_org_enc = NULL; p_index = NULL; p_uniq = NULL; p_old_index = NULL; } switch (get8(s)) { case ERL_FUN_EXT: /* mark as old (R7 and older) external fun */ if (p != NULL) p->arity = -1; /* first number of free vars (environment) */ n = get32be(s); /* then the pid */ ix = 0; if (ei_decode_pid(s, &ix, p_pid) < 0) return -1; /* then the module (atom) */ if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, p_module_org_enc, NULL) < 0) return -1; /* then the index */ if (ei_decode_long(s, &ix, p_index) < 0) return -1; /* then the uniq */ if (ei_decode_long(s, &ix, p_uniq) < 0) return -1; /* finally the free vars */ ix0 = ix; for (i = 0; i < n; ++i) { if (ei_skip_term(s, &ix) < 0) return -1; } if (p != NULL) { p->n_free_vars = n; p->free_var_len = ix - ix0; p->free_vars = ei_malloc(ix - ix0); if (!(p->free_vars)) return -1; memcpy(p->free_vars, s + ix0, ix - ix0); } s += ix; *index += s-s0; return 0; break; case ERL_NEW_FUN_EXT: /* first total size */ n = get32be(s); /* then the arity */ i = get8(s); if (p != NULL) p->arity = i; /* then md5 */ if (p != NULL) memcpy(p->md5, s, 16); s += 16; /* then index */ i = get32be(s); if (p != NULL) p->index = i; /* then the number of free vars (environment) */ i = get32be(s); if (p != NULL) p->n_free_vars = i; /* then the module (atom) */ ix = 0; if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, p_module_org_enc, NULL) < 0) return -1; /* then the old_index */ if (ei_decode_long(s, &ix, p_old_index) < 0) return -1; /* then the old_uniq */ if (ei_decode_long(s, &ix, p_uniq) < 0) return -1; /* the the pid */ if (ei_decode_pid(s, &ix, p_pid) < 0) return -1; /* finally the free vars */ s += ix; n = n - (s - s0) + 1; if (n < 0) return -1; if (p != NULL) { p->free_var_len = n; if (n > 0) { p->free_vars = malloc(n); if (!(p->free_vars)) return -1; memcpy(p->free_vars, s, n); } } s += n; *index += s-s0; return 0; break; default: return -1; } }
static int bind_parameters( sqlite3_drv_t *drv, char *buffer, int buffer_size, int *p_index, sqlite3_stmt *statement, int *p_type, int *p_size) { // decoding parameters int i, cur_list_size = -1, param_index = 1, param_indices_are_explicit = 0, result = 0; long param_index_long; char param_name[MAXATOMLEN + 1]; // parameter names shouldn't be longer than 256! char *acc_string; result = ei_decode_list_header(buffer, p_index, &cur_list_size); if (result) { // probably all parameters are integers between 0 and 255 // and the list was encoded as string (see ei documentation) ei_get_type(buffer, p_index, p_type, p_size); if (*p_type != ERL_STRING_EXT) { return output_error(drv, SQLITE_ERROR, "error while binding parameters"); } acc_string = driver_alloc(sizeof(char*) * (*p_size + 1)); ei_decode_string(buffer, p_index, acc_string); for (param_index = 1; param_index <= *p_size; param_index++) { sqlite3_bind_int(statement, param_index, (int) acc_string[param_index - 1]); } driver_free(acc_string); return 0; } for (i = 0; i < cur_list_size; i++) { if (*p_index >= buffer_size) { return output_error(drv, SQLITE_ERROR, "error while binding parameters"); } ei_get_type(buffer, p_index, p_type, p_size); if (*p_type == ERL_SMALL_TUPLE_EXT) { int old_index = *p_index; // param with name or explicit index param_indices_are_explicit = 1; if (*p_size != 2) { return output_error(drv, SQLITE_MISUSE, "tuple should contain index or name, and value"); } ei_decode_tuple_header(buffer, p_index, p_size); ei_get_type(buffer, p_index, p_type, p_size); // first element of tuple is int (index), atom, or string (name) switch (*p_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: ei_decode_long(buffer, p_index, ¶m_index_long); param_index = param_index_long; break; case ERL_ATOM_EXT: ei_decode_atom(buffer, p_index, param_name); // insert zero terminator param_name[*p_size] = '\0'; if (strncmp(param_name, "blob", 5) == 0) { // this isn't really a parameter name! *p_index = old_index; param_indices_are_explicit = 0; goto IMPLICIT_INDEX; // yuck } else { param_index = sqlite3_bind_parameter_index(statement, param_name); } break; case ERL_STRING_EXT: if (*p_size >= MAXATOMLEN) { return output_error(drv, SQLITE_TOOBIG, "parameter name too long"); } ei_decode_string(buffer, p_index, param_name); // insert zero terminator param_name[*p_size] = '\0'; param_index = sqlite3_bind_parameter_index(statement, param_name); break; default: return output_error( drv, SQLITE_MISMATCH, "parameter index must be given as integer, atom, or string"); } result = decode_and_bind_param( drv, buffer, p_index, statement, param_index, p_type, p_size); if (result != SQLITE_OK) { return result; // error has already been output } } else { IMPLICIT_INDEX: if (param_indices_are_explicit) { return output_error( drv, SQLITE_MISUSE, "parameters without indices shouldn't follow indexed or named parameters"); } result = decode_and_bind_param( drv, buffer, p_index, statement, param_index, p_type, p_size); if (result != SQLITE_OK) { return result; // error has already been output } ++param_index; } } return result; }
/* length (4), PASS_THOUGH (1), header, message */ int ei_recv_internal (int fd, char **mbufp, int *bufsz, erlang_msg *msg, int *msglenp, int staticbufp, unsigned ms) { char header[EIRECVBUF]; char *s=header; char *mbuf=*mbufp; int len = 0; int msglen = 0; int bytesread = 0; int remain; int arity; int version; int index = 0; int i = 0; int res; int show_this_msg = 0; /* get length field */ if ((res = ei_read_fill_t(fd, header, 4, ms)) != 4) { erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } len = get32be(s); /* got tick - respond and return */ if (!len) { char tock[] = {0,0,0,0}; ei_write_fill_t(fd, tock, sizeof(tock), ms); /* Failure no problem */ *msglenp = 0; return 0; /* maybe flag ERL_EAGAIN [sverkerw] */ } /* turn off tracing on each receive. it will be turned back on if * we receive a trace token. */ ei_trace(-1,NULL); /* read enough to get at least entire header */ bytesread = (len > EIRECVBUF ? EIRECVBUF : len); if ((i = ei_read_fill_t(fd,header,bytesread,ms)) != bytesread) { erl_errno = (i == -2) ? ETIMEDOUT : EIO; return -1; } /* now decode header */ /* pass-through, version, control tuple header, control message type */ s = header; index = 1; if ((get8(s) != ERL_PASS_THROUGH) || ei_decode_version(header,&index,&version) || (version != ERL_VERSION_MAGIC) || ei_decode_tuple_header(header,&index,&arity) || ei_decode_long(header,&index,&msg->msgtype)) { erl_errno = EIO; /* Maybe another code for decoding errors */ return -1; } switch (msg->msgtype) { case ERL_SEND: /* { SEND, Cookie, ToPid } */ if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_atom_as(header,&index,msg->cookie,sizeof(msg->cookie),ERLANG_UTF8,NULL,NULL) || ei_decode_pid(header,&index,&msg->to)) { erl_errno = EIO; return -1; } break; case ERL_REG_SEND: /* { REG_SEND, From, Cookie, ToName } */ if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_atom_as(header,&index,msg->cookie,sizeof(msg->cookie),ERLANG_UTF8,NULL,NULL) || ei_decode_atom_as(header,&index,msg->toname,sizeof(msg->toname),ERLANG_UTF8,NULL,NULL)) { erl_errno = EIO; return -1; } /* actual message is remaining part of headerbuf, plus any unread bytes */ break; case ERL_LINK: /* { LINK, From, To } */ case ERL_UNLINK: /* { UNLINK, From, To } */ case ERL_GROUP_LEADER: /* { GROUP_LEADER, From, To } */ if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_pid(header,&index,&msg->to)) { erl_errno = EIO; return -1; } break; case ERL_EXIT: /* { EXIT, From, To, Reason } */ case ERL_EXIT2: /* { EXIT2, From, To, Reason } */ if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_pid(header,&index,&msg->to)) { erl_errno = EIO; return -1; } break; case ERL_SEND_TT: /* { SEND_TT, Cookie, ToPid, TraceToken } */ if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_atom_as(header,&index,msg->cookie,sizeof(msg->cookie),ERLANG_UTF8,NULL,NULL) || ei_decode_pid(header,&index,&msg->to) || ei_decode_trace(header,&index,&msg->token)) { erl_errno = EIO; return -1; } ei_trace(1,&msg->token); /* turn on tracing */ break; case ERL_REG_SEND_TT: /* { REG_SEND_TT, From, Cookie, ToName, TraceToken } */ if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_atom_as(header,&index,msg->cookie,sizeof(msg->cookie),ERLANG_UTF8,NULL,NULL) || ei_decode_atom_as(header,&index,msg->toname,sizeof(msg->toname),ERLANG_UTF8,NULL,NULL) || ei_decode_trace(header,&index,&msg->token)) { erl_errno = EIO; return -1; } ei_trace(1,&msg->token); /* turn on tracing */ break; case ERL_EXIT_TT: /* { EXIT_TT, From, To, TraceToken, Reason } */ case ERL_EXIT2_TT: /* { EXIT2_TT, From, To, TraceToken, Reason } */ if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_pid(header,&index,&msg->to) || ei_decode_trace(header,&index,&msg->token)) { erl_errno = EIO; return -1; } ei_trace(1,&msg->token); /* turn on tracing */ break; default: /* unknown type, just put any remaining bytes into buffer */ break; } /* actual message is remaining part of headerbuf, plus any unread bytes */ msglen = len - index; /* message size (payload) */ remain = len - bytesread; /* bytes left to read */ /* if callers buffer is too small, we flush in the rest of the * message and discard it, unless we know that we can reallocate * the buffer in which case we do that and read the message. */ if (msglen > *bufsz) { if (staticbufp) { int sz = EIRECVBUF; /* flush in rest of packet */ while (remain > 0) { if (remain < sz) sz = remain; if ((i=ei_read_fill_t(fd,header,sz,ms)) <= 0) break; remain -= i; } erl_errno = EMSGSIZE; return -1; } else { /* Dynamic buffer --- grow it. */ #ifdef DEBUG fprintf(stderr, "Growing buffer from %d bytes to %d bytes\n", *bufsz, msglen); #endif if ((mbuf = realloc(*mbufp, msglen)) == NULL) { erl_errno = ENOMEM; return -1; } *mbufp = mbuf; *bufsz = msglen; } } /* move remaining bytes to callers buffer */ memmove(mbuf,header+index,bytesread-index); /* let the caller know how big the message is in his buffer */ *msglenp = msglen; /* read the rest of the message into callers buffer */ if (remain > 0) { if ((i = ei_read_fill_t(fd,mbuf+bytesread-index,remain,ms)) != remain) { *msglenp = bytesread-index+1; /* actual bytes in users buffer */ erl_errno = (i == -2) ? ETIMEDOUT : EIO; return -1; } } if (show_this_msg) ei_show_recmsg(stderr,msg,mbuf); /* the caller only sees "untraced" message types */ /* the trace token is buried in the message struct */ if (msg->msgtype > 10) msg->msgtype -= 10; return msg->msgtype; }
static void i2c_handle_request(const char *req, void *cookie) { struct i2c_info *i2c = (struct i2c_info *) cookie; // Commands are of the form {Command, Arguments}: // { atom(), term() } int req_index = sizeof(uint16_t); if (ei_decode_version(req, &req_index, NULL) < 0) errx(EXIT_FAILURE, "Message version issue?"); int arity; if (ei_decode_tuple_header(req, &req_index, &arity) < 0 || arity != 2) errx(EXIT_FAILURE, "expecting {cmd, args} tuple"); char cmd[MAXATOMLEN]; if (ei_decode_atom(req, &req_index, cmd) < 0) errx(EXIT_FAILURE, "expecting command atom"); char resp[256]; int resp_index = sizeof(uint16_t); // Space for payload size ei_encode_version(resp, &resp_index); if (strcmp(cmd, "read") == 0) { long int len; if (ei_decode_long(req, &req_index, &len) < 0 || len < 1 || len > I2C_SMBUS_BLOCK_MAX) errx(EXIT_FAILURE, "read amount: min=1, max=%d", I2C_SMBUS_BLOCK_MAX); char data[I2C_SMBUS_BLOCK_MAX]; if (i2c_transfer(i2c, 0, 0, data, len)) ei_encode_binary(resp, &resp_index, data,len); else { ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "error"); ei_encode_atom(resp, &resp_index, "i2c_read_failed"); } } else if (strcmp(cmd, "write") == 0) { char data[I2C_SMBUS_BLOCK_MAX]; int len; int type; long llen; if (ei_get_type(req, &req_index, &type, &len) < 0 || type != ERL_BINARY_EXT || len < 1 || len > I2C_SMBUS_BLOCK_MAX || ei_decode_binary(req, &req_index, &data, &llen) < 0) errx(EXIT_FAILURE, "write: need a binary between 1 and %d bytes", I2C_SMBUS_BLOCK_MAX); if (i2c_transfer(i2c, data, len, 0, 0)) ei_encode_atom(resp, &resp_index, "ok"); else { ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "error"); ei_encode_atom(resp, &resp_index, "i2c_write_failed"); } } else if (strcmp(cmd, "wrrd") == 0) { char write_data[I2C_SMBUS_BLOCK_MAX]; char read_data[I2C_SMBUS_BLOCK_MAX]; int write_len; long int read_len; int type; long llen; if (ei_decode_tuple_header(req, &req_index, &arity) < 0 || arity != 2) errx(EXIT_FAILURE, "wrrd: expecting {write_data, read_count} tuple"); if (ei_get_type(req, &req_index, &type, &write_len) < 0 || type != ERL_BINARY_EXT || write_len < 1 || write_len > I2C_SMBUS_BLOCK_MAX || ei_decode_binary(req, &req_index, &write_data, &llen) < 0) errx(EXIT_FAILURE, "wrrd: need a binary between 1 and %d bytes", I2C_SMBUS_BLOCK_MAX); if (ei_decode_long(req, &req_index, &read_len) < 0 || read_len < 1 || read_len > I2C_SMBUS_BLOCK_MAX) errx(EXIT_FAILURE, "wrrd: read amount: min=1, max=%d", I2C_SMBUS_BLOCK_MAX); if (i2c_transfer(i2c, write_data, write_len, read_data, read_len)) ei_encode_binary(resp, &resp_index, read_data, read_len); else { ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "error"); ei_encode_atom(resp, &resp_index, "i2c_wrrd_failed"); } } else errx(EXIT_FAILURE, "unknown command: %s", cmd); debug("sending response: %d bytes", resp_index); erlcmd_send(resp, resp_index); }
static int get_str(str *str_ptr, erl_rpc_ctx_t *ctx, int reads, int autoconvert) { int type, size; char *p; double d; long n; if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)) { erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads); return -1; } switch(type) { case ERL_FLOAT_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_double(ctx->request->buff,&ctx->request_index,&d)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } p=(char*)pkg_malloc(MAX_DIGITS); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } str_ptr->len=snprintf(p, MAX_DIGITS, "%f", d); str_ptr->s = p; break; case ERL_STRING_EXT: case ERL_LIST_EXT: case ERL_BINARY_EXT: /* allocate buffer */ p = (char*)pkg_malloc(size+1); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } if(ei_decode_strorbin(ctx->request->buff,&ctx->request_index,size+1,p)) { erl_rpc_fault(ctx,400, "Can't read parameter #%d",reads); return -1; } str_ptr->s=p; str_ptr->len=size; break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_long(ctx->request->buff,&ctx->request_index,&n)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } p=(char*)pkg_malloc(MAX_DIGITS); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } str_ptr->len=snprintf(p, MAX_DIGITS, "%ld", n); str_ptr->s = p; break; default: erl_rpc_fault(ctx,400,"Can't convert to string parameter #%d.",reads); return -1; } LM_ERR("parameter #%d:<%.*s>\n",reads,STR_FMT(str_ptr)); return 0; }
static bool decode_proplist(void *port, PropList **plist, int *szalloc, const char *buf, int *index) { int type, size; long item_type; bool succeess = false; PropList *list_head = (*plist = plist_alloc(port, szalloc)); if (DECODED(ei_get_type(buf, index, &type, &size))) { int list_arity = 0; if (DECODED(ei_decode_list_header(buf, index, &list_arity))) { ASSERT(size == list_arity); if (list_arity < 1) { succeess = false; } else { for (int i = 0; i < list_arity; i++) { if (!DECODED(ei_decode_tuple_header(buf, index, &size))) { return false; } if ((list_head->next = plist_alloc(port, szalloc)) != NULL) { *plist = (list_head = list_head->next); list_head->type = EDBC_OCI_DRV_TYPE_UNASSIGNED; char *pkey = safe_driver_alloc(port, sizeof(char) * MAXATOMLEN); if (!DECODED(ei_decode_atom(buf, index, pkey))) { return false; } list_head->name = pkey; if (!DECODED(ei_decode_long(buf, index, &item_type))) { return false; } list_head->type = item_type; switch (item_type) { case EDBC_OCI_DRV_TYPE_STRING: { if(!DECODED(ei_get_type(buf, index, &type, &size))) { return false; } ASSERT(type == ERL_STRING_EXT); TextBuffer *ptxt = zalloc(port, sizeof(TextBuffer)); char *pval = safe_driver_alloc(port, sizeof(char) * ptxt->size); ptxt->size = size + 1; ptxt->data = pval; list_head->value.buffer = ptxt; if (!DECODED(ei_decode_string(buf, index, pval))) { return false; } break; } case EDBC_OCI_DRV_TYPE_LONG: { long num; if (!DECODED(ei_decode_long(buf, index, &num))) { return false; } list_head->value.number = num; break; } default: // make error? break; } } } } } } return false; };
int next_long(GEOSCommand *command, long *value) { return ei_decode_long(command->param_bytes, &command->index, value); }
int toInteger() const { int idx = _index; long p; ei_decode_long(_buf, &idx, &p); return p; }
int next_size_t(GEOSCommand *command, size_t *value) { return ei_decode_long(command->param_bytes, &command->index, (long *) value); }
/* decode the buffer again before showing it */ int ei_show_sendmsg(FILE *stream, const char *header, const char *msgbuf) { erlang_msg msg; const char *mbuf = NULL; int index = 0; int arity = 0; int version = 0; /* skip five bytes */ index = 5; ei_decode_version(header,&index,&version); ei_decode_tuple_header(header,&index,&arity); ei_decode_long(header,&index,&msg.msgtype); switch (msg.msgtype) { case ERL_SEND: if (ei_decode_atom(header,&index,msg.cookie) || ei_decode_pid(header,&index,&msg.to)) return -1; mbuf = msgbuf; break; case ERL_SEND_TT: if (ei_decode_atom(header,&index,msg.cookie) || ei_decode_pid(header,&index,&msg.to) || ei_decode_trace(header,&index,&msg.token)) return -1; mbuf = msgbuf; break; case ERL_REG_SEND: if (ei_decode_pid(header,&index,&msg.from) || ei_decode_atom(header,&index,msg.cookie) || ei_decode_atom(header,&index,msg.toname)) return -1; mbuf = msgbuf; break; case ERL_REG_SEND_TT: if (ei_decode_pid(header,&index,&msg.from) || ei_decode_atom(header,&index,msg.cookie) || ei_decode_atom(header,&index,msg.toname) || ei_decode_trace(header,&index,&msg.token)) return -1; mbuf = msgbuf; break; case ERL_EXIT: case ERL_EXIT2: if (ei_decode_pid(header,&index,&msg.from) || ei_decode_pid(header,&index,&msg.to)) return -1; mbuf = header+index; case ERL_EXIT_TT: case ERL_EXIT2_TT: if (ei_decode_pid(header,&index,&msg.from) || ei_decode_pid(header,&index,&msg.to) || ei_decode_trace(header,&index,&msg.token)) return -1; mbuf = header+index; break; case ERL_LINK: case ERL_UNLINK: case ERL_GROUP_LEADER: if (ei_decode_pid(header,&index,&msg.from) || ei_decode_pid(header,&index,&msg.to)) return -1; mbuf = header; break; case ERL_NODE_LINK: /* nothing to do */ mbuf = header; break; default: break; } show_msg(stream, 1, &msg, mbuf); return 0; }
/** * Query a table for specified rows. * \param _h structure representing database connection * \param _k key names * \param _op operators *\param _v values of the keys that must match * \param _c column names to return * \param _n number of key=values pairs to compare * \param _nc number of columns to return * \param _o order by the specified column * \param _r pointer to a structure representing the result * \return zero on success, negative value on failure */ int erlang_srdb1_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op, const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc, const db_key_t _o, db1_res_t** _r) { ei_x_buff argbuf,retbuf; int retcode,i,j,x; int n_cols,n_rows,len; db1_res_t *res; db_row_t *rows = NULL, *row; db_val_t *val; char atom[MAXATOMLEN], *p; ei_term term; int ei_type,size; str *sname; if (!_h || !_r) { LM_ERR("invalid parameter value\n"); return -1; } *_r=NULL; LM_DBG("erlang_srdb1_query table %.*s\n",CON_TABLE(_h)->len, CON_TABLE(_h)->s); ei_x_new(&argbuf); //encode tuple {db_op, table, [cols], [params]} ei_x_encode_tuple_header(&argbuf, 5); ei_x_encode_atom(&argbuf,"select"); ei_x_encode_atom_len(&argbuf,CON_TABLE(_h)->s,CON_TABLE(_h)->len); srdb1_encode_c(_c, _nc, &argbuf); srdb1_encode_k(_k, _op, _v, _n, &argbuf); // ei_x_encode_atom_len(&argbuf,_o->s,_o->len); ei_x_encode_list_header(&argbuf, 0); retcode=erl_bind.do_erlang_call(&(CON_ERLANG(_h)->con),&(CON_ERLANG(_h)->regname), &argbuf, &retbuf); ei_x_free(&argbuf); if (retcode<0) { if(retbuf.buff) shm_free(retbuf.buff); return retcode; } // we have a tuple there: ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &i); x=retbuf.index; ei_skip_term(retbuf.buff, &x); LM_DBG("erlang_srdb1_query: position of end of field list should be %d\n",x); //first is list of 5-element tuples containing name and type of field ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_cols); LM_DBG("erlang_srdb1_query: length -f field_list is %d\n",n_cols); res=db_new_result(); if (db_allocate_columns(res, n_cols) != 0) { LM_ERR("erlang_srdb1_query: db_allocate_columns failed\n"); goto error; } RES_COL_N(res) = n_cols; for(i=0; i < n_cols; i++) { x=retbuf.index; ei_skip_term(retbuf.buff, &x); LM_DBG("erlang_srdb1_query: position of end of this field should be %d\n",x); ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j); if( j!=5) LM_ERR("erlang_srdb1_query name&type list element tuple is not 5\n"); ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //1 name len=strlen(atom); sname = (str*)pkg_malloc(sizeof(str)+len+1); if (!sname) { LM_ERR("no private memory left\n"); goto error; } sname->len = len; sname->s = (char*)sname + sizeof(str); memcpy(sname->s, atom, len); sname->s[len] = '\0'; RES_NAMES(res)[i] = sname; LM_DBG("decoded header %d, fieled 1: %s\n",i,atom); ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //2 type atom if(strcmp("int",atom)==0) { RES_TYPES(res)[i]=DB1_INT; } if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_STRING; } if(strcmp("float",atom)==0) { RES_TYPES(res)[i]=DB1_DOUBLE; } if(strcmp("datetime",atom)==0) { RES_TYPES(res)[i]=DB1_DATETIME; } // if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_BLOB; } ei_skip_term(retbuf.buff, &(retbuf.index)); //3 size (ignored) ei_skip_term(retbuf.buff, &(retbuf.index)); //4 default value (ignored) ei_skip_term(retbuf.buff, &(retbuf.index)); //3 null status (ignored) LM_DBG("end of %d record: %d\n",i,retbuf.index); } ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail, LM_DBG("erlang_srdb1_query: position after scanning is %d\n",retbuf.index); //now rows, list of tuples ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_rows); LM_DBG("erlang_srdb1_query values list size is %d\n",n_rows); if (n_rows<=0) { LM_DBG("erlang_srdb1_query no rows returned\n"); RES_ROWS(res) = NULL; RES_NUM_ROWS(res)=0; *_r=res; return 0; } RES_NUM_ROWS(res)=n_rows; rows = pkg_realloc(rows, sizeof(db_row_t) * n_rows); if (rows == NULL) { LM_ERR("erlang_srdb1_query: pkg_realloc rows failed\n"); goto error; } RES_ROWS(res) = rows; for(i=0; i < n_rows; i++) { RES_ROW_N(res)=i+1; row = &RES_ROWS(res)[i]; if (db_allocate_row(res, row) != 0) { LM_ERR("erlang_srdb1_query: db_allocate_row failed for row %d\n",i); goto error; } ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j); if(j!=n_cols) { LM_ERR("erlang_srdb1_query: mismatch:values list element tuple size is %d n_cols from header was %d\n",j, n_cols); } for (j = 0, val = ROW_VALUES(row); j < RES_COL_N(res); j++, val++) { VAL_TYPE(val) = RES_TYPES(res)[j]; VAL_NULL(val) = 0; VAL_FREE(val) = 0; retcode=ei_get_type_internal(retbuf.buff, &(retbuf.index), &ei_type, &size); if (retcode < 0) { LM_ERR("erlang_srdb1_query: error getting type for element %d %d\n",i,j); goto error; } LM_DBG("erlang_srdb1_query: element %d %d ei_type=%d size=%d\n",i,j,ei_type, size); switch(ei_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: retcode=ei_decode_long(retbuf.buff, &(retbuf.index), &VAL_INT(val)); if(retcode < 0) goto error; LM_DBG("decoded interger %d\n",VAL_INT(val)); break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: retcode=ei_decode_double(retbuf.buff, &(retbuf.index), &VAL_DOUBLE(val)); if(retcode < 0) goto error; LM_DBG("decoded float %f\n",VAL_DOUBLE(val)); break; case ERL_ATOM_EXT: case ERL_SMALL_ATOM_EXT: case ERL_ATOM_UTF8_EXT: case ERL_SMALL_ATOM_UTF8_EXT: p=pkg_malloc(size+1); if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; } retcode=ei_decode_atom(retbuf.buff, &(retbuf.index), p); if(retcode < 0) { pkg_free(p); goto error; } LM_DBG("decoded small_atom_utf %s\n",p); VAL_STRING(val)=p; VAL_FREE(val)=1; break; case ERL_STRING_EXT: p=pkg_malloc(size+1); if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; } retcode=ei_decode_string(retbuf.buff, &(retbuf.index), p); if(retcode < 0) { pkg_free(p); goto error; } LM_DBG("decoded string %s\n",p); VAL_STRING(val)=p; VAL_FREE(val)=1; break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: LM_DBG("got tuple)\n"); if (VAL_TYPE(val)==DB1_DATETIME) { struct tm tm; LM_DBG("and col type is datetime\n"); retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_year);tm.tm_year -=1900; if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mon); tm.tm_mon -=1; if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mday); if(retcode < 0) goto error; retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_hour); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_min); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_sec); if(retcode < 0) goto error; VAL_TIME(val)=mktime(&tm); break; } LM_ERR("erlang_srdb1_query: got tuple but valtype is not datetime element %d in row %d in response\n",j,i); break; case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: case ERL_PORT_EXT: case ERL_PID_EXT: case ERL_NIL_EXT: case ERL_LIST_EXT: case ERL_BINARY_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: case ERL_NEW_FUN_EXT: case ERL_FUN_EXT: default: LM_ERR("erlang_srdb1_query: don't know how to handle element %d in row %d in response\n",j,i); } } } ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail, *_r=res; return 0; error: if (res) db_free_result(res); LM_ERR("erlang_srdb1_query: Failed\n"); return -1; }