Ruby 1.9.3p327(2012-11-10revision37606)
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     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