|
Ruby
2.0.0p481(2014-05-08revision45883)
|
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 if (revents & RB_WAITFD_OUT) 00319 break; 00320 else 00321 continue; /* workaround for winsock */ 00322 } 00323 00324 /* BSD and Linux use sockerr. */ 00325 errno = sockerr; 00326 ret = -1; 00327 break; 00328 } 00329 00330 if ((revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) == RB_WAITFD_OUT) { 00331 ret = 0; 00332 break; 00333 } 00334 } 00335 00336 return ret; 00337 } 00338 00339 #ifdef __CYGWIN__ 00340 #define WAIT_IN_PROGRESS 10 00341 #endif 00342 #ifdef __APPLE__ 00343 #define WAIT_IN_PROGRESS 10 00344 #endif 00345 #ifdef __linux__ 00346 /* returns correct error */ 00347 #define WAIT_IN_PROGRESS 0 00348 #endif 00349 #ifndef WAIT_IN_PROGRESS 00350 /* BSD origin code apparently has a problem */ 00351 #define WAIT_IN_PROGRESS 1 00352 #endif 00353 00354 struct connect_arg { 00355 int fd; 00356 const struct sockaddr *sockaddr; 00357 socklen_t len; 00358 }; 00359 00360 static VALUE 00361 connect_blocking(void *data) 00362 { 00363 struct connect_arg *arg = data; 00364 return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); 00365 } 00366 00367 #if defined(SOCKS) && !defined(SOCKS5) 00368 static VALUE 00369 socks_connect_blocking(void *data) 00370 { 00371 struct connect_arg *arg = data; 00372 return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len); 00373 } 00374 #endif 00375 00376 int 00377 rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) 00378 { 00379 int status; 00380 rb_blocking_function_t *func = connect_blocking; 00381 struct connect_arg arg; 00382 #if WAIT_IN_PROGRESS > 0 00383 int wait_in_progress = -1; 00384 int sockerr; 00385 socklen_t sockerrlen; 00386 #endif 00387 00388 arg.fd = fd; 00389 arg.sockaddr = sockaddr; 00390 arg.len = len; 00391 #if defined(SOCKS) && !defined(SOCKS5) 00392 if (socks) func = socks_connect_blocking; 00393 #endif 00394 for (;;) { 00395 status = (int)BLOCKING_REGION_FD(func, &arg); 00396 if (status < 0) { 00397 switch (errno) { 00398 case EINTR: 00399 #if defined(ERESTART) 00400 case ERESTART: 00401 #endif 00402 continue; 00403 00404 case EAGAIN: 00405 #ifdef EINPROGRESS 00406 case EINPROGRESS: 00407 #endif 00408 #if WAIT_IN_PROGRESS > 0 00409 sockerrlen = (socklen_t)sizeof(sockerr); 00410 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); 00411 if (status) break; 00412 if (sockerr) { 00413 status = -1; 00414 errno = sockerr; 00415 break; 00416 } 00417 #endif 00418 #ifdef EALREADY 00419 case EALREADY: 00420 #endif 00421 #if WAIT_IN_PROGRESS > 0 00422 wait_in_progress = WAIT_IN_PROGRESS; 00423 #endif 00424 status = wait_connectable(fd); 00425 if (status) { 00426 break; 00427 } 00428 errno = 0; 00429 continue; 00430 00431 #if WAIT_IN_PROGRESS > 0 00432 case EINVAL: 00433 if (wait_in_progress-- > 0) { 00434 /* 00435 * connect() after EINPROGRESS returns EINVAL on 00436 * some platforms, need to check true error 00437 * status. 00438 */ 00439 sockerrlen = (socklen_t)sizeof(sockerr); 00440 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); 00441 if (!status && !sockerr) { 00442 struct timeval tv = {0, 100000}; 00443 rb_thread_wait_for(tv); 00444 continue; 00445 } 00446 status = -1; 00447 errno = sockerr; 00448 } 00449 break; 00450 #endif 00451 00452 #ifdef EISCONN 00453 case EISCONN: 00454 status = 0; 00455 errno = 0; 00456 break; 00457 #endif 00458 default: 00459 break; 00460 } 00461 } 00462 return status; 00463 } 00464 } 00465 00466 static void 00467 make_fd_nonblock(int fd) 00468 { 00469 int flags; 00470 #ifdef F_GETFL 00471 flags = fcntl(fd, F_GETFL); 00472 if (flags == -1) { 00473 rb_sys_fail(0); 00474 } 00475 #else 00476 flags = 0; 00477 #endif 00478 flags |= O_NONBLOCK; 00479 if (fcntl(fd, F_SETFL, flags) == -1) { 00480 rb_sys_fail(0); 00481 } 00482 } 00483 00484 static int 00485 cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len) 00486 { 00487 int ret; 00488 socklen_t len0 = 0; 00489 #ifdef HAVE_ACCEPT4 00490 static int try_accept4 = 1; 00491 #endif 00492 if (address_len) len0 = *address_len; 00493 #ifdef HAVE_ACCEPT4 00494 if (try_accept4) { 00495 int flags = 0; 00496 #ifdef SOCK_CLOEXEC 00497 flags |= SOCK_CLOEXEC; 00498 #endif 00499 ret = accept4(socket, address, address_len, flags); 00500 /* accept4 is available since Linux 2.6.28, glibc 2.10. */ 00501 if (ret != -1) { 00502 if (ret <= 2) 00503 rb_maygvl_fd_fix_cloexec(ret); 00504 if (address_len && len0 < *address_len) *address_len = len0; 00505 return ret; 00506 } 00507 if (errno != ENOSYS) { 00508 return -1; 00509 } 00510 try_accept4 = 0; 00511 } 00512 #endif 00513 ret = accept(socket, address, address_len); 00514 if (ret == -1) return -1; 00515 if (address_len && len0 < *address_len) *address_len = len0; 00516 rb_maygvl_fd_fix_cloexec(ret); 00517 return ret; 00518 } 00519 00520 00521 VALUE 00522 rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len) 00523 { 00524 int fd2; 00525 00526 rb_secure(3); 00527 rb_io_set_nonblock(fptr); 00528 fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len); 00529 if (fd2 < 0) { 00530 switch (errno) { 00531 case EAGAIN: 00532 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 00533 case EWOULDBLOCK: 00534 #endif 00535 case ECONNABORTED: 00536 #if defined EPROTO 00537 case EPROTO: 00538 #endif 00539 rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block"); 00540 } 00541 rb_sys_fail("accept(2)"); 00542 } 00543 rb_update_max_fd(fd2); 00544 make_fd_nonblock(fd2); 00545 return rsock_init_sock(rb_obj_alloc(klass), fd2); 00546 } 00547 00548 struct accept_arg { 00549 int fd; 00550 struct sockaddr *sockaddr; 00551 socklen_t *len; 00552 }; 00553 00554 static VALUE 00555 accept_blocking(void *data) 00556 { 00557 struct accept_arg *arg = data; 00558 return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len); 00559 } 00560 00561 VALUE 00562 rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) 00563 { 00564 int fd2; 00565 int retry = 0; 00566 struct accept_arg arg; 00567 00568 rb_secure(3); 00569 arg.fd = fd; 00570 arg.sockaddr = sockaddr; 00571 arg.len = len; 00572 retry: 00573 rb_thread_wait_fd(fd); 00574 fd2 = (int)BLOCKING_REGION_FD(accept_blocking, &arg); 00575 if (fd2 < 0) { 00576 switch (errno) { 00577 case EMFILE: 00578 case ENFILE: 00579 if (retry) break; 00580 rb_gc(); 00581 retry = 1; 00582 goto retry; 00583 default: 00584 if (!rb_io_wait_readable(fd)) break; 00585 retry = 0; 00586 goto retry; 00587 } 00588 rb_sys_fail(0); 00589 } 00590 rb_update_max_fd(fd2); 00591 if (!klass) return INT2NUM(fd2); 00592 return rsock_init_sock(rb_obj_alloc(klass), fd2); 00593 } 00594 00595 int 00596 rsock_getfamily(int sockfd) 00597 { 00598 struct sockaddr_storage ss; 00599 socklen_t sslen = (socklen_t)sizeof(ss); 00600 00601 ss.ss_family = AF_UNSPEC; 00602 if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0) 00603 return AF_UNSPEC; 00604 00605 return ss.ss_family; 00606 } 00607 00608 void 00609 rsock_init_socket_init() 00610 { 00611 /* 00612 * SocketError is the error class for socket. 00613 */ 00614 rb_eSocket = rb_define_class("SocketError", rb_eStandardError); 00615 rsock_init_ipsocket(); 00616 rsock_init_tcpsocket(); 00617 rsock_init_tcpserver(); 00618 rsock_init_sockssocket(); 00619 rsock_init_udpsocket(); 00620 rsock_init_unixsocket(); 00621 rsock_init_unixserver(); 00622 rsock_init_sockopt(); 00623 rsock_init_ancdata(); 00624 rsock_init_addrinfo(); 00625 rsock_init_socket_constants(); 00626 } 00627
1.7.6.1