xref: /third_party/curl/lib/curl_trc.c (revision 13498266)
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