Ruby  2.0.0p598(2014-11-13revision48408)
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, res->ai_addrlen, 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, saved_errno;
1220  struct sockaddr_storage ss;
1221  struct sockaddr *sap;
1222  socklen_t salen;
1223 
1224  sa = flags = Qnil;
1225  rb_scan_args(argc, argv, "11", &sa, &flags);
1226 
1227  fl = 0;
1228  if (!NIL_P(flags)) {
1229  fl = NUM2INT(flags);
1230  }
1232  if (!NIL_P(tmp)) {
1233  sa = tmp;
1234  if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
1235  rb_raise(rb_eTypeError, "sockaddr length too big");
1236  }
1237  memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
1238  if ((size_t)RSTRING_LEN(sa) != SS_LEN(&ss)) {
1239  rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
1240  }
1241  sap = (struct sockaddr*)&ss;
1242  salen = RSTRING_LEN(sa);
1243  goto call_nameinfo;
1244  }
1245  tmp = rb_check_array_type(sa);
1246  if (!NIL_P(tmp)) {
1247  sa = tmp;
1248  MEMZERO(&hints, struct addrinfo, 1);
1249  if (RARRAY_LEN(sa) == 3) {
1250  af = RARRAY_PTR(sa)[0];
1251  port = RARRAY_PTR(sa)[1];
1252  host = RARRAY_PTR(sa)[2];
1253  }
1254  else if (RARRAY_LEN(sa) >= 4) {
1255  af = RARRAY_PTR(sa)[0];
1256  port = RARRAY_PTR(sa)[1];
1257  host = RARRAY_PTR(sa)[3];
1258  if (NIL_P(host)) {
1259  host = RARRAY_PTR(sa)[2];
1260  }
1261  else {
1262  /*
1263  * 4th element holds numeric form, don't resolve.
1264  * see rsock_ipaddr().
1265  */
1266 #ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
1267  hints.ai_flags |= AI_NUMERICHOST;
1268 #endif
1269  }
1270  }
1271  else {
1272  rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
1273  RARRAY_LEN(sa));
1274  }
1275  /* host */
1276  if (NIL_P(host)) {
1277  hptr = NULL;
1278  }
1279  else {
1280  strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
1281  hbuf[sizeof(hbuf) - 1] = '\0';
1282  hptr = hbuf;
1283  }
1284  /* port */
1285  if (NIL_P(port)) {
1286  strcpy(pbuf, "0");
1287  pptr = NULL;
1288  }
1289  else if (FIXNUM_P(port)) {
1290  snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
1291  pptr = pbuf;
1292  }
1293  else {
1294  strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
1295  pbuf[sizeof(pbuf) - 1] = '\0';
1296  pptr = pbuf;
1297  }
1298  hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
1299  /* af */
1300  hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
1301  error = rb_getaddrinfo(hptr, pptr, &hints, &res);
1302  if (error) goto error_exit_addr;
1303  sap = res->ai_addr;
1304  salen = res->ai_addrlen;
1305  }
1306  else {
1307  rb_raise(rb_eTypeError, "expecting String or Array");
1308  }
1309 
1310  call_nameinfo:
1311  error = rb_getnameinfo(sap, salen, hbuf, sizeof(hbuf),
1312  pbuf, sizeof(pbuf), fl);
1313  if (error) goto error_exit_name;
1314  if (res) {
1315  for (r = res->ai_next; r; r = r->ai_next) {
1316  char hbuf2[1024], pbuf2[1024];
1317 
1318  sap = r->ai_addr;
1319  salen = r->ai_addrlen;
1320  error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2),
1321  pbuf2, sizeof(pbuf2), fl);
1322  if (error) goto error_exit_name;
1323  if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
1324  freeaddrinfo(res);
1325  rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
1326  }
1327  }
1328  freeaddrinfo(res);
1329  }
1330  return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
1331 
1332  error_exit_addr:
1333  saved_errno = errno;
1334  if (res) freeaddrinfo(res);
1335  errno = saved_errno;
1336  rsock_raise_socket_error("getaddrinfo", error);
1337 
1338  error_exit_name:
1339  saved_errno = errno;
1340  if (res) freeaddrinfo(res);
1341  errno = saved_errno;
1342  rsock_raise_socket_error("getnameinfo", error);
1343 
1344  UNREACHABLE;
1345 }
1346 
1347 /*
1348  * call-seq:
1349  * Socket.sockaddr_in(port, host) => sockaddr
1350  * Socket.pack_sockaddr_in(port, host) => sockaddr
1351  *
1352  * Packs _port_ and _host_ as an AF_INET/AF_INET6 sockaddr string.
1353  *
1354  * Socket.sockaddr_in(80, "127.0.0.1")
1355  * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1356  *
1357  * Socket.sockaddr_in(80, "::1")
1358  * #=> "\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"
1359  *
1360  */
1361 static VALUE
1363 {
1364  struct addrinfo *res = rsock_addrinfo(host, port, 0, 0);
1365  VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
1366 
1367  freeaddrinfo(res);
1368  OBJ_INFECT(addr, port);
1369  OBJ_INFECT(addr, host);
1370 
1371  return addr;
1372 }
1373 
1374 /*
1375  * call-seq:
1376  * Socket.unpack_sockaddr_in(sockaddr) => [port, ip_address]
1377  *
1378  * Unpacks _sockaddr_ into port and ip_address.
1379  *
1380  * _sockaddr_ should be a string or an addrinfo for AF_INET/AF_INET6.
1381  *
1382  * sockaddr = Socket.sockaddr_in(80, "127.0.0.1")
1383  * p sockaddr #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1384  * p Socket.unpack_sockaddr_in(sockaddr) #=> [80, "127.0.0.1"]
1385  *
1386  */
1387 static VALUE
1389 {
1390  struct sockaddr_in * sockaddr;
1391  VALUE host;
1392 
1393  sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
1394  if (RSTRING_LEN(addr) <
1395  (char*)&((struct sockaddr *)sockaddr)->sa_family +
1396  sizeof(((struct sockaddr *)sockaddr)->sa_family) -
1397  (char*)sockaddr)
1398  rb_raise(rb_eArgError, "too short sockaddr");
1399  if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
1400 #ifdef INET6
1401  && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
1402 #endif
1403  ) {
1404 #ifdef INET6
1405  rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
1406 #else
1407  rb_raise(rb_eArgError, "not an AF_INET sockaddr");
1408 #endif
1409  }
1410  host = rsock_make_ipaddr((struct sockaddr*)sockaddr, RSTRING_LEN(addr));
1411  OBJ_INFECT(host, addr);
1412  return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
1413 }
1414 
1415 #ifdef HAVE_SYS_UN_H
1416 
1417 /*
1418  * call-seq:
1419  * Socket.sockaddr_un(path) => sockaddr
1420  * Socket.pack_sockaddr_un(path) => sockaddr
1421  *
1422  * Packs _path_ as an AF_UNIX sockaddr string.
1423  *
1424  * Socket.sockaddr_un("/tmp/sock") #=> "\x01\x00/tmp/sock\x00\x00..."
1425  *
1426  */
1427 static VALUE
1428 sock_s_pack_sockaddr_un(VALUE self, VALUE path)
1429 {
1430  struct sockaddr_un sockaddr;
1431  VALUE addr;
1432 
1433  StringValue(path);
1434  MEMZERO(&sockaddr, struct sockaddr_un, 1);
1435  sockaddr.sun_family = AF_UNIX;
1436  if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
1437  rb_raise(rb_eArgError, "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1438  (size_t)RSTRING_LEN(path), sizeof(sockaddr.sun_path));
1439  }
1440  memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
1441  addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path));
1442  OBJ_INFECT(addr, path);
1443 
1444  return addr;
1445 }
1446 
1447 /*
1448  * call-seq:
1449  * Socket.unpack_sockaddr_un(sockaddr) => path
1450  *
1451  * Unpacks _sockaddr_ into path.
1452  *
1453  * _sockaddr_ should be a string or an addrinfo for AF_UNIX.
1454  *
1455  * sockaddr = Socket.sockaddr_un("/tmp/sock")
1456  * p Socket.unpack_sockaddr_un(sockaddr) #=> "/tmp/sock"
1457  *
1458  */
1459 static VALUE
1460 sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
1461 {
1462  struct sockaddr_un * sockaddr;
1463  VALUE path;
1464 
1465  sockaddr = (struct sockaddr_un*)SockAddrStringValuePtr(addr);
1466  if (RSTRING_LEN(addr) <
1467  (char*)&((struct sockaddr *)sockaddr)->sa_family +
1468  sizeof(((struct sockaddr *)sockaddr)->sa_family) -
1469  (char*)sockaddr)
1470  rb_raise(rb_eArgError, "too short sockaddr");
1471  if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
1472  rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
1473  }
1474  if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
1475  rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
1476  RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
1477  }
1478  path = rsock_unixpath_str(sockaddr, RSTRING_LENINT(addr));
1479  OBJ_INFECT(path, addr);
1480  return path;
1481 }
1482 #endif
1483 
1484 #if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) || defined(_WIN32)
1485 static VALUE
1486 sockaddr_obj(struct sockaddr *addr)
1487 {
1488  socklen_t len;
1489 #if defined(AF_INET6) && defined(__KAME__)
1490  struct sockaddr_in6 addr6;
1491 #endif
1492 
1493  if (addr == NULL)
1494  return Qnil;
1495 
1496  switch (addr->sa_family) {
1497  case AF_INET:
1498  len = (socklen_t)sizeof(struct sockaddr_in);
1499  break;
1500 
1501 #ifdef AF_INET6
1502  case AF_INET6:
1503  len = (socklen_t)sizeof(struct sockaddr_in6);
1504 # ifdef __KAME__
1505  /* KAME uses the 2nd 16bit word of link local IPv6 address as interface index internally */
1506  /* http://orange.kame.net/dev/cvsweb.cgi/kame/IMPLEMENTATION */
1507  /* convert fe80:1::1 to fe80::1%1 */
1508  memcpy(&addr6, addr, len);
1509  addr = (struct sockaddr *)&addr6;
1510  if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
1511  addr6.sin6_scope_id == 0 &&
1512  (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
1513  addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
1514  addr6.sin6_addr.s6_addr[2] = 0;
1515  addr6.sin6_addr.s6_addr[3] = 0;
1516  }
1517 # endif
1518  break;
1519 #endif
1520 
1521 #ifdef HAVE_SYS_UN_H
1522  case AF_UNIX:
1523  len = (socklen_t)sizeof(struct sockaddr_un);
1524  break;
1525 #endif
1526 
1527  default:
1528  len = (socklen_t)sizeof(struct sockaddr_in);
1529  break;
1530  }
1531 #ifdef SA_LEN
1532  if (len < (socklen_t)SA_LEN(addr))
1533  len = (socklen_t)SA_LEN(addr);
1534 #endif
1535 
1536  return rsock_addrinfo_new(addr, len, addr->sa_family, 0, 0, Qnil, Qnil);
1537 }
1538 #endif
1539 
1540 #if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)) || defined(SIOCGIFCONF) || defined(_WIN32)
1541 /*
1542  * call-seq:
1543  * Socket.ip_address_list => array
1544  *
1545  * Returns local IP addresses as an array.
1546  *
1547  * The array contains Addrinfo objects.
1548  *
1549  * pp Socket.ip_address_list
1550  * #=> [#<Addrinfo: 127.0.0.1>,
1551  * #<Addrinfo: 192.168.0.128>,
1552  * #<Addrinfo: ::1>,
1553  * ...]
1554  *
1555  */
1556 static VALUE
1558 {
1559 #if defined(HAVE_GETIFADDRS)
1560  struct ifaddrs *ifp = NULL;
1561  struct ifaddrs *p;
1562  int ret;
1563  VALUE list;
1564 
1565  ret = getifaddrs(&ifp);
1566  if (ret == -1) {
1567  rb_sys_fail("getifaddrs");
1568  }
1569 
1570  list = rb_ary_new();
1571  for (p = ifp; p; p = p->ifa_next) {
1572  if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
1573  rb_ary_push(list, sockaddr_obj(p->ifa_addr));
1574  }
1575  }
1576 
1577  freeifaddrs(ifp);
1578 
1579  return list;
1580 #elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)
1581  /* Solaris if_tcp(7P) */
1582  /* HP-UX has SIOCGLIFCONF too. But it uses different struct */
1583  int fd = -1;
1584  int ret;
1585  struct lifnum ln;
1586  struct lifconf lc;
1587  char *reason = NULL;
1588  int save_errno;
1589  int i;
1590  VALUE list = Qnil;
1591 
1592  lc.lifc_buf = NULL;
1593 
1594  fd = socket(AF_INET, SOCK_DGRAM, 0);
1595  if (fd == -1)
1596  rb_sys_fail("socket");
1597 
1598  memset(&ln, 0, sizeof(ln));
1599  ln.lifn_family = AF_UNSPEC;
1600 
1601  ret = ioctl(fd, SIOCGLIFNUM, &ln);
1602  if (ret == -1) {
1603  reason = "SIOCGLIFNUM";
1604  goto finish;
1605  }
1606 
1607  memset(&lc, 0, sizeof(lc));
1608  lc.lifc_family = AF_UNSPEC;
1609  lc.lifc_flags = 0;
1610  lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
1611  lc.lifc_req = xmalloc(lc.lifc_len);
1612 
1613  ret = ioctl(fd, SIOCGLIFCONF, &lc);
1614  if (ret == -1) {
1615  reason = "SIOCGLIFCONF";
1616  goto finish;
1617  }
1618 
1619  list = rb_ary_new();
1620  for (i = 0; i < ln.lifn_count; i++) {
1621  struct lifreq *req = &lc.lifc_req[i];
1622  if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
1623  if (req->lifr_addr.ss_family == AF_INET6 &&
1624  IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
1625  ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
1626  struct lifreq req2;
1627  memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
1628  ret = ioctl(fd, SIOCGLIFINDEX, &req2);
1629  if (ret == -1) {
1630  reason = "SIOCGLIFINDEX";
1631  goto finish;
1632  }
1633  ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
1634  }
1635  rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr));
1636  }
1637  }
1638 
1639  finish:
1640  save_errno = errno;
1641  if (lc.lifc_buf != NULL)
1642  xfree(lc.lifc_req);
1643  if (fd != -1)
1644  close(fd);
1645  errno = save_errno;
1646 
1647  if (reason)
1648  rb_sys_fail(reason);
1649  return list;
1650 
1651 #elif defined(SIOCGIFCONF)
1652  int fd = -1;
1653  int ret;
1654 #define EXTRA_SPACE (sizeof(struct ifconf) + sizeof(struct sockaddr_storage))
1655  char initbuf[4096+EXTRA_SPACE];
1656  char *buf = initbuf;
1657  int bufsize;
1658  struct ifconf conf;
1659  struct ifreq *req;
1660  VALUE list = Qnil;
1661  const char *reason = NULL;
1662  int save_errno;
1663 
1664  fd = socket(AF_INET, SOCK_DGRAM, 0);
1665  if (fd == -1)
1666  rb_sys_fail("socket");
1667 
1668  bufsize = sizeof(initbuf);
1669  buf = initbuf;
1670 
1671  retry:
1672  conf.ifc_len = bufsize;
1673  conf.ifc_req = (struct ifreq *)buf;
1674 
1675  /* fprintf(stderr, "bufsize: %d\n", bufsize); */
1676 
1677  ret = ioctl(fd, SIOCGIFCONF, &conf);
1678  if (ret == -1) {
1679  reason = "SIOCGIFCONF";
1680  goto finish;
1681  }
1682 
1683  /* fprintf(stderr, "conf.ifc_len: %d\n", conf.ifc_len); */
1684 
1685  if (bufsize - EXTRA_SPACE < conf.ifc_len) {
1686  if (bufsize < conf.ifc_len) {
1687  /* NetBSD returns required size for all interfaces. */
1688  bufsize = conf.ifc_len + EXTRA_SPACE;
1689  }
1690  else {
1691  bufsize = bufsize << 1;
1692  }
1693  if (buf == initbuf)
1694  buf = NULL;
1695  buf = xrealloc(buf, bufsize);
1696  goto retry;
1697  }
1698 
1699  close(fd);
1700  fd = -1;
1701 
1702  list = rb_ary_new();
1703  req = conf.ifc_req;
1704  while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
1705  struct sockaddr *addr = &req->ifr_addr;
1706  if (IS_IP_FAMILY(addr->sa_family)) {
1707  rb_ary_push(list, sockaddr_obj(addr));
1708  }
1709 #ifdef HAVE_SA_LEN
1710 # ifndef _SIZEOF_ADDR_IFREQ
1711 # define _SIZEOF_ADDR_IFREQ(r) \
1712  (sizeof(struct ifreq) + \
1713  (sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
1714  (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
1715  0))
1716 # endif
1717  req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
1718 #else
1719  req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
1720 #endif
1721  }
1722 
1723  finish:
1724 
1725  save_errno = errno;
1726  if (buf != initbuf)
1727  xfree(buf);
1728  if (fd != -1)
1729  close(fd);
1730  errno = save_errno;
1731 
1732  if (reason)
1733  rb_sys_fail(reason);
1734  return list;
1735 
1736 #undef EXTRA_SPACE
1737 #elif defined(_WIN32)
1738  typedef struct ip_adapter_unicast_address_st {
1739  unsigned LONG_LONG dummy0;
1740  struct ip_adapter_unicast_address_st *Next;
1741  struct {
1742  struct sockaddr *lpSockaddr;
1743  int iSockaddrLength;
1744  } Address;
1745  int dummy1;
1746  int dummy2;
1747  int dummy3;
1748  long dummy4;
1749  long dummy5;
1750  long dummy6;
1751  } ip_adapter_unicast_address_t;
1752  typedef struct ip_adapter_anycast_address_st {
1753  unsigned LONG_LONG dummy0;
1754  struct ip_adapter_anycast_address_st *Next;
1755  struct {
1756  struct sockaddr *lpSockaddr;
1757  int iSockaddrLength;
1758  } Address;
1759  } ip_adapter_anycast_address_t;
1760  typedef struct ip_adapter_addresses_st {
1761  unsigned LONG_LONG dummy0;
1762  struct ip_adapter_addresses_st *Next;
1763  void *dummy1;
1764  ip_adapter_unicast_address_t *FirstUnicastAddress;
1765  ip_adapter_anycast_address_t *FirstAnycastAddress;
1766  void *dummy2;
1767  void *dummy3;
1768  void *dummy4;
1769  void *dummy5;
1770  void *dummy6;
1771  BYTE dummy7[8];
1772  DWORD dummy8;
1773  DWORD dummy9;
1774  DWORD dummy10;
1775  DWORD IfType;
1776  int OperStatus;
1777  DWORD dummy12;
1778  DWORD dummy13[16];
1779  void *dummy14;
1780  } ip_adapter_addresses_t;
1781  typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
1782  HMODULE h;
1783  GetAdaptersAddresses_t pGetAdaptersAddresses;
1784  ULONG len;
1785  DWORD ret;
1786  ip_adapter_addresses_t *adapters;
1787  VALUE list;
1788 
1789  h = LoadLibrary("iphlpapi.dll");
1790  if (!h)
1791  rb_notimplement();
1792  pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
1793  if (!pGetAdaptersAddresses) {
1794  FreeLibrary(h);
1795  rb_notimplement();
1796  }
1797 
1798  ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
1799  if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
1800  errno = rb_w32_map_errno(ret);
1801  FreeLibrary(h);
1802  rb_sys_fail("GetAdaptersAddresses");
1803  }
1804  adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
1805  ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
1806  if (ret != ERROR_SUCCESS) {
1807  errno = rb_w32_map_errno(ret);
1808  FreeLibrary(h);
1809  rb_sys_fail("GetAdaptersAddresses");
1810  }
1811 
1812  list = rb_ary_new();
1813  for (; adapters; adapters = adapters->Next) {
1814  ip_adapter_unicast_address_t *uni;
1815  ip_adapter_anycast_address_t *any;
1816  if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */
1817  continue;
1818  for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
1819 #ifndef INET6
1820  if (uni->Address.lpSockaddr->sa_family == AF_INET)
1821 #else
1822  if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
1823 #endif
1824  rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr));
1825  }
1826  for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
1827 #ifndef INET6
1828  if (any->Address.lpSockaddr->sa_family == AF_INET)
1829 #else
1830  if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
1831 #endif
1832  rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr));
1833  }
1834  }
1835 
1836  FreeLibrary(h);
1837  return list;
1838 #endif
1839 }
1840 #else
1841 #define socket_s_ip_address_list rb_f_notimplement
1842 #endif
1843 
1844 void
1846 {
1848 
1849  /*
1850  * Document-class: Socket < BasicSocket
1851  *
1852  * Class +Socket+ provides access to the underlying operating system
1853  * socket implementations. It can be used to provide more operating system
1854  * specific functionality than the protocol-specific socket classes.
1855  *
1856  * The constants defined under Socket::Constants are also defined under
1857  * Socket. For example, Socket::AF_INET is usable as well as
1858  * Socket::Constants::AF_INET. See Socket::Constants for the list of
1859  * constants.
1860  *
1861  * === What's a socket?
1862  *
1863  * Sockets are endpoints of a bidirectionnal communication channel.
1864  * Sockets can communicate within a process, between processes on the same
1865  * machine or between different machines. There are many types of socket:
1866  * TCPSocket, UDPSocket or UNIXSocket for example.
1867  *
1868  * Sockets have their own vocabulary:
1869  *
1870  * *domain:*
1871  * The family of protocols:
1872  * * Socket::PF_INET
1873  * * Socket::PF_INET6
1874  * * Socket::PF_UNIX
1875  * * etc.
1876  *
1877  * *type:*
1878  * The type of communications between the two endpoints, typically
1879  * * Socket::SOCK_STREAM
1880  * * Socket::SOCK_DGRAM.
1881  *
1882  * *protocol:*
1883  * Typically _zero_.
1884  * This may be used to identify a variant of a protocol.
1885  *
1886  * *hostname:*
1887  * The identifier of a network interface:
1888  * * a string (hostname, IPv4 or IPv6 adress or +broadcast+
1889  * which specifies a broadcast address)
1890  * * a zero-length string which specifies INADDR_ANY
1891  * * an integer (interpreted as binary address in host byte order).
1892  *
1893  * === Quick start
1894  *
1895  * Many of the classes, such as TCPSocket, UDPSocket or UNIXSocket,
1896  * ease the use of sockets comparatively to the equivalent C programming interface.
1897  *
1898  * Let's create an internet socket using the IPv4 protocol in a C-like manner:
1899  *
1900  * s = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
1901  * s.connect Socket.pack_sockaddr_in(80, 'example.com')
1902  *
1903  * You could also use the TCPSocket class:
1904  *
1905  * s = TCPSocket.new 'example.com', 80
1906  *
1907  * A simple server might look like this:
1908  *
1909  * require 'socket'
1910  *
1911  * server = TCPServer.new 2000 # Server bound to port 2000
1912  *
1913  * loop do
1914  * client = server.accept # Wait for a client to connect
1915  * client.puts "Hello !"
1916  * client.puts "Time is #{Time.now}"
1917  * client.close
1918  * end
1919  *
1920  * A simple client may look like this:
1921  *
1922  * require 'socket'
1923  *
1924  * s = TCPSocket.new 'localhost', 2000
1925  *
1926  * while line = s.gets # Read lines from socket
1927  * puts line # and print them
1928  * end
1929  *
1930  * s.close # close socket when done
1931  *
1932  * === Exception Handling
1933  *
1934  * Ruby's Socket implementation raises exceptions based on the error
1935  * generated by the system dependent implementation. This is why the
1936  * methods are documented in a way that isolate Unix-based system
1937  * exceptions from Windows based exceptions. If more information on a
1938  * particular exception is needed, please refer to the Unix manual pages or
1939  * the Windows WinSock reference.
1940  *
1941  * === Convenience methods
1942  *
1943  * Although the general way to create socket is Socket.new,
1944  * there are several methods of socket creation for most cases.
1945  *
1946  * TCP client socket::
1947  * Socket.tcp, TCPSocket.open
1948  * TCP server socket::
1949  * Socket.tcp_server_loop, TCPServer.open
1950  * UNIX client socket::
1951  * Socket.unix, UNIXSocket.open
1952  * UNIX server socket::
1953  * Socket.unix_server_loop, UNIXServer.open
1954  *
1955  * === Documentation by
1956  *
1957  * * Zach Dennis
1958  * * Sam Roberts
1959  * * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
1960  *
1961  * Much material in this documentation is taken with permission from
1962  * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
1963  */
1965 
1967 
1968  rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
1969  rb_define_method(rb_cSocket, "connect", sock_connect, 1);
1970  rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
1971  rb_define_method(rb_cSocket, "bind", sock_bind, 1);
1973  rb_define_method(rb_cSocket, "accept", sock_accept, 0);
1974  rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
1975  rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
1976 
1977  rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
1978  rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
1979 
1992 #ifdef HAVE_SYS_UN_H
1993  rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
1994  rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
1995  rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
1996 #endif
1997 
1999 }
RARRAY_PTR(q->result)[0]
volatile VALUE tmp
Definition: tcltklib.c:10208
ssize_t n
Definition: bigdecimal.c:5676
struct addrinfo * rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
Definition: raddrinfo.c:379
volatile VALUE ary
Definition: tcltklib.c:9712
static VALUE sock_s_getservbyport(int argc, VALUE *argv)
Definition: socket.c:1104
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1088
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:2347
Win32OLEIDispatch * p
Definition: win32ole.c:786
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:4291
volatile VALUE pair
Definition: tkutil.c:554
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:1501
#define SA_LEN(sa)
Definition: sockport.h:29
VALUE rsock_sock_listen(VALUE sock, VALUE log)
Definition: socket.c:546
#define NI_DGRAM
Definition: addrinfo.h:128
void rb_secure(int)
Definition: safe.c:79
VALUE rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
Definition: raddrinfo.c:251
ssize_t i
Definition: bigdecimal.c:5676
Definition: io.h:63
int rsock_socktype_arg(VALUE type)
Definition: constants.c:50
int ret
Definition: tcltklib.c:280
VALUE rb_eTypeError
Definition: error.c:516
#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
gz path
Definition: zlib.c:2277
#define RSTRING_PTR(str)
NIL_P(eventloop_thread)
Definition: tcltklib.c:4067
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
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1788
#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
r
Definition: bigdecimal.c:1210
#define rb_str_new2
#define AI_CANONNAME
Definition: addrinfo.h:97
static VALUE sock_accept(VALUE sock)
Definition: socket.c:754
VALUE rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
Definition: raddrinfo.c:391
#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:1388
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2183
VALUE rb_eRangeError
Definition: error.c:520
d
Definition: strlcat.c:58
void rb_fd_fix_cloexec(int fd)
Definition: io.c:202
RUBY_EXTERN VALUE rb_mWaitWritable
Definition: ripper.y:1423
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
strcpy(cmd2, cmd)
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
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
int bufsize
Definition: regerror.c:390
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 Qnil
Definition: tcltklib.c:1895
#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)
int flags
Definition: tcltklib.c:3022
#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:503
static VALUE VALUE obj
Definition: tcltklib.c:3157
#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
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
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 * argv
Definition: tcltklib.c:1970
VALUE rb_yield(VALUE)
Definition: vm_eval.c:933
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:117
memcpy(buf+1, str, len)
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:4311
static void setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
Definition: socket.c:14
register char * s
Definition: os2.c:56
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:1362
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1574
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:545
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
int argc
Definition: tcltklib.c:1969
#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:1907
return ptr
Definition: tcltklib.c:784
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
gz end
Definition: zlib.c:2270
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
int t
Definition: ripper.c:14654
void rb_mod_sys_fail(VALUE mod, const char *mesg)
Definition: error.c:1919
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:1845
#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
klass
Definition: tcltklib.c:3503
#define INT2NUM(x)
struct rb_encoding_entry * list
Definition: encoding.c:50
static VALUE sock_bind(VALUE sock, VALUE addr)
Definition: socket.c:463
gz io
Definition: zlib.c:2261
void rb_notimplement(void)
Definition: error.c:1834
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
Real * res
Definition: bigdecimal.c:1247
#define NUM2INT(x)
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1740
static VALUE sock_s_getservbyname(int argc, VALUE *argv)
Definition: socket.c:1063
unsigned long VALUE
Definition: ripper.y:104
#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:1348
int retry
Definition: tcltklib.c:10150
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:517
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
static VALUE sock_accept_nonblock(VALUE sock)
Definition: socket.c:819
#define socket_s_ip_address_list
Definition: socket.c:1841
size_t len
Definition: tcltklib.c:3567
int ai_family
Definition: addrinfo.h:133