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