1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23#include "curl_setup.h" 24 25#include <curl/curl.h> 26#include "urldata.h" 27#include "share.h" 28#include "vtls/vtls.h" 29#include "curl_memory.h" 30 31/* The last #include file should be: */ 32#include "memdebug.h" 33 34CURLSH * 35curl_share_init(void) 36{ 37 struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); 38 if(share) 39 share->specifier |= (1<<CURL_LOCK_DATA_SHARE); 40 41 return share; 42} 43 44#undef curl_share_setopt 45CURLSHcode 46curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) 47{ 48 struct Curl_share *share = (struct Curl_share *)sh; 49 va_list param; 50 int type; 51 curl_lock_function lockfunc; 52 curl_unlock_function unlockfunc; 53 void *ptr; 54 CURLSHcode res = CURLSHE_OK; 55 56 if(share->dirty) 57 /* don't allow setting options while one or more handles are already 58 using this share */ 59 return CURLSHE_IN_USE; 60 61 va_start(param, option); 62 63 switch(option) { 64 case CURLSHOPT_SHARE: 65 /* this is a type this share will share */ 66 type = va_arg(param, int); 67 share->specifier |= (1<<type); 68 switch( type ) { 69 case CURL_LOCK_DATA_DNS: 70 if(!share->hostcache) { 71 share->hostcache = Curl_mk_dnscache(); 72 if(!share->hostcache) 73 res = CURLSHE_NOMEM; 74 } 75 break; 76 77 case CURL_LOCK_DATA_COOKIE: 78#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 79 if(!share->cookies) { 80 share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE ); 81 if(!share->cookies) 82 res = CURLSHE_NOMEM; 83 } 84#else /* CURL_DISABLE_HTTP */ 85 res = CURLSHE_NOT_BUILT_IN; 86#endif 87 break; 88 89 case CURL_LOCK_DATA_SSL_SESSION: 90#ifdef USE_SSL 91 if(!share->sslsession) { 92 share->max_ssl_sessions = 8; 93 share->sslsession = calloc(share->max_ssl_sessions, 94 sizeof(struct curl_ssl_session)); 95 share->sessionage = 0; 96 if(!share->sslsession) 97 res = CURLSHE_NOMEM; 98 } 99#else 100 res = CURLSHE_NOT_BUILT_IN; 101#endif 102 break; 103 104 case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ 105 break; 106 107 default: 108 res = CURLSHE_BAD_OPTION; 109 } 110 break; 111 112 case CURLSHOPT_UNSHARE: 113 /* this is a type this share will no longer share */ 114 type = va_arg(param, int); 115 share->specifier &= ~(1<<type); 116 switch( type ) { 117 case CURL_LOCK_DATA_DNS: 118 if(share->hostcache) { 119 Curl_hash_destroy(share->hostcache); 120 share->hostcache = NULL; 121 } 122 break; 123 124 case CURL_LOCK_DATA_COOKIE: 125#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 126 if(share->cookies) { 127 Curl_cookie_cleanup(share->cookies); 128 share->cookies = NULL; 129 } 130#else /* CURL_DISABLE_HTTP */ 131 res = CURLSHE_NOT_BUILT_IN; 132#endif 133 break; 134 135 case CURL_LOCK_DATA_SSL_SESSION: 136#ifdef USE_SSL 137 Curl_safefree(share->sslsession); 138#else 139 res = CURLSHE_NOT_BUILT_IN; 140#endif 141 break; 142 143 case CURL_LOCK_DATA_CONNECT: 144 break; 145 146 default: 147 res = CURLSHE_BAD_OPTION; 148 break; 149 } 150 break; 151 152 case CURLSHOPT_LOCKFUNC: 153 lockfunc = va_arg(param, curl_lock_function); 154 share->lockfunc = lockfunc; 155 break; 156 157 case CURLSHOPT_UNLOCKFUNC: 158 unlockfunc = va_arg(param, curl_unlock_function); 159 share->unlockfunc = unlockfunc; 160 break; 161 162 case CURLSHOPT_USERDATA: 163 ptr = va_arg(param, void *); 164 share->clientdata = ptr; 165 break; 166 167 default: 168 res = CURLSHE_BAD_OPTION; 169 break; 170 } 171 172 va_end(param); 173 174 return res; 175} 176 177CURLSHcode 178curl_share_cleanup(CURLSH *sh) 179{ 180 struct Curl_share *share = (struct Curl_share *)sh; 181 182 if(share == NULL) 183 return CURLSHE_INVALID; 184 185 if(share->lockfunc) 186 share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, 187 share->clientdata); 188 189 if(share->dirty) { 190 if(share->unlockfunc) 191 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); 192 return CURLSHE_IN_USE; 193 } 194 195 if(share->hostcache) { 196 Curl_hash_destroy(share->hostcache); 197 share->hostcache = NULL; 198 } 199 200#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 201 if(share->cookies) 202 Curl_cookie_cleanup(share->cookies); 203#endif 204 205#ifdef USE_SSL 206 if(share->sslsession) { 207 size_t i; 208 for(i = 0; i < share->max_ssl_sessions; i++) 209 Curl_ssl_kill_session(&(share->sslsession[i])); 210 free(share->sslsession); 211 } 212#endif 213 214 if(share->unlockfunc) 215 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); 216 free(share); 217 218 return CURLSHE_OK; 219} 220 221 222CURLSHcode 223Curl_share_lock(struct SessionHandle *data, curl_lock_data type, 224 curl_lock_access accesstype) 225{ 226 struct Curl_share *share = data->share; 227 228 if(share == NULL) 229 return CURLSHE_INVALID; 230 231 if(share->specifier & (1<<type)) { 232 if(share->lockfunc) /* only call this if set! */ 233 share->lockfunc(data, type, accesstype, share->clientdata); 234 } 235 /* else if we don't share this, pretend successful lock */ 236 237 return CURLSHE_OK; 238} 239 240CURLSHcode 241Curl_share_unlock(struct SessionHandle *data, curl_lock_data type) 242{ 243 struct Curl_share *share = data->share; 244 245 if(share == NULL) 246 return CURLSHE_INVALID; 247 248 if(share->specifier & (1<<type)) { 249 if(share->unlockfunc) /* only call this if set! */ 250 share->unlockfunc (data, type, share->clientdata); 251 } 252 253 return CURLSHE_OK; 254} 255