r4753: added the ability for the generic socket library to handle async
authorAndrew Tridgell <tridge@samba.org>
Sat, 15 Jan 2005 10:28:08 +0000 (10:28 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:08:50 +0000 (13:08 -0500)
connect(). This required a small API change (the addition of
a socket_connect_complete() method)
(This used to be commit b787dd166f5cca82b3710802eefb41e0a8851fc3)

source4/lib/socket/socket.c
source4/lib/socket/socket.h
source4/lib/socket/socket_ipv4.c
source4/lib/socket/socket_ipv6.c
source4/lib/socket/socket_unix.c

index 9be6faf0844148bda001f952ef1d7f43e478d377..cc43348e79f9594ea6c522459124e982b6f2e19e 100644 (file)
@@ -107,6 +107,14 @@ NTSTATUS socket_connect(struct socket_context *sock,
        return sock->ops->fn_connect(sock, my_address, my_port, server_address, server_port, flags);
 }
 
+NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags)
+{
+       if (!sock->ops->fn_connect_complete) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+       return sock->ops->fn_connect_complete(sock, flags);
+}
+
 NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags)
 {
        if (sock->type != SOCKET_TYPE_STREAM) {
index 7a8d3359627ddc763e7374aa21ee85683f45b0f1..7dd8c0ae179294da7bbd41902e0b442aa5cdf454 100644 (file)
@@ -39,6 +39,10 @@ struct socket_ops {
                                const char *server_address, int server_port,
                                uint32_t flags);
 
+       /* complete a non-blocking connect */
+       NTSTATUS (*fn_connect_complete)(struct socket_context *sock,
+                                       uint32_t flags);
+
        /* server ops */
        NTSTATUS (*fn_listen)(struct socket_context *sock,
                                const char *my_address, int port, int queue_size, uint32_t flags);
index 88570512a4c3d8a0c1c2772c6829199f920ef291..7cf2b73e4e70ef13b4f90f67a0da19ca802d18b9 100644 (file)
@@ -1,7 +1,10 @@
 /* 
    Unix SMB/CIFS implementation.
+
    Socket IPv4 functions
+
    Copyright (C) Stefan Metzmacher 2004
+   Copyright (C) Andrew Tridgell 2004-2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -36,6 +39,34 @@ static void ipv4_tcp_close(struct socket_context *sock)
        close(sock->fd);
 }
 
+static NTSTATUS ipv4_tcp_connect_complete(struct socket_context *sock, uint32_t flags)
+{
+       int error=0, ret;
+       socklen_t len = sizeof(error);
+
+       /* check for any errors that may have occurred - this is needed
+          for non-blocking connect */
+       ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len);
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+       if (error != 0) {
+               return map_nt_error_from_unix(error);
+       }
+
+       if (!(flags & SOCKET_FLAG_BLOCK)) {
+               ret = set_blocking(sock->fd, False);
+               if (ret == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
+       }
+
+       sock->state = SOCKET_STATE_CLIENT_CONNECTED;
+
+       return NT_STATUS_OK;
+}
+
+
 static NTSTATUS ipv4_tcp_connect(struct socket_context *sock,
                                 const char *my_address, int my_port,
                                 const char *srv_address, int srv_port,
@@ -79,18 +110,10 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock,
                return map_nt_error_from_unix(errno);
        }
 
-       if (!(flags & SOCKET_FLAG_BLOCK)) {
-               ret = set_blocking(sock->fd, False);
-               if (ret == -1) {
-                       return map_nt_error_from_unix(errno);
-               }
-       }
-
-       sock->state = SOCKET_STATE_CLIENT_CONNECTED;
-
-       return NT_STATUS_OK;
+       return ipv4_tcp_connect_complete(sock, flags);
 }
 
+
 static NTSTATUS ipv4_tcp_listen(struct socket_context *sock,
                                        const char *my_address, int port,
                                        int queue_size, uint32_t flags)
@@ -315,6 +338,7 @@ static const struct socket_ops ipv4_tcp_ops = {
 
        .fn_init                = ipv4_tcp_init,
        .fn_connect             = ipv4_tcp_connect,
+       .fn_connect_complete    = ipv4_tcp_connect_complete,
        .fn_listen              = ipv4_tcp_listen,
        .fn_accept              = ipv4_tcp_accept,
        .fn_recv                = ipv4_tcp_recv,
index 1685f17572474da364f9cc56a6391a37e778c3f4..35b4037ff48860c6d471517a58dc8a3da394877c 100644 (file)
@@ -50,6 +50,33 @@ static void ipv6_tcp_close(struct socket_context *sock)
        close(sock->fd);
 }
 
+static NTSTATUS ipv6_tcp_connect_complete(struct socket_context *sock, uint32_t flags)
+{
+       int error=0, ret;
+       socklen_t len = sizeof(error);
+
+       /* check for any errors that may have occurred - this is needed
+          for non-blocking connect */
+       ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len);
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+       if (error != 0) {
+               return map_nt_error_from_unix(error);
+       }
+
+       if (!(flags & SOCKET_FLAG_BLOCK)) {
+               ret = set_blocking(sock->fd, False);
+               if (ret == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
+       }
+
+       sock->state = SOCKET_STATE_CLIENT_CONNECTED;
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS ipv6_tcp_connect(struct socket_context *sock,
                                 const char *my_address, int my_port,
                                 const char *srv_address, int srv_port,
@@ -87,16 +114,7 @@ static NTSTATUS ipv6_tcp_connect(struct socket_context *sock,
                return map_nt_error_from_unix(errno);
        }
 
-       if (!(flags & SOCKET_FLAG_BLOCK)) {
-               ret = set_blocking(sock->fd, False);
-               if (ret == -1) {
-                       return map_nt_error_from_unix(errno);
-               }
-       }
-
-       sock->state = SOCKET_STATE_CLIENT_CONNECTED;
-
-       return NT_STATUS_OK;
+       return ipv6_tcp_connect_complete(sock, flags);
 }
 
 static NTSTATUS ipv6_tcp_listen(struct socket_context *sock,
@@ -333,6 +351,7 @@ static const struct socket_ops ipv6_tcp_ops = {
 
        .fn_init                = ipv6_tcp_init,
        .fn_connect             = ipv6_tcp_connect,
+       .fn_connect_complete    = ipv6_tcp_connect_complete,
        .fn_listen              = ipv6_tcp_listen,
        .fn_accept              = ipv6_tcp_accept,
        .fn_recv                = ipv6_tcp_recv,
index e35453e6e0e26d9561e31d1eef2ef927edf4f651..60a4b9ec4816d9c0790741dd92f5f4ea9c1170fb 100644 (file)
@@ -50,6 +50,33 @@ static void unixdom_close(struct socket_context *sock)
        close(sock->fd);
 }
 
+static NTSTATUS unixdom_connect_complete(struct socket_context *sock, uint32_t flags)
+{
+       int error=0, ret;
+       socklen_t len = sizeof(error);
+
+       /* check for any errors that may have occurred - this is needed
+          for non-blocking connect */
+       ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len);
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+       if (error != 0) {
+               return map_nt_error_from_unix(error);
+       }
+
+       if (!(flags & SOCKET_FLAG_BLOCK)) {
+               ret = set_blocking(sock->fd, False);
+               if (ret == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
+       }
+
+       sock->state = SOCKET_STATE_CLIENT_CONNECTED;
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS unixdom_connect(struct socket_context *sock,
                                const char *my_address, int my_port,
                                const char *srv_address, int srv_port,
@@ -66,21 +93,12 @@ static NTSTATUS unixdom_connect(struct socket_context *sock,
        srv_addr.sun_family = AF_UNIX;
        strncpy(srv_addr.sun_path, srv_address, sizeof(srv_addr.sun_path));
 
-       if (!(flags & SOCKET_FLAG_BLOCK)) {
-               ret = set_blocking(sock->fd, False);
-               if (ret == -1) {
-                       return NT_STATUS_INVALID_PARAMETER;
-               }
-       }
-
        ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
        if (ret == -1) {
                return unixdom_error(errno);
        }
 
-       sock->state = SOCKET_STATE_CLIENT_CONNECTED;
-
-       return NT_STATUS_OK;
+       return unixdom_connect_complete(sock, flags);
 }
 
 static NTSTATUS unixdom_listen(struct socket_context *sock,
@@ -252,6 +270,7 @@ static const struct socket_ops unixdom_ops = {
 
        .fn_init                = unixdom_init,
        .fn_connect             = unixdom_connect,
+       .fn_connect_complete    = unixdom_connect_complete,
        .fn_listen              = unixdom_listen,
        .fn_accept              = unixdom_accept,
        .fn_recv                = unixdom_recv,