lsquic_util.c revision 83287402
150aadb33SDmitri Tikhonov/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * Utility functions
450aadb33SDmitri Tikhonov */
550aadb33SDmitri Tikhonov
650aadb33SDmitri Tikhonov#include <ctype.h>
750aadb33SDmitri Tikhonov#include <stdint.h>
850aadb33SDmitri Tikhonov#include <stdio.h>
950aadb33SDmitri Tikhonov#include <string.h>
1050aadb33SDmitri Tikhonov#include <sys/time.h>
1183287402SDmitri Tikhonov#include <time.h>
1283287402SDmitri Tikhonov#include <unistd.h>
1383287402SDmitri Tikhonov
1483287402SDmitri Tikhonov#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__)
1583287402SDmitri Tikhonov#include <mach/mach_time.h>
1683287402SDmitri Tikhonov#endif
1750aadb33SDmitri Tikhonov
1850aadb33SDmitri Tikhonov#include "lsquic_int_types.h"
1950aadb33SDmitri Tikhonov#include "lsquic_util.h"
2050aadb33SDmitri Tikhonov
2150aadb33SDmitri Tikhonov
2283287402SDmitri Tikhonov#if defined(__APPLE__)
2383287402SDmitri Tikhonovstatic mach_timebase_info_data_t timebase;
2483287402SDmitri Tikhonov#endif
2583287402SDmitri Tikhonov
2683287402SDmitri Tikhonovvoid
2783287402SDmitri Tikhonovlsquic_init_timers (void)
2883287402SDmitri Tikhonov{
2983287402SDmitri Tikhonov#if defined(__APPLE__)
3083287402SDmitri Tikhonov    mach_timebase_info(&timebase);
3183287402SDmitri Tikhonov#endif
3283287402SDmitri Tikhonov}
3383287402SDmitri Tikhonov
3483287402SDmitri Tikhonov
3550aadb33SDmitri Tikhonovlsquic_time_t
3650aadb33SDmitri Tikhonovlsquic_time_now (void)
3750aadb33SDmitri Tikhonov{
3883287402SDmitri Tikhonov#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
3983287402SDmitri Tikhonov    struct timespec ts;
4083287402SDmitri Tikhonov    (void) clock_gettime(CLOCK_MONOTONIC, &ts);
4183287402SDmitri Tikhonov    return (lsquic_time_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
4283287402SDmitri Tikhonov#elif defined(__APPLE__)
4383287402SDmitri Tikhonov    lsquic_time_t t = mach_absolute_time();
4483287402SDmitri Tikhonov    t *= timebase.numer;
4583287402SDmitri Tikhonov    t /= timebase.denom;
4683287402SDmitri Tikhonov    t /= 1000;
4783287402SDmitri Tikhonov    return t;
4883287402SDmitri Tikhonov#else
4983287402SDmitri Tikhonov#   warn Monotonically increasing clock is not available on this platform
5050aadb33SDmitri Tikhonov    struct timeval tv;
5150aadb33SDmitri Tikhonov    (void) gettimeofday(&tv, NULL);
5250aadb33SDmitri Tikhonov    return (lsquic_time_t) tv.tv_sec * 1000000 + tv.tv_usec;
5383287402SDmitri Tikhonov#endif
5450aadb33SDmitri Tikhonov}
5550aadb33SDmitri Tikhonov
5650aadb33SDmitri Tikhonov
5750aadb33SDmitri Tikhonovint
5850aadb33SDmitri Tikhonovlsquic_is_zero (const void *pbuf, size_t bufsz)
5950aadb33SDmitri Tikhonov{
6050aadb33SDmitri Tikhonov    const unsigned char *buf, *end;
6150aadb33SDmitri Tikhonov    const unsigned long *buf_ul;
6250aadb33SDmitri Tikhonov    unsigned n_ul;
6350aadb33SDmitri Tikhonov    unsigned long n_non_zero;
6450aadb33SDmitri Tikhonov
6550aadb33SDmitri Tikhonov    buf = pbuf;
6650aadb33SDmitri Tikhonov    end = buf + bufsz;
6750aadb33SDmitri Tikhonov    buf_ul = (unsigned long *) buf;
6850aadb33SDmitri Tikhonov    n_ul = bufsz / sizeof(buf_ul[0]);
6950aadb33SDmitri Tikhonov    buf += n_ul * sizeof(buf_ul[0]);
7050aadb33SDmitri Tikhonov    n_non_zero = 0;
7150aadb33SDmitri Tikhonov
7250aadb33SDmitri Tikhonov    while (n_ul--)
7350aadb33SDmitri Tikhonov        n_non_zero |= buf_ul[n_ul];
7450aadb33SDmitri Tikhonov
7550aadb33SDmitri Tikhonov    while (buf < end)
7650aadb33SDmitri Tikhonov        n_non_zero |= *buf++;
7750aadb33SDmitri Tikhonov
7850aadb33SDmitri Tikhonov    return n_non_zero == 0;
7950aadb33SDmitri Tikhonov}
8050aadb33SDmitri Tikhonov
8150aadb33SDmitri Tikhonov
8250aadb33SDmitri Tikhonov/* XXX this function uses static buffer.  Replace it with hexdump() if possible */
8350aadb33SDmitri Tikhonovchar *get_bin_str(const void *s, size_t len, size_t max_display_len)
8450aadb33SDmitri Tikhonov{
8550aadb33SDmitri Tikhonov    const unsigned char *p, *pEnd;
8650aadb33SDmitri Tikhonov    char *pOutput;
8750aadb33SDmitri Tikhonov    size_t lenOrg = len;
8850aadb33SDmitri Tikhonov    static char str[512 * 2 + 40] = {0};
8950aadb33SDmitri Tikhonov
9050aadb33SDmitri Tikhonov    /**
9150aadb33SDmitri Tikhonov     * We alloc fixed size buffer, at most max_display_len is 512
9250aadb33SDmitri Tikhonov     */
9350aadb33SDmitri Tikhonov    size_t fit_display_len = (max_display_len > 512 ? 512 : max_display_len);
9450aadb33SDmitri Tikhonov    if (len > fit_display_len)
9550aadb33SDmitri Tikhonov        len = fit_display_len;
9650aadb33SDmitri Tikhonov
9750aadb33SDmitri Tikhonov    pOutput = &str[0] + sprintf(str, "(%zd/%zd)=0x", len, lenOrg);
9850aadb33SDmitri Tikhonov
9950aadb33SDmitri Tikhonov    for(p = s, pEnd = s + len; p < pEnd; ++p)
10050aadb33SDmitri Tikhonov    {
10150aadb33SDmitri Tikhonov        sprintf(pOutput, "%02X", *p);
10250aadb33SDmitri Tikhonov        pOutput += 2;
10350aadb33SDmitri Tikhonov    }
10450aadb33SDmitri Tikhonov    if (lenOrg > len)
10550aadb33SDmitri Tikhonov    {
10650aadb33SDmitri Tikhonov        sprintf(pOutput, "...");
10750aadb33SDmitri Tikhonov        pOutput += 3;
10850aadb33SDmitri Tikhonov    }
10950aadb33SDmitri Tikhonov    return str;
11050aadb33SDmitri Tikhonov}
11150aadb33SDmitri Tikhonov
11250aadb33SDmitri Tikhonov
11350aadb33SDmitri Tikhonovsize_t
11450aadb33SDmitri Tikhonovhexdump (const void *src_void, size_t src_sz, char *out, size_t out_sz)
11550aadb33SDmitri Tikhonov{
11650aadb33SDmitri Tikhonov/* Ruler:
11750aadb33SDmitri Tikhonov *
11850aadb33SDmitri Tikhonov      6                       31                        57              73
11950aadb33SDmitri Tikhonov      |                        |                         |               |
12050aadb33SDmitri Tikhonov0000  00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F  |................|
12150aadb33SDmitri Tikhonov *
12250aadb33SDmitri Tikhonov */
12350aadb33SDmitri Tikhonov#define LINE_SIZE (74 + 1 /* newline */)
12450aadb33SDmitri Tikhonov    const unsigned char       *src     = src_void;
12550aadb33SDmitri Tikhonov    const unsigned char *const src_end = src + src_sz;
12650aadb33SDmitri Tikhonov    char *const                out_end = out + out_sz;
12750aadb33SDmitri Tikhonov    unsigned line = 0;
12850aadb33SDmitri Tikhonov
12950aadb33SDmitri Tikhonov    while (src < src_end && out_end - out >= LINE_SIZE)
13050aadb33SDmitri Tikhonov    {
13150aadb33SDmitri Tikhonov        const unsigned char *limit = src + 16;
13250aadb33SDmitri Tikhonov        if (limit > src_end)
13350aadb33SDmitri Tikhonov            limit = src_end;
13450aadb33SDmitri Tikhonov        unsigned hex_off   = 6;
13550aadb33SDmitri Tikhonov        unsigned alpha_off = 57;
13650aadb33SDmitri Tikhonov        sprintf(out, "%04x", line++);
13750aadb33SDmitri Tikhonov        out[4] = ' ';
13850aadb33SDmitri Tikhonov        out[5] = ' ';
13950aadb33SDmitri Tikhonov        while (src < limit)
14050aadb33SDmitri Tikhonov        {
14150aadb33SDmitri Tikhonov            sprintf(out + hex_off, "%02X ", *src);
14250aadb33SDmitri Tikhonov            sprintf(out + alpha_off, "%c", isprint(*src) ? *src : '.');
14350aadb33SDmitri Tikhonov            hex_off += 3;
14450aadb33SDmitri Tikhonov            out[hex_off] = ' ';
14550aadb33SDmitri Tikhonov            hex_off += 30 == hex_off;
14650aadb33SDmitri Tikhonov            out[hex_off] = ' ';
14750aadb33SDmitri Tikhonov            ++alpha_off;
14850aadb33SDmitri Tikhonov            out[alpha_off] = ' ';
14950aadb33SDmitri Tikhonov            ++src;
15050aadb33SDmitri Tikhonov        }
15150aadb33SDmitri Tikhonov        memset(out + hex_off,   ' ', 56 - hex_off);
15250aadb33SDmitri Tikhonov        memset(out + alpha_off, '.', 73 - alpha_off);
15350aadb33SDmitri Tikhonov        out[56] = '|';
15450aadb33SDmitri Tikhonov        out[73] = '|';
15550aadb33SDmitri Tikhonov        out[74] = '\n';
15650aadb33SDmitri Tikhonov        out += LINE_SIZE;
15750aadb33SDmitri Tikhonov    }
15850aadb33SDmitri Tikhonov
15950aadb33SDmitri Tikhonov    if (out < out_end)
16050aadb33SDmitri Tikhonov        *out = '\0';
16150aadb33SDmitri Tikhonov    else
16250aadb33SDmitri Tikhonov        out_end[-1] = '\0';
16350aadb33SDmitri Tikhonov
16450aadb33SDmitri Tikhonov    return out + out_sz - out_end;
16550aadb33SDmitri Tikhonov}
166