5eeeeb65da05aa0ffee80f1ebf9720cbba9ad2ae
[platform/upstream/curl.git] / tests / libtest / testtrace.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, 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) && (ptr[i+c+1] == 0x0A)) {
66         i += (c+2-width);
67         break;
68       }
69       fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
70               ptr[i+c] : '.');
71       /* check again for 0D0A, to avoid an extra \n if it's at width */
72       if(nohex &&
73          (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) {
74         i += (c+3-width);
75         break;
76       }
77     }
78     fputc('\n', stream); /* newline */
79   }
80   fflush(stream);
81 }
82
83 int libtest_debug_cb(CURL *handle, curl_infotype type,
84                      unsigned char *data, size_t size,
85                      void *userp)
86 {
87
88   struct libtest_trace_cfg *trace_cfg = userp;
89   const char *text;
90   struct timeval tv;
91   struct tm *now;
92   char timebuf[20];
93   char *timestr;
94   time_t secs;
95
96   (void)handle;
97
98   timebuf[0] = '\0';
99   timestr = &timebuf[0];
100
101   if(trace_cfg->tracetime) {
102     tv = tutil_tvnow();
103     if(!known_offset) {
104       epoch_offset = time(NULL) - tv.tv_sec;
105       known_offset = 1;
106     }
107     secs = epoch_offset + tv.tv_sec;
108     now = localtime(&secs);  /* not thread safe but we don't care */
109     snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
110              now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
111   }
112
113   switch(type) {
114   case CURLINFO_TEXT:
115     fprintf(stderr, "%s== Info: %s", timestr, (char *)data);
116   default: /* in case a new one is introduced to shock us */
117     return 0;
118
119   case CURLINFO_HEADER_OUT:
120     text = "=> Send header";
121     break;
122   case CURLINFO_DATA_OUT:
123     text = "=> Send data";
124     break;
125   case CURLINFO_SSL_DATA_OUT:
126     text = "=> Send SSL data";
127     break;
128   case CURLINFO_HEADER_IN:
129     text = "<= Recv header";
130     break;
131   case CURLINFO_DATA_IN:
132     text = "<= Recv data";
133     break;
134   case CURLINFO_SSL_DATA_IN:
135     text = "<= Recv SSL data";
136     break;
137   }
138
139   libtest_debug_dump(timebuf, text, stderr, data, size, trace_cfg->nohex);
140   return 0;
141 }
142