diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-01-10 17:16:51 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-01-10 17:16:51 +0000 |
commit | 166c122fd399fc244ae8ba0685ae6771d84a2f76 (patch) | |
tree | 5a15395520c389a256ce3a8a4456eba7bbc8448a /ext/socket | |
parent | 7f52fa08b10cdaecf9e64e7d1e14709543d56743 (diff) | |
download | ruby-166c122fd399fc244ae8ba0685ae6771d84a2f76.tar.gz |
rdoc update.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21419 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket')
-rw-r--r-- | ext/socket/socket.c | 713 |
1 files changed, 711 insertions, 2 deletions
diff --git a/ext/socket/socket.c b/ext/socket/socket.c index fa95c5edcc..6c4bc41f6b 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -399,6 +399,17 @@ init_sock(VALUE sock, int fd) return sock; } +/* + * 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) { @@ -410,6 +421,33 @@ bsock_s_for_fd(VALUE klass, VALUE fd) 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) { @@ -436,6 +474,16 @@ bsock_shutdown(int argc, VALUE *argv, VALUE sock) 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) { @@ -454,6 +502,21 @@ bsock_close_read(VALUE sock) 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) { @@ -622,6 +685,16 @@ bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname) #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) { @@ -635,6 +708,19 @@ bsock_getsockname(VALUE sock) 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) { @@ -703,9 +789,14 @@ io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len) * call-seq: * bsock.local_address => addrinfo * - * returns an AddrInfo object for local address obtained by getsockname. + * 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) @@ -724,9 +815,16 @@ bsock_local_address(VALUE sock) * call-seq: * bsock.remote_address => addrinfo * - * returns an AddrInfo object for remote address obtained by getpeername. + * 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) @@ -771,6 +869,23 @@ send_blocking(void *data) static VALUE sockaddr_string_value(volatile VALUE *); static char *sockaddr_string_value_ptr(volatile VALUE *); +/* + * 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 + * } + */ static VALUE bsock_send(int argc, VALUE *argv, VALUE sock) { @@ -807,6 +922,19 @@ bsock_send(int argc, VALUE *argv, VALUE sock) 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) { @@ -816,6 +944,18 @@ bsock_do_not_reverse_lookup(VALUE sock) 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) { @@ -987,6 +1127,25 @@ s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) return rb_assoc_new(str, addr); } +/* + * 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) { @@ -1036,12 +1195,36 @@ 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) { @@ -1719,6 +1902,16 @@ tcp_sockaddr(struct sockaddr *addr, size_t len) return make_ipaddr(addr); } +/* + * call-seq: + * TCPSocket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list] + * + * Lookups host information by _hostname_. + * + * TCPSocket.gethostbyname("localhost") + * #=> ["localhost", ["hal"], 2, "127.0.0.1"] + * + */ static VALUE tcp_s_gethostbyname(VALUE obj, VALUE host) { @@ -1727,6 +1920,19 @@ tcp_s_gethostbyname(VALUE obj, VALUE host) tcp_sockaddr); } +/* + * call-seq: + * TCPServer.new([hostname,] port) => tcpserver + * + * Creates a new server socket bound to _port_. + * + * If _hostname_ is given, the socket is bound to it. + * + * serv = TCPServer.new("127.0.0.1", 28561) + * s = serv.accept + * s.puts Time.now + * s.close + */ static VALUE tcp_svr_init(int argc, VALUE *argv, VALUE sock) { @@ -1817,6 +2023,17 @@ s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) return init_sock(rb_obj_alloc(klass), fd2); } +/* + * call-seq: + * tcpserver.accept => tcpsocket + * + * TCPServer.open("127.0.0.1", 14641) {|serv| + * s = serv.accept + * s.puts Time.now + * s.close + * } + * + */ static VALUE tcp_accept(VALUE sock) { @@ -1872,6 +2089,20 @@ tcp_accept_nonblock(VALUE sock) (struct sockaddr *)&from, &fromlen); } +/* + * call-seq: + * tcpserver.sysaccept => file_descriptor + * + * Returns a file descriptor of a accepted connection. + * + * TCPServer.open("127.0.0.1", 28561) {|serv| + * fd = serv.sysaccept + * s = IO.for_fd(fd) + * s.puts Time.now + * s.close + * } + * + */ static VALUE tcp_sysaccept(VALUE sock) { @@ -1951,6 +2182,22 @@ init_unixsock(VALUE sock, VALUE path, int server) } #endif +/* + * call-seq: + * ipsocket.addr => [address_family, port, hostname, numeric_address] + * + * Returns the local address as an array which contains + * address_family, port, hostname and numeric_address. + * + * hostname is obtained from numeric_address using reverse lookup. + * If ipsocket.do_not_reverse_lookup is true, + * hostname is same as numeric_address. + * + * TCPSocket.open("www.ruby-lang.org", 80) {|sock| + * p sock.addr #=> ["AF_INET", 49429, "hal", "192.168.0.128"] + * } + * + */ static VALUE ip_addr(VALUE sock) { @@ -1965,6 +2212,19 @@ ip_addr(VALUE sock) return ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP); } +/* + * call-seq: + * ipsocket.peeraddr => [address_family, port, hostname, numeric_address] + * + * Returns the remote address as an array which contains + * address_family, port, hostname and numeric_address. + * It is defined for connection oritented socket such as TCPSocket. + * + * TCPSocket.open("www.ruby-lang.org", 80) {|sock| + * p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"] + * } + * + */ static VALUE ip_peeraddr(VALUE sock) { @@ -1979,12 +2239,43 @@ ip_peeraddr(VALUE sock) return ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP); } +/* + * call-seq: + * ipsocket.recvfrom(maxlen) => [mesg, ipaddr] + * ipsocket.recvfrom(maxlen, flags) => [mesg, ipaddr] + * + * Receives a message and return the message as a string and + * an address which the message come from. + * + * _maxlen_ is the maximum number of bytes to receive. + * + * _flags_ should be a bitwise OR of Socket::MSG_* constants. + * + * ipaddr is same as IPSocket#{peeraddr,addr}. + * + * u1 = UDPSocket.new + * u1.bind("127.0.0.1", 4913) + * u2 = UDPSocket.new + * u2.send "uuuu", 0, "127.0.0.1", 4913 + * p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]] + * + */ static VALUE ip_recvfrom(int argc, VALUE *argv, VALUE sock) { return s_recvfrom(sock, argc, argv, RECV_IP); } +/* + * call-seq: + * IPSocket.getaddress(host) => ipaddress + * + * Lookups IP address of _host_. + * + * IPSocket.getaddress("localhost") #=> "127.0.0.1" + * IPSocket.getaddress("ip6-localhost") #=> "::1" + * + */ static VALUE ip_s_getaddress(VALUE obj, VALUE host) { @@ -1998,6 +2289,19 @@ ip_s_getaddress(VALUE obj, VALUE host) return make_ipaddr((struct sockaddr*)&addr); } +/* + * call-seq: + * UDPSocket.new([address_family]) => socket + * + * Creates a new UDPSocket object. + * + * _address_family_ should be an integer, a string or a symbol: + * Socket::AF_INET, "AF_INET", :INET, etc. + * + * UDPSocket.new #=> #<UDPSocket:fd 3> + * UDPSocket.new(Socket::AF_INET6) #=> #<UDPSocket:fd 4> + * + */ static VALUE udp_init(int argc, VALUE *argv, VALUE sock) { @@ -2037,6 +2341,22 @@ udp_connect_internal(struct udp_arg *arg) return Qfalse; } +/* + * call-seq: + * udpsocket.connect(host, port) => 0 + * + * Connects _udpsocket_ to _host_:_port_. + * + * This makes possible to send without destination address. + * + * u1 = UDPSocket.new + * u1.bind("127.0.0.1", 4913) + * u2 = UDPSocket.new + * u2.connect("127.0.0.1", 4913) + * u2.send "uuuu", 0 + * p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]] + * + */ static VALUE udp_connect(VALUE sock, VALUE host, VALUE port) { @@ -2054,6 +2374,18 @@ udp_connect(VALUE sock, VALUE host, VALUE port) return INT2FIX(0); } +/* + * call-seq: + * udpsocket.bind(host, port) #=> 0 + * + * Binds _udpsocket_ to _host_:_port_. + * + * u1 = UDPSocket.new + * u1.bind("127.0.0.1", 4913) + * u1.send "message-to-self", 0, "127.0.0.1", 4913 + * p u1.recvfrom(10) #=> ["message-to", ["AF_INET", 4913, "localhost", "127.0.0.1"]] + * + */ static VALUE udp_bind(VALUE sock, VALUE host, VALUE port) { @@ -2075,6 +2407,28 @@ udp_bind(VALUE sock, VALUE host, VALUE port) return INT2FIX(0); } +/* + * call-seq: + * udpsocket.send(mesg, flags, host, port) => numbytes_sent + * udpsocket.send(mesg, flags, sockaddr_to) => numbytes_sent + * udpsocket.send(mesg, flags) => numbytes_sent + * + * Sends _mesg_ via _udpsocket_. + * + * _flags_ should be a bitwise OR of Socket::MSG_* constants. + * + * u1 = UDPSocket.new + * u1.bind("127.0.0.1", 4913) + * + * u2 = UDPSocket.new + * u2.send "hi", 0, "127.0.0.1", 4913 + * + * mesg, addr = u1.recvfrom(10) + * u1.send mesg, 0, addr[3], addr[1] + * + * p u2.recv(100) #=> "hi" + * + */ static VALUE udp_send(int argc, VALUE *argv, VALUE sock) { @@ -2162,6 +2516,16 @@ udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock) } #ifdef HAVE_SYS_UN_H +/* + * call-seq: + * UNIXSocket.new(path) => unixsocket + * + * Creates a new UNIX client socket connected to _path_. + * + * s = UNIXSocket.new("/tmp/sock") + * s.send "hello", 0 + * + */ static VALUE unix_init(VALUE sock, VALUE path) { @@ -2177,6 +2541,16 @@ unixpath(struct sockaddr_un *sockaddr, socklen_t len) return ""; } +/* + * call-seq: + * unixsocket.path => path + * + * Returns the path of the local address of unixsocket. + * + * s = UNIXServer.new("/tmp/sock") + * p s.path #=> "/tmp/sock" + * + */ static VALUE unix_path(VALUE sock) { @@ -2193,12 +2567,45 @@ unix_path(VALUE sock) return rb_str_dup(fptr->pathv); } +/* + * call-seq: + * UNIXServer.new(path) => unixserver + * + * Creates a new UNIX server socket bound to _path_. + * + * serv = UNIXServer.new("/tmp/sock") + * s = serv.accept + * p s.read + */ static VALUE unix_svr_init(VALUE sock, VALUE path) { return init_unixsock(sock, path, 1); } +/* + * call-seq: + * unixsocket.recvfrom(maxlen [, flags]) => [mesg, unixaddress] + * + * Receives a message via _unixsocket_. + * + * _maxlen_ is the maximum number of bytes to receive. + * + * _flags_ should be a bitwise OR of Socket::MSG_* constants. + * + * s1 = Socket.new(:UNIX, :DGRAM, 0) + * s1_ai = AddrInfo.unix("/tmp/sock1") + * s1.bind(s1_ai) + * + * s2 = Socket.new(:UNIX, :DGRAM, 0) + * s2_ai = AddrInfo.unix("/tmp/sock2") + * s2.bind(s2_ai) + * s3 = UNIXSocket.for_fd(s2.fileno) + * + * s1.send "a", 0, s2_ai + * p s3.recvfrom(10) #=> ["a", ["AF_UNIX", "/tmp/sock1"]] + * + */ static VALUE unix_recvfrom(int argc, VALUE *argv, VALUE sock) { @@ -2229,6 +2636,22 @@ sendmsg_blocking(void *data) return sendmsg(arg->fd, &arg->msg, 0); } +/* + * call-seq: + * unixsocket.send_io(io) => nil + * + * Sends _io_ as file descriptor passing. + * + * s1, s2 = UNIXSocket.pair + * + * s1.send_io STDOUT + * stdout = s2.recv_io + * + * p STDOUT.fileno #=> 1 + * p stdout.fileno #=> 6 + * + * stdout.puts "hello" # outputs "hello\n" to standard output. + */ static VALUE unix_send_io(VALUE sock, VALUE val) { @@ -2303,6 +2726,25 @@ recvmsg_blocking(void *data) return recvmsg(arg->fd, &arg->msg, 0); } +/* + * call-seq: + * unixsocket.recv_io([klass [, mode]]) => io + * + * UNIXServer.open("/tmp/sock") {|serv| + * UNIXSocket.open("/tmp/sock") {|c| + * s = serv.accept + * + * c.send_io STDOUT + * stdout = s.recv_io + * + * p STDOUT.fileno #=> 1 + * p stdout.fileno #=> 7 + * + * stdout.puts "hello" # outputs "hello\n" to standard output. + * } + * } + * + */ static VALUE unix_recv_io(int argc, VALUE *argv, VALUE sock) { @@ -2412,6 +2854,23 @@ unix_recv_io(int argc, VALUE *argv, VALUE sock) #endif } +/* + * call-seq: + * unixserver.accept => unixsocket + * + * Accepts a new connection. + * It returns new UNIXSocket object. + * + * UNIXServer.open("/tmp/sock") {|serv| + * UNIXSocket.open("/tmp/sock") {|c| + * s = serv.accept + * s.puts "hi" + * s.close + * p c.read #=> "hi\n" + * } + * } + * + */ static VALUE unix_accept(VALUE sock) { @@ -2467,6 +2926,24 @@ unix_accept_nonblock(VALUE sock) (struct sockaddr *)&from, &fromlen); } +/* + * call-seq: + * unixserver.sysaccept => file_descriptor + * + * Accepts a new connection. + * It returns the new file descriptor which is an integer. + * + * UNIXServer.open("/tmp/sock") {|serv| + * UNIXSocket.open("/tmp/sock") {|c| + * fd = serv.sysaccept + * s = IO.new(fd) + * s.puts "hi" + * s.close + * p c.read #=> "hi\n" + * } + * } + * + */ static VALUE unix_sysaccept(VALUE sock) { @@ -2486,6 +2963,17 @@ unixaddr(struct sockaddr_un *sockaddr, socklen_t len) rb_str_new2(unixpath(sockaddr, len))); } +/* + * call-seq: + * unixsocket.addr => [address_family, unix_path] + * + * Returns the local address as an array which contains + * address_family and unix_path. + * + * Example + * serv = UNIXServer.new("/tmp/sock") + * p serv.addr #=> ["AF_UNIX", "/tmp/sock"] + */ static VALUE unix_addr(VALUE sock) { @@ -2500,6 +2988,18 @@ unix_addr(VALUE sock) return unixaddr(&addr, len); } +/* + * call-seq: + * unixsocket.peeraddr => [address_family, unix_path] + * + * Returns the remote address as an array which contains + * address_family and unix_path. + * + * Example + * serv = UNIXServer.new("/tmp/sock") + * c = UNIXSocket.new("/tmp/sock") + * p c.peeraddr #=> ["AF_UNIX", "/tmp/sock"] + */ static VALUE unix_peeraddr(VALUE sock) { @@ -2522,6 +3022,24 @@ setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv) *tv = socktype_arg(type); } +/* + * call-seq: + * Socket.new(domain, socktype, protocol) => socket + * + * Creates a new socket object. + * + * _domain_ should be a communications domain such as: :INET, :INET6, :UNIX, etc. + * + * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + * + * _protocol_ should be a protocol defined in the domain. + * 0 is default protocol for the domain. + * + * Socket.new(:INET, :STREAM, 0) # TCP socket + * Socket.new(:INET, :DGRAM, 0) # UDP socket + * Socket.new(:UNIX, :STREAM, 0) # UNIX stream socket + * Socket.new(:UNIX, :DGRAM, 0) # UNIX datagram socket + */ static VALUE sock_initialize(VALUE sock, VALUE domain, VALUE type, VALUE protocol) { @@ -2556,6 +3074,27 @@ pair_yield(VALUE pair) } #endif +/* + * call-seq: + * Socket.pair(domain, type, protocol) => [socket1, socket2] + * Socket.socketpair(domain, type, protocol) => [socket1, socket2] + * + * Creates a pair of sockets connected each other. + * + * _domain_ should be a communications domain such as: :INET, :INET6, :UNIX, etc. + * + * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + * + * _protocol_ should be a protocol defined in the domain. + * 0 is default protocol for the domain. + * + * s1, s2 = Socket.pair(:UNIX, :DGRAM, 0) + * s1.send "a", 0 + * s1.send "b", 0 + * p s2.recv(10) #=> "a" + * p s2.recv(10) #=> "b" + * + */ static VALUE sock_s_socketpair(VALUE klass, VALUE domain, VALUE type, VALUE protocol) { @@ -2588,6 +3127,24 @@ sock_s_socketpair(VALUE klass, VALUE domain, VALUE type, VALUE protocol) } #ifdef HAVE_SYS_UN_H +/* + * call-seq: + * UNIXSocket.pair([type [, protocol]]) => [unixsocket1, unixsocket2] + * UNIXSocket.socketpair([type [, protocol]]) => [unixsocket1, unixsocket2] + * + * Creates a pair of sockets connected each other. + * + * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + * + * _protocol_ should be a protocol defined in the domain. + * 0 is default protocol for the domain. + * + * s1, s2 = UNIXSocket.pair + * s1.send "a", 0 + * s1.send "b", 0 + * p s2.recv(10) #=> "ab" + * + */ static VALUE unix_s_socketpair(int argc, VALUE *argv, VALUE klass) { @@ -3141,6 +3698,10 @@ sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock) return s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET); } +/* + * call-seq: + * socket.accept => [client_socket, client_addrinfo] + */ static VALUE sock_accept(VALUE sock) { @@ -3270,6 +3831,17 @@ sock_sysaccept(VALUE sock) } #ifdef HAVE_GETHOSTNAME +/* + * call-seq: + * Socket.gethostname => hostname + * + * Returns the hostname. + * + * Note that it is not guaranteed to be able to convert to IP address using gethostbyname, getaddrinfo, etc. + * + * p Socket.gethostname #=> "hal" + * + */ static VALUE sock_gethostname(VALUE obj) { @@ -3351,6 +3923,15 @@ sock_sockaddr(struct sockaddr *addr, size_t len) return rb_str_new(ptr, len); } +/* + * call-seq: + * Socket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list] + * + * Obtains the host information for _hostname_. + * + * p Socket.gethostbyname("hal") #=> ["localhost", ["hal"], 2, "\x7F\x00\x00\x01"] + * + */ static VALUE sock_s_gethostbyname(VALUE obj, VALUE host) { @@ -3358,6 +3939,15 @@ sock_s_gethostbyname(VALUE obj, VALUE host) return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr); } +/* + * call-seq: + * Socket.gethostbyaddr(address_string [, address_family]) => hostent + * + * Obtains the host information for _address_. + * + * p Socket.gethostbyaddr([221,186,184,68].pack("CCCC")) + * #=> ["carbon.ruby-lang.org", [], 2, "\xDD\xBA\xB8D"] + */ static VALUE sock_s_gethostbyaddr(int argc, VALUE *argv) { @@ -3408,6 +3998,19 @@ sock_s_gethostbyaddr(int argc, VALUE *argv) return ary; } +/* + * call-seq: + * Socket.getservbyname(service_name) => port_number + * Socket.getservbyname(service_name, protocol_name) => port_number + * + * Obtains the port number for _service_name_. + * + * If _protocol_name_ is not given, "tcp" is assumed. + * + * Socket.getservbyname("smtp") #=> 25 + * Socket.getservbyname("shell") #=> 514 + * Socket.getservbyname("syslog", "udp") #=> 514 + */ static VALUE sock_s_getservbyname(int argc, VALUE *argv) { @@ -3436,6 +4039,19 @@ sock_s_getservbyname(int argc, VALUE *argv) return INT2FIX(port); } +/* + * call-seq: + * Socket.getservbyport(port [, protocol_name]) => service + * + * Obtains the port number for _port_. + * + * If _protocol_name_ is not given, "tcp" is assumed. + * + * Socket.getservbyport(80) #=> "www" + * Socket.getservbyport(514, "tcp") #=> "shell" + * Socket.getservbyport(514, "udp") #=> "syslog" + * + */ static VALUE sock_s_getservbyport(int argc, VALUE *argv) { @@ -3459,6 +4075,30 @@ sock_s_getservbyport(int argc, VALUE *argv) return rb_tainted_str_new2(sp->s_name); } +/* + * call-seq: + * Socket.getaddrinfo(nodename, servname[, family[, socktype[, protocol[, flags]]]]) => array + * + * Obtains address information for _nodename_:_servname_. + * + * _family_ should be an address family such as: :INET, :INET6, :UNIX, etc. + * + * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + * + * _protocol_ should be a protocol defined in the family. + * 0 is default protocol for the family. + * + * _flags_ should be bitwise OR of Socket::AI_* constants. + * + * Socket.getaddrinfo("www.ruby-lang.org", "http", nil, :STREAM) + * #=> [["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68", 2, 1, 6]] # PF_INET/SOCK_STREAM/IPPROTO_TCP + * + * Socket.getaddrinfo("localhost", nil) + * #=> [["AF_INET", 0, "localhost", "127.0.0.1", 2, 1, 6], # PF_INET/SOCK_STREAM/IPPROTO_TCP + * # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 2, 17], # PF_INET/SOCK_DGRAM/IPPROTO_UDP + * # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 3, 0]] # PF_INET/SOCK_RAW/IPPROTO_IP + * + */ static VALUE sock_s_getaddrinfo(int argc, VALUE *argv) { @@ -3486,6 +4126,25 @@ sock_s_getaddrinfo(int argc, VALUE *argv) return ret; } +/* + * call-seq: + * Socket.getnameinfo(sockaddr [, flags]) => [hostname, servicename] + * + * Obtains name information for _sockaddr_. + * + * _sockaddr_ should be one of follows. + * - packed sockddr string such as Socket.sockaddr_in(80, "127.0.0.1") + * - 3-elements array such as ["AF_INET", 80, "127.0.0.1"] + * - 4-elements array such as ["AF_INET", 80, ignored, "127.0.0.1"] + * + * _flags_ should be bitwise OR of Socket::NI_* constants. + * + * Note that the last form is compatible with IPSocket#{addr,peeraddr}. + * + * Socket.getnameinfo(Socket.sockaddr_in(80, "127.0.0.1")) #=> ["localhost", "www"] + * Socket.getnameinfo(["AF_INET", 80, "127.0.0.1"]) #=> ["localhost", "www"] + * Socket.getnameinfo(["AF_INET", 80, "localhost", "127.0.0.1"]) #=> ["localhost", "www"] + */ static VALUE sock_s_getnameinfo(int argc, VALUE *argv) { @@ -3612,6 +4271,20 @@ sock_s_getnameinfo(int argc, VALUE *argv) raise_socket_error("getnameinfo", error); } +/* + * call-seq: + * Socket.sockaddr_in(port, host) => sockaddr + * Socket.pack_sockaddr_in(port, host) => sockaddr + * + * Packs _port_ and _host_ as an AF_INET/AF_INET6 sockaddr string. + * + * Socket.sockaddr_in(80, "127.0.0.1") + * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" + * + * Socket.sockaddr_in(80, "::1") + * #=> "\n\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00" + * + */ static VALUE sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host) { @@ -3625,6 +4298,19 @@ sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host) return addr; } +/* + * call-seq: + * Socket.unpack_sockaddr_in(sockaddr) => [port, ip_address] + * + * Unpacks _sockaddr_ into port and ip_address. + * + * _sockaddr_ should be a string or an addrinfo for AF_INET/AF_INET6. + * + * sockaddr = Socket.sockaddr_in(80, "127.0.0.1") + * p sockaddr #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" + * p Socket.unpack_sockaddr_in(sockaddr) #=> [80, "127.0.0.1"] + * + */ static VALUE sock_s_unpack_sockaddr_in(VALUE self, VALUE addr) { @@ -3649,6 +4335,17 @@ sock_s_unpack_sockaddr_in(VALUE self, VALUE addr) } #ifdef HAVE_SYS_UN_H + +/* + * call-seq: + * Socket.sockaddr_un(path) => sockaddr + * Socket.pack_sockaddr_un(path) => sockaddr + * + * Packs _path_ as an AF_UNIX sockaddr string. + * + * Socket.sockaddr_un("/tmp/sock") #=> "\x01\x00/tmp/sock\x00\x00..." + * + */ static VALUE sock_s_pack_sockaddr_un(VALUE self, VALUE path) { @@ -3670,6 +4367,18 @@ sock_s_pack_sockaddr_un(VALUE self, VALUE path) return addr; } +/* + * call-seq: + * Socket.unpack_sockaddr_un(sockaddr) => path + * + * Unpacks _sockaddr_ into path. + * + * _sockaddr_ should be a string or an addrinfo for AF_UNIX. + * + * sockaddr = Socket.sockaddr_un("/tmp/sock") + * p Socket.unpack_sockaddr_un(sockaddr) #=> "/tmp/sock" + * + */ static VALUE sock_s_unpack_sockaddr_un(VALUE self, VALUE addr) { |