lsquic_util.c revision 55cd0b38
1/* Copyright (c) 2017 - 2019 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 131static char 132hex_digit(uint8_t n) 133{ 134 return (n < 10) ? (n + '0') : ((n - 10) + 'a'); 135} 136 137 138size_t 139lsquic_hex_encode (const void *src, size_t src_sz, void *dst, size_t dst_sz) 140{ 141 size_t src_cur, dst_cur; 142 const uint8_t *src_hex; 143 char *dst_char; 144 145 src_hex = (const uint8_t *)src; 146 dst_char = (char *)dst; 147 src_cur = dst_cur = 0; 148 149 while (src_cur < src_sz && dst_cur < (dst_sz - 2)) 150 { 151 dst_char[dst_cur++] = hex_digit((src_hex[src_cur] & 0xf0) >> 4); 152 dst_char[dst_cur++] = hex_digit(src_hex[src_cur++] & 0x0f); 153 } 154 dst_char[dst_cur++] = '\0'; 155 return dst_cur; 156} 157 158 159size_t 160hexdump (const void *src_void, size_t src_sz, char *out, size_t out_sz) 161{ 162/* Ruler: 163 * 164 6 31 57 73 165 | | | | 1660000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |................| 167 * 168 */ 169#define LINE_SIZE (74 + 1 /* newline */) 170 const unsigned char *src = src_void; 171 const unsigned char *const src_end = src + src_sz; 172 char *const out_end = out + out_sz; 173 unsigned line = 0; 174 175 while (src < src_end && out_end - out >= LINE_SIZE) 176 { 177 const unsigned char *limit = src + 16; 178 if (limit > src_end) 179 limit = src_end; 180 unsigned hex_off = 6; 181 unsigned alpha_off = 57; 182 sprintf(out, "%04x", line++); 183 out[4] = ' '; 184 out[5] = ' '; 185 while (src < limit) 186 { 187 sprintf(out + hex_off, "%02X ", *src); 188 sprintf(out + alpha_off, "%c", isprint(*src) ? *src : '.'); 189 hex_off += 3; 190 out[hex_off] = ' '; 191 hex_off += 30 == hex_off; 192 out[hex_off] = ' '; 193 ++alpha_off; 194 out[alpha_off] = ' '; 195 ++src; 196 } 197 memset(out + hex_off, ' ', 56 - hex_off); 198 memset(out + alpha_off, '.', 73 - alpha_off); 199 out[56] = '|'; 200 out[73] = '|'; 201 out[74] = '\n'; 202 out += LINE_SIZE; 203 } 204 205 if (out < out_end) 206 *out = '\0'; 207 else 208 out_end[-1] = '\0'; 209 210 return out + out_sz - out_end; 211} 212