Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
0
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);
}
Пример #4
0
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);
  }
}
Пример #5
0
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;
}
Пример #6
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);
  }
}
Пример #7
0
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;
};
Пример #8
0
/*
 * 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;
}
Пример #9
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;
}
Пример #10
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;
    }
}
Пример #11
0
Файл: rec.c Проект: oliv3/phaspa
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;
}
Пример #12
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;
    }
}
Пример #13
0
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, &param_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;
}
Пример #14
0
Файл: eirecv.c Проект: caox/otp
/* 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;
}
Пример #15
0
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);
}
Пример #16
0
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;
}
Пример #17
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;
};
Пример #18
0
int next_long(GEOSCommand *command, long *value) {
        return ei_decode_long(command->param_bytes, &command->index, value);
}
Пример #19
0
	int toInteger() const
	{ 
		int idx = _index; long p;
		ei_decode_long(_buf, &idx, &p);
		return p;
	}
Пример #20
0
int next_size_t(GEOSCommand *command, size_t *value) {
         return ei_decode_long(command->param_bytes, &command->index, (long *) value);
}
Пример #21
0
/* 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;
}