1 /* 2 * twemproxy - A fast and lightweight proxy for memcached protocol. 3 * Copyright (C) 2011 Twitter, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #ifndef _NC_UTIL_H_ 19 #define _NC_UTIL_H_ 20 21 #include <stdarg.h> 22 23 #ifdef __GNUC__ 24 # define NC_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) 25 #else 26 # define NC_GCC_VERSION 0 27 #endif 28 #if NC_GCC_VERSION >= 2007 29 #define NC_ATTRIBUTE_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first))) 30 #else 31 #define NC_ATTRIBUTE_FORMAT(type, idx, first) 32 #endif 33 34 35 #define LF (uint8_t) 10 36 #define CR (uint8_t) 13 37 #define CRLF "\x0d\x0a" 38 #define CRLF_LEN (sizeof("\x0d\x0a") - 1) 39 40 #define NELEMS(a) ((sizeof(a)) / sizeof((a)[0])) 41 42 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 43 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 44 45 #define SQUARE(d) ((d) * (d)) 46 #define VAR(s, s2, n) (((n) < 2) ? 0.0 : ((s2) - SQUARE(s)/(n)) / ((n) - 1)) 47 #define STDDEV(s, s2, n) (((n) < 2) ? 0.0 : sqrt(VAR((s), (s2), (n)))) 48 49 #define NC_INET4_ADDRSTRLEN (sizeof("255.255.255.255") - 1) 50 #define NC_INET6_ADDRSTRLEN \ 51 (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) 52 #define NC_INET_ADDRSTRLEN MAX(NC_INET4_ADDRSTRLEN, NC_INET6_ADDRSTRLEN) 53 #define NC_UNIX_ADDRSTRLEN \ 54 (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path)) 55 56 #define NC_MAXHOSTNAMELEN 256 57 58 /* 59 * Length of 1 byte, 2 bytes, 4 bytes, 8 bytes and largest integral 60 * type (uintmax_t) in ascii, including the null terminator '\0' 61 * 62 * From stdint.h, we have: 63 * # define UINT8_MAX (255) 64 * # define UINT16_MAX (65535) 65 * # define UINT32_MAX (4294967295U) 66 * # define UINT64_MAX (__UINT64_C(18446744073709551615)) 67 */ 68 #define NC_UINT8_MAXLEN (3 + 1) 69 #define NC_UINT16_MAXLEN (5 + 1) 70 #define NC_UINT32_MAXLEN (10 + 1) 71 #define NC_UINT64_MAXLEN (20 + 1) 72 #define NC_UINTMAX_MAXLEN NC_UINT64_MAXLEN 73 74 /* 75 * Make data 'd' or pointer 'p', n-byte aligned, where n is a power of 2 76 * of 2. 77 */ 78 #define NC_ALIGNMENT sizeof(unsigned long) /* platform word */ 79 #define NC_ALIGN(d, n) (((d) + (n - 1)) & ~(n - 1)) 80 #define NC_ALIGN_PTR(p, n) \ 81 (void *) (((uintptr_t) (p) + ((uintptr_t) n - 1)) & ~((uintptr_t) n - 1)) 82 83 /* 84 * Wrapper to workaround well known, safe, implicit type conversion when 85 * invoking system calls. 86 */ 87 #define nc_gethostname(_name, _len) \ 88 gethostname((char *)_name, (size_t)_len) 89 90 #define nc_atoi(_line, _n) \ 91 _nc_atoi((uint8_t *)_line, (size_t)_n) 92 93 int nc_set_blocking(int sd); 94 int nc_set_nonblocking(int sd); 95 int nc_set_reuseaddr(int sd); 96 int nc_set_tcpnodelay(int sd); 97 int nc_set_linger(int sd, int timeout); 98 int nc_set_sndbuf(int sd, int size); 99 int nc_set_rcvbuf(int sd, int size); 100 int nc_set_tcpkeepalive(int sd); 101 int nc_get_soerror(int sd); 102 int nc_get_sndbuf(int sd); 103 int nc_get_rcvbuf(int sd); 104 105 int _nc_atoi(const uint8_t *line, size_t n); 106 bool nc_valid_port(int n); 107 108 /* 109 * Memory allocation and free wrappers. 110 * 111 * These wrappers enables us to loosely detect double free, dangling 112 * pointer access and zero-byte alloc. 113 */ 114 #define nc_alloc(_s) \ 115 _nc_alloc((size_t)(_s), __FILE__, __LINE__) 116 117 #define nc_zalloc(_s) \ 118 _nc_zalloc((size_t)(_s), __FILE__, __LINE__) 119 120 #define nc_calloc(_n, _s) \ 121 _nc_calloc((size_t)(_n), (size_t)(_s), __FILE__, __LINE__) 122 123 #define nc_realloc(_p, _s) \ 124 _nc_realloc(_p, (size_t)(_s), __FILE__, __LINE__) 125 126 #define nc_free(_p) do { \ 127 _nc_free(_p, __FILE__, __LINE__); \ 128 (_p) = NULL; \ 129 } while (0) 130 131 void *_nc_alloc(size_t size, const char *name, int line); 132 void *_nc_zalloc(size_t size, const char *name, int line); 133 void *_nc_calloc(size_t nmemb, size_t size, const char *name, int line); 134 void *_nc_realloc(void *ptr, size_t size, const char *name, int line); 135 void _nc_free(void *ptr, const char *name, int line); 136 137 /* 138 * Wrappers to send or receive n byte message on a blocking 139 * socket descriptor. 140 */ 141 #define nc_sendn(_s, _b, _n) \ 142 _nc_sendn(_s, _b, (size_t)(_n)) 143 144 #define nc_recvn(_s, _b, _n) \ 145 _nc_recvn(_s, _b, (size_t)(_n)) 146 147 /* 148 * Wrappers to read or write data to/from (multiple) buffers 149 * to a file or socket descriptor. 150 */ 151 #define nc_read(_d, _b, _n) \ 152 read(_d, _b, (size_t)(_n)) 153 154 #define nc_readv(_d, _b, _n) \ 155 readv(_d, _b, (int)(_n)) 156 157 #define nc_write(_d, _b, _n) \ 158 write(_d, _b, (size_t)(_n)) 159 160 #define nc_writev(_d, _b, _n) \ 161 writev(_d, _b, (int)(_n)) 162 163 ssize_t _nc_sendn(int sd, const void *vptr, size_t n); 164 ssize_t _nc_recvn(int sd, void *vptr, size_t n); 165 166 /* 167 * Wrappers for defining custom assert based on whether macro 168 * NC_ASSERT_PANIC or NC_ASSERT_LOG was defined at the moment 169 * ASSERT was called. 170 */ 171 #ifdef NC_ASSERT_PANIC 172 173 #define ASSERT(_x) do { \ 174 if (!(_x)) { \ 175 nc_assert(#_x, __FILE__, __LINE__, 1); \ 176 } \ 177 } while (0) 178 179 #define NOT_REACHED() ASSERT(0) 180 181 #elif NC_ASSERT_LOG 182 183 #define ASSERT(_x) do { \ 184 if (!(_x)) { \ 185 nc_assert(#_x, __FILE__, __LINE__, 0); \ 186 } \ 187 } while (0) 188 189 #define NOT_REACHED() ASSERT(0) 190 191 #else 192 193 #define ASSERT(_x) 194 195 #define NOT_REACHED() 196 197 #endif 198 199 void nc_assert(const char *cond, const char *file, int line, int panic); 200 void nc_stacktrace(int skip_count); 201 void nc_stacktrace_fd(int fd); 202 203 int _scnprintf(char *buf, size_t size, const char *fmt, ...) NC_ATTRIBUTE_FORMAT(printf, 3, 4); 204 int _vscnprintf(char *buf, size_t size, const char *fmt, va_list args); 205 int64_t nc_usec_now(void); 206 int64_t nc_msec_now(void); 207 208 /* 209 * Address resolution for internet (ipv4 and ipv6) and unix domain 210 * socket address. 211 */ 212 213 struct sockinfo { 214 int family; /* socket address family */ 215 socklen_t addrlen; /* socket address length */ 216 union { 217 struct sockaddr_in in; /* ipv4 socket address */ 218 struct sockaddr_in6 in6; /* ipv6 socket address */ 219 struct sockaddr_un un; /* unix domain address */ 220 } addr; 221 }; 222 223 int nc_resolve(const struct string *name, int port, struct sockinfo *si); 224 const char *nc_unresolve_addr(struct sockaddr *addr, socklen_t addrlen); 225 const char *nc_unresolve_peer_desc(int sd); 226 const char *nc_unresolve_desc(int sd); 227 228 #endif 229