|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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 struct stat sbuf; 00047 00048 #ifndef _WIN32 00049 if (fstat(fd, &sbuf) < 0) 00050 rb_sys_fail(0); 00051 if (!S_ISSOCK(sbuf.st_mode)) 00052 rb_raise(rb_eArgError, "not a socket file descriptor"); 00053 #else 00054 if (!rb_w32_is_socket(fd)) 00055 rb_raise(rb_eArgError, "not a socket file descriptor"); 00056 #endif 00057 00058 MakeOpenFile(sock, fp); 00059 fp->fd = fd; 00060 fp->mode = FMODE_READWRITE|FMODE_DUPLEX; 00061 rb_io_ascii8bit_binmode(sock); 00062 if (rsock_do_not_reverse_lookup) { 00063 fp->mode |= FMODE_NOREVLOOKUP; 00064 } 00065 rb_io_synchronized(fp); 00066 00067 return sock; 00068 } 00069 00070 VALUE 00071 rsock_sendto_blocking(void *data) 00072 { 00073 struct rsock_send_arg *arg = data; 00074 VALUE mesg = arg->mesg; 00075 return (VALUE)sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), 00076 arg->flags, arg->to, arg->tolen); 00077 } 00078 00079 VALUE 00080 rsock_send_blocking(void *data) 00081 { 00082 struct rsock_send_arg *arg = data; 00083 VALUE mesg = arg->mesg; 00084 return (VALUE)send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), 00085 arg->flags); 00086 } 00087 00088 struct recvfrom_arg { 00089 int fd, flags; 00090 VALUE str; 00091 socklen_t alen; 00092 struct sockaddr_storage buf; 00093 }; 00094 00095 static VALUE 00096 recvfrom_blocking(void *data) 00097 { 00098 struct recvfrom_arg *arg = data; 00099 return (VALUE)recvfrom(arg->fd, RSTRING_PTR(arg->str), RSTRING_LEN(arg->str), 00100 arg->flags, (struct sockaddr*)&arg->buf, &arg->alen); 00101 } 00102 00103 VALUE 00104 rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) 00105 { 00106 rb_io_t *fptr; 00107 VALUE str, klass; 00108 struct recvfrom_arg arg; 00109 VALUE len, flg; 00110 long buflen; 00111 long slen; 00112 00113 rb_scan_args(argc, argv, "11", &len, &flg); 00114 00115 if (flg == Qnil) arg.flags = 0; 00116 else arg.flags = NUM2INT(flg); 00117 buflen = NUM2INT(len); 00118 00119 GetOpenFile(sock, fptr); 00120 if (rb_io_read_pending(fptr)) { 00121 rb_raise(rb_eIOError, "recv for buffered IO"); 00122 } 00123 arg.fd = fptr->fd; 00124 arg.alen = (socklen_t)sizeof(arg.buf); 00125 00126 arg.str = str = rb_tainted_str_new(0, buflen); 00127 klass = RBASIC(str)->klass; 00128 RBASIC(str)->klass = 0; 00129 00130 while (rb_io_check_closed(fptr), 00131 rb_thread_wait_fd(arg.fd), 00132 (slen = BLOCKING_REGION(recvfrom_blocking, &arg)) < 0) { 00133 if (!rb_io_wait_readable(fptr->fd)) { 00134 rb_sys_fail("recvfrom(2)"); 00135 } 00136 if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) { 00137 rb_raise(rb_eRuntimeError, "buffer string modified"); 00138 } 00139 } 00140 00141 RBASIC(str)->klass = klass; 00142 if (slen < RSTRING_LEN(str)) { 00143 rb_str_set_len(str, slen); 00144 } 00145 rb_obj_taint(str); 00146 switch (from) { 00147 case RECV_RECV: 00148 return str; 00149 case RECV_IP: 00150 #if 0 00151 if (arg.alen != sizeof(struct sockaddr_in)) { 00152 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); 00153 } 00154 #endif 00155 if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */ 00156 return rb_assoc_new(str, rsock_ipaddr((struct sockaddr*)&arg.buf, fptr->mode & FMODE_NOREVLOOKUP)); 00157 else 00158 return rb_assoc_new(str, Qnil); 00159 00160 #ifdef HAVE_SYS_UN_H 00161 case RECV_UNIX: 00162 return rb_assoc_new(str, rsock_unixaddr((struct sockaddr_un*)&arg.buf, arg.alen)); 00163 #endif 00164 case RECV_SOCKET: 00165 return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, (struct sockaddr*)&arg.buf, arg.alen)); 00166 default: 00167 rb_bug("rsock_s_recvfrom called with bad value"); 00168 } 00169 } 00170 00171 VALUE 00172 rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) 00173 { 00174 rb_io_t *fptr; 00175 VALUE str; 00176 struct sockaddr_storage buf; 00177 socklen_t alen = (socklen_t)sizeof buf; 00178 VALUE len, flg; 00179 long buflen; 00180 long slen; 00181 int fd, flags; 00182 VALUE addr = Qnil; 00183 00184 rb_scan_args(argc, argv, "11", &len, &flg); 00185 00186 if (flg == Qnil) flags = 0; 00187 else flags = NUM2INT(flg); 00188 buflen = NUM2INT(len); 00189 00190 #ifdef MSG_DONTWAIT 00191 /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom. 00192 It is not portable, though. */ 00193 flags |= MSG_DONTWAIT; 00194 #endif 00195 00196 GetOpenFile(sock, fptr); 00197 if (rb_io_read_pending(fptr)) { 00198 rb_raise(rb_eIOError, "recvfrom for buffered IO"); 00199 } 00200 fd = fptr->fd; 00201 00202 str = rb_tainted_str_new(0, buflen); 00203 00204 rb_io_check_closed(fptr); 00205 rb_io_set_nonblock(fptr); 00206 slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, (struct sockaddr*)&buf, &alen); 00207 00208 if (slen < 0) { 00209 switch (errno) { 00210 case EAGAIN: 00211 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 00212 case EWOULDBLOCK: 00213 #endif 00214 rb_mod_sys_fail(rb_mWaitReadable, "recvfrom(2) would block"); 00215 } 00216 rb_sys_fail("recvfrom(2)"); 00217 } 00218 if (slen < RSTRING_LEN(str)) { 00219 rb_str_set_len(str, slen); 00220 } 00221 rb_obj_taint(str); 00222 switch (from) { 00223 case RECV_RECV: 00224 return str; 00225 00226 case RECV_IP: 00227 if (alen && alen != sizeof(buf)) /* connection-oriented socket may not return a from result */ 00228 addr = rsock_ipaddr((struct sockaddr*)&buf, fptr->mode & FMODE_NOREVLOOKUP); 00229 break; 00230 00231 case RECV_SOCKET: 00232 addr = rsock_io_socket_addrinfo(sock, (struct sockaddr*)&buf, alen); 00233 break; 00234 00235 default: 00236 rb_bug("rsock_s_recvfrom_nonblock called with bad value"); 00237 } 00238 return rb_assoc_new(str, addr); 00239 } 00240 00241 int 00242 rsock_socket(int domain, int type, int proto) 00243 { 00244 int fd; 00245 00246 fd = socket(domain, type, proto); 00247 if (fd < 0) { 00248 if (errno == EMFILE || errno == ENFILE) { 00249 rb_gc(); 00250 fd = socket(domain, type, proto); 00251 } 00252 } 00253 return fd; 00254 } 00255 00256 static int 00257 wait_connectable0(int fd, rb_fdset_t *fds_w, rb_fdset_t *fds_e) 00258 { 00259 int sockerr; 00260 socklen_t sockerrlen; 00261 00262 for (;;) { 00263 rb_fd_zero(fds_w); 00264 rb_fd_zero(fds_e); 00265 00266 rb_fd_set(fd, fds_w); 00267 rb_fd_set(fd, fds_e); 00268 00269 rb_thread_select(fd+1, 0, rb_fd_ptr(fds_w), rb_fd_ptr(fds_e), 0); 00270 00271 if (rb_fd_isset(fd, fds_w)) { 00272 return 0; 00273 } 00274 else if (rb_fd_isset(fd, fds_e)) { 00275 sockerrlen = (socklen_t)sizeof(sockerr); 00276 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, 00277 &sockerrlen) == 0) { 00278 if (sockerr == 0) 00279 continue; /* workaround for winsock */ 00280 errno = sockerr; 00281 } 00282 return -1; 00283 } 00284 } 00285 } 00286 00287 struct wait_connectable_arg { 00288 int fd; 00289 rb_fdset_t fds_w; 00290 rb_fdset_t fds_e; 00291 }; 00292 00293 #ifdef HAVE_RB_FD_INIT 00294 static VALUE 00295 try_wait_connectable(VALUE arg) 00296 { 00297 struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg; 00298 return (VALUE)wait_connectable0(p->fd, &p->fds_w, &p->fds_e); 00299 } 00300 00301 static VALUE 00302 wait_connectable_ensure(VALUE arg) 00303 { 00304 struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg; 00305 rb_fd_term(&p->fds_w); 00306 rb_fd_term(&p->fds_e); 00307 return Qnil; 00308 } 00309 #endif 00310 00311 static int 00312 wait_connectable(int fd) 00313 { 00314 struct wait_connectable_arg arg; 00315 00316 rb_fd_init(&arg.fds_w); 00317 rb_fd_init(&arg.fds_e); 00318 #ifdef HAVE_RB_FD_INIT 00319 arg.fd = fd; 00320 return (int)rb_ensure(try_wait_connectable, (VALUE)&arg, 00321 wait_connectable_ensure,(VALUE)&arg); 00322 #else 00323 return wait_connectable0(fd, &arg.fds_w, &arg.fds_e); 00324 #endif 00325 } 00326 00327 #ifdef __CYGWIN__ 00328 #define WAIT_IN_PROGRESS 10 00329 #endif 00330 #ifdef __APPLE__ 00331 #define WAIT_IN_PROGRESS 10 00332 #endif 00333 #ifdef __linux__ 00334 /* returns correct error */ 00335 #define WAIT_IN_PROGRESS 0 00336 #endif 00337 #ifndef WAIT_IN_PROGRESS 00338 /* BSD origin code apparently has a problem */ 00339 #define WAIT_IN_PROGRESS 1 00340 #endif 00341 00342 struct connect_arg { 00343 int fd; 00344 const struct sockaddr *sockaddr; 00345 socklen_t len; 00346 }; 00347 00348 static VALUE 00349 connect_blocking(void *data) 00350 { 00351 struct connect_arg *arg = data; 00352 return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); 00353 } 00354 00355 #if defined(SOCKS) && !defined(SOCKS5) 00356 static VALUE 00357 socks_connect_blocking(void *data) 00358 { 00359 struct connect_arg *arg = data; 00360 return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len); 00361 } 00362 #endif 00363 00364 int 00365 rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) 00366 { 00367 int status; 00368 rb_blocking_function_t *func = connect_blocking; 00369 struct connect_arg arg; 00370 #if WAIT_IN_PROGRESS > 0 00371 int wait_in_progress = -1; 00372 int sockerr; 00373 socklen_t sockerrlen; 00374 #endif 00375 00376 arg.fd = fd; 00377 arg.sockaddr = sockaddr; 00378 arg.len = len; 00379 #if defined(SOCKS) && !defined(SOCKS5) 00380 if (socks) func = socks_connect_blocking; 00381 #endif 00382 for (;;) { 00383 status = (int)BLOCKING_REGION(func, &arg); 00384 if (status < 0) { 00385 switch (errno) { 00386 case EINTR: 00387 #if defined(ERESTART) 00388 case ERESTART: 00389 #endif 00390 continue; 00391 00392 case EAGAIN: 00393 #ifdef EINPROGRESS 00394 case EINPROGRESS: 00395 #endif 00396 #if WAIT_IN_PROGRESS > 0 00397 sockerrlen = (socklen_t)sizeof(sockerr); 00398 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); 00399 if (status) break; 00400 if (sockerr) { 00401 status = -1; 00402 errno = sockerr; 00403 break; 00404 } 00405 #endif 00406 #ifdef EALREADY 00407 case EALREADY: 00408 #endif 00409 #if WAIT_IN_PROGRESS > 0 00410 wait_in_progress = WAIT_IN_PROGRESS; 00411 #endif 00412 status = wait_connectable(fd); 00413 if (status) { 00414 break; 00415 } 00416 errno = 0; 00417 continue; 00418 00419 #if WAIT_IN_PROGRESS > 0 00420 case EINVAL: 00421 if (wait_in_progress-- > 0) { 00422 /* 00423 * connect() after EINPROGRESS returns EINVAL on 00424 * some platforms, need to check true error 00425 * status. 00426 */ 00427 sockerrlen = (socklen_t)sizeof(sockerr); 00428 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); 00429 if (!status && !sockerr) { 00430 struct timeval tv = {0, 100000}; 00431 rb_thread_wait_for(tv); 00432 continue; 00433 } 00434 status = -1; 00435 errno = sockerr; 00436 } 00437 break; 00438 #endif 00439 00440 #ifdef EISCONN 00441 case EISCONN: 00442 status = 0; 00443 errno = 0; 00444 break; 00445 #endif 00446 default: 00447 break; 00448 } 00449 } 00450 return status; 00451 } 00452 } 00453 00454 static void 00455 make_fd_nonblock(int fd) 00456 { 00457 int flags; 00458 #ifdef F_GETFL 00459 flags = fcntl(fd, F_GETFL); 00460 if (flags == -1) { 00461 rb_sys_fail(0); 00462 } 00463 #else 00464 flags = 0; 00465 #endif 00466 flags |= O_NONBLOCK; 00467 if (fcntl(fd, F_SETFL, flags) == -1) { 00468 rb_sys_fail(0); 00469 } 00470 } 00471 00472 VALUE 00473 rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len) 00474 { 00475 int fd2; 00476 00477 rb_secure(3); 00478 rb_io_set_nonblock(fptr); 00479 fd2 = accept(fptr->fd, (struct sockaddr*)sockaddr, len); 00480 if (fd2 < 0) { 00481 switch (errno) { 00482 case EAGAIN: 00483 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 00484 case EWOULDBLOCK: 00485 #endif 00486 case ECONNABORTED: 00487 #if defined EPROTO 00488 case EPROTO: 00489 #endif 00490 rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block"); 00491 } 00492 rb_sys_fail("accept(2)"); 00493 } 00494 make_fd_nonblock(fd2); 00495 return rsock_init_sock(rb_obj_alloc(klass), fd2); 00496 } 00497 00498 struct accept_arg { 00499 int fd; 00500 struct sockaddr *sockaddr; 00501 socklen_t *len; 00502 }; 00503 00504 static VALUE 00505 accept_blocking(void *data) 00506 { 00507 struct accept_arg *arg = data; 00508 return (VALUE)accept(arg->fd, arg->sockaddr, arg->len); 00509 } 00510 00511 VALUE 00512 rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) 00513 { 00514 int fd2; 00515 int retry = 0; 00516 struct accept_arg arg; 00517 00518 rb_secure(3); 00519 arg.fd = fd; 00520 arg.sockaddr = sockaddr; 00521 arg.len = len; 00522 retry: 00523 rb_thread_wait_fd(fd); 00524 fd2 = (int)BLOCKING_REGION(accept_blocking, &arg); 00525 if (fd2 < 0) { 00526 switch (errno) { 00527 case EMFILE: 00528 case ENFILE: 00529 if (retry) break; 00530 rb_gc(); 00531 retry = 1; 00532 goto retry; 00533 default: 00534 if (!rb_io_wait_readable(fd)) break; 00535 retry = 0; 00536 goto retry; 00537 } 00538 rb_sys_fail(0); 00539 } 00540 if (!klass) return INT2NUM(fd2); 00541 return rsock_init_sock(rb_obj_alloc(klass), fd2); 00542 } 00543 00544 int 00545 rsock_getfamily(int sockfd) 00546 { 00547 struct sockaddr_storage ss; 00548 socklen_t sslen = (socklen_t)sizeof(ss); 00549 00550 ss.ss_family = AF_UNSPEC; 00551 if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0) 00552 return AF_UNSPEC; 00553 00554 return ss.ss_family; 00555 } 00556 00557 /* 00558 * SocketError is the error class for socket. 00559 */ 00560 void 00561 rsock_init_socket_init() 00562 { 00563 rb_eSocket = rb_define_class("SocketError", rb_eStandardError); 00564 rsock_init_ipsocket(); 00565 rsock_init_tcpsocket(); 00566 rsock_init_tcpserver(); 00567 rsock_init_sockssocket(); 00568 rsock_init_udpsocket(); 00569 rsock_init_unixsocket(); 00570 rsock_init_unixserver(); 00571 rsock_init_sockopt(); 00572 rsock_init_ancdata(); 00573 rsock_init_addrinfo(); 00574 rsock_init_socket_constants(); 00575 } 00576
1.7.3