Ruby  2.0.0p247(2013-06-27revision41674)
ext/socket/basicsocket.c
Go to the documentation of this file.
00001 /************************************************
00002 
00003   basicsocket.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 /*
00014  * call-seq:
00015  *   BasicSocket.for_fd(fd) => basicsocket
00016  *
00017  * Returns a socket object which contains the file descriptor, _fd_.
00018  *
00019  *   # If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
00020  *   STDIN_SOCK = Socket.for_fd(STDIN.fileno)
00021  *   p STDIN_SOCK.remote_address
00022  *
00023  */
00024 static VALUE
00025 bsock_s_for_fd(VALUE klass, VALUE fd)
00026 {
00027     rb_io_t *fptr;
00028     VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd));
00029 
00030     GetOpenFile(sock, fptr);
00031 
00032     return sock;
00033 }
00034 
00035 /*
00036  * call-seq:
00037  *   basicsocket.shutdown([how]) => 0
00038  *
00039  * Calls shutdown(2) system call.
00040  *
00041  * s.shutdown(Socket::SHUT_RD) disallows further read.
00042  *
00043  * s.shutdown(Socket::SHUT_WR) disallows further write.
00044  *
00045  * s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
00046  *
00047  * _how_ can be symbol or string:
00048  * - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD.
00049  * - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR.
00050  * - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR.
00051  *
00052  *   UNIXSocket.pair {|s1, s2|
00053  *     s1.puts "ping"
00054  *     s1.shutdown(:WR)
00055  *     p s2.read          #=> "ping\n"
00056  *     s2.puts "pong"
00057  *     s2.close
00058  *     p s1.read          #=> "pong\n"
00059  *   }
00060  *
00061  */
00062 static VALUE
00063 bsock_shutdown(int argc, VALUE *argv, VALUE sock)
00064 {
00065     VALUE howto;
00066     int how;
00067     rb_io_t *fptr;
00068 
00069     if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
00070         rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
00071     }
00072     rb_scan_args(argc, argv, "01", &howto);
00073     if (howto == Qnil)
00074         how = SHUT_RDWR;
00075     else {
00076         how = rsock_shutdown_how_arg(howto);
00077         if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
00078             rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
00079         }
00080     }
00081     GetOpenFile(sock, fptr);
00082     if (shutdown(fptr->fd, how) == -1)
00083         rb_sys_fail(0);
00084 
00085     return INT2FIX(0);
00086 }
00087 
00088 /*
00089  * call-seq:
00090  *   basicsocket.close_read => nil
00091  *
00092  * Disallows further read using shutdown system call.
00093  *
00094  *   s1, s2 = UNIXSocket.pair
00095  *   s1.close_read
00096  *   s2.puts #=> Broken pipe (Errno::EPIPE)
00097  */
00098 static VALUE
00099 bsock_close_read(VALUE sock)
00100 {
00101     rb_io_t *fptr;
00102 
00103     if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
00104         rb_raise(rb_eSecurityError, "Insecure: can't close socket");
00105     }
00106     GetOpenFile(sock, fptr);
00107     shutdown(fptr->fd, 0);
00108     if (!(fptr->mode & FMODE_WRITABLE)) {
00109         return rb_io_close(sock);
00110     }
00111     fptr->mode &= ~FMODE_READABLE;
00112 
00113     return Qnil;
00114 }
00115 
00116 /*
00117  * call-seq:
00118  *   basicsocket.close_write => nil
00119  *
00120  * Disallows further write using shutdown system call.
00121  *
00122  *   UNIXSocket.pair {|s1, s2|
00123  *     s1.print "ping"
00124  *     s1.close_write
00125  *     p s2.read        #=> "ping"
00126  *     s2.print "pong"
00127  *     s2.close
00128  *     p s1.read        #=> "pong"
00129  *   }
00130  */
00131 static VALUE
00132 bsock_close_write(VALUE sock)
00133 {
00134     rb_io_t *fptr;
00135 
00136     if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
00137         rb_raise(rb_eSecurityError, "Insecure: can't close socket");
00138     }
00139     GetOpenFile(sock, fptr);
00140     if (!(fptr->mode & FMODE_READABLE)) {
00141         return rb_io_close(sock);
00142     }
00143     shutdown(fptr->fd, 1);
00144     fptr->mode &= ~FMODE_WRITABLE;
00145 
00146     return Qnil;
00147 }
00148 
00149 /*
00150  * Document-method: setsockopt
00151  * call-seq:
00152  *   setsockopt(level, optname, optval)
00153  *   setsockopt(socketoption)
00154  *
00155  * Sets a socket option. These are protocol and system specific, see your
00156  * local system documentation for details.
00157  *
00158  * === Parameters
00159  * * +level+ is an integer, usually one of the SOL_ constants such as
00160  *   Socket::SOL_SOCKET, or a protocol level.
00161  *   A string or symbol of the name, possibly without prefix, is also
00162  *   accepted.
00163  * * +optname+ is an integer, usually one of the SO_ constants, such
00164  *   as Socket::SO_REUSEADDR.
00165  *   A string or symbol of the name, possibly without prefix, is also
00166  *   accepted.
00167  * * +optval+ is the value of the option, it is passed to the underlying
00168  *   setsockopt() as a pointer to a certain number of bytes. How this is
00169  *   done depends on the type:
00170  *   - Fixnum: value is assigned to an int, and a pointer to the int is
00171  *     passed, with length of sizeof(int).
00172  *   - true or false: 1 or 0 (respectively) is assigned to an int, and the
00173  *     int is passed as for a Fixnum. Note that +false+ must be passed,
00174  *     not +nil+.
00175  *   - String: the string's data and length is passed to the socket.
00176  * * +socketoption+ is an instance of Socket::Option
00177  *
00178  * === Examples
00179  *
00180  * Some socket options are integers with boolean values, in this case
00181  * #setsockopt could be called like this:
00182  *   sock.setsockopt(:SOCKET, :REUSEADDR, true)
00183  *   sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
00184  *   sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
00185  *
00186  * Some socket options are integers with numeric values, in this case
00187  * #setsockopt could be called like this:
00188  *   sock.setsockopt(:IP, :TTL, 255)
00189  *   sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
00190  *   sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
00191  *
00192  * Option values may be structs. Passing them can be complex as it involves
00193  * examining your system headers to determine the correct definition. An
00194  * example is an +ip_mreq+, which may be defined in your system headers as:
00195  *   struct ip_mreq {
00196  *     struct  in_addr imr_multiaddr;
00197  *     struct  in_addr imr_interface;
00198  *   };
00199  *
00200  * In this case #setsockopt could be called like this:
00201  *   optval = IPAddr.new("224.0.0.251").hton +
00202  *            IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton
00203  *   sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
00204  *
00205 */
00206 static VALUE
00207 bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
00208 {
00209     VALUE lev, optname, val;
00210     int family, level, option;
00211     rb_io_t *fptr;
00212     int i;
00213     char *v;
00214     int vlen;
00215 
00216     if (argc == 1) {
00217         lev = rb_funcall(argv[0], rb_intern("level"), 0);
00218         optname = rb_funcall(argv[0], rb_intern("optname"), 0);
00219         val = rb_funcall(argv[0], rb_intern("data"), 0);
00220     }
00221     else {
00222         rb_scan_args(argc, argv, "30", &lev, &optname, &val);
00223     }
00224 
00225     rb_secure(2);
00226     GetOpenFile(sock, fptr);
00227     family = rsock_getfamily(fptr->fd);
00228     level = rsock_level_arg(family, lev);
00229     option = rsock_optname_arg(family, level, optname);
00230 
00231     switch (TYPE(val)) {
00232       case T_FIXNUM:
00233         i = FIX2INT(val);
00234         goto numval;
00235       case T_FALSE:
00236         i = 0;
00237         goto numval;
00238       case T_TRUE:
00239         i = 1;
00240       numval:
00241         v = (char*)&i; vlen = (int)sizeof(i);
00242         break;
00243       default:
00244         StringValue(val);
00245         v = RSTRING_PTR(val);
00246         vlen = RSTRING_LENINT(val);
00247         break;
00248     }
00249 
00250 #define rb_sys_fail_path(path) rb_sys_fail_str(path)
00251 
00252     rb_io_check_closed(fptr);
00253     if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
00254         rb_sys_fail_path(fptr->pathv);
00255 
00256     return INT2FIX(0);
00257 }
00258 
00259 #if !defined(__BEOS__)
00260 /*
00261  * Document-method: getsockopt
00262  * call-seq:
00263  *   getsockopt(level, optname) => socketoption
00264  *
00265  * Gets a socket option. These are protocol and system specific, see your
00266  * local system documentation for details. The option is returned as
00267  * a Socket::Option object.
00268  *
00269  * === Parameters
00270  * * +level+ is an integer, usually one of the SOL_ constants such as
00271  *   Socket::SOL_SOCKET, or a protocol level.
00272  *   A string or symbol of the name, possibly without prefix, is also
00273  *   accepted.
00274  * * +optname+ is an integer, usually one of the SO_ constants, such
00275  *   as Socket::SO_REUSEADDR.
00276  *   A string or symbol of the name, possibly without prefix, is also
00277  *   accepted.
00278  *
00279  * === Examples
00280  *
00281  * Some socket options are integers with boolean values, in this case
00282  * #getsockopt could be called like this:
00283  *
00284  *   reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool
00285  *
00286  *   optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
00287  *   optval = optval.unpack "i"
00288  *   reuseaddr = optval[0] == 0 ? false : true
00289  *
00290  * Some socket options are integers with numeric values, in this case
00291  * #getsockopt could be called like this:
00292  *
00293  *   ipttl = sock.getsockopt(:IP, :TTL).int
00294  *
00295  *   optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
00296  *   ipttl = optval.unpack("i")[0]
00297  *
00298  * Option values may be structs. Decoding them can be complex as it involves
00299  * examining your system headers to determine the correct definition. An
00300  * example is a +struct linger+, which may be defined in your system headers
00301  * as:
00302  *   struct linger {
00303  *     int l_onoff;
00304  *     int l_linger;
00305  *   };
00306  *
00307  * In this case #getsockopt could be called like this:
00308  *
00309  *   # Socket::Option knows linger structure.
00310  *   onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger
00311  *
00312  *   optval =  sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
00313  *   onoff, linger = optval.unpack "ii"
00314  *   onoff = onoff == 0 ? false : true
00315 */
00316 static VALUE
00317 bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
00318 {
00319     int level, option;
00320     socklen_t len;
00321     char *buf;
00322     rb_io_t *fptr;
00323     int family;
00324 
00325     GetOpenFile(sock, fptr);
00326     family = rsock_getfamily(fptr->fd);
00327     level = rsock_level_arg(family, lev);
00328     option = rsock_optname_arg(family, level, optname);
00329     len = 256;
00330     buf = ALLOCA_N(char,len);
00331 
00332     rb_io_check_closed(fptr);
00333 
00334     if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
00335         rb_sys_fail_path(fptr->pathv);
00336 
00337     return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
00338 }
00339 #else
00340 #define bsock_getsockopt rb_f_notimplement
00341 #endif
00342 
00343 /*
00344  * call-seq:
00345  *   basicsocket.getsockname => sockaddr
00346  *
00347  * Returns the local address of the socket as a sockaddr string.
00348  *
00349  *   TCPServer.open("127.0.0.1", 15120) {|serv|
00350  *     p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
00351  *   }
00352  *
00353  * If Addrinfo object is preferred over the binary string,
00354  * use BasicSocket#local_address.
00355  */
00356 static VALUE
00357 bsock_getsockname(VALUE sock)
00358 {
00359     struct sockaddr_storage buf;
00360     socklen_t len = (socklen_t)sizeof buf;
00361     socklen_t len0 = len;
00362     rb_io_t *fptr;
00363 
00364     GetOpenFile(sock, fptr);
00365     if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00366         rb_sys_fail("getsockname(2)");
00367     if (len0 < len) len = len0;
00368     return rb_str_new((char*)&buf, len);
00369 }
00370 
00371 /*
00372  * call-seq:
00373  *   basicsocket.getpeername => sockaddr
00374  *
00375  * Returns the remote address of the socket as a sockaddr string.
00376  *
00377  *   TCPServer.open("127.0.0.1", 1440) {|serv|
00378  *     c = TCPSocket.new("127.0.0.1", 1440)
00379  *     s = serv.accept
00380  *     p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
00381  *   }
00382  *
00383  * If Addrinfo object is preferred over the binary string,
00384  * use BasicSocket#remote_address.
00385  *
00386  */
00387 static VALUE
00388 bsock_getpeername(VALUE sock)
00389 {
00390     struct sockaddr_storage buf;
00391     socklen_t len = (socklen_t)sizeof buf;
00392     socklen_t len0 = len;
00393     rb_io_t *fptr;
00394 
00395     GetOpenFile(sock, fptr);
00396     if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00397         rb_sys_fail("getpeername(2)");
00398     if (len0 < len) len = len0;
00399     return rb_str_new((char*)&buf, len);
00400 }
00401 
00402 #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
00403 /*
00404  * call-seq:
00405  *   basicsocket.getpeereid => [euid, egid]
00406  *
00407  * Returns the user and group on the peer of the UNIX socket.
00408  * The result is a two element array which contains the effective uid and the effective gid.
00409  *
00410  *   Socket.unix_server_loop("/tmp/sock") {|s|
00411  *     begin
00412  *       euid, egid = s.getpeereid
00413  *
00414  *       # Check the connected client is myself or not.
00415  *       next if euid != Process.uid
00416  *
00417  *       # do something about my resource.
00418  *
00419  *     ensure
00420  *       s.close
00421  *     end
00422  *   }
00423  *
00424  */
00425 static VALUE
00426 bsock_getpeereid(VALUE self)
00427 {
00428 #if defined(HAVE_GETPEEREID)
00429     rb_io_t *fptr;
00430     uid_t euid;
00431     gid_t egid;
00432     GetOpenFile(self, fptr);
00433     if (getpeereid(fptr->fd, &euid, &egid) == -1)
00434         rb_sys_fail("getpeereid");
00435     return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
00436 #elif defined(SO_PEERCRED) /* GNU/Linux */
00437     rb_io_t *fptr;
00438     struct ucred cred;
00439     socklen_t len = sizeof(cred);
00440     GetOpenFile(self, fptr);
00441     if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
00442         rb_sys_fail("getsockopt(SO_PEERCRED)");
00443     return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
00444 #elif defined(HAVE_GETPEERUCRED) /* Solaris */
00445     rb_io_t *fptr;
00446     ucred_t *uc = NULL;
00447     VALUE ret;
00448     GetOpenFile(self, fptr);
00449     if (getpeerucred(fptr->fd, &uc) == -1)
00450         rb_sys_fail("getpeerucred");
00451     ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
00452     ucred_free(uc);
00453     return ret;
00454 #endif
00455 }
00456 #else
00457 #define bsock_getpeereid rb_f_notimplement
00458 #endif
00459 
00460 /*
00461  * call-seq:
00462  *   bsock.local_address => addrinfo
00463  *
00464  * Returns an Addrinfo object for local address obtained by getsockname.
00465  *
00466  * Note that addrinfo.protocol is filled by 0.
00467  *
00468  *   TCPSocket.open("www.ruby-lang.org", 80) {|s|
00469  *     p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP>
00470  *   }
00471  *
00472  *   TCPServer.open("127.0.0.1", 1512) {|serv|
00473  *     p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP>
00474  *   }
00475  *
00476  */
00477 static VALUE
00478 bsock_local_address(VALUE sock)
00479 {
00480     struct sockaddr_storage buf;
00481     socklen_t len = (socklen_t)sizeof buf;
00482     socklen_t len0 = len;
00483     rb_io_t *fptr;
00484 
00485     GetOpenFile(sock, fptr);
00486     if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00487         rb_sys_fail("getsockname(2)");
00488     if (len0 < len) len = len0;
00489     return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
00490 }
00491 
00492 /*
00493  * call-seq:
00494  *   bsock.remote_address => addrinfo
00495  *
00496  * Returns an Addrinfo object for remote address obtained by getpeername.
00497  *
00498  * Note that addrinfo.protocol is filled by 0.
00499  *
00500  *   TCPSocket.open("www.ruby-lang.org", 80) {|s|
00501  *     p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP>
00502  *   }
00503  *
00504  *   TCPServer.open("127.0.0.1", 1728) {|serv|
00505  *     c = TCPSocket.new("127.0.0.1", 1728)
00506  *     s = serv.accept
00507  *     p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP>
00508  *   }
00509  *
00510  */
00511 static VALUE
00512 bsock_remote_address(VALUE sock)
00513 {
00514     struct sockaddr_storage buf;
00515     socklen_t len = (socklen_t)sizeof buf;
00516     socklen_t len0 = len;
00517     rb_io_t *fptr;
00518 
00519     GetOpenFile(sock, fptr);
00520     if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00521         rb_sys_fail("getpeername(2)");
00522     if (len0 < len) len = len0;
00523     return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
00524 }
00525 
00526 /*
00527  * call-seq:
00528  *   basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent
00529  *
00530  * send _mesg_ via _basicsocket_.
00531  *
00532  * _mesg_ should be a string.
00533  *
00534  * _flags_ should be a bitwise OR of Socket::MSG_* constants.
00535  *
00536  * _dest_sockaddr_ should be a packed sockaddr string or an addrinfo.
00537  *
00538  *   TCPSocket.open("localhost", 80) {|s|
00539  *     s.send "GET / HTTP/1.0\r\n\r\n", 0
00540  *     p s.read
00541  *   }
00542  */
00543 VALUE
00544 rsock_bsock_send(int argc, VALUE *argv, VALUE sock)
00545 {
00546     struct rsock_send_arg arg;
00547     VALUE flags, to;
00548     rb_io_t *fptr;
00549     int n;
00550     rb_blocking_function_t *func;
00551 
00552     rb_secure(4);
00553     rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
00554 
00555     StringValue(arg.mesg);
00556     if (!NIL_P(to)) {
00557         SockAddrStringValue(to);
00558         to = rb_str_new4(to);
00559         arg.to = (struct sockaddr *)RSTRING_PTR(to);
00560         arg.tolen = (socklen_t)RSTRING_LENINT(to);
00561         func = rsock_sendto_blocking;
00562     }
00563     else {
00564         func = rsock_send_blocking;
00565     }
00566     GetOpenFile(sock, fptr);
00567     arg.fd = fptr->fd;
00568     arg.flags = NUM2INT(flags);
00569     while (rb_thread_fd_writable(arg.fd),
00570            (n = (int)BLOCKING_REGION_FD(func, &arg)) < 0) {
00571         if (rb_io_wait_writable(arg.fd)) {
00572             continue;
00573         }
00574         rb_sys_fail("send(2)");
00575     }
00576     return INT2FIX(n);
00577 }
00578 
00579 /*
00580  * call-seq:
00581  *   basicsocket.do_not_reverse_lookup => true or false
00582  *
00583  * Gets the do_not_reverse_lookup flag of _basicsocket_.
00584  *
00585  *   TCPSocket.open("www.ruby-lang.org", 80) {|sock|
00586  *     p sock.do_not_reverse_lookup      #=> false
00587  *     p sock.peeraddr                   #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
00588  *     sock.do_not_reverse_lookup = true
00589  *     p sock.peeraddr                   #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
00590  *   }
00591  */
00592 static VALUE
00593 bsock_do_not_reverse_lookup(VALUE sock)
00594 {
00595     rb_io_t *fptr;
00596 
00597     GetOpenFile(sock, fptr);
00598     return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
00599 }
00600 
00601 /*
00602  * call-seq:
00603  *   basicsocket.do_not_reverse_lookup = bool
00604  *
00605  * Sets the do_not_reverse_lookup flag of _basicsocket_.
00606  *
00607  *   BasicSocket.do_not_reverse_lookup = false
00608  *   p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> false
00609  *   BasicSocket.do_not_reverse_lookup = true
00610  *   p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> true
00611  *
00612  */
00613 static VALUE
00614 bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
00615 {
00616     rb_io_t *fptr;
00617 
00618     rb_secure(4);
00619     GetOpenFile(sock, fptr);
00620     if (RTEST(state)) {
00621         fptr->mode |= FMODE_NOREVLOOKUP;
00622     }
00623     else {
00624         fptr->mode &= ~FMODE_NOREVLOOKUP;
00625     }
00626     return sock;
00627 }
00628 
00629 /*
00630  * call-seq:
00631  *   basicsocket.recv(maxlen) => mesg
00632  *   basicsocket.recv(maxlen, flags) => mesg
00633  *
00634  * Receives a message.
00635  *
00636  * _maxlen_ is the maximum number of bytes to receive.
00637  *
00638  * _flags_ should be a bitwise OR of Socket::MSG_* constants.
00639  *
00640  *   UNIXSocket.pair {|s1, s2|
00641  *     s1.puts "Hello World"
00642  *     p s2.recv(4)                     #=> "Hell"
00643  *     p s2.recv(4, Socket::MSG_PEEK)   #=> "o Wo"
00644  *     p s2.recv(4)                     #=> "o Wo"
00645  *     p s2.recv(10)                    #=> "rld\n"
00646  *   }
00647  */
00648 static VALUE
00649 bsock_recv(int argc, VALUE *argv, VALUE sock)
00650 {
00651     return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
00652 }
00653 
00654 /*
00655  * call-seq:
00656  *      basicsocket.recv_nonblock(maxlen) => mesg
00657  *      basicsocket.recv_nonblock(maxlen, flags) => mesg
00658  *
00659  * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
00660  * O_NONBLOCK is set for the underlying file descriptor.
00661  * _flags_ is zero or more of the +MSG_+ options.
00662  * The result, _mesg_, is the data received.
00663  *
00664  * When recvfrom(2) returns 0, Socket#recv_nonblock returns
00665  * an empty string as data.
00666  * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
00667  *
00668  * === Parameters
00669  * * +maxlen+ - the number of bytes to receive from the socket
00670  * * +flags+ - zero or more of the +MSG_+ options
00671  *
00672  * === Example
00673  *      serv = TCPServer.new("127.0.0.1", 0)
00674  *      af, port, host, addr = serv.addr
00675  *      c = TCPSocket.new(addr, port)
00676  *      s = serv.accept
00677  *      c.send "aaa", 0
00678  *      begin # emulate blocking recv.
00679  *        p s.recv_nonblock(10) #=> "aaa"
00680  *      rescue IO::WaitReadable
00681  *        IO.select([s])
00682  *        retry
00683  *      end
00684  *
00685  * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
00686  * to _recv_nonblock_ fails.
00687  *
00688  * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
00689  * including Errno::EWOULDBLOCK.
00690  *
00691  * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
00692  * it is extended by IO::WaitReadable.
00693  * So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock.
00694  *
00695  * === See
00696  * * Socket#recvfrom
00697  */
00698 
00699 static VALUE
00700 bsock_recv_nonblock(int argc, VALUE *argv, VALUE sock)
00701 {
00702     return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
00703 }
00704 
00705 /*
00706  * call-seq:
00707  *   BasicSocket.do_not_reverse_lookup => true or false
00708  *
00709  * Gets the global do_not_reverse_lookup flag.
00710  *
00711  *   BasicSocket.do_not_reverse_lookup  #=> false
00712  */
00713 static VALUE
00714 bsock_do_not_rev_lookup(void)
00715 {
00716     return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
00717 }
00718 
00719 /*
00720  * call-seq:
00721  *   BasicSocket.do_not_reverse_lookup = bool
00722  *
00723  * Sets the global do_not_reverse_lookup flag.
00724  *
00725  * The flag is used for initial value of do_not_reverse_lookup for each socket.
00726  *
00727  *   s1 = TCPSocket.new("localhost", 80)
00728  *   p s1.do_not_reverse_lookup                 #=> true
00729  *   BasicSocket.do_not_reverse_lookup = false
00730  *   s2 = TCPSocket.new("localhost", 80)
00731  *   p s2.do_not_reverse_lookup                 #=> false
00732  *   p s1.do_not_reverse_lookup                 #=> true
00733  *
00734  */
00735 static VALUE
00736 bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
00737 {
00738     rb_secure(4);
00739     rsock_do_not_reverse_lookup = RTEST(val);
00740     return val;
00741 }
00742 
00743 void
00744 rsock_init_basicsocket(void)
00745 {
00746     /*
00747      * Document-class: BasicSocket < IO
00748      *
00749      * BasicSocket is the super class for all the Socket classes.
00750      */
00751     rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
00752     rb_undef_method(rb_cBasicSocket, "initialize");
00753 
00754     rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
00755                                bsock_do_not_rev_lookup, 0);
00756     rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
00757                                bsock_do_not_rev_lookup_set, 1);
00758     rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
00759 
00760     rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
00761     rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
00762     rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
00763     rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, -1);
00764     rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
00765     rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
00766     rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
00767     rb_define_method(rb_cBasicSocket, "getpeereid", bsock_getpeereid, 0);
00768     rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0);
00769     rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0);
00770     rb_define_method(rb_cBasicSocket, "send", rsock_bsock_send, -1);
00771     rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
00772     rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
00773     rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
00774     rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
00775 
00776     rb_define_method(rb_cBasicSocket, "sendmsg", rsock_bsock_sendmsg, -1); /* in ancdata.c */
00777     rb_define_method(rb_cBasicSocket, "sendmsg_nonblock", rsock_bsock_sendmsg_nonblock, -1); /* in ancdata.c */
00778     rb_define_method(rb_cBasicSocket, "recvmsg", rsock_bsock_recvmsg, -1); /* in ancdata.c */
00779     rb_define_method(rb_cBasicSocket, "recvmsg_nonblock", rsock_bsock_recvmsg_nonblock, -1); /* in ancdata.c */
00780 
00781 }
00782