]> Zhao Yanbai Git Server - minix.git/commitdiff
Asynchronous connect (for non-blocking socket connect emulation)
authorPhilip Homburg <philip@cs.vu.nl>
Fri, 30 Sep 2005 12:44:39 +0000 (12:44 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Fri, 30 Sep 2005 12:44:39 +0000 (12:44 +0000)
include/net/gen/tcp_io.h
servers/inet/generic/tcp.c

index 3d025be4090047807ae6a33240561a663514daa8..6443b47460fe79e023ee2e958661b024a43e5caf 100755 (executable)
@@ -36,6 +36,11 @@ typedef struct nwio_tcpcl
        long nwtcl_ttl;
 } nwio_tcpcl_t;
 
+#define TCF_DEFAULT    0       /* Default parameters */
+#define TCF_ASYNCH     1       /* Asynchronous connect for non-blocking
+                                * socket emulation.
+                                */
+
 typedef struct nwio_tcpatt
 {
        long nwta_flags;
index 432270492d078beecb9ffb1846e9891a22adff61..76128cce1c4ccfeb3445dbb1df2805d07ea23b18 100644 (file)
@@ -284,6 +284,13 @@ unsigned operations;
                        return ENOTCONN;        /* Is this right? */
                return resops;
        }
+       if (tcp_fd->tf_flags & TFF_CONNECTING)
+       {
+               /* Special case for CONNECTING */
+               if (operations & SR_SELECT_WRITE)
+                       tcp_fd->tf_flags |= TFF_SEL_WRITE;
+               return 0;
+       }
        if (operations & SR_SELECT_READ)
        {
                if (!(tcp_fd->tf_flags & TFF_CONNECTEDx))
@@ -807,7 +814,12 @@ assert (conf_acc->acc_length == sizeof(*tcp_conf));
                break;
        case NWIOTCPCONN:
                if (tcp_fd->tf_flags & TFF_CONNECTING)
-                       assert(NOT_IMPLEMENTED);
+               {
+                       tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+                       reply_thr_get (tcp_fd, EALREADY, TRUE);
+                       result= NW_OK;
+                       break;
+               }
                if (tcp_fd->tf_flags & TFF_CONNECTEDx)
                {
                        tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
@@ -816,6 +828,8 @@ assert (conf_acc->acc_length == sizeof(*tcp_conf));
                        break;
                }
                result= tcp_connect(tcp_fd);
+               if (result == NW_OK)
+                       tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
                break;
        case NWIOTCPLISTEN:
        case NWIOTCPLISTENQ:
@@ -1839,10 +1853,6 @@ tcp_conn_t *tcp_conn;
                return;
        }
 
-       assert(tcp_fd->tf_flags & TFF_IOCTL_IP);
-       assert(tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
-               tcp_fd->tf_ioreq == NWIOTCPCONN);
-
        if (tcp_conn->tc_state == TCS_CLOSED)
        {
                reply= tcp_conn->tc_error;
@@ -1855,6 +1865,28 @@ tcp_conn_t *tcp_conn;
                tcp_fd->tf_flags |= TFF_CONNECTEDx;
                reply= NW_OK;
        }
+
+       if (tcp_fd->tf_flags & TFF_CONNECTING)
+       {
+               /* Special code for asynchronous connects */
+               tcp_fd->tf_flags &= ~TFF_CONNECTING;
+
+               /* Reply for select */
+               if ((tcp_fd->tf_flags & TFF_SEL_WRITE) &&
+                       tcp_fd->tf_select_res)
+               {
+                       tcp_fd->tf_flags &= ~TFF_SEL_WRITE;
+                       tcp_fd->tf_select_res(tcp_fd->tf_srfd,
+                               SR_SELECT_WRITE);
+               }
+
+               return;
+       }
+
+       assert(tcp_fd->tf_flags & TFF_IOCTL_IP);
+       assert(tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
+               tcp_fd->tf_ioreq == NWIOTCPCONN);
+
        tcp_reply_ioctl (tcp_fd, reply);
 }
 
@@ -1920,10 +1952,25 @@ int fd;
                assert(tcp_fd->tf_listenq[i] == NULL);
        }
 
+       if (tcp_fd->tf_flags & TFF_CONNECTING)
+       {
+               tcp_conn= tcp_fd->tf_conn;
+               assert(tcp_conn != NULL);
+
+               assert (tcp_conn->tc_connInprogress);
+               tcp_conn->tc_connInprogress= 0;
+               tcp_conn->tc_fd= NULL;
+               tcp_fd->tf_conn= NULL;
+               tcp_close_connection(tcp_conn, ENOCONN);
+
+               tcp_fd->tf_flags &= ~TFF_CONNECTING;
+       }
+
        tcp_fd->tf_flags &= ~TFF_INUSE;
        if (!tcp_fd->tf_conn)
                return;
 
+
        tcp_conn= tcp_fd->tf_conn;
        assert(tcp_conn->tc_fd == tcp_fd);
        tcp_conn->tc_fd= NULL;
@@ -2020,6 +2067,10 @@ PRIVATE int tcp_connect(tcp_fd)
 tcp_fd_t *tcp_fd;
 {
        tcp_conn_t *tcp_conn;
+       nwio_tcpcl_t *tcpcl;
+       long nwtcl_flags;
+       int r, do_asynch;
+       acc_t *data;
 
        if (!(tcp_fd->tf_flags & TFF_CONF_SET))
        {
@@ -2036,6 +2087,28 @@ tcp_fd_t *tcp_fd;
                return NW_OK;
        }
 
+       data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
+               sizeof(*tcpcl), TRUE);
+       if (!data)
+               return EFAULT;
+
+       data= bf_packIffLess(data, sizeof(*tcpcl));
+       assert (data->acc_length == sizeof(*tcpcl));
+       tcpcl= (nwio_tcpcl_t *)ptr2acc_data(data);
+
+       nwtcl_flags= tcpcl->nwtcl_flags;
+       bf_afree(data); data= NULL; tcpcl= NULL;
+
+       if (nwtcl_flags == TCF_ASYNCH)
+               do_asynch= 1;
+       else if (nwtcl_flags == TCF_DEFAULT)
+               do_asynch= 0;
+       else
+       {
+               tcp_reply_ioctl(tcp_fd, EINVAL);
+               return NW_OK;
+       }
+
        assert(!tcp_fd->tf_conn);
        tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport,
                tcp_fd->tf_port->tp_ipaddr,
@@ -2060,7 +2133,14 @@ tcp_fd_t *tcp_fd;
        }
        tcp_fd->tf_conn= tcp_conn;
 
-       return tcp_su4connect(tcp_fd);
+       r= tcp_su4connect(tcp_fd);
+       if (r == NW_SUSPEND && do_asynch)
+       {
+               tcp_fd->tf_flags |= TFF_CONNECTING;
+               tcp_reply_ioctl(tcp_fd, EINPROGRESS);
+               r= NW_OK;
+       }
+       return r;
 }
 
 /*