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 "http2.h" 40#include "http_proxy.h" 41#include "cf-h1-proxy.h" 42#include "cf-h2-proxy.h" 43#include "cf-haproxy.h" 44#include "cf-https-connect.h" 45#include "socks.h" 46#include "strtok.h" 47#include "vtls/vtls.h" 48#include "vquic/vquic.h" 49 50/* The last 3 #include files should be in this order */ 51#include "curl_printf.h" 52#include "curl_memory.h" 53#include "memdebug.h" 54 55 56void Curl_debug(struct Curl_easy *data, curl_infotype type, 57 char *ptr, size_t size) 58{ 59 if(data->set.verbose) { 60 static const char s_infotype[CURLINFO_END][3] = { 61 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; 62 if(data->set.fdebug) { 63 bool inCallback = Curl_is_in_callback(data); 64 Curl_set_in_callback(data, true); 65 (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); 66 Curl_set_in_callback(data, inCallback); 67 } 68 else { 69 switch(type) { 70 case CURLINFO_TEXT: 71 case CURLINFO_HEADER_OUT: 72 case CURLINFO_HEADER_IN: 73 fwrite(s_infotype[type], 2, 1, data->set.err); 74 fwrite(ptr, size, 1, data->set.err); 75 break; 76 default: /* nada */ 77 break; 78 } 79 } 80 } 81} 82 83 84/* Curl_failf() is for messages stating why we failed. 85 * The message SHALL NOT include any LF or CR. 86 */ 87void Curl_failf(struct Curl_easy *data, const char *fmt, ...) 88{ 89 DEBUGASSERT(!strchr(fmt, '\n')); 90 if(data->set.verbose || data->set.errorbuffer) { 91 va_list ap; 92 int len; 93 char error[CURL_ERROR_SIZE + 2]; 94 va_start(ap, fmt); 95 len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); 96 97 if(data->set.errorbuffer && !data->state.errorbuf) { 98 strcpy(data->set.errorbuffer, error); 99 data->state.errorbuf = TRUE; /* wrote error string */ 100 } 101 error[len++] = '\n'; 102 error[len] = '\0'; 103 Curl_debug(data, CURLINFO_TEXT, error, len); 104 va_end(ap); 105 } 106} 107 108#if !defined(CURL_DISABLE_VERBOSE_STRINGS) 109 110/* Curl_infof() is for info message along the way */ 111#define MAXINFO 2048 112 113void Curl_infof(struct Curl_easy *data, const char *fmt, ...) 114{ 115 DEBUGASSERT(!strchr(fmt, '\n')); 116 if(data && data->set.verbose) { 117 va_list ap; 118 int len; 119 char buffer[MAXINFO + 2]; 120 va_start(ap, fmt); 121 len = mvsnprintf(buffer, MAXINFO, fmt, ap); 122 va_end(ap); 123 buffer[len++] = '\n'; 124 buffer[len] = '\0'; 125 Curl_debug(data, CURLINFO_TEXT, buffer, len); 126 } 127} 128 129void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, 130 const char *fmt, ...) 131{ 132 DEBUGASSERT(cf); 133 if(Curl_trc_cf_is_verbose(cf, data)) { 134 va_list ap; 135 int len; 136 char buffer[MAXINFO + 2]; 137 len = msnprintf(buffer, MAXINFO, "[%s] ", cf->cft->name); 138 va_start(ap, fmt); 139 len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap); 140 va_end(ap); 141 buffer[len++] = '\n'; 142 buffer[len] = '\0'; 143 Curl_debug(data, CURLINFO_TEXT, buffer, len); 144 } 145} 146 147 148static struct Curl_cftype *cf_types[] = { 149 &Curl_cft_tcp, 150 &Curl_cft_udp, 151 &Curl_cft_unix, 152 &Curl_cft_tcp_accept, 153 &Curl_cft_happy_eyeballs, 154 &Curl_cft_setup, 155#ifdef USE_NGHTTP2 156 &Curl_cft_nghttp2, 157#endif 158#ifdef USE_SSL 159 &Curl_cft_ssl, 160#ifndef CURL_DISABLE_PROXY 161 &Curl_cft_ssl_proxy, 162#endif 163#endif 164#if !defined(CURL_DISABLE_PROXY) 165#if !defined(CURL_DISABLE_HTTP) 166 &Curl_cft_h1_proxy, 167#ifdef USE_NGHTTP2 168 &Curl_cft_h2_proxy, 169#endif 170 &Curl_cft_http_proxy, 171#endif /* !CURL_DISABLE_HTTP */ 172 &Curl_cft_haproxy, 173 &Curl_cft_socks_proxy, 174#endif /* !CURL_DISABLE_PROXY */ 175#ifdef ENABLE_QUIC 176 &Curl_cft_http3, 177#endif 178#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) 179 &Curl_cft_http_connect, 180#endif 181 NULL, 182}; 183 184CURLcode Curl_trc_opt(const char *config) 185{ 186 char *token, *tok_buf, *tmp; 187 size_t i; 188 int lvl; 189 190 tmp = strdup(config); 191 if(!tmp) 192 return CURLE_OUT_OF_MEMORY; 193 194 token = strtok_r(tmp, ", ", &tok_buf); 195 while(token) { 196 switch(*token) { 197 case '-': 198 lvl = CURL_LOG_LVL_NONE; 199 ++token; 200 break; 201 case '+': 202 lvl = CURL_LOG_LVL_INFO; 203 ++token; 204 break; 205 default: 206 lvl = CURL_LOG_LVL_INFO; 207 break; 208 } 209 for(i = 0; cf_types[i]; ++i) { 210 if(strcasecompare(token, "all")) { 211 cf_types[i]->log_level = lvl; 212 } 213 else if(strcasecompare(token, cf_types[i]->name)) { 214 cf_types[i]->log_level = lvl; 215 break; 216 } 217 } 218 token = strtok_r(NULL, ", ", &tok_buf); 219 } 220 free(tmp); 221 return CURLE_OK; 222} 223 224CURLcode Curl_trc_init(void) 225{ 226#ifdef DEBUGBUILD 227 /* WIP: we use the auto-init from an env var only in DEBUG builds for 228 * convenience. */ 229 const char *config = getenv("CURL_DEBUG"); 230 if(config) { 231 return Curl_trc_opt(config); 232 } 233#endif /* DEBUGBUILD */ 234 return CURLE_OK; 235} 236#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ 237 238CURLcode Curl_trc_init(void) 239{ 240 return CURLE_OK; 241} 242 243#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */ 244