Merge branch 'winevents-clean' of https://github.com/dechamps/tinc into 1.1
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 28 Jun 2014 19:49:55 +0000 (21:49 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 28 Jun 2014 19:49:55 +0000 (21:49 +0200)
src/net_socket.c
src/utils.h

index 0a4dd9a..3b6399b 100644 (file)
@@ -401,30 +401,38 @@ static void handle_meta_io(void *data, int flags) {
        connection_t *c = data;
 
        if(c->status.connecting) {
-               /* The event loop does not protect against spurious events. Verify that we are actually connected. */
-               if (connect(c->socket, &c->address.sa, sizeof(c->address)) == 0)
-                       logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): redundant connect() unexpectedly succeeded", c->name, c->hostname);
-               else if (!sockisconn(sockerrno)) {
-                       if (!sockalready(sockerrno)) {
-                               logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while checking connection status for %s (%s): %s", c->name, c->hostname, sockstrerror(sockerrno));
+               /*
+                  The event loop does not protect against spurious events. Verify that we are actually connected
+                  by issuing an empty send() call.
+
+                  Note that the behavior of send() on potentially unconnected sockets differ between platforms:
+                  +------------+-----------+-------------+-----------+
+                  |   Event    |   POSIX   |    Linux    |  Windows  |
+                  +------------+-----------+-------------+-----------+
+                  | Spurious   | ENOTCONN  | EWOULDBLOCK | ENOTCONN  |
+                  | Failed     | ENOTCONN  | (cause)     | ENOTCONN  |
+                  | Successful | (success) | (success)   | (success) |
+                  +------------+-----------+-------------+-----------+
+               */
+               if (send(c->socket, NULL, 0, 0) != 0) {
+                       if (sockwouldblock(sockerrno))
+                               return;
+                       int socket_error;
+                       if (!socknotconn(sockerrno))
+                               socket_error = sockerrno;
+                       else {
+                               int len = sizeof socket_error;
+                               getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&socket_error, &len);
+                       }
+                       if (socket_error) {
+                               logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(socket_error));
                                terminate_connection(c, false);
                        }
                        return;
                }
 
                c->status.connecting = false;
-
-               int result;
-               socklen_t len = sizeof result;
-               getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len);
-
-               if(!result)
-                       finish_connecting(c);
-               else {
-                       logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(result));
-                       terminate_connection(c, false);
-                       return;
-               }
+               finish_connecting(c);
        }
 
        if(flags & IO_WRITE)
index a6adffb..7e519f4 100644 (file)
@@ -37,8 +37,7 @@ extern const char *winerror(int);
 #define sockmsgsize(x) ((x) == WSAEMSGSIZE)
 #define sockinprogress(x) ((x) == WSAEINPROGRESS || (x) == WSAEWOULDBLOCK)
 #define sockinuse(x) ((x) == WSAEADDRINUSE)
-#define sockalready(x) ((x) == WSAEALREADY || (x) == WSAEINVAL || (x) == WSAEWOULDBLOCK) /* See MSDN for connect() */
-#define sockisconn(x) ((x) == WSAEISCONN)
+#define socknotconn(x) ((x) == WSAENOTCONN)
 #else
 #define sockerrno errno
 #define sockstrerror(x) strerror(x)
@@ -46,8 +45,7 @@ extern const char *winerror(int);
 #define sockmsgsize(x) ((x) == EMSGSIZE)
 #define sockinprogress(x) ((x) == EINPROGRESS)
 #define sockinuse(x) ((x) == EADDRINUSE)
-#define sockalready(x) ((x) == EALREADY)
-#define sockisconn(x) ((x) == EISCONN)
+#define socknotconn(x) ((x) == ENOTCONN)
 #endif
 
 extern unsigned int bitfield_to_int(const void *bitfield, size_t size);