]> jfr.im git - solanum.git/commitdiff
rb_connect: use SO_ERROR
authorSimon Arlott <sa.me.uk>
Wed, 23 Aug 2017 21:15:05 +0000 (22:15 +0100)
committerSimon Arlott <sa.me.uk>
Thu, 24 Aug 2017 19:08:19 +0000 (20:08 +0100)
librb/src/commio.c

index 2b3f07e0108ec09a2336b5888e1aedc1302e96db..6b4dfa0b2ee9978320bc4ce63f7ac22645a625a8 100644 (file)
@@ -68,7 +68,7 @@ static int number_fd = 0;
 int rb_maxconnections = 0;
 
 static PF rb_connect_timeout;
-static PF rb_connect_tryconnect;
+static PF rb_connect_outcome;
 static void mangle_mapped_sockaddr(struct sockaddr *in);
 
 #ifndef HAVE_SOCKETPAIR
@@ -434,7 +434,9 @@ void
 rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
               struct sockaddr *clocal, CNCB * callback, void *data, int timeout)
 {
-       if(F == NULL)
+       int retval;
+
+       if (F == NULL)
                return;
 
        lrb_assert(callback);
@@ -462,9 +464,32 @@ rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
        /* We have a valid IP, so we just call tryconnect */
        /* Make sure we actually set the timeout here .. */
        rb_settimeout(F, timeout, rb_connect_timeout, NULL);
-       rb_connect_tryconnect(F, NULL);
-}
 
+       retval = connect(F->fd,
+                        (struct sockaddr *)&F->connect->hostaddr,
+                        GET_SS_LEN(&F->connect->hostaddr));
+       /* Error? */
+       if (retval < 0) {
+               /*
+                * If we get EISCONN, then we've already connect()ed the socket,
+                * which is a good thing.
+                *   -- adrian
+                */
+               rb_get_errno();
+               if (errno == EISCONN) {
+                       rb_connect_callback(F, RB_OK);
+               } else if (rb_ignore_errno(errno)) {
+                       /* Ignore error? Reschedule */
+                       rb_setselect(F, RB_SELECT_CONNECT, rb_connect_outcome, NULL);
+               } else {
+                       /* Error? Fail with RB_ERR_CONNECT */
+                       rb_connect_callback(F, RB_ERR_CONNECT);
+               }
+               return;
+       }
+       /* If we get here, we've succeeded, so call with RB_OK */
+       rb_connect_callback(F, RB_OK);
+}
 
 /*
  * rb_connect_callback() - call the callback, and continue with life
@@ -505,45 +530,28 @@ rb_connect_timeout(rb_fde_t *F, void *notused)
        rb_connect_callback(F, RB_ERR_TIMEOUT);
 }
 
-/* static void rb_connect_tryconnect(rb_platform_fd_t fd, void *notused)
- * Input: The fd, the handler data(unused).
- * Output: None.
- * Side-effects: Try and connect with pending connect data for the FD. If
- *               we succeed or get a fatal error, call the callback.
- *               Otherwise, it is still blocking or something, so register
- *               to select for a write event on this FD.
- */
 static void
-rb_connect_tryconnect(rb_fde_t *F, void *notused)
+rb_connect_outcome(rb_fde_t *F, void *notused)
 {
        int retval;
+       int err = 0;
+       socklen_t len = sizeof(err);
 
        if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
                return;
-       /* Try the connect() */
-       retval = connect(F->fd,
-                        (struct sockaddr *)&F->connect->hostaddr,
-                        GET_SS_LEN(&F->connect->hostaddr));
-       /* Error? */
-       if(retval < 0)
-       {
-               /*
-                * If we get EISCONN, then we've already connect()ed the socket,
-                * which is a good thing.
-                *   -- adrian
-                */
+       retval = getsockopt(F->fd, SOL_SOCKET, SO_ERROR, &err, &len);
+       if (retval < 0) {
                rb_get_errno();
-               if(errno == EISCONN)
-                       rb_connect_callback(F, RB_OK);
-               else if(rb_ignore_errno(errno))
-                       /* Ignore error? Reschedule */
-                       rb_setselect(F, RB_SELECT_CONNECT, rb_connect_tryconnect, NULL);
-               else
-                       /* Error? Fail with RB_ERR_CONNECT */
-                       rb_connect_callback(F, RB_ERR_CONNECT);
+       } else if (err != 0) {
+               errno = err;
+               retval = -1;
+       }
+       if (retval < 0) {
+               /* Error? Fail with RB_ERR_CONNECT */
+               rb_connect_callback(F, RB_ERR_CONNECT);
                return;
        }
-       /* If we get here, we've suceeded, so call with RB_OK */
+       /* If we get here, we've succeeded, so call with RB_OK */
        rb_connect_callback(F, RB_OK);
 }