summaryrefslogtreecommitdiff
path: root/ext/socket/basicsocket.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-01-17 04:11:27 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-01-17 04:11:27 +0000
commit97cbab78dcc43f696077d3bbce1ee35f9d947339 (patch)
tree7570d3897cbfe9d7b45c077dbf4b760b246243cb /ext/socket/basicsocket.c
parent8ae8afa649e7f59bfddf60dcb9fb844c02b3dc95 (diff)
* ext/socket: split files for each class.
* ext/socket/rubysocket.h: common header. * ext/socket/basicsocket.c: new file for BasicSocket. * ext/socket/ipsocket.c: new file for IPSocket. * ext/socket/tcpsocket.c: new file for TCPSocket. * ext/socket/tcpserver.c: new file for TCPServer. * ext/socket/sockssocket.c: new file for SOCKSSocket. * ext/socket/udpsocket.c: new file for UDPSocket. * ext/socket/unixsocket.c: new file for UNIXSocket. * ext/socket/unixserver.c: new file for UNIXServer. * ext/socket/socket.c: now for Socket. * ext/socket/raddrinfo.c: new file for AddrInfo and name resolution. * ext/socket/constants.c: new file for constants. * ext/socket/init.c: new file for utilities. * ext/socket/mkconstants.rb: export *_to_int. * ext/socket/extconf.rb: add new object files. * ext/socket/depend: add dependencies for new files. * ext/.document: add new files. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21619 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket/basicsocket.c')
-rw-r--r--ext/socket/basicsocket.c640
1 files changed, 640 insertions, 0 deletions
diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c
new file mode 100644
index 0000000000..4b8e94653f
--- /dev/null
+++ b/ext/socket/basicsocket.c
@@ -0,0 +1,640 @@
+/************************************************
+
+ basicsocket.c -
+
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
+
+************************************************/
+
+#include "rubysocket.h"
+
+/*
+ * call-seq:
+ * BasicSocket.for_fd(fd) => basicsocket
+ *
+ * Returns a socket object which contains the file descriptor, _fd_.
+ *
+ * # If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
+ * STDIN_SOCK = Socket.for_fd(STDIN.fileno)
+ * p STDIN_SOCK.remote_address
+ *
+ */
+static VALUE
+bsock_s_for_fd(VALUE klass, VALUE fd)
+{
+ rb_io_t *fptr;
+ VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));
+
+ GetOpenFile(sock, fptr);
+
+ return sock;
+}
+
+/*
+ * call-seq:
+ * basicsocket.shutdown([how]) => 0
+ *
+ * Calls shutdown(2) system call.
+ *
+ * s.shutdown(Socket::SHUT_RD) disallows further read.
+ *
+ * s.shutdown(Socket::SHUT_WR) disallows further write.
+ *
+ * s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
+ *
+ * _how_ can be symbol or string:
+ * - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD.
+ * - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR.
+ * - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR.
+ *
+ * UNIXSocket.pair {|s1, s2|
+ * s1.puts "ping"
+ * s1.shutdown(:WR)
+ * p s2.read #=> "ping\n"
+ * s2.puts "pong"
+ * s2.close
+ * p s1.read #=> "pong\n"
+ * }
+ *
+ */
+static VALUE
+bsock_shutdown(int argc, VALUE *argv, VALUE sock)
+{
+ VALUE howto;
+ int how;
+ rb_io_t *fptr;
+
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
+ }
+ rb_scan_args(argc, argv, "01", &howto);
+ if (howto == Qnil)
+ how = SHUT_RDWR;
+ else {
+ how = shutdown_how_arg(howto);
+ if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
+ rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
+ }
+ }
+ GetOpenFile(sock, fptr);
+ if (shutdown(fptr->fd, how) == -1)
+ rb_sys_fail(0);
+
+ return INT2FIX(0);
+}
+
+/*
+ * call-seq:
+ * basicsocket.close_read => nil
+ *
+ * Disallows further read.
+ *
+ * s1, s2 = UNIXSocket.pair
+ * s1.close_read
+ * s2.puts #=> Broken pipe (Errno::EPIPE)
+ */
+static VALUE
+bsock_close_read(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't close socket");
+ }
+ GetOpenFile(sock, fptr);
+ shutdown(fptr->fd, 0);
+ if (!(fptr->mode & FMODE_WRITABLE)) {
+ return rb_io_close(sock);
+ }
+ fptr->mode &= ~FMODE_READABLE;
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * basicsocket.close_write => nil
+ *
+ * Disallows further write.
+ *
+ * UNIXSocket.pair {|s1, s2|
+ * s1.print "ping"
+ * s1.close_write
+ * p s2.read #=> "ping"
+ * s2.print "pong"
+ * s2.close
+ * p s1.read #=> "pong"
+ * }
+ */
+static VALUE
+bsock_close_write(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't close socket");
+ }
+ GetOpenFile(sock, fptr);
+ if (!(fptr->mode & FMODE_READABLE)) {
+ return rb_io_close(sock);
+ }
+ shutdown(fptr->fd, 1);
+ fptr->mode &= ~FMODE_WRITABLE;
+
+ return Qnil;
+}
+
+/*
+ * Document-method: setsockopt
+ * call-seq: setsockopt(level, optname, optval)
+ *
+ * Sets a socket option. These are protocol and system specific, see your
+ * local sytem documentation for details.
+ *
+ * === Parameters
+ * * +level+ is an integer, usually one of the SOL_ constants such as
+ * Socket::SOL_SOCKET, or a protocol level.
+ * * +optname+ is an integer, usually one of the SO_ constants, such
+ * as Socket::SO_REUSEADDR.
+ * * +optval+ is the value of the option, it is passed to the underlying
+ * setsockopt() as a pointer to a certain number of bytes. How this is
+ * done depends on the type:
+ * - Fixnum: value is assigned to an int, and a pointer to the int is
+ * passed, with length of sizeof(int).
+ * - true or false: 1 or 0 (respectively) is assigned to an int, and the
+ * int is passed as for a Fixnum. Note that +false+ must be passed,
+ * not +nil+.
+ * - String: the string's data and length is passed to the socket.
+ *
+ * === Examples
+ *
+ * Some socket options are integers with boolean values, in this case
+ * #setsockopt could be called like this:
+ * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
+ *
+ * Some socket options are integers with numeric values, in this case
+ * #setsockopt could be called like this:
+ * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
+ *
+ * Option values may be structs. Passing them can be complex as it involves
+ * examining your system headers to determine the correct definition. An
+ * example is an +ip_mreq+, which may be defined in your system headers as:
+ * struct ip_mreq {
+ * struct in_addr imr_multiaddr;
+ * struct in_addr imr_interface;
+ * };
+ *
+ * In this case #setsockopt could be called like this:
+ * optval = IPAddr.new("224.0.0.251") + Socket::INADDR_ANY
+ * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
+ *
+*/
+static VALUE
+bsock_setsockopt(VALUE sock, VALUE lev, VALUE optname, VALUE val)
+{
+ int level, option;
+ rb_io_t *fptr;
+ int i;
+ char *v;
+ int vlen;
+
+ rb_secure(2);
+ level = level_arg(lev);
+ option = optname_arg(level, optname);
+
+ switch (TYPE(val)) {
+ case T_FIXNUM:
+ i = FIX2INT(val);
+ goto numval;
+ case T_FALSE:
+ i = 0;
+ goto numval;
+ case T_TRUE:
+ i = 1;
+ numval:
+ v = (char*)&i; vlen = sizeof(i);
+ break;
+ default:
+ StringValue(val);
+ v = RSTRING_PTR(val);
+ vlen = RSTRING_LEN(val);
+ break;
+ }
+
+#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
+
+ GetOpenFile(sock, fptr);
+ if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
+ rb_sys_fail_path(fptr->pathv);
+
+ return INT2FIX(0);
+}
+
+/*
+ * Document-method: getsockopt
+ * call-seq: getsockopt(level, optname)
+ *
+ * Gets a socket option. These are protocol and system specific, see your
+ * local sytem documentation for details. The option is returned as
+ * a String with the data being the binary value of the socket option.
+ *
+ * === Parameters
+ * * +level+ is an integer, usually one of the SOL_ constants such as
+ * Socket::SOL_SOCKET, or a protocol level.
+ * * +optname+ is an integer, usually one of the SO_ constants, such
+ * as Socket::SO_REUSEADDR.
+ *
+ * === Examples
+ *
+ * Some socket options are integers with boolean values, in this case
+ * #getsockopt could be called like this:
+ * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
+ * optval = optval.unpack "i"
+ * reuseaddr = optval[0] == 0 ? false : true
+ *
+ * Some socket options are integers with numeric values, in this case
+ * #getsockopt could be called like this:
+ * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
+ * ipttl = optval.unpack("i")[0]
+ *
+ * Option values may be structs. Decoding them can be complex as it involves
+ * examining your system headers to determine the correct definition. An
+ * example is a +struct linger+, which may be defined in your system headers
+ * as:
+ * struct linger {
+ * int l_onoff;
+ * int l_linger;
+ * };
+ *
+ * In this case #getsockopt could be called like this:
+ * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
+ * onoff, linger = optval.unpack "ii"
+*/
+static VALUE
+bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
+{
+#if !defined(__BEOS__)
+ int level, option;
+ socklen_t len;
+ char *buf;
+ rb_io_t *fptr;
+
+ level = level_arg(lev);
+ option = optname_arg(level, optname);
+ len = 256;
+ buf = ALLOCA_N(char,len);
+
+ GetOpenFile(sock, fptr);
+ if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
+ rb_sys_fail_path(fptr->pathv);
+
+ return rb_str_new(buf, len);
+#else
+ rb_notimplement();
+#endif
+}
+
+/*
+ * call-seq:
+ * basicsocket.getsockname => sockaddr
+ *
+ * Returns the local address of the socket as a sockaddr string.
+ *
+ * TCPServer.open("127.0.0.1", 15120) {|serv|
+ * p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ * }
+ */
+static VALUE
+bsock_getsockname(VALUE sock)
+{
+ char buf[1024];
+ socklen_t len = sizeof buf;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getsockname(fptr->fd, (struct sockaddr*)buf, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return rb_str_new(buf, len);
+}
+
+/*
+ * call-seq:
+ * basicsocket.getpeername => sockaddr
+ *
+ * Returns the remote address of the socket as a sockaddr string.
+ *
+ * TCPServer.open("127.0.0.1", 1440) {|serv|
+ * c = TCPSocket.new("127.0.0.1", 1440)
+ * s = serv.accept
+ * p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ * }
+ *
+ */
+static VALUE
+bsock_getpeername(VALUE sock)
+{
+ char buf[1024];
+ socklen_t len = sizeof buf;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getpeername(fptr->fd, (struct sockaddr*)buf, &len) < 0)
+ rb_sys_fail("getpeername(2)");
+ return rb_str_new(buf, len);
+}
+
+/*
+ * call-seq:
+ * bsock.local_address => addrinfo
+ *
+ * Returns an AddrInfo object for local address obtained by getsockname.
+ *
+ * Note that addrinfo.protocol is filled by 0.
+ *
+ * TCPServer.open("127.0.0.1", 1512) {|serv|
+ * p serv.local_address #=> #<AddrInfo: 127.0.0.1:1512 TCP>
+ * }
+ *
+ */
+static VALUE
+bsock_local_address(VALUE sock)
+{
+ char buf[1024];
+ socklen_t len = sizeof buf;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getsockname(fptr->fd, (struct sockaddr*)buf, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return fd_socket_addrinfo(fptr->fd, (struct sockaddr *)buf, len);
+}
+
+/*
+ * call-seq:
+ * bsock.remote_address => addrinfo
+ *
+ * Returns an AddrInfo object for remote address obtained by getpeername.
+ *
+ * Note that addrinfo.protocol is filled by 0.
+ *
+ * TCPServer.open("127.0.0.1", 1728) {|serv|
+ * c = TCPSocket.new("127.0.0.1", 1728)
+ * s = serv.accept
+ * p s.remote_address #=> #<AddrInfo: 127.0.0.1:36504 TCP>
+ * }
+ *
+ */
+static VALUE
+bsock_remote_address(VALUE sock)
+{
+ char buf[1024];
+ socklen_t len = sizeof buf;
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getpeername(fptr->fd, (struct sockaddr*)buf, &len) < 0)
+ rb_sys_fail("getpeername(2)");
+ return fd_socket_addrinfo(fptr->fd, (struct sockaddr *)buf, len);
+}
+
+/*
+ * call-seq:
+ * basicsocket.send(mesg, flags [, sockaddr_to]) => numbytes_sent
+ *
+ * send _mesg_ via _basicsocket_.
+ *
+ * _mesg_ should be a string.
+ *
+ * _flags_ should be a bitwise OR of Socket::MSG_* constants.
+ *
+ * _sockaddr_to_ should be a packed sockaddr string or an addrinfo.
+ *
+ * TCPSocket.open("localhost", 80) {|s|
+ * s.send "GET / HTTP/1.0\r\n\r\n", 0
+ * p s.read
+ * }
+ */
+VALUE
+bsock_send(int argc, VALUE *argv, VALUE sock)
+{
+ struct send_arg arg;
+ VALUE flags, to;
+ rb_io_t *fptr;
+ int n;
+ rb_blocking_function_t *func;
+
+ rb_secure(4);
+ rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
+
+ StringValue(arg.mesg);
+ if (!NIL_P(to)) {
+ SockAddrStringValue(to);
+ to = rb_str_new4(to);
+ arg.to = (struct sockaddr *)RSTRING_PTR(to);
+ arg.tolen = RSTRING_LEN(to);
+ func = sendto_blocking;
+ }
+ else {
+ func = send_blocking;
+ }
+ GetOpenFile(sock, fptr);
+ arg.fd = fptr->fd;
+ arg.flags = NUM2INT(flags);
+ while (rb_thread_fd_writable(arg.fd),
+ (n = (int)BLOCKING_REGION(func, &arg)) < 0) {
+ if (rb_io_wait_writable(arg.fd)) {
+ continue;
+ }
+ rb_sys_fail("send(2)");
+ }
+ return INT2FIX(n);
+}
+
+/*
+ * call-seq:
+ * basicsocket.do_not_reverse_lookup => true or false
+ *
+ * Gets the do_not_reverse_lookup flag of _basicsocket_.
+ *
+ * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
+ * p sock.do_not_reverse_lookup #=> false
+ * p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
+ * sock.do_not_reverse_lookup = true
+ * p sock.peeraddr #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
+ * }
+ */
+static VALUE
+bsock_do_not_reverse_lookup(VALUE sock)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(sock, fptr);
+ return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * basicsocket.do_not_reverse_lookup = bool
+ *
+ * Sets the do_not_reverse_lookup flag of _basicsocket_.
+ *
+ * BasicSocket.do_not_reverse_lookup = false
+ * p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> false
+ * BasicSocket.do_not_reverse_lookup = true
+ * p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> true
+ *
+ */
+static VALUE
+bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
+{
+ rb_io_t *fptr;
+
+ rb_secure(4);
+ GetOpenFile(sock, fptr);
+ if (RTEST(state)) {
+ fptr->mode |= FMODE_NOREVLOOKUP;
+ }
+ else {
+ fptr->mode &= ~FMODE_NOREVLOOKUP;
+ }
+ return sock;
+}
+
+/*
+ * call-seq:
+ * basicsocket.recv(maxlen) => mesg
+ * basicsocket.recv(maxlen, flags) => mesg
+ *
+ * Receives a message.
+ *
+ * _maxlen_ is the maximum number of bytes to receive.
+ *
+ * _flags_ should be a bitwise OR of Socket::MSG_* constants.
+ *
+ * UNIXSocket.pair {|s1, s2|
+ * s1.puts "Hello World"
+ * p s2.recv(4) #=> "Hell"
+ * p s2.recv(4, Socket::MSG_PEEK) #=> "o Wo"
+ * p s2.recv(4) #=> "o Wo"
+ * p s2.recv(10) #=> "rld\n"
+ * }
+ */
+static VALUE
+bsock_recv(int argc, VALUE *argv, VALUE sock)
+{
+ return s_recvfrom(sock, argc, argv, RECV_RECV);
+}
+
+/*
+ * call-seq:
+ * basicsocket.recv_nonblock(maxlen) => mesg
+ * basicsocket.recv_nonblock(maxlen, flags) => mesg
+ *
+ * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * _flags_ is zero or more of the +MSG_+ options.
+ * The result, _mesg_, is the data received.
+ *
+ * When recvfrom(2) returns 0, Socket#recv_nonblock returns
+ * an empty string as data.
+ * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
+ *
+ * === Parameters
+ * * +maxlen+ - the number of bytes to receive from the socket
+ * * +flags+ - zero or more of the +MSG_+ options
+ *
+ * === Example
+ * serv = TCPServer.new("127.0.0.1", 0)
+ * af, port, host, addr = serv.addr
+ * c = TCPSocket.new(addr, port)
+ * s = serv.accept
+ * c.send "aaa", 0
+ * IO.select([s]) # emulate blocking recv.
+ * p s.recv_nonblock(10) #=> "aaa"
+ *
+ * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
+ * to _recv_nonblock_ fails.
+ *
+ * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
+ * including Errno::EWOULDBLOCK.
+ *
+ * === See
+ * * Socket#recvfrom
+ */
+
+static VALUE
+bsock_recv_nonblock(int argc, VALUE *argv, VALUE sock)
+{
+ return s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
+}
+
+/*
+ * call-seq:
+ * BasicSocket.do_not_reverse_lookup => true or false
+ *
+ * Gets the global do_not_reverse_lookup flag.
+ *
+ * BasicSocket.do_not_reverse_lookup #=> false
+ */
+static VALUE
+bsock_do_not_rev_lookup(void)
+{
+ return do_not_reverse_lookup?Qtrue:Qfalse;
+}
+
+/*
+ * call-seq:
+ * BasicSocket.do_not_reverse_lookup = bool
+ *
+ * Sets the global do_not_reverse_lookup flag.
+ *
+ * The flag is used for initial value of do_not_reverse_lookup for each socket.
+ *
+ * s1 = TCPSocket.new("localhost", 80)
+ * p s1.do_not_reverse_lookup #=> true
+ * BasicSocket.do_not_reverse_lookup = false
+ * s2 = TCPSocket.new("localhost", 80)
+ * p s2.do_not_reverse_lookup #=> false
+ * p s1.do_not_reverse_lookup #=> true
+ *
+ */
+static VALUE
+bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
+{
+ rb_secure(4);
+ do_not_reverse_lookup = RTEST(val);
+ return val;
+}
+
+/*
+ * BasicSocket class
+ */
+void
+Init_basicsocket(void)
+{
+ rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
+ rb_undef_method(rb_cBasicSocket, "initialize");
+
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
+ bsock_do_not_rev_lookup, 0);
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
+ bsock_do_not_rev_lookup_set, 1);
+ rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
+
+ rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
+ rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
+ rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
+ rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, 3);
+ rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
+ rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
+ rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
+ rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0);
+ rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0);
+ rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
+ rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
+ rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
+ rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
+ rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
+}