Coverage Report

Created: 2024-02-25 06:14

/src/PROJ/curl/lib/share.c
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) 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 "hsts.h"
33
34
/* The last 3 #include files should be in this order */
35
#include "curl_printf.h"
36
#include "curl_memory.h"
37
#include "memdebug.h"
38
39
struct Curl_share *
40
curl_share_init(void)
41
0
{
42
0
  struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
43
0
  if(share) {
44
0
    share->magic = CURL_GOOD_SHARE;
45
0
    share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
46
0
    Curl_init_dnscache(&share->hostcache, 23);
47
0
  }
48
49
0
  return share;
50
0
}
51
52
#undef curl_share_setopt
53
CURLSHcode
54
curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
55
0
{
56
0
  va_list param;
57
0
  int type;
58
0
  curl_lock_function lockfunc;
59
0
  curl_unlock_function unlockfunc;
60
0
  void *ptr;
61
0
  CURLSHcode res = CURLSHE_OK;
62
63
0
  if(!GOOD_SHARE_HANDLE(share))
64
0
    return CURLSHE_INVALID;
65
66
0
  if(share->dirty)
67
    /* don't allow setting options while one or more handles are already
68
       using this share */
69
0
    return CURLSHE_IN_USE;
70
71
0
  va_start(param, option);
72
73
0
  switch(option) {
74
0
  case CURLSHOPT_SHARE:
75
    /* this is a type this share will share */
76
0
    type = va_arg(param, int);
77
78
0
    switch(type) {
79
0
    case CURL_LOCK_DATA_DNS:
80
0
      break;
81
82
0
    case CURL_LOCK_DATA_COOKIE:
83
0
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
84
0
      if(!share->cookies) {
85
0
        share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE);
86
0
        if(!share->cookies)
87
0
          res = CURLSHE_NOMEM;
88
0
      }
89
#else   /* CURL_DISABLE_HTTP */
90
      res = CURLSHE_NOT_BUILT_IN;
91
#endif
92
0
      break;
93
94
0
    case CURL_LOCK_DATA_HSTS:
95
0
#ifndef CURL_DISABLE_HSTS
96
0
      if(!share->hsts) {
97
0
        share->hsts = Curl_hsts_init();
98
0
        if(!share->hsts)
99
0
          res = CURLSHE_NOMEM;
100
0
      }
101
#else   /* CURL_DISABLE_HSTS */
102
      res = CURLSHE_NOT_BUILT_IN;
103
#endif
104
0
      break;
105
106
0
    case CURL_LOCK_DATA_SSL_SESSION:
107
0
#ifdef USE_SSL
108
0
      if(!share->sslsession) {
109
0
        share->max_ssl_sessions = 8;
110
0
        share->sslsession = calloc(share->max_ssl_sessions,
111
0
                                   sizeof(struct Curl_ssl_session));
112
0
        share->sessionage = 0;
113
0
        if(!share->sslsession)
114
0
          res = CURLSHE_NOMEM;
115
0
      }
116
#else
117
      res = CURLSHE_NOT_BUILT_IN;
118
#endif
119
0
      break;
120
121
0
    case CURL_LOCK_DATA_CONNECT:
122
0
      if(Curl_conncache_init(&share->conn_cache, 103))
123
0
        res = CURLSHE_NOMEM;
124
0
      break;
125
126
0
    case CURL_LOCK_DATA_PSL:
127
0
#ifndef USE_LIBPSL
128
0
      res = CURLSHE_NOT_BUILT_IN;
129
0
#endif
130
0
      break;
131
132
0
    default:
133
0
      res = CURLSHE_BAD_OPTION;
134
0
    }
135
0
    if(!res)
136
0
      share->specifier |= (unsigned int)(1<<type);
137
0
    break;
138
139
0
  case CURLSHOPT_UNSHARE:
140
    /* this is a type this share will no longer share */
141
0
    type = va_arg(param, int);
142
0
    share->specifier &= ~(unsigned int)(1<<type);
143
0
    switch(type) {
144
0
    case CURL_LOCK_DATA_DNS:
145
0
      break;
146
147
0
    case CURL_LOCK_DATA_COOKIE:
148
0
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
149
0
      if(share->cookies) {
150
0
        Curl_cookie_cleanup(share->cookies);
151
0
        share->cookies = NULL;
152
0
      }
153
#else   /* CURL_DISABLE_HTTP */
154
      res = CURLSHE_NOT_BUILT_IN;
155
#endif
156
0
      break;
157
158
0
    case CURL_LOCK_DATA_HSTS:
159
0
#ifndef CURL_DISABLE_HSTS
160
0
      if(share->hsts) {
161
0
        Curl_hsts_cleanup(&share->hsts);
162
0
      }
163
#else   /* CURL_DISABLE_HSTS */
164
      res = CURLSHE_NOT_BUILT_IN;
165
#endif
166
0
      break;
167
168
0
    case CURL_LOCK_DATA_SSL_SESSION:
169
0
#ifdef USE_SSL
170
0
      Curl_safefree(share->sslsession);
171
#else
172
      res = CURLSHE_NOT_BUILT_IN;
173
#endif
174
0
      break;
175
176
0
    case CURL_LOCK_DATA_CONNECT:
177
0
      break;
178
179
0
    default:
180
0
      res = CURLSHE_BAD_OPTION;
181
0
      break;
182
0
    }
183
0
    break;
184
185
0
  case CURLSHOPT_LOCKFUNC:
186
0
    lockfunc = va_arg(param, curl_lock_function);
187
0
    share->lockfunc = lockfunc;
188
0
    break;
189
190
0
  case CURLSHOPT_UNLOCKFUNC:
191
0
    unlockfunc = va_arg(param, curl_unlock_function);
192
0
    share->unlockfunc = unlockfunc;
193
0
    break;
194
195
0
  case CURLSHOPT_USERDATA:
196
0
    ptr = va_arg(param, void *);
197
0
    share->clientdata = ptr;
198
0
    break;
199
200
0
  default:
201
0
    res = CURLSHE_BAD_OPTION;
202
0
    break;
203
0
  }
