Blob Blame History Raw
diff -up stunnel-4.56/src/client.c.pollhup stunnel-4.56/src/client.c
--- stunnel-4.56/src/client.c.pollhup	2016-03-31 17:17:01.438314029 +0200
+++ stunnel-4.56/src/client.c	2016-03-31 17:25:48.573618470 +0200
@@ -595,35 +595,6 @@ static void transfer(CLI *c) {
             }
         }
 
-        /****************************** check for hangup conditions */
-        if(s_poll_hup(c->fds, c->sock_rfd->fd)) {
-            s_log(LOG_INFO, "Read socket closed (hangup)");
-            sock_open_rd=0;
-        }
-        if(s_poll_hup(c->fds, c->sock_wfd->fd)) {
-            if(c->ssl_ptr) {
-                s_log(LOG_ERR,
-                    "Write socket closed (hangup) with %d unsent byte(s)",
-                    c->ssl_ptr);
-                longjmp(c->err, 1); /* reset the socket */
-            }
-            s_log(LOG_INFO, "Write socket closed (hangup)");
-            sock_open_wr=0;
-        }
-        if(s_poll_hup(c->fds, c->ssl_rfd->fd) ||
-                s_poll_hup(c->fds, c->ssl_wfd->fd)) {
-            /* hangup -> buggy (e.g. Microsoft) peer:
-             * SSL socket closed without close_notify alert */
-            if(c->sock_ptr) {
-                s_log(LOG_ERR,
-                    "SSL socket closed (hangup) with %d unsent byte(s)",
-                    c->sock_ptr);
-                longjmp(c->err, 1); /* reset the socket */
-            }
-            s_log(LOG_INFO, "SSL socket closed (hangup)");
-            SSL_set_shutdown(c->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
-        }
-
         /****************************** retrieve results from c->fds */
         sock_can_rd=s_poll_canread(c->fds, c->sock_rfd->fd);
         sock_can_wr=s_poll_canwrite(c->fds, c->sock_wfd->fd);
@@ -828,6 +799,36 @@ static void transfer(CLI *c) {
             }
         }
 
+        /****************************** check for hangup conditions */
+        if(s_poll_rdhup(c->fds, c->sock_rfd->fd) &&
+                    !s_poll_canread(c->fds, c->sock_rfd->fd)) {
+            s_log(LOG_INFO, "Read socket closed (hangup)");
+            sock_open_rd=0;
+        }
+        if(s_poll_hup(c->fds, c->sock_wfd->fd)) {
+            if(c->ssl_ptr) {
+                s_log(LOG_ERR,
+                    "Write socket closed (hangup) with %d unsent byte(s)",
+                    c->ssl_ptr);
+                longjmp(c->err, 1); /* reset the socket */
+            }
+            s_log(LOG_INFO, "Write socket closed (hangup)");
+            sock_open_wr=0;
+        }
+        if((s_poll_hup(c->fds, c->ssl_rfd->fd) && !s_poll_canread(c->fds, c->sock_rfd->fd)) ||
+                s_poll_hup(c->fds, c->ssl_wfd->fd)) {
+            /* hangup -> buggy (e.g. Microsoft) peer:
+             * SSL socket closed without close_notify alert */
+            if(c->sock_ptr) {
+                s_log(LOG_ERR,
+                    "SSL socket closed (hangup) with %d unsent byte(s)",
+                    c->sock_ptr);
+                longjmp(c->err, 1); /* reset the socket */
+            }
+            s_log(LOG_INFO, "SSL socket closed (hangup)");
+            SSL_set_shutdown(c->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+        }
+
         /****************************** check write shutdown conditions */
         if(sock_open_wr && SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN && !c->ssl_ptr) {
             sock_open_wr=0; /* no further write allowed */
diff -up stunnel-4.56/src/network.c.pollhup stunnel-4.56/src/network.c
--- stunnel-4.56/src/network.c.pollhup	2013-03-13 14:41:02.000000000 +0100
+++ stunnel-4.56/src/network.c	2016-03-31 17:25:48.574618494 +0200
@@ -79,8 +79,12 @@ void s_poll_add(s_poll_set *fds, int fd,
         fds->ufds[i].events=0;
         fds->nfds++;
     }
-    if(rd)
+    if(rd) {
         fds->ufds[i].events|=POLLIN;
+#ifdef POLLRDHUP
+        fds->ufds[i].events|=POLLRDHUP;
+#endif
+    }
     if(wr)
         fds->ufds[i].events|=POLLOUT;
 }
@@ -103,12 +107,27 @@ int s_poll_canwrite(s_poll_set *fds, int
     return 0; /* not listed in fds */
 }
 
+/* best doc: http://lxr.free-electrons.com/source/net/ipv4/tcp.c#L456 */
+
 int s_poll_hup(s_poll_set *fds, int fd) {
     unsigned int i;
 
     for(i=0; i<fds->nfds; i++)
         if(fds->ufds[i].fd==fd)
-            return fds->ufds[i].revents&POLLHUP;
+            return fds->ufds[i].revents&POLLHUP; /* read and write closed */
+    return 0; /* not listed in fds */
+}
+
+int s_poll_rdhup(s_poll_set *fds, int fd) {
+    unsigned int i;
+
+    for(i=0; i<fds->nfds; i++)
+        if(fds->ufds[i].fd==fd)
+#ifdef POLLRDHUP
+            return fds->ufds[i].revents&POLLRDHUP; /* read closed */
+#else
+            return fds->ufds[i].revents&POLLHUP; /* read and write closed */
+#endif
     return 0; /* not listed in fds */
 }
 
@@ -336,6 +355,12 @@ int s_poll_hup(s_poll_set *fds, int fd)
     return 0; /* FIXME: how to detect HUP condition with select()? */
 }
 
+int s_poll_rdhup(s_poll_set *fds, int fd) {
+    (void)fds; /* skip warning about unused parameter */
+    (void)fd; /* skip warning about unused parameter */
+    return 0; /* FIXME: how to detect RDHUP condition with select()? */
+}
+
 int s_poll_error(s_poll_set *fds, int fd) {
     /* error conditions are signaled as read, but apparently *not* in Winsock:
      * http://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx */
diff -up stunnel-4.56/src/prototypes.h.pollhup stunnel-4.56/src/prototypes.h
--- stunnel-4.56/src/prototypes.h.pollhup	2013-03-19 18:30:55.000000000 +0100
+++ stunnel-4.56/src/prototypes.h	2016-03-31 17:25:48.574618494 +0200
@@ -385,6 +385,7 @@ void s_poll_add(s_poll_set *, int, int,
 int s_poll_canread(s_poll_set *, int);
 int s_poll_canwrite(s_poll_set *, int);
 int s_poll_hup(s_poll_set *, int);
+int s_poll_rdhup(s_poll_set *, int);
 int s_poll_error(s_poll_set *, int);
 int s_poll_wait(s_poll_set *, int, int);