Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Utilities / cmcurl / lib / share.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2022, 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.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  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24
25 #include "curl_setup.h"
26
27 #include <curl/curl.h>
28 #include "urldata.h"
29 #include "share.h"
30 #include "psl.h"
31 #include "vtls/vtls.h"
32 #include "curl_memory.h"
33
34 /* The last #include file should be: */
35 #include "memdebug.h"
36
37 struct Curl_share *
38 curl_share_init(void)
39 {
40   struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
41   if(share) {
42     share->magic = CURL_GOOD_SHARE;
43     share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
44     Curl_init_dnscache(&share->hostcache, 23);
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(!GOOD_SHARE_HANDLE(share))
62     return CURLSHE_INVALID;
63
64   if(share->dirty)
65     /* don't allow setting options while one or more handles are already
66        using this share */
67     return CURLSHE_IN_USE;
68
69   va_start(param, option);
70
71   switch(option) {
72   case CURLSHOPT_SHARE:
73     /* this is a type this share will share */
74     type = va_arg(param, int);
75
76     switch(type) {
77     case CURL_LOCK_DATA_DNS:
78       break;
79
80     case CURL_LOCK_DATA_COOKIE:
81 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
82       if(!share->cookies) {
83         share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE);
84         if(!share->cookies)
85           res = CURLSHE_NOMEM;
86       }
87 #else   /* CURL_DISABLE_HTTP */
88       res = CURLSHE_NOT_BUILT_IN;
89 #endif
90       break;
91
92     case CURL_LOCK_DATA_SSL_SESSION:
93 #ifdef USE_SSL
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)
100           res = CURLSHE_NOMEM;
101       }
102 #else
103       res = CURLSHE_NOT_BUILT_IN;
104 #endif
105       break;
106
107     case CURL_LOCK_DATA_CONNECT:
108       if(Curl_conncache_init(&share->conn_cache, 103))
109         res = CURLSHE_NOMEM;
110       break;
111
112     case CURL_LOCK_DATA_PSL:
113 #ifndef USE_LIBPSL
114       res = CURLSHE_NOT_BUILT_IN;
115 #endif
116       break;
117
118     default:
119       res = CURLSHE_BAD_OPTION;
120     }
121     if(!res)
122       share->specifier |= (1<<type);
123     break;
124
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);
129     switch(type) {
130     case CURL_LOCK_DATA_DNS:
131       break;
132
133     case CURL_LOCK_DATA_COOKIE:
134 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
135       if(share->cookies) {
136         Curl_cookie_cleanup(share->cookies);
137         share->cookies = NULL;
138       }
139 #else   /* CURL_DISABLE_HTTP */
140       res = CURLSHE_NOT_BUILT_IN;
141 #endif
142       break;
143
144     case CURL_LOCK_DATA_SSL_SESSION:
145 #ifdef USE_SSL
146       Curl_safefree(share->sslsession);
147 #else
148       res = CURLSHE_NOT_BUILT_IN;
149 #endif
150       break;
151
152     case CURL_LOCK_DATA_CONNECT:
153       break;
154
155     default:
156       res = CURLSHE_BAD_OPTION;
157       break;
158     }
159     break;
160
161   case CURLSHOPT_LOCKFUNC:
162     lockfunc = va_arg(param, curl_lock_function);
163     share->lockfunc = lockfunc;
164     break;
165
166   case CURLSHOPT_UNLOCKFUNC:
167     unlockfunc = va_arg(param, curl_unlock_function);
168     share->unlockfunc = unlockfunc;
169     break;
170
171   case CURLSHOPT_USERDATA:
172     ptr = va_arg(param, void *);
173     share->clientdata = ptr;
174     break;
175
176   default:
177     res = CURLSHE_BAD_OPTION;
178     break;
179   }
180
181   va_end(param);
182
183   return res;
184 }
185
186 CURLSHcode
187 curl_share_cleanup(struct Curl_share *share)
188 {
189   if(!GOOD_SHARE_HANDLE(share))
190     return CURLSHE_INVALID;
191
192   if(share->lockfunc)
193     share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
194                     share->clientdata);
195
196   if(share->dirty) {
197     if(share->unlockfunc)
198       share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
199     return CURLSHE_IN_USE;
200   }
201
202   Curl_conncache_close_all_connections(&share->conn_cache);
203   Curl_conncache_destroy(&share->conn_cache);
204   Curl_hash_destroy(&share->hostcache);
205
206 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
207   Curl_cookie_cleanup(share->cookies);
208 #endif
209
210 #ifdef USE_SSL
211   if(share->sslsession) {
212     size_t i;
213     for(i = 0; i < share->max_ssl_sessions; i++)
214       Curl_ssl_kill_session(&(share->sslsession[i]));
215     free(share->sslsession);
216   }
217 #endif
218
219   Curl_psl_destroy(&share->psl);
220
221   if(share->unlockfunc)
222     share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
223   share->magic = 0;
224   free(share);
225
226   return CURLSHE_OK;
227 }
228
229
230 CURLSHcode
231 Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
232                 curl_lock_access accesstype)
233 {
234   struct Curl_share *share = data->share;
235
236   if(!share)
237     return CURLSHE_INVALID;
238
239   if(share->specifier & (1<<type)) {
240     if(share->lockfunc) /* only call this if set! */
241       share->lockfunc(data, type, accesstype, share->clientdata);
242   }
243   /* else if we don't share this, pretend successful lock */
244
245   return CURLSHE_OK;
246 }
247
248 CURLSHcode
249 Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
250 {
251   struct Curl_share *share = data->share;
252
253   if(!share)
254     return CURLSHE_INVALID;
255
256   if(share->specifier & (1<<type)) {
257     if(share->unlockfunc) /* only call this if set! */
258       share->unlockfunc (data, type, share->clientdata);
259   }
260
261   return CURLSHE_OK;
262 }