Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /************************************************ 00002 00003 init.c - 00004 00005 created at: Thu Mar 31 12:21:29 JST 1994 00006 00007 Copyright (C) 1993-2007 Yukihiro Matsumoto 00008 00009 ************************************************/ 00010 00011 #include "rubysocket.h" 00012 00013 VALUE rb_cBasicSocket; 00014 VALUE rb_cIPSocket; 00015 VALUE rb_cTCPSocket; 00016 VALUE rb_cTCPServer; 00017 VALUE rb_cUDPSocket; 00018 #ifdef AF_UNIX 00019 VALUE rb_cUNIXSocket; 00020 VALUE rb_cUNIXServer; 00021 #endif 00022 VALUE rb_cSocket; 00023 VALUE rb_cAddrinfo; 00024 00025 VALUE rb_eSocket; 00026 00027 #ifdef SOCKS 00028 VALUE rb_cSOCKSSocket; 00029 #endif 00030 00031 int rsock_do_not_reverse_lookup = 1; 00032 00033 void 00034 rsock_raise_socket_error(const char *reason, int error) 00035 { 00036 #ifdef EAI_SYSTEM 00037 if (error == EAI_SYSTEM) rb_sys_fail(reason); 00038 #endif 00039 rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error)); 00040 } 00041 00042 VALUE 00043 rsock_init_sock(VALUE sock, int fd) 00044 { 00045 rb_io_t *fp; 00046 #ifndef _WIN32 00047 struct stat sbuf; 00048 00049 if (fstat(fd, &sbuf) < 0) 00050 rb_sys_fail(0); 00051 rb_update_max_fd(fd); 00052 if (!S_ISSOCK(sbuf.st_mode)) 00053 rb_raise(rb_eArgError, "not a socket file descriptor"); 00054 #else 00055 rb_update_max_fd(fd); 00056 if (!rb_w32_is_socket(fd)) 00057 rb_raise(rb_eArgError, "not a socket file descriptor"); 00058 #endif 00059 00060 MakeOpenFile(sock, fp); 00061 fp->fd = fd; 00062 fp->mode = FMODE_READWRITE|FMODE_DUPLEX; 00063 rb_io_ascii8bit_binmode(sock); 00064 if (rsock_do_not_reverse_lookup) { 00065 fp->mode |= FMODE_NOREVLOOKUP; 00066 } 00067 rb_io_synchronized(fp); 00068 00069 return sock; 00070 } 00071 00072 VALUE 00073 rsock_sendto_blocking(void *data) 00074 { 00075 struct rsock_send_arg *arg = data; 00076 VALUE mesg = arg->mesg; 00077 return (VALUE)sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), 00078 arg->flags, arg->to, arg->tolen); 00079 } 00080 00081 VALUE 00082 rsock_send_blocking(void *data) 00083 { 00084 struct rsock_send_arg *arg = data; 00085 VALUE mesg = arg->mesg; 00086 return (VALUE)send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), 00087 arg->flags); 00088 } 00089 00090 struct recvfrom_arg { 00091 int fd, flags; 00092 VALUE str; 00093 socklen_t alen; 00094 struct sockaddr_storage buf; 00095 }; 00096 00097 static VALUE 00098 recvfrom_blocking(void *data) 00099 { 00100 struct recvfrom_arg *arg = data; 00101 return (VALUE)recvfrom(arg->fd, RSTRING_PTR(arg->str), RSTRING_LEN(arg->str), 00102 arg->flags, (struct sockaddr*)&arg->buf, &arg->alen); 00103 } 00104 00105 VALUE 00106 rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) 00107 { 00108 rb_io_t *fptr; 00109 VALUE str, klass; 00110 struct recvfrom_arg arg; 00111 VALUE len, flg; 00112 long buflen; 00113 long slen; 00114 00115 rb_scan_args(argc, argv, "11", &len, &flg); 00116 00117 if (flg == Qnil) arg.flags = 0; 00118 else arg.flags = NUM2INT(flg); 00119 buflen = NUM2INT(len); 00120 00121 GetOpenFile(sock, fptr); 00122 if (rb_io_read_pending(fptr)) { 00123 rb_raise(rb_eIOError, "recv for buffered IO"); 00124 } 00125 arg.fd = fptr->fd; 00126 arg.alen = (socklen_t)sizeof(arg.buf); 00127 00128 arg.str = str = rb_tainted_str_new(0, buflen); 00129 klass = RBASIC(str)->klass; 00130 RBASIC(str)->klass = 0; 00131 00132 while (rb_io_check_closed(fptr), 00133 rb_thread_wait_fd(arg.fd), 00134 (slen = BLOCKING_REGION_FD(recvfrom_blocking, &arg)) < 0) { 00135 if (!rb_io_wait_readable(fptr->fd)) { 00136 rb_sys_fail("recvfrom(2)"); 00137 } 00138 if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) { 00139 rb_raise(rb_eRuntimeError, "buffer string modified"); 00140 } 00141 } 00142 00143 RBASIC(str)->klass = klass; 00144 if (slen < RSTRING_LEN(str)) { 00145 rb_str_set_len(str, slen); 00146 } 00147 rb_obj_taint(str); 00148 switch (from) { 00149 case RECV_RECV: 00150 return str; 00151 case RECV_IP: 00152 #if 0 00153 if (arg.alen != sizeof(struct sockaddr_in)) { 00154 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); 00155 } 00156 #endif 00157 if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */ 00158 return rb_assoc_new(str, rsock_ipaddr((struct sockaddr*)&arg.buf, fptr->mode & FMODE_NOREVLOOKUP)); 00159 else 00160 return rb_assoc_new(str, Qnil); 00161 00162 #ifdef HAVE_SYS_UN_H 00163 case RECV_UNIX: 00164 return rb_assoc_new(str, rsock_unixaddr((struct sockaddr_un*)&arg.buf, arg.alen)); 00165 #endif 00166 case RECV_SOCKET: 00167 return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, (struct sockaddr*)&arg.buf, arg.alen)); 00168 default: 00169 rb_bug("rsock_s_recvfrom called with bad value"); 00170 } 00171 } 00172 00173 VALUE 00174 rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) 00175 { 00176 rb_io_t *fptr; 00177 VALUE str; 00178 struct sockaddr_storage buf; 00179 socklen_t alen = (socklen_t)sizeof buf; 00180 VALUE len, flg; 00181 long buflen; 00182 long slen; 00183 int fd, flags; 00184 VALUE addr = Qnil; 00185 00186 rb_scan_args(argc, argv, "11", &len, &flg); 00187 00188 if (flg == Qnil) flags = 0; 00189 else flags = NUM2INT(flg); 00190 buflen = NUM2INT(len); 00191 00192 #ifdef MSG_DONTWAIT 00193 /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom. 00194 It is not portable, though. */ 00195 flags |= MSG_DONTWAIT; 00196 #endif 00197 00198 GetOpenFile(sock, fptr); 00199 if (rb_io_read_pending(fptr)) { 00200 rb_raise(rb_eIOError, "recvfrom for buffered IO"); 00201 } 00202 fd = fptr->fd; 00203 00204 str = rb_tainted_str_new(0, buflen); 00205 00206 rb_io_check_closed(fptr); 00207 rb_io_set_nonblock(fptr); 00208 slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, (struct sockaddr*)&buf, &alen); 00209 00210 if (slen < 0) { 00211 switch (errno) { 00212 case EAGAIN: 00213 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 00214 case EWOULDBLOCK: 00215 #endif 00216 rb_mod_sys_fail(rb_mWaitReadable, "recvfrom(2) would block"); 00217 } 00218 rb_sys_fail("recvfrom(2)"); 00219 } 00220 if (slen < RSTRING_LEN(str)) { 00221 rb_str_set_len(str, slen); 00222 } 00223 rb_obj_taint(str); 00224 switch (from) { 00225 case RECV_RECV: 00226 return str; 00227 00228 case RECV_IP: 00229 if (alen && alen != sizeof(buf)) /* connection-oriented socket may not return a from result */ 00230 addr = rsock_ipaddr((struct sockaddr*)&buf, fptr->mode & FMODE_NOREVLOOKUP); 00231 break; 00232 00233 case RECV_SOCKET: 00234 addr = rsock_io_socket_addrinfo(sock, (struct sockaddr*)&buf, alen); 00235 break; 00236 00237 default: 00238 rb_bug("rsock_s_recvfrom_nonblock called with bad value"); 00239 } 00240 return rb_assoc_new(str, addr); 00241 } 00242 00243 static int 00244 rsock_socket0(int domain, int type, int proto) 00245 { 00246 int ret; 00247 00248 #ifdef SOCK_CLOEXEC 00249 static int try_sock_cloexec = 1; 00250 if (try_sock_cloexec) { 00251 ret = socket(domain, type|SOCK_CLOEXEC, proto); 00252 if (ret == -1 && errno == EINVAL) { 00253 /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */ 00254 ret = socket(domain, type, proto); 00255 if (ret != -1) { 00256 try_sock_cloexec = 0; 00257 } 00258 } 00259 } 00260 else { 00261 ret = socket(domain, type, proto); 00262 } 00263 #else 00264 ret = socket(domain, type, proto); 00265 #endif 00266 if (ret == -1) 00267 return -1; 00268 00269 rb_fd_fix_cloexec(ret); 00270 00271 return ret; 00272 00273 } 00274 00275 int 00276 rsock_socket(int domain, int type, int proto) 00277 { 00278 int fd; 00279 00280 fd = rsock_socket0(domain, type, proto); 00281 if (fd < 0) { 00282 if (errno == EMFILE || errno == ENFILE) { 00283 rb_gc(); 00284 fd = rsock_socket0(domain, type, proto); 00285 } 00286 } 00287 if (0 <= fd) 00288 rb_update_max_fd(fd); 00289 return fd; 00290 } 00291 00292 static int 00293 wait_connectable(int fd) 00294 { 00295 int sockerr; 00296 socklen_t sockerrlen; 00297 int revents; 00298 int ret; 00299 00300 for (;;) { 00301 /* 00302 * Stevens book says, succuessful finish turn on RB_WAITFD_OUT and 00303 * failure finish turn on both RB_WAITFD_IN and RB_WAITFD_OUT. 00304 */ 00305 revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL); 00306 00307 if (revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) { 00308 sockerrlen = (socklen_t)sizeof(sockerr); 00309 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); 00310 00311 /* 00312 * Solaris getsockopt(SO_ERROR) return -1 and set errno 00313 * in getsockopt(). Let's return immediately. 00314 */ 00315 if (ret < 0) 00316 break; 00317 if (sockerr == 0) 00318 continue; /* workaround for winsock */ 00319 00320 /* BSD and Linux use sockerr. */ 00321 errno = sockerr; 00322 ret = -1; 00323 break; 00324 } 00325 00326 if ((revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) == RB_WAITFD_OUT) { 00327 ret = 0; 00328 break; 00329 } 00330 } 00331 00332 return ret; 00333 } 00334 00335 #ifdef __CYGWIN__ 00336 #define WAIT_IN_PROGRESS 10 00337 #endif 00338 #ifdef __APPLE__ 00339 #define WAIT_IN_PROGRESS 10 00340 #endif 00341 #ifdef __linux__ 00342 /* returns correct error */ 00343 #define WAIT_IN_PROGRESS 0 00344 #endif 00345 #ifndef WAIT_IN_PROGRESS 00346 /* BSD origin code apparently has a problem */ 00347 #define WAIT_IN_PROGRESS 1 00348 #endif 00349 00350 struct connect_arg { 00351 int fd; 00352 const struct sockaddr *sockaddr; 00353 socklen_t len; 00354 }; 00355 00356 static VALUE 00357 connect_blocking(void *data) 00358 { 00359 struct connect_arg *arg = data; 00360 return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); 00361 } 00362 00363 #if defined(SOCKS) && !defined(SOCKS5) 00364 static VALUE 00365 socks_connect_blocking(void *data) 00366 { 00367 struct connect_arg *arg = data; 00368 return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len); 00369 } 00370 #endif 00371 00372 int 00373 rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) 00374 { 00375 int status; 00376 rb_blocking_function_t *func = connect_blocking; 00377 struct connect_arg arg; 00378 #if WAIT_IN_PROGRESS > 0 00379 int wait_in_progress = -1; 00380 int sockerr; 00381 socklen_t sockerrlen; 00382 #endif 00383 00384 arg.fd = fd; 00385 arg.sockaddr = sockaddr; 00386 arg.len = len; 00387 #if defined(SOCKS) && !defined(SOCKS5) 00388 if (socks) func = socks_connect_blocking; 00389 #endif 00390 for (;;) { 00391 status = (int)BLOCKING_REGION_FD(func, &arg); 00392 if (status < 0) { 00393 switch (errno) { 00394 case EINTR: 00395 #if defined(ERESTART) 00396 case ERESTART: 00397 #endif 00398 continue; 00399 00400 case EAGAIN: 00401 #ifdef EINPROGRESS 00402 case EINPROGRESS: 00403 #endif 00404 #if WAIT_IN_PROGRESS > 0 00405 sockerrlen = (socklen_t)sizeof(sockerr); 00406 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); 00407 if (status) break; 00408 if (sockerr) { 00409 status = -1; 00410 errno = sockerr; 00411 break; 00412 } 00413 #endif 00414 #ifdef EALREADY 00415 case EALREADY: 00416 #endif 00417 #if WAIT_IN_PROGRESS > 0 00418 wait_in_progress = WAIT_IN_PROGRESS; 00419 #endif 00420 status = wait_connectable(fd); 00421 if (status) { 00422 break; 00423 } 00424 errno = 0; 00425 continue; 00426 00427 #if WAIT_IN_PROGRESS > 0 00428 case EINVAL: 00429 if (wait_in_progress-- > 0) { 00430 /* 00431 * connect() after EINPROGRESS returns EINVAL on 00432 * some platforms, need to check true error 00433 * status. 00434 */ 00435 sockerrlen = (socklen_t)sizeof(sockerr); 00436 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); 00437 if (!status && !sockerr) { 00438 struct timeval tv = {0, 100000}; 00439 rb_thread_wait_for(tv); 00440 continue; 00441 } 00442 status = -1; 00443 errno = sockerr; 00444 } 00445 break; 00446 #endif 00447 00448 #ifdef EISCONN 00449 case EISCONN: 00450 status = 0; 00451 errno = 0; 00452 break; 00453 #endif 00454 default: 00455 break; 00456 } 00457 } 00458 return status; 00459 } 00460 } 00461 00462 static void 00463 make_fd_nonblock(int fd) 00464 { 00465 int flags; 00466 #ifdef F_GETFL 00467 flags = fcntl(fd, F_GETFL); 00468 if (flags == -1) { 00469 rb_sys_fail(0); 00470 } 00471 #else 00472 flags = 0; 00473 #endif 00474 flags |= O_NONBLOCK; 00475 if (fcntl(fd, F_SETFL, flags) == -1) { 00476 rb_sys_fail(0); 00477 } 00478 } 00479 00480 static int 00481 cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len) 00482 { 00483 int ret; 00484 socklen_t len0 = 0; 00485 #ifdef HAVE_ACCEPT4 00486 static int try_accept4 = 1; 00487 #endif 00488 if (address_len) len0 = *address_len; 00489 #ifdef HAVE_ACCEPT4 00490 if (try_accept4) { 00491 ret = accept4(socket, address, address_len, SOCK_CLOEXEC); 00492 /* accept4 is available since Linux 2.6.28, glibc 2.10. */ 00493 if (ret != -1) { 00494 if (ret <= 2) 00495 rb_maygvl_fd_fix_cloexec(ret); 00496 if (address_len && len0 < *address_len) *address_len = len0; 00497 return ret; 00498 } 00499 if (errno != ENOSYS) { 00500 return -1; 00501 } 00502 try_accept4 = 0; 00503 } 00504 #endif 00505 ret = accept(socket, address, address_len); 00506 if (ret == -1) return -1; 00507 if (address_len && len0 < *address_len) *address_len = len0; 00508 rb_maygvl_fd_fix_cloexec(ret); 00509 return ret; 00510 } 00511 00512 00513 VALUE 00514 rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len) 00515 { 00516 int fd2; 00517 00518 rb_secure(3); 00519 rb_io_set_nonblock(fptr); 00520 fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len); 00521 if (fd2 < 0) { 00522 switch (errno) { 00523 case EAGAIN: 00524 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 00525 case EWOULDBLOCK: 00526 #endif 00527 case ECONNABORTED: 00528 #if defined EPROTO 00529 case EPROTO: 00530 #endif 00531 rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block"); 00532 } 00533 rb_sys_fail("accept(2)"); 00534 } 00535 rb_update_max_fd(fd2); 00536 make_fd_nonblock(fd2); 00537 return rsock_init_sock(rb_obj_alloc(klass), fd2); 00538 } 00539 00540 struct accept_arg { 00541 int fd; 00542 struct sockaddr *sockaddr; 00543 socklen_t *len; 00544 }; 00545 00546 static VALUE 00547 accept_blocking(void *data) 00548 { 00549 struct accept_arg *arg = data; 00550 return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len); 00551 } 00552 00553 VALUE 00554 rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) 00555 { 00556 int fd2; 00557 int retry = 0; 00558 struct accept_arg arg; 00559 00560 rb_secure(3); 00561 arg.fd = fd; 00562 arg.sockaddr = sockaddr; 00563 arg.len = len; 00564 retry: 00565 rb_thread_wait_fd(fd); 00566 fd2 = (int)BLOCKING_REGION_FD(accept_blocking, &arg); 00567 if (fd2 < 0) { 00568 switch (errno) { 00569 case EMFILE: 00570 case ENFILE: 00571 if (retry) break; 00572 rb_gc(); 00573 retry = 1; 00574 goto retry; 00575 default: 00576 if (!rb_io_wait_readable(fd)) break; 00577 retry = 0; 00578 goto retry; 00579 } 00580 rb_sys_fail(0); 00581 } 00582 rb_update_max_fd(fd2); 00583 if (!klass) return INT2NUM(fd2); 00584 return rsock_init_sock(rb_obj_alloc(klass), fd2); 00585 } 00586 00587 int 00588 rsock_getfamily(int sockfd) 00589 { 00590 struct sockaddr_storage ss; 00591 socklen_t sslen = (socklen_t)sizeof(ss); 00592 00593 ss.ss_family = AF_UNSPEC; 00594 if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0) 00595 return AF_UNSPEC; 00596 00597 return ss.ss_family; 00598 } 00599 00600 void 00601 rsock_init_socket_init() 00602 { 00603 /* 00604 * SocketError is the error class for socket. 00605 */ 00606 rb_eSocket = rb_define_class("SocketError", rb_eStandardError); 00607 rsock_init_ipsocket(); 00608 rsock_init_tcpsocket(); 00609 rsock_init_tcpserver(); 00610 rsock_init_sockssocket(); 00611 rsock_init_udpsocket(); 00612 rsock_init_unixsocket(); 00613 rsock_init_unixserver(); 00614 rsock_init_sockopt(); 00615 rsock_init_ancdata(); 00616 rsock_init_addrinfo(); 00617 rsock_init_socket_constants(); 00618 } 00619