xref: /third_party/curl/tests/libtest/testtrace.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 "test.h"
26#include "testutil.h"
27#include "testtrace.h"
28#include "memdebug.h"
29
30struct libtest_trace_cfg libtest_debug_config;
31
32static time_t epoch_offset; /* for test time tracing */
33static int    known_offset; /* for test time tracing */
34
35static
36void libtest_debug_dump(const char *timebuf, const char *text, FILE *stream,
37                        const unsigned char *ptr, size_t size, int nohex)
38{
39  size_t i;
40  size_t c;
41
42  unsigned int width = 0x10;
43
44  if(nohex)
45    /* without the hex output, we can fit more on screen */
46    width = 0x40;
47
48  fprintf(stream, "%s%s, %zu bytes (0x%zx)\n", timebuf, text,
49          size, size);
50
51  for(i = 0; i < size; i += width) {
52
53    fprintf(stream, "%04zx: ", i);
54
55    if(!nohex) {
56      /* hex not disabled, show it */
57      for(c = 0; c < width; c++)
58        if(i + c < size)
59          fprintf(stream, "%02x ", ptr[i + c]);
60        else
61          fputs("   ", stream);
62    }
63
64    for(c = 0; (c < width) && (i + c < size); c++) {
65      /* check for 0D0A; if found, skip past and start a new line of output */
66      if(nohex &&
67         (i + c + 1 < size) && (ptr[i + c] == 0x0D) &&
68         (ptr[i + c + 1] == 0x0A)) {
69        i += (c + 2 - width);
70        break;
71      }
72      fprintf(stream, "%c", ((ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80)) ?
73              ptr[i + c] : '.');
74      /* check again for 0D0A, to avoid an extra \n if it's at width */
75      if(nohex &&
76         (i + c + 2 < size) && (ptr[i + c + 1] == 0x0D) &&
77         (ptr[i + c + 2] == 0x0A)) {
78        i += (c + 3 - width);
79        break;
80      }
81    }
82    fputc('\n', stream); /* newline */
83  }
84  fflush(stream);
85}
86
87int libtest_debug_cb(CURL *handle, curl_infotype type,
88                     unsigned char *data, size_t size,
89                     void *userp)
90{
91
92  struct libtest_trace_cfg *trace_cfg = userp;
93  const char *text;
94  struct timeval tv;
95  char timebuf[20];
96  char *timestr;
97  time_t secs;
98
99  (void)handle;
100
101  timebuf[0] = '\0';
102  timestr = &timebuf[0];
103
104  if(trace_cfg->tracetime) {
105    struct tm *now;
106    tv = tutil_tvnow();
107    if(!known_offset) {
108      epoch_offset = time(NULL) - tv.tv_sec;
109      known_offset = 1;
110    }
111    secs = epoch_offset + tv.tv_sec;
112    now = localtime(&secs);  /* not thread safe but we don't care */
113    msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
114              now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
115  }
116
117  switch(type) {
118  case CURLINFO_TEXT:
119    fprintf(stderr, "%s== Info: %s", timestr, (char *)data);
120    return 0;
121  case CURLINFO_HEADER_OUT:
122    text = "=> Send header";
123    break;
124  case CURLINFO_DATA_OUT:
125    text = "=> Send data";
126    break;
127  case CURLINFO_SSL_DATA_OUT:
128    text = "=> Send SSL data";
129    break;
130  case CURLINFO_HEADER_IN:
131    text = "<= Recv header";
132    break;
133  case CURLINFO_DATA_IN:
134    text = "<= Recv data";
135    break;
136  case CURLINFO_SSL_DATA_IN:
137    text = "<= Recv SSL data";
138    break;
139  default: /* in case a new one is introduced to shock us */
140    return 0;
141  }
142
143  libtest_debug_dump(timebuf, text, stderr, data, size, trace_cfg->nohex);
144  return 0;
145}
146