aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlejandro Alvarez <aalvarez@cern.ch>2011-09-20 17:43:54 +0200
committerDaniel Stenberg <daniel@haxx.se>2011-09-28 23:06:34 +0200
commit5793bc370c794a10e6ed014cb535a47672842ae6 (patch)
tree9b9a40d8278cb30124bfcc8e2e63daf73ff228d3 /lib
parentff5ba6e43d808b8cc7c8e099bb0329206031478f (diff)
SSL session sharing support added
With locking, plus test, plus documentation
Diffstat (limited to 'lib')
-rw-r--r--lib/share.c24
-rw-r--r--lib/share.h4
-rw-r--r--lib/sslgen.c49
-rw-r--r--lib/sslgen.h2
-rw-r--r--lib/url.c9
5 files changed, 80 insertions, 8 deletions
diff --git a/lib/share.c b/lib/share.c
index a3db4ded9..a3eae1639 100644
--- a/lib/share.c
+++ b/lib/share.c
@@ -25,6 +25,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "share.h"
+#include "sslgen.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -82,7 +83,16 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
break;
#endif /* CURL_DISABLE_HTTP */
- case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */
+ case CURL_LOCK_DATA_SSL_SESSION:
+ if(!share->sslsession) {
+ share->nsslsession = 8;
+ share->sslsession = calloc(share->nsslsession,
+ sizeof(struct curl_ssl_session));
+ if(!share->sslsession)
+ return CURLSHE_NOMEM;
+ }
+ break;
+
case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
default:
@@ -112,6 +122,11 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
#endif /* CURL_DISABLE_HTTP */
case CURL_LOCK_DATA_SSL_SESSION:
+ if(share->sslsession) {
+ free(share->sslsession);
+ share->sslsession = NULL;
+ share->nsslsession = 0;
+ }
break;
case CURL_LOCK_DATA_CONNECT:
@@ -148,6 +163,7 @@ CURLSHcode
curl_share_cleanup(CURLSH *sh)
{
struct Curl_share *share = (struct Curl_share *)sh;
+ unsigned int i;
if(share == NULL)
return CURLSHE_INVALID;
@@ -170,6 +186,12 @@ curl_share_cleanup(CURLSH *sh)
if(share->cookies)
Curl_cookie_cleanup(share->cookies);
+ if(share->sslsession) {
+ for(i = 0; i < share->nsslsession; ++i)
+ Curl_ssl_kill_session(&(share->sslsession[i]));
+ free(share->sslsession);
+ }
+
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
free(share);
diff --git a/lib/share.h b/lib/share.h
index ea8e233d2..cf200008f 100644
--- a/lib/share.h
+++ b/lib/share.h
@@ -26,6 +26,7 @@
#include "setup.h"
#include <curl/curl.h>
#include "cookie.h"
+#include "urldata.h"
/* SalfordC says "A structure member may not be volatile". Hence:
*/
@@ -46,6 +47,9 @@ struct Curl_share {
struct curl_hash *hostcache;
struct CookieInfo *cookies;
+
+ struct curl_ssl_session *sslsession;
+ unsigned int nsslsession;
};
CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
diff --git a/lib/sslgen.c b/lib/sslgen.c
index 005d82ef3..77c641b24 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -62,6 +62,7 @@
#include "url.h"
#include "curl_memory.h"
#include "progress.h"
+#include "share.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -236,6 +237,10 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
/* session ID re-use is disabled */
return TRUE;
+ /* Lock for reading if shared */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SHARED);
+
for(i=0; i< data->set.ssl.numsessions; i++) {
check = &data->state.session[i];
if(!check->sessionid)
@@ -254,13 +259,19 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
}
}
*ssl_sessionid = NULL;
+
+ /* Unlock for reading */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
+
return TRUE;
}
/*
* Kill a single session ID entry in the cache.
*/
-static int kill_session(struct curl_ssl_session *session)
+int Curl_ssl_kill_session(struct curl_ssl_session *session)
{
if(session->sessionid) {
/* defensive check */
@@ -288,14 +299,23 @@ static int kill_session(struct curl_ssl_session *session)
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
{
int i;
- for(i=0; i< conn->data->set.ssl.numsessions; i++) {
- struct curl_ssl_session *check = &conn->data->state.session[i];
+ struct SessionHandle *data=conn->data;
+
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION,
+ CURL_LOCK_ACCESS_SINGLE);
+
+ for(i=0; i< data->set.ssl.numsessions; i++) {
+ struct curl_ssl_session *check = &data->state.session[i];
if(check->sessionid == ssl_sessionid) {
- kill_session(check);
+ Curl_ssl_kill_session(check);
break;
}
}
+
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
}
/*
@@ -325,6 +345,10 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
/* Now we should add the session ID and the host name to the cache, (remove
the oldest if necessary) */
+ /* If using shared SSL session, lock! */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+
/* find an empty slot for us, or find the oldest */
for(i=1; (i<data->set.ssl.numsessions) &&
data->state.session[i].sessionid; i++) {
@@ -335,7 +359,7 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
}
if(i == data->set.ssl.numsessions)
/* cache is full, we must "kill" the oldest entry! */
- kill_session(store);
+ Curl_ssl_kill_session(store);
else
store = &data->state.session[i]; /* use this slot */
@@ -349,6 +373,11 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
store->name = clone_host; /* clone host name */
store->remote_port = conn->remote_port; /* port number */
+
+ /* Unlock */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
@@ -363,14 +392,20 @@ void Curl_ssl_close_all(struct SessionHandle *data)
{
long i;
/* kill the session ID cache */
- if(data->state.session) {
+ if(data->state.session &&
+ !(data->share && data->share->sslsession == data->state.session)) {
+
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+
for(i=0; i< data->set.ssl.numsessions; i++)
/* the single-killer function handles empty table slots */
- kill_session(&data->state.session[i]);
+ Curl_ssl_kill_session(&data->state.session[i]);
/* free the cache data */
free(data->state.session);
data->state.session = NULL;
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
}
curlssl_close_all(data);
diff --git a/lib/sslgen.h b/lib/sslgen.h
index ec8fe50bb..73164fd23 100644
--- a/lib/sslgen.h
+++ b/lib/sslgen.h
@@ -64,6 +64,8 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
void *ssl_sessionid,
size_t idsize);
+/* Kill a single session ID entry in the cache */
+int Curl_ssl_kill_session(struct curl_ssl_session *session);
/* delete a session from the cache */
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
diff --git a/lib/url.c b/lib/url.c
index 086091485..c9135a6b3 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2083,6 +2083,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
if(data->share->cookies == data->cookies)
data->cookies = NULL;
+ if(data->share->sslsession == data->state.session) {
+ data->state.session = NULL;
+ data->set.ssl.numsessions = 0;
+ }
+
data->share->dirty--;
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -2114,6 +2119,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->cookies = data->share->cookies;
}
#endif /* CURL_DISABLE_HTTP */
+ if(data->share->sslsession) {
+ data->set.ssl.numsessions = data->share->nsslsession;
+ data->state.session = data->share->sslsession;
+ }
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}