Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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
39 sock_initialize(int argc, VALUE *argv, VALUE sock)
40 {
41 VALUE domain, type, protocol;
42 int fd;
43 int d, t;
44
45 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
46 if (NIL_P(protocol))
47 protocol = INT2FIX(0);
48
49 rb_secure(3);
50 setup_domain_and_type(domain, &d, type, &t);
51 fd = rsock_socket(d, t, NUM2INT(protocol));
52 if (fd < 0) rb_sys_fail("socket(2)");
53
54 return rsock_init_sock(sock, fd);
55 }
56
57 #if defined HAVE_SOCKETPAIR
58 static VALUE
59 io_call_close(VALUE io)
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
153 rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
154 {
155 VALUE domain, type, protocol;
156 int d, t, p, sp[2];
157 int ret;
158 VALUE s1, s2, r;
159
160 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
161 if (NIL_P(protocol))
162 protocol = INT2FIX(0);
163
164 setup_domain_and_type(domain, &d, type, &t);
165 p = NUM2INT(protocol);
166 ret = rsock_socketpair(d, t, p, sp);
167 if (ret < 0) {
168 rb_sys_fail("socketpair(2)");
169 }
170 rb_fd_fix_cloexec(sp[0]);
171 rb_fd_fix_cloexec(sp[1]);
172
173 s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
174 s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
175 r = rb_assoc_new(s1, s2);
176 if (rb_block_given_p()) {
177 return rb_ensure(pair_yield, r, io_close, s1);
178 }
179 return r;
180 }
181 #else
182 #define rsock_sock_s_socketpair rb_f_notimplement
183 #endif
184
185 /*
186 * call-seq:
187 * socket.connect(remote_sockaddr) => 0
188 *
189 * Requests a connection to be made on the given +remote_sockaddr+. Returns 0 if
190 * successful, otherwise an exception is raised.
191 *
192 * === Parameter
193 * * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
194 *
195 * === Example:
196 * # Pull down Google's web page
197 * require 'socket'
198 * include Socket::Constants
199 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
200 * sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
201 * socket.connect( sockaddr )
202 * socket.write( "GET / HTTP/1.0\r\n\r\n" )
203 * results = socket.read
204 *
205 * === Unix-based Exceptions
206 * On unix-based systems the following system exceptions may be raised if
207 * the call to _connect_ fails:
208 * * Errno::EACCES - search permission is denied for a component of the prefix
209 * path or write access to the +socket+ is denied
210 * * Errno::EADDRINUSE - the _sockaddr_ is already in use
211 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
212 * local machine
213 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
214 * the address family of the specified +socket+
215 * * Errno::EALREADY - a connection is already in progress for the specified
216 * socket
217 * * Errno::EBADF - the +socket+ is not a valid file descriptor
218 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
219 * refused the connection request
220 * * Errno::ECONNRESET - the remote host reset the connection request
221 * * Errno::EFAULT - the _sockaddr_ cannot be accessed
222 * * Errno::EHOSTUNREACH - the destination host cannot be reached (probably
223 * because the host is down or a remote router cannot reach it)
224 * * Errno::EINPROGRESS - the O_NONBLOCK is set for the +socket+ and the
225 * connection cannot be immediately established; the connection will be
226 * established asynchronously
227 * * Errno::EINTR - the attempt to establish the connection was interrupted by
228 * delivery of a signal that was caught; the connection will be established
229 * asynchronously
230 * * Errno::EISCONN - the specified +socket+ is already connected
231 * * Errno::EINVAL - the address length used for the _sockaddr_ is not a valid
232 * length for the address family or there is an invalid family in _sockaddr_
233 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
234 * PATH_MAX
235 * * Errno::ENETDOWN - the local interface used to reach the destination is down
236 * * Errno::ENETUNREACH - no route to the network is present
237 * * Errno::ENOBUFS - no buffer space is available
238 * * Errno::ENOSR - there were insufficient STREAMS resources available to
239 * complete the operation
240 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
241 * * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected
242 * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket
243 * bound to the specified peer address
244 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
245 * was made.
246 *
247 * On unix-based systems if the address family of the calling +socket+ is
248 * AF_UNIX the follow exceptions may be raised if the call to _connect_
249 * fails:
250 * * Errno::EIO - an i/o error occurred while reading from or writing to the
251 * file system
252 * * Errno::ELOOP - too many symbolic links were encountered in translating
253 * the pathname in _sockaddr_
254 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
255 * characters, or an entire pathname exceeded PATH_MAX characters
256 * * Errno::ENOENT - a component of the pathname does not name an existing file
257 * or the pathname is an empty string
258 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
259 * is not a directory
260 *
261 * === Windows Exceptions
262 * On Windows systems the following system exceptions may be raised if
263 * the call to _connect_ fails:
264 * * Errno::ENETDOWN - the network is down
265 * * Errno::EADDRINUSE - the socket's local address is already in use
266 * * Errno::EINTR - the socket was cancelled
267 * * Errno::EINPROGRESS - a blocking socket is in progress or the service provider
268 * is still processing a callback function. Or a nonblocking connect call is
269 * in progress on the +socket+.
270 * * Errno::EALREADY - see Errno::EINVAL
271 * * Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as
272 * ADDR_ANY TODO check ADDRANY TO INADDR_ANY
273 * * Errno::EAFNOSUPPORT - addresses in the specified family cannot be used with
274 * with this +socket+
275 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
276 * refused the connection request
277 * * Errno::EFAULT - the socket's internal address or address length parameter
278 * is too small or is not a valid part of the user space address
279 * * Errno::EINVAL - the +socket+ is a listening socket
280 * * Errno::EISCONN - the +socket+ is already connected
281 * * Errno::ENETUNREACH - the network cannot be reached from this host at this time
282 * * Errno::EHOSTUNREACH - no route to the network is present
283 * * Errno::ENOBUFS - no buffer space is available
284 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
285 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
286 * was made.
287 * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the
288 * connection cannot be completed immediately
289 * * Errno::EACCES - the attempt to connect the datagram socket to the
290 * broadcast address failed
291 *
292 * === See
293 * * connect manual pages on unix-based systems
294 * * connect function in Microsoft's Winsock functions reference
295 */
296 static VALUE
297 sock_connect(VALUE sock, VALUE addr)
298 {
299 rb_io_t *fptr;
300 int fd, n;
301
302 SockAddrStringValue(addr);
303 addr = rb_str_new4(addr);
304 GetOpenFile(sock, fptr);
305 fd = fptr->fd;
306 n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr), 0);
307 if (n < 0) {
308 rb_sys_fail("connect(2)");
309 }
310
311 return INT2FIX(n);
312 }
313
314 /*
315 * call-seq:
316 * socket.connect_nonblock(remote_sockaddr) => 0
317 *
318 * Requests a connection to be made on the given +remote_sockaddr+ after
319 * O_NONBLOCK is set for the underlying file descriptor.
320 * Returns 0 if successful, otherwise an exception is raised.
321 *
322 * === Parameter
323 * * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
324 *
325 * === Example:
326 * # Pull down Google's web page
327 * require 'socket'
328 * include Socket::Constants
329 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
330 * sockaddr = Socket.sockaddr_in(80, 'www.google.com')
331 * begin # emulate blocking connect
332 * socket.connect_nonblock(sockaddr)
333 * rescue IO::WaitWritable
334 * IO.select(nil, [socket]) # wait 3-way handshake completion
335 * begin
336 * socket.connect_nonblock(sockaddr) # check connection failure
337 * rescue Errno::EISCONN
338 * end
339 * end
340 * socket.write("GET / HTTP/1.0\r\n\r\n")
341 * results = socket.read
342 *
343 * Refer to Socket#connect for the exceptions that may be thrown if the call
344 * to _connect_nonblock_ fails.
345 *
346 * Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
347 * including Errno::EINPROGRESS.
348 *
349 * If the exception is Errno::EINPROGRESS,
350 * it is extended by IO::WaitWritable.
351 * So IO::WaitWritable can be used to rescue the exceptions for retrying connect_nonblock.
352 *
353 * === See
354 * * Socket#connect
355 */
356 static VALUE
357 sock_connect_nonblock(VALUE sock, VALUE addr)
358 {
359 rb_io_t *fptr;
360 int n;
361
362 SockAddrStringValue(addr);
363 addr = rb_str_new4(addr);
364 GetOpenFile(sock, fptr);
365 rb_io_set_nonblock(fptr);
366 n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr));
367 if (n < 0) {
368 if (errno == EINPROGRESS)
369 rb_mod_sys_fail(rb_mWaitWritable, "connect(2) would block");
370 rb_sys_fail("connect(2)");
371 }
372
373 return INT2FIX(n);
374 }
375
376 /*
377 * call-seq:
378 * socket.bind(local_sockaddr) => 0
379 *
380 * Binds to the given local address.
381 *
382 * === Parameter
383 * * +local_sockaddr+ - the +struct+ sockaddr contained in a string or an Addrinfo object
384 *
385 * === Example
386 * require 'socket'
387 *
388 * # use Addrinfo
389 * socket = Socket.new(:INET, :STREAM, 0)
390 * socket.bind(Addrinfo.tcp("127.0.0.1", 2222))
391 * p socket.local_address #=> #<Addrinfo: 127.0.0.1:2222 TCP>
392 *
393 * # use struct sockaddr
394 * include Socket::Constants
395 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
396 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
397 * socket.bind( sockaddr )
398 *
399 * === Unix-based Exceptions
400 * On unix-based based systems the following system exceptions may be raised if
401 * the call to _bind_ fails:
402 * * Errno::EACCES - the specified _sockaddr_ is protected and the current
403 * user does not have permission to bind to it
404 * * Errno::EADDRINUSE - the specified _sockaddr_ is already in use
405 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
406 * local machine
407 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
408 * the family of the calling +socket+
409 * * Errno::EBADF - the _sockaddr_ specified is not a valid file descriptor
410 * * Errno::EFAULT - the _sockaddr_ argument cannot be accessed
411 * * Errno::EINVAL - the +socket+ is already bound to an address, and the
412 * protocol does not support binding to the new _sockaddr_ or the +socket+
413 * has been shut down.
414 * * Errno::EINVAL - the address length is not a valid length for the address
415 * family
416 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
417 * PATH_MAX
418 * * Errno::ENOBUFS - no buffer space is available
419 * * Errno::ENOSR - there were insufficient STREAMS resources available to
420 * complete the operation
421 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
422 * * Errno::EOPNOTSUPP - the socket type of the +socket+ does not support
423 * binding to an address
424 *
425 * On unix-based based systems if the address family of the calling +socket+ is
426 * Socket::AF_UNIX the follow exceptions may be raised if the call to _bind_
427 * fails:
428 * * Errno::EACCES - search permission is denied for a component of the prefix
429 * path or write access to the +socket+ is denied
430 * * Errno::EDESTADDRREQ - the _sockaddr_ argument is a null pointer
431 * * Errno::EISDIR - same as Errno::EDESTADDRREQ
432 * * Errno::EIO - an i/o error occurred
433 * * Errno::ELOOP - too many symbolic links were encountered in translating
434 * the pathname in _sockaddr_
435 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
436 * characters, or an entire pathname exceeded PATH_MAX characters
437 * * Errno::ENOENT - a component of the pathname does not name an existing file
438 * or the pathname is an empty string
439 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
440 * is not a directory
441 * * Errno::EROFS - the name would reside on a read only filesystem
442 *
443 * === Windows Exceptions
444 * On Windows systems the following system exceptions may be raised if
445 * the call to _bind_ fails:
446 * * Errno::ENETDOWN-- the network is down
447 * * Errno::EACCES - the attempt to connect the datagram socket to the
448 * broadcast address failed
449 * * Errno::EADDRINUSE - the socket's local address is already in use
450 * * Errno::EADDRNOTAVAIL - the specified address is not a valid address for this
451 * computer
452 * * Errno::EFAULT - the socket's internal address or address length parameter
453 * is too small or is not a valid part of the user space addressed
454 * * Errno::EINVAL - the +socket+ is already bound to an address
455 * * Errno::ENOBUFS - no buffer space is available
456 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
457 *
458 * === See
459 * * bind manual pages on unix-based systems
460 * * bind function in Microsoft's Winsock functions reference
461 */
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
546 rsock_sock_listen(VALUE sock, VALUE log)
547 {
548 rb_io_t *fptr;
549 int backlog;
550
551 rb_secure(4);
552 backlog = NUM2INT(log);
553 GetOpenFile(sock, fptr);
554 if (listen(fptr->fd, backlog) < 0)
555 rb_sys_fail("listen(2)");
556
557 return INT2FIX(0);
558 }
559
560 /*
561 * call-seq:
562 * socket.recvfrom(maxlen) => [mesg, sender_addrinfo]
563 * socket.recvfrom(maxlen, flags) => [mesg, sender_addrinfo]
564 *
565 * Receives up to _maxlen_ bytes from +socket+. _flags_ is zero or more
566 * of the +MSG_+ options. The first element of the results, _mesg_, is the data
567 * received. The second element, _sender_addrinfo_, contains protocol-specific
568 * address information of the sender.
569 *
570 * === Parameters
571 * * +maxlen+ - the maximum number of bytes to receive from the socket
572 * * +flags+ - zero or more of the +MSG_+ options
573 *
574 * === Example
575 * # In one file, start this first
576 * require 'socket'
577 * include Socket::Constants
578 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
579 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
580 * socket.bind( sockaddr )
581 * socket.listen( 5 )
582 * client, client_addrinfo = socket.accept
583 * data = client.recvfrom( 20 )[0].chomp
584 * puts "I only received 20 bytes '#{data}'"
585 * sleep 1
586 * socket.close
587 *
588 * # In another file, start this second
589 * require 'socket'
590 * include Socket::Constants
591 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
592 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
593 * socket.connect( sockaddr )
594 * socket.puts "Watch this get cut short!"
595 * socket.close
596 *
597 * === Unix-based Exceptions
598 * On unix-based based systems the following system exceptions may be raised if the
599 * call to _recvfrom_ fails:
600 * * Errno::EAGAIN - the +socket+ file descriptor is marked as O_NONBLOCK and no
601 * data is waiting to be received; or MSG_OOB is set and no out-of-band data
602 * is available and either the +socket+ file descriptor is marked as
603 * O_NONBLOCK or the +socket+ does not support blocking to wait for
604 * out-of-band-data
605 * * Errno::EWOULDBLOCK - see Errno::EAGAIN
606 * * Errno::EBADF - the +socket+ is not a valid file descriptor
607 * * Errno::ECONNRESET - a connection was forcibly closed by a peer
608 * * Errno::EFAULT - the socket's internal buffer, address or address length
609 * cannot be accessed or written
610 * * Errno::EINTR - a signal interrupted _recvfrom_ before any data was available
611 * * Errno::EINVAL - the MSG_OOB flag is set and no out-of-band data is available
612 * * Errno::EIO - an i/o error occurred while reading from or writing to the
613 * filesystem
614 * * Errno::ENOBUFS - insufficient resources were available in the system to
615 * perform the operation
616 * * Errno::ENOMEM - insufficient memory was available to fulfill the request
617 * * Errno::ENOSR - there were insufficient STREAMS resources available to
618 * complete the operation
619 * * Errno::ENOTCONN - a receive is attempted on a connection-mode socket that
620 * is not connected
621 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
622 * * Errno::EOPNOTSUPP - the specified flags are not supported for this socket type
623 * * Errno::ETIMEDOUT - the connection timed out during connection establishment
624 * or due to a transmission timeout on an active connection
625 *
626 * === Windows Exceptions
627 * On Windows systems the following system exceptions may be raised if
628 * the call to _recvfrom_ fails:
629 * * Errno::ENETDOWN - the network is down
630 * * Errno::EFAULT - the internal buffer and from parameters on +socket+ are not
631 * part of the user address space, or the internal fromlen parameter is
632 * too small to accommodate the peer address
633 * * Errno::EINTR - the (blocking) call was cancelled by an internal call to
634 * the WinSock function WSACancelBlockingCall
635 * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
636 * the service provider is still processing a callback function
637 * * Errno::EINVAL - +socket+ has not been bound with a call to _bind_, or an
638 * unknown flag was specified, or MSG_OOB was specified for a socket with
639 * SO_OOBINLINE enabled, or (for byte stream-style sockets only) the internal
640 * len parameter on +socket+ was zero or negative
641 * * Errno::EISCONN - +socket+ is already connected. The call to _recvfrom_ is
642 * not permitted with a connected socket on a socket that is connection
643 * oriented or connectionless.
644 * * Errno::ENETRESET - the connection has been broken due to the keep-alive
645 * activity detecting a failure while the operation was in progress.
646 * * Errno::EOPNOTSUPP - MSG_OOB was specified, but +socket+ is not stream-style
647 * such as type SOCK_STREAM. OOB data is not supported in the communication
648 * domain associated with +socket+, or +socket+ is unidirectional and
649 * supports only send operations
650 * * Errno::ESHUTDOWN - +socket+ has been shutdown. It is not possible to
651 * call _recvfrom_ on a socket after _shutdown_ has been invoked.
652 * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and a call to
653 * _recvfrom_ would block.
654 * * Errno::EMSGSIZE - the message was too large to fit into the specified buffer
655 * and was truncated.
656 * * Errno::ETIMEDOUT - the connection has been dropped, because of a network
657 * failure or because the system on the other end went down without
658 * notice
659 * * Errno::ECONNRESET - the virtual circuit was reset by the remote side
660 * executing a hard or abortive close. The application should close the
661 * socket; it is no longer usable. On a UDP-datagram socket this error
662 * indicates a previous send operation resulted in an ICMP Port Unreachable
663 * message.
664 */
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
754 sock_accept(VALUE sock)
755 {
756 rb_io_t *fptr;
757 VALUE sock2;
758 struct sockaddr_storage buf;
759 socklen_t len = (socklen_t)sizeof buf;
760
761 GetOpenFile(sock, fptr);
762 sock2 = rsock_s_accept(rb_cSocket,fptr->fd,(struct sockaddr*)&buf,&len);
763
764 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
765 }
766
767 /*
768 * call-seq:
769 * socket.accept_nonblock => [client_socket, client_addrinfo]
770 *
771 * Accepts an incoming connection using accept(2) after
772 * O_NONBLOCK is set for the underlying file descriptor.
773 * It returns an array containing the accepted socket
774 * for the incoming connection, _client_socket_,
775 * and an Addrinfo, _client_addrinfo_.
776 *
777 * === Example
778 * # In one script, start this first
779 * require 'socket'
780 * include Socket::Constants
781 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
782 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
783 * socket.bind(sockaddr)
784 * socket.listen(5)
785 * begin # emulate blocking accept
786 * client_socket, client_addrinfo = socket.accept_nonblock
787 * rescue IO::WaitReadable, Errno::EINTR
788 * IO.select([socket])
789 * retry
790 * end
791 * puts "The client said, '#{client_socket.readline.chomp}'"
792 * client_socket.puts "Hello from script one!"
793 * socket.close
794 *
795 * # In another script, start this second
796 * require 'socket'
797 * include Socket::Constants
798 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
799 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
800 * socket.connect(sockaddr)
801 * socket.puts "Hello from script 2."
802 * puts "The server said, '#{socket.readline.chomp}'"
803 * socket.close
804 *
805 * Refer to Socket#accept for the exceptions that may be thrown if the call
806 * to _accept_nonblock_ fails.
807 *
808 * Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
809 * including Errno::EWOULDBLOCK.
810 *
811 * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED or Errno::EPROTO,
812 * it is extended by IO::WaitReadable.
813 * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
814 *
815 * === See
816 * * Socket#accept
817 */
818 static VALUE
819 sock_accept_nonblock(VALUE sock)
820 {
821 rb_io_t *fptr;
822 VALUE sock2;
823 struct sockaddr_storage buf;
824 socklen_t len = (socklen_t)sizeof buf;
825
826 GetOpenFile(sock, fptr);
827 sock2 = rsock_s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)&buf, &len);
828 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
829 }
830
831 /*
832 * call-seq:
833 * socket.sysaccept => [client_socket_fd, client_addrinfo]
834 *
835 * Accepts an incoming connection returning an array containing the (integer)
836 * file descriptor for the incoming connection, _client_socket_fd_,
837 * and an Addrinfo, _client_addrinfo_.
838 *
839 * === Example
840 * # In one script, start this first
841 * require 'socket'
842 * include Socket::Constants
843 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
844 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
845 * socket.bind( sockaddr )
846 * socket.listen( 5 )
847 * client_fd, client_addrinfo = socket.sysaccept
848 * client_socket = Socket.for_fd( client_fd )
849 * puts "The client said, '#{client_socket.readline.chomp}'"
850 * client_socket.puts "Hello from script one!"
851 * socket.close
852 *
853 * # In another script, start this second
854 * require 'socket'
855 * include Socket::Constants
856 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
857 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
858 * socket.connect( sockaddr )
859 * socket.puts "Hello from script 2."
860 * puts "The server said, '#{socket.readline.chomp}'"
861 * socket.close
862 *
863 * Refer to Socket#accept for the exceptions that may be thrown if the call
864 * to _sysaccept_ fails.
865 *
866 * === See
867 * * Socket#accept
868 */
869 static VALUE
870 sock_sysaccept(VALUE sock)
871 {
872 rb_io_t *fptr;
873 VALUE sock2;
874 struct sockaddr_storage buf;
875 socklen_t len = (socklen_t)sizeof buf;
876
877 GetOpenFile(sock, fptr);
878 sock2 = rsock_s_accept(0,fptr->fd,(struct sockaddr*)&buf,&len);
879
880 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
881 }
882
883 #ifdef HAVE_GETHOSTNAME
884 /*
885 * call-seq:
886 * Socket.gethostname => hostname
887 *
888 * Returns the hostname.
889 *
890 * p Socket.gethostname #=> "hal"
891 *
892 * Note that it is not guaranteed to be able to convert to IP address using gethostbyname, getaddrinfo, etc.
893 * If you need local IP address, use Socket.ip_address_list.
894 */
895 static VALUE
896 sock_gethostname(VALUE obj)
897 {
898 #ifndef HOST_NAME_MAX
899 # define HOST_NAME_MAX 1024
900 #endif
901 char buf[HOST_NAME_MAX+1];
902
903 rb_secure(3);
904 if (gethostname(buf, (int)sizeof buf - 1) < 0)
905 rb_sys_fail("gethostname");
906
907 buf[sizeof buf - 1] = '\0';
908 return rb_str_new2(buf);
909 }
910 #else
911 #ifdef HAVE_UNAME
912
913 #include <sys/utsname.h>
914
915 static VALUE
916 sock_gethostname(VALUE obj)
917 {
918 struct utsname un;
919
920 rb_secure(3);
921 uname(&un);
922 return rb_str_new2(un.nodename);
923 }
924 #else
925 #define sock_gethostname rb_f_notimplement
926 #endif
927 #endif
928
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
985 sock_s_gethostbyname(VALUE obj, VALUE host)
986 {
987 rb_secure(3);
988 return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
989 }
990
991 /*
992 * call-seq:
993 * Socket.gethostbyaddr(address_string [, address_family]) => hostent
994 *
995 * Obtains the host information for _address_.
996 *
997 * p Socket.gethostbyaddr([221,186,184,68].pack("CCCC"))
998 * #=> ["carbon.ruby-lang.org", [], 2, "\xDD\xBA\xB8D"]
999 */
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 }
1230 tmp = rb_check_sockaddr_string_type(sa);
1231 if (!NIL_P(tmp)) {
1232 sa = tmp;
1233 if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
1234 rb_raise(rb_eTypeError, "sockaddr length too big");
1235 }
1236 memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
1237 if ((size_t)RSTRING_LEN(sa) != SS_LEN(&ss)) {
1238 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
1239 }
1240 sap = (struct sockaddr*)&ss;
1241 goto call_nameinfo;
1242 }
1243 tmp = rb_check_array_type(sa);
1244 if (!NIL_P(tmp)) {
1245 sa = tmp;
1246 MEMZERO(&hints, struct addrinfo, 1);
1247 if (RARRAY_LEN(sa) == 3) {
1248 af = RARRAY_PTR(sa)[0];
1249 port = RARRAY_PTR(sa)[1];
1250 host = RARRAY_PTR(sa)[2];
1251 }
1252 else if (RARRAY_LEN(sa) >= 4) {
1253 af = RARRAY_PTR(sa)[0];
1254 port = RARRAY_PTR(sa)[1];
1255 host = RARRAY_PTR(sa)[3];
1256 if (NIL_P(host)) {
1257 host = RARRAY_PTR(sa)[2];
1258 }
1259 else {
1260 /*
1261 * 4th element holds numeric form, don't resolve.
1262 * see rsock_ipaddr().
1263 */
1264 #ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
1265 hints.ai_flags |= AI_NUMERICHOST;
1266 #endif
1267 }
1268 }
1269 else {
1270 rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
1271 RARRAY_LEN(sa));
1272 }
1273 /* host */
1274 if (NIL_P(host)) {
1275 hptr = NULL;
1276 }
1277 else {
1278 strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
1279 hbuf[sizeof(hbuf) - 1] = '\0';
1280 hptr = hbuf;
1281 }
1282 /* port */
1283 if (NIL_P(port)) {
1284 strcpy(pbuf, "0");
1285 pptr = NULL;
1286 }
1287 else if (FIXNUM_P(port)) {
1288 snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
1289 pptr = pbuf;
1290 }
1291 else {
1292 strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
1293 pbuf[sizeof(pbuf) - 1] = '\0';
1294 pptr = pbuf;
1295 }
1296 hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
1297 /* af */
1298 hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
1299 error = rb_getaddrinfo(hptr, pptr, &hints, &res);
1300 if (error) goto error_exit_addr;
1301 sap = res->ai_addr;
1302 }
1303 else {
1304 rb_raise(rb_eTypeError, "expecting String or Array");
1305 }
1306
1307 call_nameinfo:
1308 error = rb_getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
1309 pbuf, sizeof(pbuf), fl);
1310 if (error) goto error_exit_name;
1311 if (res) {
1312 for (r = res->ai_next; r; r = r->ai_next) {
1313 char hbuf2[1024], pbuf2[1024];
1314
1315 sap = r->ai_addr;
1316 error = rb_getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
1317 pbuf2, sizeof(pbuf2), fl);
1318 if (error) goto error_exit_name;
1319 if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
1320 freeaddrinfo(res);
1321 rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
1322 }
1323 }
1324 freeaddrinfo(res);
1325 }
1326 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
1327
1328 error_exit_addr:
1329 if (res) freeaddrinfo(res);
1330 rsock_raise_socket_error("getaddrinfo", error);
1331
1332 error_exit_name:
1333 if (res) freeaddrinfo(res);
1334 rsock_raise_socket_error("getnameinfo", error);
1335
1336 UNREACHABLE;
1337 }
1338
1339 /*
1340 * call-seq:
1341 * Socket.sockaddr_in(port, host) => sockaddr
1342 * Socket.pack_sockaddr_in(port, host) => sockaddr
1343 *
1344 * Packs _port_ and _host_ as an AF_INET/AF_INET6 sockaddr string.
1345 *
1346 * Socket.sockaddr_in(80, "127.0.0.1")
1347 * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1348 *
1349 * Socket.sockaddr_in(80, "::1")
1350 * #=> "\n\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
1351 *
1352 */
1353 static VALUE
1354 sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
1355 {
1356 struct addrinfo *res = rsock_addrinfo(host, port, 0, 0);
1357 VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
1358
1359 freeaddrinfo(res);
1360 OBJ_INFECT(addr, port);
1361 OBJ_INFECT(addr, host);
1362
1363 return addr;
1364 }
1365
1366 /*
1367 * call-seq:
1368 * Socket.unpack_sockaddr_in(sockaddr) => [port, ip_address]
1369 *
1370 * Unpacks _sockaddr_ into port and ip_address.
1371 *
1372 * _sockaddr_ should be a string or an addrinfo for AF_INET/AF_INET6.
1373 *
1374 * sockaddr = Socket.sockaddr_in(80, "127.0.0.1")
1375 * p sockaddr #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1376 * p Socket.unpack_sockaddr_in(sockaddr) #=> [80, "127.0.0.1"]
1377 *
1378 */
1379 static VALUE
1380 sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
1381 {
1382 struct sockaddr_in * sockaddr;
1383 VALUE host;
1384
1385 sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
1386 if (RSTRING_LEN(addr) <
1387 (char*)&((struct sockaddr *)sockaddr)->sa_family +
1388 sizeof(((struct sockaddr *)sockaddr)->sa_family) -
1389 (char*)sockaddr)
1390 rb_raise(rb_eArgError, "too short sockaddr");
1391 if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
1392 #ifdef INET6
1393 && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
1394 #endif
1395 ) {
1396 #ifdef INET6
1397 rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
1398 #else
1399 rb_raise(rb_eArgError, "not an AF_INET sockaddr");
1400 #endif
1401 }
1402 host = rsock_make_ipaddr((struct sockaddr*)sockaddr);
1403 OBJ_INFECT(host, addr);
1404 return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
1405 }
1406
1407 #ifdef HAVE_SYS_UN_H
1408
1409 /*
1410 * call-seq:
1411 * Socket.sockaddr_un(path) => sockaddr
1412 * Socket.pack_sockaddr_un(path) => sockaddr
1413 *
1414 * Packs _path_ as an AF_UNIX sockaddr string.
1415 *
1416 * Socket.sockaddr_un("/tmp/sock") #=> "\x01\x00/tmp/sock\x00\x00..."
1417 *
1418 */
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
1549 socket_s_ip_address_list(VALUE self)
1550 {
1551 #if defined(HAVE_GETIFADDRS)
1552 struct ifaddrs *ifp = NULL;
1553 struct ifaddrs *p;
1554 int ret;
1555 VALUE list;
1556
1557 ret = getifaddrs(&ifp);
1558 if (ret == -1) {
1559 rb_sys_fail("getifaddrs");
1560 }
1561
1562 list = rb_ary_new();
1563 for (p = ifp; p; p = p->ifa_next) {
1564 if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
1565 rb_ary_push(list, sockaddr_obj(p->ifa_addr));
1566 }
1567 }
1568
1569 freeifaddrs(ifp);
1570
1571 return list;
1572 #elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)
1573 /* Solaris if_tcp(7P) */
1574 /* HP-UX has SIOCGLIFCONF too. But it uses different struct */
1575 int fd = -1;
1576 int ret;
1577 struct lifnum ln;
1578 struct lifconf lc;
1579 char *reason = NULL;
1580 int save_errno;
1581 int i;
1582 VALUE list = Qnil;
1583
1584 lc.lifc_buf = NULL;
1585
1586 fd = socket(AF_INET, SOCK_DGRAM, 0);
1587 if (fd == -1)
1588 rb_sys_fail("socket");
1589
1590 memset(&ln, 0, sizeof(ln));
1591 ln.lifn_family = AF_UNSPEC;
1592
1593 ret = ioctl(fd, SIOCGLIFNUM, &ln);
1594 if (ret == -1) {
1595 reason = "SIOCGLIFNUM";
1596 goto finish;
1597 }
1598
1599 memset(&lc, 0, sizeof(lc));
1600 lc.lifc_family = AF_UNSPEC;
1601 lc.lifc_flags = 0;
1602 lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
1603 lc.lifc_req = xmalloc(lc.lifc_len);
1604
1605 ret = ioctl(fd, SIOCGLIFCONF, &lc);
1606 if (ret == -1) {
1607 reason = "SIOCGLIFCONF";
1608 goto finish;
1609 }
1610
1611 list = rb_ary_new();
1612 for (i = 0; i < ln.lifn_count; i++) {
1613 struct lifreq *req = &lc.lifc_req[i];
1614 if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
1615 if (req->lifr_addr.ss_family == AF_INET6 &&
1616 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
1617 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
1618 struct lifreq req2;
1619 memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
1620 ret = ioctl(fd, SIOCGLIFINDEX, &req2);
1621 if (ret == -1) {
1622 reason = "SIOCGLIFINDEX";
1623 goto finish;
1624 }
1625 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
1626 }
1627 rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr));
1628 }
1629 }
1630
1631 finish:
1632 save_errno = errno;
1633 if (lc.lifc_buf != NULL)
1634 xfree(lc.lifc_req);
1635 if (fd != -1)
1636 close(fd);
1637 errno = save_errno;
1638
1639 if (reason)
1640 rb_sys_fail(reason);
1641 return list;
1642
1643 #elif defined(SIOCGIFCONF)
1644 int fd = -1;
1645 int ret;
1646 #define EXTRA_SPACE (sizeof(struct ifconf) + sizeof(struct sockaddr_storage))
1647 char initbuf[4096+EXTRA_SPACE];
1648 char *buf = initbuf;
1649 int bufsize;
1650 struct ifconf conf;
1651 struct ifreq *req;
1652 VALUE list = Qnil;
1653 const char *reason = NULL;
1654 int save_errno;
1655
1656 fd = socket(AF_INET, SOCK_DGRAM, 0);
1657 if (fd == -1)
1658 rb_sys_fail("socket");
1659
1660 bufsize = sizeof(initbuf);
1661 buf = initbuf;
1662
1663 retry:
1664 conf.ifc_len = bufsize;
1665 conf.ifc_req = (struct ifreq *)buf;
1666
1667 /* fprintf(stderr, "bufsize: %d\n", bufsize); */
1668
1669 ret = ioctl(fd, SIOCGIFCONF, &conf);
1670 if (ret == -1) {
1671 reason = "SIOCGIFCONF";
1672 goto finish;
1673 }
1674
1675 /* fprintf(stderr, "conf.ifc_len: %d\n", conf.ifc_len); */
1676
1677 if (bufsize - EXTRA_SPACE < conf.ifc_len) {
1678 if (bufsize < conf.ifc_len) {
1679 /* NetBSD returns required size for all interfaces. */
1680 bufsize = conf.ifc_len + EXTRA_SPACE;
1681 }
1682 else {
1683 bufsize = bufsize << 1;
1684 }
1685 if (buf == initbuf)
1686 buf = NULL;
1687 buf = xrealloc(buf, bufsize);
1688 goto retry;
1689 }
1690
1691 close(fd);
1692 fd = -1;
1693
1694 list = rb_ary_new();
1695 req = conf.ifc_req;
1696 while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
1697 struct sockaddr *addr = &req->ifr_addr;
1698 if (IS_IP_FAMILY(addr->sa_family)) {
1699 rb_ary_push(list, sockaddr_obj(addr));
1700 }
1701 #ifdef HAVE_SA_LEN
1702 # ifndef _SIZEOF_ADDR_IFREQ
1703 # define _SIZEOF_ADDR_IFREQ(r) \
1704 (sizeof(struct ifreq) + \
1705 (sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
1706 (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
1707 0))
1708 # endif
1709 req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
1710 #else
1711 req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
1712 #endif
1713 }
1714
1715 finish:
1716
1717 save_errno = errno;
1718 if (buf != initbuf)
1719 xfree(buf);
1720 if (fd != -1)
1721 close(fd);
1722 errno = save_errno;
1723
1724 if (reason)
1725 rb_sys_fail(reason);
1726 return list;
1727
1728 #undef EXTRA_SPACE
1729 #elif defined(_WIN32)
1730 typedef struct ip_adapter_unicast_address_st {
1731 unsigned LONG_LONG dummy0;
1732 struct ip_adapter_unicast_address_st *Next;
1733 struct {
1734 struct sockaddr *lpSockaddr;
1735 int iSockaddrLength;
1736 } Address;
1737 int dummy1;
1738 int dummy2;
1739 int dummy3;
1740 long dummy4;
1741 long dummy5;
1742 long dummy6;
1743 } ip_adapter_unicast_address_t;
1744 typedef struct ip_adapter_anycast_address_st {
1745 unsigned LONG_LONG dummy0;
1746 struct ip_adapter_anycast_address_st *Next;
1747 struct {
1748 struct sockaddr *lpSockaddr;
1749 int iSockaddrLength;
1750 } Address;
1751 } ip_adapter_anycast_address_t;
1752 typedef struct ip_adapter_addresses_st {
1753 unsigned LONG_LONG dummy0;
1754 struct ip_adapter_addresses_st *Next;
1755 void *dummy1;
1756 ip_adapter_unicast_address_t *FirstUnicastAddress;
1757 ip_adapter_anycast_address_t *FirstAnycastAddress;
1758 void *dummy2;
1759 void *dummy3;
1760 void *dummy4;
1761 void *dummy5;
1762 void *dummy6;
1763 BYTE dummy7[8];
1764 DWORD dummy8;
1765 DWORD dummy9;
1766 DWORD dummy10;
1767 DWORD IfType;
1768 int OperStatus;
1769 DWORD dummy12;
1770 DWORD dummy13[16];
1771 void *dummy14;
1772 } ip_adapter_addresses_t;
1773 typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
1774 HMODULE h;
1775 GetAdaptersAddresses_t pGetAdaptersAddresses;
1776 ULONG len;
1777 DWORD ret;
1778 ip_adapter_addresses_t *adapters;
1779 VALUE list;
1780
1781 h = LoadLibrary("iphlpapi.dll");
1782 if (!h)
1783 rb_notimplement();
1784 pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
1785 if (!pGetAdaptersAddresses) {
1786 FreeLibrary(h);
1787 rb_notimplement();
1788 }
1789
1790 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
1791 if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
1792 errno = rb_w32_map_errno(ret);
1793 FreeLibrary(h);
1794 rb_sys_fail("GetAdaptersAddresses");
1795 }
1796 adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
1797 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
1798 if (ret != ERROR_SUCCESS) {
1799 errno = rb_w32_map_errno(ret);
1800 FreeLibrary(h);
1801 rb_sys_fail("GetAdaptersAddresses");
1802 }
1803
1804 list = rb_ary_new();
1805 for (; adapters; adapters = adapters->Next) {
1806 ip_adapter_unicast_address_t *uni;
1807 ip_adapter_anycast_address_t *any;
1808 if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */
1809 continue;
1810 for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
1811 #ifndef INET6
1812 if (uni->Address.lpSockaddr->sa_family == AF_INET)
1813 #else
1814 if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
1815 #endif
1816 rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr));
1817 }
1818 for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
1819 #ifndef INET6
1820 if (any->Address.lpSockaddr->sa_family == AF_INET)
1821 #else
1822 if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
1823 #endif
1824 rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr));
1825 }
1826 }
1827
1828 FreeLibrary(h);
1829 return list;
1830 #endif
1831 }
1832 #else
1833 #define socket_s_ip_address_list rb_f_notimplement
1834 #endif
1835
1836 void
1837 Init_socket()
1838 {
1839 rsock_init_basicsocket();
1840
1841 /*
1842 * Document-class: Socket < BasicSocket
1843 *
1844 * Class +Socket+ provides access to the underlying operating system
1845 * socket implementations. It can be used to provide more operating system
1846 * specific functionality than the protocol-specific socket classes.
1847 *
1848 * The constants defined under Socket::Constants are also defined under
1849 * Socket. For example, Socket::AF_INET is usable as well as
1850 * Socket::Constants::AF_INET. See Socket::Constants for the list of
1851 * constants.
1852 *
1853 * === What's a socket?
1854 *
1855 * Sockets are endpoints of a bidirectionnal communication channel.
1856 * Sockets can communicate within a process, between processes on the same
1857 * machine or between different machines. There are many types of socket:
1858 * TCPSocket, UDPSocket or UNIXSocket for example.
1859 *
1860 * Sockets have their own vocabulary:
1861 *
1862 * *domain:*
1863 * The family of protocols:
1864 * * Socket::PF_INET
1865 * * Socket::PF_INET6
1866 * * Socket::PF_UNIX
1867 * * etc.
1868 *
1869 * *type:*
1870 * The type of communications between the two endpoints, typically
1871 * * Socket::SOCK_STREAM
1872 * * Socket::SOCK_DGRAM.
1873 *
1874 * *protocol:*
1875 * Typically _zero_.
1876 * This may be used to identify a variant of a protocol.
1877 *
1878 * *hostname:*
1879 * The identifier of a network interface:
1880 * * a string (hostname, IPv4 or IPv6 adress or +broadcast+
1881 * which specifies a broadcast address)
1882 * * a zero-length string which specifies INADDR_ANY
1883 * * an integer (interpreted as binary address in host byte order).
1884 *
1885 * === Quick start
1886 *
1887 * Many of the classes, such as TCPSocket, UDPSocket or UNIXSocket,
1888 * ease the use of sockets comparatively to the equivalent C programming interface.
1889 *
1890 * Let's create an internet socket using the IPv4 protocol in a C-like manner:
1891 *
1892 * s = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
1893 * s.connect Socket.pack_sockaddr_in(80, 'example.com')
1894 *
1895 * You could also use the TCPSocket class:
1896 *
1897 * s = TCPSocket.new 'example.com', 80
1898 *
1899 * A simple server might look like this:
1900 *
1901 * require 'socket'
1902 *
1903 * server = TCPServer.new 2000 # Server bound to port 2000
1904 *
1905 * loop do
1906 * client = server.accept # Wait for a client to connect
1907 * client.puts "Hello !"
1908 * client.puts "Time is #{Time.now}"
1909 * client.close
1910 * end
1911 *
1912 * A simple client may look like this:
1913 *
1914 * require 'socket'
1915 *
1916 * s = TCPSocket.new 'localhost', 2000
1917 *
1918 * while line = s.gets # Read lines from socket
1919 * puts line # and print them
1920 * end
1921 *
1922 * s.close # close socket when done
1923 *
1924 * === Exception Handling
1925 *
1926 * Ruby's Socket implementation raises exceptions based on the error
1927 * generated by the system dependent implementation. This is why the
1928 * methods are documented in a way that isolate Unix-based system
1929 * exceptions from Windows based exceptions. If more information on a
1930 * particular exception is needed, please refer to the Unix manual pages or
1931 * the Windows WinSock reference.
1932 *
1933 * === Convenience methods
1934 *
1935 * Although the general way to create socket is Socket.new,
1936 * there are several methods of socket creation for most cases.
1937 *
1938 * TCP client socket::
1939 * Socket.tcp, TCPSocket.open
1940 * TCP server socket::
1941 * Socket.tcp_server_loop, TCPServer.open
1942 * UNIX client socket::
1943 * Socket.unix, UNIXSocket.open
1944 * UNIX server socket::
1945 * Socket.unix_server_loop, UNIXServer.open
1946 *
1947 * === Documentation by
1948 *
1949 * * Zach Dennis
1950 * * Sam Roberts
1951 * * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
1952 *
1953 * Much material in this documentation is taken with permission from
1954 * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
1955 */
1956 rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
1957
1958 rsock_init_socket_init();
1959
1960 rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
1961 rb_define_method(rb_cSocket, "connect", sock_connect, 1);
1962 rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
1963 rb_define_method(rb_cSocket, "bind", sock_bind, 1);
1964 rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
1965 rb_define_method(rb_cSocket, "accept", sock_accept, 0);
1966 rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
1967 rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
1968
1969 rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
1970 rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
1971
1972 rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1);
1973 rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1);
1974 rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
1975 rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
1976 rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
1977 rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);
1978 rb_define_singleton_method(rb_cSocket, "getservbyport", sock_s_getservbyport, -1);
1979 rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
1980 rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
1981 rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
1982 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
1983 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
1984 #ifdef HAVE_SYS_UN_H
1985 rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
1986 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
1987 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
1988 #endif
1989
1990 rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0);
1991 }
RARRAY_PTR
RARRAY_PTR(q->result)[0]
tmp
volatile VALUE tmp
Definition: tcltklib.c:10209
n
ssize_t n
Definition: bigdecimal.c:5655
rsock_addrinfo
struct addrinfo * rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
Definition: raddrinfo.c:371
ary
volatile VALUE ary
Definition: tcltklib.c:9713
sock_s_getservbyport
static VALUE sock_s_getservbyport(int argc, VALUE *argv)
Definition: socket.c:1104
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1101
ioctl
int ioctl(int, int,...)
Definition: win32.c:2438
Next
#define Next(p, e, enc)
Definition: dir.c:98
OBJ_INFECT
#define OBJ_INFECT(x, s)
rb_io_set_nonblock
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2338
p
Win32OLEIDispatch * p
Definition: win32ole.c:786
rb_cBasicSocket
VALUE rb_cBasicSocket
Definition: init.c:13
rb_tainted_str_new2
#define rb_tainted_str_new2
SockAddrStringValue
#define SockAddrStringValue(v)
Definition: rubysocket.h:208
io_call_close
static VALUE io_call_close(VALUE io)
Definition: io.c:4279
pair
volatile VALUE pair
Definition: tkutil.c:554
sock_initialize
static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
Definition: socket.c:39
rb_define_singleton_method
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
SA_LEN
#define SA_LEN(sa)
Definition: sockport.h:29
rsock_sock_listen
VALUE rsock_sock_listen(VALUE sock, VALUE log)
Definition: socket.c:546
NI_DGRAM
#define NI_DGRAM
Definition: addrinfo.h:128
rb_secure
void rb_secure(int)
Definition: safe.c:79
i
ssize_t i
Definition: bigdecimal.c:5655
rb_io_t
Definition: io.h:63
rsock_socktype_arg
int rsock_socktype_arg(VALUE type)
Definition: constants.c:50
ret
int ret
Definition: tcltklib.c:280
rsock_ipaddr
VALUE rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup)
Definition: raddrinfo.c:383
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:511
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:40
names
st_table * names
Definition: encoding.c:53
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
rsock_init_sock
VALUE rsock_init_sock(VALUE sock, int fd)
Definition: init.c:43
path
gz path
Definition: zlib.c:2279
RSTRING_PTR
#define RSTRING_PTR(str)
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
sock_s_getaddrinfo
static VALUE sock_s_getaddrinfo(int argc, VALUE *argv)
Definition: socket.c:1159
xfree
#define xfree
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
rb_str_new4
#define rb_str_new4
rsock_s_accept
VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:558
rb_check_sockaddr_string_type
VALUE rb_check_sockaddr_string_type(VALUE val)
Definition: raddrinfo.c:2148
r
r
Definition: bigdecimal.c:1196
rb_str_new2
#define rb_str_new2
AI_CANONNAME
#define AI_CANONNAME
Definition: addrinfo.h:97
sock_accept
static VALUE sock_accept(VALUE sock)
Definition: socket.c:754
EINPROGRESS
#define EINPROGRESS
Definition: win32.h:477
STRTOUL
#define STRTOUL(str, endptr, base)
rb_w32_map_errno
int rb_w32_map_errno(DWORD)
Definition: win32.c:223
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:120
dv
static const unsigned char dv[]
Definition: nkf.c:586
sock_s_unpack_sockaddr_in
static VALUE sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
Definition: socket.c:1380
rsock_make_ipaddr
VALUE rsock_make_ipaddr(struct sockaddr *addr)
Definition: raddrinfo.c:243
rsock_io_socket_addrinfo
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2175
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:515
d
d
Definition: strlcat.c:58
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:202
rb_mWaitWritable
RUBY_EXTERN VALUE rb_mWaitWritable
Definition: ripper.y:1423
rsock_make_hostent
VALUE rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE(*ipaddr)(struct sockaddr *, size_t))
Definition: raddrinfo.c:524
MEMZERO
#define MEMZERO(p, type, n)
sock_s_getnameinfo
static VALUE sock_s_getnameinfo(int argc, VALUE *argv)
Definition: socket.c:1212
sock_connect_nonblock
static VALUE sock_connect_nonblock(VALUE sock, VALUE addr)
Definition: socket.c:357
strcpy
strcpy(cmd2, cmd)
rsock_addrinfo_new
VALUE rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, int family, int socktype, int protocol, VALUE canonname, VALUE inspectname)
Definition: raddrinfo.c:621
sock_recvfrom
static VALUE sock_recvfrom(int argc, VALUE *argv, VALUE sock)
Definition: socket.c:666
rb_gc
void rb_gc(void)
Definition: gc.c:3108
memset
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
bufsize
int bufsize
Definition: regerror.c:388
rb_rescue
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:763
FIXNUM_P
#define FIXNUM_P(f)
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:672
sock_sockaddr
static VALUE sock_sockaddr(struct sockaddr *addr, size_t len)
Definition: socket.c:953
RARRAY_LEN
#define RARRAY_LEN(a)
rsock_family_arg
int rsock_family_arg(VALUE domain)
Definition: constants.c:43
Qnil
#define Qnil
Definition: tcltklib.c:1896
StringValuePtr
#define StringValuePtr(v)
DWORD
IUnknown DWORD
Definition: win32ole.c:149
sock_sysaccept
static VALUE sock_sysaccept(VALUE sock)
Definition: socket.c:870
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:424
StringValueCStr
#define StringValueCStr(v)
flags
int flags
Definition: tcltklib.c:3023
PRIuSIZE
#define PRIuSIZE
rsock_socket
int rsock_socket(int domain, int type, int proto)
Definition: init.c:276
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
RSTRING_LEN
#define RSTRING_LEN(str)
INT2FIX
#define INT2FIX(i)
rb_io_t::fd
int fd
Definition: io.h:64
addrinfo::ai_canonname
char * ai_canonname
Definition: addrinfo.h:137
sock_gethostname
#define sock_gethostname
Definition: socket.c:925
xmalloc
#define xmalloc
xrealloc
#define xrealloc
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
rsock_init_socket_init
void rsock_init_socket_init()
Definition: init.c:605
ALLOCA_N
#define ALLOCA_N(type, n)
rb_cSocket
VALUE rb_cSocket
Definition: init.c:22
SockAddrStringValuePtr
#define SockAddrStringValuePtr(v)
Definition: rubysocket.h:209
argv
VALUE * argv
Definition: tcltklib.c:1971
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:934
IS_IP_FAMILY
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:117
memcpy
memcpy(buf+1, str, len)
errno
int errno
rsock_s_recvfrom
VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:106
StringValue
#define StringValue(v)
io_close
static VALUE io_close(VALUE io)
Definition: io.c:4285
setup_domain_and_type
static void setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
Definition: socket.c:14
s
register char * s
Definition: os2.c:56
freeaddrinfo
void freeaddrinfo(struct addrinfo *ai)
Definition: getaddrinfo.c:211
sock_s_pack_sockaddr_in
static VALUE sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
Definition: socket.c:1354
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:545
sockaddr_storage
Definition: rubysocket.h:134
rsock_init_basicsocket
void rsock_init_basicsocket(void)
Definition: basicsocket.c:744
rsock_do_not_reverse_lookup
int rsock_do_not_reverse_lookup
Definition: init.c:31
type
int type
Definition: tcltklib.c:111
argc
int argc
Definition: tcltklib.c:1970
AI_NUMERICHOST
#define AI_NUMERICHOST
Definition: addrinfo.h:98
make_addrinfo
static VALUE make_addrinfo(struct addrinfo *res0, int norevlookup)
Definition: socket.c:930
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
sock_connect
static VALUE sock_connect(VALUE sock, VALUE addr)
Definition: socket.c:297
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1899
ptr
return ptr
Definition: tcltklib.c:784
addrinfo::ai_protocol
int ai_protocol
Definition: addrinfo.h:135
rb_getnameinfo
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:210
end
gz end
Definition: zlib.c:2272
rb_eSocket
VALUE rb_eSocket
Definition: init.c:25
NUM2LONG
#define NUM2LONG(x)
rubysocket.h
PF_UNSPEC
#define PF_UNSPEC
Definition: sockport.h:73
addrinfo::ai_socktype
int ai_socktype
Definition: addrinfo.h:134
rsock_revlookup_flag
int rsock_revlookup_flag(VALUE revlookup, int *norevlookup)
Definition: ipsocket.c:140
t
int t
Definition: ripper.c:14699
rb_mod_sys_fail
void rb_mod_sys_fail(VALUE mod, const char *mesg)
Definition: error.c:1911
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:557
proto
#define proto(p)
Definition: sdbm.h:60
rsock_raise_socket_error
void rsock_raise_socket_error(const char *reason, int error)
Definition: init.c:34
rsock_connect
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
Definition: init.c:373
Init_socket
void Init_socket()
Definition: socket.c:1837
AF_UNSPEC
#define AF_UNSPEC
Definition: sockport.h:69
rsock_getaddrinfo
struct addrinfo * rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
Definition: raddrinfo.c:343
klass
klass
Definition: tcltklib.c:3504
INT2NUM
#define INT2NUM(x)
list
struct rb_encoding_entry * list
Definition: encoding.c:50
sock_bind
static VALUE sock_bind(VALUE sock, VALUE addr)
Definition: socket.c:463
io
gz io
Definition: zlib.c:2263
rb_notimplement
void rb_notimplement(void)
Definition: error.c:1826
rsock_s_accept_nonblock
VALUE rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:518
addrinfo::ai_next
struct addrinfo * ai_next
Definition: addrinfo.h:139
RSTRING_LENINT
#define RSTRING_LENINT(str)
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:425
res
Real * res
Definition: bigdecimal.c:1233
NUM2INT
#define NUM2INT(x)
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1721
sock_s_getservbyname
static VALUE sock_s_getservbyname(int argc, VALUE *argv)
Definition: socket.c:1063
RECV_SOCKET
Definition: rubysocket.h:267
VALUE
unsigned long VALUE
Definition: ripper.y:104
SS_LEN
#define SS_LEN(ss)
Definition: sockport.h:30
addrinfo::ai_addrlen
size_t ai_addrlen
Definition: addrinfo.h:136
rsock_sock_s_socketpair
#define rsock_sock_s_socketpair
Definition: socket.c:182
addrinfo
Definition: addrinfo.h:131
snprintf
#define snprintf
sock_s_gethostbyaddr
static VALUE sock_s_gethostbyaddr(int argc, VALUE *argv)
Definition: socket.c:1001
rb_intern
#define rb_intern(str)
addrinfo::ai_flags
int ai_flags
Definition: addrinfo.h:132
NULL
#define NULL
Definition: _sdbm.c:103
rsock_s_recvfrom_nonblock
VALUE rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:174
rb_getaddrinfo
int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
Definition: raddrinfo.c:167
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
retry
int retry
Definition: tcltklib.c:10151
ULONG
static ULONG(STDMETHODCALLTYPE AddRef)(IDispatch __RPC_FAR *This)
Definition: win32ole.c:614
addrinfo::ai_addr
struct sockaddr * ai_addr
Definition: addrinfo.h:138
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
sock_s_gethostbyname
static VALUE sock_s_gethostbyname(VALUE obj, VALUE host)
Definition: socket.c:985
sock_recvfrom_nonblock
static VALUE sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
Definition: socket.c:734
sock_accept_nonblock
static VALUE sock_accept_nonblock(VALUE sock)
Definition: socket.c:819
socket_s_ip_address_list
#define socket_s_ip_address_list
Definition: socket.c:1833
len
size_t len
Definition: tcltklib.c:3568
addrinfo::ai_family
int ai_family
Definition: addrinfo.h:133