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