Make non blocking I/O work for accept BIOs.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 12 Oct 2000 01:50:33 +0000 (01:50 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 12 Oct 2000 01:50:33 +0000 (01:50 +0000)
CHANGES
crypto/bio/b_sock.c
crypto/bio/bio.h
crypto/bio/bss_acpt.c
doc/crypto/BIO_s_accept.pod
ssl/bio_ssl.c
ssl/ssl.h
ssl/ssl_lib.c

diff --git a/CHANGES b/CHANGES
index 929431cb02da6c2a4110e2d1a67866c544947439..76ff81d1d7b2730eedd3cf685f63b2575b1c0e1f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,13 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) Fix for non blocking accept BIOs. Added new I/O special reason
+     BIO_RR_ACCEPT to cover this case. Previously use of accept BIOs
+     with non blocking I/O was not possible because no retry code was
+     implemented. Also added new SSL code SSL_WANT_ACCEPT to cover
+     this case.
+     [Steve Henson]
+
   *) Fix for bug in DirectoryString mask setting. Add support for
      X509_NAME_print_ex() in 'req' and X509_print_ex() function
      to allow certificate printing to more controllable, additional
index e971a07de0e13998a087f99fc7de6d426a357058..da2ff2900f05ede11a8044fddcd4e396dc9383f2 100644 (file)
@@ -661,6 +661,7 @@ int BIO_accept(int sock, char **addr)
        ret=accept(sock,(struct sockaddr *)&from,(void *)&len);
        if (ret == INVALID_SOCKET)
                {
+               if(BIO_sock_should_retry(ret)) return -2;
                SYSerr(SYS_F_ACCEPT,get_last_socket_error());
                BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
                goto end;
index 97003b503c6669e5241c830e76e007c9990f7841..c15f5e55fff396d0d4215c693724d11b7f981beb 100644 (file)
@@ -179,7 +179,7 @@ extern "C" {
 #define BIO_retry_type(a)              ((a)->flags & BIO_FLAGS_RWS)
 #define BIO_should_retry(a)            ((a)->flags & BIO_FLAGS_SHOULD_RETRY)
 
-/* The next two are used in conjunction with the
+/* The next three are used in conjunction with the
  * BIO_should_io_special() condition.  After this returns true,
  * BIO *BIO_get_retry_BIO(BIO *bio, int *reason); will walk the BIO 
  * stack and return the 'reason' for the special and the offending BIO.
@@ -188,6 +188,8 @@ extern "C" {
 #define BIO_RR_SSL_X509_LOOKUP         0x01
 /* Returned from the connect BIO when a connect would have blocked */
 #define BIO_RR_CONNECT                 0x02
+/* Returned from the accept BIO when an accept would have blocked */
+#define BIO_RR_ACCEPT                  0x03
 
 /* These are passed by the BIO callback */
 #define BIO_CB_FREE    0x01
index 4da5822062c173c13dec556bfec52158a02f6be0..0c440fbb5f94a668e712d977a294f05a368ae50c 100644 (file)
@@ -236,8 +236,20 @@ again:
                        c->state=ACPT_S_OK;
                        goto again;
                        }
+               BIO_clear_retry_flags(b);
+               b->retry_reason=0;
                i=BIO_accept(c->accept_sock,&(c->addr));
+
+               /* -2 return means we should retry */
+               if(i == -2)
+                       {
+                       BIO_set_retry_special(b);
+                       b->retry_reason=BIO_RR_ACCEPT;
+                       return -1;
+                       }
+
                if (i < 0) return(i);
+
                bio=BIO_new_socket(i,BIO_CLOSE);
                if (bio == NULL) goto err;
 
index c49da7fb02c0dc09e9251a37103f442d29b15e6c..b2b8e911e8339b97fe1ed65c8bd0273450c8e644 100644 (file)
@@ -92,7 +92,7 @@ BIO_do_accept() serves two functions. When it is first
 called, after the accept BIO has been setup, it will attempt
 to create the accept socket and bind an address to it. Second
 and subsequent calls to BIO_do_accept() will await an incoming
-connection.
+connection, or request a retry in non blocking mode.
 
 =head1 NOTES
 
@@ -130,6 +130,13 @@ however because the accept BIO will still accept additional incoming
 connections. This can be resolved by using BIO_pop() (see above)
 and freeing up the accept BIO after the initial connection.
 
+If the underlying accept socket is non blocking and BIO_do_accept() is
+called to await an incoming connection it is possible for
+BIO_should_io_special() with the reason BIO_RR_ACCEPT. If this happens
+then it is an indication that an accept attempt would block: the application
+should take appropriate action to wait until the underlying socket has
+accepted a connection and retry the call.
+
 =head1 RETURN VALUES
 
 TBA
index d85555a7e697056411fd792e5dfc820be06cca21..9141ec0d7b7756a248e3fbdcdfa6771388b78c5a 100644 (file)
@@ -206,6 +206,10 @@ static int ssl_read(BIO *b, char *out, int outl)
                BIO_set_retry_special(b);
                retry_reason=BIO_RR_SSL_X509_LOOKUP;
                break;
+       case SSL_ERROR_WANT_ACCEPT:
+               BIO_set_retry_special(b);
+               retry_reason=BIO_RR_ACCEPT;
+               break;
        case SSL_ERROR_WANT_CONNECT:
                BIO_set_retry_special(b);
                retry_reason=BIO_RR_CONNECT;
index 87e609ed379cdec1be8cda8412db16ba18138e61..2bc994a0f4bcda513389c92fca16218fbaed74ac 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -831,6 +831,7 @@ size_t SSL_get_peer_finished(SSL *s, void *buf, size_t count);
 #define SSL_ERROR_SYSCALL              5 /* look at error stack/return value/errno */
 #define SSL_ERROR_ZERO_RETURN          6
 #define SSL_ERROR_WANT_CONNECT         7
+#define SSL_ERROR_WANT_ACCEPT          8
 
 #define SSL_CTRL_NEED_TMP_RSA                  1
 #define SSL_CTRL_SET_TMP_RSA                   2
index fec98dd8f43d44eee71df442be777ec74a43c4a6..ed2b820984e44ca55049628bb3d5817f5271170e 100644 (file)
@@ -1543,6 +1543,8 @@ int SSL_get_error(SSL *s,int i)
                        reason=BIO_get_retry_reason(bio);
                        if (reason == BIO_RR_CONNECT)
                                return(SSL_ERROR_WANT_CONNECT);
+                       else if (reason == BIO_RR_ACCEPT)
+                               return(SSL_ERROR_WANT_ACCEPT);
                        else
                                return(SSL_ERROR_SYSCALL); /* unknown */
                        }
@@ -1561,6 +1563,8 @@ int SSL_get_error(SSL *s,int i)
                        reason=BIO_get_retry_reason(bio);
                        if (reason == BIO_RR_CONNECT)
                                return(SSL_ERROR_WANT_CONNECT);
+                       else if (reason == BIO_RR_ACCEPT)
+                               return(SSL_ERROR_WANT_ACCEPT);
                        else
                                return(SSL_ERROR_SYSCALL);
                        }