204
205
0
  va_end(param);
206
207
0
  return res;
208
0
}
209
210
CURLSHcode
211
curl_share_cleanup(struct Curl_share *share)
212
0
{
213
0
  if(!GOOD_SHARE_HANDLE(share))
214
0
    return CURLSHE_INVALID;
215
216
0
  if(share->lockfunc)
217
0
    share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
218
0
                    share->clientdata);
219
220
0
  if(share->dirty) {
221
0
    if(share->unlockfunc)
222
0
      share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
223
0
    return CURLSHE_IN_USE;
224
0
  }
225
226
0
  Curl_conncache_close_all_connections(&share->conn_cache);
227
0
  Curl_conncache_destroy(&share->conn_cache);
228
0
  Curl_hash_destroy(&share->hostcache);
229
230
0
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
231
0
  Curl_cookie_cleanup(share->cookies);
232
0
#endif
233
234
0
#ifndef CURL_DISABLE_HSTS
235
0
  Curl_hsts_cleanup(&share->hsts);
236
0
#endif
237
238
0
#ifdef USE_SSL
239
0
  if(share->sslsession) {
240
0
    size_t i;
241
0
    for(i = 0; i < share->max_ssl_sessions; i++)
242
0
      Curl_ssl_kill_session(&(share->sslsession[i]));
243
0
    free(share->sslsession);
244
0
  }
245
0
#endif
246
247
0
  Curl_psl_destroy(&share->psl);
248
249
0
  if(share->unlockfunc)
250
0
    share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
251
0
  share->magic = 0;
252
0
  free(share);
253
254
0
  return CURLSHE_OK;
255
0
}
256
257
258
CURLSHcode
259
Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
260
                curl_lock_access accesstype)
261
0
{
262
0
  struct Curl_share *share = data->share;
263
264
0
  if(!share)
265
0
    return CURLSHE_INVALID;
266
267
0
  if(share->specifier & (unsigned int)(1<<type)) {
268
0
    if(share->lockfunc) /* only call this if set! */
269
0
      share->lockfunc(data, type, accesstype, share->clientdata);
270
0
  }
271
  /* else if we don't share this, pretend successful lock */
272
273
0
  return CURLSHE_OK;
274
0
}
275
276
CURLSHcode
277
Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
278
0
{
279
0
  struct Curl_share *share = data->share;
280
281
0
  if(!share)
282
0
    return CURLSHE_INVALID;
283
284
0
  if(share->specifier & (unsigned int)(1<<type)) {
285
0
    if(share->unlockfunc) /* only call this if set! */
286
0
      share->unlockfunc (data, type, share->clientdata);
287
0
  }
288
289
0
  return CURLSHE_OK;
290
0
}