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