[PATCH 4/6] server: Use an enum to store socket connection state.

Zebediah Figura z.figura12 at gmail.com
Thu Jun 10 19:36:26 CDT 2021


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 include/winsock2.h |   5 --
 server/sock.c      | 191 +++++++++++++++++++++++++--------------------
 2 files changed, 107 insertions(+), 89 deletions(-)

diff --git a/include/winsock2.h b/include/winsock2.h
index a10f81db668..abc82554d8e 100644
--- a/include/winsock2.h
+++ b/include/winsock2.h
@@ -291,11 +291,6 @@ extern "C" {
 #define FD_ROUTING_INTERFACE_CHANGE 0x00000100
 #define FD_ADDRESS_LIST_CHANGE      0x00000200
 
-#ifdef __WINESRC__
-#define FD_WINE_LISTENING           0x10000000
-#define FD_WINE_CONNECTED           0x40000000
-#endif
-
 /* Constants for LPCONDITIONPROC */
 #define CF_ACCEPT                  0x0000
 #define CF_REJECT                  0x0001
diff --git a/server/sock.c b/server/sock.c
index 4cd84637baf..aa2c6842efc 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -131,11 +131,20 @@ struct connect_req
     unsigned int addr_len, send_len, send_cursor;
 };
 
+enum connection_state
+{
+    SOCK_LISTENING,
+    SOCK_UNCONNECTED,
+    SOCK_CONNECTING,
+    SOCK_CONNECTED,
+    SOCK_CONNECTIONLESS,
+};
+
 struct sock
 {
     struct object       obj;         /* object header */
     struct fd          *fd;          /* socket file descriptor */
-    unsigned int        state;       /* status bits */
+    enum connection_state state;     /* connection state */
     unsigned int        mask;        /* event mask */
     /* pending FD_* events which have not yet been reported to the application */
     unsigned int        pending_events;
@@ -603,8 +612,7 @@ static void complete_async_connect( struct sock *sock )
 
     sock->pending_events &= ~(FD_CONNECT | FD_READ | FD_WRITE);
     sock->reported_events &= ~(FD_CONNECT | FD_READ | FD_WRITE);
-    sock->state |= FD_WINE_CONNECTED;
-    sock->state &= ~(FD_CONNECT | FD_WINE_LISTENING);
+    sock->state = SOCK_CONNECTED;
 
     if (!req->send_len)
     {
@@ -660,12 +668,12 @@ static int get_poll_flags( struct sock *sock, int event )
 
     /* A connection-mode socket which has never been connected does not return
      * write or hangup events, but Linux reports POLLOUT | POLLHUP. */
-    if (sock->type == WS_SOCK_STREAM && !(sock->state & (FD_CONNECT | FD_WINE_CONNECTED | FD_WINE_LISTENING)))
+    if (sock->state == SOCK_UNCONNECTED)
         event &= ~(POLLOUT | POLLHUP);
 
     if (event & POLLIN)
     {
-        if (sock->state & FD_WINE_LISTENING)
+        if (sock->state == SOCK_LISTENING)
             flags |= AFD_POLL_ACCEPT;
         else
             flags |= AFD_POLL_READ;
@@ -674,7 +682,7 @@ static int get_poll_flags( struct sock *sock, int event )
         flags |= is_oobinline( sock ) ? AFD_POLL_READ : AFD_POLL_OOB;
     if (event & POLLOUT)
         flags |= AFD_POLL_WRITE;
-    if (sock->state & FD_WINE_CONNECTED)
+    if (sock->state == SOCK_CONNECTED)
         flags |= AFD_POLL_CONNECT;
     if (event & POLLHUP)
         flags |= AFD_POLL_HUP;
@@ -816,32 +824,39 @@ static void post_socket_event( struct sock *sock, unsigned int event_bit, unsign
     }
 }
 
-static void sock_dispatch_events( struct sock *sock, int prevstate, int event, int error )
+static void sock_dispatch_events( struct sock *sock, enum connection_state prevstate, int event, int error )
 {
-    if (prevstate & FD_CONNECT)
+    switch (prevstate)
     {
-        post_socket_event( sock, FD_CONNECT_BIT, sock_get_error( error ) );
-        goto end;
-    }
-    if (prevstate & FD_WINE_LISTENING)
-    {
-        post_socket_event( sock, FD_ACCEPT_BIT, sock_get_error( error ) );
-        goto end;
+    case SOCK_UNCONNECTED:
+        break;
+
+    case SOCK_CONNECTING:
+        if (event & (POLLOUT | POLLERR | POLLHUP))
+            post_socket_event( sock, FD_CONNECT_BIT, sock_get_error( error ) );
+        break;
+
+    case SOCK_LISTENING:
+        if (event & (POLLIN | POLLERR | POLLHUP))
+            post_socket_event( sock, FD_ACCEPT_BIT, sock_get_error( error ) );
+        break;
+
+    case SOCK_CONNECTED:
+    case SOCK_CONNECTIONLESS:
+        if (event & POLLIN)
+            post_socket_event( sock, FD_READ_BIT, 0 );
+
+        if (event & POLLOUT)
+            post_socket_event( sock, FD_WRITE_BIT, 0 );
+
+        if (event & POLLPRI)
+            post_socket_event( sock, FD_OOB_BIT, 0 );
+
+        if (event & (POLLERR | POLLHUP))
+            post_socket_event( sock, FD_CLOSE_BIT, sock_get_error( error ) );
+        break;
     }
 
-    if (event & POLLIN)
-        post_socket_event( sock, FD_READ_BIT, 0 );
-
-    if (event & POLLOUT)
-        post_socket_event( sock, FD_WRITE_BIT, 0 );
-
-    if (event & POLLPRI)
-        post_socket_event( sock, FD_OOB_BIT, 0 );
-
-    if (event & (POLLERR|POLLHUP))
-        post_socket_event( sock, FD_CLOSE_BIT, sock_get_error( error ) );
-
-end:
     sock_wake_up( sock );
 }
 
@@ -849,7 +864,7 @@ static void sock_poll_event( struct fd *fd, int event )
 {
     struct sock *sock = get_fd_user( fd );
     int hangup_seen = 0;
-    int prevstate = sock->state;
+    enum connection_state prevstate = sock->state;
     int error = 0;
 
     assert( sock->obj.ops == &sock_ops );
@@ -859,32 +874,32 @@ static void sock_poll_event( struct fd *fd, int event )
     /* we may change event later, remove from loop here */
     if (event & (POLLERR|POLLHUP)) set_fd_events( sock->fd, -1 );
 
-    if (sock->state & FD_CONNECT)
+    switch (sock->state)
     {
+    case SOCK_UNCONNECTED:
+        break;
+
+    case SOCK_CONNECTING:
         if (event & (POLLERR|POLLHUP))
         {
-            /* we didn't get connected? */
-            sock->state &= ~FD_CONNECT;
+            sock->state = SOCK_UNCONNECTED;
             event &= ~POLLOUT;
             error = sock_error( fd );
         }
         else if (event & POLLOUT)
         {
-            /* we got connected */
-            sock->state |= FD_WINE_CONNECTED;
-            sock->state &= ~FD_CONNECT;
+            sock->state = SOCK_CONNECTED;
             sock->connect_time = current_time;
         }
-    }
-    else if (sock->state & FD_WINE_LISTENING)
-    {
-        /* listening */
+        break;
+
+    case SOCK_LISTENING:
         if (event & (POLLERR|POLLHUP))
             error = sock_error( fd );
-    }
-    else
-    {
-        /* normal data flow */
+        break;
+
+    case SOCK_CONNECTED:
+    case SOCK_CONNECTIONLESS:
         if (sock->type == WS_SOCK_STREAM && (event & POLLIN))
         {
             char dummy;
@@ -926,6 +941,7 @@ static void sock_poll_event( struct fd *fd, int event )
 
         if (hangup_seen)
             event |= POLLHUP;
+        break;
     }
 
     complete_async_polls( sock, event, error );
@@ -952,7 +968,7 @@ static int poll_flags_from_afd( struct sock *sock, int flags )
     /* A connection-mode socket which has never been connected does
      * not return write or hangup events, but Linux returns
      * POLLOUT | POLLHUP. */
-    if (sock->type == WS_SOCK_STREAM && !(sock->state & (FD_CONNECT | FD_WINE_CONNECTED | FD_WINE_LISTENING)))
+    if (sock->state == SOCK_UNCONNECTED)
         return -1;
 
     if (flags & (AFD_POLL_READ | AFD_POLL_ACCEPT))
@@ -979,41 +995,50 @@ static int sock_get_poll_events( struct fd *fd )
     if (!sock->type) /* not initialized yet */
         return -1;
 
-    /* A connection-mode Windows socket which has never been connected does not
-     * return any events, but Linux returns POLLOUT | POLLHUP. Hence we need to
-     * return -1 here, to prevent the socket from being polled on at all. */
-    if (sock->type == WS_SOCK_STREAM && !(sock->state & (FD_CONNECT | FD_WINE_CONNECTED | FD_WINE_LISTENING)))
+    switch (sock->state)
+    {
+    case SOCK_UNCONNECTED:
+        /* A connection-mode Windows socket which has never been connected does
+         * not return any events, but Linux returns POLLOUT | POLLHUP. Hence we
+         * need to return -1 here, to prevent the socket from being polled on at
+         * all. */
         return -1;
 
-    if (sock->state & FD_CONNECT)
-        /* connecting, wait for writable */
+    case SOCK_CONNECTING:
         return POLLOUT;
 
-    if (!list_empty( &sock->accept_list ) || sock->accept_recv_req )
-    {
-        ev |= POLLIN | POLLPRI;
-    }
-    else if (async_queued( &sock->read_q ))
-    {
-        if (async_waiting( &sock->read_q )) ev |= POLLIN | POLLPRI;
-    }
-    else if (sock->state & FD_WINE_LISTENING)
-    {
-        if (mask & FD_ACCEPT)
+    case SOCK_LISTENING:
+        if (!list_empty( &sock->accept_list ) || (mask & FD_ACCEPT))
             ev |= POLLIN;
-    }
-    else if (!sock->rd_shutdown && (mask & FD_READ))
-        ev |= POLLIN | POLLPRI;
-    /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
-    else if (sock->type == WS_SOCK_STREAM && (mask & FD_CLOSE) && !(sock->reported_events & FD_READ))
-        ev |= POLLIN;
+        break;
 
-    if (async_queued( &sock->write_q ))
-    {
-        if (async_waiting( &sock->write_q )) ev |= POLLOUT;
+    case SOCK_CONNECTED:
+    case SOCK_CONNECTIONLESS:
+        if (sock->accept_recv_req)
+        {
+            ev |= POLLIN;
+        }
+        else if (async_queued( &sock->read_q ))
+        {
+            if (async_waiting( &sock->read_q )) ev |= POLLIN | POLLPRI;
+        }
+        else if (!sock->rd_shutdown && (mask & FD_READ))
+            ev |= POLLIN | POLLPRI;
+        /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
+        else if (sock->state == SOCK_CONNECTED && (mask & FD_CLOSE) && !(sock->reported_events & FD_READ))
+            ev |= POLLIN;
+
+        if (async_queued( &sock->write_q ))
+        {
+            if (async_waiting( &sock->write_q )) ev |= POLLOUT;
+        }
+        else if (!sock->wr_shutdown && (mask & FD_WRITE))
+        {
+            ev |= POLLOUT;
+        }
+
+        break;
     }
-    else if (!sock->wr_shutdown && (mask & FD_WRITE))
-        ev |= POLLOUT;
 
     LIST_FOR_EACH_ENTRY( req, &poll_list, struct poll_req, entry )
     {
@@ -1067,8 +1092,7 @@ static void sock_queue_async( struct fd *fd, struct async *async, int type, int
         return;
     }
 
-    if ( ( !( sock->state & (FD_CONNECT|FD_WINE_LISTENING) ) && type == ASYNC_TYPE_READ  ) ||
-         ( !( sock->state & (FD_CONNECT) ) && type == ASYNC_TYPE_WRITE ) )
+    if (sock->state != SOCK_CONNECTED)
     {
         set_error( STATUS_PIPE_DISCONNECTED );
         return;
@@ -1181,7 +1205,7 @@ static struct sock *create_socket(void)
 
     if (!(sock = alloc_object( &sock_ops ))) return NULL;
     sock->fd      = NULL;
-    sock->state   = 0;
+    sock->state   = SOCK_UNCONNECTED;
     sock->mask    = 0;
     sock->pending_events = 0;
     sock->reported_events = 0;
@@ -1359,6 +1383,7 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u
     }
 #endif
 
+    sock->state  = (type == WS_SOCK_STREAM ? SOCK_UNCONNECTED : SOCK_CONNECTIONLESS);
     sock->flags  = flags;
     sock->proto  = protocol;
     sock->type   = type;
@@ -1423,7 +1448,7 @@ static struct sock *accept_socket( struct sock *sock )
         }
 
         /* newly created socket gets the same properties of the listening socket */
-        acceptsock->state   = FD_WINE_CONNECTED;
+        acceptsock->state   = SOCK_CONNECTED;
         acceptsock->nonblocking = sock->nonblocking;
         acceptsock->mask    = sock->mask;
         acceptsock->proto   = sock->proto;
@@ -1477,7 +1502,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
             return FALSE;
     }
 
-    acceptsock->state |= FD_WINE_CONNECTED;
+    acceptsock->state = SOCK_CONNECTED;
     acceptsock->pending_events = 0;
     acceptsock->reported_events = 0;
     acceptsock->proto   = sock->proto;
@@ -1765,8 +1790,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
 
         sock->pending_events &= ~FD_ACCEPT;
         sock->reported_events &= ~FD_ACCEPT;
-        sock->state |= FD_WINE_LISTENING;
-        sock->state &= ~(FD_CONNECT | FD_WINE_CONNECTED);
+        sock->state = SOCK_LISTENING;
 
         /* a listening socket can no longer be accepted into */
         allow_fd_caching( sock->fd );
@@ -1804,7 +1828,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
             return 0;
         }
 
-        if (sock->state & FD_CONNECT)
+        if (sock->state == SOCK_CONNECTING)
         {
             /* FIXME: STATUS_ADDRESS_ALREADY_ASSOCIATED probably isn't right,
              * but there's no status code that maps to WSAEALREADY... */
@@ -1827,8 +1851,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
 
         if (!ret)
         {
-            sock->state |= FD_WINE_CONNECTED;
-            sock->state &= ~FD_CONNECT;
+            sock->state = SOCK_CONNECTED;
 
             if (!send_len) return 1;
         }
@@ -1836,7 +1859,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
         if (!(req = mem_alloc( sizeof(*req) )))
             return 0;
 
-        sock->state |= FD_CONNECT;
+        sock->state = SOCK_CONNECTING;
 
         if (params->synchronous && sock->nonblocking)
         {
@@ -1877,7 +1900,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
             return 0;
         }
 
-        if (sock->type == WS_SOCK_STREAM && !(sock->state & FD_WINE_CONNECTED))
+        if (sock->state != SOCK_CONNECTED && sock->state != SOCK_CONNECTIONLESS)
         {
             set_error( STATUS_INVALID_CONNECTION );
             return 0;
-- 
2.30.2




More information about the wine-devel mailing list