X-Git-Url: http://git.samba.org/samba.git/?p=ira%2Fwip.git;a=blobdiff_plain;f=lib%2Ftsocket%2Ftsocket_helpers.c;h=1876dc3882f75f67d173dcf9b7fadfd049f3f7ea;hp=b2edf43d97fff481947c4f659154c0f76da59813;hb=b46599590f0b2801e1658dc32b6c074d5a14828c;hpb=ca202cf464aec82e63be4b2160f394f56b8c195e diff --git a/lib/tsocket/tsocket_helpers.c b/lib/tsocket/tsocket_helpers.c index b2edf43d97f..1876dc3882f 100644 --- a/lib/tsocket/tsocket_helpers.c +++ b/lib/tsocket/tsocket_helpers.c @@ -22,156 +22,136 @@ */ #include "replace.h" -#include "system/network.h" -#include "system/filesys.h" #include "tsocket.h" #include "tsocket_internal.h" -int tsocket_error_from_errno(int ret, - int sys_errno, - bool *retry) +struct tdgram_sendto_queue_state { + /* this structs are owned by the caller */ + struct { + struct tevent_context *ev; + struct tdgram_context *dgram; + const uint8_t *buf; + size_t len; + const struct tsocket_address *dst; + } caller; + ssize_t ret; +}; + +static void tdgram_sendto_queue_trigger(struct tevent_req *req, + void *private_data); +static void tdgram_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] ev The event context the operation should work on + * @param[in] dgram The tdgram_context 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 *tdgram_sendto_queue_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tdgram_context *dgram, + struct tevent_queue *queue, + const uint8_t *buf, + size_t len, + struct tsocket_address *dst) { - *retry = false; - - if (ret >= 0) { - return 0; - } - - if (ret != -1) { - return EIO; - } - - if (sys_errno == 0) { - return EIO; - } - - if (sys_errno == EINTR) { - *retry = true; - return sys_errno; - } - - if (sys_errno == EINPROGRESS) { - *retry = true; - return sys_errno; - } - - if (sys_errno == EAGAIN) { - *retry = true; - return sys_errno; - } - -#ifdef EWOULDBLOCK - if (sys_errno == EWOULDBLOCK) { - *retry = true; - return sys_errno; - } -#endif - - return sys_errno; + struct tevent_req *req; + struct tdgram_sendto_queue_state *state; + bool ok; + + req = tevent_req_create(mem_ctx, &state, + struct tdgram_sendto_queue_state); + if (!req) { + return NULL; + } + + state->caller.ev = ev; + state->caller.dgram = dgram; + state->caller.buf = buf; + state->caller.len = len; + state->caller.dst = dst; + state->ret = -1; + + ok = tevent_queue_add(queue, + ev, + req, + tdgram_sendto_queue_trigger, + NULL); + if (!ok) { + tevent_req_nomem(NULL, req); + goto post; + } + + return req; + + post: + tevent_req_post(req, ev); + return req; } -int tsocket_simple_int_recv(struct tevent_req *req, int *perrno) +static void tdgram_sendto_queue_trigger(struct tevent_req *req, + void *private_data) { - enum tevent_req_state state; - uint64_t error; - - if (!tevent_req_is_error(req, &state, &error)) { - return 0; - } - - switch (state) { - case TEVENT_REQ_NO_MEMORY: - *perrno = ENOMEM; - return -1; - case TEVENT_REQ_TIMED_OUT: - *perrno = ETIMEDOUT; - return -1; - case TEVENT_REQ_USER_ERROR: - *perrno = (int)error; - return -1; - default: - *perrno = EIO; - return -1; - } - - *perrno = EIO; - return -1; + struct tdgram_sendto_queue_state *state = tevent_req_data(req, + struct tdgram_sendto_queue_state); + struct tevent_req *subreq; + + subreq = tdgram_sendto_send(state, + state->caller.ev, + state->caller.dgram, + state->caller.buf, + state->caller.len, + state->caller.dst); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, tdgram_sendto_queue_done, req); } -int tsocket_common_prepare_fd(int fd, bool high_fd) +static void tdgram_sendto_queue_done(struct tevent_req *subreq) { - int i; - int sys_errno = 0; - int fds[3]; - int num_fds = 0; - - int result, flags; - - if (fd == -1) { - return -1; - } - - /* first make a fd >= 3 */ - if (high_fd) { - while (fd < 3) { - fds[num_fds++] = fd; - fd = dup(fd); - if (fd == -1) { - sys_errno = errno; - break; - } - } - for (i=0; iret = ret; + + tevent_req_done(req); +} - if ((flags = fcntl(fd, F_GETFL)) == -1) { - goto fail; - } +ssize_t tdgram_sendto_queue_recv(struct tevent_req *req, int *perrno) +{ + struct tdgram_sendto_queue_state *state = tevent_req_data(req, + struct tdgram_sendto_queue_state); + ssize_t ret; - flags |= FLAG_TO_SET; - if (fcntl(fd, F_SETFL, flags) == -1) { - goto fail; + ret = tsocket_simple_int_recv(req, perrno); + if (ret == 0) { + ret = state->ret; } -#undef FLAG_TO_SET - - /* fd should be closed on exec() */ -#ifdef FD_CLOEXEC - result = flags = fcntl(fd, F_GETFD, 0); - if (flags >= 0) { - flags |= FD_CLOEXEC; - result = fcntl(fd, F_SETFD, flags); - } - if (result < 0) { - goto fail; - } -#endif - return fd; - - fail: - if (fd != -1) { - sys_errno = errno; - close(fd); - errno = sys_errno; - } - return -1; + tevent_req_received(req); + return ret; }