diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/tsocket/tsocket.h | 8 | ||||
-rw-r--r-- | lib/tsocket/tsocket_sendto.c | 125 |
2 files changed, 133 insertions, 0 deletions
diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h index 7987571bc3..4445aafe9d 100644 --- a/lib/tsocket/tsocket.h +++ b/lib/tsocket/tsocket.h @@ -179,5 +179,13 @@ struct tevent_req *tsocket_sendto_send(struct tsocket_context *sock, const struct tsocket_address *dst); ssize_t tsocket_sendto_recv(struct tevent_req *req, int *perrno); +struct tevent_req *tsocket_sendto_queue_send(TALLOC_CTX *mem_ctx, + struct tsocket_context *sock, + struct tevent_queue *queue, + const uint8_t *buf, + size_t len, + struct tsocket_address *dst); +ssize_t tsocket_sendto_queue_recv(struct tevent_req *req, int *perrno); + #endif /* _TSOCKET_H */ diff --git a/lib/tsocket/tsocket_sendto.c b/lib/tsocket/tsocket_sendto.c index 9486374d26..4531c40321 100644 --- a/lib/tsocket/tsocket_sendto.c +++ b/lib/tsocket/tsocket_sendto.c @@ -134,3 +134,128 @@ ssize_t tsocket_sendto_recv(struct tevent_req *req, int *perrno) tevent_req_received(req); return ret; } + +struct tsocket_sendto_queue_state { + /* this structs are owned by the caller */ + struct { + struct tsocket_context *sock; + const uint8_t *buf; + size_t len; + const struct tsocket_address *dst; + } caller; + ssize_t ret; +}; + +static void tsocket_sendto_queue_trigger(struct tevent_req *req, + void *private_data); +static void tsocket_sendto_queue_done(struct tevent_req *subreq); + +/** + * @brief Queue a dgram blob for sending through the socket + * @param[in] mem_ctx The memory context for the result + * @param[in] sock The socket to send the message buffer + * @param[in] queue The existing dgram queue + * @param[in] buf The message buffer + * @param[in] len The message length + * @param[in] dst The destination socket address + * @retval The async request handle + * + * This function queues a blob for sending to destination through an existing + * dgram socket. The async callback is triggered when the whole blob is + * delivered to the underlying system socket. + * + * The caller needs to make sure that all non-scalar input parameters hang + * arround for the whole lifetime of the request. + */ +struct tevent_req *tsocket_sendto_queue_send(TALLOC_CTX *mem_ctx, + struct tsocket_context *sock, + struct tevent_queue *queue, + const uint8_t *buf, + size_t len, + struct tsocket_address *dst) +{ + struct tevent_req *req; + struct tsocket_sendto_queue_state *state; + bool ok; + + req = tevent_req_create(mem_ctx, &state, + struct tsocket_sendto_queue_state); + if (!req) { + return NULL; + } + + state->caller.sock = sock; + state->caller.buf = buf; + state->caller.len = len; + state->caller.dst = dst; + state->ret = -1; + + ok = tevent_queue_add(queue, + sock->event.ctx, + req, + tsocket_sendto_queue_trigger, + NULL); + if (!ok) { + tevent_req_nomem(NULL, req); + goto post; + } + + return req; + + post: + return tevent_req_post(req, sock->event.ctx); +} + +static void tsocket_sendto_queue_trigger(struct tevent_req *req, + void *private_data) +{ + struct tsocket_sendto_queue_state *state = tevent_req_data(req, + struct tsocket_sendto_queue_state); + struct tevent_req *subreq; + + subreq = tsocket_sendto_send(state->caller.sock, + state, + state->caller.buf, + state->caller.len, + state->caller.dst); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, tsocket_sendto_queue_done ,req); +} + +static void tsocket_sendto_queue_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct tsocket_sendto_queue_state *state = tevent_req_data(req, + struct tsocket_sendto_queue_state); + ssize_t ret; + int sys_errno; + + ret = tsocket_sendto_recv(subreq, &sys_errno); + talloc_free(subreq); + if (ret == -1) { + tevent_req_error(req, sys_errno); + return; + } + state->ret = ret; + + tevent_req_done(req); +} + +ssize_t tsocket_sendto_queue_recv(struct tevent_req *req, int *perrno) +{ + struct tsocket_sendto_queue_state *state = tevent_req_data(req, + struct tsocket_sendto_queue_state); + ssize_t ret; + + ret = tsocket_simple_int_recv(req, perrno); + if (ret == 0) { + ret = state->ret; + } + + tevent_req_received(req); + return ret; +} + |