Ruby  2.0.0p451(2014-02-24revision45167)
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_ 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  */
38 static VALUE
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
58 static VALUE
60 {
61  return rb_funcall(io, rb_intern("close"), 0, 0);
62 }
63 
64 static VALUE
65 io_close(VALUE io)
66 {
67  return rb_rescue(io_call_close, io, 0, 0);
68 }
69 
70 static VALUE
71 pair_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 
79 static int
80 rsock_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 
117 static int
118 rsock_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  */
152 VALUE
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  */
296 static VALUE
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  */
356 static VALUE
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  */
462 static VALUE
463 sock_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  */
545 VALUE
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  */
665 static VALUE
666 sock_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  */
733 static VALUE
734 sock_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  */
753 static VALUE
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  */
818 static VALUE
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  */
869 static VALUE
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  */
895 static VALUE
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 
915 static VALUE
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 
929 static VALUE
930 make_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 
952 static VALUE
953 sock_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  */
984 static VALUE
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  */
1000 static VALUE
1001 sock_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  */
1062 static VALUE
1063 sock_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  */
1103 static VALUE
1104 sock_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  */
1158 static VALUE
1159 sock_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  */
1211 static VALUE
1212 sock_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  }
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  */
1353 static VALUE
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  */
1379 static VALUE
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  */
1419 static VALUE
1420 sock_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  */
1451 static VALUE
1452 sock_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)
1477 static VALUE
1478 sockaddr_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  */
1548 static VALUE
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 
1836 void
1838 {
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  */
1957 
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);
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 
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 
1991 }
struct addrinfo * rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
Definition: raddrinfo.c:379
static VALUE sock_s_getservbyport(int argc, VALUE *argv)
Definition: socket.c:1104
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1101
int ioctl(int, int,...)
Definition: win32.c:2438
#define Next(p, e, enc)
Definition: dir.c:98
#define OBJ_INFECT(x, s)
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2338
int i
Definition: win32ole.c:784
unsigned long VALUE
Definition: ripper.y:104
VALUE rb_cBasicSocket
Definition: init.c:13
#define rb_tainted_str_new2
#define SockAddrStringValue(v)
Definition: rubysocket.h:208
static VALUE io_call_close(VALUE io)
Definition: io.c:4279
static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
Definition: socket.c:39
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
#define SA_LEN(sa)
Definition: sockport.h:29
#define NI_DGRAM
Definition: addrinfo.h:128
void rb_secure(int)
Definition: safe.c:79
Definition: io.h:63
int rsock_socktype_arg(VALUE type)
Definition: constants.c:50
VALUE rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup)
Definition: raddrinfo.c:391
VALUE rb_eTypeError
Definition: error.c:511
#define UNREACHABLE
Definition: ruby.h:40
st_table * names
Definition: encoding.c:53
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
VALUE rsock_init_sock(VALUE sock, int fd)
Definition: init.c:43
#define RSTRING_PTR(str)
static VALUE sock_s_getaddrinfo(int argc, VALUE *argv)
Definition: socket.c:1159
#define xfree
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:773
#define Qnil
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
#define rb_str_new4
VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:562
VALUE rb_check_sockaddr_string_type(VALUE val)
Definition: raddrinfo.c:2156
#define rb_str_new2
#define AI_CANONNAME
Definition: addrinfo.h:97
static VALUE sock_accept(VALUE sock)
Definition: socket.c:754
#define EINPROGRESS
Definition: win32.h:477
#define STRTOUL(str, endptr, base)
int rb_w32_map_errno(DWORD)
Definition: win32.c:223
#define GetOpenFile(obj, fp)
Definition: io.h:120
static const unsigned char dv[]
Definition: nkf.c:586
static VALUE sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
Definition: socket.c:1380
VALUE rsock_make_ipaddr(struct sockaddr *addr)
Definition: raddrinfo.c:251
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2183
VALUE rb_eRangeError
Definition: error.c:515
void rb_fd_fix_cloexec(int fd)
Definition: io.c:202
RUBY_EXTERN VALUE rb_mWaitWritable
Definition: ripper.y:1423
Win32OLEIDispatch * p
Definition: win32ole.c:786
VALUE rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE(*ipaddr)(struct sockaddr *, size_t))
Definition: raddrinfo.c:532
#define MEMZERO(p, type, n)
static VALUE sock_s_getnameinfo(int argc, VALUE *argv)
Definition: socket.c:1212
static VALUE sock_connect_nonblock(VALUE sock, VALUE addr)
Definition: socket.c:357
VALUE rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, int family, int socktype, int protocol, VALUE canonname, VALUE inspectname)
Definition: raddrinfo.c:629
static VALUE sock_recvfrom(int argc, VALUE *argv, VALUE sock)
Definition: socket.c:666
void rb_gc(void)
Definition: gc.c:3110
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:763
#define FIXNUM_P(f)
int rb_block_given_p(void)
Definition: eval.c:672
static VALUE sock_sockaddr(struct sockaddr *addr, size_t len)
Definition: socket.c:953
#define RARRAY_LEN(a)
int rsock_family_arg(VALUE domain)
Definition: constants.c:43
#define StringValuePtr(v)
IUnknown DWORD
Definition: win32ole.c:149
static VALUE sock_sysaccept(VALUE sock)
Definition: socket.c:870
VALUE rb_ary_new(void)
Definition: array.c:424
#define StringValueCStr(v)
#define PRIuSIZE
int rsock_socket(int domain, int type, int proto)
Definition: init.c:276
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
#define RSTRING_LEN(str)
#define INT2FIX(i)
int fd
Definition: io.h:64
char * ai_canonname
Definition: addrinfo.h:137
#define sock_gethostname
Definition: socket.c:925
#define xmalloc
#define xrealloc
int argc
Definition: ruby.c:130
#define NIL_P(v)
void rsock_init_socket_init()
Definition: init.c:609
#define ALLOCA_N(type, n)
VALUE rb_cSocket
Definition: init.c:22
#define SockAddrStringValuePtr(v)
Definition: rubysocket.h:209
VALUE rb_yield(VALUE)
Definition: vm_eval.c:933
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:117
VALUE rsock_sock_listen(VALUE sock, VALUE log)
Definition: socket.c:546
int errno
VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:106
#define StringValue(v)
static VALUE io_close(VALUE io)
Definition: io.c:4285
static void setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
Definition: socket.c:14
void freeaddrinfo(struct addrinfo *ai)
Definition: getaddrinfo.c:211
static VALUE sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
Definition: socket.c:1354
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:545
#define RARRAY_PTR(a)
void rsock_init_basicsocket(void)
Definition: basicsocket.c:744
int rsock_do_not_reverse_lookup
Definition: init.c:31
int type
Definition: tcltklib.c:111
#define AI_NUMERICHOST
Definition: addrinfo.h:98
static VALUE make_addrinfo(struct addrinfo *res0, int norevlookup)
Definition: socket.c:930
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
static VALUE sock_connect(VALUE sock, VALUE addr)
Definition: socket.c:297
void rb_sys_fail(const char *mesg)
Definition: error.c:1899
int ai_protocol
Definition: addrinfo.h:135
int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
Definition: raddrinfo.c:218
VALUE rb_eSocket
Definition: init.c:25
#define NUM2LONG(x)
#define PF_UNSPEC
Definition: sockport.h:73
int ai_socktype
Definition: addrinfo.h:134
int rsock_revlookup_flag(VALUE revlookup, int *norevlookup)
Definition: ipsocket.c:140
void rb_mod_sys_fail(VALUE mod, const char *mesg)
Definition: error.c:1911
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:557
#define proto(p)
Definition: sdbm.h:60
void rsock_raise_socket_error(const char *reason, int error)
Definition: init.c:34
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
Definition: init.c:377
void Init_socket()
Definition: socket.c:1837
#define AF_UNSPEC
Definition: sockport.h:69
struct addrinfo * rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
Definition: raddrinfo.c:351
#define INT2NUM(x)
struct rb_encoding_entry * list
Definition: encoding.c:50
static VALUE sock_bind(VALUE sock, VALUE addr)
Definition: socket.c:463
void rb_notimplement(void)
Definition: error.c:1826
VALUE rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:522
struct addrinfo * ai_next
Definition: addrinfo.h:139
#define RSTRING_LENINT(str)
VALUE rb_str_new(const char *, long)
Definition: string.c:425
#define NUM2INT(x)
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1721
static VALUE sock_s_getservbyname(int argc, VALUE *argv)
Definition: socket.c:1063
#define SS_LEN(ss)
Definition: sockport.h:30
size_t ai_addrlen
Definition: addrinfo.h:136
#define rsock_sock_s_socketpair
Definition: socket.c:182
#define snprintf
static VALUE sock_s_gethostbyaddr(int argc, VALUE *argv)
Definition: socket.c:1001
#define rb_intern(str)
int ai_flags
Definition: addrinfo.h:132
#define NULL
Definition: _sdbm.c:103
VALUE rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:174
int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
Definition: raddrinfo.c:175
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
static ULONG(STDMETHODCALLTYPE AddRef)(IDispatch __RPC_FAR *This)
Definition: win32ole.c:614
struct sockaddr * ai_addr
Definition: addrinfo.h:138
VALUE rb_eArgError
Definition: error.c:512
static VALUE sock_s_gethostbyname(VALUE obj, VALUE host)
Definition: socket.c:985
static VALUE sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
Definition: socket.c:734
char ** argv
Definition: ruby.c:131
static VALUE sock_accept_nonblock(VALUE sock)
Definition: socket.c:819
#define socket_s_ip_address_list
Definition: socket.c:1833
int ai_family
Definition: addrinfo.h:133