Coverage Report

Created: 2022-10-16 06:45

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