- Added ssl_session_reset() to allow re-use of already set non-connection specific context information

diff --git a/ChangeLog b/ChangeLog
index 2a18a34..63ec368 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 PolarSSL ChangeLog
 
+= Version Trunk
+Features
+   * Added ssl_session_reset() to allow better multi-connection pools of
+     SSL contexts without needing to set all non-connection-specific
+	 data and pointers again. Adapted ssl_server to use this functionality.
+
 = Version 1.0.0 released on 2011-07-27
 Features
    * Expanded cipher layer with support for CFB128 and CTR mode
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 45cb1cc..8cdb636 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -378,6 +378,15 @@
 int ssl_init( ssl_context *ssl );
 
 /**
+ * \brief          Reset an already initialized SSL context for re-use
+ *                 while retaining application-set variables, function
+ *                 pointers and data.
+ *
+ * \param ssl      SSL context
+ */
+void ssl_session_reset( ssl_context *ssl );
+
+/**
  * \brief          Set the current endpoint type
  *
  * \param ssl      SSL context
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 004c70a..7e6e86c 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1732,6 +1732,49 @@
 }
 
 /*
+ * Reset an initialized and used SSL context for re-use while retaining
+ * all application-set variables, function pointers and data.
+ */
+void ssl_session_reset( ssl_context *ssl )
+{
+    ssl->state = SSL_HELLO_REQUEST;
+    
+    ssl->in_offt = NULL;
+
+    ssl->in_msgtype = 0;
+    ssl->in_msglen = 0;
+    ssl->in_left = 0;
+
+    ssl->in_hslen = 0;
+    ssl->nb_zero = 0;
+
+    ssl->out_msgtype = 0;
+    ssl->out_msglen = 0;
+    ssl->out_left = 0;
+
+    ssl->do_crypt = 0;
+    ssl->pmslen = 0;
+    ssl->keylen = 0;
+    ssl->minlen = 0;
+    ssl->ivlen = 0;
+    ssl->maclen = 0;
+
+    memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+    memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+    memset( ssl->randbytes, 0, 64 );
+    memset( ssl->premaster, 0, 256 );
+    memset( ssl->iv_enc, 0, 16 );
+    memset( ssl->iv_dec, 0, 16 );
+    memset( ssl->mac_enc, 0, 32 );
+    memset( ssl->mac_dec, 0, 32 );
+    memset( ssl->ctx_enc, 0, 128 );
+    memset( ssl->ctx_dec, 0, 128 );
+
+     md5_starts( &ssl->fin_md5  );
+    sha1_starts( &ssl->fin_sha1 );
+}
+
+/*
  * SSL set accessors
  */
 void ssl_set_endpoint( ssl_context *ssl, int endpoint )
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index be92b0d..694908c 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -186,7 +186,7 @@
 {
     int ret, len;
     int listen_fd;
-    int client_fd;
+    int client_fd = -1;
     unsigned char buf[1024];
 
     havege_state hs;
@@ -250,44 +250,18 @@
     printf( " ok\n" );
 
     /*
-     * 3. Wait until a client connects
-     */
-#ifdef WIN32
-    ShellExecute( NULL, "open", "https://localhost:4433/",
-                  NULL, NULL, SW_SHOWNORMAL );
-#endif
-
-    client_fd = -1;
-    memset( &ssl, 0, sizeof( ssl ) );
-
-accept:
-
-    net_close( client_fd );
-    ssl_free( &ssl );
-
-    printf( "  . Waiting for a remote connection ..." );
-    fflush( stdout );
-
-    if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
-    {
-        printf( " failed\n  ! net_accept returned %d\n\n", ret );
-        goto exit;
-    }
-
-    printf( " ok\n" );
-
-    /*
      * 4. Setup stuff
      */
     printf( "  . Setting up the RNG and SSL data...." );
     fflush( stdout );
 
+    memset( &ssl, 0, sizeof( ssl ) );
     havege_init( &hs );
 
     if( ( ret = ssl_init( &ssl ) ) != 0 )
     {
         printf( " failed\n  ! ssl_init returned %d\n\n", ret );
-        goto accept;
+        goto exit;
     }
 
     printf( " ok\n" );
@@ -297,8 +271,7 @@
 
     ssl_set_rng( &ssl, havege_rand, &hs );
     ssl_set_dbg( &ssl, my_debug, stdout );
-    ssl_set_bio( &ssl, net_recv, &client_fd,
-                       net_send, &client_fd );
+
     ssl_set_scb( &ssl, my_get_session,
                        my_set_session );
 
@@ -311,6 +284,38 @@
     ssl_set_own_cert( &ssl, &srvcert, &rsa );
     ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G );
 
+    printf( " ok\n" );
+
+reset:
+    if( client_fd != -1 )
+        net_close( client_fd );
+
+    ssl_session_reset( &ssl );
+
+    /*
+     * 3. Wait until a client connects
+     */
+#ifdef WIN32
+    ShellExecute( NULL, "open", "https://localhost:4433/",
+                  NULL, NULL, SW_SHOWNORMAL );
+#endif
+
+    client_fd = -1;
+
+    printf( "  . Waiting for a remote connection ..." );
+    fflush( stdout );
+
+    if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
+    {
+        printf( " failed\n  ! net_accept returned %d\n\n", ret );
+        goto exit;
+    }
+
+    ssl_set_bio( &ssl, net_recv, &client_fd,
+                       net_send, &client_fd );
+
+    printf( " ok\n" );
+
     /*
      * 5. Handshake
      */
@@ -322,7 +327,7 @@
         if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
         {
             printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
-            goto accept;
+            goto reset;
         }
     }
 
@@ -382,7 +387,7 @@
         if( ret == POLARSSL_ERR_NET_CONN_RESET )
         {
             printf( " failed\n  ! peer closed the connection\n\n" );
-            goto accept;
+            goto reset;
         }
 
         if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
@@ -396,7 +401,7 @@
     printf( " %d bytes written\n\n%s\n", len, (char *) buf );
 
     ssl_close_notify( &ssl );
-    goto accept;
+    goto reset;
 
 exit: