1/************************************************ 2 3 basicsocket.c - 4 5 created at: Thu Mar 31 12:21:29 JST 1994 6 7 Copyright (C) 1993-2007 Yukihiro Matsumoto 8 9************************************************/ 10 11#include "rubysocket.h" 12 13/* 14 * call-seq: 15 * BasicSocket.for_fd(fd) => basicsocket 16 * 17 * Returns a socket object which contains the file descriptor, _fd_. 18 * 19 * # If invoked by inetd, STDIN/STDOUT/STDERR is a socket. 20 * STDIN_SOCK = Socket.for_fd(STDIN.fileno) 21 * p STDIN_SOCK.remote_address 22 * 23 */ 24static VALUE 25bsock_s_for_fd(VALUE klass, VALUE fd) 26{ 27 rb_io_t *fptr; 28 VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd)); 29 30 GetOpenFile(sock, fptr); 31 32 return sock; 33} 34 35/* 36 * call-seq: 37 * basicsocket.shutdown([how]) => 0 38 * 39 * Calls shutdown(2) system call. 40 * 41 * s.shutdown(Socket::SHUT_RD) disallows further read. 42 * 43 * s.shutdown(Socket::SHUT_WR) disallows further write. 44 * 45 * s.shutdown(Socket::SHUT_RDWR) disallows further read and write. 46 * 47 * _how_ can be symbol or string: 48 * - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD. 49 * - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR. 50 * - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR. 51 * 52 * UNIXSocket.pair {|s1, s2| 53 * s1.puts "ping" 54 * s1.shutdown(:WR) 55 * p s2.read #=> "ping\n" 56 * s2.puts "pong" 57 * s2.close 58 * p s1.read #=> "pong\n" 59 * } 60 * 61 */ 62static VALUE 63bsock_shutdown(int argc, VALUE *argv, VALUE sock) 64{ 65 VALUE howto; 66 int how; 67 rb_io_t *fptr; 68 69 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) { 70 rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket"); 71 } 72 rb_scan_args(argc, argv, "01", &howto); 73 if (howto == Qnil) 74 how = SHUT_RDWR; 75 else { 76 how = rsock_shutdown_how_arg(howto); 77 if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) { 78 rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR"); 79 } 80 } 81 GetOpenFile(sock, fptr); 82 if (shutdown(fptr->fd, how) == -1) 83 rb_sys_fail(0); 84 85 return INT2FIX(0); 86} 87 88/* 89 * call-seq: 90 * basicsocket.close_read => nil 91 * 92 * Disallows further read using shutdown system call. 93 * 94 * s1, s2 = UNIXSocket.pair 95 * s1.close_read 96 * s2.puts #=> Broken pipe (Errno::EPIPE) 97 */ 98static VALUE 99bsock_close_read(VALUE sock) 100{ 101 rb_io_t *fptr; 102 103 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) { 104 rb_raise(rb_eSecurityError, "Insecure: can't close socket"); 105 } 106 GetOpenFile(sock, fptr); 107 shutdown(fptr->fd, 0); 108 if (!(fptr->mode & FMODE_WRITABLE)) { 109 return rb_io_close(sock); 110 } 111 fptr->mode &= ~FMODE_READABLE; 112 113 return Qnil; 114} 115 116/* 117 * call-seq: 118 * basicsocket.close_write => nil 119 * 120 * Disallows further write using shutdown system call. 121 * 122 * UNIXSocket.pair {|s1, s2| 123 * s1.print "ping" 124 * s1.close_write 125 * p s2.read #=> "ping" 126 * s2.print "pong" 127 * s2.close 128 * p s1.read #=> "pong" 129 * } 130 */ 131static VALUE 132bsock_close_write(VALUE sock) 133{ 134 rb_io_t *fptr; 135 136 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) { 137 rb_raise(rb_eSecurityError, "Insecure: can't close socket"); 138 } 139 GetOpenFile(sock, fptr); 140 if (!(fptr->mode & FMODE_READABLE)) { 141 return rb_io_close(sock); 142 } 143 shutdown(fptr->fd, 1); 144 fptr->mode &= ~FMODE_WRITABLE; 145 146 return Qnil; 147} 148 149/* 150 * Document-method: setsockopt 151 * call-seq: 152 * setsockopt(level, optname, optval) 153 * setsockopt(socketoption) 154 * 155 * Sets a socket option. These are protocol and system specific, see your 156 * local system documentation for details. 157 * 158 * === Parameters 159 * * +level+ is an integer, usually one of the SOL_ constants such as 160 * Socket::SOL_SOCKET, or a protocol level. 161 * A string or symbol of the name, possibly without prefix, is also 162 * accepted. 163 * * +optname+ is an integer, usually one of the SO_ constants, such 164 * as Socket::SO_REUSEADDR. 165 * A string or symbol of the name, possibly without prefix, is also 166 * accepted. 167 * * +optval+ is the value of the option, it is passed to the underlying 168 * setsockopt() as a pointer to a certain number of bytes. How this is 169 * done depends on the type: 170 * - Fixnum: value is assigned to an int, and a pointer to the int is 171 * passed, with length of sizeof(int). 172 * - true or false: 1 or 0 (respectively) is assigned to an int, and the 173 * int is passed as for a Fixnum. Note that +false+ must be passed, 174 * not +nil+. 175 * - String: the string's data and length is passed to the socket. 176 * * +socketoption+ is an instance of Socket::Option 177 * 178 * === Examples 179 * 180 * Some socket options are integers with boolean values, in this case 181 * #setsockopt could be called like this: 182 * sock.setsockopt(:SOCKET, :REUSEADDR, true) 183 * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) 184 * sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true)) 185 * 186 * Some socket options are integers with numeric values, in this case 187 * #setsockopt could be called like this: 188 * sock.setsockopt(:IP, :TTL, 255) 189 * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255) 190 * sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255)) 191 * 192 * Option values may be structs. Passing them can be complex as it involves 193 * examining your system headers to determine the correct definition. An 194 * example is an +ip_mreq+, which may be defined in your system headers as: 195 * struct ip_mreq { 196 * struct in_addr imr_multiaddr; 197 * struct in_addr imr_interface; 198 * }; 199 * 200 * In this case #setsockopt could be called like this: 201 * optval = IPAddr.new("224.0.0.251").hton + 202 * IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton 203 * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval) 204 * 205*/ 206static VALUE 207bsock_setsockopt(int argc, VALUE *argv, VALUE sock) 208{ 209 VALUE lev, optname, val; 210 int family, level, option; 211 rb_io_t *fptr; 212 int i; 213 char *v; 214 int vlen; 215 216 if (argc == 1) { 217 lev = rb_funcall(argv[0], rb_intern("level"), 0); 218 optname = rb_funcall(argv[0], rb_intern("optname"), 0); 219 val = rb_funcall(argv[0], rb_intern("data"), 0); 220 } 221 else { 222 rb_scan_args(argc, argv, "30", &lev, &optname, &val); 223 } 224 225 rb_secure(2); 226 GetOpenFile(sock, fptr); 227 family = rsock_getfamily(fptr->fd); 228 level = rsock_level_arg(family, lev); 229 option = rsock_optname_arg(family, level, optname); 230 231 switch (TYPE(val)) { 232 case T_FIXNUM: 233 i = FIX2INT(val); 234 goto numval; 235 case T_FALSE: 236 i = 0; 237 goto numval; 238 case T_TRUE: 239 i = 1; 240 numval: 241 v = (char*)&i; vlen = (int)sizeof(i); 242 break; 243 default: 244 StringValue(val); 245 v = RSTRING_PTR(val); 246 vlen = RSTRING_LENINT(val); 247 break; 248 } 249 250#define rb_sys_fail_path(path) rb_sys_fail_str(path) 251 252 rb_io_check_closed(fptr); 253 if (setsockopt(fptr->fd, level, option, v, vlen) < 0) 254 rb_sys_fail_path(fptr->pathv); 255 256 return INT2FIX(0); 257} 258 259#if !defined(__BEOS__) 260/* 261 * Document-method: getsockopt 262 * call-seq: 263 * getsockopt(level, optname) => socketoption 264 * 265 * Gets a socket option. These are protocol and system specific, see your 266 * local system documentation for details. The option is returned as 267 * a Socket::Option object. 268 * 269 * === Parameters 270 * * +level+ is an integer, usually one of the SOL_ constants such as 271 * Socket::SOL_SOCKET, or a protocol level. 272 * A string or symbol of the name, possibly without prefix, is also 273 * accepted. 274 * * +optname+ is an integer, usually one of the SO_ constants, such 275 * as Socket::SO_REUSEADDR. 276 * A string or symbol of the name, possibly without prefix, is also 277 * accepted. 278 * 279 * === Examples 280 * 281 * Some socket options are integers with boolean values, in this case 282 * #getsockopt could be called like this: 283 * 284 * reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool 285 * 286 * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR) 287 * optval = optval.unpack "i" 288 * reuseaddr = optval[0] == 0 ? false : true 289 * 290 * Some socket options are integers with numeric values, in this case 291 * #getsockopt could be called like this: 292 * 293 * ipttl = sock.getsockopt(:IP, :TTL).int 294 * 295 * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL) 296 * ipttl = optval.unpack("i")[0] 297 * 298 * Option values may be structs. Decoding them can be complex as it involves 299 * examining your system headers to determine the correct definition. An 300 * example is a +struct linger+, which may be defined in your system headers 301 * as: 302 * struct linger { 303 * int l_onoff; 304 * int l_linger; 305 * }; 306 * 307 * In this case #getsockopt could be called like this: 308 * 309 * # Socket::Option knows linger structure. 310 * onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger 311 * 312 * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER) 313 * onoff, linger = optval.unpack "ii" 314 * onoff = onoff == 0 ? false : true 315*/ 316static VALUE 317bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname) 318{ 319 int level, option; 320 socklen_t len; 321 char *buf; 322 rb_io_t *fptr; 323 int family; 324 325 GetOpenFile(sock, fptr); 326 family = rsock_getfamily(fptr->fd); 327 level = rsock_level_arg(family, lev); 328 option = rsock_optname_arg(family, level, optname); 329 len = 256; 330 buf = ALLOCA_N(char,len); 331 332 rb_io_check_closed(fptr); 333 334 if (getsockopt(fptr->fd, level, option, buf, &len) < 0) 335 rb_sys_fail_path(fptr->pathv); 336 337 return rsock_sockopt_new(family, level, option, rb_str_new(buf, len)); 338} 339#else 340#define bsock_getsockopt rb_f_notimplement 341#endif 342 343/* 344 * call-seq: 345 * basicsocket.getsockname => sockaddr 346 * 347 * Returns the local address of the socket as a sockaddr string. 348 * 349 * TCPServer.open("127.0.0.1", 15120) {|serv| 350 * p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" 351 * } 352 * 353 * If Addrinfo object is preferred over the binary string, 354 * use BasicSocket#local_address. 355 */ 356static VALUE 357bsock_getsockname(VALUE sock) 358{ 359 struct sockaddr_storage buf; 360 socklen_t len = (socklen_t)sizeof buf; 361 socklen_t len0 = len; 362 rb_io_t *fptr; 363 364 GetOpenFile(sock, fptr); 365 if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0) 366 rb_sys_fail("getsockname(2)"); 367 if (len0 < len) len = len0; 368 return rb_str_new((char*)&buf, len); 369} 370 371/* 372 * call-seq: 373 * basicsocket.getpeername => sockaddr 374 * 375 * Returns the remote address of the socket as a sockaddr string. 376 * 377 * TCPServer.open("127.0.0.1", 1440) {|serv| 378 * c = TCPSocket.new("127.0.0.1", 1440) 379 * s = serv.accept 380 * p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" 381 * } 382 * 383 * If Addrinfo object is preferred over the binary string, 384 * use BasicSocket#remote_address. 385 * 386 */ 387static VALUE 388bsock_getpeername(VALUE sock) 389{ 390 struct sockaddr_storage buf; 391 socklen_t len = (socklen_t)sizeof buf; 392 socklen_t len0 = len; 393 rb_io_t *fptr; 394 395 GetOpenFile(sock, fptr); 396 if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0) 397 rb_sys_fail("getpeername(2)"); 398 if (len0 < len) len = len0; 399 return rb_str_new((char*)&buf, len); 400} 401 402#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED) 403/* 404 * call-seq: 405 * basicsocket.getpeereid => [euid, egid] 406 * 407 * Returns the user and group on the peer of the UNIX socket. 408 * The result is a two element array which contains the effective uid and the effective gid. 409 * 410 * Socket.unix_server_loop("/tmp/sock") {|s| 411 * begin 412 * euid, egid = s.getpeereid 413 * 414 * # Check the connected client is myself or not. 415 * next if euid != Process.uid 416 * 417 * # do something about my resource. 418 * 419 * ensure 420 * s.close 421 * end 422 * } 423 * 424 */ 425static VALUE 426bsock_getpeereid(VALUE self) 427{ 428#if defined(HAVE_GETPEEREID) 429 rb_io_t *fptr; 430 uid_t euid; 431 gid_t egid; 432 GetOpenFile(self, fptr); 433 if (getpeereid(fptr->fd, &euid, &egid) == -1) 434 rb_sys_fail("getpeereid"); 435 return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid)); 436#elif defined(SO_PEERCRED) /* GNU/Linux */ 437 rb_io_t *fptr; 438 struct ucred cred; 439 socklen_t len = sizeof(cred); 440 GetOpenFile(self, fptr); 441 if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1) 442 rb_sys_fail("getsockopt(SO_PEERCRED)"); 443 return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid)); 444#elif defined(HAVE_GETPEERUCRED) /* Solaris */ 445 rb_io_t *fptr; 446 ucred_t *uc = NULL; 447 VALUE ret; 448 GetOpenFile(self, fptr); 449 if (getpeerucred(fptr->fd, &uc) == -1) 450 rb_sys_fail("getpeerucred"); 451 ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc))); 452 ucred_free(uc); 453 return ret; 454#endif 455} 456#else 457#define bsock_getpeereid rb_f_notimplement 458#endif 459 460/* 461 * call-seq: 462 * bsock.local_address => addrinfo 463 * 464 * Returns an Addrinfo object for local address obtained by getsockname. 465 * 466 * Note that addrinfo.protocol is filled by 0. 467 * 468 * TCPSocket.open("www.ruby-lang.org", 80) {|s| 469 * p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP> 470 * } 471 * 472 * TCPServer.open("127.0.0.1", 1512) {|serv| 473 * p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP> 474 * } 475 * 476 */ 477static VALUE 478bsock_local_address(VALUE sock) 479{ 480 struct sockaddr_storage buf; 481 socklen_t len = (socklen_t)sizeof buf; 482 socklen_t len0 = len; 483 rb_io_t *fptr; 484 485 GetOpenFile(sock, fptr); 486 if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0) 487 rb_sys_fail("getsockname(2)"); 488 if (len0 < len) len = len0; 489 return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len); 490} 491 492/* 493 * call-seq: 494 * bsock.remote_address => addrinfo 495 * 496 * Returns an Addrinfo object for remote address obtained by getpeername. 497 * 498 * Note that addrinfo.protocol is filled by 0. 499 * 500 * TCPSocket.open("www.ruby-lang.org", 80) {|s| 501 * p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP> 502 * } 503 * 504 * TCPServer.open("127.0.0.1", 1728) {|serv| 505 * c = TCPSocket.new("127.0.0.1", 1728) 506 * s = serv.accept 507 * p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP> 508 * } 509 * 510 */ 511static VALUE 512bsock_remote_address(VALUE sock) 513{ 514 struct sockaddr_storage buf; 515 socklen_t len = (socklen_t)sizeof buf; 516 socklen_t len0 = len; 517 rb_io_t *fptr; 518 519 GetOpenFile(sock, fptr); 520 if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0) 521 rb_sys_fail("getpeername(2)"); 522 if (len0 < len) len = len0; 523 return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len); 524} 525 526/* 527 * call-seq: 528 * basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent 529 * 530 * send _mesg_ via _basicsocket_. 531 * 532 * _mesg_ should be a string. 533 * 534 * _flags_ should be a bitwise OR of Socket::MSG_* constants. 535 * 536 * _dest_sockaddr_ should be a packed sockaddr string or an addrinfo. 537 * 538 * TCPSocket.open("localhost", 80) {|s| 539 * s.send "GET / HTTP/1.0\r\n\r\n", 0 540 * p s.read 541 * } 542 */ 543VALUE 544rsock_bsock_send(int argc, VALUE *argv, VALUE sock) 545{ 546 struct rsock_send_arg arg; 547 VALUE flags, to; 548 rb_io_t *fptr; 549 int n; 550 rb_blocking_function_t *func; 551 552 rb_secure(4); 553 rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to); 554 555 StringValue(arg.mesg); 556 if (!NIL_P(to)) { 557 SockAddrStringValue(to); 558 to = rb_str_new4(to); 559 arg.to = (struct sockaddr *)RSTRING_PTR(to); 560 arg.tolen = (socklen_t)RSTRING_LENINT(to); 561 func = rsock_sendto_blocking; 562 } 563 else { 564 func = rsock_send_blocking; 565 } 566 GetOpenFile(sock, fptr); 567 arg.fd = fptr->fd; 568 arg.flags = NUM2INT(flags); 569 while (rb_thread_fd_writable(arg.fd), 570 (n = (int)BLOCKING_REGION_FD(func, &arg)) < 0) { 571 if (rb_io_wait_writable(arg.fd)) { 572 continue; 573 } 574 rb_sys_fail("send(2)"); 575 } 576 return INT2FIX(n); 577} 578 579/* 580 * call-seq: 581 * basicsocket.do_not_reverse_lookup => true or false 582 * 583 * Gets the do_not_reverse_lookup flag of _basicsocket_. 584 * 585 * TCPSocket.open("www.ruby-lang.org", 80) {|sock| 586 * p sock.do_not_reverse_lookup #=> false 587 * p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"] 588 * sock.do_not_reverse_lookup = true 589 * p sock.peeraddr #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"] 590 * } 591 */ 592static VALUE 593bsock_do_not_reverse_lookup(VALUE sock) 594{ 595 rb_io_t *fptr; 596 597 GetOpenFile(sock, fptr); 598 return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse; 599} 600 601/* 602 * call-seq: 603 * basicsocket.do_not_reverse_lookup = bool 604 * 605 * Sets the do_not_reverse_lookup flag of _basicsocket_. 606 * 607 * BasicSocket.do_not_reverse_lookup = false 608 * p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> false 609 * BasicSocket.do_not_reverse_lookup = true 610 * p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> true 611 * 612 */ 613static VALUE 614bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state) 615{ 616 rb_io_t *fptr; 617 618 rb_secure(4); 619 GetOpenFile(sock, fptr); 620 if (RTEST(state)) { 621 fptr->mode |= FMODE_NOREVLOOKUP; 622 } 623 else { 624 fptr->mode &= ~FMODE_NOREVLOOKUP; 625 } 626 return sock; 627} 628 629/* 630 * call-seq: 631 * basicsocket.recv(maxlen) => mesg 632 * basicsocket.recv(maxlen, flags) => mesg 633 * 634 * Receives a message. 635 * 636 * _maxlen_ is the maximum number of bytes to receive. 637 * 638 * _flags_ should be a bitwise OR of Socket::MSG_* constants. 639 * 640 * UNIXSocket.pair {|s1, s2| 641 * s1.puts "Hello World" 642 * p s2.recv(4) #=> "Hell" 643 * p s2.recv(4, Socket::MSG_PEEK) #=> "o Wo" 644 * p s2.recv(4) #=> "o Wo" 645 * p s2.recv(10) #=> "rld\n" 646 * } 647 */ 648static VALUE 649bsock_recv(int argc, VALUE *argv, VALUE sock) 650{ 651 return rsock_s_recvfrom(sock, argc, argv, RECV_RECV); 652} 653 654/* 655 * call-seq: 656 * basicsocket.recv_nonblock(maxlen) => mesg 657 * basicsocket.recv_nonblock(maxlen, flags) => mesg 658 * 659 * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after 660 * O_NONBLOCK is set for the underlying file descriptor. 661 * _flags_ is zero or more of the +MSG_+ options. 662 * The result, _mesg_, is the data received. 663 * 664 * When recvfrom(2) returns 0, Socket#recv_nonblock returns 665 * an empty string as data. 666 * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc. 667 * 668 * === Parameters 669 * * +maxlen+ - the number of bytes to receive from the socket 670 * * +flags+ - zero or more of the +MSG_+ options 671 * 672 * === Example 673 * serv = TCPServer.new("127.0.0.1", 0) 674 * af, port, host, addr = serv.addr 675 * c = TCPSocket.new(addr, port) 676 * s = serv.accept 677 * c.send "aaa", 0 678 * begin # emulate blocking recv. 679 * p s.recv_nonblock(10) #=> "aaa" 680 * rescue IO::WaitReadable 681 * IO.select([s]) 682 * retry 683 * end 684 * 685 * Refer to Socket#recvfrom for the exceptions that may be thrown if the call 686 * to _recv_nonblock_ fails. 687 * 688 * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure, 689 * including Errno::EWOULDBLOCK. 690 * 691 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN, 692 * it is extended by IO::WaitReadable. 693 * So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock. 694 * 695 * === See 696 * * Socket#recvfrom 697 */ 698 699static VALUE 700bsock_recv_nonblock(int argc, VALUE *argv, VALUE sock) 701{ 702 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_RECV); 703} 704 705/* 706 * call-seq: 707 * BasicSocket.do_not_reverse_lookup => true or false 708 * 709 * Gets the global do_not_reverse_lookup flag. 710 * 711 * BasicSocket.do_not_reverse_lookup #=> false 712 */ 713static VALUE 714bsock_do_not_rev_lookup(void) 715{ 716 return rsock_do_not_reverse_lookup?Qtrue:Qfalse; 717} 718 719/* 720 * call-seq: 721 * BasicSocket.do_not_reverse_lookup = bool 722 * 723 * Sets the global do_not_reverse_lookup flag. 724 * 725 * The flag is used for initial value of do_not_reverse_lookup for each socket. 726 * 727 * s1 = TCPSocket.new("localhost", 80) 728 * p s1.do_not_reverse_lookup #=> true 729 * BasicSocket.do_not_reverse_lookup = false 730 * s2 = TCPSocket.new("localhost", 80) 731 * p s2.do_not_reverse_lookup #=> false 732 * p s1.do_not_reverse_lookup #=> true 733 * 734 */ 735static VALUE 736bsock_do_not_rev_lookup_set(VALUE self, VALUE val) 737{ 738 rb_secure(4); 739 rsock_do_not_reverse_lookup = RTEST(val); 740 return val; 741} 742 743void 744rsock_init_basicsocket(void) 745{ 746 /* 747 * Document-class: BasicSocket < IO 748 * 749 * BasicSocket is the super class for all the Socket classes. 750 */ 751 rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO); 752 rb_undef_method(rb_cBasicSocket, "initialize"); 753 754 rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup", 755 bsock_do_not_rev_lookup, 0); 756 rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=", 757 bsock_do_not_rev_lookup_set, 1); 758 rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1); 759 760 rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0); 761 rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0); 762 rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1); 763 rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, -1); 764 rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2); 765 rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0); 766 rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0); 767 rb_define_method(rb_cBasicSocket, "getpeereid", bsock_getpeereid, 0); 768 rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0); 769 rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0); 770 rb_define_method(rb_cBasicSocket, "send", rsock_bsock_send, -1); 771 rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1); 772 rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1); 773 rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0); 774 rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1); 775 776 rb_define_method(rb_cBasicSocket, "sendmsg", rsock_bsock_sendmsg, -1); /* in ancdata.c */ 777 rb_define_method(rb_cBasicSocket, "sendmsg_nonblock", rsock_bsock_sendmsg_nonblock, -1); /* in ancdata.c */ 778 rb_define_method(rb_cBasicSocket, "recvmsg", rsock_bsock_recvmsg, -1); /* in ancdata.c */ 779 rb_define_method(rb_cBasicSocket, "recvmsg_nonblock", rsock_bsock_recvmsg_nonblock, -1); /* in ancdata.c */ 780 781} 782