1 /* anet.c -- Basic TCP socket stuff made a bit less boring 2 * 3 * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * * Neither the name of Redis nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without 16 * specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "fmacros.h" 32 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <sys/stat.h> 36 #include <sys/un.h> 37 #include <netinet/in.h> 38 #include <netinet/tcp.h> 39 #include <arpa/inet.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <string.h> 43 #include <netdb.h> 44 #include <errno.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 48 #include "anet.h" 49 50 static void anetSetError(char *err, const char *fmt, ...) 51 { 52 va_list ap; 53 54 if (!err) return; 55 va_start(ap, fmt); 56 vsnprintf(err, ANET_ERR_LEN, fmt, ap); 57 va_end(ap); 58 } 59 60 int anetNonBlock(char *err, int fd) 61 { 62 int flags; 63 64 /* Set the socket non-blocking. 65 * Note that fcntl(2) for F_GETFL and F_SETFL can't be 66 * interrupted by a signal. */ 67 if ((flags = fcntl(fd, F_GETFL)) == -1) { 68 anetSetError(err, "fcntl(F_GETFL): %s", strerror(errno)); 69 return ANET_ERR; 70 } 71 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 72 anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)); 73 return ANET_ERR; 74 } 75 return ANET_OK; 76 } 77 78 /* Set TCP keep alive option to detect dead peers. The interval option 79 * is only used for Linux as we are using Linux-specific APIs to set 80 * the probe send time, interval, and count. */ 81 int anetKeepAlive(char *err, int fd, int interval) 82 { 83 int val = 1; 84 85 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1) 86 { 87 anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); 88 return ANET_ERR; 89 } 90 91 #ifdef __linux__ 92 /* Default settings are more or less garbage, with the keepalive time 93 * set to 7200 by default on Linux. Modify settings to make the feature 94 * actually useful. */ 95 96 /* Send first probe after interval. */ 97 val = interval; 98 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { 99 anetSetError(err, "setsockopt TCP_KEEPIDLE: %s\n", strerror(errno)); 100 return ANET_ERR; 101 } 102 103 /* Send next probes after the specified interval. Note that we set the 104 * delay as interval / 3, as we send three probes before detecting 105 * an error (see the next setsockopt call). */ 106 val = interval/3; 107 if (val == 0) val = 1; 108 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { 109 anetSetError(err, "setsockopt TCP_KEEPINTVL: %s\n", strerror(errno)); 110 return ANET_ERR; 111 } 112 113 /* Consider the socket in error state after three we send three ACK 114 * probes without getting a reply. */ 115 val = 3; 116 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { 117 anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno)); 118 return ANET_ERR; 119 } 120 #endif 121 122 return ANET_OK; 123 } 124 125 static int anetSetTcpNoDelay(char *err, int fd, int val) 126 { 127 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1) 128 { 129 anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno)); 130 return ANET_ERR; 131 } 132 return ANET_OK; 133 } 134 135 int anetEnableTcpNoDelay(char *err, int fd) 136 { 137 return anetSetTcpNoDelay(err, fd, 1); 138 } 139 140 int anetDisableTcpNoDelay(char *err, int fd) 141 { 142 return anetSetTcpNoDelay(err, fd, 0); 143 } 144 145 146 int anetSetSendBuffer(char *err, int fd, int buffsize) 147 { 148 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) 149 { 150 anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno)); 151 return ANET_ERR; 152 } 153 return ANET_OK; 154 } 155 156 int anetTcpKeepAlive(char *err, int fd) 157 { 158 int yes = 1; 159 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { 160 anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); 161 return ANET_ERR; 162 } 163 return ANET_OK; 164 } 165 166 int anetResolve(char *err, char *host, char *ipbuf) 167 { 168 struct sockaddr_in sa; 169 170 sa.sin_family = AF_INET; 171 if (inet_aton(host, &sa.sin_addr) == 0) { 172 struct hostent *he; 173 174 he = gethostbyname(host); 175 if (he == NULL) { 176 anetSetError(err, "can't resolve: %s", host); 177 return ANET_ERR; 178 } 179 memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); 180 } 181 strcpy(ipbuf,inet_ntoa(sa.sin_addr)); 182 return ANET_OK; 183 } 184 185 static int anetCreateSocket(char *err, int domain) { 186 int s, on = 1; 187 if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { 188 anetSetError(err, "creating socket: %s", strerror(errno)); 189 return ANET_ERR; 190 } 191 192 /* Make sure connection-intensive things like the redis benchmark 193 * will be able to close/open sockets a zillion of times */ 194 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { 195 anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); 196 return ANET_ERR; 197 } 198 return s; 199 } 200 201 #define ANET_CONNECT_NONE 0 202 #define ANET_CONNECT_NONBLOCK 1 203 static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) 204 { 205 int s; 206 struct sockaddr_in sa; 207 208 if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) 209 return ANET_ERR; 210 211 sa.sin_family = AF_INET; 212 sa.sin_port = htons(port); 213 if (inet_aton(addr, &sa.sin_addr) == 0) { 214 struct hostent *he; 215 216 he = gethostbyname(addr); 217 if (he == NULL) { 218 anetSetError(err, "can't resolve: %s", addr); 219 close(s); 220 return ANET_ERR; 221 } 222 memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); 223 } 224 if (flags & ANET_CONNECT_NONBLOCK) { 225 if (anetNonBlock(err,s) != ANET_OK) 226 return ANET_ERR; 227 } 228 if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { 229 if (errno == EINPROGRESS && 230 flags & ANET_CONNECT_NONBLOCK) 231 return s; 232 233 anetSetError(err, "connect: %s", strerror(errno)); 234 close(s); 235 return ANET_ERR; 236 } 237 return s; 238 } 239 240 int anetTcpConnect(char *err, char *addr, int port) 241 { 242 return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONE); 243 } 244 245 int anetTcpNonBlockConnect(char *err, char *addr, int port) 246 { 247 return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK); 248 } 249 250 int anetUnixGenericConnect(char *err, char *path, int flags) 251 { 252 int s; 253 struct sockaddr_un sa; 254 255 if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) 256 return ANET_ERR; 257 258 sa.sun_family = AF_LOCAL; 259 strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); 260 if (flags & ANET_CONNECT_NONBLOCK) { 261 if (anetNonBlock(err,s) != ANET_OK) 262 return ANET_ERR; 263 } 264 if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) { 265 if (errno == EINPROGRESS && 266 flags & ANET_CONNECT_NONBLOCK) 267 return s; 268 269 anetSetError(err, "connect: %s", strerror(errno)); 270 close(s); 271 return ANET_ERR; 272 } 273 return s; 274 } 275 276 int anetUnixConnect(char *err, char *path) 277 { 278 return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE); 279 } 280 281 int anetUnixNonBlockConnect(char *err, char *path) 282 { 283 return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK); 284 } 285 286 /* Like read(2) but make sure 'count' is read before to return 287 * (unless error or EOF condition is encountered) */ 288 int anetRead(int fd, char *buf, int count) 289 { 290 int nread, totlen = 0; 291 while(totlen != count) { 292 nread = read(fd,buf,count-totlen); 293 if (nread == 0) return totlen; 294 if (nread == -1) return -1; 295 totlen += nread; 296 buf += nread; 297 } 298 return totlen; 299 } 300 301 /* Like write(2) but make sure 'count' is read before to return 302 * (unless error is encountered) */ 303 int anetWrite(int fd, char *buf, int count) 304 { 305 int nwritten, totlen = 0; 306 while(totlen != count) { 307 nwritten = write(fd,buf,count-totlen); 308 if (nwritten == 0) return totlen; 309 if (nwritten == -1) return -1; 310 totlen += nwritten; 311 buf += nwritten; 312 } 313 return totlen; 314 } 315 316 static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) { 317 if (bind(s,sa,len) == -1) { 318 anetSetError(err, "bind: %s", strerror(errno)); 319 close(s); 320 return ANET_ERR; 321 } 322 323 /* Use a backlog of 512 entries. We pass 511 to the listen() call because 324 * the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); 325 * which will thus give us a backlog of 512 entries */ 326 if (listen(s, 511) == -1) { 327 anetSetError(err, "listen: %s", strerror(errno)); 328 close(s); 329 return ANET_ERR; 330 } 331 return ANET_OK; 332 } 333 334 int anetTcpServer(char *err, int port, char *bindaddr) 335 { 336 int s; 337 struct sockaddr_in sa; 338 339 if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) 340 return ANET_ERR; 341 342 memset(&sa,0,sizeof(sa)); 343 sa.sin_family = AF_INET; 344 sa.sin_port = htons(port); 345 sa.sin_addr.s_addr = htonl(INADDR_ANY); 346 if (bindaddr && inet_aton(bindaddr, &sa.sin_addr) == 0) { 347 anetSetError(err, "invalid bind address"); 348 close(s); 349 return ANET_ERR; 350 } 351 if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR) 352 return ANET_ERR; 353 return s; 354 } 355 356 int anetUnixServer(char *err, char *path, mode_t perm) 357 { 358 int s; 359 struct sockaddr_un sa; 360 361 if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) 362 return ANET_ERR; 363 364 memset(&sa,0,sizeof(sa)); 365 sa.sun_family = AF_LOCAL; 366 strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); 367 if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR) 368 return ANET_ERR; 369 if (perm) 370 chmod(sa.sun_path, perm); 371 return s; 372 } 373 374 static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { 375 int fd; 376 while(1) { 377 fd = accept(s,sa,len); 378 if (fd == -1) { 379 if (errno == EINTR) 380 continue; 381 else { 382 anetSetError(err, "accept: %s", strerror(errno)); 383 return ANET_ERR; 384 } 385 } 386 break; 387 } 388 return fd; 389 } 390 391 int anetTcpAccept(char *err, int s, char *ip, int *port) { 392 int fd; 393 struct sockaddr_in sa; 394 socklen_t salen = sizeof(sa); 395 if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR) 396 return ANET_ERR; 397 398 if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); 399 if (port) *port = ntohs(sa.sin_port); 400 return fd; 401 } 402 403 int anetUnixAccept(char *err, int s) { 404 int fd; 405 struct sockaddr_un sa; 406 socklen_t salen = sizeof(sa); 407 if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR) 408 return ANET_ERR; 409 410 return fd; 411 } 412 413 int anetPeerToString(int fd, char *ip, int *port) { 414 struct sockaddr_in sa; 415 socklen_t salen = sizeof(sa); 416 417 if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) { 418 *port = 0; 419 ip[0] = '?'; 420 ip[1] = '\0'; 421 return -1; 422 } 423 if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); 424 if (port) *port = ntohs(sa.sin_port); 425 return 0; 426 } 427 428 int anetSockName(int fd, char *ip, int *port) { 429 struct sockaddr_in sa; 430 socklen_t salen = sizeof(sa); 431 432 if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) { 433 *port = 0; 434 ip[0] = '?'; 435 ip[1] = '\0'; 436 return -1; 437 } 438 if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); 439 if (port) *port = ntohs(sa.sin_port); 440 return 0; 441 } 442