lib: Add accept_send/recv
authorVolker Lendecke <vl@samba.org>
Sun, 30 Nov 2014 15:10:32 +0000 (16:10 +0100)
committerVolker Lendecke <vl@samba.org>
Tue, 7 Jun 2016 12:34:10 +0000 (14:34 +0200)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
lib/async_req/async_sock.c
lib/async_req/async_sock.h

index c0ad8f303b8fcd7b8b1f6e2f5f54ca80f405be3a..9ccec9e70207c032338e929f03cc2427ff5ae2e7 100644 (file)
@@ -635,3 +635,86 @@ bool wait_for_read_recv(struct tevent_req *req, int *perr)
 
        return true;
 }
+
+struct accept_state {
+       struct tevent_fd *fde;
+       int listen_sock;
+       socklen_t addrlen;
+       struct sockaddr_storage addr;
+       int sock;
+};
+
+static void accept_handler(struct tevent_context *ev, struct tevent_fd *fde,
+                          uint16_t flags, void *private_data);
+
+struct tevent_req *accept_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+                              int listen_sock)
+{
+       struct tevent_req *req;
+       struct accept_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct accept_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->listen_sock = listen_sock;
+
+       state->fde = tevent_add_fd(ev, state, listen_sock, TEVENT_FD_READ,
+                                  accept_handler, req);
+       if (tevent_req_nomem(state->fde, req)) {
+               return tevent_req_post(req, ev);
+       }
+       return req;
+}
+
+static void accept_handler(struct tevent_context *ev, struct tevent_fd *fde,
+                          uint16_t flags, void *private_data)
+{
+       struct tevent_req *req = talloc_get_type_abort(
+               private_data, struct tevent_req);
+       struct accept_state *state = tevent_req_data(req, struct accept_state);
+       int ret;
+
+       TALLOC_FREE(state->fde);
+
+       if ((flags & TEVENT_FD_READ) == 0) {
+               tevent_req_error(req, EIO);
+               return;
+       }
+       state->addrlen = sizeof(state->addr);
+
+       ret = accept(state->listen_sock, (struct sockaddr *)&state->addr,
+                    &state->addrlen);
+       if ((ret == -1) && (errno == EINTR)) {
+               /* retry */
+               return;
+       }
+       if (ret == -1) {
+               tevent_req_error(req, errno);
+               return;
+       }
+       state->sock = ret;
+       tevent_req_done(req);
+}
+
+int accept_recv(struct tevent_req *req, struct sockaddr_storage *paddr,
+               socklen_t *paddrlen, int *perr)
+{
+       struct accept_state *state = tevent_req_data(req, struct accept_state);
+       int err;
+
+       if (tevent_req_is_unix_error(req, &err)) {
+               if (perr != NULL) {
+                       *perr = err;
+               }
+               return -1;
+       }
+       if (paddr != NULL) {
+               memcpy(paddr, &state->addr, state->addrlen);
+       }
+       if (paddrlen != NULL) {
+               *paddrlen = state->addrlen;
+       }
+       return state->sock;
+}
index abbf822228db3163845e052b49853ddc29c090bd..9cc052e253b3d3222c256938a6035651d9aa556c 100644 (file)
@@ -57,4 +57,9 @@ struct tevent_req *wait_for_read_send(TALLOC_CTX *mem_ctx,
                                      bool check_errors);
 bool wait_for_read_recv(struct tevent_req *req, int *perr);
 
+struct tevent_req *accept_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+                              int listen_sock);
+int accept_recv(struct tevent_req *req, struct sockaddr_storage *paddr,
+               socklen_t *paddrlen, int *perr);
+
 #endif