Ruby  2.0.0p247(2013-06-27revision41674)
ext/socket/init.c
Go to the documentation of this file.
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