lsquic_util.c revision 229fce07
1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 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> 1083287402SDmitri Tikhonov#include <time.h> 11461e84d8SAmol Deshpande#ifndef WIN32 12461e84d8SAmol Deshpande#include <sys/time.h> 1383287402SDmitri Tikhonov#include <unistd.h> 14461e84d8SAmol Deshpande#else 15461e84d8SAmol Deshpande#include <vc_compat.h> 16461e84d8SAmol Deshpande#endif 1783287402SDmitri Tikhonov 1883287402SDmitri Tikhonov#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__) 1983287402SDmitri Tikhonov#include <mach/mach_time.h> 2083287402SDmitri Tikhonov#endif 2150aadb33SDmitri Tikhonov 2250aadb33SDmitri Tikhonov#include "lsquic_int_types.h" 2350aadb33SDmitri Tikhonov#include "lsquic_util.h" 2450aadb33SDmitri Tikhonov 2550aadb33SDmitri Tikhonov 2683287402SDmitri Tikhonov#if defined(__APPLE__) 2783287402SDmitri Tikhonovstatic mach_timebase_info_data_t timebase; 2883287402SDmitri Tikhonov#endif 29461e84d8SAmol Deshpande#if defined(WIN32) 30461e84d8SAmol Deshpandestatic LARGE_INTEGER perf_frequency; 31461e84d8SAmol Deshpande#endif 3283287402SDmitri Tikhonov 3383287402SDmitri Tikhonovvoid 3483287402SDmitri Tikhonovlsquic_init_timers (void) 3583287402SDmitri Tikhonov{ 3683287402SDmitri Tikhonov#if defined(__APPLE__) 3783287402SDmitri Tikhonov mach_timebase_info(&timebase); 3883287402SDmitri Tikhonov#endif 39461e84d8SAmol Deshpande#if defined(WIN32) 40461e84d8SAmol Deshpande QueryPerformanceFrequency(&perf_frequency); 41461e84d8SAmol Deshpande#endif 4283287402SDmitri Tikhonov} 4383287402SDmitri Tikhonov 4483287402SDmitri Tikhonov 4550aadb33SDmitri Tikhonovlsquic_time_t 4650aadb33SDmitri Tikhonovlsquic_time_now (void) 4750aadb33SDmitri Tikhonov{ 4883287402SDmitri Tikhonov#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 4983287402SDmitri Tikhonov struct timespec ts; 5083287402SDmitri Tikhonov (void) clock_gettime(CLOCK_MONOTONIC, &ts); 5183287402SDmitri Tikhonov return (lsquic_time_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; 5283287402SDmitri Tikhonov#elif defined(__APPLE__) 5383287402SDmitri Tikhonov lsquic_time_t t = mach_absolute_time(); 5483287402SDmitri Tikhonov t *= timebase.numer; 5583287402SDmitri Tikhonov t /= timebase.denom; 5683287402SDmitri Tikhonov t /= 1000; 5783287402SDmitri Tikhonov return t; 58461e84d8SAmol Deshpande#elif defined(WIN32) 59461e84d8SAmol Deshpande LARGE_INTEGER counter; 60461e84d8SAmol Deshpande lsquic_time_t t; 61461e84d8SAmol Deshpande QueryPerformanceCounter(&counter); 62461e84d8SAmol Deshpande t = counter.QuadPart; 63461e84d8SAmol Deshpande t *= 1000000; 64461e84d8SAmol Deshpande t /= perf_frequency.QuadPart; 65461e84d8SAmol Deshpande return t; 6683287402SDmitri Tikhonov#else 6783287402SDmitri Tikhonov# warn Monotonically increasing clock is not available on this platform 6850aadb33SDmitri Tikhonov struct timeval tv; 6950aadb33SDmitri Tikhonov (void) gettimeofday(&tv, NULL); 7050aadb33SDmitri Tikhonov return (lsquic_time_t) tv.tv_sec * 1000000 + tv.tv_usec; 7183287402SDmitri Tikhonov#endif 7250aadb33SDmitri Tikhonov} 7350aadb33SDmitri Tikhonov 7450aadb33SDmitri Tikhonov 7550aadb33SDmitri Tikhonovint 7650aadb33SDmitri Tikhonovlsquic_is_zero (const void *pbuf, size_t bufsz) 7750aadb33SDmitri Tikhonov{ 7850aadb33SDmitri Tikhonov const unsigned char *buf, *end; 7950aadb33SDmitri Tikhonov const unsigned long *buf_ul; 8050aadb33SDmitri Tikhonov unsigned n_ul; 8150aadb33SDmitri Tikhonov unsigned long n_non_zero; 8250aadb33SDmitri Tikhonov 8350aadb33SDmitri Tikhonov buf = pbuf; 8450aadb33SDmitri Tikhonov end = buf + bufsz; 8550aadb33SDmitri Tikhonov buf_ul = (unsigned long *) buf; 8650aadb33SDmitri Tikhonov n_ul = bufsz / sizeof(buf_ul[0]); 8750aadb33SDmitri Tikhonov buf += n_ul * sizeof(buf_ul[0]); 8850aadb33SDmitri Tikhonov n_non_zero = 0; 8950aadb33SDmitri Tikhonov 9050aadb33SDmitri Tikhonov while (n_ul--) 9150aadb33SDmitri Tikhonov n_non_zero |= buf_ul[n_ul]; 9250aadb33SDmitri Tikhonov 9350aadb33SDmitri Tikhonov while (buf < end) 9450aadb33SDmitri Tikhonov n_non_zero |= *buf++; 9550aadb33SDmitri Tikhonov 9650aadb33SDmitri Tikhonov return n_non_zero == 0; 9750aadb33SDmitri Tikhonov} 9850aadb33SDmitri Tikhonov 9950aadb33SDmitri Tikhonov 10050aadb33SDmitri Tikhonov/* XXX this function uses static buffer. Replace it with hexdump() if possible */ 10150aadb33SDmitri Tikhonovchar *get_bin_str(const void *s, size_t len, size_t max_display_len) 10250aadb33SDmitri Tikhonov{ 10350aadb33SDmitri Tikhonov const unsigned char *p, *pEnd; 10450aadb33SDmitri Tikhonov char *pOutput; 10550aadb33SDmitri Tikhonov size_t lenOrg = len; 10650aadb33SDmitri Tikhonov static char str[512 * 2 + 40] = {0}; 10750aadb33SDmitri Tikhonov 10850aadb33SDmitri Tikhonov /** 10950aadb33SDmitri Tikhonov * We alloc fixed size buffer, at most max_display_len is 512 11050aadb33SDmitri Tikhonov */ 11150aadb33SDmitri Tikhonov size_t fit_display_len = (max_display_len > 512 ? 512 : max_display_len); 11250aadb33SDmitri Tikhonov if (len > fit_display_len) 11350aadb33SDmitri Tikhonov len = fit_display_len; 11450aadb33SDmitri Tikhonov 11550aadb33SDmitri Tikhonov pOutput = &str[0] + sprintf(str, "(%zd/%zd)=0x", len, lenOrg); 11650aadb33SDmitri Tikhonov 117461e84d8SAmol Deshpande for(p = s, pEnd = (unsigned char*)s + len; p < pEnd; ++p) 11850aadb33SDmitri Tikhonov { 11950aadb33SDmitri Tikhonov sprintf(pOutput, "%02X", *p); 12050aadb33SDmitri Tikhonov pOutput += 2; 12150aadb33SDmitri Tikhonov } 12250aadb33SDmitri Tikhonov if (lenOrg > len) 12350aadb33SDmitri Tikhonov { 12450aadb33SDmitri Tikhonov sprintf(pOutput, "..."); 12550aadb33SDmitri Tikhonov pOutput += 3; 12650aadb33SDmitri Tikhonov } 12750aadb33SDmitri Tikhonov return str; 12850aadb33SDmitri Tikhonov} 12950aadb33SDmitri Tikhonov 13050aadb33SDmitri Tikhonov 13150aadb33SDmitri Tikhonovsize_t 13250aadb33SDmitri Tikhonovhexdump (const void *src_void, size_t src_sz, char *out, size_t out_sz) 13350aadb33SDmitri Tikhonov{ 13450aadb33SDmitri Tikhonov/* Ruler: 13550aadb33SDmitri Tikhonov * 13650aadb33SDmitri Tikhonov 6 31 57 73 13750aadb33SDmitri Tikhonov | | | | 13850aadb33SDmitri Tikhonov0000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |................| 13950aadb33SDmitri Tikhonov * 14050aadb33SDmitri Tikhonov */ 14150aadb33SDmitri Tikhonov#define LINE_SIZE (74 + 1 /* newline */) 14250aadb33SDmitri Tikhonov const unsigned char *src = src_void; 14350aadb33SDmitri Tikhonov const unsigned char *const src_end = src + src_sz; 14450aadb33SDmitri Tikhonov char *const out_end = out + out_sz; 14550aadb33SDmitri Tikhonov unsigned line = 0; 14650aadb33SDmitri Tikhonov 14750aadb33SDmitri Tikhonov while (src < src_end && out_end - out >= LINE_SIZE) 14850aadb33SDmitri Tikhonov { 14950aadb33SDmitri Tikhonov const unsigned char *limit = src + 16; 15050aadb33SDmitri Tikhonov if (limit > src_end) 15150aadb33SDmitri Tikhonov limit = src_end; 15250aadb33SDmitri Tikhonov unsigned hex_off = 6; 15350aadb33SDmitri Tikhonov unsigned alpha_off = 57; 15450aadb33SDmitri Tikhonov sprintf(out, "%04x", line++); 15550aadb33SDmitri Tikhonov out[4] = ' '; 15650aadb33SDmitri Tikhonov out[5] = ' '; 15750aadb33SDmitri Tikhonov while (src < limit) 15850aadb33SDmitri Tikhonov { 15950aadb33SDmitri Tikhonov sprintf(out + hex_off, "%02X ", *src); 16050aadb33SDmitri Tikhonov sprintf(out + alpha_off, "%c", isprint(*src) ? *src : '.'); 16150aadb33SDmitri Tikhonov hex_off += 3; 16250aadb33SDmitri Tikhonov out[hex_off] = ' '; 16350aadb33SDmitri Tikhonov hex_off += 30 == hex_off; 16450aadb33SDmitri Tikhonov out[hex_off] = ' '; 16550aadb33SDmitri Tikhonov ++alpha_off; 16650aadb33SDmitri Tikhonov out[alpha_off] = ' '; 16750aadb33SDmitri Tikhonov ++src; 16850aadb33SDmitri Tikhonov } 16950aadb33SDmitri Tikhonov memset(out + hex_off, ' ', 56 - hex_off); 17050aadb33SDmitri Tikhonov memset(out + alpha_off, '.', 73 - alpha_off); 17150aadb33SDmitri Tikhonov out[56] = '|'; 17250aadb33SDmitri Tikhonov out[73] = '|'; 17350aadb33SDmitri Tikhonov out[74] = '\n'; 17450aadb33SDmitri Tikhonov out += LINE_SIZE; 17550aadb33SDmitri Tikhonov } 17650aadb33SDmitri Tikhonov 17750aadb33SDmitri Tikhonov if (out < out_end) 17850aadb33SDmitri Tikhonov *out = '\0'; 17950aadb33SDmitri Tikhonov else 18050aadb33SDmitri Tikhonov out_end[-1] = '\0'; 18150aadb33SDmitri Tikhonov 18250aadb33SDmitri Tikhonov return out + out_sz - out_end; 18350aadb33SDmitri Tikhonov} 184