VirtualBox

source: vbox/trunk/src/libs/curl-8.11.1/lib/curl_trc.c@ 108048

Last change on this file since 108048 was 108048, checked in by vboxsync, 8 weeks ago

curl-8.11.1: Applied and adjusted our curl changes to 8.7.1. jiraref:VBP-1535

File size: 11.1 KB
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
29#include "curl_trc.h"
30#include "urldata.h"
31#include "easyif.h"
32#include "cfilters.h"
33#include "timeval.h"
34#include "multiif.h"
35#include "strcase.h"
36
37#include "cf-socket.h"
38#include "connect.h"
39#include "doh.h"
40#include "http2.h"
41#include "http_proxy.h"
42#include "cf-h1-proxy.h"
43#include "cf-h2-proxy.h"
44#include "cf-haproxy.h"
45#include "cf-https-connect.h"
46#include "socks.h"
47#include "strtok.h"
48#include "vtls/vtls.h"
49#include "vquic/vquic.h"
50
51/* The last 3 #include files should be in this order */
52#include "curl_printf.h"
53#include "curl_memory.h"
54#include "memdebug.h"
55
56#ifndef ARRAYSIZE
57#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
58#endif
59
60void Curl_debug(struct Curl_easy *data, curl_infotype type,
61 char *ptr, size_t size)
62{
63 if(data->set.verbose) {
64 static const char s_infotype[CURLINFO_END][3] = {
65 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
66 if(data->set.fdebug) {
67 bool inCallback = Curl_is_in_callback(data);
68 Curl_set_in_callback(data, TRUE);
69 (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
70 Curl_set_in_callback(data, inCallback);
71 }
72 else {
73 switch(type) {
74 case CURLINFO_TEXT:
75 case CURLINFO_HEADER_OUT:
76 case CURLINFO_HEADER_IN:
77 fwrite(s_infotype[type], 2, 1, data->set.err);
78 fwrite(ptr, size, 1, data->set.err);
79 break;
80 default: /* nada */
81 break;
82 }
83 }
84 }
85}
86
87
88/* Curl_failf() is for messages stating why we failed.
89 * The message SHALL NOT include any LF or CR.
90 */
91void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
92{
93 DEBUGASSERT(!strchr(fmt, '\n'));
94 if(data->set.verbose || data->set.errorbuffer) {
95 va_list ap;
96 int len;
97 char error[CURL_ERROR_SIZE + 2];
98 va_start(ap, fmt);
99 len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
100
101 if(data->set.errorbuffer && !data->state.errorbuf) {
102 strcpy(data->set.errorbuffer, error);
103 data->state.errorbuf = TRUE; /* wrote error string */
104 }
105 error[len++] = '\n';
106 error[len] = '\0';
107 Curl_debug(data, CURLINFO_TEXT, error, len);
108 va_end(ap);
109 }
110}
111
112#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
113
114/* Curl_infof() is for info message along the way */
115#define MAXINFO 2048
116
117static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
118 const char * const fmt, va_list ap) CURL_PRINTF(3, 0);
119
120static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
121 const char * const fmt, va_list ap)
122{
123 int len = 0;
124 char buffer[MAXINFO + 5];
125 if(feat)
126 len = msnprintf(buffer, (MAXINFO + 1), "[%s] ", feat->name);
127 len += mvsnprintf(buffer + len, (MAXINFO + 1) - len, fmt, ap);
128 if(len >= MAXINFO) { /* too long, shorten with '...' */
129 --len;
130 buffer[len++] = '.';
131 buffer[len++] = '.';
132 buffer[len++] = '.';
133 }
134 buffer[len++] = '\n';
135 buffer[len] = '\0';
136 Curl_debug(data, CURLINFO_TEXT, buffer, len);
137}
138
139void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
140{
141 DEBUGASSERT(!strchr(fmt, '\n'));
142 if(Curl_trc_is_verbose(data)) {
143 va_list ap;
144 va_start(ap, fmt);
145 trc_infof(data, data->state.feat, fmt, ap);
146 va_end(ap);
147 }
148}
149
150void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
151 const char *fmt, ...)
152{
153 DEBUGASSERT(cf);
154 if(Curl_trc_cf_is_verbose(cf, data)) {
155 va_list ap;
156 int len = 0;
157 char buffer[MAXINFO + 2];
158 if(data->state.feat)
159 len += msnprintf(buffer + len, MAXINFO - len, "[%s] ",
160 data->state.feat->name);
161 if(cf->sockindex)
162 len += msnprintf(buffer + len, MAXINFO - len, "[%s-%d] ",
163 cf->cft->name, cf->sockindex);
164 else
165 len += msnprintf(buffer + len, MAXINFO - len, "[%s] ", cf->cft->name);
166 va_start(ap, fmt);
167 len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
168 va_end(ap);
169 buffer[len++] = '\n';
170 buffer[len] = '\0';
171 Curl_debug(data, CURLINFO_TEXT, buffer, len);
172 }
173}
174
175struct curl_trc_feat Curl_trc_feat_read = {
176 "READ",
177 CURL_LOG_LVL_NONE,
178};
179struct curl_trc_feat Curl_trc_feat_write = {
180 "WRITE",
181 CURL_LOG_LVL_NONE,
182};
183
184void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
185{
186 DEBUGASSERT(!strchr(fmt, '\n'));
187 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_read)) {
188 va_list ap;
189 va_start(ap, fmt);
190 trc_infof(data, &Curl_trc_feat_read, fmt, ap);
191 va_end(ap);
192 }
193}
194
195void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
196{
197 DEBUGASSERT(!strchr(fmt, '\n'));
198 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_write)) {
199 va_list ap;
200 va_start(ap, fmt);
201 trc_infof(data, &Curl_trc_feat_write, fmt, ap);
202 va_end(ap);
203 }
204}
205
206#ifndef CURL_DISABLE_FTP
207struct curl_trc_feat Curl_trc_feat_ftp = {
208 "FTP",
209 CURL_LOG_LVL_NONE,
210};
211
212void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
213{
214 DEBUGASSERT(!strchr(fmt, '\n'));
215 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) {
216 va_list ap;
217 va_start(ap, fmt);
218 trc_infof(data, &Curl_trc_feat_ftp, fmt, ap);
219 va_end(ap);
220 }
221}
222#endif /* !CURL_DISABLE_FTP */
223
224#ifndef CURL_DISABLE_SMTP
225struct curl_trc_feat Curl_trc_feat_smtp = {
226 "SMTP",
227 CURL_LOG_LVL_NONE,
228};
229
230void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
231{
232 DEBUGASSERT(!strchr(fmt, '\n'));
233 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_smtp)) {
234 va_list ap;
235 va_start(ap, fmt);
236 trc_infof(data, &Curl_trc_feat_smtp, fmt, ap);
237 va_end(ap);
238 }
239}
240#endif /* !CURL_DISABLE_SMTP */
241
242#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
243struct curl_trc_feat Curl_trc_feat_ws = {
244 "WS",
245 CURL_LOG_LVL_NONE,
246};
247
248void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
249{
250 DEBUGASSERT(!strchr(fmt, '\n'));
251 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) {
252 va_list ap;
253 va_start(ap, fmt);
254 trc_infof(data, &Curl_trc_feat_ws, fmt, ap);
255 va_end(ap);
256 }
257}
258#endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */
259
260#define TRC_CT_NONE (0)
261#define TRC_CT_PROTOCOL (1<<(0))
262#define TRC_CT_NETWORK (1<<(1))
263#define TRC_CT_PROXY (1<<(2))
264
265struct trc_feat_def {
266 struct curl_trc_feat *feat;
267 unsigned int category;
268};
269
270static struct trc_feat_def trc_feats[] = {
271 { &Curl_trc_feat_read, TRC_CT_NONE },
272 { &Curl_trc_feat_write, TRC_CT_NONE },
273#ifndef CURL_DISABLE_FTP
274 { &Curl_trc_feat_ftp, TRC_CT_PROTOCOL },
275#endif
276#ifndef CURL_DISABLE_DOH
277 { &Curl_doh_trc, TRC_CT_NETWORK },
278#endif
279#ifndef CURL_DISABLE_SMTP
280 { &Curl_trc_feat_smtp, TRC_CT_PROTOCOL },
281#endif
282#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
283 { &Curl_trc_feat_ws, TRC_CT_PROTOCOL },
284#endif
285};
286
287struct trc_cft_def {
288 struct Curl_cftype *cft;
289 unsigned int category;
290};
291
292static struct trc_cft_def trc_cfts[] = {
293 { &Curl_cft_tcp, TRC_CT_NETWORK },
294 { &Curl_cft_udp, TRC_CT_NETWORK },
295 { &Curl_cft_unix, TRC_CT_NETWORK },
296 { &Curl_cft_tcp_accept, TRC_CT_NETWORK },
297 { &Curl_cft_happy_eyeballs, TRC_CT_NETWORK },
298 { &Curl_cft_setup, TRC_CT_PROTOCOL },
299#ifdef USE_NGHTTP2
300 { &Curl_cft_nghttp2, TRC_CT_PROTOCOL },
301#endif
302#ifdef USE_SSL
303 { &Curl_cft_ssl, TRC_CT_NETWORK },
304#ifndef CURL_DISABLE_PROXY
305 { &Curl_cft_ssl_proxy, TRC_CT_PROXY },
306#endif
307#endif
308#if !defined(CURL_DISABLE_PROXY)
309#if !defined(CURL_DISABLE_HTTP)
310 { &Curl_cft_h1_proxy, TRC_CT_PROXY },
311#ifdef USE_NGHTTP2
312 { &Curl_cft_h2_proxy, TRC_CT_PROXY },
313#endif
314 { &Curl_cft_http_proxy, TRC_CT_PROXY },
315#endif /* !CURL_DISABLE_HTTP */
316 { &Curl_cft_haproxy, TRC_CT_PROXY },
317 { &Curl_cft_socks_proxy, TRC_CT_PROXY },
318#endif /* !CURL_DISABLE_PROXY */
319#ifdef USE_HTTP3
320 { &Curl_cft_http3, TRC_CT_PROTOCOL },
321#endif
322#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
323 { &Curl_cft_http_connect, TRC_CT_PROTOCOL },
324#endif
325};
326
327static void trc_apply_level_by_name(const char * const token, int lvl)
328{
329 size_t i;
330
331 for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
332 if(strcasecompare(token, trc_cfts[i].cft->name)) {
333 trc_cfts[i].cft->log_level = lvl;
334 break;
335 }
336 }
337 for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
338 if(strcasecompare(token, trc_feats[i].feat->name)) {
339 trc_feats[i].feat->log_level = lvl;
340 break;
341 }
342 }
343}
344
345static void trc_apply_level_by_category(int category, int lvl)
346{
347 size_t i;
348
349 for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
350 if(!category || (trc_cfts[i].category & category))
351 trc_cfts[i].cft->log_level = lvl;
352 }
353 for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
354 if(!category || (trc_feats[i].category & category))
355 trc_feats[i].feat->log_level = lvl;
356 }
357}
358
359static CURLcode trc_opt(const char *config)
360{
361 char *token, *tok_buf, *tmp;
362 int lvl;
363
364 tmp = strdup(config);
365 if(!tmp)
366 return CURLE_OUT_OF_MEMORY;
367
368 token = Curl_strtok_r(tmp, ", ", &tok_buf);
369 while(token) {
370 switch(*token) {
371 case '-':
372 lvl = CURL_LOG_LVL_NONE;
373 ++token;
374 break;
375 case '+':
376 lvl = CURL_LOG_LVL_INFO;
377 ++token;
378 break;
379 default:
380 lvl = CURL_LOG_LVL_INFO;
381 break;
382 }
383 if(strcasecompare(token, "all"))
384 trc_apply_level_by_category(TRC_CT_NONE, lvl);
385 else if(strcasecompare(token, "protocol"))
386 trc_apply_level_by_category(TRC_CT_PROTOCOL, lvl);
387 else if(strcasecompare(token, "network"))
388 trc_apply_level_by_category(TRC_CT_NETWORK, lvl);
389 else if(strcasecompare(token, "proxy"))
390 trc_apply_level_by_category(TRC_CT_PROXY, lvl);
391 else
392 trc_apply_level_by_name(token, lvl);
393
394 token = Curl_strtok_r(NULL, ", ", &tok_buf);
395 }
396 free(tmp);
397 return CURLE_OK;
398}
399
400CURLcode Curl_trc_opt(const char *config)
401{
402 CURLcode result = config ? trc_opt(config) : CURLE_OK;
403#ifdef DEBUGBUILD
404 /* CURL_DEBUG can override anything */
405 if(!result) {
406 const char *dbg_config = getenv("CURL_DEBUG");
407 if(dbg_config)
408 result = trc_opt(dbg_config);
409 }
410#endif /* DEBUGBUILD */
411 return result;
412}
413
414CURLcode Curl_trc_init(void)
415{
416#ifdef DEBUGBUILD
417 return Curl_trc_opt(NULL);
418#else
419 return CURLE_OK;
420#endif
421}
422
423#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
424
425CURLcode Curl_trc_init(void)
426{
427 return CURLE_OK;
428}
429
430#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette