From: Sam Roberts Date: 2005-07-08T23:48:59+09:00 Subject: docs patch for class IPSocket, class Socket, and Socket.getservbyname, Socket.getaddrinfo I don't have the time to continue, but if somebody is interested, I think the following is fairly useful - get rid of the comment before committing. Note that I don't know what some of the possible AI_ flags do, thus the "...". Its against the 1.8 src, sorry. Cheers, Sam Index: socket.c =================================================================== RCS file: /src/ruby/ext/socket/socket.c,v retrieving revision 1.108.2.29 diff -u -r1.108.2.29 socket.c --- socket.c 2 Jul 2005 15:22:11 -0000 1.108.2.29 +++ socket.c 8 Jul 2005 14:40:38 -0000 @@ -2236,6 +2236,36 @@ return rb_str_new(ptr, len); } +/* + * Document-class: IPSocket + * + * IPSocket is the parent of TCPSocket and UDPSocket and implements function + * common to them. + * + * A number of APIs in IPSocket, Socket, and their descendants return an + * address as an array. The members of that array are: + * - address family: A string like "AF_INET" or "AF_INET6" if it is one of the + * commonly used families, the string "unknown:#" (where `#' is the address + * family number) if it is not one of the common ones. The strings map to + * the Socket::AF_* constants. + * - port: The port number. + * - name: Either the canonical name from looking the address up in the DNS, or + * the address in presentation format + * - address: The address in presentation format (a dotted decimal string for + * IPv4, a hex string for IPv6). + * + * The address and port can be used directly to create sockets and bind or + * connect them to the address. + */ + +/* + * Document-class: Socket + * + * Socket contains a number of generally useful singleton methods and + * constants, as well as offering low-level interfaces that can be used to + * develop socket applications using protocols other than TCP, UDP, and UNIX + * domain sockets. + */ static VALUE sock_s_gethostbyname(obj, host) VALUE obj, host; @@ -2296,6 +2326,18 @@ return ary; } +/* + * Document-method: getservbyname + * call-seq: Socket.getservbyname(name, proto="tcp") => port + * + * +name+ is a service name ("ftp", "telnet", ...) and proto is a protocol name + * ("udp", "tcp", ...). '/etc/services' (or your systems equivalent) is + * searched for a service for +name+ and +proto+, and the port number is + * returned. + * + * Note that unlike Socket.getaddrinfo +proto+ may not be specified using the + * Socket::SOCK_* constants, a string must must be used. + */ static VALUE sock_s_getservbyaname(argc, argv) int argc; @@ -2326,6 +2368,117 @@ return INT2FIX(port); } +/* +Documentation should explain the following: + +$ pp Socket.getaddrinfo("", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) +[["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]] + +$ pp Socket.getaddrinfo(nil, 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) +[["AF_INET6", 1, "::", "::", 30, 1, 6], + ["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]] + +$ pp Socket.getaddrinfo("localhost", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) +[["AF_INET6", 1, "localhost", "::1", 30, 1, 6], + ["AF_INET", 1, "localhost", "127.0.0.1", 2, 1, 6]] + +$ pp Socket.getaddrinfo("ensemble.local.", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) +[["AF_INET", 1, "localhost", "192.168.123.154", 2, 1, 6]] + +Why aren't limit args accepted as :family=>..., :flags=>... + +*/ +/* + * Document-method: getaddrinfo + * call-seq: Socket.getaddrinfo(host, service, family=nil, socktype=nil, protocol=nil, flags=nil) => ainfo + * + * Return address information for +host+ and +port+. The remaining arguments + * are hints that limit the address information returned. + * + * This method corresponds closely to the POSIX.1g getaddrinfo() definition. + * + * === Parameters + * - +host+ is a host name or an address string (dotted decimal for IPv4, or a hex string + * for IPv6) for which to return information. A nil is also allowed, its meaning + * depends on +flags+, see below. + * - +service+ is a service name ("http", "ssh", ...), or + * a port number (80, 22, ...), see Socket.getservbyname for more + * information. A nil is also allowed, meaning zero. + * - +family+ limits the output to a specific address family, one of the + * Socket::AF_* constants. Socket::AF_INET (IPv4) and Socket::AF_INET6 (IPv6) + * are the most commonly used families. You will usually pass either nil or + * Socket::AF_UNSPEC, allowing the IPv6 information to be returned first if + * +host+ is reachable via IPv6, and IPv4 information otherwise. The two + * strings "AF_INET" or "AF_INET6" are also allowed, they are converted to + * their respective Socket::AF_* constants. + * - +socktype+ limits the output to a specific type of socket, one of the + * Socket::SOCK_* constants. Socket::SOCK_STREAM (for TCP) and + * Socket::SOCK_DGRAM (for UDP) are the most commonly used socket types. If + * nil, then information for all types of sockets supported by +service+ will + * be returned. You will usually know what type of socket you intend to + * create, and should pass that socket type in. + * - +protocol+ limits the output to a specific protocol numpber, one of the + * Socket::IPPROTO_* constants. It is usually implied by the socket type + * (Socket::SOCK_STREAM => Socket::IPPROTO_TCP, ...), if you pass other than + * nil you already know what this is for. + * - +flags+ is one of the Socket::AI_* constants. They mean: + * - Socket::AI_PASSIVE: when set, if +host+ is nil the 'any' address will be + * returned, Socket::INADDR_ANY or 0 for IPv4, "0::0" or "::" for IPv6. This + * address is suitable for use by servers that will bind their socket and do + * a passive listen, thus the name of the flag. Otherwise the local or + * loopback address will be returned, this is "127.0.0.1" for IPv4 and "::1' + * for IPv6. + * - ... + * + * + * === Returns + * + * Returns an array of arrays, where each subarray contains: + * - address family, a string like "AF_INET" or "AF_INET6" + * - port number, the port number for +service+ + * - host name, either a canonical name for +host+, or it's address in presentation + * format if the address could not be looked up. + * - host IP, the address of +host+ in presentation format + * - address family, as a numeric value (one of the Socket::AF_* constants). + * - socket type, as a numeric value (one of the Socket::SOCK_* constants). + * - protocol number, as a numeric value (one of the Socket::IPPROTO_* constants). + * + * The first four values are identical to what is commonly returned as an + * address array, see IPSocket for more information. + * + * === Examples + * + * Not all input combinations are valid, and while there are many combinations, + * only a few cases are common. + * + * A typical client will call getaddrinfo with the +host+ and +service+ it + * wants to connect to. It knows that it will attempt to connect with either + * TCP or UDP, and specifies +sockettype+ accordingly. It loops through all + * returned addresses, and try to connect to them in turn: + * + * ainfo = Socket::getaddrinfo('www.example.com', 'www', nil, Socket::SOCK_STREAM) + * ainfo.each do |af, port, name, addr| + * begin + * sock = TCPSocket.new(addr, port) + * # ... + * exit 1 + * rescue + * end + * end + * + * With UDP you don't know if connection suceeded, but if communication fails, + * the next address can be tried. + * + * A typical server will call getaddrinfo with a +host+ of nil, the +service+ + * it listens to, and a +flags+ of Socket::AI_PASSIVE. It will listen for + * connections on the first returned address: + * ainfo = Socket::getaddrinfo(nil, 'www', nil, Socket::SOCK_STREAM, nil, Socket::AI_PASSIVE) + * af, port, name, addr = ainfo.first + * sock = TCPServer(addr, port) + * while( client = s.accept ) + * # ... + * end + */ static VALUE sock_s_getaddrinfo(argc, argv) int argc;