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