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