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 int anetTcpNoDelay(char *err, int fd) 79 { 80 int yes = 1; 81 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) 82 { 83 anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno)); 84 return ANET_ERR; 85 } 86 return ANET_OK; 87 } 88 89 int anetSetSendBuffer(char *err, int fd, int buffsize) 90 { 91 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) 92 { 93 anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno)); 94 return ANET_ERR; 95 } 96 return ANET_OK; 97 } 98 99 int anetTcpKeepAlive(char *err, int fd) 100 { 101 int yes = 1; 102 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { 103 anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); 104 return ANET_ERR; 105 } 106 return ANET_OK; 107 } 108 109 int anetResolve(char *err, char *host, char *ipbuf) 110 { 111 struct sockaddr_in sa; 112 113 sa.sin_family = AF_INET; 114 if (inet_aton(host, &sa.sin_addr) == 0) { 115 struct hostent *he; 116 117 he = gethostbyname(host); 118 if (he == NULL) { 119 anetSetError(err, "can't resolve: %s", host); 120 return ANET_ERR; 121 } 122 memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); 123 } 124 strcpy(ipbuf,inet_ntoa(sa.sin_addr)); 125 return ANET_OK; 126 } 127 128 static int anetCreateSocket(char *err, int domain) { 129 int s, on = 1; 130 if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { 131 anetSetError(err, "creating socket: %s", strerror(errno)); 132 return ANET_ERR; 133 } 134 135 /* Make sure connection-intensive things like the redis benchmark 136 * will be able to close/open sockets a zillion of times */ 137 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { 138 anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); 139 return ANET_ERR; 140 } 141 return s; 142 } 143 144 #define ANET_CONNECT_NONE 0 145 #define ANET_CONNECT_NONBLOCK 1 146 static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) 147 { 148 int s; 149 struct sockaddr_in sa; 150 151 if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) 152 return ANET_ERR; 153 154 sa.sin_family = AF_INET; 155 sa.sin_port = htons(port); 156 if (inet_aton(addr, &sa.sin_addr) == 0) { 157 struct hostent *he; 158 159 he = gethostbyname(addr); 160 if (he == NULL) { 161 anetSetError(err, "can't resolve: %s", addr); 162 close(s); 163 return ANET_ERR; 164 } 165 memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); 166 } 167 if (flags & ANET_CONNECT_NONBLOCK) { 168 if (anetNonBlock(err,s) != ANET_OK) 169 return ANET_ERR; 170 } 171 if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { 172 if (errno == EINPROGRESS && 173 flags & ANET_CONNECT_NONBLOCK) 174 return s; 175 176 anetSetError(err, "connect: %s", strerror(errno)); 177 close(s); 178 return ANET_ERR; 179 } 180 return s; 181 } 182 183 int anetTcpConnect(char *err, char *addr, int port) 184 { 185 return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONE); 186 } 187 188 int anetTcpNonBlockConnect(char *err, char *addr, int port) 189 { 190 return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK); 191 } 192 193 int anetUnixGenericConnect(char *err, char *path, int flags) 194 { 195 int s; 196 struct sockaddr_un sa; 197 198 if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) 199 return ANET_ERR; 200 201 sa.sun_family = AF_LOCAL; 202 strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); 203 if (flags & ANET_CONNECT_NONBLOCK) { 204 if (anetNonBlock(err,s) != ANET_OK) 205 return ANET_ERR; 206 } 207 if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) { 208 if (errno == EINPROGRESS && 209 flags & ANET_CONNECT_NONBLOCK) 210 return s; 211 212 anetSetError(err, "connect: %s", strerror(errno)); 213 close(s); 214 return ANET_ERR; 215 } 216 return s; 217 } 218 219 int anetUnixConnect(char *err, char *path) 220 { 221 return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE); 222 } 223 224 int anetUnixNonBlockConnect(char *err, char *path) 225 { 226 return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK); 227 } 228 229 /* Like read(2) but make sure 'count' is read before to return 230 * (unless error or EOF condition is encountered) */ 231 int anetRead(int fd, char *buf, int count) 232 { 233 int nread, totlen = 0; 234 while(totlen != count) { 235 nread = read(fd,buf,count-totlen); 236 if (nread == 0) return totlen; 237 if (nread == -1) return -1; 238 totlen += nread; 239 buf += nread; 240 } 241 return totlen; 242 } 243 244 /* Like write(2) but make sure 'count' is read before to return 245 * (unless error is encountered) */ 246 int anetWrite(int fd, char *buf, int count) 247 { 248 int nwritten, totlen = 0; 249 while(totlen != count) { 250 nwritten = write(fd,buf,count-totlen); 251 if (nwritten == 0) return totlen; 252 if (nwritten == -1) return -1; 253 totlen += nwritten; 254 buf += nwritten; 255 } 256 return totlen; 257 } 258 259 static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) { 260 if (bind(s,sa,len) == -1) { 261 anetSetError(err, "bind: %s", strerror(errno)); 262 close(s); 263 return ANET_ERR; 264 } 265 266 /* Use a backlog of 512 entries. We pass 511 to the listen() call because 267 * the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); 268 * which will thus give us a backlog of 512 entries */ 269 if (listen(s, 511) == -1) { 270 anetSetError(err, "listen: %s", strerror(errno)); 271 close(s); 272 return ANET_ERR; 273 } 274 return ANET_OK; 275 } 276 277 int anetTcpServer(char *err, int port, char *bindaddr) 278 { 279 int s; 280 struct sockaddr_in sa; 281 282 if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) 283 return ANET_ERR; 284 285 memset(&sa,0,sizeof(sa)); 286 sa.sin_family = AF_INET; 287 sa.sin_port = htons(port); 288 sa.sin_addr.s_addr = htonl(INADDR_ANY); 289 if (bindaddr && inet_aton(bindaddr, &sa.sin_addr) == 0) { 290 anetSetError(err, "invalid bind address"); 291 close(s); 292 return ANET_ERR; 293 } 294 if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR) 295 return ANET_ERR; 296 return s; 297 } 298 299 int anetUnixServer(char *err, char *path, mode_t perm) 300 { 301 int s; 302 struct sockaddr_un sa; 303 304 if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) 305 return ANET_ERR; 306 307 memset(&sa,0,sizeof(sa)); 308 sa.sun_family = AF_LOCAL; 309 strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); 310 if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR) 311 return ANET_ERR; 312 if (perm) 313 chmod(sa.sun_path, perm); 314 return s; 315 } 316 317 static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { 318 int fd; 319 while(1) { 320 fd = accept(s,sa,len); 321 if (fd == -1) { 322 if (errno == EINTR) 323 continue; 324 else { 325 anetSetError(err, "accept: %s", strerror(errno)); 326 return ANET_ERR; 327 } 328 } 329 break; 330 } 331 return fd; 332 } 333 334 int anetTcpAccept(char *err, int s, char *ip, int *port) { 335 int fd; 336 struct sockaddr_in sa; 337 socklen_t salen = sizeof(sa); 338 if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR) 339 return ANET_ERR; 340 341 if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); 342 if (port) *port = ntohs(sa.sin_port); 343 return fd; 344 } 345 346 int anetUnixAccept(char *err, int s) { 347 int fd; 348 struct sockaddr_un sa; 349 socklen_t salen = sizeof(sa); 350 if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR) 351 return ANET_ERR; 352 353 return fd; 354 } 355 356 int anetPeerToString(int fd, char *ip, int *port) { 357 struct sockaddr_in sa; 358 socklen_t salen = sizeof(sa); 359 360 if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) { 361 *port = 0; 362 ip[0] = '?'; 363 ip[1] = '\0'; 364 return -1; 365 } 366 if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); 367 if (port) *port = ntohs(sa.sin_port); 368 return 0; 369 } 370 371 int anetSockName(int fd, char *ip, int *port) { 372 struct sockaddr_in sa; 373 socklen_t salen = sizeof(sa); 374 375 if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) { 376 *port = 0; 377 ip[0] = '?'; 378 ip[1] = '\0'; 379 return -1; 380 } 381 if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); 382 if (port) *port = ntohs(sa.sin_port); 383 return 0; 384 } 385