Пример #1
0
void binrpc_free_rpc_array(struct binrpc_val* a, int size)
{
	int r;
	for (r=0; r<size; r++){
		if (a[r].name.s)
			binrpc_free(a[r].name.s);
		if ((a[r].type==BINRPC_T_STR || a[r].type==BINRPC_T_BYTES) &&
				a[r].u.strval.s){
			binrpc_free(a[r].u.strval.s);
		}
	}
	binrpc_free(a);
}
Пример #2
0
void binrpc_close_connection(struct binrpc_handle* handle)
{
	if (handle->socket != -1) {
		close(handle->socket);
		handle->socket = -1;
	}
	if (handle->buf) {
		binrpc_free(handle->buf);
		handle->buf = NULL;
	}
}
Пример #3
0
int binrpc_parse_response(struct binrpc_val** vals, int* val_count,
	struct binrpc_response_handle *resp_handle)
{
	struct binrpc_val val;
	unsigned char *p, *end;
	int ret, i;

	resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0;

	if (*val_count==0){
		*val_count=VAL_ARRAY_CHUNK; /* start with a reasonable size */
	}
	*vals = (struct binrpc_val*) binrpc_malloc(*val_count*sizeof(**vals));
	if (*vals == 0)
		goto error_mem;
	p = resp_handle->reply_buf;
	end = p + resp_handle->in_pkt.tlen;
	i=0;
	
	/* read body */
	while(p < end){
		val.type = BINRPC_T_ALL;
		val.name.s = 0;
		val.name.len = 0;
		p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret);
		if (ret<0){
			if (ret==E_BINRPC_EOP){
				break;
			}
			snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
					"ERROR while parsing the record %d,"
					" @%d: %02x : %s", i,
					resp_handle->in_pkt.offset, *p, binrpc_error(ret));
			goto error;
		}
		if (i >= *val_count){
			struct binrpc_val *t;
			t= (struct binrpc_val*) binrpc_realloc(*vals, (VAL_ARRAY_CHUNK+(*val_count))*sizeof(**vals));
			if (t==0)
				goto error_mem;
			*vals = t;
			*val_count += VAL_ARRAY_CHUNK;
		}
		(*vals)[i] = val;
		i++;
	}
	if (i == 0) {
		binrpc_free(*vals);
		*vals = NULL;
	}
	else if (i<*val_count){
/*		do not try to save memory because it causes fragmentation when used ser mem utils and "regualar" memory leak
		struct binrpc_val *t;
		t = (struct binrpc_val*) binrpc_realloc(*vals, i*sizeof(**vals));
		if (t) *vals = t;
*/
	}
	*val_count = i;
	return 0;
error_mem:
	snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
		"parse_response: out of memory");
error:
	if (*vals){
		binrpc_free(*vals);
		*vals = NULL;
	}
	*val_count=0;
	return FATAL_ERROR;
}
Пример #4
0
void binrpc_release_response(struct binrpc_response_handle *resp_handle) {
	if (resp_handle->reply_buf) {
		binrpc_free(resp_handle->reply_buf);
		resp_handle->reply_buf = NULL;
	}
}
Пример #5
0
/* parse the body into a malloc allocated,  binrpc_val array */
int binrpc_send_command(
	struct binrpc_handle* handle, char* method, char** args, int arg_count,
	struct binrpc_response_handle *resp_handle)
{
	struct binrpc_pkt req_pkt;
	struct binrpc_val v;
	int i, size, res = FATAL_ERROR, ret = 0;
	unsigned char *req_buf = NULL;

