1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel (at) 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 34 CURLSH * 35 curl_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 if(Curl_mk_dnscache(&share->hostcache)) { 42 free(share); 43 return NULL; 44 } 45 } 46 47 return share; 48 } 49 50 #undef curl_share_setopt 51 CURLSHcode 52 curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) 53 { 54 struct Curl_share *share = (struct Curl_share *)sh; 55 va_list param; 56 int type; 57 curl_lock_function lockfunc; 58 curl_unlock_function unlockfunc; 59 void *ptr; 60 CURLSHcode res = CURLSHE_OK; 61 62 if(share->dirty) 63 /* don't allow setting options while one or more handles are already 64 using this share */ 65 return CURLSHE_IN_USE; 66 67 va_start(param, option); 68 69 switch(option) { 70 case CURLSHOPT_SHARE: 71 /* this is a type this share will share */ 72 type = va_arg(param, int); 73 share->specifier |= (1<<type); 74 switch( type ) { 75 case CURL_LOCK_DATA_DNS: 76 break; 77 78 case CURL_LOCK_DATA_COOKIE: 79 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 80 if(!share->cookies) { 81 share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE ); 82 if(!share->cookies) 83 res = CURLSHE_NOMEM; 84 } 85 #else /* CURL_DISABLE_HTTP */ 86 res = CURLSHE_NOT_BUILT_IN; 87 #endif 88 break; 89 90 case CURL_LOCK_DATA_SSL_SESSION: 91 #ifdef USE_SSL 92 if(!share->sslsession) { 93 share->max_ssl_sessions = 8; 94 share->sslsession = calloc(share->max_ssl_sessions, 95 sizeof(struct curl_ssl_session)); 96 share->sessionage = 0; 97 if(!share->sslsession) 98 res = CURLSHE_NOMEM; 99 } 100 #else 101 res = CURLSHE_NOT_BUILT_IN; 102 #endif 103 break; 104 105 case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ 106 break; 107 108 default: 109 res = CURLSHE_BAD_OPTION; 110 } 111 break; 112 113 case CURLSHOPT_UNSHARE: 114 /* this is a type this share will no longer share */ 115 type = va_arg(param, int); 116 share->specifier &= ~(1<<type); 117 switch( type ) { 118 case CURL_LOCK_DATA_DNS: 119 break; 120 121 case CURL_LOCK_DATA_COOKIE: 122 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 123 if(share->cookies) { 124 Curl_cookie_cleanup(share->cookies); 125 share->cookies = NULL; 126 } 127 #else /* CURL_DISABLE_HTTP */ 128 res = CURLSHE_NOT_BUILT_IN; 129 #endif 130 break; 131 132 case CURL_LOCK_DATA_SSL_SESSION: 133 #ifdef USE_SSL 134 Curl_safefree(share->sslsession); 135 #else 136 res = CURLSHE_NOT_BUILT_IN; 137 #endif 138 break; 139 140 case CURL_LOCK_DATA_CONNECT: 141 break; 142 143 default: 144 res = CURLSHE_BAD_OPTION; 145 break; 146 } 147 break; 148 149 case CURLSHOPT_LOCKFUNC: 150 lockfunc = va_arg(param, curl_lock_function); 151 share->lockfunc = lockfunc; 152 break; 153 154 case CURLSHOPT_UNLOCKFUNC: 155 unlockfunc = va_arg(param, curl_unlock_function); 156 share->unlockfunc = unlockfunc; 157 break; 158 159 case CURLSHOPT_USERDATA: 160 ptr = va_arg(param, void *); 161 share->clientdata = ptr; 162 break; 163 164 default: 165 res = CURLSHE_BAD_OPTION; 166 break; 167 } 168 169 va_end(param); 170 171 return res; 172 } 173 174 CURLSHcode 175 curl_share_cleanup(CURLSH *sh) 176 { 177 struct Curl_share *share = (struct Curl_share *)sh; 178 179 if(share == NULL) 180 return CURLSHE_INVALID; 181 182 if(share->lockfunc) 183 share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, 184 share->clientdata); 185 186 if(share->dirty) { 187 if(share->unlockfunc) 188 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); 189 return CURLSHE_IN_USE; 190 } 191 192 Curl_hash_destroy(&share->hostcache); 193 194 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 195 Curl_cookie_cleanup(share->cookies); 196 #endif 197 198 #ifdef USE_SSL 199 if(share->sslsession) { 200 size_t i; 201 for(i = 0; i < share->max_ssl_sessions; i++) 202 Curl_ssl_kill_session(&(share->sslsession[i])); 203 free(share->sslsession); 204 } 205 #endif 206 207 if(share->unlockfunc) 208 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); 209 free(share); 210 211 return CURLSHE_OK; 212 } 213 214 215 CURLSHcode 216 Curl_share_lock(struct SessionHandle *data, curl_lock_data type, 217 curl_lock_access accesstype) 218 { 219 struct Curl_share *share = data->share; 220 221 if(share == NULL) 222 return CURLSHE_INVALID; 223 224 if(share->specifier & (1<<type)) { 225 if(share->lockfunc) /* only call this if set! */ 226 share->lockfunc(data, type, accesstype, share->clientdata); 227 } 228 /* else if we don't share this, pretend successful lock */ 229 230 return CURLSHE_OK; 231 } 232 233 CURLSHcode 234 Curl_share_unlock(struct SessionHandle *data, curl_lock_data type) 235 { 236 struct Curl_share *share = data->share; 237 238 if(share == NULL) 239 return CURLSHE_INVALID; 240 241 if(share->specifier & (1<<type)) { 242 if(share->unlockfunc) /* only call this if set! */ 243 share->unlockfunc (data, type, share->clientdata); 244 } 245 246 return CURLSHE_OK; 247 } 248