/* returns: -1 on error, number of bytes written on success */ static int send_binrpc_cmd(int s, struct binrpc_cmd* cmd, int cookie) { struct iovec v[IOVEC_CNT]; int r; unsigned char msg_body[MAX_BODY_SIZE]; unsigned char msg_hdr[BINRPC_MAX_HDR_SIZE]; struct binrpc_pkt body; int ret; int n; ret=binrpc_init_pkt(&body, msg_body, MAX_BODY_SIZE); if (ret<0) goto binrpc_err; ret=binrpc_addstr(&body, cmd->method, strlen(cmd->method)); if (ret<0) goto binrpc_err; for (r=0; r<cmd->argc; r++){ switch(cmd->argv[r].type){ case BINRPC_T_STR: ret=binrpc_addstr(&body, cmd->argv[r].u.strval.s, cmd->argv[r].u.strval.len); break; case BINRPC_T_INT: ret=binrpc_addint(&body, cmd->argv[r].u.intval); break; case BINRPC_T_DOUBLE: ret=binrpc_adddouble(&body, cmd->argv[r].u.fval); break; default: fprintf(stderr, "ERROR: unsupported type %d\n", cmd->argv[r].type); } if (ret<0) goto binrpc_err; } ret=binrpc_build_hdr(BINRPC_REQ, binrpc_pkt_len(&body), cookie, msg_hdr, BINRPC_MAX_HDR_SIZE); if (ret<0) goto binrpc_err; v[0].iov_base=msg_hdr; v[0].iov_len=ret; v[1].iov_base=msg_body; v[1].iov_len=binrpc_pkt_len(&body); write_again: if ((n=writev(s, v, 2))<0){ if (errno==EINTR) goto write_again; goto error_send; } return n; error_send: return -1; binrpc_err: return -2; }
static struct rpc_struct_l* new_rpc_struct() { struct rpc_struct_l* rs; /* alloc everything in one chunk */ rs=ctl_malloc(sizeof(struct rpc_struct_l)+STRUCT_MAX_BODY); if (rs==0) goto error; memset(rs, 0, sizeof(struct rpc_struct_l)); clist_init(&rs->substructs, next, prev); if (binrpc_init_pkt(&rs->pkt, (unsigned char*)rs+sizeof(struct rpc_struct_l), STRUCT_MAX_BODY)<0){ ctl_free(rs); goto error; } return rs; error: return 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; }