	memset(&resp_handle->in_pkt, 0, sizeof(resp_handle->in_pkt));	
	if (!method || strlen(method) == 0) {
		snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
			"send_command: method name not specified");
		goto fail;
	
	}
	size = BINRPC_MIN_RECORD_SIZE + 8 + strlen(method) + 1; /*max.possible optional value len */	
	for (i=0; i<arg_count; i++) {
		if (parse_arg(&v, args[i]) < 0)
			goto fail;
		switch (v.type) {
			case BINRPC_T_STR:
				size += v.u.strval.len + 1;
				break;
			case BINRPC_T_INT:
			case BINRPC_T_DOUBLE:
				size += sizeof(int);
				break;
			default:
				snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
					"BUG: send_command: unexpected value type");
				goto fail;
		}
		size +=  BINRPC_MIN_RECORD_SIZE + 8;
	}
	req_buf = binrpc_malloc(size);
	if (!req_buf) {
		snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
			"send_command: not enough memory to allocate buffer. Needed %d bytes", size);
		goto fail;
	}
	if ((ret = binrpc_init_pkt(&req_pkt, req_buf, size)) < 0) goto fail2;

	if ((ret = binrpc_addstr(&req_pkt, method, strlen(method))) < 0) goto fail2;

	for (i=0; i<arg_count; i++) {
		if (parse_arg(&v, args[i]) < 0)
			goto fail;
		switch (v.type) {
			case BINRPC_T_STR:
				if ((ret = binrpc_addstr(&req_pkt,  v.u.strval.s,  v.u.strval.len)) < 0) goto fail2;
				break;
			case BINRPC_T_INT:
				if ((ret = binrpc_addint(&req_pkt, v.u.intval)) < 0) goto fail2;
				break;
			case BINRPC_T_DOUBLE:
				if ((ret = binrpc_adddouble(&req_pkt, v.u.fval)) < 0) goto fail2;
				break;
			default:
				break;
		}
	}

	if (binrpc_send_command_ex(handle, &req_pkt, resp_handle) < 0) {
		goto fail;
	}
	res = 0;
fail:	
	if (req_buf) binrpc_free(req_buf);
	return res;	
fail2:
	snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
		"send_command: error when preparing params: %s", binrpc_error(ret));
	goto fail;
}
Пример #6
0
/* reads the whole reply
 * returns < 0 on error, reply size on success + initializes resp_handle */
static int get_reply(struct binrpc_handle *handle, 
			int cookie, 
			struct binrpc_response_handle *resp_handle)
{
	unsigned char *crt, *hdr_end;
	int n, ret, tl;
	
	ret = 0;
	resp_handle->reply_buf = NULL;
	hdr_end = crt = handle->buf;
	
