curl_trc.c (17344B)
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 "multiif.h" 34 35 #include "cf-socket.h" 36 #include "connect.h" 37 #include "doh.h" 38 #include "http2.h" 39 #include "http_proxy.h" 40 #include "cf-h1-proxy.h" 41 #include "cf-h2-proxy.h" 42 #include "cf-haproxy.h" 43 #include "cf-https-connect.h" 44 #include "socks.h" 45 #include "curlx/strparse.h" 46 #include "vtls/vtls.h" 47 #include "vquic/vquic.h" 48 49 /* The last 3 #include files should be in this order */ 50 #include "curl_printf.h" 51 #include "curl_memory.h" 52 #include "memdebug.h" 53 54 static void trc_write(struct Curl_easy *data, curl_infotype type, 55 const char *ptr, size_t size) 56 { 57 if(data->set.verbose) { 58 if(data->set.fdebug) { 59 bool inCallback = Curl_is_in_callback(data); 60 Curl_set_in_callback(data, TRUE); 61 (void)(*data->set.fdebug)(data, type, CURL_UNCONST(ptr), size, 62 data->set.debugdata); 63 Curl_set_in_callback(data, inCallback); 64 } 65 else { 66 static const char s_infotype[CURLINFO_END][3] = { 67 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; 68 switch(type) { 69 case CURLINFO_TEXT: 70 case CURLINFO_HEADER_OUT: 71 case CURLINFO_HEADER_IN: 72 fwrite(s_infotype[type], 2, 1, data->set.err); 73 fwrite(ptr, size, 1, data->set.err); 74 break; 75 default: /* nada */ 76 break; 77 } 78 } 79 } 80 } 81 82 /* max length we trace before ending in '...' */ 83 #define TRC_LINE_MAX 2048 84 85 #define CURL_TRC_FMT_IDSC "[x-%" CURL_FORMAT_CURL_OFF_T "] " 86 #define CURL_TRC_FMT_IDSD "[%" CURL_FORMAT_CURL_OFF_T "-x] " 87 #define CURL_TRC_FMT_IDSDC "[%" CURL_FORMAT_CURL_OFF_T "-%" \ 88 CURL_FORMAT_CURL_OFF_T "] " 89 90 static struct curl_trc_feat Curl_trc_feat_ids = { 91 "LIB-IDS", 92 CURL_LOG_LVL_NONE, 93 }; 94 #define CURL_TRC_IDS(data) \ 95 (Curl_trc_is_verbose(data) && \ 96 Curl_trc_feat_ids.log_level >= CURL_LOG_LVL_INFO) 97 98 static size_t trc_print_ids(struct Curl_easy *data, char *buf, size_t maxlen) 99 { 100 curl_off_t cid = data->conn ? 101 data->conn->connection_id : data->state.recent_conn_id; 102 if(data->id >= 0) { 103 if(cid >= 0) 104 return msnprintf(buf, maxlen, CURL_TRC_FMT_IDSDC, data->id, cid); 105 else 106 return msnprintf(buf, maxlen, CURL_TRC_FMT_IDSD, data->id); 107 } 108 else if(cid >= 0) 109 return msnprintf(buf, maxlen, CURL_TRC_FMT_IDSC, cid); 110 else { 111 return msnprintf(buf, maxlen, "[x-x] "); 112 } 113 } 114 115 static size_t trc_end_buf(char *buf, size_t len, size_t maxlen, bool addnl) 116 { 117 /* make sure we end the trace line in `buf` properly. It needs 118 * to end with a terminating '\0' or '\n\0' */ 119 if(len >= (maxlen - (addnl ? 2 : 1))) { 120 len = maxlen - 5; 121 buf[len++] = '.'; 122 buf[len++] = '.'; 123 buf[len++] = '.'; 124 buf[len++] = '\n'; 125 } 126 else if(addnl) 127 buf[len++] = '\n'; 128 buf[len] = '\0'; 129 return len; 130 } 131 132 void Curl_debug(struct Curl_easy *data, curl_infotype type, 133 const char *ptr, size_t size) 134 { 135 if(data->set.verbose) { 136 static const char s_infotype[CURLINFO_END][3] = { 137 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; 138 char buf[TRC_LINE_MAX]; 139 size_t len; 140 if(data->set.fdebug) { 141 bool inCallback = Curl_is_in_callback(data); 142 143 if(CURL_TRC_IDS(data) && (size < TRC_LINE_MAX)) { 144 len = trc_print_ids(data, buf, TRC_LINE_MAX); 145 len += msnprintf(buf + len, TRC_LINE_MAX - len, "%.*s", 146 (int)size, ptr); 147 len = trc_end_buf(buf, len, TRC_LINE_MAX, FALSE); 148 Curl_set_in_callback(data, TRUE); 149 (void)(*data->set.fdebug)(data, type, buf, len, data->set.debugdata); 150 Curl_set_in_callback(data, inCallback); 151 } 152 else { 153 Curl_set_in_callback(data, TRUE); 154 (void)(*data->set.fdebug)(data, type, CURL_UNCONST(ptr), 155 size, data->set.debugdata); 156 Curl_set_in_callback(data, inCallback); 157 } 158 } 159 else { 160 switch(type) { 161 case CURLINFO_TEXT: 162 case CURLINFO_HEADER_OUT: 163 case CURLINFO_HEADER_IN: 164 if(CURL_TRC_IDS(data)) { 165 len = trc_print_ids(data, buf, TRC_LINE_MAX); 166 fwrite(buf, len, 1, data->set.err); 167 } 168 fwrite(s_infotype[type], 2, 1, data->set.err); 169 fwrite(ptr, size, 1, data->set.err); 170 break; 171 default: /* nada */ 172 break; 173 } 174 } 175 } 176 } 177 178 /* Curl_failf() is for messages stating why we failed. 179 * The message SHALL NOT include any LF or CR. 180 */ 181 void Curl_failf(struct Curl_easy *data, const char *fmt, ...) 182 { 183 DEBUGASSERT(!strchr(fmt, '\n')); 184 if(data->set.verbose || data->set.errorbuffer) { 185 va_list ap; 186 size_t len; 187 char error[CURL_ERROR_SIZE + 2]; 188 va_start(ap, fmt); 189 len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); 190 191 if(data->set.errorbuffer && !data->state.errorbuf) { 192 strcpy(data->set.errorbuffer, error); 193 data->state.errorbuf = TRUE; /* wrote error string */ 194 } 195 error[len++] = '\n'; 196 error[len] = '\0'; 197 trc_write(data, CURLINFO_TEXT, error, len); 198 va_end(ap); 199 } 200 } 201 202 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) 203 204 205 static void trc_infof(struct Curl_easy *data, 206 struct curl_trc_feat *feat, 207 const char *opt_id, int opt_id_idx, 208 const char * const fmt, va_list ap) CURL_PRINTF(5, 0); 209 210 static void trc_infof(struct Curl_easy *data, 211 struct curl_trc_feat *feat, 212 const char *opt_id, int opt_id_idx, 213 const char * const fmt, va_list ap) 214 { 215 size_t len = 0; 216 char buf[TRC_LINE_MAX]; 217 218 if(CURL_TRC_IDS(data)) 219 len += trc_print_ids(data, buf + len, TRC_LINE_MAX - len); 220 if(feat) 221 len += msnprintf(buf + len, TRC_LINE_MAX - len, "[%s] ", feat->name); 222 if(opt_id) { 223 if(opt_id_idx > 0) 224 len += msnprintf(buf + len, TRC_LINE_MAX - len, "[%s-%d] ", 225 opt_id, opt_id_idx); 226 else 227 len += msnprintf(buf + len, TRC_LINE_MAX - len, "[%s] ", opt_id); 228 } 229 len += mvsnprintf(buf + len, TRC_LINE_MAX - len, fmt, ap); 230 len = trc_end_buf(buf, len, TRC_LINE_MAX, TRUE); 231 trc_write(data, CURLINFO_TEXT, buf, len); 232 } 233 234 void Curl_infof(struct Curl_easy *data, const char *fmt, ...) 235 { 236 DEBUGASSERT(!strchr(fmt, '\n')); 237 if(Curl_trc_is_verbose(data)) { 238 va_list ap; 239 va_start(ap, fmt); 240 trc_infof(data, data->state.feat, NULL, 0, fmt, ap); 241 va_end(ap); 242 } 243 } 244 245 void Curl_trc_cf_infof(struct Curl_easy *data, const struct Curl_cfilter *cf, 246 const char *fmt, ...) 247 { 248 DEBUGASSERT(cf); 249 if(Curl_trc_cf_is_verbose(cf, data)) { 250 va_list ap; 251 va_start(ap, fmt); 252 trc_infof(data, data->state.feat, cf->cft->name, cf->sockindex, fmt, ap); 253 va_end(ap); 254 } 255 } 256 257 struct curl_trc_feat Curl_trc_feat_multi = { 258 "MULTI", 259 CURL_LOG_LVL_NONE, 260 }; 261 struct curl_trc_feat Curl_trc_feat_read = { 262 "READ", 263 CURL_LOG_LVL_NONE, 264 }; 265 struct curl_trc_feat Curl_trc_feat_write = { 266 "WRITE", 267 CURL_LOG_LVL_NONE, 268 }; 269 struct curl_trc_feat Curl_trc_feat_dns = { 270 "DNS", 271 CURL_LOG_LVL_NONE, 272 }; 273 274 275 static const char * const Curl_trc_mstate_names[]={ 276 "INIT", 277 "PENDING", 278 "SETUP", 279 "CONNECT", 280 "RESOLVING", 281 "CONNECTING", 282 "TUNNELING", 283 "PROTOCONNECT", 284 "PROTOCONNECTING", 285 "DO", 286 "DOING", 287 "DOING_MORE", 288 "DID", 289 "PERFORMING", 290 "RATELIMITING", 291 "DONE", 292 "COMPLETED", 293 "MSGSENT", 294 }; 295 296 const char *Curl_trc_mstate_name(int state) 297 { 298 if((state >= 0) && ((size_t)state < CURL_ARRAYSIZE(Curl_trc_mstate_names))) 299 return Curl_trc_mstate_names[(size_t)state]; 300 return "?"; 301 } 302 303 void Curl_trc_multi(struct Curl_easy *data, const char *fmt, ...) 304 { 305 DEBUGASSERT(!strchr(fmt, '\n')); 306 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_multi)) { 307 const char *sname = (data->id >= 0) ? 308 Curl_trc_mstate_name(data->mstate) : NULL; 309 va_list ap; 310 va_start(ap, fmt); 311 trc_infof(data, &Curl_trc_feat_multi, sname, 0, fmt, ap); 312 va_end(ap); 313 } 314 } 315 316 void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...) 317 { 318 DEBUGASSERT(!strchr(fmt, '\n')); 319 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_read)) { 320 va_list ap; 321 va_start(ap, fmt); 322 trc_infof(data, &Curl_trc_feat_read, NULL, 0, fmt, ap); 323 va_end(ap); 324 } 325 } 326 327 void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...) 328 { 329 DEBUGASSERT(!strchr(fmt, '\n')); 330 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_write)) { 331 va_list ap; 332 va_start(ap, fmt); 333 trc_infof(data, &Curl_trc_feat_write, NULL, 0, fmt, ap); 334 va_end(ap); 335 } 336 } 337 338 void Curl_trc_dns(struct Curl_easy *data, const char *fmt, ...) 339 { 340 DEBUGASSERT(!strchr(fmt, '\n')); 341 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_dns)) { 342 va_list ap; 343 va_start(ap, fmt); 344 trc_infof(data, &Curl_trc_feat_dns, NULL, 0, fmt, ap); 345 va_end(ap); 346 } 347 } 348 349 #ifndef CURL_DISABLE_FTP 350 struct curl_trc_feat Curl_trc_feat_ftp = { 351 "FTP", 352 CURL_LOG_LVL_NONE, 353 }; 354 355 void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...) 356 { 357 DEBUGASSERT(!strchr(fmt, '\n')); 358 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) { 359 va_list ap; 360 va_start(ap, fmt); 361 trc_infof(data, &Curl_trc_feat_ftp, NULL, 0, fmt, ap); 362 va_end(ap); 363 } 364 } 365 #endif /* !CURL_DISABLE_FTP */ 366 367 #ifndef CURL_DISABLE_SMTP 368 struct curl_trc_feat Curl_trc_feat_smtp = { 369 "SMTP", 370 CURL_LOG_LVL_NONE, 371 }; 372 373 void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...) 374 { 375 DEBUGASSERT(!strchr(fmt, '\n')); 376 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_smtp)) { 377 va_list ap; 378 va_start(ap, fmt); 379 trc_infof(data, &Curl_trc_feat_smtp, NULL, 0, fmt, ap); 380 va_end(ap); 381 } 382 } 383 #endif /* !CURL_DISABLE_SMTP */ 384 385 #ifdef USE_SSL 386 struct curl_trc_feat Curl_trc_feat_ssls = { 387 "SSLS", 388 CURL_LOG_LVL_NONE, 389 }; 390 391 void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...) 392 { 393 DEBUGASSERT(!strchr(fmt, '\n')); 394 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) { 395 va_list ap; 396 va_start(ap, fmt); 397 trc_infof(data, &Curl_trc_feat_ssls, NULL, 0, fmt, ap); 398 va_end(ap); 399 } 400 } 401 #endif /* USE_SSL */ 402 403 #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) 404 struct curl_trc_feat Curl_trc_feat_ws = { 405 "WS", 406 CURL_LOG_LVL_NONE, 407 }; 408 409 void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...) 410 { 411 DEBUGASSERT(!strchr(fmt, '\n')); 412 if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) { 413 va_list ap; 414 va_start(ap, fmt); 415 trc_infof(data, &Curl_trc_feat_ws, NULL, 0, fmt, ap); 416 va_end(ap); 417 } 418 } 419 #endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */ 420 421 #define TRC_CT_NONE (0) 422 #define TRC_CT_PROTOCOL (1<<(0)) 423 #define TRC_CT_NETWORK (1<<(1)) 424 #define TRC_CT_PROXY (1<<(2)) 425 #define TRC_CT_INTERNALS (1<<(3)) 426 427 struct trc_feat_def { 428 struct curl_trc_feat *feat; 429 unsigned int category; 430 }; 431 432 static struct trc_feat_def trc_feats[] = { 433 { &Curl_trc_feat_ids, TRC_CT_INTERNALS }, 434 { &Curl_trc_feat_multi, TRC_CT_NETWORK }, 435 { &Curl_trc_feat_read, TRC_CT_NONE }, 436 { &Curl_trc_feat_write, TRC_CT_NONE }, 437 { &Curl_trc_feat_dns, TRC_CT_NETWORK }, 438 #ifndef CURL_DISABLE_FTP 439 { &Curl_trc_feat_ftp, TRC_CT_PROTOCOL }, 440 #endif 441 #ifndef CURL_DISABLE_DOH 442 #endif 443 #ifndef CURL_DISABLE_SMTP 444 { &Curl_trc_feat_smtp, TRC_CT_PROTOCOL }, 445 #endif 446 #ifdef USE_SSL 447 { &Curl_trc_feat_ssls, TRC_CT_NETWORK }, 448 #endif 449 #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) 450 { &Curl_trc_feat_ws, TRC_CT_PROTOCOL }, 451 #endif 452 }; 453 454 struct trc_cft_def { 455 struct Curl_cftype *cft; 456 unsigned int category; 457 }; 458 459 static struct trc_cft_def trc_cfts[] = { 460 { &Curl_cft_tcp, TRC_CT_NETWORK }, 461 { &Curl_cft_udp, TRC_CT_NETWORK }, 462 { &Curl_cft_unix, TRC_CT_NETWORK }, 463 { &Curl_cft_tcp_accept, TRC_CT_NETWORK }, 464 { &Curl_cft_happy_eyeballs, TRC_CT_NETWORK }, 465 { &Curl_cft_setup, TRC_CT_PROTOCOL }, 466 #ifdef USE_NGHTTP2 467 { &Curl_cft_nghttp2, TRC_CT_PROTOCOL }, 468 #endif 469 #ifdef USE_SSL 470 { &Curl_cft_ssl, TRC_CT_NETWORK }, 471 #ifndef CURL_DISABLE_PROXY 472 { &Curl_cft_ssl_proxy, TRC_CT_PROXY }, 473 #endif 474 #endif 475 #if !defined(CURL_DISABLE_PROXY) 476 #if !defined(CURL_DISABLE_HTTP) 477 { &Curl_cft_h1_proxy, TRC_CT_PROXY }, 478 #ifdef USE_NGHTTP2 479 { &Curl_cft_h2_proxy, TRC_CT_PROXY }, 480 #endif 481 { &Curl_cft_http_proxy, TRC_CT_PROXY }, 482 #endif /* !CURL_DISABLE_HTTP */ 483 { &Curl_cft_haproxy, TRC_CT_PROXY }, 484 { &Curl_cft_socks_proxy, TRC_CT_PROXY }, 485 #endif /* !CURL_DISABLE_PROXY */ 486 #ifdef USE_HTTP3 487 { &Curl_cft_http3, TRC_CT_PROTOCOL }, 488 #endif 489 #if !defined(CURL_DISABLE_HTTP) 490 { &Curl_cft_http_connect, TRC_CT_PROTOCOL }, 491 #endif 492 }; 493 494 static void trc_apply_level_by_name(struct Curl_str *token, int lvl) 495 { 496 size_t i; 497 498 for(i = 0; i < CURL_ARRAYSIZE(trc_cfts); ++i) { 499 if(curlx_str_casecompare(token, trc_cfts[i].cft->name)) { 500 trc_cfts[i].cft->log_level = lvl; 501 break; 502 } 503 } 504 for(i = 0; i < CURL_ARRAYSIZE(trc_feats); ++i) { 505 if(curlx_str_casecompare(token, trc_feats[i].feat->name)) { 506 trc_feats[i].feat->log_level = lvl; 507 break; 508 } 509 } 510 } 511 512 static void trc_apply_level_by_category(int category, int lvl) 513 { 514 size_t i; 515 516 for(i = 0; i < CURL_ARRAYSIZE(trc_cfts); ++i) { 517 if(!category || (trc_cfts[i].category & category)) 518 trc_cfts[i].cft->log_level = lvl; 519 } 520 for(i = 0; i < CURL_ARRAYSIZE(trc_feats); ++i) { 521 if(!category || (trc_feats[i].category & category)) 522 trc_feats[i].feat->log_level = lvl; 523 } 524 } 525 526 static CURLcode trc_opt(const char *config) 527 { 528 struct Curl_str out; 529 while(!curlx_str_until(&config, &out, 32, ',')) { 530 int lvl = CURL_LOG_LVL_INFO; 531 const char *token = curlx_str(&out); 532 533 if(*token == '-') { 534 lvl = CURL_LOG_LVL_NONE; 535 curlx_str_nudge(&out, 1); 536 } 537 else if(*token == '+') 538 curlx_str_nudge(&out, 1); 539 540 if(curlx_str_casecompare(&out, "all")) 541 trc_apply_level_by_category(TRC_CT_NONE, lvl); 542 else if(curlx_str_casecompare(&out, "protocol")) 543 trc_apply_level_by_category(TRC_CT_PROTOCOL, lvl); 544 else if(curlx_str_casecompare(&out, "network")) 545 trc_apply_level_by_category(TRC_CT_NETWORK, lvl); 546 else if(curlx_str_casecompare(&out, "proxy")) 547 trc_apply_level_by_category(TRC_CT_PROXY, lvl); 548 else if(curlx_str_casecompare(&out, "doh")) { 549 struct Curl_str dns = { "dns", 3 }; 550 trc_apply_level_by_name(&dns, lvl); 551 } 552 else 553 trc_apply_level_by_name(&out, lvl); 554 555 if(curlx_str_single(&config, ',')) 556 break; 557 } 558 return CURLE_OK; 559 } 560 561 CURLcode Curl_trc_opt(const char *config) 562 { 563 CURLcode result = config ? trc_opt(config) : CURLE_OK; 564 #ifdef DEBUGBUILD 565 /* CURL_DEBUG can override anything */ 566 if(!result) { 567 const char *dbg_config = getenv("CURL_DEBUG"); 568 if(dbg_config) 569 result = trc_opt(dbg_config); 570 } 571 #endif /* DEBUGBUILD */ 572 return result; 573 } 574 575 CURLcode Curl_trc_init(void) 576 { 577 #ifdef DEBUGBUILD 578 return Curl_trc_opt(NULL); 579 #else 580 return CURLE_OK; 581 #endif 582 } 583 584 #else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ 585 586 CURLcode Curl_trc_init(void) 587 { 588 return CURLE_OK; 589 } 590 591 void Curl_infof(struct Curl_easy *data, const char *fmt, ...) 592 { 593 (void)data; (void)fmt; 594 } 595 596 void Curl_trc_cf_infof(struct Curl_easy *data, const struct Curl_cfilter *cf, 597 const char *fmt, ...) 598 { 599 (void)data; (void)cf; (void)fmt; 600 } 601 602 struct curl_trc_feat; 603 604 void Curl_trc_multi(struct Curl_easy *data, const char *fmt, ...) 605 { 606 (void)data; (void)fmt; 607 } 608 609 void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...) 610 { 611 (void)data; (void)fmt; 612 } 613 614 void Curl_trc_dns(struct Curl_easy *data, const char *fmt, ...) 615 { 616 (void)data; (void)fmt; 617 } 618 619 void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...) 620 { 621 (void)data; (void)fmt; 622 } 623 624 #ifndef CURL_DISABLE_FTP 625 void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...) 626 { 627 (void)data; (void)fmt; 628 } 629 #endif 630 #ifndef CURL_DISABLE_SMTP 631 void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...) 632 { 633 (void)data; (void)fmt; 634 } 635 #endif 636 #if !defined(CURL_DISABLE_WEBSOCKETS) || !defined(CURL_DISABLE_HTTP) 637 void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...) 638 { 639 (void)data; (void)fmt; 640 } 641 #endif 642 643 void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...) 644 { 645 (void)data; 646 (void)fmt; 647 } 648 649 #endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */