diff --git a/modules/ctl/binrpc_run.c b/modules/ctl/binrpc_run.c index 3e3e33f17..da5f62d9e 100644 --- a/modules/ctl/binrpc_run.c +++ b/modules/ctl/binrpc_run.c @@ -107,6 +107,8 @@ struct iovec_array{ struct iovec* v; int idx; int len; + int (*output)(struct iovec_array *); + void *data; }; /* send */ @@ -254,15 +256,17 @@ error: inline static int append_iovec(struct iovec_array* a, unsigned char* buf, int len) { - - if (a->idx >= a->len) - goto error; + int ret; + + if (a->idx >= a->len) { + ret = a->output(a); + if (ret < 0) + return ret; + } a->v[a->idx].iov_base=buf; a->v[a->idx].iov_len=len; a->idx++; return 0; -error: - return -1; /* overflow */ } @@ -537,6 +541,22 @@ static void rpc_fault_reset(struct binrpc_ctx* ctx) } } +/* wrapper around sock_send_v for staggered buffer writing */ +static int rpc_send_v(struct iovec_array *a) +{ + int ret; + + if (a->idx <= 0) + return 0; + + ret = sock_send_v(a->data, a->v, a->idx); + if (ret < 0) + return ret; + + a->idx = 0; + return 0; +} + /* build the reply from the current body */ static int rpc_send(struct binrpc_ctx* ctx) { @@ -551,6 +571,8 @@ static int rpc_send(struct binrpc_ctx* ctx) a.v=v; a.idx=1; a.len=MAX_MSG_CHUNKS; + a.output = rpc_send_v; + a.data = ctx->send_h; if (ctx->replied){ LOG(L_ERR, "ERROR: binrpc: rpc_send: rpc method %s tried to reply" @@ -573,7 +595,7 @@ static int rpc_send(struct binrpc_ctx* ctx) LOG(L_ERR, "ERROR: binrprc: rpc_send: too many message chunks\n"); goto error; } - if ((err=sock_send_v(ctx->send_h, v, a.idx))<0){ + if ((err = a.output(&a)) < 0){ if (err==-2){ LOG(L_ERR, "ERROR: binrpc: rpc_send: send failed: " "datagram too big\n");