hiutil.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <errno.h>
  8. #include <sys/time.h>
  9. #include <sys/types.h>
  10. #include <netinet/in.h>
  11. #include <netinet/tcp.h>
  12. #include "hiutil.h"
  13. #ifdef HI_HAVE_BACKTRACE
  14. # include <execinfo.h>
  15. #endif
  16. int
  17. hi_set_blocking(int sd)
  18. {
  19. int flags;
  20. flags = fcntl(sd, F_GETFL, 0);
  21. if (flags < 0) {
  22. return flags;
  23. }
  24. return fcntl(sd, F_SETFL, flags & ~O_NONBLOCK);
  25. }
  26. int
  27. hi_set_nonblocking(int sd)
  28. {
  29. int flags;
  30. flags = fcntl(sd, F_GETFL, 0);
  31. if (flags < 0) {
  32. return flags;
  33. }
  34. return fcntl(sd, F_SETFL, flags | O_NONBLOCK);
  35. }
  36. int
  37. hi_set_reuseaddr(int sd)
  38. {
  39. int reuse;
  40. socklen_t len;
  41. reuse = 1;
  42. len = sizeof(reuse);
  43. return setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &reuse, len);
  44. }
  45. /*
  46. * Disable Nagle algorithm on TCP socket.
  47. *
  48. * This option helps to minimize transmit latency by disabling coalescing
  49. * of data to fill up a TCP segment inside the kernel. Sockets with this
  50. * option must use readv() or writev() to do data transfer in bulk and
  51. * hence avoid the overhead of small packets.
  52. */
  53. int
  54. hi_set_tcpnodelay(int sd)
  55. {
  56. int nodelay;
  57. socklen_t len;
  58. nodelay = 1;
  59. len = sizeof(nodelay);
  60. return setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, &nodelay, len);
  61. }
  62. int
  63. hi_set_linger(int sd, int timeout)
  64. {
  65. struct linger linger;
  66. socklen_t len;
  67. linger.l_onoff = 1;
  68. linger.l_linger = timeout;
  69. len = sizeof(linger);
  70. return setsockopt(sd, SOL_SOCKET, SO_LINGER, &linger, len);
  71. }
  72. int
  73. hi_set_sndbuf(int sd, int size)
  74. {
  75. socklen_t len;
  76. len = sizeof(size);
  77. return setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &size, len);
  78. }
  79. int
  80. hi_set_rcvbuf(int sd, int size)
  81. {
  82. socklen_t len;
  83. len = sizeof(size);
  84. return setsockopt(sd, SOL_SOCKET, SO_RCVBUF, &size, len);
  85. }
  86. int
  87. hi_get_soerror(int sd)
  88. {
  89. int status, err;
  90. socklen_t len;
  91. err = 0;
  92. len = sizeof(err);
  93. status = getsockopt(sd, SOL_SOCKET, SO_ERROR, &err, &len);
  94. if (status == 0) {
  95. errno = err;
  96. }
  97. return status;
  98. }
  99. int
  100. hi_get_sndbuf(int sd)
  101. {
  102. int status, size;
  103. socklen_t len;
  104. size = 0;
  105. len = sizeof(size);
  106. status = getsockopt(sd, SOL_SOCKET, SO_SNDBUF, &size, &len);
  107. if (status < 0) {
  108. return status;
  109. }
  110. return size;
  111. }
  112. int
  113. hi_get_rcvbuf(int sd)
  114. {
  115. int status, size;
  116. socklen_t len;
  117. size = 0;
  118. len = sizeof(size);
  119. status = getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &size, &len);
  120. if (status < 0) {
  121. return status;
  122. }
  123. return size;
  124. }
  125. int
  126. _hi_atoi(uint8_t *line, size_t n)
  127. {
  128. int value;
  129. if (n == 0) {
  130. return -1;
  131. }
  132. for (value = 0; n--; line++) {
  133. if (*line < '0' || *line > '9') {
  134. return -1;
  135. }
  136. value = value * 10 + (*line - '0');
  137. }
  138. if (value < 0) {
  139. return -1;
  140. }
  141. return value;
  142. }
  143. void
  144. _hi_itoa(uint8_t *s, int num)
  145. {
  146. uint8_t c;
  147. uint8_t sign = 0;
  148. if(s == NULL)
  149. {
  150. return;
  151. }
  152. uint32_t len, i;
  153. len = 0;
  154. if(num < 0)
  155. {
  156. sign = 1;
  157. num = abs(num);
  158. }
  159. else if(num == 0)
  160. {
  161. s[len++] = '0';
  162. return;
  163. }
  164. while(num % 10 || num /10)
  165. {
  166. c = num %10 + '0';
  167. num = num /10;
  168. s[len+1] = s[len];
  169. s[len] = c;
  170. len ++;
  171. }
  172. if(sign == 1)
  173. {
  174. s[len++] = '-';
  175. }
  176. s[len] = '\0';
  177. for(i = 0; i < len/2; i ++)
  178. {
  179. c = s[i];
  180. s[i] = s[len - i -1];
  181. s[len - i -1] = c;
  182. }
  183. }
  184. int
  185. hi_valid_port(int n)
  186. {
  187. if (n < 1 || n > UINT16_MAX) {
  188. return 0;
  189. }
  190. return 1;
  191. }
  192. int _uint_len(uint32_t num)
  193. {
  194. int n = 0;
  195. if(num == 0)
  196. {
  197. return 1;
  198. }
  199. while(num != 0)
  200. {
  201. n ++;
  202. num /= 10;
  203. }
  204. return n;
  205. }
  206. void *
  207. _hi_alloc(size_t size, const char *name, int line)
  208. {
  209. void *p;
  210. ASSERT(size != 0);
  211. p = malloc(size);
  212. if(name == NULL && line == 1)
  213. {
  214. }
  215. return p;
  216. }
  217. void *
  218. _hi_zalloc(size_t size, const char *name, int line)
  219. {
  220. void *p;
  221. p = _hi_alloc(size, name, line);
  222. if (p != NULL) {
  223. memset(p, 0, size);
  224. }
  225. return p;
  226. }
  227. void *
  228. _hi_calloc(size_t nmemb, size_t size, const char *name, int line)
  229. {
  230. return _hi_zalloc(nmemb * size, name, line);
  231. }
  232. void *
  233. _hi_realloc(void *ptr, size_t size, const char *name, int line)
  234. {
  235. void *p;
  236. ASSERT(size != 0);
  237. p = realloc(ptr, size);
  238. if(name == NULL && line == 1)
  239. {
  240. }
  241. return p;
  242. }
  243. void
  244. _hi_free(void *ptr, const char *name, int line)
  245. {
  246. ASSERT(ptr != NULL);
  247. if(name == NULL && line == 1)
  248. {
  249. }
  250. free(ptr);
  251. }
  252. void
  253. hi_stacktrace(int skip_count)
  254. {
  255. if(skip_count > 0)
  256. {
  257. }
  258. #ifdef HI_HAVE_BACKTRACE
  259. void *stack[64];
  260. char **symbols;
  261. int size, i, j;
  262. size = backtrace(stack, 64);
  263. symbols = backtrace_symbols(stack, size);
  264. if (symbols == NULL) {
  265. return;
  266. }
  267. skip_count++; /* skip the current frame also */
  268. for (i = skip_count, j = 0; i < size; i++, j++) {
  269. printf("[%d] %s\n", j, symbols[i]);
  270. }
  271. free(symbols);
  272. #endif
  273. }
  274. void
  275. hi_stacktrace_fd(int fd)
  276. {
  277. if(fd > 0)
  278. {
  279. }
  280. #ifdef HI_HAVE_BACKTRACE
  281. void *stack[64];
  282. int size;
  283. size = backtrace(stack, 64);
  284. backtrace_symbols_fd(stack, size, fd);
  285. #endif
  286. }
  287. void
  288. hi_assert(const char *cond, const char *file, int line, int panic)
  289. {
  290. printf("File: %s Line: %d: %s\n", file, line, cond);
  291. if (panic) {
  292. hi_stacktrace(1);
  293. abort();
  294. }
  295. abort();
  296. }
  297. int
  298. _vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
  299. {
  300. int n;
  301. n = vsnprintf(buf, size, fmt, args);
  302. /*
  303. * The return value is the number of characters which would be written
  304. * into buf not including the trailing '\0'. If size is == 0 the
  305. * function returns 0.
  306. *
  307. * On error, the function also returns 0. This is to allow idiom such
  308. * as len += _vscnprintf(...)
  309. *
  310. * See: http://lwn.net/Articles/69419/
  311. */
  312. if (n <= 0) {
  313. return 0;
  314. }
  315. if (n < (int) size) {
  316. return n;
  317. }
  318. return (int)(size - 1);
  319. }
  320. int
  321. _scnprintf(char *buf, size_t size, const char *fmt, ...)
  322. {
  323. va_list args;
  324. int n;
  325. va_start(args, fmt);
  326. n = _vscnprintf(buf, size, fmt, args);
  327. va_end(args);
  328. return n;
  329. }
  330. /*
  331. * Send n bytes on a blocking descriptor
  332. */
  333. ssize_t
  334. _hi_sendn(int sd, const void *vptr, size_t n)
  335. {
  336. size_t nleft;
  337. ssize_t nsend;
  338. const char *ptr;
  339. ptr = vptr;
  340. nleft = n;
  341. while (nleft > 0) {
  342. nsend = send(sd, ptr, nleft, 0);
  343. if (nsend < 0) {
  344. if (errno == EINTR) {
  345. continue;
  346. }
  347. return nsend;
  348. }
  349. if (nsend == 0) {
  350. return -1;
  351. }
  352. nleft -= (size_t)nsend;
  353. ptr += nsend;
  354. }
  355. return (ssize_t)n;
  356. }
  357. /*
  358. * Recv n bytes from a blocking descriptor
  359. */
  360. ssize_t
  361. _hi_recvn(int sd, void *vptr, size_t n)
  362. {
  363. size_t nleft;
  364. ssize_t nrecv;
  365. char *ptr;
  366. ptr = vptr;
  367. nleft = n;
  368. while (nleft > 0) {
  369. nrecv = recv(sd, ptr, nleft, 0);
  370. if (nrecv < 0) {
  371. if (errno == EINTR) {
  372. continue;
  373. }
  374. return nrecv;
  375. }
  376. if (nrecv == 0) {
  377. break;
  378. }
  379. nleft -= (size_t)nrecv;
  380. ptr += nrecv;
  381. }
  382. return (ssize_t)(n - nleft);
  383. }
  384. /*
  385. * Return the current time in microseconds since Epoch
  386. */
  387. int64_t
  388. hi_usec_now(void)
  389. {
  390. struct timeval now;
  391. int64_t usec;
  392. int status;
  393. status = gettimeofday(&now, NULL);
  394. if (status < 0) {
  395. return -1;
  396. }
  397. usec = (int64_t)now.tv_sec * 1000000LL + (int64_t)now.tv_usec;
  398. return usec;
  399. }
  400. /*
  401. * Return the current time in milliseconds since Epoch
  402. */
  403. int64_t
  404. hi_msec_now(void)
  405. {
  406. return hi_usec_now() / 1000LL;
  407. }
  408. void print_string_with_length(char *s, size_t len)
  409. {
  410. char *token;
  411. for(token = s; token <= s + len; token ++)
  412. {
  413. printf("%c", *token);
  414. }
  415. printf("\n");
  416. }
  417. void print_string_with_length_fix_CRLF(char *s, size_t len)
  418. {
  419. char *token;
  420. for(token = s; token < s + len; token ++)
  421. {
  422. if(*token == CR)
  423. {
  424. printf("\\r");
  425. }
  426. else if(*token == LF)
  427. {
  428. printf("\\n");
  429. }
  430. else
  431. {
  432. printf("%c", *token);
  433. }
  434. }
  435. printf("\n");
  436. }