Author: rhuijben
Date: Sun Nov 29 11:09:44 2015
New Revision: 1717031

URL: http://svn.apache.org/viewvc?rev=1717031&view=rev
Log:
With the config store available we now have a location to store ssl session
state for resumption keyed by host+portnumber. Use this to optimize creating
additional ssl sessions (and in case of http/1.1 resetting connections),
within a single serf context.

* buckets/ssl_buckets.c
  (ssl_handshake): Check the config to see if we have a cached session.

* config_store.c
  (ssl_session_data): New struct.
  (SERF_CONFIG__SSL_SESSION): New config value.
  (serf__config_store_set_ssl_session,
   serf__config_store_get_ssl_session): New function.

* serf_private.h
  (serf__config_store_set_ssl_session,
   serf__config_store_get_ssl_session): New function.

Modified:
    serf/trunk/buckets/ssl_buckets.c
    serf/trunk/config_store.c
    serf/trunk/serf_private.h

Modified: serf/trunk/buckets/ssl_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/ssl_buckets.c?rev=1717031&r1=1717030&r2=1717031&view=diff
==============================================================================
--- serf/trunk/buckets/ssl_buckets.c (original)
+++ serf/trunk/buckets/ssl_buckets.c Sun Nov 29 11:09:44 2015
@@ -917,6 +917,19 @@ static apr_status_t ssl_handshake(serf_s
                                   int do_want_read)
 {
     int ssl_result;
+    const unsigned char *data;
+    apr_size_t len;
+
+    /* If we have a cached session, use it to allow speeding up the handshake 
*/
+    if (ctx->config
+        && !serf__config_store_get_ssl_session(ctx->config, &data, &len)) {
+
+        SSL_SESSION *sess;
+
+        sess = d2i_SSL_SESSION(NULL, &data, (long)len);
+
+        SSL_set_session(ctx->ssl, sess);
+    }
 
     ctx->crypt_status = APR_SUCCESS; /* Clear before calling SSL */
     ssl_result = SSL_do_handshake(ctx->ssl);
@@ -1547,6 +1560,32 @@ void serf_ssl_server_cert_chain_callback
     context->server_cert_userdata = data;
 }
 
+static int ssl_new_session(SSL *ssl, SSL_SESSION *session)
+{
+    serf_ssl_context_t *ctx = SSL_get_app_data(ssl);
+    void *mem;
+    unsigned char *der_data;
+    apr_size_t der_len;
+
+    if (!ctx->config)
+        return 0;
+
+    der_len = i2d_SSL_SESSION(session, NULL);
+
+    mem = serf_bucket_mem_alloc(ctx->allocator, der_len);
+    der_data = mem;
+    if (der_len == i2d_SSL_SESSION(session, &der_data)) {
+        /* der_data was modified by i2d_SSL_SESSION(), so
+           we store the original pointer */
+        (void)serf__config_store_set_ssl_session(ctx->config,
+                                                 mem, der_len);
+    }
+
+    serf_bucket_mem_free(ctx->allocator, mem);
+
+    return 0;
+}
+
 static serf_ssl_context_t *ssl_init_context(serf_bucket_alloc_t *allocator)
 {
     serf_ssl_context_t *ssl_ctx;
@@ -1596,6 +1635,10 @@ static serf_ssl_context_t *ssl_init_cont
 
     SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio);
 
+    /* Enable SSL callback to store the SSL session state to allow
+       optimized resumption later. */
+    SSL_CTX_sess_set_new_cb(ssl_ctx->ctx, ssl_new_session);
+
     SSL_set_connect_state(ssl_ctx->ssl);
 
     SSL_set_app_data(ssl_ctx->ssl, ssl_ctx);

Modified: serf/trunk/config_store.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/config_store.c?rev=1717031&r1=1717030&r2=1717031&view=diff
==============================================================================
--- serf/trunk/config_store.c (original)
+++ serf/trunk/config_store.c Sun Nov 29 11:09:44 2015
@@ -475,3 +475,52 @@ apr_status_t serf_config_remove_value(se
 {
     return serf_config_set_object(config, key, NULL);
 }
+
+struct ssl_session_data
+{
+    unsigned char *session;
+    apr_size_t session_len;
+};
+
+#define SERF_CONFIG__SSL_SESSION       (SERF_CONFIG_PER_HOST | 0xF00001)
+
+apr_status_t
+serf__config_store_set_ssl_session(serf_config_t *config,
+                                   const unsigned char *session,
+                                   apr_size_t session_len)
+{
+    struct ssl_session_data *ssld = serf_bucket_mem_alloc(config->allocator,
+                                                          sizeof(*ssld)
+                                                          + session_len);
+
+    ssld->session = ((unsigned char *)ssld) + sizeof(*ssld);
+    ssld->session_len = session_len;
+
+    memcpy(ssld->session, session, session_len);
+
+    return config_set_object(config, SERF_CONFIG__SSL_SESSION, ssld,
+                             serf_bucket_mem_free);
+}
+
+apr_status_t
+serf__config_store_get_ssl_session(serf_config_t *config,
+                                   const unsigned char **session,
+                                   apr_size_t *session_len)
+{
+    const struct ssl_session_data *ssld;
+    apr_status_t status;
+    void *value;
+
+    status = serf_config_get_object(config, SERF_CONFIG__SSL_SESSION, &value);
+
+    if (status)
+        return status;
+    else if (!value)
+        return APR_ENOENT;
+
+    ssld = value;
+
+    *session = ssld->session;
+    *session_len = ssld->session_len;
+    return APR_SUCCESS;
+}

Modified: serf/trunk/serf_private.h
URL: 
http://svn.apache.org/viewvc/serf/trunk/serf_private.h?rev=1717031&r1=1717030&r2=1717031&view=diff
==============================================================================
--- serf/trunk/serf_private.h (original)
+++ serf/trunk/serf_private.h Sun Nov 29 11:09:44 2015
@@ -352,6 +352,16 @@ apr_status_t serf__config_store_create_l
 apr_status_t serf__config_store_create_ctx_config(serf_context_t *ctx,
                                                   serf_config_t **config);
 
+/* Stores session data for a host in the session cache*/
+apr_status_t serf__config_store_set_ssl_session(serf_config_t *config,
+                                                const unsigned char *session,
+                                                apr_size_t session_len);
+
+/* Tries to get session data for a host from the session cache */
+apr_status_t serf__config_store_get_ssl_session(serf_config_t *config,
+                                                const unsigned char **session,
+                                                apr_size_t *session_len);
+
 
 /* Cleans up all connection specific configuration values */
 apr_status_t


Reply via email to