Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# 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(NIL_P(path) ? 0 : RSTRING_PTR(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     rb_io_t *fptr;
    00362
    00363     GetOpenFile(sock, fptr);
    00364     if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
    00365         rb_sys_fail("getsockname(2)");
    00366     return rb_str_new((char*)&buf, len);
    00367 }
    00368
    00369 /*
    00370  * call-seq:
    00371  *   basicsocket.getpeername => sockaddr
    00372  *
    00373  * Returns the remote address of the socket as a sockaddr string.
    00374  *
    00375  *   TCPServer.open("127.0.0.1", 1440) {|serv|
    00376  *     c = TCPSocket.new("127.0.0.1", 1440)
    00377  *     s = serv.accept
    00378  *     p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
    00379  *   }
    00380  *
    00381  * If Addrinfo object is preferred over the binary string,
    00382  * use BasicSocket#remote_address.
    00383  *
    00384  */
    00385 static VALUE
    00386 bsock_getpeername(VALUE sock)
    00387 {
    00388     struct sockaddr_storage buf;
    00389     socklen_t len = (socklen_t)sizeof buf;
    00390     rb_io_t *fptr;
    00391
    00392     GetOpenFile(sock, fptr);
    00393     if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
    00394         rb_sys_fail("getpeername(2)");
    00395     return rb_str_new((char*)&buf, len);
    00396 }
    00397
    00398 #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
    00399 /*
    00400  * call-seq:
    00401  *   basicsocket.getpeereid => [euid, egid]
    00402  *
    00403  * Returns the user and group on the peer of the UNIX socket.
    00404  * The result is a two element array which contains the effective uid and the effective gid.
    00405  *
    00406  *   Socket.unix_server_loop("/tmp/sock") {|s|
    00407  *     begin
    00408  *       euid, egid = s.getpeereid
    00409  *
    00410  *       # Check the connected client is myself or not.
    00411  *       next if euid != Process.uid
    00412  *
    00413  *       # do something about my resource.
    00414  *
    00415  *     ensure
    00416  *       s.close
    00417  *     end
    00418  *   }
    00419  *
    00420  */
    00421 static VALUE
    00422 bsock_getpeereid(VALUE self)
    00423 {
    00424 #if defined(HAVE_GETPEEREID)
    00425     rb_io_t *fptr;
    00426     uid_t euid;
    00427     gid_t egid;
    00428     GetOpenFile(self, fptr);
    00429     if (getpeereid(fptr->fd, &euid, &egid) == -1)
    00430         rb_sys_fail("getpeereid");
    00431     return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
    00432 #elif defined(SO_PEERCRED) /* GNU/Linux */
    00433     rb_io_t *fptr;
    00434     struct ucred cred;
    00435     socklen_t len = sizeof(cred);
    00436     GetOpenFile(self, fptr);
    00437     if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
    00438         rb_sys_fail("getsockopt(SO_PEERCRED)");
    00439     return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
    00440 #elif defined(HAVE_GETPEERUCRED) /* Solaris */
    00441     rb_io_t *fptr;
    00442     ucred_t *uc = NULL;
    00443     VALUE ret;
    00444     GetOpenFile(self, fptr);
    00445     if (getpeerucred(fptr->fd, &uc) == -1)
    00446         rb_sys_fail("getpeerucred");
    00447     ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
    00448     ucred_free(uc);
    00449     return ret;
    00450 #endif
    00451 }
    00452 #else
    00453 #define bsock_getpeereid rb_f_notimplement
    00454 #endif
    00455
    00456 /*
    00457  * call-seq:
    00458  *   bsock.local_address => addrinfo
    00459  *
    00460  * Returns an Addrinfo object for local address obtained by getsockname.
    00461  *
    00462  * Note that addrinfo.protocol is filled by 0.
    00463  *
    00464  *   TCPSocket.open("www.ruby-lang.org", 80) {|s|
    00465  *     p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP>
    00466  *   }
    00467  *
    00468  *   TCPServer.open("127.0.0.1", 1512) {|serv|
    00469  *     p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP>
    00470  *   }
    00471  *
    00472  */
    00473 static VALUE
    00474 bsock_local_address(VALUE sock)
    00475 {
    00476     struct sockaddr_storage buf;
    00477     socklen_t len = (socklen_t)sizeof buf;
    00478     rb_io_t *fptr;
    00479
    00480     GetOpenFile(sock, fptr);
    00481     if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
    00482         rb_sys_fail("getsockname(2)");
    00483     return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
    00484 }
    00485
    00486 /*
    00487  * call-seq:
    00488  *   bsock.remote_address => addrinfo
    00489  *
    00490  * Returns an Addrinfo object for remote address obtained by getpeername.
    00491  *
    00492  * Note that addrinfo.protocol is filled by 0.
    00493  *
    00494  *   TCPSocket.open("www.ruby-lang.org", 80) {|s|
    00495  *     p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP>
    00496  *   }
    00497  *
    00498  *   TCPServer.open("127.0.0.1", 1728) {|serv|
    00499  *     c = TCPSocket.new("127.0.0.1", 1728)
    00500  *     s = serv.accept
    00501  *     p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP>
    00502  *   }
    00503  *
    00504  */
    00505 static VALUE
    00506 bsock_remote_address(VALUE sock)
    00507 {
    00508     struct sockaddr_storage buf;
    00509     socklen_t len = (socklen_t)sizeof buf;
    00510     rb_io_t *fptr;
    00511
    00512     GetOpenFile(sock, fptr);
    00513     if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
    00514         rb_sys_fail("getpeername(2)");
    00515     return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
    00516 }
    00517
    00518 /*
    00519  * call-seq:
    00520  *   basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent
    00521  *
    00522  * send _mesg_ via _basicsocket_.
    00523  *
    00524  * _mesg_ should be a string.
    00525  *
    00526  * _flags_ should be a bitwise OR of Socket::MSG_* constants.
    00527  *
    00528  * _dest_sockaddr_ should be a packed sockaddr string or an addrinfo.
    00529  *
    00530  *   TCPSocket.open("localhost", 80) {|s|
    00531  *     s.send "GET / HTTP/1.0\r\n\r\n", 0
    00532  *     p s.read
    00533  *   }
    00534  */
    00535 VALUE
    00536 rsock_bsock_send(int argc, VALUE *argv, VALUE sock)
    00537 {
    00538     struct rsock_send_arg arg;
    00539     VALUE flags, to;
    00540     rb_io_t *fptr;
    00541     int n;
    00542     rb_blocking_function_t *func;
    00543
    00544     rb_secure(4);
    00545     rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
    00546
    00547     StringValue(arg.mesg);
    00548     if (!NIL_P(to)) {
    00549         SockAddrStringValue(to);
    00550         to = rb_str_new4(to);
    00551         arg.to = (struct sockaddr *)RSTRING_PTR(to);
    00552         arg.tolen = (socklen_t)RSTRING_LENINT(to);
    00553         func = rsock_sendto_blocking;
    00554     }
    00555     else {
    00556         func = rsock_send_blocking;
    00557     }
    00558     GetOpenFile(sock, fptr);
    00559     arg.fd = fptr->fd;
    00560     arg.flags = NUM2INT(flags);
    00561     while (rb_thread_fd_writable(arg.fd),
    00562            (n = (int)BLOCKING_REGION(func, &arg)) < 0) {
    00563         if (rb_io_wait_writable(arg.fd)) {
    00564             continue;
    00565         }
    00566         rb_sys_fail("send(2)");
    00567     }
    00568     return INT2FIX(n);
    00569 }
    00570
    00571 /*
    00572  * call-seq:
    00573  *   basicsocket.do_not_reverse_lookup => true or false
    00574  *
    00575  * Gets the do_not_reverse_lookup flag of _basicsocket_.
    00576  *
    00577  *   TCPSocket.open("www.ruby-lang.org", 80) {|sock|
    00578  *     p sock.do_not_reverse_lookup      #=> false
    00579  *     p sock.peeraddr                   #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
    00580  *     sock.do_not_reverse_lookup = true
    00581  *     p sock.peeraddr                   #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
    00582  *   }
    00583  */
    00584 static VALUE
    00585 bsock_do_not_reverse_lookup(VALUE sock)
    00586 {
    00587     rb_io_t *fptr;
    00588
    00589     GetOpenFile(sock, fptr);
    00590     return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
    00591 }
    00592
    00593 /*
    00594  * call-seq:
    00595  *   basicsocket.do_not_reverse_lookup = bool
    00596  *
    00597  * Sets the do_not_reverse_lookup flag of _basicsocket_.
    00598  *
    00599  *   BasicSocket.do_not_reverse_lookup = false
    00600  *   p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> false
    00601  *   BasicSocket.do_not_reverse_lookup = true
    00602  *   p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> true
    00603  *
    00604  */
    00605 static VALUE
    00606 bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
    00607 {
    00608     rb_io_t *fptr;
    00609
    00610     rb_secure(4);
    00611     GetOpenFile(sock, fptr);
    00612     if (RTEST(state)) {
    00613         fptr->mode |= FMODE_NOREVLOOKUP;
    00614     }
    00615     else {
    00616         fptr->mode &= ~FMODE_NOREVLOOKUP;
    00617     }
    00618     return sock;
    00619 }
    00620
    00621 /*
    00622  * call-seq:
    00623  *   basicsocket.recv(maxlen) => mesg
    00624  *   basicsocket.recv(maxlen, flags) => mesg
    00625  *
    00626  * Receives a message.
    00627  *
    00628  * _maxlen_ is the maximum number of bytes to receive.
    00629  *
    00630  * _flags_ should be a bitwise OR of Socket::MSG_* constants.
    00631  *
    00632  *   UNIXSocket.pair {|s1, s2|
    00633  *     s1.puts "Hello World"
    00634  *     p s2.recv(4)                     #=> "Hell"
    00635  *     p s2.recv(4, Socket::MSG_PEEK)   #=> "o Wo"
    00636  *     p s2.recv(4)                     #=> "o Wo"
    00637  *     p s2.recv(10)                    #=> "rld\n"
    00638  *   }
    00639  */
    00640 static VALUE
    00641 bsock_recv(int argc, VALUE *argv, VALUE sock)
    00642 {
    00643     return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
    00644 }
    00645
    00646 /*
    00647  * call-seq:
    00648  *      basicsocket.recv_nonblock(maxlen) => mesg
    00649  *      basicsocket.recv_nonblock(maxlen, flags) => mesg
    00650  *
    00651  * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
    00652  * O_NONBLOCK is set for the underlying file descriptor.
    00653  * _flags_ is zero or more of the +MSG_+ options.
    00654  * The result, _mesg_, is the data received.
    00655  *
    00656  * When recvfrom(2) returns 0, Socket#recv_nonblock returns
    00657  * an empty string as data.
    00658  * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
    00659  *
    00660  * === Parameters
    00661  * * +maxlen+ - the number of bytes to receive from the socket
    00662  * * +flags+ - zero or more of the +MSG_+ options
    00663  *
    00664  * === Example
    00665  *      serv = TCPServer.new("127.0.0.1", 0)
    00666  *      af, port, host, addr = serv.addr
    00667  *      c = TCPSocket.new(addr, port)
    00668  *      s = serv.accept
    00669  *      c.send "aaa", 0
    00670  *      begin # emulate blocking recv.
    00671  *        p s.recv_nonblock(10) #=> "aaa"
    00672  *      rescue IO::WaitReadable
    00673  *        IO.select([s])
    00674  *        retry
    00675  *      end
    00676  *
    00677  * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
    00678  * to _recv_nonblock_ fails.
    00679  *
    00680  * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
    00681  * including Errno::EWOULDBLOCK.
    00682  *
    00683  * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
    00684  * it is extended by IO::WaitReadable.
    00685  * So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock.
    00686  *
    00687  * === See
    00688  * * Socket#recvfrom
    00689  */
    00690
    00691 static VALUE
    00692 bsock_recv_nonblock(int argc, VALUE *argv, VALUE sock)
    00693 {
    00694     return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
    00695 }
    00696
    00697 /*
    00698  * call-seq:
    00699  *   BasicSocket.do_not_reverse_lookup => true or false
    00700  *
    00701  * Gets the global do_not_reverse_lookup flag.
    00702  *
    00703  *   BasicSocket.do_not_reverse_lookup  #=> false
    00704  */
    00705 static VALUE
    00706 bsock_do_not_rev_lookup(void)
    00707 {
    00708     return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
    00709 }
    00710
    00711 /*
    00712  * call-seq:
    00713  *   BasicSocket.do_not_reverse_lookup = bool
    00714  *
    00715  * Sets the global do_not_reverse_lookup flag.
    00716  *
    00717  * The flag is used for initial value of do_not_reverse_lookup for each socket.
    00718  *
    00719  *   s1 = TCPSocket.new("localhost", 80)
    00720  *   p s1.do_not_reverse_lookup                 #=> true
    00721  *   BasicSocket.do_not_reverse_lookup = false
    00722  *   s2 = TCPSocket.new("localhost", 80)
    00723  *   p s2.do_not_reverse_lookup                 #=> false
    00724  *   p s1.do_not_reverse_lookup                 #=> true
    00725  *
    00726  */
    00727 static VALUE
    00728 bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
    00729 {
    00730     rb_secure(4);
    00731     rsock_do_not_reverse_lookup = RTEST(val);
    00732     return val;
    00733 }
    00734
    00735 /*
    00736  * BasicSocket is the super class for the all socket classes.
    00737  */
    00738 void
    00739 rsock_init_basicsocket(void)
    00740 {
    00741     rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
    00742     rb_undef_method(rb_cBasicSocket, "initialize");
    00743
    00744     rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
    00745                                bsock_do_not_rev_lookup, 0);
    00746     rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
    00747                                bsock_do_not_rev_lookup_set, 1);
    00748     rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
    00749
    00750     rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
    00751     rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
    00752     rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
    00753     rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, -1);
    00754     rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
    00755     rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
    00756     rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
    00757     rb_define_method(rb_cBasicSocket, "getpeereid", bsock_getpeereid, 0);
    00758     rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0);
    00759     rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0);
    00760     rb_define_method(rb_cBasicSocket, "send", rsock_bsock_send, -1);
    00761     rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
    00762     rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
    00763     rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
    00764     rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
    00765
    00766     rb_define_method(rb_cBasicSocket, "sendmsg", rsock_bsock_sendmsg, -1); /* in ancdata.c */
    00767     rb_define_method(rb_cBasicSocket, "sendmsg_nonblock", rsock_bsock_sendmsg_nonblock, -1); /* in ancdata.c */
    00768     rb_define_method(rb_cBasicSocket, "recvmsg", rsock_bsock_recvmsg, -1); /* in ancdata.c */
    00769     rb_define_method(rb_cBasicSocket, "recvmsg_nonblock", rsock_bsock_recvmsg_nonblock, -1); /* in ancdata.c */
    00770
    00771 }
    00772