Ruby  2.0.0p481(2014-05-08revision45883)
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                 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