mirror of
https://github.com/moparisthebest/curl
synced 2025-02-28 09:21:50 -05:00
SSL session sharing support added
With locking, plus test, plus documentation
This commit is contained in:
parent
ff5ba6e43d
commit
5793bc370c
@ -64,6 +64,11 @@ Cached DNS hosts will be shared across the easy handles using this shared
|
|||||||
object. Note that when you use the multi interface, all easy handles added to
|
object. Note that when you use the multi interface, all easy handles added to
|
||||||
the same multi handle will share DNS cache by default without this having to
|
the same multi handle will share DNS cache by default without this having to
|
||||||
be used!
|
be used!
|
||||||
|
.IP CURL_LOCK_DATA_SSL_SESSION
|
||||||
|
SSL session IDs will be shared accross the easy handles using this shared
|
||||||
|
object. This will reduce the time spent in the SSL handshake when reconnecting
|
||||||
|
to the same server. Note SSL session IDs are reused within the same easy handle
|
||||||
|
by default.
|
||||||
.RE
|
.RE
|
||||||
.IP CURLSHOPT_UNSHARE
|
.IP CURLSHOPT_UNSHARE
|
||||||
This option does the opposite of \fICURLSHOPT_SHARE\fP. It specifies that
|
This option does the opposite of \fICURLSHOPT_SHARE\fP. It specifies that
|
||||||
|
24
lib/share.c
24
lib/share.c
@ -25,6 +25,7 @@
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "share.h"
|
#include "share.h"
|
||||||
|
#include "sslgen.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
@ -82,7 +83,16 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
|
|||||||
break;
|
break;
|
||||||
#endif /* CURL_DISABLE_HTTP */
|
#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) */
|
case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -112,6 +122,11 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
|
|||||||
#endif /* CURL_DISABLE_HTTP */
|
#endif /* CURL_DISABLE_HTTP */
|
||||||
|
|
||||||
case CURL_LOCK_DATA_SSL_SESSION:
|
case CURL_LOCK_DATA_SSL_SESSION:
|
||||||
|
if(share->sslsession) {
|
||||||
|
free(share->sslsession);
|
||||||
|
share->sslsession = NULL;
|
||||||
|
share->nsslsession = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CURL_LOCK_DATA_CONNECT:
|
case CURL_LOCK_DATA_CONNECT:
|
||||||
@ -148,6 +163,7 @@ CURLSHcode
|
|||||||
curl_share_cleanup(CURLSH *sh)
|
curl_share_cleanup(CURLSH *sh)
|
||||||
{
|
{
|
||||||
struct Curl_share *share = (struct Curl_share *)sh;
|
struct Curl_share *share = (struct Curl_share *)sh;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
if(share == NULL)
|
if(share == NULL)
|
||||||
return CURLSHE_INVALID;
|
return CURLSHE_INVALID;
|
||||||
@ -170,6 +186,12 @@ curl_share_cleanup(CURLSH *sh)
|
|||||||
if(share->cookies)
|
if(share->cookies)
|
||||||
Curl_cookie_cleanup(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)
|
if(share->unlockfunc)
|
||||||
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
|
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
|
||||||
free(share);
|
free(share);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "cookie.h"
|
#include "cookie.h"
|
||||||
|
#include "urldata.h"
|
||||||
|
|
||||||
/* SalfordC says "A structure member may not be volatile". Hence:
|
/* SalfordC says "A structure member may not be volatile". Hence:
|
||||||
*/
|
*/
|
||||||
@ -46,6 +47,9 @@ struct Curl_share {
|
|||||||
|
|
||||||
struct curl_hash *hostcache;
|
struct curl_hash *hostcache;
|
||||||
struct CookieInfo *cookies;
|
struct CookieInfo *cookies;
|
||||||
|
|
||||||
|
struct curl_ssl_session *sslsession;
|
||||||
|
unsigned int nsslsession;
|
||||||
};
|
};
|
||||||
|
|
||||||
CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
|
CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
|
||||||
|
49
lib/sslgen.c
49
lib/sslgen.c
@ -62,6 +62,7 @@
|
|||||||
#include "url.h"
|
#include "url.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
|
#include "share.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
@ -236,6 +237,10 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
|
|||||||
/* session ID re-use is disabled */
|
/* session ID re-use is disabled */
|
||||||
return TRUE;
|
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++) {
|
for(i=0; i< data->set.ssl.numsessions; i++) {
|
||||||
check = &data->state.session[i];
|
check = &data->state.session[i];
|
||||||
if(!check->sessionid)
|
if(!check->sessionid)
|
||||||
@ -254,13 +259,19 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ssl_sessionid = NULL;
|
*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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kill a single session ID entry in the cache.
|
* 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) {
|
if(session->sessionid) {
|
||||||
/* defensive check */
|
/* 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)
|
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i< conn->data->set.ssl.numsessions; i++) {
|
struct SessionHandle *data=conn->data;
|
||||||
struct curl_ssl_session *check = &conn->data->state.session[i];
|
|
||||||
|
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) {
|
if(check->sessionid == ssl_sessionid) {
|
||||||
kill_session(check);
|
Curl_ssl_kill_session(check);
|
||||||
break;
|
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
|
/* Now we should add the session ID and the host name to the cache, (remove
|
||||||
the oldest if necessary) */
|
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 */
|
/* find an empty slot for us, or find the oldest */
|
||||||
for(i=1; (i<data->set.ssl.numsessions) &&
|
for(i=1; (i<data->set.ssl.numsessions) &&
|
||||||
data->state.session[i].sessionid; i++) {
|
data->state.session[i].sessionid; i++) {
|
||||||
@ -335,7 +359,7 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
if(i == data->set.ssl.numsessions)
|
if(i == data->set.ssl.numsessions)
|
||||||
/* cache is full, we must "kill" the oldest entry! */
|
/* cache is full, we must "kill" the oldest entry! */
|
||||||
kill_session(store);
|
Curl_ssl_kill_session(store);
|
||||||
else
|
else
|
||||||
store = &data->state.session[i]; /* use this slot */
|
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->name = clone_host; /* clone host name */
|
||||||
store->remote_port = conn->remote_port; /* port number */
|
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)) {
|
if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
|
||||||
store->sessionid = NULL; /* let caller free sessionid */
|
store->sessionid = NULL; /* let caller free sessionid */
|
||||||
free(clone_host);
|
free(clone_host);
|
||||||
@ -363,14 +392,20 @@ void Curl_ssl_close_all(struct SessionHandle *data)
|
|||||||
{
|
{
|
||||||
long i;
|
long i;
|
||||||
/* kill the session ID cache */
|
/* 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++)
|
for(i=0; i< data->set.ssl.numsessions; i++)
|
||||||
/* the single-killer function handles empty table slots */
|
/* 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 the cache data */
|
||||||
free(data->state.session);
|
free(data->state.session);
|
||||||
data->state.session = NULL;
|
data->state.session = NULL;
|
||||||
|
|
||||||
|
Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
curlssl_close_all(data);
|
curlssl_close_all(data);
|
||||||
|
@ -64,6 +64,8 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
|
|||||||
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||||
void *ssl_sessionid,
|
void *ssl_sessionid,
|
||||||
size_t idsize);
|
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 */
|
/* delete a session from the cache */
|
||||||
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
|
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
|
||||||
|
|
||||||
|
@ -2083,6 +2083,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
if(data->share->cookies == data->cookies)
|
if(data->share->cookies == data->cookies)
|
||||||
data->cookies = NULL;
|
data->cookies = NULL;
|
||||||
|
|
||||||
|
if(data->share->sslsession == data->state.session) {
|
||||||
|
data->state.session = NULL;
|
||||||
|
data->set.ssl.numsessions = 0;
|
||||||
|
}
|
||||||
|
|
||||||
data->share->dirty--;
|
data->share->dirty--;
|
||||||
|
|
||||||
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
|
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;
|
data->cookies = data->share->cookies;
|
||||||
}
|
}
|
||||||
#endif /* CURL_DISABLE_HTTP */
|
#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);
|
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
246
tests/libtest/lib586.c
Normal file
246
tests/libtest/lib586.c
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
#define THREADS 2
|
||||||
|
|
||||||
|
/* struct containing data of a thread */
|
||||||
|
struct Tdata {
|
||||||
|
CURLSH *share;
|
||||||
|
char *url;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct userdata {
|
||||||
|
char *text;
|
||||||
|
int counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* lock callback */
|
||||||
|
static void my_lock(CURL *handle, curl_lock_data data, curl_lock_access laccess,
|
||||||
|
void *useptr )
|
||||||
|
{
|
||||||
|
const char *what;
|
||||||
|
struct userdata *user = (struct userdata *)useptr;
|
||||||
|
|
||||||
|
(void)handle;
|
||||||
|
(void)laccess;
|
||||||
|
|
||||||
|
switch ( data ) {
|
||||||
|
case CURL_LOCK_DATA_SHARE:
|
||||||
|
what = "share";
|
||||||
|
break;
|
||||||
|
case CURL_LOCK_DATA_DNS:
|
||||||
|
what = "dns";
|
||||||
|
break;
|
||||||
|
case CURL_LOCK_DATA_COOKIE:
|
||||||
|
what = "cookie";
|
||||||
|
break;
|
||||||
|
case CURL_LOCK_DATA_SSL_SESSION:
|
||||||
|
what = "ssl_session";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "lock: no such data: %d\n", (int)data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("lock: %-6s [%s]: %d\n", what, user->text, user->counter);
|
||||||
|
user->counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlock callback */
|
||||||
|
static void my_unlock(CURL *handle, curl_lock_data data, void *useptr )
|
||||||
|
{
|
||||||
|
const char *what;
|
||||||
|
struct userdata *user = (struct userdata *)useptr;
|
||||||
|
(void)handle;
|
||||||
|
switch ( data ) {
|
||||||
|
case CURL_LOCK_DATA_SHARE:
|
||||||
|
what = "share";
|
||||||
|
break;
|
||||||
|
case CURL_LOCK_DATA_DNS:
|
||||||
|
what = "dns";
|
||||||
|
break;
|
||||||
|
case CURL_LOCK_DATA_COOKIE:
|
||||||
|
what = "cookie";
|
||||||
|
break;
|
||||||
|
case CURL_LOCK_DATA_SSL_SESSION:
|
||||||
|
what = "ssl_session";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unlock: no such data: %d\n", (int)data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("unlock: %-6s [%s]: %d\n", what, user->text, user->counter);
|
||||||
|
user->counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the dummy thread function */
|
||||||
|
static void *fire(void *ptr)
|
||||||
|
{
|
||||||
|
CURLcode code;
|
||||||
|
struct Tdata *tdata = (struct Tdata*)ptr;
|
||||||
|
CURL *curl;
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
if ((curl = curl_easy_init()) == NULL) {
|
||||||
|
fprintf(stderr, "curl_easy_init() failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, tdata->url);
|
||||||
|
printf( "CURLOPT_SHARE\n" );
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share);
|
||||||
|
|
||||||
|
printf( "PERFORM\n" );
|
||||||
|
code = curl_easy_perform(curl);
|
||||||
|
if( code != CURLE_OK ) {
|
||||||
|
fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n",
|
||||||
|
tdata->url, i, (int)code);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf( "CLEANUP\n" );
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test function */
|
||||||
|
int test(char *URL)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
CURLSHcode scode = CURLSHE_OK;
|
||||||
|
char *url;
|
||||||
|
struct Tdata tdata;
|
||||||
|
CURL *curl;
|
||||||
|
CURLSH *share;
|
||||||
|
int i;
|
||||||
|
struct userdata user;
|
||||||
|
|
||||||
|
user.text = (char *)"Pigs in space";
|
||||||
|
user.counter = 0;
|
||||||
|
|
||||||
|
printf( "GLOBAL_INIT\n" );
|
||||||
|
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
|
||||||
|
fprintf(stderr, "curl_global_init() failed\n");
|
||||||
|
return TEST_ERR_MAJOR_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare share */
|
||||||
|
printf( "SHARE_INIT\n" );
|
||||||
|
if ((share = curl_share_init()) == NULL) {
|
||||||
|
fprintf(stderr, "curl_share_init() failed\n");
|
||||||
|
curl_global_cleanup();
|
||||||
|
return TEST_ERR_MAJOR_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CURLSHE_OK == scode ) {
|
||||||
|
printf( "CURLSHOPT_LOCKFUNC\n" );
|
||||||
|
scode = curl_share_setopt( share, CURLSHOPT_LOCKFUNC, my_lock);
|
||||||
|
}
|
||||||
|
if ( CURLSHE_OK == scode ) {
|
||||||
|
printf( "CURLSHOPT_UNLOCKFUNC\n" );
|
||||||
|
scode = curl_share_setopt( share, CURLSHOPT_UNLOCKFUNC, my_unlock);
|
||||||
|
}
|
||||||
|
if ( CURLSHE_OK == scode ) {
|
||||||
|
printf( "CURLSHOPT_USERDATA\n" );
|
||||||
|
scode = curl_share_setopt( share, CURLSHOPT_USERDATA, &user);
|
||||||
|
}
|
||||||
|
if ( CURLSHE_OK == scode ) {
|
||||||
|
printf( "CURL_LOCK_DATA_SSL_SESSION\n" );
|
||||||
|
scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CURLSHE_OK != scode ) {
|
||||||
|
fprintf(stderr, "curl_share_setopt() failed\n");
|
||||||
|
curl_share_cleanup(share);
|
||||||
|
curl_global_cleanup();
|
||||||
|
return TEST_ERR_MAJOR_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
/* start treads */
|
||||||
|
for (i=1; i<=THREADS; i++ ) {
|
||||||
|
|
||||||
|
/* set thread data */
|
||||||
|
tdata.url = URL;
|
||||||
|
tdata.share = share;
|
||||||
|
|
||||||
|
/* simulate thread, direct call of "thread" function */
|
||||||
|
printf( "*** run %d\n",i );
|
||||||
|
fire( &tdata );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fetch a another one */
|
||||||
|
printf( "*** run %d\n", i );
|
||||||
|
if ((curl = curl_easy_init()) == NULL) {
|
||||||
|
fprintf(stderr, "curl_easy_init() failed\n");
|
||||||
|
curl_share_cleanup(share);
|
||||||
|
curl_global_cleanup();
|
||||||
|
return TEST_ERR_MAJOR_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = URL;
|
||||||
|
test_setopt( curl, CURLOPT_URL, url );
|
||||||
|
printf( "CURLOPT_SHARE\n" );
|
||||||
|
test_setopt( curl, CURLOPT_SHARE, share );
|
||||||
|
|
||||||
|
printf( "PERFORM\n" );
|
||||||
|
curl_easy_perform( curl );
|
||||||
|
|
||||||
|
/* try to free share, expect to fail because share is in use*/
|
||||||
|
printf( "try SHARE_CLEANUP...\n" );
|
||||||
|
scode = curl_share_cleanup( share );
|
||||||
|
if ( scode==CURLSHE_OK )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "curl_share_cleanup succeed but error expected\n");
|
||||||
|
share = NULL;
|
||||||
|
} else {
|
||||||
|
printf( "SHARE_CLEANUP failed, correct\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
test_cleanup:
|
||||||
|
|
||||||
|
/* clean up last handle */
|
||||||
|
printf( "CLEANUP\n" );
|
||||||
|
curl_easy_cleanup( curl );
|
||||||
|
|
||||||
|
/* free share */
|
||||||
|
printf( "SHARE_CLEANUP\n" );
|
||||||
|
scode = curl_share_cleanup( share );
|
||||||
|
if ( scode!=CURLSHE_OK )
|
||||||
|
fprintf(stderr, "curl_share_cleanup failed, code errno %d\n",
|
||||||
|
(int)scode);
|
||||||
|
|
||||||
|
printf( "GLOBAL_CLEANUP\n" );
|
||||||
|
curl_global_cleanup();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user