1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
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.se/docs/copyright.html.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * SPDX-License-Identifier: curl
23 ***************************************************************************/
25 #include "curl_setup.h"
27 #include <curl/curl.h>
31 #include "vtls/vtls.h"
32 #include "curl_memory.h"
34 /* The last #include file should be: */
40 struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
42 share->magic = CURL_GOOD_SHARE;
43 share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
44 Curl_init_dnscache(&share->hostcache, 23);
50 #undef curl_share_setopt
52 curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
56 curl_lock_function lockfunc;
57 curl_unlock_function unlockfunc;
59 CURLSHcode res = CURLSHE_OK;
61 if(!GOOD_SHARE_HANDLE(share))
62 return CURLSHE_INVALID;
65 /* don't allow setting options while one or more handles are already
67 return CURLSHE_IN_USE;
69 va_start(param, option);
73 /* this is a type this share will share */
74 type = va_arg(param, int);
77 case CURL_LOCK_DATA_DNS:
80 case CURL_LOCK_DATA_COOKIE:
81 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
83 share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE);
87 #else /* CURL_DISABLE_HTTP */
88 res = CURLSHE_NOT_BUILT_IN;
92 case CURL_LOCK_DATA_SSL_SESSION:
94 if(!share->sslsession) {
95 share->max_ssl_sessions = 8;
96 share->sslsession = calloc(share->max_ssl_sessions,
97 sizeof(struct Curl_ssl_session));
98 share->sessionage = 0;
99 if(!share->sslsession)
103 res = CURLSHE_NOT_BUILT_IN;
107 case CURL_LOCK_DATA_CONNECT:
108 if(Curl_conncache_init(&share->conn_cache, 103))
112 case CURL_LOCK_DATA_PSL:
114 res = CURLSHE_NOT_BUILT_IN;
119 res = CURLSHE_BAD_OPTION;
122 share->specifier |= (1<<type);
125 case CURLSHOPT_UNSHARE:
126 /* this is a type this share will no longer share */
127 type = va_arg(param, int);
128 share->specifier &= ~(1<<type);
130 case CURL_LOCK_DATA_DNS:
133 case CURL_LOCK_DATA_COOKIE:
134 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
136 Curl_cookie_cleanup(share->cookies);
137 share->cookies = NULL;
139 #else /* CURL_DISABLE_HTTP */
140 res = CURLSHE_NOT_BUILT_IN;
144 case CURL_LOCK_DATA_SSL_SESSION:
146 Curl_safefree(share->sslsession);
148 res = CURLSHE_NOT_BUILT_IN;
152 case CURL_LOCK_DATA_CONNECT:
156 res = CURLSHE_BAD_OPTION;
161 case CURLSHOPT_LOCKFUNC:
162 lockfunc = va_arg(param, curl_lock_function);
163 share->lockfunc = lockfunc;
166 case CURLSHOPT_UNLOCKFUNC:
167 unlockfunc = va_arg(param, curl_unlock_function);
168 share->unlockfunc = unlockfunc;
171 case CURLSHOPT_USERDATA:
172 ptr = va_arg(param, void *);
173 share->clientdata = ptr;
177 res = CURLSHE_BAD_OPTION;
187 curl_share_cleanup(struct Curl_share *share)
189 if(!GOOD_SHARE_HANDLE(share))
190 return CURLSHE_INVALID;
193 share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
197 if(share->unlockfunc)
198 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
199 return CURLSHE_IN_USE;
202 Curl_conncache_close_all_connections(&share->conn_cache);
203 Curl_conncache_destroy(&share->conn_cache);
204 Curl_hash_destroy(&share->hostcache);
206 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
207 Curl_cookie_cleanup(share->cookies);
211 if(share->sslsession) {
213 for(i = 0; i < share->max_ssl_sessions; i++)
214 Curl_ssl_kill_session(&(share->sslsession[i]));
215 free(share->sslsession);
219 Curl_psl_destroy(&share->psl);
221 if(share->unlockfunc)
222 share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
231 Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
232 curl_lock_access accesstype)
234 struct Curl_share *share = data->share;
237 return CURLSHE_INVALID;
239 if(share->specifier & (1<<type)) {
240 if(share->lockfunc) /* only call this if set! */
241 share->lockfunc(data, type, accesstype, share->clientdata);
243 /* else if we don't share this, pretend successful lock */
249 Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
251 struct Curl_share *share = data->share;
254 return CURLSHE_INVALID;
256 if(share->specifier & (1<<type)) {
257 if(share->unlockfunc) /* only call this if set! */
258 share->unlockfunc (data, type, share->clientdata);