1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2012, 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 http://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
28struct libtest_trace_cfg libtest_debug_config;
29
30static time_t epoch_offset; /* for test time tracing */
31static int    known_offset; /* for test time tracing */
32
33static
34void 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
83int 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
143