lsquic_util.c revision 461e84d8
1/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * Utility functions
4 */
5
6#include <ctype.h>
7#include <stdint.h>
8#include <stdio.h>
9#include <string.h>
10#include <time.h>
11#ifndef WIN32
12#include <sys/time.h>
13#include <unistd.h>
14#else
15#include <vc_compat.h>
16#endif
17
18#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__)
19#include <mach/mach_time.h>
20#endif
21
22#include "lsquic_int_types.h"
23#include "lsquic_util.h"
24
25
26#if defined(__APPLE__)
27static mach_timebase_info_data_t timebase;
28#endif
29#if defined(WIN32)
30static LARGE_INTEGER perf_frequency;
31#endif
32
33void
34lsquic_init_timers (void)
35{
36#if defined(__APPLE__)
37    mach_timebase_info(&timebase);
38#endif
39#if defined(WIN32)
40    QueryPerformanceFrequency(&perf_frequency);
41#endif
42}
43
44
45lsquic_time_t
46lsquic_time_now (void)
47{
48#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
49    struct timespec ts;
50    (void) clock_gettime(CLOCK_MONOTONIC, &ts);
51    return (lsquic_time_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
52#elif defined(__APPLE__)
53    lsquic_time_t t = mach_absolute_time();
54    t *= timebase.numer;
55    t /= timebase.denom;
56    t /= 1000;
57    return t;
58#elif defined(WIN32)
59    LARGE_INTEGER counter;
60    lsquic_time_t t;
61    QueryPerformanceCounter(&counter);
62    t = counter.QuadPart;
63    t *= 1000000;
64    t /= perf_frequency.QuadPart;
65    return t;
66#else
67#   warn Monotonically increasing clock is not available on this platform
68    struct timeval tv;
69    (void) gettimeofday(&tv, NULL);
70    return (lsquic_time_t) tv.tv_sec * 1000000 + tv.tv_usec;
71#endif
72}
73
74
75int
76lsquic_is_zero (const void *pbuf, size_t bufsz)
77{
78    const unsigned char *buf, *end;
79    const unsigned long *buf_ul;
80    unsigned n_ul;
81    unsigned long n_non_zero;
82
83    buf = pbuf;
84    end = buf + bufsz;
85    buf_ul = (unsigned long *) buf;
86    n_ul = bufsz / sizeof(buf_ul[0]);
87    buf += n_ul * sizeof(buf_ul[0]);
88    n_non_zero = 0;
89
90    while (n_ul--)
91        n_non_zero |= buf_ul[n_ul];
92
93    while (buf < end)
94        n_non_zero |= *buf++;
95
96    return n_non_zero == 0;
97}
98
99
100/* XXX this function uses static buffer.  Replace it with hexdump() if possible */
101char *get_bin_str(const void *s, size_t len, size_t max_display_len)
102{
103    const unsigned char *p, *pEnd;
104    char *pOutput;
105    size_t lenOrg = len;
106    static char str[512 * 2 + 40] = {0};
107
108    /**
109     * We alloc fixed size buffer, at most max_display_len is 512
110     */
111    size_t fit_display_len = (max_display_len > 512 ? 512 : max_display_len);
112    if (len > fit_display_len)
113        len = fit_display_len;
114
115    pOutput = &str[0] + sprintf(str, "(%zd/%zd)=0x", len, lenOrg);
116
117    for(p = s, pEnd = (unsigned char*)s + len; p < pEnd; ++p)
118    {
119        sprintf(pOutput, "%02X", *p);
120        pOutput += 2;
121    }
122    if (lenOrg > len)
123    {
124        sprintf(pOutput, "...");
125        pOutput += 3;
126    }
127    return str;
128}
129
130
131size_t
132hexdump (const void *src_void, size_t src_sz, char *out, size_t out_sz)
133{
134/* Ruler:
135 *
136      6                       31                        57              73
137      |                        |                         |               |
1380000  00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F  |................|
139 *
140 */
141#define LINE_SIZE (74 + 1 /* newline */)
142    const unsigned char       *src     = src_void;
143    const unsigned char *const src_end = src + src_sz;
144    char *const                out_end = out + out_sz;
145    unsigned line = 0;
146
147    while (src < src_end && out_end - out >= LINE_SIZE)
148    {
149        const unsigned char *limit = src + 16;
150        if (limit > src_end)
151            limit = src_end;
152        unsigned hex_off   = 6;
153        unsigned alpha_off = 57;
154        sprintf(out, "%04x", line++);
155        out[4] = ' ';
156        out[5] = ' ';
157        while (src < limit)
158        {
159            sprintf(out + hex_off, "%02X ", *src);
160            sprintf(out + alpha_off, "%c", isprint(*src) ? *src : '.');
161            hex_off += 3;
162            out[hex_off] = ' ';
163            hex_off += 30 == hex_off;
164            out[hex_off] = ' ';
165            ++alpha_off;
166            out[alpha_off] = ' ';
167            ++src;
168        }
169        memset(out + hex_off,   ' ', 56 - hex_off);
170        memset(out + alpha_off, '.', 73 - alpha_off);
171        out[56] = '|';
172        out[73] = '|';
173        out[74] = '\n';
174        out += LINE_SIZE;
175    }
176
177    if (out < out_end)
178        *out = '\0';
179    else
180        out_end[-1] = '\0';
181
182    return out + out_sz - out_end;
183}
184