/* returns: -1 on error, number of bytes written on success */ static int send_binrpc_cmd(struct binrpc_handle* handle, struct binrpc_pkt *pkt, int cookie) { struct iovec v[IOVEC_CNT]; unsigned char msg_hdr[BINRPC_MAX_HDR_SIZE]; int n; if ((n=binrpc_build_hdr(BINRPC_REQ, binrpc_pkt_len(pkt), cookie, msg_hdr, BINRPC_MAX_HDR_SIZE)) < 0) { snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "send_binrpc_cmd: build header error: %s", binrpc_error(n)); return FATAL_ERROR; } v[0].iov_base=msg_hdr; v[0].iov_len=n; v[1].iov_base=pkt->body; v[1].iov_len=binrpc_pkt_len(pkt); write_again: if ((n=writev(handle->socket, v, 2))<0){ if (errno==EINTR) goto write_again; snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "send_binrpc_cmd: send packet failed: %s (%d)", strerror(errno), errno); return FATAL_ERROR; } return n; }
/* 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 int body_get_len(struct binrpc_pkt* body, struct rpc_struct_head* sl_head) { struct rpc_struct_l* l; int len; len=binrpc_pkt_len(body); clist_foreach(sl_head, l, next){ len+=body_get_len(&l->pkt, &l->substructs); }
/* doubles the size */ static struct rpc_struct_l* grow_rpc_struct(struct rpc_struct_l *rs) { struct rpc_struct_l* new_rs; int csize; /* body */ csize=binrpc_pkt_len(&rs->pkt); csize*=2; new_rs=ctl_realloc(rs, sizeof(struct rpc_struct_l)+csize); if (new_rs){ binrpc_pkt_update_buf(&rs->pkt, (unsigned char*)new_rs+sizeof(struct rpc_struct_l), csize); } return new_rs; }
/* appends buf to an already init. binrpc_pkt */ inline static int append_pkt_body(struct binrpc_pkt* p, unsigned char* buf, int len) { if ((int)(p->end-p->crt)<len){ goto error; #if 0 size=2*(int)(p->end-p->body); offset=binrpc_pkt_len(p); for(;(size-offset)<len; size*=2); /* find new size */ new_b=ctl_realloc(p->body, size); if (new_b==0) goto error; binrpc_pkt_update_buf(p, new_b, size); #endif } memcpy(p->crt, buf, len); p->crt+=len; return 0; error: return -1; /* buff. overflow */ }