From eb723c2061ece9652638866b5336f3f377339c8f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Apr 2009 18:18:51 +0200 Subject: tsocket: add tstream_writev_queue_send/recv() metze --- lib/tsocket/tsocket.h | 8 +++ lib/tsocket/tsocket_helpers.c | 124 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) (limited to 'lib/tsocket') diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h index aef73ae8c5..ed56995572 100644 --- a/lib/tsocket/tsocket.h +++ b/lib/tsocket/tsocket.h @@ -214,5 +214,13 @@ struct tevent_req *tstream_readv_pdu_send(TALLOC_CTX *mem_ctx, void *next_vector_private); int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno); +struct tevent_req *tstream_writev_queue_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tstream_context *stream, + struct tevent_queue *queue, + const struct iovec *vector, + size_t count); +int tstream_writev_queue_recv(struct tevent_req *req, int *perrno); + #endif /* _TSOCKET_H */ diff --git a/lib/tsocket/tsocket_helpers.c b/lib/tsocket/tsocket_helpers.c index 1b9a9bf670..99cb25b396 100644 --- a/lib/tsocket/tsocket_helpers.c +++ b/lib/tsocket/tsocket_helpers.c @@ -320,3 +320,127 @@ int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno) return ret; } +struct tstream_writev_queue_state { + /* this structs are owned by the caller */ + struct { + struct tevent_context *ev; + struct tstream_context *stream; + const struct iovec *vector; + size_t count; + } caller; + int ret; +}; + +static void tstream_writev_queue_trigger(struct tevent_req *req, + void *private_data); +static void tstream_writev_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] ev The tevent_context to run on + * @param[in] stream The stream to send data through + * @param[in] queue The existing send queue + * @param[in] vector The iovec vector so write + * @param[in] count The size of the vector + * @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 *tstream_writev_queue_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tstream_context *stream, + struct tevent_queue *queue, + const struct iovec *vector, + size_t count) +{ + struct tevent_req *req; + struct tstream_writev_queue_state *state; + bool ok; + + req = tevent_req_create(mem_ctx, &state, + struct tstream_writev_queue_state); + if (!req) { + return NULL; + } + + state->caller.ev = ev; + state->caller.stream = stream; + state->caller.vector = vector; + state->caller.count = count; + state->ret = -1; + + ok = tevent_queue_add(queue, + ev, + req, + tstream_writev_queue_trigger, + NULL); + if (!ok) { + tevent_req_nomem(NULL, req); + goto post; + } + + return req; + + post: + return tevent_req_post(req, ev); +} + +static void tstream_writev_queue_trigger(struct tevent_req *req, + void *private_data) +{ + struct tstream_writev_queue_state *state = tevent_req_data(req, + struct tstream_writev_queue_state); + struct tevent_req *subreq; + + subreq = tstream_writev_send(state, + state->caller.ev, + state->caller.stream, + state->caller.vector, + state->caller.count); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, tstream_writev_queue_done ,req); +} + +static void tstream_writev_queue_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct tstream_writev_queue_state *state = tevent_req_data(req, + struct tstream_writev_queue_state); + int ret; + int sys_errno; + + ret = tstream_writev_recv(subreq, &sys_errno); + talloc_free(subreq); + if (ret == -1) { + tevent_req_error(req, sys_errno); + return; + } + state->ret = ret; + + tevent_req_done(req); +} + +int tstream_writev_queue_recv(struct tevent_req *req, int *perrno) +{ + struct tstream_writev_queue_state *state = tevent_req_data(req, + struct tstream_writev_queue_state); + int ret; + + ret = tsocket_simple_int_recv(req, perrno); + if (ret == 0) { + ret = state->ret; + } + + tevent_req_received(req); + return ret; +} + -- cgit