Convert async_connect to "normal" style
authorVolker Lendecke <vl@samba.org>
Sat, 3 Jan 2009 23:26:49 +0000 (00:26 +0100)
committerVolker Lendecke <vl@samba.org>
Sun, 4 Jan 2009 15:42:40 +0000 (16:42 +0100)
source3/include/async_sock.h
source3/lib/async_sock.c

index 892ffef08715a3443c1cd7c8904bc3a0fcc3953c..c6f95d64d551a201974b8155236a92abc8134bfb 100644 (file)
@@ -32,9 +32,11 @@ struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
 struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev,
                             int fd, void *buffer, size_t length,
                             int flags);
-struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev,
-                               int fd, const struct sockaddr *address,
-                               socklen_t address_len);
+struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
+                                    struct event_context *ev,
+                                    int fd, const struct sockaddr *address,
+                                    socklen_t address_len);
+NTSTATUS async_connect_recv(struct async_req *req, int *perrno);
 
 struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
                               int fd, const void *buffer, size_t length,
index f755f7ac582d4adf351ccd963c9ad65808fd71ef..bb89a1353ae4b21e8b3ccacd88c93c0e93689eda 100644 (file)
@@ -535,63 +535,16 @@ NTSTATUS recvall_recv(struct async_req *req)
        return async_req_simple_recv(req);
 }
 
-/**
- * fde event handler for connect(2)
- * @param[in] ev       The event context that sent us here
- * @param[in] fde      The file descriptor event associated with the connect
- * @param[in] flags    Indicate read/writeability of the socket
- * @param[in] priv     private data, "struct async_req *" in this case
- */
-
-static void async_connect_callback(struct event_context *ev,
-                                  struct fd_event *fde, uint16_t flags,
-                                  void *priv)
-{
-       struct async_req *req = talloc_get_type_abort(
-               priv, struct async_req);
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-       struct param_connect *p = &state->param.param_connect;
-
-       if (state->syscall_type != ASYNC_SYSCALL_CONNECT) {
-               async_req_error(req, NT_STATUS_INTERNAL_ERROR);
-               return;
-       }
-
-       TALLOC_FREE(state->fde);
-
-       /*
-        * Stevens, Network Programming says that if there's a
-        * successful connect, the socket is only writable. Upon an
-        * error, it's both readable and writable.
-        */
-       if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE))
-           == (EVENT_FD_READ|EVENT_FD_WRITE)) {
-               int sockerr;
-               socklen_t err_len = sizeof(sockerr);
-
-               if (getsockopt(p->fd, SOL_SOCKET, SO_ERROR,
-                              (void *)&sockerr, &err_len) == 0) {
-                       errno = sockerr;
-               }
-
-               state->sys_errno = errno;
-
-               DEBUG(10, ("connect returned %s\n", strerror(errno)));
-
-               sys_fcntl_long(p->fd, F_SETFL, p->old_sockflags);
-
-               async_req_error(req, map_nt_error_from_unix(state->sys_errno));
-               return;
-       }
-
-       sys_fcntl_long(p->fd, F_SETFL, p->old_sockflags);
-
-       state->result.result_int = 0;
-       state->sys_errno = 0;
+struct async_connect_state {
+       int fd;
+       int result;
+       int sys_errno;
+       long old_sockflags;
+};
 
-       async_req_done(req);
-}
+static void async_connect_connected(struct event_context *ev,
+                                   struct fd_event *fde, uint16_t flags,
+                                   void *priv);
 
 /**
  * @brief async version of connect(2)
@@ -606,48 +559,46 @@ static void async_connect_callback(struct event_context *ev,
  * connect in an async state. This will be reset when the request is finished.
  */
 
-struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev,
-                               int fd, const struct sockaddr *address,
-                               socklen_t address_len)
+struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
+                                    struct event_context *ev,
+                                    int fd, const struct sockaddr *address,
+                                    socklen_t address_len)
 {
        struct async_req *result;
-       struct async_syscall_state *state;
-       struct param_connect *p;
+       struct async_connect_state *state;
+       struct fd_event *fde;
+       NTSTATUS status;
 
-       result = async_syscall_new(mem_ctx, ev, ASYNC_SYSCALL_CONNECT, &state);
+       result = async_req_new(mem_ctx);
        if (result == NULL) {
                return NULL;
        }
-       p = &state->param.param_connect;
+       state = talloc(result, struct async_connect_state);
+       if (state == NULL) {
+               goto fail;
+       }
+       result->private_data = state;
 
        /**
         * We have to set the socket to nonblocking for async connect(2). Keep
         * the old sockflags around.
         */
 
-       p->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0);
+       state->fd = fd;
+       state->sys_errno = 0;
 