	do {		
		n = read(handle->socket, crt, handle->buf_size - (crt-handle->buf));
		if (n < 0){
			if (errno==EINTR)
				continue;
			snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
				"get_reply: read reply failed: %s (%d)",
				strerror(errno), errno);
			return FATAL_ERROR;
		}
		if (verbose >= 3){
			/* dump it in hex */
			printf("received %d bytes in reply (@offset %d):\n", 
			       n, (int)(crt-handle->buf));
			hexdump(crt, n, 1);
		}
		crt += n;
		hdr_end = binrpc_parse_init(&resp_handle->in_pkt, handle->buf, crt - handle->buf, &ret);
		
	} while (ret == E_BINRPC_MORE_DATA);
	if (ret < 0){
		snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
			"get_reply: reply parsing error: %s",
			binrpc_error(ret));
		return FATAL_ERROR;
	}

	if (verbose>1){
		printf("new packet: type %02x, len %d, cookie %02x\n",
				resp_handle->in_pkt.type, resp_handle->in_pkt.tlen, resp_handle->in_pkt.cookie);
	}
	if (resp_handle->in_pkt.cookie!=cookie){
		snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
			"get_reply: reply parsing error: "
			"cookie doesn't match: sent: %02x, received: %02x", 
			cookie, resp_handle->in_pkt.cookie);
		return FATAL_ERROR;
	}

	/* we know total size and we can allocate buffer for received data */
	tl = resp_handle->in_pkt.tlen;
	
	if (handle->sock_type == SOCK_DGRAM) {
		/* we must read all datagram in one read call, otherwise unread part is truncated and lost. Read will block execution */
		if (crt - hdr_end < tl) {
			snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
				"get_reply: datagram truncated. Received: %d, Expected: %d.",
				crt-hdr_end, tl);
			return FATAL_ERROR;		
		}
	}
	if (crt - hdr_end > tl) {
		/* header contains probably data from next message, in case of STREAM it could be unread but it's waste of time */
		crt = hdr_end + tl;	
	}
	
	resp_handle->reply_buf = (unsigned char *) binrpc_malloc(tl);
	if (!resp_handle->reply_buf) {
		snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
			"get_reply: not enough memory to allocate reply buffer. %d bytes needed.",
			resp_handle->in_pkt.tlen);
		return FATAL_ERROR;
	}
	crt = resp_handle->reply_buf + (crt-hdr_end);
	memcpy(resp_handle->reply_buf, hdr_end, crt - resp_handle->reply_buf);
	tl -= crt - resp_handle->reply_buf;
	while (tl > 0) {
		n=read(handle->socket, crt, tl);
		if (n < 0){
			if (errno==EINTR)
				continue;
			snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
				"get_reply: read reply failed: %s (%d)",
				strerror(errno), errno);
			binrpc_free(resp_handle->reply_buf);
			resp_handle->reply_buf = NULL;
			return FATAL_ERROR;
		}
		if (verbose >= 3){
			/* dump it in hex */
			printf("received %d bytes in reply (@offset %d):\n", 
			       n, (int)(crt-resp_handle->reply_buf));
			hexdump(crt, n, 1);
		}
		crt += n;
		tl -= n;
	}
	
	return (int)(crt-resp_handle->reply_buf);
}
Пример #7
0
int main(int argc, char** argv)
{
	struct binrpc_response_handle resp_handle;
	unsigned char* txt_rsp = NULL;
	int txt_rsp_len = 0;
	struct binrpc_handle handle;
	struct binrpc_val *vals = NULL;
	int cnt, i, err_no;
	char *errs;
	
	if (argc < 2) goto err;
	
	if (binrpc_open_connection_url(&handle, argv[1]) < 0) goto err2;
	if (binrpc_send_command(&handle, argv[2], argv+3, argc-3, &resp_handle) < 0) {
		binrpc_close_connection(&handle);
		goto err2;
	}
	binrpc_close_connection(&handle);

	if (binrpc_response_to_text(&resp_handle, &txt_rsp, &txt_rsp_len, '\n') < 0) goto err3;
	fprintf(stdout, "binrpc_response_to_text():\n--------------------------\n%s\n", txt_rsp);
	
	fprintf(stdout, "\nbinrpc_print_response():\n------------------------\n");
	binrpc_print_response(&resp_handle, NULL);
	
	fprintf(stdout, "\nbinrpc_parse_response():\n------------------------\n");
	cnt = 0;
	switch (binrpc_get_response_type(&resp_handle)) {
		case 0:
			if (binrpc_parse_response(&vals, &cnt, &resp_handle) < 0) goto err3;
			fprintf(stdout, "#Records: %d\n", cnt);
			for (i = 0; i < cnt; i++) {
				fprintf(stdout, "#%.2d: type:%d name:%.*s\n", i, vals[i].type, vals[i].name.len, vals[i].name.s);
			}
			break;
		case 1:
			if (binrpc_parse_error_response(&resp_handle, &err_no, &errs) <0) goto err3;
			fprintf(stdout, "%d %s\n", err_no, errs);
			break;
		default:
			fprintf(stdout, "Unknown response type: %d\n", binrpc_get_response_type(&resp_handle));	
			break;
	}

	if (vals != NULL) {
		binrpc_free(vals);
	}	
	if (txt_rsp != NULL) {
		binrpc_free(txt_rsp);
	}
	binrpc_release_response(&resp_handle);
	
	return 0;
err:
	fprintf(stderr, "Usage: %s url mathod [params]\n", NAME);
	return -1;
err3:
	if (vals != NULL) {
		binrpc_free(vals);
	}	
	if (txt_rsp) {
		binrpc_free(txt_rsp);
	}
	binrpc_release_response(&resp_handle);
err2:
	fprintf(stderr, "ERROR: %s\n", binrpc_get_last_errs());
	return -2;
}