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