-       if (p->old_sockflags == -1) {
-               if (async_post_status(result, ev,
-                                     map_nt_error_from_unix(errno))) {
-                       return result;
-               }
-               TALLOC_FREE(result);
-               return NULL;
+       state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0);
+       if (state->old_sockflags == -1) {
+               goto post_errno;
        }
 
        set_blocking(fd, false);
 
-       state->result.result_int = connect(fd, address, address_len);
-
-       if (state->result.result_int == 0) {
+       state->result = connect(fd, address, address_len);
+       if (state->result == 0) {
                state->sys_errno = 0;
-               if (async_post_status(result, ev, NT_STATUS_OK)) {
-                       return result;
-               }
-               sys_fcntl_long(fd, F_SETFL, p->old_sockflags);
-               TALLOC_FREE(result);
-               return NULL;
+               status = NT_STATUS_OK;
+               goto post_status;
        }
 
        /**
@@ -662,32 +613,93 @@ struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev,
              errno == EISCONN ||
 #endif
              errno == EAGAIN || errno == EINTR)) {
+               goto post_errno;
+       }
 
-               state->sys_errno = errno;
-
-               if (async_post_status(result, ev,
-                                     map_nt_error_from_unix(errno))) {
-                       return result;
-               }
-               sys_fcntl_long(fd, F_SETFL, p->old_sockflags);
-               TALLOC_FREE(result);
-               return NULL;
+       fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE,
+                          async_connect_connected, result);
+       if (fde == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto post_status;
        }
+       return result;
 
-       state->fde = event_add_fd(ev, state, fd,
-                                 EVENT_FD_READ | EVENT_FD_WRITE,
-                                 async_connect_callback, result);
-       if (state->fde == NULL) {
-               sys_fcntl_long(fd, F_SETFL, p->old_sockflags);
-               TALLOC_FREE(result);
-               return NULL;
+ post_errno:
+       state->sys_errno = errno;
+       status = map_nt_error_from_unix(state->sys_errno);
+ post_status:
+       sys_fcntl_long(fd, F_SETFL, state->old_sockflags);
+       if (!async_post_status(result, ev, status)) {
+               goto fail;
        }
-       result->private_data = state;
+       return result;
+ fail:
+       TALLOC_FREE(result);
+       return NULL;
+}
 
-       state->param.param_connect.fd = fd;
-       state->param.param_connect.address = address;
-       state->param.param_connect.address_len = address_len;
+/**
+ * fde event handler for connect(2)
+ * @param[in] ev       The event context that sent us here
+ * @param[in] fde      The file descriptor event associated with the connect
+ * @param[in] flags    Indicate read/writeability of the socket
+ * @param[in] priv     private data, "struct async_req *" in this case
+ */
 
-       return result;
+static void async_connect_connected(struct event_context *ev,
+                                   struct fd_event *fde, uint16_t flags,
+                                   void *priv)
+{
+       struct async_req *req = talloc_get_type_abort(
+               priv, struct async_req);
+       struct async_connect_state *state = talloc_get_type_abort(
+               req->private_data, struct async_connect_state);
+
+       TALLOC_FREE(fde);
+
+       /*
+        * Stevens, Network Programming says that if there's a
+        * successful connect, the socket is only writable. Upon an
+        * error, it's both readable and writable.
+        */
+       if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE))
+           == (EVENT_FD_READ|EVENT_FD_WRITE)) {
+               int sockerr;
+               socklen_t err_len = sizeof(sockerr);
+
+               if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
+                              (void *)&sockerr, &err_len) == 0) {
+                       errno = sockerr;
+               }
+
+               state->sys_errno = errno;
+
+               DEBUG(10, ("connect returned %s\n", strerror(errno)));
+
+               sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
+               async_req_error(req, map_nt_error_from_unix(state->sys_errno));
+               return;
+       }
+
+       state->sys_errno = 0;
+       async_req_done(req);
 }
 
+NTSTATUS async_connect_recv(struct async_req *req, int *perrno)
+{
+       struct async_connect_state *state = talloc_get_type_abort(
+               req->private_data, struct async_connect_state);
+       NTSTATUS status;
+
+       sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
+
+       *perrno = state->sys_errno;
+
+       if (async_req_is_error(req, &status)) {
+               return status;
+       }
+       if (state->sys_errno == 0) {
+               return NT_STATUS_OK;
+       }
+       return map_nt_error_from_unix(state->sys_errno);
+}