113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#include "curl_setup.h" 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#include <curl/curl.h> 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include "curl_trc.h" 3013498266Sopenharmony_ci#include "urldata.h" 3113498266Sopenharmony_ci#include "easyif.h" 3213498266Sopenharmony_ci#include "cfilters.h" 3313498266Sopenharmony_ci#include "timeval.h" 3413498266Sopenharmony_ci#include "multiif.h" 3513498266Sopenharmony_ci#include "strcase.h" 3613498266Sopenharmony_ci 3713498266Sopenharmony_ci#include "cf-socket.h" 3813498266Sopenharmony_ci#include "connect.h" 3913498266Sopenharmony_ci#include "http2.h" 4013498266Sopenharmony_ci#include "http_proxy.h" 4113498266Sopenharmony_ci#include "cf-h1-proxy.h" 4213498266Sopenharmony_ci#include "cf-h2-proxy.h" 4313498266Sopenharmony_ci#include "cf-haproxy.h" 4413498266Sopenharmony_ci#include "cf-https-connect.h" 4513498266Sopenharmony_ci#include "socks.h" 4613498266Sopenharmony_ci#include "strtok.h" 4713498266Sopenharmony_ci#include "vtls/vtls.h" 4813498266Sopenharmony_ci#include "vquic/vquic.h" 4913498266Sopenharmony_ci 5013498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 5113498266Sopenharmony_ci#include "curl_printf.h" 5213498266Sopenharmony_ci#include "curl_memory.h" 5313498266Sopenharmony_ci#include "memdebug.h" 5413498266Sopenharmony_ci 5513498266Sopenharmony_ci 5613498266Sopenharmony_civoid Curl_debug(struct Curl_easy *data, curl_infotype type, 5713498266Sopenharmony_ci char *ptr, size_t size) 5813498266Sopenharmony_ci{ 5913498266Sopenharmony_ci if(data->set.verbose) { 6013498266Sopenharmony_ci static const char s_infotype[CURLINFO_END][3] = { 6113498266Sopenharmony_ci "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; 6213498266Sopenharmony_ci if(data->set.fdebug) { 6313498266Sopenharmony_ci bool inCallback = Curl_is_in_callback(data); 6413498266Sopenharmony_ci Curl_set_in_callback(data, true); 6513498266Sopenharmony_ci (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); 6613498266Sopenharmony_ci Curl_set_in_callback(data, inCallback); 6713498266Sopenharmony_ci } 6813498266Sopenharmony_ci else { 6913498266Sopenharmony_ci switch(type) { 7013498266Sopenharmony_ci case CURLINFO_TEXT: 7113498266Sopenharmony_ci case CURLINFO_HEADER_OUT: 7213498266Sopenharmony_ci case CURLINFO_HEADER_IN: 7313498266Sopenharmony_ci fwrite(s_infotype[type], 2, 1, data->set.err); 7413498266Sopenharmony_ci fwrite(ptr, size, 1, data->set.err); 7513498266Sopenharmony_ci break; 7613498266Sopenharmony_ci default: /* nada */ 7713498266Sopenharmony_ci break; 7813498266Sopenharmony_ci } 7913498266Sopenharmony_ci } 8013498266Sopenharmony_ci } 8113498266Sopenharmony_ci} 8213498266Sopenharmony_ci 8313498266Sopenharmony_ci 8413498266Sopenharmony_ci/* Curl_failf() is for messages stating why we failed. 8513498266Sopenharmony_ci * The message SHALL NOT include any LF or CR. 8613498266Sopenharmony_ci */ 8713498266Sopenharmony_civoid Curl_failf(struct Curl_easy *data, const char *fmt, ...) 8813498266Sopenharmony_ci{ 8913498266Sopenharmony_ci DEBUGASSERT(!strchr(fmt, '\n')); 9013498266Sopenharmony_ci if(data->set.verbose || data->set.errorbuffer) { 9113498266Sopenharmony_ci va_list ap; 9213498266Sopenharmony_ci int len; 9313498266Sopenharmony_ci char error[CURL_ERROR_SIZE + 2]; 9413498266Sopenharmony_ci va_start(ap, fmt); 9513498266Sopenharmony_ci len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); 9613498266Sopenharmony_ci 9713498266Sopenharmony_ci if(data->set.errorbuffer && !data->state.errorbuf) { 9813498266Sopenharmony_ci strcpy(data->set.errorbuffer, error); 9913498266Sopenharmony_ci data->state.errorbuf = TRUE; /* wrote error string */ 10013498266Sopenharmony_ci } 10113498266Sopenharmony_ci error[len++] = '\n'; 10213498266Sopenharmony_ci error[len] = '\0'; 10313498266Sopenharmony_ci Curl_debug(data, CURLINFO_TEXT, error, len); 10413498266Sopenharmony_ci va_end(ap); 10513498266Sopenharmony_ci } 10613498266Sopenharmony_ci} 10713498266Sopenharmony_ci 10813498266Sopenharmony_ci#if !defined(CURL_DISABLE_VERBOSE_STRINGS) 10913498266Sopenharmony_ci 11013498266Sopenharmony_ci/* Curl_infof() is for info message along the way */ 11113498266Sopenharmony_ci#define MAXINFO 2048 11213498266Sopenharmony_ci 11313498266Sopenharmony_civoid Curl_infof(struct Curl_easy *data, const char *fmt, ...) 11413498266Sopenharmony_ci{ 11513498266Sopenharmony_ci DEBUGASSERT(!strchr(fmt, '\n')); 11613498266Sopenharmony_ci if(data && data->set.verbose) { 11713498266Sopenharmony_ci va_list ap; 11813498266Sopenharmony_ci int len; 11913498266Sopenharmony_ci char buffer[MAXINFO + 2]; 12013498266Sopenharmony_ci va_start(ap, fmt); 12113498266Sopenharmony_ci len = mvsnprintf(buffer, MAXINFO, fmt, ap); 12213498266Sopenharmony_ci va_end(ap); 12313498266Sopenharmony_ci buffer[len++] = '\n'; 12413498266Sopenharmony_ci buffer[len] = '\0'; 12513498266Sopenharmony_ci Curl_debug(data, CURLINFO_TEXT, buffer, len); 12613498266Sopenharmony_ci } 12713498266Sopenharmony_ci} 12813498266Sopenharmony_ci 12913498266Sopenharmony_civoid Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, 13013498266Sopenharmony_ci const char *fmt, ...) 13113498266Sopenharmony_ci{ 13213498266Sopenharmony_ci DEBUGASSERT(cf); 13313498266Sopenharmony_ci if(Curl_trc_cf_is_verbose(cf, data)) { 13413498266Sopenharmony_ci va_list ap; 13513498266Sopenharmony_ci int len; 13613498266Sopenharmony_ci char buffer[MAXINFO + 2]; 13713498266Sopenharmony_ci len = msnprintf(buffer, MAXINFO, "[%s] ", cf->cft->name); 13813498266Sopenharmony_ci va_start(ap, fmt); 13913498266Sopenharmony_ci len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap); 14013498266Sopenharmony_ci va_end(ap); 14113498266Sopenharmony_ci buffer[len++] = '\n'; 14213498266Sopenharmony_ci buffer[len] = '\0'; 14313498266Sopenharmony_ci Curl_debug(data, CURLINFO_TEXT, buffer, len); 14413498266Sopenharmony_ci } 14513498266Sopenharmony_ci} 14613498266Sopenharmony_ci 14713498266Sopenharmony_ci 14813498266Sopenharmony_cistatic struct Curl_cftype *cf_types[] = { 14913498266Sopenharmony_ci &Curl_cft_tcp, 15013498266Sopenharmony_ci &Curl_cft_udp, 15113498266Sopenharmony_ci &Curl_cft_unix, 15213498266Sopenharmony_ci &Curl_cft_tcp_accept, 15313498266Sopenharmony_ci &Curl_cft_happy_eyeballs, 15413498266Sopenharmony_ci &Curl_cft_setup, 15513498266Sopenharmony_ci#ifdef USE_NGHTTP2 15613498266Sopenharmony_ci &Curl_cft_nghttp2, 15713498266Sopenharmony_ci#endif 15813498266Sopenharmony_ci#ifdef USE_SSL 15913498266Sopenharmony_ci &Curl_cft_ssl, 16013498266Sopenharmony_ci#ifndef CURL_DISABLE_PROXY 16113498266Sopenharmony_ci &Curl_cft_ssl_proxy, 16213498266Sopenharmony_ci#endif 16313498266Sopenharmony_ci#endif 16413498266Sopenharmony_ci#if !defined(CURL_DISABLE_PROXY) 16513498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) 16613498266Sopenharmony_ci &Curl_cft_h1_proxy, 16713498266Sopenharmony_ci#ifdef USE_NGHTTP2 16813498266Sopenharmony_ci &Curl_cft_h2_proxy, 16913498266Sopenharmony_ci#endif 17013498266Sopenharmony_ci &Curl_cft_http_proxy, 17113498266Sopenharmony_ci#endif /* !CURL_DISABLE_HTTP */ 17213498266Sopenharmony_ci &Curl_cft_haproxy, 17313498266Sopenharmony_ci &Curl_cft_socks_proxy, 17413498266Sopenharmony_ci#endif /* !CURL_DISABLE_PROXY */ 17513498266Sopenharmony_ci#ifdef ENABLE_QUIC 17613498266Sopenharmony_ci &Curl_cft_http3, 17713498266Sopenharmony_ci#endif 17813498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) 17913498266Sopenharmony_ci &Curl_cft_http_connect, 18013498266Sopenharmony_ci#endif 18113498266Sopenharmony_ci NULL, 18213498266Sopenharmony_ci}; 18313498266Sopenharmony_ci 18413498266Sopenharmony_ciCURLcode Curl_trc_opt(const char *config) 18513498266Sopenharmony_ci{ 18613498266Sopenharmony_ci char *token, *tok_buf, *tmp; 18713498266Sopenharmony_ci size_t i; 18813498266Sopenharmony_ci int lvl; 18913498266Sopenharmony_ci 19013498266Sopenharmony_ci tmp = strdup(config); 19113498266Sopenharmony_ci if(!tmp) 19213498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 19313498266Sopenharmony_ci 19413498266Sopenharmony_ci token = strtok_r(tmp, ", ", &tok_buf); 19513498266Sopenharmony_ci while(token) { 19613498266Sopenharmony_ci switch(*token) { 19713498266Sopenharmony_ci case '-': 19813498266Sopenharmony_ci lvl = CURL_LOG_LVL_NONE; 19913498266Sopenharmony_ci ++token; 20013498266Sopenharmony_ci break; 20113498266Sopenharmony_ci case '+': 20213498266Sopenharmony_ci lvl = CURL_LOG_LVL_INFO; 20313498266Sopenharmony_ci ++token; 20413498266Sopenharmony_ci break; 20513498266Sopenharmony_ci default: 20613498266Sopenharmony_ci lvl = CURL_LOG_LVL_INFO; 20713498266Sopenharmony_ci break; 20813498266Sopenharmony_ci } 20913498266Sopenharmony_ci for(i = 0; cf_types[i]; ++i) { 21013498266Sopenharmony_ci if(strcasecompare(token, "all")) { 21113498266Sopenharmony_ci cf_types[i]->log_level = lvl; 21213498266Sopenharmony_ci } 21313498266Sopenharmony_ci else if(strcasecompare(token, cf_types[i]->name)) { 21413498266Sopenharmony_ci cf_types[i]->log_level = lvl; 21513498266Sopenharmony_ci break; 21613498266Sopenharmony_ci } 21713498266Sopenharmony_ci } 21813498266Sopenharmony_ci token = strtok_r(NULL, ", ", &tok_buf); 21913498266Sopenharmony_ci } 22013498266Sopenharmony_ci free(tmp); 22113498266Sopenharmony_ci return CURLE_OK; 22213498266Sopenharmony_ci} 22313498266Sopenharmony_ci 22413498266Sopenharmony_ciCURLcode Curl_trc_init(void) 22513498266Sopenharmony_ci{ 22613498266Sopenharmony_ci#ifdef DEBUGBUILD 22713498266Sopenharmony_ci /* WIP: we use the auto-init from an env var only in DEBUG builds for 22813498266Sopenharmony_ci * convenience. */ 22913498266Sopenharmony_ci const char *config = getenv("CURL_DEBUG"); 23013498266Sopenharmony_ci if(config) { 23113498266Sopenharmony_ci return Curl_trc_opt(config); 23213498266Sopenharmony_ci } 23313498266Sopenharmony_ci#endif /* DEBUGBUILD */ 23413498266Sopenharmony_ci return CURLE_OK; 23513498266Sopenharmony_ci} 23613498266Sopenharmony_ci#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ 23713498266Sopenharmony_ci 23813498266Sopenharmony_ciCURLcode Curl_trc_init(void) 23913498266Sopenharmony_ci{ 24013498266Sopenharmony_ci return CURLE_OK; 24113498266Sopenharmony_ci} 24213498266Sopenharmony_ci 24313498266Sopenharmony_ci#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */ 244