Add support for asynchronous session lookup.
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 3a39cfd..d8cb474 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -321,9 +321,14 @@
 		case SSL3_ST_SR_CLNT_HELLO_A:
 		case SSL3_ST_SR_CLNT_HELLO_B:
 		case SSL3_ST_SR_CLNT_HELLO_C:
-
+		case SSL3_ST_SR_CLNT_HELLO_D:
 			s->shutdown=0;
 			ret=ssl3_get_client_hello(s);
+			if (ret == PENDING_SESSION) {
+				s->state = SSL3_ST_SR_CLNT_HELLO_D;
+				s->rwstate = SSL_PENDING_SESSION;
+				goto end;
+			}
 			if (ret <= 0) goto end;
 			s->renegotiate = 2;
 			s->state=SSL3_ST_SW_SRVR_HELLO_A;
@@ -887,16 +892,27 @@
 		{
 		s->state=SSL3_ST_SR_CLNT_HELLO_B;
 		}
-	s->first_packet=1;
-	n=s->method->ssl_get_message(s,
-		SSL3_ST_SR_CLNT_HELLO_B,
-		SSL3_ST_SR_CLNT_HELLO_C,
-		SSL3_MT_CLIENT_HELLO,
-		SSL3_RT_MAX_PLAIN_LENGTH,
-		&ok);
+	if (s->state != SSL3_ST_SR_CLNT_HELLO_D)
+		{
+		s->first_packet=1;
+		n=s->method->ssl_get_message(s,
+			SSL3_ST_SR_CLNT_HELLO_B,
+			SSL3_ST_SR_CLNT_HELLO_C,
+			SSL3_MT_CLIENT_HELLO,
+			SSL3_RT_MAX_PLAIN_LENGTH,
+			&ok);
 
-	if (!ok) return((int)n);
-	s->first_packet=0;
+		if (!ok) return((int)n);
+		s->first_packet=0;
+		}
+	else
+		{
+		/* We have previously parsed the ClientHello message, and can't
+		 * call ssl_get_message again without hashing the message into
+		 * the Finished digest again. */
+		n = s->init_num;
+		}
+
 	d=p=(unsigned char *)s->init_msg;
 
 	/* use version from inside client hello, not from record header
@@ -967,6 +983,11 @@
 			}
 		else if (i == -1)
 			goto err;
+		else if (i == PENDING_SESSION)
+			{
+			ret = PENDING_SESSION;
+			goto err;
+			}
 		else /* i == 0 */
 			{
 			if (!ssl_get_new_session(s,1))
@@ -1337,7 +1358,7 @@
 		}
 err:
 	if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);
-	return ret < 0 ? -1 : ret;
+	return ret;
 	}
 
 int ssl3_send_server_hello(SSL *s)
diff --git a/ssl/ssl.h b/ssl/ssl.h
index e5aa03a..6b7ffe5 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1146,6 +1146,11 @@
 void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
 void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
 SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
+/* SSL_magic_pending_session_ptr returns a magic SSL_SESSION* which indicates
+ * that the session isn't currently unavailable. SSL_get_error will then return
+ * SSL_ERROR_PENDING_SESSION and the handshake can be retried later when the
+ * lookup has completed. */
+SSL_SESSION *SSL_magic_pending_session_ptr(void);
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
 void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
@@ -1251,12 +1256,14 @@
 #define SSL_WRITING	2
 #define SSL_READING	3
 #define SSL_X509_LOOKUP	4
+#define SSL_PENDING_SESSION	7
 
 /* These will only be used when doing non-blocking IO */
 #define SSL_want_nothing(s)	(SSL_want(s) == SSL_NOTHING)
 #define SSL_want_read(s)	(SSL_want(s) == SSL_READING)
 #define SSL_want_write(s)	(SSL_want(s) == SSL_WRITING)
 #define SSL_want_x509_lookup(s)	(SSL_want(s) == SSL_X509_LOOKUP)
+#define SSL_want_session(s)	(SSL_want(s) == SSL_PENDING_SESSION)
 
 #define SSL_MAC_FLAG_READ_MAC_STREAM 1
 #define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
@@ -1666,6 +1673,7 @@
 #define SSL_ERROR_ZERO_RETURN		6
 #define SSL_ERROR_WANT_CONNECT		7
 #define SSL_ERROR_WANT_ACCEPT		8
+#define SSL_ERROR_PENDING_SESSION	11
 
 #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 c536600..c08dbb3 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2707,6 +2707,9 @@
 			return(SSL_ERROR_SSL);
 		}
 
+	if ((i < 0) && SSL_want_session(s))
+		return(SSL_ERROR_PENDING_SESSION);
+
 	if ((i < 0) && SSL_want_read(s))
 		{
 		bio=SSL_get_rbio(s);
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index cbfa172..91c8c1c 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -474,6 +474,8 @@
 #define CERT_PRIVATE_KEY	2
 */
 
+#define PENDING_SESSION -10000
+
 #ifndef OPENSSL_NO_EC
 /* From ECC-TLS draft, used in encoding the curve type in 
  * ECParameters
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 9054fd1..5d8b054 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -143,10 +143,20 @@
 
 #include "ssl_locl.h"
 
+/* The address of this is a magic value, a pointer to which is returned by
+ * SSL_magic_pending_session_ptr(). It allows a session callback to indicate
+ * that it needs to asynchronously fetch session information. */
+static char g_pending_session_magic;
+
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
 static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
 
+SSL_SESSION *SSL_magic_pending_session_ptr()
+	{
+	return (SSL_SESSION*) &g_pending_session_magic;
+	}
+
 SSL_SESSION *SSL_get_session(const SSL *ssl)
 /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
 	{
@@ -500,6 +510,13 @@
 	
 		if ((ret=s->session_ctx->get_session_cb(s,session_id,len,&copy)))
 			{
+			if (ret == SSL_magic_pending_session_ptr())
+				{
+				/* This is a magic value which indicates that
+				 * the callback needs to unwind the stack and
+				 * figure out the session asynchronously. */
+				return PENDING_SESSION;
+				}
 			s->session_ctx->stats.sess_cb_hit++;
 
 			/* Increment reference count now if the session callback
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index c8851ff..6d0c741 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -149,6 +149,7 @@
 case SSL3_ST_SR_CLNT_HELLO_A:	str="SSLv3 read client hello A"; break;
 case SSL3_ST_SR_CLNT_HELLO_B:	str="SSLv3 read client hello B"; break;
 case SSL3_ST_SR_CLNT_HELLO_C:	str="SSLv3 read client hello C"; break;
+case SSL3_ST_SR_CLNT_HELLO_D:	str="SSLv3 read client hello D"; break;
 case SSL3_ST_SW_HELLO_REQ_A:	str="SSLv3 write hello request A"; break;
 case SSL3_ST_SW_HELLO_REQ_B:	str="SSLv3 write hello request B"; break;
 case SSL3_ST_SW_HELLO_REQ_C:	str="SSLv3 write hello request C"; break;
@@ -268,6 +269,7 @@
 case SSL3_ST_SR_CLNT_HELLO_A:			str="3RCH_A"; break;
 case SSL3_ST_SR_CLNT_HELLO_B:			str="3RCH_B"; break;
 case SSL3_ST_SR_CLNT_HELLO_C:			str="3RCH_C"; break;
+case SSL3_ST_SR_CLNT_HELLO_D:			str="3RCH_D"; break;
 case SSL3_ST_SW_SRVR_HELLO_A:			str="3WSH_A"; break;
 case SSL3_ST_SW_SRVR_HELLO_B:			str="3WSH_B"; break;
 case SSL3_ST_SW_CERT_A:				str="3WSC_A"; break;