1/************************************************
2
3  socket.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
13static void
14setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
15{
16    *dv = rsock_family_arg(domain);
17    *tv = rsock_socktype_arg(type);
18}
19
20/*
21 * call-seq:
22 *   Socket.new(domain, socktype [, protocol]) => socket
23 *
24 * Creates a new socket object.
25 *
26 * _domain_ should be a communications domain such as: :INET, :INET6, :UNIX, etc.
27 *
28 * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
29 *
30 * _protocol_ is optional and should be a protocol defined in the domain.
31 * If protocol is not given, 0 is used internally.
32 *
33 *   Socket.new(:INET, :STREAM) # TCP socket
34 *   Socket.new(:INET, :DGRAM)  # UDP socket
35 *   Socket.new(:UNIX, :STREAM) # UNIX stream socket
36 *   Socket.new(:UNIX, :DGRAM)  # UNIX datagram socket
37 */
38static VALUE
39sock_initialize(int argc, VALUE *argv, VALUE sock)
40{
41    VALUE domain, type, protocol;
42    int fd;
43    int d, t;
44
45    rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
46    if (NIL_P(protocol))
47        protocol = INT2FIX(0);
48
49    rb_secure(3);
50    setup_domain_and_type(domain, &d, type, &t);
51    fd = rsock_socket(d, t, NUM2INT(protocol));
52    if (fd < 0) rb_sys_fail("socket(2)");
53
54    return rsock_init_sock(sock, fd);
55}
56
57#if defined HAVE_SOCKETPAIR
58static VALUE
59io_call_close(VALUE io)
60{
61    return rb_funcall(io, rb_intern("close"), 0, 0);
62}
63
64static VALUE
65io_close(VALUE io)
66{
67    return rb_rescue(io_call_close, io, 0, 0);
68}
69
70static VALUE
71pair_yield(VALUE pair)
72{
73    return rb_ensure(rb_yield, pair, io_close, rb_ary_entry(pair, 1));
74}
75#endif
76
77#if defined HAVE_SOCKETPAIR
78
79static int
80rsock_socketpair0(int domain, int type, int protocol, int sv[2])
81{
82    int ret;
83
84#ifdef SOCK_CLOEXEC
85    static int try_sock_cloexec = 1;
86    if (try_sock_cloexec) {
87        ret = socketpair(domain, type|SOCK_CLOEXEC, protocol, sv);
88        if (ret == -1 && errno == EINVAL) {
89            /* SOCK_CLOEXEC is available since Linux 2.6.27.  Linux 2.6.18 fails with EINVAL */
90            ret = socketpair(domain, type, protocol, sv);
91            if (ret != -1) {
92                /* The reason of EINVAL may be other than SOCK_CLOEXEC.
93                 * So disable SOCK_CLOEXEC only if socketpair() succeeds without SOCK_CLOEXEC.
94                 * Ex. Socket.pair(:UNIX, 0xff) fails with EINVAL.
95                 */
96                try_sock_cloexec = 0;
97            }
98        }
99    }
100    else {
101        ret = socketpair(domain, type, protocol, sv);
102    }
103#else
104    ret = socketpair(domain, type, protocol, sv);
105#endif
106
107    if (ret == -1) {
108        return -1;
109    }
110
111    rb_fd_fix_cloexec(sv[0]);
112    rb_fd_fix_cloexec(sv[1]);
113
114    return ret;
115}
116
117static int
118rsock_socketpair(int domain, int type, int protocol, int sv[2])
119{
120    int ret;
121
122    ret = rsock_socketpair0(domain, type, protocol, sv);
123    if (ret < 0 && (errno == EMFILE || errno == ENFILE)) {
124        rb_gc();
125        ret = rsock_socketpair0(domain, type, protocol, sv);
126    }
127
128    return ret;
129}
130
131/*
132 * call-seq:
133 *   Socket.pair(domain, type, protocol)       => [socket1, socket2]
134 *   Socket.socketpair(domain, type, protocol) => [socket1, socket2]
135 *
136 * Creates a pair of sockets connected each other.
137 *
138 * _domain_ should be a communications domain such as: :INET, :INET6, :UNIX, etc.
139 *
140 * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
141 *
142 * _protocol_ should be a protocol defined in the domain,
143 * defaults to 0 for the domain.
144 *
145 *   s1, s2 = Socket.pair(:UNIX, :DGRAM, 0)
146 *   s1.send "a", 0
147 *   s1.send "b", 0
148 *   p s2.recv(10) #=> "a"
149 *   p s2.recv(10) #=> "b"
150 *
151 */
152VALUE
153rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
154{
155    VALUE domain, type, protocol;
156    int d, t, p, sp[2];
157    int ret;
158    VALUE s1, s2, r;
159
160    rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
161    if (NIL_P(protocol))
162        protocol = INT2FIX(0);
163
164    setup_domain_and_type(domain, &d, type, &t);
165    p = NUM2INT(protocol);
166    ret = rsock_socketpair(d, t, p, sp);
167    if (ret < 0) {
168	rb_sys_fail("socketpair(2)");
169    }
170    rb_fd_fix_cloexec(sp[0]);
171    rb_fd_fix_cloexec(sp[1]);
172
173    s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
174    s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
175    r = rb_assoc_new(s1, s2);
176    if (rb_block_given_p()) {
177        return rb_ensure(pair_yield, r, io_close, s1);
178    }
179    return r;
180}
181#else
182#define rsock_sock_s_socketpair rb_f_notimplement
183#endif
184
185/*
186 * call-seq:
187 * 	socket.connect(remote_sockaddr) => 0
188 *
189 * Requests a connection to be made on the given +remote_sockaddr+. Returns 0 if
190 * successful, otherwise an exception is raised.
191 *
192 * === Parameter
193 * * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
194 *
195 * === Example:
196 * 	# Pull down Google's web page
197 * 	require 'socket'
198 * 	include Socket::Constants
199 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
200 * 	sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
201 * 	socket.connect( sockaddr )
202 * 	socket.write( "GET / HTTP/1.0\r\n\r\n" )
203 * 	results = socket.read
204 *
205 * === Unix-based Exceptions
206 * On unix-based systems the following system exceptions may be raised if
207 * the call to _connect_ fails:
208 * * Errno::EACCES - search permission is denied for a component of the prefix
209 *   path or write access to the +socket+ is denied
210 * * Errno::EADDRINUSE - the _sockaddr_ is already in use
211 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
212 *   local machine
213 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
214 *   the address family of the specified +socket+
215 * * Errno::EALREADY - a connection is already in progress for the specified
216 *   socket
217 * * Errno::EBADF - the +socket+ is not a valid file descriptor
218 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
219 *   refused the connection request
220 * * Errno::ECONNRESET - the remote host reset the connection request
221 * * Errno::EFAULT - the _sockaddr_ cannot be accessed
222 * * Errno::EHOSTUNREACH - the destination host cannot be reached (probably
223 *   because the host is down or a remote router cannot reach it)
224 * * Errno::EINPROGRESS - the O_NONBLOCK is set for the +socket+ and the
225 *   connection cannot be immediately established; the connection will be
226 *   established asynchronously
227 * * Errno::EINTR - the attempt to establish the connection was interrupted by
228 *   delivery of a signal that was caught; the connection will be established
229 *   asynchronously
230 * * Errno::EISCONN - the specified +socket+ is already connected
231 * * Errno::EINVAL - the address length used for the _sockaddr_ is not a valid
232 *   length for the address family or there is an invalid family in _sockaddr_
233 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
234 *   PATH_MAX
235 * * Errno::ENETDOWN - the local interface used to reach the destination is down
236 * * Errno::ENETUNREACH - no route to the network is present
237 * * Errno::ENOBUFS - no buffer space is available
238 * * Errno::ENOSR - there were insufficient STREAMS resources available to
239 *   complete the operation
240 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
241 * * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected
242 * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket
243 *   bound to the specified peer address
244 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
245 *   was made.
246 *
247 * On unix-based systems if the address family of the calling +socket+ is
248 * AF_UNIX the follow exceptions may be raised if the call to _connect_
249 * fails:
250 * * Errno::EIO - an i/o error occurred while reading from or writing to the
251 *   file system
252 * * Errno::ELOOP - too many symbolic links were encountered in translating
253 *   the pathname in _sockaddr_
254 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
255 *   characters, or an entire pathname exceeded PATH_MAX characters
256 * * Errno::ENOENT - a component of the pathname does not name an existing file
257 *   or the pathname is an empty string
258 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
259 *   is not a directory
260 *
261 * === Windows Exceptions
262 * On Windows systems the following system exceptions may be raised if
263 * the call to _connect_ fails:
264 * * Errno::ENETDOWN - the network is down
265 * * Errno::EADDRINUSE - the socket's local address is already in use
266 * * Errno::EINTR - the socket was cancelled
267 * * Errno::EINPROGRESS - a blocking socket is in progress or the service provider
268 *   is still processing a callback function. Or a nonblocking connect call is
269 *   in progress on the +socket+.
270 * * Errno::EALREADY - see Errno::EINVAL
271 * * Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as
272 *   ADDR_ANY TODO check ADDRANY TO INADDR_ANY
273 * * Errno::EAFNOSUPPORT - addresses in the specified family cannot be used with
274 *   with this +socket+
275 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
276 *   refused the connection request
277 * * Errno::EFAULT - the socket's internal address or address length parameter
278 *   is too small or is not a valid part of the user space address
279 * * Errno::EINVAL - the +socket+ is a listening socket
280 * * Errno::EISCONN - the +socket+ is already connected
281 * * Errno::ENETUNREACH - the network cannot be reached from this host at this time
282 * * Errno::EHOSTUNREACH - no route to the network is present
283 * * Errno::ENOBUFS - no buffer space is available
284 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
285 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
286 *   was made.
287 * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the
288 *   connection cannot be completed immediately
289 * * Errno::EACCES - the attempt to connect the datagram socket to the
290 *   broadcast address failed
291 *
292 * === See
293 * * connect manual pages on unix-based systems
294 * * connect function in Microsoft's Winsock functions reference
295 */
296static VALUE
297sock_connect(VALUE sock, VALUE addr)
298{
299    rb_io_t *fptr;
300    int fd, n;
301
302    SockAddrStringValue(addr);
303    addr = rb_str_new4(addr);
304    GetOpenFile(sock, fptr);
305    fd = fptr->fd;
306    n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr), 0);
307    if (n < 0) {
308	rb_sys_fail("connect(2)");
309    }
310
311    return INT2FIX(n);
312}
313
314/*
315 * call-seq:
316 * 	socket.connect_nonblock(remote_sockaddr) => 0
317 *
318 * Requests a connection to be made on the given +remote_sockaddr+ after
319 * O_NONBLOCK is set for the underlying file descriptor.
320 * Returns 0 if successful, otherwise an exception is raised.
321 *
322 * === Parameter
323 * * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
324 *
325 * === Example:
326 * 	# Pull down Google's web page
327 * 	require 'socket'
328 * 	include Socket::Constants
329 * 	socket = Socket.new(AF_INET, SOCK_STREAM, 0)
330 * 	sockaddr = Socket.sockaddr_in(80, 'www.google.com')
331 * 	begin # emulate blocking connect
332 * 	  socket.connect_nonblock(sockaddr)
333 * 	rescue IO::WaitWritable
334 * 	  IO.select(nil, [socket]) # wait 3-way handshake completion
335 * 	  begin
336 * 	    socket.connect_nonblock(sockaddr) # check connection failure
337 * 	  rescue Errno::EISCONN
338 * 	  end
339 * 	end
340 * 	socket.write("GET / HTTP/1.0\r\n\r\n")
341 * 	results = socket.read
342 *
343 * Refer to Socket#connect for the exceptions that may be thrown if the call
344 * to _connect_nonblock_ fails.
345 *
346 * Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
347 * including Errno::EINPROGRESS.
348 *
349 * If the exception is Errno::EINPROGRESS,
350 * it is extended by IO::WaitWritable.
351 * So IO::WaitWritable can be used to rescue the exceptions for retrying connect_nonblock.
352 *
353 * === See
354 * * Socket#connect
355 */
356static VALUE
357sock_connect_nonblock(VALUE sock, VALUE addr)
358{
359    rb_io_t *fptr;
360    int n;
361
362    SockAddrStringValue(addr);
363    addr = rb_str_new4(addr);
364    GetOpenFile(sock, fptr);
365    rb_io_set_nonblock(fptr);
366    n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr));
367    if (n < 0) {
368        if (errno == EINPROGRESS)
369            rb_mod_sys_fail(rb_mWaitWritable, "connect(2) would block");
370	rb_sys_fail("connect(2)");
371    }
372
373    return INT2FIX(n);
374}
375
376/*
377 * call-seq:
378 * 	socket.bind(local_sockaddr) => 0
379 *
380 * Binds to the given local address.
381 *
382 * === Parameter
383 * * +local_sockaddr+ - the +struct+ sockaddr contained in a string or an Addrinfo object
384 *
385 * === Example
386 * 	require 'socket'
387 *
388 * 	# use Addrinfo
389 * 	socket = Socket.new(:INET, :STREAM, 0)
390 * 	socket.bind(Addrinfo.tcp("127.0.0.1", 2222))
391 * 	p socket.local_address #=> #<Addrinfo: 127.0.0.1:2222 TCP>
392 *
393 * 	# use struct sockaddr
394 * 	include Socket::Constants
395 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
396 * 	sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
397 * 	socket.bind( sockaddr )
398 *
399 * === Unix-based Exceptions
400 * On unix-based based systems the following system exceptions may be raised if
401 * the call to _bind_ fails:
402 * * Errno::EACCES - the specified _sockaddr_ is protected and the current
403 *   user does not have permission to bind to it
404 * * Errno::EADDRINUSE - the specified _sockaddr_ is already in use
405 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
406 *   local machine
407 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
408 *   the family of the calling +socket+
409 * * Errno::EBADF - the _sockaddr_ specified is not a valid file descriptor
410 * * Errno::EFAULT - the _sockaddr_ argument cannot be accessed
411 * * Errno::EINVAL - the +socket+ is already bound to an address, and the
412 *   protocol does not support binding to the new _sockaddr_ or the +socket+
413 *   has been shut down.
414 * * Errno::EINVAL - the address length is not a valid length for the address
415 *   family
416 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
417 *   PATH_MAX
418 * * Errno::ENOBUFS - no buffer space is available
419 * * Errno::ENOSR - there were insufficient STREAMS resources available to
420 *   complete the operation
421 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
422 * * Errno::EOPNOTSUPP - the socket type of the +socket+ does not support
423 *   binding to an address
424 *
425 * On unix-based based systems if the address family of the calling +socket+ is
426 * Socket::AF_UNIX the follow exceptions may be raised if the call to _bind_
427 * fails:
428 * * Errno::EACCES - search permission is denied for a component of the prefix
429 *   path or write access to the +socket+ is denied
430 * * Errno::EDESTADDRREQ - the _sockaddr_ argument is a null pointer
431 * * Errno::EISDIR - same as Errno::EDESTADDRREQ
432 * * Errno::EIO - an i/o error occurred
433 * * Errno::ELOOP - too many symbolic links were encountered in translating
434 *   the pathname in _sockaddr_
435 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
436 *   characters, or an entire pathname exceeded PATH_MAX characters
437 * * Errno::ENOENT - a component of the pathname does not name an existing file
438 *   or the pathname is an empty string
439 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
440 *   is not a directory
441 * * Errno::EROFS - the name would reside on a read only filesystem
442 *
443 * === Windows Exceptions
444 * On Windows systems the following system exceptions may be raised if
445 * the call to _bind_ fails:
446 * * Errno::ENETDOWN-- the network is down
447 * * Errno::EACCES - the attempt to connect the datagram socket to the
448 *   broadcast address failed
449 * * Errno::EADDRINUSE - the socket's local address is already in use
450 * * Errno::EADDRNOTAVAIL - the specified address is not a valid address for this
451 *   computer
452 * * Errno::EFAULT - the socket's internal address or address length parameter
453 *   is too small or is not a valid part of the user space addressed
454 * * Errno::EINVAL - the +socket+ is already bound to an address
455 * * Errno::ENOBUFS - no buffer space is available
456 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
457 *
458 * === See
459 * * bind manual pages on unix-based systems
460 * * bind function in Microsoft's Winsock functions reference
461 */
462static VALUE
463sock_bind(VALUE sock, VALUE addr)
464{
465    rb_io_t *fptr;
466
467    SockAddrStringValue(addr);
468    GetOpenFile(sock, fptr);
469    if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr)) < 0)
470	rb_sys_fail("bind(2)");
471
472    return INT2FIX(0);
473}
474
475/*
476 * call-seq:
477 * 	socket.listen( int ) => 0
478 *
479 * Listens for connections, using the specified +int+ as the backlog. A call
480 * to _listen_ only applies if the +socket+ is of type SOCK_STREAM or
481 * SOCK_SEQPACKET.
482 *
483 * === Parameter
484 * * +backlog+ - the maximum length of the queue for pending connections.
485 *
486 * === Example 1
487 * 	require 'socket'
488 * 	include Socket::Constants
489 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
490 * 	sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
491 * 	socket.bind( sockaddr )
492 * 	socket.listen( 5 )
493 *
494 * === Example 2 (listening on an arbitrary port, unix-based systems only):
495 * 	require 'socket'
496 * 	include Socket::Constants
497 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
498 * 	socket.listen( 1 )
499 *
500 * === Unix-based Exceptions
501 * On unix based systems the above will work because a new +sockaddr+ struct
502 * is created on the address ADDR_ANY, for an arbitrary port number as handed
503 * off by the kernel. It will not work on Windows, because Windows requires that
504 * the +socket+ is bound by calling _bind_ before it can _listen_.
505 *
506 * If the _backlog_ amount exceeds the implementation-dependent maximum
507 * queue length, the implementation's maximum queue length will be used.
508 *
509 * On unix-based based systems the following system exceptions may be raised if the
510 * call to _listen_ fails:
511 * * Errno::EBADF - the _socket_ argument is not a valid file descriptor
512 * * Errno::EDESTADDRREQ - the _socket_ is not bound to a local address, and
513 *   the protocol does not support listening on an unbound socket
514 * * Errno::EINVAL - the _socket_ is already connected
515 * * Errno::ENOTSOCK - the _socket_ argument does not refer to a socket
516 * * Errno::EOPNOTSUPP - the _socket_ protocol does not support listen
517 * * Errno::EACCES - the calling process does not have appropriate privileges
518 * * Errno::EINVAL - the _socket_ has been shut down
519 * * Errno::ENOBUFS - insufficient resources are available in the system to
520 *   complete the call
521 *
522 * === Windows Exceptions
523 * On Windows systems the following system exceptions may be raised if
524 * the call to _listen_ fails:
525 * * Errno::ENETDOWN - the network is down
526 * * Errno::EADDRINUSE - the socket's local address is already in use. This
527 *   usually occurs during the execution of _bind_ but could be delayed
528 *   if the call to _bind_ was to a partially wildcard address (involving
529 *   ADDR_ANY) and if a specific address needs to be committed at the
530 *   time of the call to _listen_
531 * * Errno::EINPROGRESS - a Windows Sockets 1.1 call is in progress or the
532 *   service provider is still processing a callback function
533 * * Errno::EINVAL - the +socket+ has not been bound with a call to _bind_.
534 * * Errno::EISCONN - the +socket+ is already connected
535 * * Errno::EMFILE - no more socket descriptors are available
536 * * Errno::ENOBUFS - no buffer space is available
537 * * Errno::ENOTSOC - +socket+ is not a socket
538 * * Errno::EOPNOTSUPP - the referenced +socket+ is not a type that supports
539 *   the _listen_ method
540 *
541 * === See
542 * * listen manual pages on unix-based systems
543 * * listen function in Microsoft's Winsock functions reference
544 */
545VALUE
546rsock_sock_listen(VALUE sock, VALUE log)
547{
548    rb_io_t *fptr;
549    int backlog;
550
551    rb_secure(4);
552    backlog = NUM2INT(log);
553    GetOpenFile(sock, fptr);
554    if (listen(fptr->fd, backlog) < 0)
555	rb_sys_fail("listen(2)");
556
557    return INT2FIX(0);
558}
559
560/*
561 * call-seq:
562 * 	socket.recvfrom(maxlen) => [mesg, sender_addrinfo]
563 * 	socket.recvfrom(maxlen, flags) => [mesg, sender_addrinfo]
564 *
565 * Receives up to _maxlen_ bytes from +socket+. _flags_ is zero or more
566 * of the +MSG_+ options. The first element of the results, _mesg_, is the data
567 * received. The second element, _sender_addrinfo_, contains protocol-specific
568 * address information of the sender.
569 *
570 * === Parameters
571 * * +maxlen+ - the maximum number of bytes to receive from the socket
572 * * +flags+ - zero or more of the +MSG_+ options
573 *
574 * === Example
575 * 	# In one file, start this first
576 * 	require 'socket'
577 * 	include Socket::Constants
578 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
579 * 	sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
580 * 	socket.bind( sockaddr )
581 * 	socket.listen( 5 )
582 * 	client, client_addrinfo = socket.accept
583 * 	data = client.recvfrom( 20 )[0].chomp
584 * 	puts "I only received 20 bytes '#{data}'"
585 * 	sleep 1
586 * 	socket.close
587 *
588 * 	# In another file, start this second
589 * 	require 'socket'
590 * 	include Socket::Constants
591 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
592 * 	sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
593 * 	socket.connect( sockaddr )
594 * 	socket.puts "Watch this get cut short!"
595 * 	socket.close
596 *
597 * === Unix-based Exceptions
598 * On unix-based based systems the following system exceptions may be raised if the
599 * call to _recvfrom_ fails:
600 * * Errno::EAGAIN - the +socket+ file descriptor is marked as O_NONBLOCK and no
601 *   data is waiting to be received; or MSG_OOB is set and no out-of-band data
602 *   is available and either the +socket+ file descriptor is marked as
603 *   O_NONBLOCK or the +socket+ does not support blocking to wait for
604 *   out-of-band-data
605 * * Errno::EWOULDBLOCK - see Errno::EAGAIN
606 * * Errno::EBADF - the +socket+ is not a valid file descriptor
607 * * Errno::ECONNRESET - a connection was forcibly closed by a peer
608 * * Errno::EFAULT - the socket's internal buffer, address or address length
609 *   cannot be accessed or written
610 * * Errno::EINTR - a signal interrupted _recvfrom_ before any data was available
611 * * Errno::EINVAL - the MSG_OOB flag is set and no out-of-band data is available
612 * * Errno::EIO - an i/o error occurred while reading from or writing to the
613 *   filesystem
614 * * Errno::ENOBUFS - insufficient resources were available in the system to
615 *   perform the operation
616 * * Errno::ENOMEM - insufficient memory was available to fulfill the request
617 * * Errno::ENOSR - there were insufficient STREAMS resources available to
618 *   complete the operation
619 * * Errno::ENOTCONN - a receive is attempted on a connection-mode socket that
620 *   is not connected
621 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
622 * * Errno::EOPNOTSUPP - the specified flags are not supported for this socket type
623 * * Errno::ETIMEDOUT - the connection timed out during connection establishment
624 *   or due to a transmission timeout on an active connection
625 *
626 * === Windows Exceptions
627 * On Windows systems the following system exceptions may be raised if
628 * the call to _recvfrom_ fails:
629 * * Errno::ENETDOWN - the network is down
630 * * Errno::EFAULT - the internal buffer and from parameters on +socket+ are not
631 *   part of the user address space, or the internal fromlen parameter is
632 *   too small to accommodate the peer address
633 * * Errno::EINTR - the (blocking) call was cancelled by an internal call to
634 *   the WinSock function WSACancelBlockingCall
635 * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
636 *   the service provider is still processing a callback function
637 * * Errno::EINVAL - +socket+ has not been bound with a call to _bind_, or an
638 *   unknown flag was specified, or MSG_OOB was specified for a socket with
639 *   SO_OOBINLINE enabled, or (for byte stream-style sockets only) the internal
640 *   len parameter on +socket+ was zero or negative
641 * * Errno::EISCONN - +socket+ is already connected. The call to _recvfrom_ is
642 *   not permitted with a connected socket on a socket that is connection
643 *   oriented or connectionless.
644 * * Errno::ENETRESET - the connection has been broken due to the keep-alive
645 *   activity detecting a failure while the operation was in progress.
646 * * Errno::EOPNOTSUPP - MSG_OOB was specified, but +socket+ is not stream-style
647 *   such as type SOCK_STREAM. OOB data is not supported in the communication
648 *   domain associated with +socket+, or +socket+ is unidirectional and
649 *   supports only send operations
650 * * Errno::ESHUTDOWN - +socket+ has been shutdown. It is not possible to
651 *   call _recvfrom_ on a socket after _shutdown_ has been invoked.
652 * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and a  call to
653 *   _recvfrom_ would block.
654 * * Errno::EMSGSIZE - the message was too large to fit into the specified buffer
655 *   and was truncated.
656 * * Errno::ETIMEDOUT - the connection has been dropped, because of a network
657 *   failure or because the system on the other end went down without
658 *   notice
659 * * Errno::ECONNRESET - the virtual circuit was reset by the remote side
660 *   executing a hard or abortive close. The application should close the
661 *   socket; it is no longer usable. On a UDP-datagram socket this error
662 *   indicates a previous send operation resulted in an ICMP Port Unreachable
663 *   message.
664 */
665static VALUE
666sock_recvfrom(int argc, VALUE *argv, VALUE sock)
667{
668    return rsock_s_recvfrom(sock, argc, argv, RECV_SOCKET);
669}
670
671/*
672 * call-seq:
673 * 	socket.recvfrom_nonblock(maxlen) => [mesg, sender_addrinfo]
674 * 	socket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_addrinfo]
675 *
676 * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
677 * O_NONBLOCK is set for the underlying file descriptor.
678 * _flags_ is zero or more of the +MSG_+ options.
679 * The first element of the results, _mesg_, is the data received.
680 * The second element, _sender_addrinfo_, contains protocol-specific address
681 * information of the sender.
682 *
683 * When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns
684 * an empty string as data.
685 * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
686 *
687 * === Parameters
688 * * +maxlen+ - the maximum number of bytes to receive from the socket
689 * * +flags+ - zero or more of the +MSG_+ options
690 *
691 * === Example
692 * 	# In one file, start this first
693 * 	require 'socket'
694 * 	include Socket::Constants
695 * 	socket = Socket.new(AF_INET, SOCK_STREAM, 0)
696 * 	sockaddr = Socket.sockaddr_in(2200, 'localhost')
697 * 	socket.bind(sockaddr)
698 * 	socket.listen(5)
699 * 	client, client_addrinfo = socket.accept
700 * 	begin # emulate blocking recvfrom
701 * 	  pair = client.recvfrom_nonblock(20)
702 * 	rescue IO::WaitReadable
703 * 	  IO.select([client])
704 * 	  retry
705 * 	end
706 * 	data = pair[0].chomp
707 * 	puts "I only received 20 bytes '#{data}'"
708 * 	sleep 1
709 * 	socket.close
710 *
711 * 	# In another file, start this second
712 * 	require 'socket'
713 * 	include Socket::Constants
714 * 	socket = Socket.new(AF_INET, SOCK_STREAM, 0)
715 * 	sockaddr = Socket.sockaddr_in(2200, 'localhost')
716 * 	socket.connect(sockaddr)
717 * 	socket.puts "Watch this get cut short!"
718 * 	socket.close
719 *
720 * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
721 * to _recvfrom_nonblock_ fails.
722 *
723 * Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
724 * including Errno::EWOULDBLOCK.
725 *
726 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
727 * it is extended by IO::WaitReadable.
728 * So IO::WaitReadable can be used to rescue the exceptions for retrying recvfrom_nonblock.
729 *
730 * === See
731 * * Socket#recvfrom
732 */
733static VALUE
734sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
735{
736    return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
737}
738
739/*
740 * call-seq:
741 *   socket.accept => [client_socket, client_addrinfo]
742 *
743 * Accepts a next connection.
744 * Returns a new Socket object and Addrinfo object.
745 *
746 *   serv = Socket.new(:INET, :STREAM, 0)
747 *   serv.listen(5)
748 *   c = Socket.new(:INET, :STREAM, 0)
749 *   c.connect(serv.connect_address)
750 *   p serv.accept #=> [#<Socket:fd 6>, #<Addrinfo: 127.0.0.1:48555 TCP>]
751 *
752 */
753static VALUE
754sock_accept(VALUE sock)
755{
756    rb_io_t *fptr;
757    VALUE sock2;
758    struct sockaddr_storage buf;
759    socklen_t len = (socklen_t)sizeof buf;
760
761    GetOpenFile(sock, fptr);
762    sock2 = rsock_s_accept(rb_cSocket,fptr->fd,(struct sockaddr*)&buf,&len);
763
764    return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
765}
766
767/*
768 * call-seq:
769 * 	socket.accept_nonblock => [client_socket, client_addrinfo]
770 *
771 * Accepts an incoming connection using accept(2) after
772 * O_NONBLOCK is set for the underlying file descriptor.
773 * It returns an array containing the accepted socket
774 * for the incoming connection, _client_socket_,
775 * and an Addrinfo, _client_addrinfo_.
776 *
777 * === Example
778 * 	# In one script, start this first
779 * 	require 'socket'
780 * 	include Socket::Constants
781 * 	socket = Socket.new(AF_INET, SOCK_STREAM, 0)
782 * 	sockaddr = Socket.sockaddr_in(2200, 'localhost')
783 * 	socket.bind(sockaddr)
784 * 	socket.listen(5)
785 * 	begin # emulate blocking accept
786 * 	  client_socket, client_addrinfo = socket.accept_nonblock
787 * 	rescue IO::WaitReadable, Errno::EINTR
788 * 	  IO.select([socket])
789 * 	  retry
790 * 	end
791 * 	puts "The client said, '#{client_socket.readline.chomp}'"
792 * 	client_socket.puts "Hello from script one!"
793 * 	socket.close
794 *
795 * 	# In another script, start this second
796 * 	require 'socket'
797 * 	include Socket::Constants
798 * 	socket = Socket.new(AF_INET, SOCK_STREAM, 0)
799 * 	sockaddr = Socket.sockaddr_in(2200, 'localhost')
800 * 	socket.connect(sockaddr)
801 * 	socket.puts "Hello from script 2."
802 * 	puts "The server said, '#{socket.readline.chomp}'"
803 * 	socket.close
804 *
805 * Refer to Socket#accept for the exceptions that may be thrown if the call
806 * to _accept_nonblock_ fails.
807 *
808 * Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
809 * including Errno::EWOULDBLOCK.
810 *
811 * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED or Errno::EPROTO,
812 * it is extended by IO::WaitReadable.
813 * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
814 *
815 * === See
816 * * Socket#accept
817 */
818static VALUE
819sock_accept_nonblock(VALUE sock)
820{
821    rb_io_t *fptr;
822    VALUE sock2;
823    struct sockaddr_storage buf;
824    socklen_t len = (socklen_t)sizeof buf;
825
826    GetOpenFile(sock, fptr);
827    sock2 = rsock_s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)&buf, &len);
828    return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
829}
830
831/*
832 * call-seq:
833 * 	socket.sysaccept => [client_socket_fd, client_addrinfo]
834 *
835 * Accepts an incoming connection returning an array containing the (integer)
836 * file descriptor for the incoming connection, _client_socket_fd_,
837 * and an Addrinfo, _client_addrinfo_.
838 *
839 * === Example
840 * 	# In one script, start this first
841 * 	require 'socket'
842 * 	include Socket::Constants
843 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
844 * 	sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
845 * 	socket.bind( sockaddr )
846 * 	socket.listen( 5 )
847 * 	client_fd, client_addrinfo = socket.sysaccept
848 * 	client_socket = Socket.for_fd( client_fd )
849 * 	puts "The client said, '#{client_socket.readline.chomp}'"
850 * 	client_socket.puts "Hello from script one!"
851 * 	socket.close
852 *
853 * 	# In another script, start this second
854 * 	require 'socket'
855 * 	include Socket::Constants
856 * 	socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
857 * 	sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
858 * 	socket.connect( sockaddr )
859 * 	socket.puts "Hello from script 2."
860 * 	puts "The server said, '#{socket.readline.chomp}'"
861 * 	socket.close
862 *
863 * Refer to Socket#accept for the exceptions that may be thrown if the call
864 * to _sysaccept_ fails.
865 *
866 * === See
867 * * Socket#accept
868 */
869static VALUE
870sock_sysaccept(VALUE sock)
871{
872    rb_io_t *fptr;
873    VALUE sock2;
874    struct sockaddr_storage buf;
875    socklen_t len = (socklen_t)sizeof buf;
876
877    GetOpenFile(sock, fptr);
878    sock2 = rsock_s_accept(0,fptr->fd,(struct sockaddr*)&buf,&len);
879
880    return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
881}
882
883#ifdef HAVE_GETHOSTNAME
884/*
885 * call-seq:
886 *   Socket.gethostname => hostname
887 *
888 * Returns the hostname.
889 *
890 *   p Socket.gethostname #=> "hal"
891 *
892 * Note that it is not guaranteed to be able to convert to IP address using gethostbyname, getaddrinfo, etc.
893 * If you need local IP address, use Socket.ip_address_list.
894 */
895static VALUE
896sock_gethostname(VALUE obj)
897{
898#ifndef HOST_NAME_MAX
899#  define HOST_NAME_MAX 1024
900#endif
901    char buf[HOST_NAME_MAX+1];
902
903    rb_secure(3);
904    if (gethostname(buf, (int)sizeof buf - 1) < 0)
905	rb_sys_fail("gethostname");
906
907    buf[sizeof buf - 1] = '\0';
908    return rb_str_new2(buf);
909}
910#else
911#ifdef HAVE_UNAME
912
913#include <sys/utsname.h>
914
915static VALUE
916sock_gethostname(VALUE obj)
917{
918    struct utsname un;
919
920    rb_secure(3);
921    uname(&un);
922    return rb_str_new2(un.nodename);
923}
924#else
925#define sock_gethostname rb_f_notimplement
926#endif
927#endif
928
929static VALUE
930make_addrinfo(struct addrinfo *res0, int norevlookup)
931{
932    VALUE base, ary;
933    struct addrinfo *res;
934
935    if (res0 == NULL) {
936	rb_raise(rb_eSocket, "host not found");
937    }
938    base = rb_ary_new();
939    for (res = res0; res; res = res->ai_next) {
940	ary = rsock_ipaddr(res->ai_addr, norevlookup);
941	if (res->ai_canonname) {
942	    RARRAY_PTR(ary)[2] = rb_str_new2(res->ai_canonname);
943	}
944	rb_ary_push(ary, INT2FIX(res->ai_family));
945	rb_ary_push(ary, INT2FIX(res->ai_socktype));
946	rb_ary_push(ary, INT2FIX(res->ai_protocol));
947	rb_ary_push(base, ary);
948    }
949    return base;
950}
951
952static VALUE
953sock_sockaddr(struct sockaddr *addr, size_t len)
954{
955    char *ptr;
956
957    switch (addr->sa_family) {
958      case AF_INET:
959	ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
960	len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
961	break;
962#ifdef AF_INET6
963      case AF_INET6:
964	ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
965	len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
966	break;
967#endif
968      default:
969        rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
970	break;
971    }
972    return rb_str_new(ptr, len);
973}
974
975/*
976 * call-seq:
977 *   Socket.gethostbyname(hostname) => [official_hostname, alias_hostnames, address_family, *address_list]
978 *
979 * Obtains the host information for _hostname_.
980 *
981 *   p Socket.gethostbyname("hal") #=> ["localhost", ["hal"], 2, "\x7F\x00\x00\x01"]
982 *
983 */
984static VALUE
985sock_s_gethostbyname(VALUE obj, VALUE host)
986{
987    rb_secure(3);
988    return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
989}
990
991/*
992 * call-seq:
993 *   Socket.gethostbyaddr(address_string [, address_family]) => hostent
994 *
995 * Obtains the host information for _address_.
996 *
997 *   p Socket.gethostbyaddr([221,186,184,68].pack("CCCC"))
998 *   #=> ["carbon.ruby-lang.org", [], 2, "\xDD\xBA\xB8D"]
999 */
1000static VALUE
1001sock_s_gethostbyaddr(int argc, VALUE *argv)
1002{
1003    VALUE addr, family;
1004    struct hostent *h;
1005    char **pch;
1006    VALUE ary, names;
1007    int t = AF_INET;
1008
1009    rb_scan_args(argc, argv, "11", &addr, &family);
1010    StringValue(addr);
1011    if (!NIL_P(family)) {
1012	t = rsock_family_arg(family);
1013    }
1014#ifdef AF_INET6
1015    else if (RSTRING_LEN(addr) == 16) {
1016	t = AF_INET6;
1017    }
1018#endif
1019    h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_LENINT(addr), t);
1020    if (h == NULL) {
1021#ifdef HAVE_HSTRERROR
1022	extern int h_errno;
1023	rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
1024#else
1025	rb_raise(rb_eSocket, "host not found");
1026#endif
1027    }
1028    ary = rb_ary_new();
1029    rb_ary_push(ary, rb_str_new2(h->h_name));
1030    names = rb_ary_new();
1031    rb_ary_push(ary, names);
1032    if (h->h_aliases != NULL) {
1033	for (pch = h->h_aliases; *pch; pch++) {
1034	    rb_ary_push(names, rb_str_new2(*pch));
1035	}
1036    }
1037    rb_ary_push(ary, INT2NUM(h->h_addrtype));
1038#ifdef h_addr
1039    for (pch = h->h_addr_list; *pch; pch++) {
1040	rb_ary_push(ary, rb_str_new(*pch, h->h_length));
1041    }
1042#else
1043    rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
1044#endif
1045
1046    return ary;
1047}
1048
1049/*
1050 * call-seq:
1051 *   Socket.getservbyname(service_name)                => port_number
1052 *   Socket.getservbyname(service_name, protocol_name) => port_number
1053 *
1054 * Obtains the port number for _service_name_.
1055 *
1056 * If _protocol_name_ is not given, "tcp" is assumed.
1057 *
1058 *   Socket.getservbyname("smtp")          #=> 25
1059 *   Socket.getservbyname("shell")         #=> 514
1060 *   Socket.getservbyname("syslog", "udp") #=> 514
1061 */
1062static VALUE
1063sock_s_getservbyname(int argc, VALUE *argv)
1064{
1065    VALUE service, proto;
1066    struct servent *sp;
1067    long port;
1068    const char *servicename, *protoname = "tcp";
1069
1070    rb_scan_args(argc, argv, "11", &service, &proto);
1071    StringValue(service);
1072    if (!NIL_P(proto)) StringValue(proto);
1073    servicename = StringValueCStr(service);
1074    if (!NIL_P(proto)) protoname = StringValueCStr(proto);
1075    sp = getservbyname(servicename, protoname);
1076    if (sp) {
1077	port = ntohs(sp->s_port);
1078    }
1079    else {
1080	char *end;
1081
1082	port = STRTOUL(servicename, &end, 0);
1083	if (*end != '\0') {
1084	    rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
1085	}
1086    }
1087    return INT2FIX(port);
1088}
1089
1090/*
1091 * call-seq:
1092 *   Socket.getservbyport(port [, protocol_name]) => service
1093 *
1094 * Obtains the port number for _port_.
1095 *
1096 * If _protocol_name_ is not given, "tcp" is assumed.
1097 *
1098 *   Socket.getservbyport(80)         #=> "www"
1099 *   Socket.getservbyport(514, "tcp") #=> "shell"
1100 *   Socket.getservbyport(514, "udp") #=> "syslog"
1101 *
1102 */
1103static VALUE
1104sock_s_getservbyport(int argc, VALUE *argv)
1105{
1106    VALUE port, proto;
1107    struct servent *sp;
1108    long portnum;
1109    const char *protoname = "tcp";
1110
1111    rb_scan_args(argc, argv, "11", &port, &proto);
1112    portnum = NUM2LONG(port);
1113    if (portnum != (uint16_t)portnum) {
1114	const char *s = portnum > 0 ? "big" : "small";
1115	rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
1116    }
1117    if (!NIL_P(proto)) protoname = StringValueCStr(proto);
1118
1119    sp = getservbyport((int)htons((uint16_t)portnum), protoname);
1120    if (!sp) {
1121	rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
1122    }
1123    return rb_tainted_str_new2(sp->s_name);
1124}
1125
1126/*
1127 * call-seq:
1128 *   Socket.getaddrinfo(nodename, servname[, family[, socktype[, protocol[, flags[, reverse_lookup]]]]]) => array
1129 *
1130 * Obtains address information for _nodename_:_servname_.
1131 *
1132 * _family_ should be an address family such as: :INET, :INET6, :UNIX, etc.
1133 *
1134 * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
1135 *
1136 * _protocol_ should be a protocol defined in the family,
1137 * and defaults to 0 for the family.
1138 *
1139 * _flags_ should be bitwise OR of Socket::AI_* constants.
1140 *
1141 *   Socket.getaddrinfo("www.ruby-lang.org", "http", nil, :STREAM)
1142 *   #=> [["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68", 2, 1, 6]] # PF_INET/SOCK_STREAM/IPPROTO_TCP
1143 *
1144 *   Socket.getaddrinfo("localhost", nil)
1145 *   #=> [["AF_INET", 0, "localhost", "127.0.0.1", 2, 1, 6],  # PF_INET/SOCK_STREAM/IPPROTO_TCP
1146 *   #    ["AF_INET", 0, "localhost", "127.0.0.1", 2, 2, 17], # PF_INET/SOCK_DGRAM/IPPROTO_UDP
1147 *   #    ["AF_INET", 0, "localhost", "127.0.0.1", 2, 3, 0]]  # PF_INET/SOCK_RAW/IPPROTO_IP
1148 *
1149 * _reverse_lookup_ directs the form of the third element, and has to
1150 * be one of below.  If _reverse_lookup_ is omitted, the default value is +nil+.
1151 *
1152 *   +true+, +:hostname+:  hostname is obtained from numeric address using reverse lookup, which may take a time.
1153 *   +false+, +:numeric+:  hostname is same as numeric address.
1154 *   +nil+:              obey to the current +do_not_reverse_lookup+ flag.
1155 *
1156 * If Addrinfo object is preferred, use Addrinfo.getaddrinfo.
1157 */
1158static VALUE
1159sock_s_getaddrinfo(int argc, VALUE *argv)
1160{
1161    VALUE host, port, family, socktype, protocol, flags, ret, revlookup;
1162    struct addrinfo hints, *res;
1163    int norevlookup;
1164
1165    rb_scan_args(argc, argv, "25", &host, &port, &family, &socktype, &protocol, &flags, &revlookup);
1166
1167    MEMZERO(&hints, struct addrinfo, 1);
1168    hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
1169
1170    if (!NIL_P(socktype)) {
1171	hints.ai_socktype = rsock_socktype_arg(socktype);
1172    }
1173    if (!NIL_P(protocol)) {
1174	hints.ai_protocol = NUM2INT(protocol);
1175    }
1176    if (!NIL_P(flags)) {
1177	hints.ai_flags = NUM2INT(flags);
1178    }
1179    if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
1180	norevlookup = rsock_do_not_reverse_lookup;
1181    }
1182    res = rsock_getaddrinfo(host, port, &hints, 0);
1183
1184    ret = make_addrinfo(res, norevlookup);
1185    freeaddrinfo(res);
1186    return ret;
1187}
1188
1189/*
1190 * call-seq:
1191 *   Socket.getnameinfo(sockaddr [, flags]) => [hostname, servicename]
1192 *
1193 * Obtains name information for _sockaddr_.
1194 *
1195 * _sockaddr_ should be one of follows.
1196 * - packed sockaddr string such as Socket.sockaddr_in(80, "127.0.0.1")
1197 * - 3-elements array such as ["AF_INET", 80, "127.0.0.1"]
1198 * - 4-elements array such as ["AF_INET", 80, ignored, "127.0.0.1"]
1199 *
1200 * _flags_ should be bitwise OR of Socket::NI_* constants.
1201 *
1202 * Note:
1203 * The last form is compatible with IPSocket#addr and IPSocket#peeraddr.
1204 *
1205 *   Socket.getnameinfo(Socket.sockaddr_in(80, "127.0.0.1"))       #=> ["localhost", "www"]
1206 *   Socket.getnameinfo(["AF_INET", 80, "127.0.0.1"])              #=> ["localhost", "www"]
1207 *   Socket.getnameinfo(["AF_INET", 80, "localhost", "127.0.0.1"]) #=> ["localhost", "www"]
1208 *
1209 * If Addrinfo object is preferred, use Addrinfo#getnameinfo.
1210 */
1211static VALUE
1212sock_s_getnameinfo(int argc, VALUE *argv)
1213{
1214    VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
1215    char *hptr, *pptr;
1216    char hbuf[1024], pbuf[1024];
1217    int fl;
1218    struct addrinfo hints, *res = NULL, *r;
1219    int error;
1220    struct sockaddr_storage ss;
1221    struct sockaddr *sap;
1222
1223    sa = flags = Qnil;
1224    rb_scan_args(argc, argv, "11", &sa, &flags);
1225
1226    fl = 0;
1227    if (!NIL_P(flags)) {
1228	fl = NUM2INT(flags);
1229    }
1230    tmp = rb_check_sockaddr_string_type(sa);
1231    if (!NIL_P(tmp)) {
1232	sa = tmp;
1233	if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
1234	    rb_raise(rb_eTypeError, "sockaddr length too big");
1235	}
1236	memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
1237	if ((size_t)RSTRING_LEN(sa) != SS_LEN(&ss)) {
1238	    rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
1239	}
1240	sap = (struct sockaddr*)&ss;
1241	goto call_nameinfo;
1242    }
1243    tmp = rb_check_array_type(sa);
1244    if (!NIL_P(tmp)) {
1245	sa = tmp;
1246	MEMZERO(&hints, struct addrinfo, 1);
1247	if (RARRAY_LEN(sa) == 3) {
1248	    af = RARRAY_PTR(sa)[0];
1249	    port = RARRAY_PTR(sa)[1];
1250	    host = RARRAY_PTR(sa)[2];
1251	}
1252	else if (RARRAY_LEN(sa) >= 4) {
1253	    af = RARRAY_PTR(sa)[0];
1254	    port = RARRAY_PTR(sa)[1];
1255	    host = RARRAY_PTR(sa)[3];
1256	    if (NIL_P(host)) {
1257		host = RARRAY_PTR(sa)[2];
1258	    }
1259	    else {
1260		/*
1261		 * 4th element holds numeric form, don't resolve.
1262		 * see rsock_ipaddr().
1263		 */
1264#ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
1265		hints.ai_flags |= AI_NUMERICHOST;
1266#endif
1267	    }
1268	}
1269	else {
1270	    rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
1271		     RARRAY_LEN(sa));
1272	}
1273	/* host */
1274	if (NIL_P(host)) {
1275	    hptr = NULL;
1276	}
1277	else {
1278	    strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
1279	    hbuf[sizeof(hbuf) - 1] = '\0';
1280	    hptr = hbuf;
1281	}
1282	/* port */
1283	if (NIL_P(port)) {
1284	    strcpy(pbuf, "0");
1285	    pptr = NULL;
1286	}
1287	else if (FIXNUM_P(port)) {
1288	    snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
1289	    pptr = pbuf;
1290	}
1291	else {
1292	    strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
1293	    pbuf[sizeof(pbuf) - 1] = '\0';
1294	    pptr = pbuf;
1295	}
1296	hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
1297	/* af */
1298        hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
1299	error = rb_getaddrinfo(hptr, pptr, &hints, &res);
1300	if (error) goto error_exit_addr;
1301	sap = res->ai_addr;
1302    }
1303    else {
1304	rb_raise(rb_eTypeError, "expecting String or Array");
1305    }
1306
1307  call_nameinfo:
1308    error = rb_getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
1309			   pbuf, sizeof(pbuf), fl);
1310    if (error) goto error_exit_name;
1311    if (res) {
1312	for (r = res->ai_next; r; r = r->ai_next) {
1313	    char hbuf2[1024], pbuf2[1024];
1314
1315	    sap = r->ai_addr;
1316	    error = rb_getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
1317				   pbuf2, sizeof(pbuf2), fl);
1318	    if (error) goto error_exit_name;
1319	    if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
1320		freeaddrinfo(res);
1321		rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
1322	    }
1323	}
1324	freeaddrinfo(res);
1325    }
1326    return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
1327
1328  error_exit_addr:
1329    if (res) freeaddrinfo(res);
1330    rsock_raise_socket_error("getaddrinfo", error);
1331
1332  error_exit_name:
1333    if (res) freeaddrinfo(res);
1334    rsock_raise_socket_error("getnameinfo", error);
1335
1336    UNREACHABLE;
1337}
1338
1339/*
1340 * call-seq:
1341 *   Socket.sockaddr_in(port, host)      => sockaddr
1342 *   Socket.pack_sockaddr_in(port, host) => sockaddr
1343 *
1344 * Packs _port_ and _host_ as an AF_INET/AF_INET6 sockaddr string.
1345 *
1346 *   Socket.sockaddr_in(80, "127.0.0.1")
1347 *   #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1348 *
1349 *   Socket.sockaddr_in(80, "::1")
1350 *   #=> "\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"
1351 *
1352 */
1353static VALUE
1354sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
1355{
1356    struct addrinfo *res = rsock_addrinfo(host, port, 0, 0);
1357    VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
1358
1359    freeaddrinfo(res);
1360    OBJ_INFECT(addr, port);
1361    OBJ_INFECT(addr, host);
1362
1363    return addr;
1364}
1365
1366/*
1367 * call-seq:
1368 *   Socket.unpack_sockaddr_in(sockaddr) => [port, ip_address]
1369 *
1370 * Unpacks _sockaddr_ into port and ip_address.
1371 *
1372 * _sockaddr_ should be a string or an addrinfo for AF_INET/AF_INET6.
1373 *
1374 *   sockaddr = Socket.sockaddr_in(80, "127.0.0.1")
1375 *   p sockaddr #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1376 *   p Socket.unpack_sockaddr_in(sockaddr) #=> [80, "127.0.0.1"]
1377 *
1378 */
1379static VALUE
1380sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
1381{
1382    struct sockaddr_in * sockaddr;
1383    VALUE host;
1384
1385    sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
1386    if (RSTRING_LEN(addr) <
1387        (char*)&((struct sockaddr *)sockaddr)->sa_family +
1388        sizeof(((struct sockaddr *)sockaddr)->sa_family) -
1389        (char*)sockaddr)
1390        rb_raise(rb_eArgError, "too short sockaddr");
1391    if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
1392#ifdef INET6
1393        && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
1394#endif
1395        ) {
1396#ifdef INET6
1397        rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
1398#else
1399        rb_raise(rb_eArgError, "not an AF_INET sockaddr");
1400#endif
1401    }
1402    host = rsock_make_ipaddr((struct sockaddr*)sockaddr);
1403    OBJ_INFECT(host, addr);
1404    return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
1405}
1406
1407#ifdef HAVE_SYS_UN_H
1408
1409/*
1410 * call-seq:
1411 *   Socket.sockaddr_un(path)      => sockaddr
1412 *   Socket.pack_sockaddr_un(path) => sockaddr
1413 *
1414 * Packs _path_ as an AF_UNIX sockaddr string.
1415 *
1416 *   Socket.sockaddr_un("/tmp/sock") #=> "\x01\x00/tmp/sock\x00\x00..."
1417 *
1418 */
1419static VALUE
1420sock_s_pack_sockaddr_un(VALUE self, VALUE path)
1421{
1422    struct sockaddr_un sockaddr;
1423    VALUE addr;
1424
1425    StringValue(path);
1426    MEMZERO(&sockaddr, struct sockaddr_un, 1);
1427    sockaddr.sun_family = AF_UNIX;
1428    if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
1429        rb_raise(rb_eArgError, "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1430            (size_t)RSTRING_LEN(path), sizeof(sockaddr.sun_path));
1431    }
1432    memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
1433    addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path));
1434    OBJ_INFECT(addr, path);
1435
1436    return addr;
1437}
1438
1439/*
1440 * call-seq:
1441 *   Socket.unpack_sockaddr_un(sockaddr) => path
1442 *
1443 * Unpacks _sockaddr_ into path.
1444 *
1445 * _sockaddr_ should be a string or an addrinfo for AF_UNIX.
1446 *
1447 *   sockaddr = Socket.sockaddr_un("/tmp/sock")
1448 *   p Socket.unpack_sockaddr_un(sockaddr) #=> "/tmp/sock"
1449 *
1450 */
1451static VALUE
1452sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
1453{
1454    struct sockaddr_un * sockaddr;
1455    VALUE path;
1456
1457    sockaddr = (struct sockaddr_un*)SockAddrStringValuePtr(addr);
1458    if (RSTRING_LEN(addr) <
1459        (char*)&((struct sockaddr *)sockaddr)->sa_family +
1460        sizeof(((struct sockaddr *)sockaddr)->sa_family) -
1461        (char*)sockaddr)
1462        rb_raise(rb_eArgError, "too short sockaddr");
1463    if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
1464        rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
1465    }
1466    if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
1467	rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
1468		 RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
1469    }
1470    path = rsock_unixpath_str(sockaddr, RSTRING_LENINT(addr));
1471    OBJ_INFECT(path, addr);
1472    return path;
1473}
1474#endif
1475
1476#if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) || defined(_WIN32)
1477static VALUE
1478sockaddr_obj(struct sockaddr *addr)
1479{
1480    socklen_t len;
1481#if defined(AF_INET6) && defined(__KAME__)
1482    struct sockaddr_in6 addr6;
1483#endif
1484
1485    if (addr == NULL)
1486        return Qnil;
1487
1488    switch (addr->sa_family) {
1489      case AF_INET:
1490        len = (socklen_t)sizeof(struct sockaddr_in);
1491        break;
1492
1493#ifdef AF_INET6
1494      case AF_INET6:
1495        len = (socklen_t)sizeof(struct sockaddr_in6);
1496#  ifdef __KAME__
1497	/* KAME uses the 2nd 16bit word of link local IPv6 address as interface index internally */
1498        /* http://orange.kame.net/dev/cvsweb.cgi/kame/IMPLEMENTATION */
1499	/* convert fe80:1::1 to fe80::1%1 */
1500	memcpy(&addr6, addr, len);
1501	addr = (struct sockaddr *)&addr6;
1502	if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
1503	    addr6.sin6_scope_id == 0 &&
1504	    (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
1505	    addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
1506	    addr6.sin6_addr.s6_addr[2] = 0;
1507	    addr6.sin6_addr.s6_addr[3] = 0;
1508	}
1509#  endif
1510        break;
1511#endif
1512
1513#ifdef HAVE_SYS_UN_H
1514      case AF_UNIX:
1515        len = (socklen_t)sizeof(struct sockaddr_un);
1516        break;
1517#endif
1518
1519      default:
1520        len = (socklen_t)sizeof(struct sockaddr_in);
1521        break;
1522    }
1523#ifdef SA_LEN
1524    if (len < (socklen_t)SA_LEN(addr))
1525	len = (socklen_t)SA_LEN(addr);
1526#endif
1527
1528    return rsock_addrinfo_new(addr, len, addr->sa_family, 0, 0, Qnil, Qnil);
1529}
1530#endif
1531
1532#if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)) || defined(SIOCGIFCONF) ||  defined(_WIN32)
1533/*
1534 * call-seq:
1535 *   Socket.ip_address_list => array
1536 *
1537 * Returns local IP addresses as an array.
1538 *
1539 * The array contains Addrinfo objects.
1540 *
1541 *  pp Socket.ip_address_list
1542 *  #=> [#<Addrinfo: 127.0.0.1>,
1543 *       #<Addrinfo: 192.168.0.128>,
1544 *       #<Addrinfo: ::1>,
1545 *       ...]
1546 *
1547 */
1548static VALUE
1549socket_s_ip_address_list(VALUE self)
1550{
1551#if defined(HAVE_GETIFADDRS)
1552    struct ifaddrs *ifp = NULL;
1553    struct ifaddrs *p;
1554    int ret;
1555    VALUE list;
1556
1557    ret = getifaddrs(&ifp);
1558    if (ret == -1) {
1559        rb_sys_fail("getifaddrs");
1560    }
1561
1562    list = rb_ary_new();
1563    for (p = ifp; p; p = p->ifa_next) {
1564        if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
1565            rb_ary_push(list, sockaddr_obj(p->ifa_addr));
1566        }
1567    }
1568
1569    freeifaddrs(ifp);
1570
1571    return list;
1572#elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)
1573    /* Solaris if_tcp(7P) */
1574    /* HP-UX has SIOCGLIFCONF too.  But it uses different struct */
1575    int fd = -1;
1576    int ret;
1577    struct lifnum ln;
1578    struct lifconf lc;
1579    char *reason = NULL;
1580    int save_errno;
1581    int i;
1582    VALUE list = Qnil;
1583
1584    lc.lifc_buf = NULL;
1585
1586    fd = socket(AF_INET, SOCK_DGRAM, 0);
1587    if (fd == -1)
1588        rb_sys_fail("socket");
1589
1590    memset(&ln, 0, sizeof(ln));
1591    ln.lifn_family = AF_UNSPEC;
1592
1593    ret = ioctl(fd, SIOCGLIFNUM, &ln);
1594    if (ret == -1) {
1595	reason = "SIOCGLIFNUM";
1596	goto finish;
1597    }
1598
1599    memset(&lc, 0, sizeof(lc));
1600    lc.lifc_family = AF_UNSPEC;
1601    lc.lifc_flags = 0;
1602    lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
1603    lc.lifc_req = xmalloc(lc.lifc_len);
1604
1605    ret = ioctl(fd, SIOCGLIFCONF, &lc);
1606    if (ret == -1) {
1607	reason = "SIOCGLIFCONF";
1608	goto finish;
1609    }
1610
1611    list = rb_ary_new();
1612    for (i = 0; i < ln.lifn_count; i++) {
1613	struct lifreq *req = &lc.lifc_req[i];
1614        if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
1615            if (req->lifr_addr.ss_family == AF_INET6 &&
1616                IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
1617                ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
1618                struct lifreq req2;
1619                memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
1620                ret = ioctl(fd, SIOCGLIFINDEX, &req2);
1621                if (ret == -1) {
1622                    reason = "SIOCGLIFINDEX";
1623                    goto finish;
1624                }
1625                ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
1626            }
1627            rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr));
1628        }
1629    }
1630
1631  finish:
1632    save_errno = errno;
1633    if (lc.lifc_buf != NULL)
1634	xfree(lc.lifc_req);
1635    if (fd != -1)
1636	close(fd);
1637    errno = save_errno;
1638
1639    if (reason)
1640	rb_sys_fail(reason);
1641    return list;
1642
1643#elif defined(SIOCGIFCONF)
1644    int fd = -1;
1645    int ret;
1646#define EXTRA_SPACE (sizeof(struct ifconf) + sizeof(struct sockaddr_storage))
1647    char initbuf[4096+EXTRA_SPACE];
1648    char *buf = initbuf;
1649    int bufsize;
1650    struct ifconf conf;
1651    struct ifreq *req;
1652    VALUE list = Qnil;
1653    const char *reason = NULL;
1654    int save_errno;
1655
1656    fd = socket(AF_INET, SOCK_DGRAM, 0);
1657    if (fd == -1)
1658        rb_sys_fail("socket");
1659
1660    bufsize = sizeof(initbuf);
1661    buf = initbuf;
1662
1663  retry:
1664    conf.ifc_len = bufsize;
1665    conf.ifc_req = (struct ifreq *)buf;
1666
1667    /* fprintf(stderr, "bufsize: %d\n", bufsize); */
1668
1669    ret = ioctl(fd, SIOCGIFCONF, &conf);
1670    if (ret == -1) {
1671        reason = "SIOCGIFCONF";
1672        goto finish;
1673    }
1674
1675    /* fprintf(stderr, "conf.ifc_len: %d\n", conf.ifc_len); */
1676
1677    if (bufsize - EXTRA_SPACE < conf.ifc_len) {
1678	if (bufsize < conf.ifc_len) {
1679	    /* NetBSD returns required size for all interfaces. */
1680	    bufsize = conf.ifc_len + EXTRA_SPACE;
1681	}
1682	else {
1683	    bufsize = bufsize << 1;
1684	}
1685	if (buf == initbuf)
1686	    buf = NULL;
1687	buf = xrealloc(buf, bufsize);
1688	goto retry;
1689    }
1690
1691    close(fd);
1692    fd = -1;
1693
1694    list = rb_ary_new();
1695    req = conf.ifc_req;
1696    while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
1697	struct sockaddr *addr = &req->ifr_addr;
1698        if (IS_IP_FAMILY(addr->sa_family)) {
1699	    rb_ary_push(list, sockaddr_obj(addr));
1700	}
1701#ifdef HAVE_SA_LEN
1702# ifndef _SIZEOF_ADDR_IFREQ
1703#  define _SIZEOF_ADDR_IFREQ(r) \
1704          (sizeof(struct ifreq) + \
1705           (sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
1706            (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
1707            0))
1708# endif
1709	req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
1710#else
1711	req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
1712#endif
1713    }
1714
1715  finish:
1716
1717    save_errno = errno;
1718    if (buf != initbuf)
1719        xfree(buf);
1720    if (fd != -1)
1721	close(fd);
1722    errno = save_errno;
1723
1724    if (reason)
1725	rb_sys_fail(reason);
1726    return list;
1727
1728#undef EXTRA_SPACE
1729#elif defined(_WIN32)
1730    typedef struct ip_adapter_unicast_address_st {
1731	unsigned LONG_LONG dummy0;
1732	struct ip_adapter_unicast_address_st *Next;
1733	struct {
1734	    struct sockaddr *lpSockaddr;
1735	    int iSockaddrLength;
1736	} Address;
1737	int dummy1;
1738	int dummy2;
1739	int dummy3;
1740	long dummy4;
1741	long dummy5;
1742	long dummy6;
1743    } ip_adapter_unicast_address_t;
1744    typedef struct ip_adapter_anycast_address_st {
1745	unsigned LONG_LONG dummy0;
1746	struct ip_adapter_anycast_address_st *Next;
1747	struct {
1748	    struct sockaddr *lpSockaddr;
1749	    int iSockaddrLength;
1750	} Address;
1751    } ip_adapter_anycast_address_t;
1752    typedef struct ip_adapter_addresses_st {
1753	unsigned LONG_LONG dummy0;
1754	struct ip_adapter_addresses_st *Next;
1755	void *dummy1;
1756	ip_adapter_unicast_address_t *FirstUnicastAddress;
1757	ip_adapter_anycast_address_t *FirstAnycastAddress;
1758	void *dummy2;
1759	void *dummy3;
1760	void *dummy4;
1761	void *dummy5;
1762	void *dummy6;
1763	BYTE dummy7[8];
1764	DWORD dummy8;
1765	DWORD dummy9;
1766	DWORD dummy10;
1767	DWORD IfType;
1768	int OperStatus;
1769	DWORD dummy12;
1770	DWORD dummy13[16];
1771	void *dummy14;
1772    } ip_adapter_addresses_t;
1773    typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
1774    HMODULE h;
1775    GetAdaptersAddresses_t pGetAdaptersAddresses;
1776    ULONG len;
1777    DWORD ret;
1778    ip_adapter_addresses_t *adapters;
1779    VALUE list;
1780
1781    h = LoadLibrary("iphlpapi.dll");
1782    if (!h)
1783	rb_notimplement();
1784    pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
1785    if (!pGetAdaptersAddresses) {
1786	FreeLibrary(h);
1787	rb_notimplement();
1788    }
1789
1790    ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
1791    if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
1792	errno = rb_w32_map_errno(ret);
1793	FreeLibrary(h);
1794	rb_sys_fail("GetAdaptersAddresses");
1795    }
1796    adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
1797    ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
1798    if (ret != ERROR_SUCCESS) {
1799	errno = rb_w32_map_errno(ret);
1800	FreeLibrary(h);
1801	rb_sys_fail("GetAdaptersAddresses");
1802    }
1803
1804    list = rb_ary_new();
1805    for (; adapters; adapters = adapters->Next) {
1806	ip_adapter_unicast_address_t *uni;
1807	ip_adapter_anycast_address_t *any;
1808	if (adapters->OperStatus != 1)	/* 1 means IfOperStatusUp */
1809	    continue;
1810	for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
1811#ifndef INET6
1812	    if (uni->Address.lpSockaddr->sa_family == AF_INET)
1813#else
1814	    if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
1815#endif
1816		rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr));
1817	}
1818	for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
1819#ifndef INET6
1820	    if (any->Address.lpSockaddr->sa_family == AF_INET)
1821#else
1822	    if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
1823#endif
1824		rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr));
1825	}
1826    }
1827
1828    FreeLibrary(h);
1829    return list;
1830#endif
1831}
1832#else
1833#define socket_s_ip_address_list rb_f_notimplement
1834#endif
1835
1836void
1837Init_socket()
1838{
1839    rsock_init_basicsocket();
1840
1841    /*
1842     * Document-class: Socket < BasicSocket
1843     *
1844     * Class +Socket+ provides access to the underlying operating system
1845     * socket implementations.  It can be used to provide more operating system
1846     * specific functionality than the protocol-specific socket classes.
1847     *
1848     * The constants defined under Socket::Constants are also defined under
1849     * Socket.  For example, Socket::AF_INET is usable as well as
1850     * Socket::Constants::AF_INET.  See Socket::Constants for the list of
1851     * constants.
1852     *
1853     * === What's a socket?
1854     *
1855     * Sockets are endpoints of a bidirectionnal communication channel.
1856     * Sockets can communicate within a process, between processes on the same
1857     * machine or between different machines.  There are many types of socket:
1858     * TCPSocket, UDPSocket or UNIXSocket for example.
1859     *
1860     * Sockets have their own vocabulary:
1861     *
1862     * *domain:*
1863     * The family of protocols:
1864     * *    Socket::PF_INET
1865     * *    Socket::PF_INET6
1866     * *    Socket::PF_UNIX
1867     * *    etc.
1868     *
1869     * *type:*
1870     * The type of communications between the two endpoints, typically
1871     * *    Socket::SOCK_STREAM
1872     * *    Socket::SOCK_DGRAM.
1873     *
1874     * *protocol:*
1875     * Typically _zero_.
1876     * This may be used to identify a variant of a protocol.
1877     *
1878     * *hostname:*
1879     * The identifier of a network interface:
1880     * *    a string (hostname, IPv4 or IPv6 adress or +broadcast+
1881     *	    which specifies a broadcast address)
1882     * *    a zero-length string which specifies INADDR_ANY
1883     * *    an integer (interpreted as binary address in host byte order).
1884     *
1885     * === Quick start
1886     *
1887     * Many of the classes, such as TCPSocket, UDPSocket or UNIXSocket,
1888     * ease the use of sockets comparatively to the equivalent C programming interface.
1889     *
1890     * Let's create an internet socket using the IPv4 protocol in a C-like manner:
1891     *
1892     *   s = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
1893     *   s.connect Socket.pack_sockaddr_in(80, 'example.com')
1894     *
1895     * You could also use the TCPSocket class:
1896     *
1897     *   s = TCPSocket.new 'example.com', 80
1898     *
1899     * A simple server might look like this:
1900     *
1901     *   require 'socket'
1902     *
1903     *   server = TCPServer.new 2000 # Server bound to port 2000
1904     *
1905     *   loop do
1906     *     client = server.accept    # Wait for a client to connect
1907     *     client.puts "Hello !"
1908     *     client.puts "Time is #{Time.now}"
1909     *     client.close
1910     *   end
1911     *
1912     * A simple client may look like this:
1913     *
1914     *   require 'socket'
1915     *
1916     *   s = TCPSocket.new 'localhost', 2000
1917     *
1918     *   while line = s.gets # Read lines from socket
1919     *     puts line         # and print them
1920     *   end
1921     *
1922     *   s.close             # close socket when done
1923     *
1924     * === Exception Handling
1925     *
1926     * Ruby's Socket implementation raises exceptions based on the error
1927     * generated by the system dependent implementation.  This is why the
1928     * methods are documented in a way that isolate Unix-based system
1929     * exceptions from Windows based exceptions. If more information on a
1930     * particular exception is needed, please refer to the Unix manual pages or
1931     * the Windows WinSock reference.
1932     *
1933     * === Convenience methods
1934     *
1935     * Although the general way to create socket is Socket.new,
1936     * there are several methods of socket creation for most cases.
1937     *
1938     * TCP client socket::
1939     *   Socket.tcp, TCPSocket.open
1940     * TCP server socket::
1941     *   Socket.tcp_server_loop, TCPServer.open
1942     * UNIX client socket::
1943     *   Socket.unix, UNIXSocket.open
1944     * UNIX server socket::
1945     *   Socket.unix_server_loop, UNIXServer.open
1946     *
1947     * === Documentation by
1948     *
1949     * * Zach Dennis
1950     * * Sam Roberts
1951     * * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
1952     *
1953     * Much material in this documentation is taken with permission from
1954     * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
1955     */
1956    rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
1957
1958    rsock_init_socket_init();
1959
1960    rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
1961    rb_define_method(rb_cSocket, "connect", sock_connect, 1);
1962    rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
1963    rb_define_method(rb_cSocket, "bind", sock_bind, 1);
1964    rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
1965    rb_define_method(rb_cSocket, "accept", sock_accept, 0);
1966    rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
1967    rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
1968
1969    rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
1970    rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
1971
1972    rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1);
1973    rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1);
1974    rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
1975    rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
1976    rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
1977    rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);
1978    rb_define_singleton_method(rb_cSocket, "getservbyport", sock_s_getservbyport, -1);
1979    rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
1980    rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
1981    rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
1982    rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
1983    rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
1984#ifdef HAVE_SYS_UN_H
1985    rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
1986    rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
1987    rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
1988#endif
1989
1990    rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0);
1991}
1992