Ruby
2.0.0p247(2013-06-27revision41674)
|
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