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