int find_first_gteq(char* buf, int pos, void* key, compare_info* lu, int at_least) { int list_arity, inner_arity; int list_pos = 0, cmp_val; off_t pair_pos = 0; if(ei_decode_list_header(buf, &pos, &list_arity) < 0) { return ERROR_PARSE; } while(list_pos < list_arity) { //{<<"key", some other term} pair_pos = pos; //Save pos of kv/kp pair tuple if(ei_decode_tuple_header(buf, &pos, &inner_arity) < 0) { return ERROR_PARSE; } lu->last_cmp_key = (*lu->from_ext)(lu, buf,pos); cmp_val = (*lu->compare) (lu->last_cmp_key, key); lu->last_cmp_val = cmp_val; lu->list_pos = list_pos; if(cmp_val >= 0 && list_pos >= at_least) { break; } ei_skip_term(buf, &pos); //skip over the key ei_skip_term(buf, &pos); //skip over the value list_pos++; } return pair_pos; }
int mr_push_kv_range(char* buf, int pos, int bound, int end, couchfile_modify_result *dst) { int current = 0; int term_begin_pos; ei_decode_list_header(buf, &pos, NULL); int errcode = 0; while(current < end && errcode == 0) { term_begin_pos = pos; ei_skip_term(buf, &pos); if(current >= bound) { //Parse KV pair into a leaf_value couchfile_leaf_value *lv = malloc(sizeof(couchfile_leaf_value)); lv->term.buf = buf+term_begin_pos; lv->term.size = pos-term_begin_pos; nodelist* n = make_nodelist(); dst->values_end->next = n; dst->values_end = n; n->value.leaf = lv; dst->node_len += lv->term.size; dst->count++; errcode = maybe_flush(dst); } current++; } return errcode; }
void term_to_buf(eterm_buf *dst, char* buf, int *pos) { int start = *pos; ei_skip_term(buf, pos); dst->buf = buf + start; dst->size = *pos - start; }
eqmlTerm operator[] (int elem) const { int idx = _index; for (int i = 1; i < elem; ++i) ei_skip_term(_buf, &idx); return eqmlTerm(_buf, idx); }
/* * Find member in tuple (aka RPC struct) */ static int find_member(erl_rpc_ctx_t *ctx, int arity, const char* member_name) { int index,i=0; int type,size; char key_name[MAXATOMLEN]; /* save position */ index = ctx->request_index; /* { name, Value, name, Value...} */ while (i < arity) { if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)) { erl_rpc_fault(ctx,400,"Bad struct member type"); goto error; } if(ei_decode_atom(ctx->request->buff,&ctx->request_index, key_name)) { erl_rpc_fault(ctx,400,"Bad member name"); goto error; } if (strcasecmp(member_name,key_name)) { if(ei_skip_term(ctx->request->buff,&ctx->request_index)) { erl_rpc_fault(ctx,400,"Unexpected end of struct tuple"); goto error; } continue; } else { /* return at current position */ return 0; } i++; } erl_rpc_fault(ctx,400, "Member %s not found",member_name); error: ctx->request_index = index; return -1; }
void mr_push_kp_range(char* buf, int pos, int bound, int end, couchfile_modify_result *dst) { DBG("Moving items %d - %d into result.\r\n", bound, end); int current = 0; ei_decode_list_header(buf, &pos, NULL); while(current < end) { if(current >= bound) { DBG(" .... %d\r\n", current); mr_push_pointerinfo(read_pointer(buf,pos), dst); } ei_skip_term(buf, &pos); current++; } }
int ei_decode_alloc_string(char *buff, int *index, unsigned char **str, int *len) { int type = 0; EI(ei_get_type(buff, index, &type, len)); if(type == ERL_STRING_EXT) { *str = genq_alloc((sizeof(unsigned char))*(*len+1)); EIC(ei_decode_string_safe(buff, index, *str), free_alloc_string(str, len)); return 0; } else if(type == ERL_LIST_EXT || type == ERL_NIL_EXT) { // String larger than 65535 int arity = 0; EI(ei_decode_list_header(buff, index, &arity)); *str = genq_alloc((sizeof(unsigned char))*(*len+1)); int i; for(i=0; i < *len; ++i) { EIC(ei_decode_char_safe(buff, index, &(*str)[i]), free_alloc_string(str, len)); } (*str)[*len] = '\0'; if(arity > 0) { EIC(ei_skip_term(buff, index), free_alloc_string(str, len)); // skip tail } return 0; } else if(type == ERL_ATOM_EXT) { *str = genq_alloc(sizeof(unsigned char)*(*len+1)); (*str)[*len] = '\0'; EIC(ei_decode_atom_safe(buff, index, *str), free_alloc_string(str, len)); return 0; } else if(type == ERL_BINARY_EXT) { *str = genq_alloc(sizeof(unsigned char)*(*len+1)); (*str)[*len] = '\0'; long llen = 0; EIC(ei_decode_binary(buff, index, *str, &llen), free_alloc_string(str, len)); return 0; } else { LOG("ERROR unknown type %d\n", type); *len = -1; return -1; } }
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[16]; 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(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 inline int decode_and_bind_param( sqlite3_drv_t *drv, char *buffer, int *p_index, sqlite3_stmt *statement, int param_index, int *p_type, int *p_size) { int result; sqlite3_int64 int64_val; double double_val; char* char_buf_val; long bin_size; ei_get_type(buffer, p_index, p_type, p_size); switch (*p_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: ei_decode_longlong(buffer, p_index, &int64_val); result = sqlite3_bind_int64(statement, param_index, int64_val); break; case ERL_FLOAT_EXT: #ifdef NEW_FLOAT_EXT case NEW_FLOAT_EXT: // what's the difference? #endif ei_decode_double(buffer, p_index, &double_val); result = sqlite3_bind_double(statement, param_index, double_val); break; case ERL_ATOM_EXT: // include space for null separator char_buf_val = driver_alloc((*p_size + 1) * sizeof(char)); ei_decode_atom(buffer, p_index, char_buf_val); if (strncmp(char_buf_val, "null", 5) == 0) { result = sqlite3_bind_null(statement, param_index); } else { output_error(drv, SQLITE_MISUSE, "Non-null atom as parameter"); return 1; } break; case ERL_STRING_EXT: // include space for null separator char_buf_val = driver_alloc((*p_size + 1) * sizeof(char)); ei_decode_string(buffer, p_index, char_buf_val); result = sqlite3_bind_text(statement, param_index, char_buf_val, *p_size, &driver_free_fun); break; case ERL_BINARY_EXT: char_buf_val = driver_alloc(*p_size * sizeof(char)); ei_decode_binary(buffer, p_index, char_buf_val, &bin_size); result = sqlite3_bind_text(statement, param_index, char_buf_val, *p_size, &driver_free_fun); break; case ERL_SMALL_TUPLE_EXT: // assume this is {blob, Blob} ei_get_type(buffer, p_index, p_type, p_size); ei_decode_tuple_header(buffer, p_index, p_size); if (*p_size != 2) { output_error(drv, SQLITE_MISUSE, "bad parameter type"); return 1; } ei_skip_term(buffer, p_index); // skipped the atom 'blob' ei_get_type(buffer, p_index, p_type, p_size); if (*p_type != ERL_BINARY_EXT) { output_error(drv, SQLITE_MISUSE, "bad parameter type"); return 1; } char_buf_val = driver_alloc(*p_size * sizeof(char)); ei_decode_binary(buffer, p_index, char_buf_val, &bin_size); result = sqlite3_bind_blob(statement, param_index, char_buf_val, *p_size, &driver_free_fun); break; default: output_error(drv, SQLITE_MISUSE, "bad parameter type"); return 1; } if (result != SQLITE_OK) { output_db_error(drv); return result; } return SQLITE_OK; }
int erl_rpc_scan(erl_rpc_ctx_t* ctx, char* fmt, ...) { int* int_ptr; char** char_ptr; str* str_ptr; double* double_ptr; void** void_ptr; str s; /* helper str */ int reads = 0; int modifiers = 0; int autoconv = 0; int type,size; erl_rpc_ctx_t *handler; va_list ap; va_start(ap,fmt); while(*fmt && ctx->size) { /* optional and we at the end of decoding params */ if (ctx->optional && !ctx->size) { break; } if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)) { erl_rpc_fault(ctx,400,"Can't determine data type, for parameter #%d",reads); LM_ERR("Can't determine data type, for parameter #%d",reads); goto error; } switch(*fmt) { case '*': /* start of optional parameters */ modifiers++; ctx->optional = 1; reads++; fmt++; continue; case '.': /* autoconvert */ modifiers++; autoconv = 1; reads++; fmt++; continue; case 'b': /* Bool */ case 't': /* Date and time */ case 'd': /* Integer */ int_ptr = va_arg(ap, int*); if (get_int(int_ptr,ctx,reads,autoconv)) { goto error; } break; case 'f': /* double */ double_ptr = va_arg(ap, double*); if (get_double(double_ptr,ctx,reads,autoconv)) { goto error; } break; case 'S': /* str structure */ str_ptr = va_arg(ap, str*); if (get_str(str_ptr,ctx,reads,autoconv)) { goto error; } break; case 's':/* zero terminated string */ char_ptr = va_arg(ap, char **); if (get_str(&s,ctx,reads,autoconv)) { goto error; } *char_ptr = s.s; break; case '{': void_ptr = va_arg(ap,void**); if (type!=ERL_SMALL_TUPLE_EXT && type!=ERL_LARGE_TUPLE_EXT) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d (t=%c).",reads,type); goto error; } handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t)); if (!handler) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); goto error; } *handler = *ctx; /* copy state */ handler->optional = 0; handler->no_params = 0; handler->size = size; /* size of tuple */ if (add_to_recycle_bin(JUNK_PKGCHAR,handler,ctx)) { pkg_free(handler); goto error; } /* skip element */ if (ei_skip_term(ctx->request->buff,&ctx->request_index)) { goto error; } /* go where we stopped */ *(erl_rpc_ctx_t**)void_ptr = handler; break; default: LM_ERR("Invalid parameter type in formatting string: %c\n", *fmt); erl_rpc_fault(ctx, 500, "Server Internal Error (Invalid Formatting String)"); goto error; } autoconv = 0; /* reset autovoncersion for next parameter */ reads++; fmt++; ctx->size--; } va_end(ap); return reads-modifiers; error: va_end(ap); return -(reads-modifiers); }
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_internal(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: 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: 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: 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_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; } }
void decode_encode(struct Type** tv, int nobj) { struct my_obj objv[10]; int oix = 0; char* packet; char* inp; char* outp; char out_buf[BUFSZ]; int size1, size2, size3; int err, i; ei_x_buff arg; packet = read_packet(NULL); inp = packet+1; outp = out_buf; ei_x_new(&arg); for (i=0; i<nobj; i++) { struct Type* t = tv[i]; MESSAGE("ei_decode_%s, arg is type %s", t->name, t->type); size1 = 0; err = t->ei_decode_fp(inp, &size1, NULL); if (err != 0) { if (err != -1) { fail("decode returned non zero but not -1"); } else { fail("decode returned non zero"); } return; } if (size1 < 1) { fail("size is < 1"); return; } if (size1 > BUFSZ) { fail("size is > BUFSZ"); return; } size2 = 0; objv[oix].nterms = 0; objv[oix].startp = inp; err = t->ei_decode_fp(inp, &size2, &objv[oix]); if (err != 0) { if (err != -1) { fail("decode returned non zero but not -1"); } else { fail("decode returned non zero"); } return; } if (size1 != size2) { MESSAGE("size1 = %d, size2 = %d\n",size1,size2); fail("decode sizes differs"); return; } if (!objv[oix].nterms) { size2 = 0; err = ei_skip_term(inp, &size2); if (err != 0) { fail("ei_skip_term returned non zero"); return; } if (size1 != size2) { MESSAGE("size1 = %d, size2 = %d\n",size1,size2); fail("skip size differs"); return; } } MESSAGE("ei_encode_%s buf is NULL, arg is type %s", t->name, t->type); size2 = 0; err = t->ei_encode_fp(NULL, &size2, &objv[oix]); if (err != 0) { if (err != -1) { fail("size calculation returned non zero but not -1"); return; } else { fail("size calculation returned non zero"); return; } } if (size1 != size2) { MESSAGE("size1 = %d, size2 = %d\n",size1,size2); fail("decode and encode size differs when buf is NULL"); return; } MESSAGE("ei_encode_%s, arg is type %s", t->name, t->type); size3 = 0; err = t->ei_encode_fp(outp, &size3, &objv[oix]); if (err != 0) { if (err != -1) { fail("returned non zero but not -1"); } else { fail("returned non zero"); } return; } if (size1 != size3) { MESSAGE("size1 = %d, size2 = %d\n",size1,size3); fail("decode and encode size differs"); return; } MESSAGE("ei_x_encode_%s, arg is type %s", t->name, t->type); err = t->ei_x_encode_fp(&arg, &objv[oix]); if (err != 0) { if (err != -1) { fail("returned non zero but not -1"); } else { fail("returned non zero"); } ei_x_free(&arg); return; } if (arg.index < 1) { fail("size is < 1"); ei_x_free(&arg); return; } inp += size1; outp += size1; if (objv[oix].nterms) { /* container term */ if (++oix >= sizeof(objv)/sizeof(*objv)) fail("Term too deep"); } else { /* "leaf" term */ while (oix > 0) { if (--(objv[oix - 1].nterms) == 0) { /* last element in container */ --oix; size2 = 0; err = ei_skip_term(objv[oix].startp, &size2); if (err != 0) { fail("ei_skip_term returned non zero"); return; } if (objv[oix].startp + size2 != inp) { MESSAGE("size1 = %d, size2 = %d\n", size1, size2); fail("container skip size differs"); return; } } else break; /* more elements in container */ } } } if (oix > 0) { fail("Container not complete"); } send_buffer(out_buf, outp - out_buf); send_buffer(arg.buff, arg.index); ei_x_free(&arg); free_packet(packet); }
void dump_eterm(ei_x_buff *x) { int etype, esize, arity; long long num; char *atom; int i; char *binary; long bin_size; double fnum; ei_get_type(x->buff, &x->index, &etype, &esize); uwsgi_log("etype: %d/%c esize: %d\n", etype, etype, esize); switch(etype) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: ei_decode_longlong(x->buff, &x->index, &num); uwsgi_log("num: %lu\n", num); break; case ERL_FLOAT_EXT: ei_decode_double(x->buff, &x->index, &fnum); uwsgi_log("float: %f\n", fnum); break; case ERL_STRING_EXT: atom = uwsgi_malloc(esize+1); ei_decode_string(x->buff, &x->index, atom); uwsgi_log("string: %s\n", atom); free(atom); break; case ERL_ATOM_EXT: atom = uwsgi_malloc(esize+1); ei_decode_atom(x->buff, &x->index, atom); uwsgi_log("atom: %s\n", atom); free(atom); break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: ei_decode_tuple_header(x->buff, &x->index, &arity); for(i=0;i<arity;i++) { dump_eterm(x); } break; case ERL_LIST_EXT: case ERL_NIL_EXT: ei_decode_list_header(x->buff, &x->index, &arity); if (arity == 0) { uwsgi_log("nil value\n"); break; } for(i=0;i<arity+1;i++) { dump_eterm(x); } break; case ERL_BINARY_EXT: binary = uwsgi_malloc(esize); ei_decode_binary(x->buff, &x->index, binary, &bin_size); uwsgi_log("binary data of %d bytes\n", bin_size); free(binary); break; default: uwsgi_log("ignored...\n"); ei_skip_term(x->buff, &x->index); break; } }
void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) { int etype, esize; int arity; char *gen_call; char *module; char *call; char buffer[0xffff]; char *argv[256] ; uint16_t argvs[256] ; int argc = 0; uint16_t ret; ei_x_buff xr; erlang_ref eref; ei_get_type(x->buff, &x->index, &etype, &esize); #ifdef UWSGI_DEBUG uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT); #endif if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return; ei_decode_tuple_header(x->buff, &x->index, &arity); #ifdef UWSGI_DEBUG uwsgi_log("rpc arity %d\n", arity); #endif if (arity != 3) return ; ei_get_type(x->buff, &x->index, &etype, &esize); if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ; gen_call = uwsgi_malloc(esize); if (etype == ERL_ATOM_EXT) { ei_decode_atom(x->buff, &x->index, gen_call); } else { ei_decode_string(x->buff, &x->index, gen_call); } #ifdef UWSGI_DEBUG uwsgi_log("gen call = %s\n", gen_call); #endif ei_get_type(x->buff, &x->index, &etype, &esize); if (etype != ERL_SMALL_TUPLE_EXT) return ; ei_decode_tuple_header(x->buff, &x->index, &arity); if (arity != 2) return ; ei_get_type(x->buff, &x->index, &etype, &esize); ei_skip_term(x->buff, &x->index); ei_get_type(x->buff, &x->index, &etype, &esize); ei_decode_ref(x->buff, &x->index, &eref); ei_get_type(x->buff, &x->index, &etype, &esize); module = uwsgi_malloc(esize); if (etype == ERL_ATOM_EXT) { ei_decode_atom(x->buff, &x->index, module); } else { ei_decode_string(x->buff, &x->index, module); } ei_get_type(x->buff, &x->index, &etype, &esize); if (etype != ERL_SMALL_TUPLE_EXT) return ; ei_decode_tuple_header(x->buff, &x->index, &arity); #ifdef UWSGI_DEBUG uwsgi_log("arity: %d\n", arity); #endif if (arity != 5) return ; ei_get_type(x->buff, &x->index, &etype, &esize); char *method = uwsgi_malloc(esize); if (etype == ERL_ATOM_EXT) { ei_decode_atom(x->buff, &x->index, method); } else { ei_decode_string(x->buff, &x->index, method); } if (strcmp(method, "call")) return; ei_get_type(x->buff, &x->index, &etype, &esize); if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ; module = uwsgi_malloc(esize); if (etype == ERL_ATOM_EXT) { ei_decode_atom(x->buff, &x->index, module); } else { ei_decode_string(x->buff, &x->index, module); } ei_get_type(x->buff, &x->index, &etype, &esize); if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ; call = uwsgi_malloc(esize); if (etype == ERL_ATOM_EXT) { ei_decode_atom(x->buff, &x->index, call); } else { ei_decode_string(x->buff, &x->index, call); } #ifdef UWSGI_DEBUG uwsgi_log("RPC %s %s\n", module, call); #endif ei_get_type(x->buff, &x->index, &etype, &esize); if (etype == ERL_ATOM_EXT) { argc = 1; argv[0] = uwsgi_malloc(esize+1); ei_decode_atom(x->buff, &x->index, argv[0]); argvs[1] = esize; } else if (etype == ERL_STRING_EXT) { argc = 1; argv[0] = uwsgi_malloc(esize+1); ei_decode_string(x->buff, &x->index, argv[0]); argvs[1] = esize; } ret = uwsgi_rpc(call, argc, argv, argvs, buffer); #ifdef UWSGI_DEBUG uwsgi_log("buffer: %.*s\n", ret, buffer); #endif ei_x_new_with_version(&xr); ei_x_encode_tuple_header(&xr, 2); //ei_x_encode_atom(&xr, "rex"); ei_x_encode_ref(&xr, &eref); ei_x_encode_string_len(&xr, buffer, ret); uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_send(fd, from, xr.buff, xr.index)); //uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_reg_send(&uerl.cnode, fd, "rex", xr.buff, xr.index)); }
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; 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 == NULL ? (erlang_pid*)NULL : &p->pid)) < 0) return -1; /* then the module (atom) */ if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0) return -1; /* then the index */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->index)) < 0) return -1; /* then the uniq */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &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); /* FIXME check result */ 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(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0) return -1; /* then the old_index */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->old_index)) < 0) return -1; /* then the old_uniq */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0) return -1; /* the the pid */ if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0) return -1; /* finally the free vars */ s += ix; n = n - (s - s0) + 1; if (p != NULL) { p->free_var_len = n; if (n > 0) { p->free_vars = malloc(n); /* FIXME check result */ memcpy(p->free_vars, s, n); } } *index += s-s0; return 0; break; default: return -1; } }
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); } }
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: case ERL_NEW_PID_EXT: if (ei_decode_pid(buf, index, NULL) < 0) return -1; break; case ERL_PORT_EXT: case ERL_NEW_PORT_EXT: if (ei_decode_port(buf, index, NULL) < 0) return -1; break; case ERL_NEW_REFERENCE_EXT: case ERL_NEWER_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_MAP_EXT: if (ei_decode_map_header(buf, index, &n) < 0) return -1; n *= 2; 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_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; } }
int modify_node(couchfile_modify_request *rq, couchfile_pointer_info *nptr, int start, int end, couchfile_modify_result *dst) { eterm_buf current_node; int curnode_pos = 0; int read_size = 0; int list_start_pos = 0; int node_len = 0; int node_bound = 0; int errcode = 0; int kpos = 0; char node_type[MAXATOMLEN + 1]; node_type[0] = 0; DBG("Enter modify_node. %d - %d\r\n", start, end); if(start == end) { return 0; } if(nptr == NULL) { current_node = empty_root; } else { if((read_size = pread_bin(rq->fd, nptr->pointer, ¤t_node.buf)) < 0) { return ERROR_READ_FILE; } current_node.size = read_size; DBG("... read node from %d\r\n", nptr->pointer); curnode_pos++; //Skip over 131. } couchfile_modify_result *local_result = make_modres(rq); ei_decode_tuple_header(current_node.buf, &curnode_pos, NULL); if(ei_decode_atom(current_node.buf, &curnode_pos, node_type) < 0) { errcode = ERROR_PARSE; goto cleanup; } list_start_pos = curnode_pos; if(ei_decode_list_header(current_node.buf, &curnode_pos, &node_len) < 0) { errcode = ERROR_PARSE; goto cleanup; } if(strcmp("kv_node", node_type) == 0) { local_result->node_type = KV_NODE; while(start < end) { DBG("act on kvnode item\r\n"); if(node_bound >= node_len) { //We're at the end of a leaf node. DBG(" ... exec action at end!\r\n"); switch(rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_action(&rq->actions[start], local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if(rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL); } break; } start++; } else { kpos = find_first_gteq(current_node.buf, list_start_pos, rq->actions[start].cmp_key, &rq->cmp, node_bound); if(kpos < 0) { errcode = ERROR_PARSE; goto cleanup; } //Add items from node_bound up to but not including the current mr_push_kv_range(current_node.buf, list_start_pos, node_bound, rq->cmp.list_pos, local_result); if(rq->cmp.last_cmp_val > 0) // Node key > action key { DBG(" Inserting action before\r\n"); switch(rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_action(&rq->actions[start], local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if(rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL); } break; } start++; node_bound = rq->cmp.list_pos; } else if(rq->cmp.last_cmp_val < 0) // Node key < action key { DBG(" -- Continue with this action\r\n"); node_bound = rq->cmp.list_pos + 1; mr_push_kv_range(current_node.buf, list_start_pos, node_bound - 1, node_bound, local_result); } else //Node key == action key { DBG(" Replacing value with action\r\n"); switch(rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_action(&rq->actions[start], local_result); node_bound = rq->cmp.list_pos + 1; break; case ACTION_REMOVE: local_result->modified = 1; node_bound = rq->cmp.list_pos + 1; break; case ACTION_FETCH: if(rq->fetch_callback) { eterm_buf cb_tmp; int cb_vpos = kpos; ei_decode_tuple_header(current_node.buf, &cb_vpos, NULL); ei_skip_term(current_node.buf, &cb_vpos); cb_tmp.buf = current_node.buf + cb_vpos; cb_tmp.size = cb_vpos; ei_skip_term(current_node.buf, &cb_vpos); cb_tmp.size = cb_vpos - cb_tmp.size; (*rq->fetch_callback)(rq, rq->actions[start].key, &cb_tmp); } node_bound = rq->cmp.list_pos; break; } start++; } } } //Push any items past the end of what we dealt with onto result. if(node_bound < node_len) { mr_push_kv_range(current_node.buf, list_start_pos, node_bound, node_len, local_result); } } else if(strcmp("kp_node", node_type) == 0) { local_result->node_type = KP_NODE; while(start < end) { kpos = find_first_gteq(current_node.buf, list_start_pos, rq->actions[start].cmp_key, &rq->cmp, node_bound); if(kpos < 0) { errcode = ERROR_PARSE; goto cleanup; } if(rq->cmp.list_pos == (node_len - 1)) //got last item in kp_node { //Push all items in node onto mr mr_push_kp_range(current_node.buf, list_start_pos, node_bound, rq->cmp.list_pos, local_result); DBG(" ...descending into final item of kpnode\r\n"); couchfile_pointer_info *desc = read_pointer(current_node.buf, kpos); errcode = modify_node(rq, desc, start, end, local_result); if(local_result->values_end->value.pointer != desc) { free(desc); } if(errcode < 0) { goto cleanup; } node_bound = node_len; break; } else { //Get all actions with key <= the key of the current item in the //kp_node //Push items in node up to but not including current onto mr mr_push_kp_range(current_node.buf, list_start_pos, node_bound, rq->cmp.list_pos - 1, local_result); int range_end = start; while(range_end < end && ((*rq->cmp.compare)(rq->actions[range_end].cmp_key, rq->cmp.last_cmp_key) <= 0)) { range_end++; } DBG(" ...descending into item %d of kpnode\r\n", rq->cmp.list_pos); node_bound = rq->cmp.list_pos + 1; couchfile_pointer_info *desc = read_pointer(current_node.buf, kpos); errcode = modify_node(rq, desc, start, range_end, local_result); if(local_result->values_end->value.pointer != desc) { free(desc); } if(errcode < 0) { goto cleanup; } start = range_end; } } DBG(".. Finished kp node, up to %d\r\n", node_bound); if(node_bound < node_len) { //Processed all the actions but haven't exhausted this kpnode. //push the rest of it onto the mr. mr_push_kp_range(current_node.buf, list_start_pos, node_bound, node_len, local_result); } } else { errcode = ERROR_PARSE; goto cleanup; } //If we've done modifications, write out the last leaf node. errcode = flush_mr(local_result); if(errcode == 0) { if(!local_result->modified && nptr != NULL) { //If we didn't do anything, give back the pointer to the original mr_push_pointerinfo(nptr, dst); } else { //Otherwise, give back the pointers to the nodes we've created. dst->modified = 1; errcode = mr_move_pointers(local_result, dst); } } cleanup: free_modres(local_result); if(current_node.buf != empty_root.buf) { free(current_node.buf); } return errcode; }
int main(void) #endif { ErlConnect conp; Erl_IpAddr thisipaddr = (Erl_IpAddr)0; FILE *fp = (FILE *)0; char* charp = "foo"; double *doublep = NULL; double doublex = 0.0; ei_cnode xec; ei_reg *ei_regp = NULL; ei_term eterm; ei_x_buff eix; erlang_big *bigp = NULL; erlang_fun efun; erlang_msg *msgp = NULL; erlang_msg emsg; erlang_pid *pidp = NULL; erlang_pid epid; erlang_port eport; erlang_ref eref; erlang_trace etrace; int *intp = NULL; int intx = 0; long *longp = NULL; long longx = 0; short creation = 0; struct ei_reg_stat *ei_reg_statp = NULL; struct ei_reg_tabstat *ei_reg_tabstatp = NULL; struct hostent *hostp = NULL; unsigned char * ucharp = (unsigned char *)"foo"; unsigned long *ulongp = NULL; unsigned long ulongx = 0; void *voidp = NULL; #ifndef VXWORKS EI_LONGLONG *longlongp = (EI_LONGLONG*)NULL; EI_LONGLONG longlongx = 0; EI_ULONGLONG *ulonglongp = (EI_ULONGLONG*)NULL; EI_ULONGLONG ulonglongx = 0; #endif enum erlang_char_encoding enc; intx = erl_errno; ei_connect_init(&xec, charp, charp, creation); ei_connect_xinit (&xec, charp, charp, charp, thisipaddr, charp, creation); ei_connect(&xec, charp); ei_xconnect (&xec, thisipaddr, charp); ei_receive(intx, ucharp, intx); ei_receive_msg(intx, &emsg, &eix); ei_xreceive_msg(intx, &emsg, &eix); ei_send(intx, &epid, charp, intx); ei_reg_send(&xec, intx, charp, charp, intx); ei_rpc(&xec, intx, charp, charp, charp, intx, &eix); ei_rpc_to(&xec, intx, charp, charp, charp, intx); ei_rpc_from(&xec, intx, intx, &emsg, &eix); ei_publish(&xec, intx); ei_accept(&xec, intx, &conp); ei_unpublish(&xec); ei_thisnodename(&xec); ei_thishostname(&xec); ei_thisalivename(&xec); ei_self(&xec); ei_gethostbyname(charp); ei_gethostbyaddr(charp, intx, intx); ei_gethostbyname_r(charp, hostp, charp, intx, intp); ei_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp); ei_encode_version(charp, intp); ei_x_encode_version(&eix); ei_encode_long(charp, intp, longx); ei_x_encode_long(&eix, longx); ei_encode_ulong(charp, intp, ulongx); ei_x_encode_ulong(&eix, ulongx); ei_encode_double(charp, intp, doublex); ei_x_encode_double(&eix, doublex); ei_encode_boolean(charp, intp, intx); ei_x_encode_boolean(&eix, intx); ei_encode_char(charp, intp, 'a'); ei_x_encode_char(&eix, 'a'); ei_encode_string(charp, intp, charp); ei_encode_string_len(charp, intp, charp, intx); ei_x_encode_string(&eix, charp); ei_x_encode_string_len(&eix, charp, intx); ei_encode_atom(charp, intp, charp); ei_encode_atom_as(charp, intp, charp, ERLANG_LATIN1, ERLANG_UTF8); ei_encode_atom_len(charp, intp, charp, intx); ei_encode_atom_len_as(charp, intp, charp, intx, ERLANG_ASCII, ERLANG_LATIN1); ei_x_encode_atom(&eix, charp); ei_x_encode_atom_as(&eix, charp, ERLANG_LATIN1, ERLANG_UTF8); ei_x_encode_atom_len(&eix, charp, intx); ei_x_encode_atom_len_as(&eix, charp, intx, ERLANG_LATIN1, ERLANG_UTF8); ei_encode_binary(charp, intp, (void *)0, longx); ei_x_encode_binary(&eix, (void*)0, intx); ei_encode_pid(charp, intp, &epid); ei_x_encode_pid(&eix, &epid); ei_encode_fun(charp, intp, &efun); ei_x_encode_fun(&eix, &efun); ei_encode_port(charp, intp, &eport); ei_x_encode_port(&eix, &eport); ei_encode_ref(charp, intp, &eref); ei_x_encode_ref(&eix, &eref); ei_encode_trace(charp, intp, &etrace); ei_x_encode_trace(&eix, &etrace); ei_encode_tuple_header(charp, intp, intx); ei_x_encode_tuple_header(&eix, longx); ei_encode_list_header(charp, intp, intx); ei_x_encode_list_header(&eix, longx); /* #define ei_encode_empty_list(buf,i) ei_encode_list_header(buf,i,0) */ ei_x_encode_empty_list(&eix); ei_get_type(charp, intp, intp, intp); ei_get_type_internal(charp, intp, intp, intp); ei_decode_version(charp, intp, intp); ei_decode_long(charp, intp, longp); ei_decode_ulong(charp, intp, ulongp); ei_decode_double(charp, intp, doublep); ei_decode_boolean(charp, intp, intp); ei_decode_char(charp, intp, charp); ei_decode_string(charp, intp, charp); ei_decode_atom(charp, intp, charp); ei_decode_atom_as(charp, intp, charp, MAXATOMLEN_UTF8, ERLANG_WHATEVER, &enc, &enc); ei_decode_binary(charp, intp, (void *)0, longp); ei_decode_fun(charp, intp, &efun); free_fun(&efun); ei_decode_pid(charp, intp, &epid); ei_decode_port(charp, intp, &eport); ei_decode_ref(charp, intp, &eref); ei_decode_trace(charp, intp, &etrace); ei_decode_tuple_header(charp, intp, intp); ei_decode_list_header(charp, intp, intp); ei_decode_ei_term(charp, intp, &eterm); ei_print_term(fp, charp, intp); ei_s_print_term(&charp, charp, intp); ei_x_format(&eix, charp); ei_x_format_wo_ver(&eix, charp); ei_x_new(&eix); ei_x_new_with_version(&eix); ei_x_free(&eix); ei_x_append(&eix, &eix); ei_x_append_buf(&eix, charp, intx); ei_skip_term(charp, intp); ei_reg_open(intx); ei_reg_resize(ei_regp, intx); ei_reg_close(ei_regp); ei_reg_setival(ei_regp, charp, longx); ei_reg_setfval(ei_regp, charp, doublex); ei_reg_setsval(ei_regp, charp, charp); ei_reg_setpval(ei_regp, charp, voidp, intx); ei_reg_setval(ei_regp, charp, intx); ei_reg_getival(ei_regp, charp); ei_reg_getfval(ei_regp, charp); ei_reg_getsval(ei_regp, charp); ei_reg_getpval(ei_regp, charp, intp); ei_reg_getval(ei_regp, charp, intx); ei_reg_markdirty(ei_regp, charp); ei_reg_delete(ei_regp, charp); ei_reg_stat(ei_regp, charp, ei_reg_statp); ei_reg_tabstat(ei_regp, ei_reg_tabstatp); ei_reg_dump(intx, ei_regp, charp, intx); ei_reg_restore(intx, ei_regp, charp); ei_reg_purge(ei_regp); #if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP) { mpz_t obj; ei_decode_bignum(charp, intp, obj); ei_encode_bignum(charp, intp, obj); ei_x_encode_bignum(&eix, obj); } #endif /* HAVE_GMP_H && HAVE_LIBGMP */ #ifndef VXWORKS ei_decode_longlong(charp, intp, longlongp); ei_decode_ulonglong(charp, intp, ulonglongp); ei_encode_longlong(charp, intp, longlongx); ei_encode_ulonglong(charp, intp, ulonglongx); ei_x_encode_longlong(&eix, longlongx); ei_x_encode_ulonglong(&eix, ulonglongx); #endif #ifdef USE_EI_UNDOCUMENTED ei_decode_intlist(charp, intp, longp, intp); ei_receive_encoded(intx, &charp, intp, msgp, intp); ei_send_encoded(intx, pidp, charp, intx); ei_send_reg_encoded(intx, pidp, charp, charp, intx); ei_decode_big(charp, intp, bigp); ei_big_comp(bigp, bigp); ei_big_to_double(bigp, doublep); ei_small_to_big(intx, bigp); ei_alloc_big(intx); ei_free_big(bigp); #endif /* USE_EI_UNDOCUMENTED */ return BUFSIZ + EAGAIN + EHOSTUNREACH + EIO + EI_BIN + EI_DELET + EI_DIRTY + EI_FLT + EI_FORCE + EI_INT + EI_NOPURGE + EI_STR + EMSGSIZE + ENOMEM + ERL_ERROR + ERL_EXIT + ERL_LINK + ERL_MSG + ERL_NO_TIMEOUT + ERL_REG_SEND + ERL_SEND + ERL_TICK + ERL_TIMEOUT + ERL_UNLINK + ETIMEDOUT + MAXATOMLEN; }
/** * 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; }