Make non blocking I/O work for accept BIOs.
diff --git a/CHANGES b/CHANGES
index 929431c..76ff81d 100644
--- 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
diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c
index e971a07..da2ff29 100644
--- a/crypto/bio/b_sock.c
+++ b/crypto/bio/b_sock.c
@@ -661,6 +661,7 @@
 	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;
diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h
index 97003b5..c15f5e5 100644
--- a/crypto/bio/bio.h
+++ b/crypto/bio/bio.h
@@ -179,7 +179,7 @@
 #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 @@
 #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
diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c
index 4da5822..0c440fb 100644
--- a/crypto/bio/bss_acpt.c
+++ b/crypto/bio/bss_acpt.c
@@ -236,8 +236,20 @@
 			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;
 
diff --git a/doc/crypto/BIO_s_accept.pod b/doc/crypto/BIO_s_accept.pod
index c49da7f..b2b8e91 100644
--- a/doc/crypto/BIO_s_accept.pod
+++ b/doc/crypto/BIO_s_accept.pod
@@ -92,7 +92,7 @@
 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 @@
 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
diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c
index d85555a..9141ec0 100644
--- a/ssl/bio_ssl.c
+++ b/ssl/bio_ssl.c
@@ -206,6 +206,10 @@
 		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;
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 87e609e..2bc994a 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -831,6 +831,7 @@
 #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
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index fec98dd..ed2b820 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1543,6 +1543,8 @@
 			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 @@
 			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);
 			}