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
25#define _MPRINTF_REPLACE /* use our functions only */
26#include <curl/mprintf.h>
27
28#include "testutil.h"
29#include "testtrace.h"
30#include "memdebug.h"
31
32struct libtest_trace_cfg libtest_debug_config;
33
34static time_t epoch_offset; /* for test time tracing */
35static int    known_offset; /* for test time tracing */
36
37static
38void libtest_debug_dump(const char *timebuf, const char *text, FILE *stream,
39                        const unsigned char *ptr, size_t size, int nohex)
40{
41  size_t i;
42  size_t c;
43
44  unsigned int width = 0x10;
45
46  if(nohex)
47    /* without the hex output, we can fit more on screen */
48    width = 0x40;
49
50  fprintf(stream, "%s%s, %d bytes (0x%x)\n", timebuf, text,
51          (int)size, (int)size);
52
53  for(i = 0; i < size; i += width) {
54
55    fprintf(stream, "%04x: ", (int)i);
56
57    if(!nohex) {
58      /* hex not disabled, show it */
59      for(c = 0; c < width; c++)
60        if(i+c < size)
61          fprintf(stream, "%02x ", ptr[i+c]);
62        else
63          fputs("   ", stream);
64    }
65
66    for(c = 0; (c < width) && (i+c < size); c++) {
67      /* check for 0D0A; if found, skip past and start a new line of output */
68      if(nohex &&
69         (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) {
70        i += (c+2-width);
71        break;
72      }
73      fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
74              ptr[i+c] : '.');
75      /* check again for 0D0A, to avoid an extra \n if it's at width */
76      if(nohex &&
77         (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (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  struct tm *now;
96  char timebuf[20];
97  char *timestr;
98  time_t secs;
99
100  (void)handle;
101
102  timebuf[0] = '\0';
103  timestr = &timebuf[0];
104
105  if(trace_cfg->tracetime) {
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    snprintf(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  default: /* in case a new one is introduced to shock us */
121    return 0;
122
123  case CURLINFO_HEADER_OUT:
124    text = "=> Send header";
125    break;
126  case CURLINFO_DATA_OUT:
127    text = "=> Send data";
128    break;
129  case CURLINFO_SSL_DATA_OUT:
130    text = "=> Send SSL data";
131    break;
132  case CURLINFO_HEADER_IN:
133    text = "<= Recv header";
134    break;
135  case CURLINFO_DATA_IN:
136    text = "<= Recv data";
137    break;
138  case CURLINFO_SSL_DATA_IN:
139    text = "<= Recv SSL data";
140    break;
141  }
142
143  libtest_debug_dump(timebuf, text, stderr, data, size, trace_cfg->nohex);
144  return 0;
145}
146
147