Update to RDoc 2.1.0 r112
[rbx.git] / stdlib / ext / socket / socket.c
blob829e89b63a574dc176862ee9485258775f268624
1 /************************************************
3 socket.c -
5 $Author: knu $
6 $Date: 2007-02-19 01:34:19 -0800 (Mon, 19 Feb 2007) $
7 created at: Thu Mar 31 12:21:29 JST 1994
9 Copyright (C) 1993-2001 Yukihiro Matsumoto
11 ************************************************/
13 #include "ruby.h"
14 #include "rubyio.h"
15 #include "rubysig.h"
16 #include "util.h"
17 #include <stdio.h>
18 #include <sys/types.h>
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
24 #ifdef HAVE_SYS_UIO_H
25 #include <sys/uio.h>
26 #endif
28 #ifndef _WIN32
29 #if defined(__BEOS__)
30 # include <net/socket.h>
31 #else
32 # include <sys/socket.h>
33 # define pseudo_AF_FTIP pseudo_AF_RTIP /* workaround for NetBSD and etc. */
34 #endif
35 #include <netinet/in.h>
36 #ifdef HAVE_NETINET_IN_SYSTM_H
37 # include <netinet/in_systm.h>
38 #endif
39 #ifdef HAVE_NETINET_TCP_H
40 # include <netinet/tcp.h>
41 #endif
42 #ifdef HAVE_NETINET_UDP_H
43 # include <netinet/udp.h>
44 #endif
45 #ifdef HAVE_ARPA_INET_H
46 # include <arpa/inet.h>
47 #endif
48 #include <netdb.h>
49 #endif
50 #include <errno.h>
51 #ifdef HAVE_SYS_UN_H
52 #include <sys/un.h>
53 #endif
55 #if defined(HAVE_FCNTL)
56 #ifdef HAVE_SYS_SELECT_H
57 #include <sys/select.h>
58 #endif
59 #ifdef HAVE_SYS_TYPES_H
60 #include <sys/types.h>
61 #endif
62 #ifdef HAVE_SYS_TIME_H
63 #include <sys/time.h>
64 #endif
65 #ifdef HAVE_FCNTL_H
66 #include <fcntl.h>
67 #endif
68 #endif
69 #ifndef EWOULDBLOCK
70 #define EWOULDBLOCK EAGAIN
71 #endif
72 #ifndef HAVE_GETADDRINFO
73 # include "addrinfo.h"
74 #endif
75 #include "sockport.h"
77 #if defined(__vms)
78 #include <tcp.h>
79 #endif
81 static int do_not_reverse_lookup = 0;
83 VALUE rb_cBasicSocket;
84 VALUE rb_cIPSocket;
85 VALUE rb_cTCPSocket;
86 VALUE rb_cTCPServer;
87 VALUE rb_cUDPSocket;
88 #ifdef AF_UNIX
89 VALUE rb_cUNIXSocket;
90 VALUE rb_cUNIXServer;
91 #endif
92 VALUE rb_cSocket;
94 static VALUE rb_eSocket;
96 #ifdef SOCKS
97 VALUE rb_cSOCKSSocket;
98 #ifdef SOCKS5
99 #include <socks.h>
100 #else
101 void SOCKSinit();
102 int Rconnect();
103 #endif
104 #endif
106 #define INET_CLIENT 0
107 #define INET_SERVER 1
108 #define INET_SOCKS 2
110 #ifndef HAVE_SOCKADDR_STORAGE
112 * RFC 2553: protocol-independent placeholder for socket addresses
114 #define _SS_MAXSIZE 128
115 #define _SS_ALIGNSIZE (sizeof(double))
116 #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2)
117 #define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \
118 _SS_PAD1SIZE - _SS_ALIGNSIZE)
120 struct sockaddr_storage {
121 #ifdef HAVE_SA_LEN
122 unsigned char ss_len; /* address length */
123 unsigned char ss_family; /* address family */
124 #else
125 unsigned short ss_family;
126 #endif
127 char __ss_pad1[_SS_PAD1SIZE];
128 double __ss_align; /* force desired structure storage alignment */
129 char __ss_pad2[_SS_PAD2SIZE];
131 #endif
133 #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
134 #define LOOKUP_ORDERS 3
135 static int lookup_order_table[LOOKUP_ORDERS] = {
136 #if defined(LOOKUP_ORDER_HACK_INET)
137 PF_INET, PF_INET6, PF_UNSPEC,
138 #elif defined(LOOKUP_ORDER_HACK_INET6)
139 PF_INET6, PF_INET, PF_UNSPEC,
140 #else
141 /* should not happen */
142 #endif
145 static int
146 ruby_getaddrinfo(nodename, servname, hints, res)
147 char *nodename;
148 char *servname;
149 struct addrinfo *hints;
150 struct addrinfo **res;
152 struct addrinfo tmp_hints;
153 int i, af, error;
155 if (hints->ai_family != PF_UNSPEC) {
156 return getaddrinfo(nodename, servname, hints, res);
159 for (i = 0; i < LOOKUP_ORDERS; i++) {
160 af = lookup_order_table[i];
161 MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
162 tmp_hints.ai_family = af;
163 error = getaddrinfo(nodename, servname, &tmp_hints, res);
164 if (error) {
165 if (tmp_hints.ai_family == PF_UNSPEC) {
166 break;
169 else {
170 break;
174 return error;
176 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
177 #endif
179 #if defined(_AIX)
180 static int
181 ruby_getaddrinfo__aix(nodename, servname, hints, res)
182 char *nodename;
183 char *servname;
184 struct addrinfo *hints;
185 struct addrinfo **res;
187 int error = getaddrinfo(nodename, servname, hints, res);
188 struct addrinfo *r;
189 if (error)
190 return error;
191 for (r = *res; r != NULL; r = r->ai_next) {
192 if (r->ai_addr->sa_family == 0)
193 r->ai_addr->sa_family = r->ai_family;
194 if (r->ai_addr->sa_len == 0)
195 r->ai_addr->sa_len = r->ai_addrlen;
197 return 0;
199 #undef getaddrinfo
200 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
201 static int
202 ruby_getnameinfo__aix(sa, salen, host, hostlen, serv, servlen, flags)
203 const struct sockaddr *sa;
204 size_t salen;
205 char *host;
206 size_t hostlen;
207 char *serv;
208 size_t servlen;
209 int flags;
211 struct sockaddr_in6 *sa6;
212 u_int32_t *a6;
214 if (sa->sa_family == AF_INET6) {
215 sa6 = (struct sockaddr_in6 *)sa;
216 a6 = sa6->sin6_addr.u6_addr.u6_addr32;
218 if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
219 strncpy(host, "::", hostlen);
220 snprintf(serv, servlen, "%d", sa6->sin6_port);
221 return 0;
224 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
226 #undef getnameinfo
227 #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
228 ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
229 #ifndef CMSG_SPACE
230 # define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
231 #endif
232 #ifndef CMSG_LEN
233 # define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
234 #endif
235 #endif
237 #ifdef HAVE_CLOSESOCKET
238 #undef close
239 #define close closesocket
240 #endif
242 static VALUE
243 init_sock(sock, fd)
244 VALUE sock;
245 int fd;
247 OpenFile *fp;
249 MakeOpenFile(sock, fp);
250 fp->f = rb_fdopen(fd, "r");
251 fp->f2 = rb_fdopen(fd, "w");
252 fp->mode = FMODE_READWRITE;
253 rb_io_synchronized(fp);
255 return sock;
258 static VALUE
259 bsock_s_for_fd(klass, fd)
260 VALUE klass, fd;
262 OpenFile *fptr;
263 VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));
265 GetOpenFile(sock, fptr);
267 return sock;
270 static VALUE
271 bsock_shutdown(argc, argv, sock)
272 int argc;
273 VALUE *argv;
274 VALUE sock;
276 VALUE howto;
277 int how;
278 OpenFile *fptr;
280 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
281 rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
283 rb_scan_args(argc, argv, "01", &howto);
284 if (howto == Qnil)
285 how = 2;
286 else {
287 how = NUM2INT(howto);
288 if (how < 0 || 2 < how) {
289 rb_raise(rb_eArgError, "`how' should be either 0, 1, 2");
292 GetOpenFile(sock, fptr);
293 if (shutdown(fileno(fptr->f), how) == -1)
294 rb_sys_fail(0);
296 return INT2FIX(0);
299 static VALUE
300 bsock_close_read(sock)
301 VALUE sock;
303 OpenFile *fptr;
305 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
306 rb_raise(rb_eSecurityError, "Insecure: can't close socket");
308 GetOpenFile(sock, fptr);
309 shutdown(fileno(fptr->f), 0);
310 if (!(fptr->mode & FMODE_WRITABLE)) {
311 return rb_io_close(sock);
313 fptr->mode &= ~FMODE_READABLE;
315 return Qnil;
318 static VALUE
319 bsock_close_write(sock)
320 VALUE sock;
322 OpenFile *fptr;
324 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
325 rb_raise(rb_eSecurityError, "Insecure: can't close socket");
327 GetOpenFile(sock, fptr);
328 if (!(fptr->mode & FMODE_READABLE)) {
329 return rb_io_close(sock);
331 shutdown(fileno(fptr->f2), 1);
332 fptr->mode &= ~FMODE_WRITABLE;
334 return Qnil;
338 * Document-method: setsockopt
339 * call-seq: setsockopt(level, optname, optval)
341 * Sets a socket option. These are protocol and system specific, see your
342 * local sytem documentation for details.
344 * === Parameters
345 * * +level+ is an integer, usually one of the SOL_ constants such as
346 * Socket::SOL_SOCKET, or a protocol level.
347 * * +optname+ is an integer, usually one of the SO_ constants, such
348 * as Socket::SO_REUSEADDR.
349 * * +optval+ is the value of the option, it is passed to the underlying
350 * setsockopt() as a pointer to a certain number of bytes. How this is
351 * done depends on the type:
352 * - Fixnum: value is assigned to an int, and a pointer to the int is
353 * passed, with length of sizeof(int).
354 * - true or false: 1 or 0 (respectively) is assigned to an int, and the
355 * int is passed as for a Fixnum. Note that +false+ must be passed,
356 * not +nil+.
357 * - String: the string's data and length is passed to the socket.
359 * === Examples
361 * Some socket options are integers with boolean values, in this case
362 * #setsockopt could be called like this:
363 * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
365 * Some socket options are integers with numeric values, in this case
366 * #setsockopt could be called like this:
367 * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
369 * Option values may be structs. Passing them can be complex as it involves
370 * examining your system headers to determine the correct definition. An
371 * example is an +ip_mreq+, which may be defined in your system headers as:
372 * struct ip_mreq {
373 * struct in_addr imr_multiaddr;
374 * struct in_addr imr_interface;
375 * };
377 * In this case #setsockopt could be called like this:
378 * optval = IPAddr.new("224.0.0.251") + Socket::INADDR_ANY
379 * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
382 static VALUE
383 bsock_setsockopt(sock, lev, optname, val)
384 VALUE sock, lev, optname, val;
386 int level, option;
387 OpenFile *fptr;
388 int i;
389 char *v;
390 int vlen;
392 rb_secure(2);
393 level = NUM2INT(lev);
394 option = NUM2INT(optname);
396 switch (TYPE(val)) {
397 case T_FIXNUM:
398 i = FIX2INT(val);
399 goto numval;
400 case T_FALSE:
401 i = 0;
402 goto numval;
403 case T_TRUE:
404 i = 1;
405 numval:
406 v = (char*)&i; vlen = sizeof(i);
407 break;
408 default:
409 StringValue(val);
410 v = RSTRING(val)->ptr;
411 vlen = RSTRING(val)->len;
412 break;
415 GetOpenFile(sock, fptr);
416 if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0)
417 rb_sys_fail(fptr->path);
419 return INT2FIX(0);
423 * Document-method: getsockopt
424 * call-seq: getsockopt(level, optname)
426 * Gets a socket option. These are protocol and system specific, see your
427 * local sytem documentation for details. The option is returned as
428 * a String with the data being the binary value of the socket option.
430 * === Parameters
431 * * +level+ is an integer, usually one of the SOL_ constants such as
432 * Socket::SOL_SOCKET, or a protocol level.
433 * * +optname+ is an integer, usually one of the SO_ constants, such
434 * as Socket::SO_REUSEADDR.
436 * === Examples
438 * Some socket options are integers with boolean values, in this case
439 * #getsockopt could be called like this:
440 * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
441 * optval = optval.unpack "i"
442 * reuseaddr = optval[0] == 0 ? false : true
444 * Some socket options are integers with numeric values, in this case
445 * #getsockopt could be called like this:
446 * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
447 * ipttl = optval.unpack("i")[0]
449 * Option values may be structs. Decoding them can be complex as it involves
450 * examining your system headers to determine the correct definition. An
451 * example is a +struct linger+, which may be defined in your system headers
452 * as:
453 * struct linger {
454 * int l_onoff;
455 * int l_linger;
456 * };
458 * In this case #getsockopt could be called like this:
459 * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
460 * onoff, linger = optval.unpack "ii"
462 static VALUE
463 bsock_getsockopt(sock, lev, optname)
464 VALUE sock, lev, optname;
466 #if !defined(__BEOS__)
467 int level, option;
468 socklen_t len;
469 char *buf;
470 OpenFile *fptr;
472 level = NUM2INT(lev);
473 option = NUM2INT(optname);
474 len = 256;
475 buf = ALLOCA_N(char,len);
476 GetOpenFile(sock, fptr);
478 GetOpenFile(sock, fptr);
479 if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0)
480 rb_sys_fail(fptr->path);
482 return rb_str_new(buf, len);
483 #else
484 rb_notimplement();
485 #endif
488 static VALUE
489 bsock_getsockname(sock)
490 VALUE sock;
492 char buf[1024];
493 socklen_t len = sizeof buf;
494 OpenFile *fptr;
496 GetOpenFile(sock, fptr);
497 if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
498 rb_sys_fail("getsockname(2)");
499 return rb_str_new(buf, len);
502 static VALUE
503 bsock_getpeername(sock)
504 VALUE sock;
506 char buf[1024];
507 socklen_t len = sizeof buf;
508 OpenFile *fptr;
510 GetOpenFile(sock, fptr);
511 if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
512 rb_sys_fail("getpeername(2)");
513 return rb_str_new(buf, len);
516 static VALUE
517 bsock_send(argc, argv, sock)
518 int argc;
519 VALUE *argv;
520 VALUE sock;
522 VALUE mesg, to;
523 VALUE flags;
524 OpenFile *fptr;
525 FILE *f;
526 int fd, n;
528 rb_secure(4);
529 rb_scan_args(argc, argv, "21", &mesg, &flags, &to);
531 StringValue(mesg);
532 if (!NIL_P(to)) StringValue(to);
533 GetOpenFile(sock, fptr);
534 f = GetWriteFile(fptr);
535 fd = fileno(f);
536 rb_thread_fd_writable(fd);
537 retry:
538 if (!NIL_P(to)) {
539 TRAP_BEG;
540 n = sendto(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
541 (struct sockaddr*)RSTRING(to)->ptr, RSTRING(to)->len);
542 TRAP_END;
544 else {
545 TRAP_BEG;
546 n = send(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags));
547 TRAP_END;
549 if (n < 0) {
550 if (rb_io_wait_writable(fd)) {
551 goto retry;
553 rb_sys_fail("send(2)");
555 return INT2FIX(n);
558 static VALUE ipaddr _((struct sockaddr*));
559 #ifdef HAVE_SYS_UN_H
560 static VALUE unixaddr _((struct sockaddr_un*, socklen_t));
561 #endif
563 enum sock_recv_type {
564 RECV_RECV, /* BasicSocket#recv(no from) */
565 RECV_IP, /* IPSocket#recvfrom */
566 RECV_UNIX, /* UNIXSocket#recvfrom */
567 RECV_SOCKET /* Socket#recvfrom */
570 static VALUE
571 s_recvfrom(sock, argc, argv, from)
572 VALUE sock;
573 int argc;
574 VALUE *argv;
575 enum sock_recv_type from;
577 OpenFile *fptr;
578 VALUE str;
579 char buf[1024];
580 socklen_t alen = sizeof buf;
581 VALUE len, flg;
582 long buflen;
583 long slen;
584 int fd, flags;
586 rb_scan_args(argc, argv, "11", &len, &flg);
588 if (flg == Qnil) flags = 0;
589 else flags = NUM2INT(flg);
590 buflen = NUM2INT(len);
592 GetOpenFile(sock, fptr);
593 if (rb_read_pending(fptr->f)) {
594 rb_raise(rb_eIOError, "recv for buffered IO");
596 fd = fileno(fptr->f);
598 str = rb_tainted_str_new(0, buflen);
600 retry:
601 rb_str_locktmp(str);
602 rb_thread_wait_fd(fd);
603 TRAP_BEG;
604 slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct sockaddr*)buf, &alen);
605 TRAP_END;
606 rb_str_unlocktmp(str);
608 if (slen < 0) {
609 if (rb_io_wait_readable(fd)) {
610 goto retry;
612 rb_sys_fail("recvfrom(2)");
614 if (slen < RSTRING(str)->len) {
615 RSTRING(str)->len = slen;
616 RSTRING(str)->ptr[slen] = '\0';
618 rb_obj_taint(str);
619 switch (from) {
620 case RECV_RECV:
621 return (VALUE)str;
622 case RECV_IP:
623 #if 0
624 if (alen != sizeof(struct sockaddr_in)) {
625 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
627 #endif
628 if (alen) /* OSX doesn't return a 'from' result from recvfrom for connection-oriented sockets */
629 return rb_assoc_new(str, ipaddr((struct sockaddr*)buf));
630 else
631 return rb_assoc_new(str, Qnil);
633 #ifdef HAVE_SYS_UN_H
634 case RECV_UNIX:
635 return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf, alen));
636 #endif
637 case RECV_SOCKET:
638 return rb_assoc_new(str, rb_str_new(buf, alen));
639 default:
640 rb_bug("s_recvfrom called with bad value");
644 static VALUE
645 s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
647 OpenFile *fptr;
648 VALUE str;
649 char buf[1024];
650 socklen_t alen = sizeof buf;
651 VALUE len, flg;
652 long buflen;
653 long slen;
654 int fd, flags;
655 VALUE addr = Qnil;
657 rb_scan_args(argc, argv, "11", &len, &flg);
659 if (flg == Qnil) flags = 0;
660 else flags = NUM2INT(flg);
661 buflen = NUM2INT(len);
663 #ifdef MSG_DONTWAIT
664 /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
665 It is not portable, though. */
666 flags |= MSG_DONTWAIT;
667 #endif
669 GetOpenFile(sock, fptr);
670 if (rb_read_pending(fptr->f)) {
671 rb_raise(rb_eIOError, "recvfrom for buffered IO");
673 fd = fileno(fptr->f);
675 str = rb_tainted_str_new(0, buflen);
677 rb_io_check_closed(fptr);
678 rb_io_set_nonblock(fptr);
679 slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct sockaddr*)buf, &alen);
681 if (slen < 0) {
682 rb_sys_fail("recvfrom(2)");
684 if (slen < RSTRING(str)->len) {
685 RSTRING(str)->len = slen;
686 RSTRING(str)->ptr[slen] = '\0';
688 rb_obj_taint(str);
689 switch (from) {
690 case RECV_RECV:
691 return str;
693 case RECV_IP:
694 if (alen) /* connection-oriented socket may not return a from result */
695 addr = ipaddr((struct sockaddr*)buf);
696 break;
698 case RECV_SOCKET:
699 addr = rb_str_new(buf, alen);
700 break;
702 default:
703 rb_bug("s_recvfrom_nonblock called with bad value");
705 return rb_assoc_new(str, addr);
708 static VALUE
709 bsock_recv(argc, argv, sock)
710 int argc;
711 VALUE *argv;
712 VALUE sock;
714 return s_recvfrom(sock, argc, argv, RECV_RECV);
718 * call-seq:
719 * basicsocket.recv_nonblock(maxlen) => mesg
720 * basicsocket.recv_nonblock(maxlen, flags) => mesg
722 * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
723 * O_NONBLOCK is set for the underlying file descriptor.
724 * _flags_ is zero or more of the +MSG_+ options.
725 * The result, _mesg_, is the data received.
727 * When recvfrom(2) returns 0, Socket#recv_nonblock returns
728 * an empty string as data.
729 * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
731 * === Parameters
732 * * +maxlen+ - the number of bytes to receive from the socket
733 * * +flags+ - zero or more of the +MSG_+ options
735 * === Example
736 * serv = TCPServer.new("127.0.0.1", 0)
737 * af, port, host, addr = serv.addr
738 * c = TCPSocket.new(addr, port)
739 * s = serv.accept
740 * c.send "aaa", 0
741 * IO.select([s])
742 * p s.recv_nonblock(10) #=> "aaa"
744 * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
745 * to _recv_nonblock_ fails.
747 * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
748 * including Errno::EAGAIN.
750 * === See
751 * * Socket#recvfrom
754 static VALUE
755 bsock_recv_nonblock(argc, argv, sock)
756 int argc;
757 VALUE *argv;
758 VALUE sock;
760 return s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
763 static VALUE
764 bsock_do_not_rev_lookup()
766 return do_not_reverse_lookup?Qtrue:Qfalse;
769 static VALUE
770 bsock_do_not_rev_lookup_set(self, val)
771 VALUE self, val;
773 rb_secure(4);
774 do_not_reverse_lookup = RTEST(val);
775 return val;
778 static void
779 make_ipaddr0(addr, buf, len)
780 struct sockaddr *addr;
781 char *buf;
782 size_t len;
784 int error;
786 error = getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
787 if (error) {
788 rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
792 static VALUE
793 make_ipaddr(addr)
794 struct sockaddr *addr;
796 char buf[1024];
798 make_ipaddr0(addr, buf, sizeof(buf));
799 return rb_str_new2(buf);
802 static void
803 make_inetaddr(host, buf, len)
804 long host;
805 char *buf;
806 size_t len;
808 struct sockaddr_in sin;
810 MEMZERO(&sin, struct sockaddr_in, 1);
811 sin.sin_family = AF_INET;
812 SET_SIN_LEN(&sin, sizeof(sin));
813 sin.sin_addr.s_addr = host;
814 make_ipaddr0((struct sockaddr*)&sin, buf, len);
817 static int
818 str_isnumber(p)
819 const char *p;
821 char *ep;
823 if (!p || *p == '\0')
824 return 0;
825 ep = NULL;
826 (void)strtoul(p, &ep, 10);
827 if (ep && *ep == '\0')
828 return 1;
829 else
830 return 0;
833 static char *
834 host_str(host, hbuf, len)
835 VALUE host;
836 char *hbuf;
837 size_t len;
839 if (NIL_P(host)) {
840 return NULL;
842 else if (rb_obj_is_kind_of(host, rb_cInteger)) {
843 long i = NUM2LONG(host);
845 make_inetaddr(htonl(i), hbuf, len);
846 return hbuf;
848 else {
849 char *name;
851 SafeStringValue(host);
852 name = RSTRING(host)->ptr;
853 if (!name || *name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) {
854 make_inetaddr(INADDR_ANY, hbuf, len);
856 else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
857 make_inetaddr(INADDR_BROADCAST, hbuf, len);
859 else if (strlen(name) >= len) {
860 rb_raise(rb_eArgError, "hostname too long (%d)", strlen(name));
862 else {
863 strcpy(hbuf, name);
865 return hbuf;
869 static char *
870 port_str(port, pbuf, len)
871 VALUE port;
872 char *pbuf;
873 size_t len;
875 if (NIL_P(port)) {
876 return 0;
878 else if (FIXNUM_P(port)) {
879 snprintf(pbuf, len, "%ld", FIX2LONG(port));
880 return pbuf;
882 else {
883 char *serv;
885 SafeStringValue(port);
886 serv = RSTRING(port)->ptr;
887 if (strlen(serv) >= len) {
888 rb_raise(rb_eArgError, "service name too long (%d)", strlen(serv));
890 strcpy(pbuf, serv);
891 return pbuf;
895 #ifndef NI_MAXHOST
896 # define 1025
897 #endif
898 #ifndef NI_MAXSERV
899 # define 32
900 #endif
902 static struct addrinfo*
903 sock_addrinfo(host, port, socktype, flags)
904 VALUE host, port;
905 int socktype, flags;
907 struct addrinfo hints;
908 struct addrinfo* res = NULL;
909 char *hostp, *portp;
910 int error;
911 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
913 hostp = host_str(host, hbuf, sizeof(hbuf));
914 portp = port_str(port, pbuf, sizeof(pbuf));
916 if (socktype == 0 && flags == 0 && str_isnumber(portp)) {
917 socktype = SOCK_DGRAM;
920 MEMZERO(&hints, struct addrinfo, 1);
921 hints.ai_family = AF_UNSPEC;
922 hints.ai_socktype = socktype;
923 hints.ai_flags = flags;
924 error = getaddrinfo(hostp, portp, &hints, &res);
925 if (error) {
926 if (hostp && hostp[strlen(hostp)-1] == '\n') {
927 rb_raise(rb_eSocket, "newline at the end of hostname");
929 rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
932 #if defined(__APPLE__) && defined(__MACH__)
934 struct addrinfo *r;
935 r = res;
936 while (r) {
937 if (! r->ai_socktype) r->ai_socktype = hints.ai_socktype;
938 if (! r->ai_protocol) {
939 if (r->ai_socktype == SOCK_DGRAM) {
940 r->ai_protocol = IPPROTO_UDP;
941 } else if (r->ai_socktype == SOCK_STREAM) {
942 r->ai_protocol = IPPROTO_TCP;
945 r = r->ai_next;
948 #endif
949 return res;
952 static VALUE
953 ipaddr(sockaddr)
954 struct sockaddr *sockaddr;
956 VALUE family, port, addr1, addr2;
957 VALUE ary;
958 int error;
959 char hbuf[1024], pbuf[1024];
961 switch (sockaddr->sa_family) {
962 case AF_UNSPEC:
963 family = rb_str_new2("AF_UNSPEC");
964 break;
965 case AF_INET:
966 family = rb_str_new2("AF_INET");
967 break;
968 #ifdef INET6
969 case AF_INET6:
970 family = rb_str_new2("AF_INET6");
971 break;
972 #endif
973 #ifdef AF_LOCAL
974 case AF_LOCAL:
975 family = rb_str_new2("AF_LOCAL");
976 break;
977 #elif AF_UNIX
978 case AF_UNIX:
979 family = rb_str_new2("AF_UNIX");
980 break;
981 #endif
982 default:
983 sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
984 family = rb_str_new2(pbuf);
985 break;
987 addr1 = Qnil;
988 if (!do_not_reverse_lookup) {
989 error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
990 NULL, 0, 0);
991 if (! error) {
992 addr1 = rb_str_new2(hbuf);
995 error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
996 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
997 if (error) {
998 rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
1000 addr2 = rb_str_new2(hbuf);
1001 if (addr1 == Qnil) {
1002 addr1 = addr2;
1004 port = INT2FIX(atoi(pbuf));
1005 ary = rb_ary_new3(4, family, port, addr1, addr2);
1007 return ary;
1010 static int
1011 ruby_socket(domain, type, proto)
1012 int domain, type, proto;
1014 int fd;
1016 fd = socket(domain, type, proto);
1017 if (fd < 0) {
1018 if (errno == EMFILE || errno == ENFILE) {
1019 rb_gc();
1020 fd = socket(domain, type, proto);
1023 return fd;
1026 static int
1027 wait_connectable(fd)
1028 int fd;
1030 int sockerr;
1031 socklen_t sockerrlen;
1032 fd_set fds_w;
1033 fd_set fds_e;
1035 for (;;) {
1036 FD_ZERO(&fds_w);
1037 FD_ZERO(&fds_e);
1039 FD_SET(fd, &fds_w);
1040 FD_SET(fd, &fds_e);
1042 rb_thread_select(fd+1, 0, &fds_w, &fds_e, 0);
1044 if (FD_ISSET(fd, &fds_w)) {
1045 return 0;
1047 else if (FD_ISSET(fd, &fds_e)) {
1048 sockerrlen = sizeof(sockerr);
1049 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
1050 &sockerrlen) == 0) {
1051 if (sockerr == 0)
1052 continue; /* workaround for winsock */
1053 errno = sockerr;
1055 return -1;
1059 return 0;
1062 #ifdef __CYGWIN__
1063 #define WAIT_IN_PROGRESS 10
1064 #endif
1065 #ifdef __APPLE__
1066 #define WAIT_IN_PROGRESS 10
1067 #endif
1068 #ifdef __linux__
1069 /* returns correct error */
1070 #define WAIT_IN_PROGRESS 0
1071 #endif
1072 #ifndef WAIT_IN_PROGRESS
1073 /* BSD origin code apparently has a problem */
1074 #define WAIT_IN_PROGRESS 1
1075 #endif
1077 static int
1078 ruby_connect(fd, sockaddr, len, socks)
1079 int fd;
1080 struct sockaddr *sockaddr;
1081 int len;
1082 int socks;
1084 int status;
1085 int mode;
1086 #if WAIT_IN_PROGRESS > 0
1087 int wait_in_progress = -1;
1088 int sockerr;
1089 socklen_t sockerrlen;
1090 #endif
1092 #if defined(HAVE_FCNTL)
1093 # if defined(F_GETFL)
1094 mode = fcntl(fd, F_GETFL, 0);
1095 # else
1096 mode = 0;
1097 # endif
1099 #ifdef O_NDELAY
1100 # define NONBLOCKING O_NDELAY
1101 #else
1102 #ifdef O_NBIO
1103 # define NONBLOCKING O_NBIO
1104 #else
1105 # define NONBLOCKING O_NONBLOCK
1106 #endif
1107 #endif
1108 #ifdef SOCKS5
1109 if (!socks)
1110 #endif
1111 fcntl(fd, F_SETFL, mode|NONBLOCKING);
1112 #endif /* HAVE_FCNTL */
1114 for (;;) {
1115 #if defined(SOCKS) && !defined(SOCKS5)
1116 if (socks) {
1117 status = Rconnect(fd, sockaddr, len);
1119 else
1120 #endif
1122 status = connect(fd, sockaddr, len);
1124 if (status < 0) {
1125 switch (errno) {
1126 case EAGAIN:
1127 #ifdef EINPROGRESS
1128 case EINPROGRESS:
1129 #endif
1130 #if WAIT_IN_PROGRESS > 0
1131 sockerrlen = sizeof(sockerr);
1132 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
1133 if (status) break;
1134 if (sockerr) {
1135 status = -1;
1136 errno = sockerr;
1137 break;
1139 #endif
1140 #ifdef EALREADY
1141 case EALREADY:
1142 #endif
1143 #if WAIT_IN_PROGRESS > 0
1144 wait_in_progress = WAIT_IN_PROGRESS;
1145 #endif
1146 status = wait_connectable(fd);
1147 if (status) {
1148 break;
1150 errno = 0;
1151 continue;
1153 #if WAIT_IN_PROGRESS > 0
1154 case EINVAL:
1155 if (wait_in_progress-- > 0) {
1157 * connect() after EINPROGRESS returns EINVAL on
1158 * some platforms, need to check true error
1159 * status.
1161 sockerrlen = sizeof(sockerr);
1162 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
1163 if (!status && !sockerr) {
1164 struct timeval tv = {0, 100000};
1165 rb_thread_wait_for(tv);
1166 continue;
1168 status = -1;
1169 errno = sockerr;
1171 break;
1172 #endif
1174 #ifdef EISCONN
1175 case EISCONN:
1176 status = 0;
1177 errno = 0;
1178 break;
1179 #endif
1180 default:
1181 break;
1184 #ifdef HAVE_FCNTL
1185 fcntl(fd, F_SETFL, mode);
1186 #endif
1187 return status;
1191 struct inetsock_arg
1193 VALUE sock;
1194 struct {
1195 VALUE host, serv;
1196 struct addrinfo *res;
1197 } remote, local;
1198 int type;
1199 int fd;
1202 static VALUE
1203 inetsock_cleanup(arg)
1204 struct inetsock_arg *arg;
1206 if (arg->remote.res) {
1207 freeaddrinfo(arg->remote.res);
1208 arg->remote.res = 0;
1210 if (arg->local.res) {
1211 freeaddrinfo(arg->local.res);
1212 arg->local.res = 0;
1214 if (arg->fd >= 0) {
1215 close(arg->fd);
1217 return Qnil;
1220 static VALUE
1221 init_inetsock_internal(arg)
1222 struct inetsock_arg *arg;
1224 int type = arg->type;
1225 struct addrinfo *res;
1226 int fd, status = 0;
1227 char *syscall;
1229 arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
1230 (type == INET_SERVER) ? AI_PASSIVE : 0);
1232 * Maybe also accept a local address
1235 if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
1236 arg->local.res = sock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0);
1239 arg->fd = fd = -1;
1240 for (res = arg->remote.res; res; res = res->ai_next) {
1241 status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
1242 syscall = "socket(2)";
1243 fd = status;
1244 if (fd < 0) {
1245 continue;
1247 arg->fd = fd;
1248 if (type == INET_SERVER) {
1249 #if !defined(_WIN32) && !defined(__CYGWIN__)
1250 status = 1;
1251 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1252 (char*)&status, sizeof(status));
1253 #endif
1254 status = bind(fd, res->ai_addr, res->ai_addrlen);
1255 syscall = "bind(2)";
1257 else {
1258 if (arg->local.res) {
1259 status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
1260 syscall = "bind(2)";
1263 if (status >= 0) {
1264 status = ruby_connect(fd, res->ai_addr, res->ai_addrlen,
1265 (type == INET_SOCKS));
1266 syscall = "connect(2)";
1270 if (status < 0) {
1271 close(fd);
1272 arg->fd = fd = -1;
1273 continue;
1274 } else
1275 break;
1277 if (status < 0) {
1278 rb_sys_fail(syscall);
1281 arg->fd = -1;
1283 if (type == INET_SERVER)
1284 listen(fd, 5);
1286 /* create new instance */
1287 return init_sock(arg->sock, fd);
1290 static VALUE
1291 init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type)
1292 VALUE sock, remote_host, remote_serv, local_host, local_serv;
1293 int type;
1295 struct inetsock_arg arg;
1296 arg.sock = sock;
1297 arg.remote.host = remote_host;
1298 arg.remote.serv = remote_serv;
1299 arg.remote.res = 0;
1300 arg.local.host = local_host;
1301 arg.local.serv = local_serv;
1302 arg.local.res = 0;
1303 arg.type = type;
1304 arg.fd = -1;
1305 return rb_ensure(init_inetsock_internal, (VALUE)&arg,
1306 inetsock_cleanup, (VALUE)&arg);
1310 * call-seq:
1311 * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil)
1313 * Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+
1314 * and +local_port+ are specified, then those parameters are used on the local
1315 * end to establish the connection.
1317 static VALUE
1318 tcp_init(argc, argv, sock)
1319 int argc;
1320 VALUE *argv;
1321 VALUE sock;
1323 VALUE remote_host, remote_serv;
1324 VALUE local_host, local_serv;
1326 rb_scan_args(argc, argv, "22", &remote_host, &remote_serv,
1327 &local_host, &local_serv);
1329 return init_inetsock(sock, remote_host, remote_serv,
1330 local_host, local_serv, INET_CLIENT);
1333 #ifdef SOCKS
1334 static VALUE
1335 socks_init(sock, host, serv)
1336 VALUE sock, host, serv;
1338 static init = 0;
1340 if (init == 0) {
1341 SOCKSinit("ruby");
1342 init = 1;
1345 return init_inetsock(sock, host, serv, Qnil, Qnil, INET_SOCKS);
1348 #ifdef SOCKS5
1349 static VALUE
1350 socks_s_close(sock)
1351 VALUE sock;
1353 OpenFile *fptr;
1355 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
1356 rb_raise(rb_eSecurityError, "Insecure: can't close socket");
1358 GetOpenFile(sock, fptr);
1359 shutdown(fileno(fptr->f), 2);
1360 shutdown(fileno(fptr->f2), 2);
1361 return rb_io_close(sock);
1363 #endif
1364 #endif
1366 struct hostent_arg {
1367 VALUE host;
1368 struct addrinfo* addr;
1369 VALUE (*ipaddr)_((struct sockaddr*, size_t));
1372 static VALUE
1373 make_hostent_internal(arg)
1374 struct hostent_arg *arg;
1376 VALUE host = arg->host;
1377 struct addrinfo* addr = arg->addr;
1378 VALUE (*ipaddr)_((struct sockaddr*, size_t)) = arg->ipaddr;
1380 struct addrinfo *ai;
1381 struct hostent *h;
1382 VALUE ary, names;
1383 char **pch;
1384 const char* hostp;
1385 char hbuf[NI_MAXHOST];
1387 ary = rb_ary_new();
1388 if (addr->ai_canonname) {
1389 hostp = addr->ai_canonname;
1391 else {
1392 hostp = host_str(host, hbuf, sizeof(hbuf));
1394 rb_ary_push(ary, rb_str_new2(hostp));
1396 if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
1397 names = rb_ary_new();
1398 if (h->h_aliases != NULL) {
1399 for (pch = h->h_aliases; *pch; pch++) {
1400 rb_ary_push(names, rb_str_new2(*pch));
1404 else {
1405 names = rb_ary_new2(0);
1407 rb_ary_push(ary, names);
1408 rb_ary_push(ary, INT2NUM(addr->ai_family));
1409 for (ai = addr; ai; ai = ai->ai_next) {
1410 /* Pushing all addresses regardless of address family is not the
1411 * behaviour expected of gethostbyname(). All the addresses in struct
1412 * hostent->h_addr_list must be of the same family.
1414 if(ai->ai_family == addr->ai_family) {
1415 rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
1419 return ary;
1422 static VALUE
1423 make_hostent(host, addr, ipaddr)
1424 VALUE host;
1425 struct addrinfo* addr;
1426 VALUE (*ipaddr)_((struct sockaddr*, size_t));
1428 struct hostent_arg arg;
1430 arg.host = host;
1431 arg.addr = addr;
1432 arg.ipaddr = ipaddr;
1433 return rb_ensure(make_hostent_internal, (VALUE)&arg,
1434 RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)addr);
1437 VALUE
1438 tcp_sockaddr(addr, len)
1439 struct sockaddr *addr;
1440 size_t len;
1442 return make_ipaddr(addr);
1445 static VALUE
1446 tcp_s_gethostbyname(obj, host)
1447 VALUE obj, host;
1449 rb_secure(3);
1450 return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), tcp_sockaddr);
1453 static VALUE
1454 tcp_svr_init(argc, argv, sock)
1455 int argc;
1456 VALUE *argv;
1457 VALUE sock;
1459 VALUE arg1, arg2;
1461 if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2)
1462 return init_inetsock(sock, arg1, arg2, Qnil, Qnil, INET_SERVER);
1463 else
1464 return init_inetsock(sock, Qnil, arg1, Qnil, Qnil, INET_SERVER);
1467 static VALUE
1468 s_accept_nonblock(VALUE klass, OpenFile *fptr, struct sockaddr *sockaddr, socklen_t *len)
1470 int fd2;
1472 rb_secure(3);
1473 rb_io_set_nonblock(fptr);
1474 fd2 = accept(fileno(fptr->f), (struct sockaddr*)sockaddr, len);
1475 if (fd2 < 0) {
1476 rb_sys_fail("accept(2)");
1478 return init_sock(rb_obj_alloc(klass), fd2);
1481 static VALUE
1482 s_accept(klass, fd, sockaddr, len)
1483 VALUE klass;
1484 int fd;
1485 struct sockaddr *sockaddr;
1486 socklen_t *len;
1488 int fd2;
1489 int retry = 0;
1491 rb_secure(3);
1492 retry:
1493 rb_thread_wait_fd(fd);
1494 #if defined(_nec_ews)
1495 fd2 = accept(fd, sockaddr, len);
1496 #else
1497 TRAP_BEG;
1498 fd2 = accept(fd, sockaddr, len);
1499 TRAP_END;
1500 #endif
1501 if (fd2 < 0) {
1502 switch (errno) {
1503 case EMFILE:
1504 case ENFILE:
1505 if (retry) break;
1506 rb_gc();
1507 retry = 1;
1508 goto retry;
1509 case EWOULDBLOCK:
1510 break;
1511 default:
1512 if (!rb_io_wait_readable(fd)) break;
1513 retry = 0;
1514 goto retry;
1516 rb_sys_fail(0);
1518 if (!klass) return INT2NUM(fd2);
1519 return init_sock(rb_obj_alloc(klass), fd2);
1522 static VALUE
1523 tcp_accept(sock)
1524 VALUE sock;
1526 OpenFile *fptr;
1527 struct sockaddr_storage from;
1528 socklen_t fromlen;
1530 GetOpenFile(sock, fptr);
1531 fromlen = sizeof(from);
1532 return s_accept(rb_cTCPSocket, fileno(fptr->f),
1533 (struct sockaddr*)&from, &fromlen);
1537 * call-seq:
1538 * tcpserver.accept_nonblock => tcpsocket
1540 * Accepts an incoming connection using accept(2) after
1541 * O_NONBLOCK is set for the underlying file descriptor.
1542 * It returns an accepted TCPSocket for the incoming connection.
1544 * === Example
1545 * require 'socket'
1546 * serv = TCPServer.new(2202)
1547 * begin
1548 * sock = serv.accept_nonblock
1549 * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
1550 * IO.select([serv])
1551 * retry
1552 * end
1553 * # sock is an accepted socket.
1555 * Refer to Socket#accept for the exceptions that may be thrown if the call
1556 * to TCPServer#accept_nonblock fails.
1558 * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure,
1559 * including Errno::EAGAIN.
1561 * === See
1562 * * TCPServer#accept
1563 * * Socket#accept
1565 static VALUE
1566 tcp_accept_nonblock(sock)
1567 VALUE sock;
1569 OpenFile *fptr;
1570 struct sockaddr_storage from;
1571 socklen_t fromlen;
1573 GetOpenFile(sock, fptr);
1574 fromlen = sizeof(from);
1575 return s_accept_nonblock(rb_cTCPSocket, fptr,
1576 (struct sockaddr *)&from, &fromlen);
1579 static VALUE
1580 tcp_sysaccept(sock)
1581 VALUE sock;
1583 OpenFile *fptr;
1584 struct sockaddr_storage from;
1585 socklen_t fromlen;
1587 GetOpenFile(sock, fptr);
1588 fromlen = sizeof(from);
1589 return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen);
1592 #ifdef HAVE_SYS_UN_H
1593 struct unixsock_arg {
1594 struct sockaddr_un *sockaddr;
1595 int fd;
1598 static VALUE
1599 unixsock_connect_internal(arg)
1600 struct unixsock_arg *arg;
1602 return (VALUE)ruby_connect(arg->fd, arg->sockaddr, sizeof(*arg->sockaddr),
1606 static VALUE
1607 init_unixsock(sock, path, server)
1608 VALUE sock;
1609 VALUE path;
1610 int server;
1612 struct sockaddr_un sockaddr;
1613 int fd, status;
1614 OpenFile *fptr;
1616 SafeStringValue(path);
1617 fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
1618 if (fd < 0) {
1619 rb_sys_fail("socket(2)");
1622 MEMZERO(&sockaddr, struct sockaddr_un, 1);
1623 sockaddr.sun_family = AF_UNIX;
1624 if (sizeof(sockaddr.sun_path) <= RSTRING(path)->len) {
1625 rb_raise(rb_eArgError, "too long unix socket path (max: %dbytes)",
1626 (int)sizeof(sockaddr.sun_path)-1);
1628 strcpy(sockaddr.sun_path, StringValueCStr(path));
1630 if (server) {
1631 status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
1633 else {
1634 int prot;
1635 struct unixsock_arg arg;
1636 arg.sockaddr = &sockaddr;
1637 arg.fd = fd;
1638 status = rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot);
1639 if (prot) {
1640 close(fd);
1641 rb_jump_tag(prot);
1645 if (status < 0) {
1646 close(fd);
1647 rb_sys_fail(sockaddr.sun_path);
1650 if (server) listen(fd, 5);
1652 init_sock(sock, fd);
1653 GetOpenFile(sock, fptr);
1654 if (server) {
1655 fptr->path = strdup(RSTRING(path)->ptr);
1658 return sock;
1660 #endif
1662 static VALUE
1663 ip_addr(sock)
1664 VALUE sock;
1666 OpenFile *fptr;
1667 struct sockaddr_storage addr;
1668 socklen_t len = sizeof addr;
1670 GetOpenFile(sock, fptr);
1672 if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1673 rb_sys_fail("getsockname(2)");
1674 return ipaddr((struct sockaddr*)&addr);
1677 static VALUE
1678 ip_peeraddr(sock)
1679 VALUE sock;
1681 OpenFile *fptr;
1682 struct sockaddr_storage addr;
1683 socklen_t len = sizeof addr;
1685 GetOpenFile(sock, fptr);
1687 if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1688 rb_sys_fail("getpeername(2)");
1689 return ipaddr((struct sockaddr*)&addr);
1692 static VALUE
1693 ip_recvfrom(argc, argv, sock)
1694 int argc;
1695 VALUE *argv;
1696 VALUE sock;
1698 return s_recvfrom(sock, argc, argv, RECV_IP);
1701 static VALUE
1702 ip_s_getaddress(obj, host)
1703 VALUE obj, host;
1705 struct sockaddr_storage addr;
1706 struct addrinfo *res = sock_addrinfo(host, Qnil, SOCK_STREAM, 0);
1708 /* just take the first one */
1709 memcpy(&addr, res->ai_addr, res->ai_addrlen);
1710 freeaddrinfo(res);
1712 return make_ipaddr((struct sockaddr*)&addr);
1715 static VALUE
1716 udp_init(argc, argv, sock)
1717 int argc;
1718 VALUE *argv;
1719 VALUE sock;
1721 VALUE arg;
1722 int socktype = AF_INET;
1723 int fd;
1725 rb_secure(3);
1726 if (rb_scan_args(argc, argv, "01", &arg) == 1) {
1727 socktype = NUM2INT(arg);
1729 fd = ruby_socket(socktype, SOCK_DGRAM, 0);
1730 if (fd < 0) {
1731 rb_sys_fail("socket(2) - udp");
1734 return init_sock(sock, fd);
1737 struct udp_arg
1739 struct addrinfo *res;
1740 int fd;
1743 static VALUE
1744 udp_connect_internal(arg)
1745 struct udp_arg *arg;
1747 int fd = arg->fd;
1748 struct addrinfo *res;
1750 for (res = arg->res; res; res = res->ai_next) {
1751 if (ruby_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
1752 return Qtrue;
1755 return Qfalse;
1758 static VALUE
1759 udp_connect(sock, host, port)
1760 VALUE sock, host, port;
1762 OpenFile *fptr;
1763 struct udp_arg arg;
1764 VALUE ret;
1766 rb_secure(3);
1767 arg.res = sock_addrinfo(host, port, SOCK_DGRAM, 0);
1768 GetOpenFile(sock, fptr);
1769 arg.fd = fileno(fptr->f);
1770 ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
1771 RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)arg.res);
1772 if (!ret) rb_sys_fail("connect(2)");
1773 return INT2FIX(0);
1776 static VALUE
1777 udp_bind(sock, host, port)
1778 VALUE sock, host, port;
1780 OpenFile *fptr;
1781 struct addrinfo *res0, *res;
1783 rb_secure(3);
1784 res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
1785 GetOpenFile(sock, fptr);
1786 for (res = res0; res; res = res->ai_next) {
1787 if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
1788 continue;
1790 freeaddrinfo(res0);
1791 return INT2FIX(0);
1793 freeaddrinfo(res0);
1794 rb_sys_fail("bind(2)");
1795 return INT2FIX(0);
1798 static VALUE
1799 udp_send(argc, argv, sock)
1800 int argc;
1801 VALUE *argv;
1802 VALUE sock;
1804 VALUE mesg, flags, host, port;
1805 OpenFile *fptr;
1806 FILE *f;
1807 int n;
1808 struct addrinfo *res0, *res;
1810 if (argc == 2 || argc == 3) {
1811 return bsock_send(argc, argv, sock);
1813 rb_secure(4);
1814 rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
1816 StringValue(mesg);
1817 res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
1818 GetOpenFile(sock, fptr);
1819 f = GetWriteFile(fptr);
1820 for (res = res0; res; res = res->ai_next) {
1821 retry:
1822 n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
1823 res->ai_addr, res->ai_addrlen);
1824 if (n >= 0) {
1825 freeaddrinfo(res0);
1826 return INT2FIX(n);
1828 if (rb_io_wait_writable(fileno(f))) {
1829 goto retry;
1832 freeaddrinfo(res0);
1833 rb_sys_fail("sendto(2)");
1834 return INT2FIX(n);
1838 * call-seq:
1839 * udpsocket.recvfrom_nonblock(maxlen) => [mesg, sender_inet_addr]
1840 * udpsocket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_inet_addr]
1842 * Receives up to _maxlen_ bytes from +udpsocket+ using recvfrom(2) after
1843 * O_NONBLOCK is set for the underlying file descriptor.
1844 * _flags_ is zero or more of the +MSG_+ options.
1845 * The first element of the results, _mesg_, is the data received.
1846 * The second element, _sender_inet_addr_, is an array to represent the sender address.
1848 * When recvfrom(2) returns 0,
1849 * Socket#recvfrom_nonblock returns an empty string as data.
1850 * It means an empty packet.
1852 * === Parameters
1853 * * +maxlen+ - the number of bytes to receive from the socket
1854 * * +flags+ - zero or more of the +MSG_+ options
1856 * === Example
1857 * require 'socket'
1858 * s1 = UDPSocket.new
1859 * s1.bind("127.0.0.1", 0)
1860 * s2 = UDPSocket.new
1861 * s2.bind("127.0.0.1", 0)
1862 * s2.connect(*s1.addr.values_at(3,1))
1863 * s1.connect(*s2.addr.values_at(3,1))
1864 * s1.send "aaa", 0
1865 * IO.select([s2])
1866 * p s2.recvfrom_nonblock(10) #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
1868 * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
1869 * to _recvfrom_nonblock_ fails.
1871 * UDPSocket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
1872 * including Errno::EAGAIN.
1874 * === See
1875 * * Socket#recvfrom
1877 static VALUE
1878 udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
1880 return s_recvfrom_nonblock(sock, argc, argv, RECV_IP);
1883 #ifdef HAVE_SYS_UN_H
1884 static VALUE
1885 unix_init(sock, path)
1886 VALUE sock, path;
1888 return init_unixsock(sock, path, 0);
1891 static char *
1892 unixpath(struct sockaddr_un *sockaddr, socklen_t len)
1894 if (sockaddr->sun_path < (char*)sockaddr + len)
1895 return sockaddr->sun_path;
1896 else
1897 return "";
1900 static VALUE
1901 unix_path(sock)
1902 VALUE sock;
1904 OpenFile *fptr;
1906 GetOpenFile(sock, fptr);
1907 if (fptr->path == 0) {
1908 struct sockaddr_un addr;
1909 socklen_t len = sizeof(addr);
1910 if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1911 rb_sys_fail(0);
1912 fptr->path = strdup(unixpath(&addr, len));
1914 return rb_str_new2(fptr->path);
1917 static VALUE
1918 unix_svr_init(sock, path)
1919 VALUE sock, path;
1921 return init_unixsock(sock, path, 1);
1924 static VALUE
1925 unix_recvfrom(argc, argv, sock)
1926 int argc;
1927 VALUE *argv;
1928 VALUE sock;
1930 return s_recvfrom(sock, argc, argv, RECV_UNIX);
1933 #if defined(HAVE_ST_MSG_CONTROL) && defined(SCM_RIGHTS)
1934 #define FD_PASSING_BY_MSG_CONTROL 1
1935 #else
1936 #define FD_PASSING_BY_MSG_CONTROL 0
1937 #endif
1939 #if defined(HAVE_ST_MSG_ACCRIGHTS)
1940 #define FD_PASSING_BY_MSG_ACCRIGHTS 1
1941 #else
1942 #define FD_PASSING_BY_MSG_ACCRIGHTS 0
1943 #endif
1945 static VALUE
1946 unix_send_io(sock, val)
1947 VALUE sock, val;
1949 #if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
1950 int fd;
1951 OpenFile *fptr;
1952 struct msghdr msg;
1953 struct iovec vec[1];
1954 char buf[1];
1956 #if FD_PASSING_BY_MSG_CONTROL
1957 struct {
1958 struct cmsghdr hdr;
1959 int fd;
1960 } cmsg;
1961 #endif
1963 if (rb_obj_is_kind_of(val, rb_cIO)) {
1964 OpenFile *valfptr;
1965 GetOpenFile(val, valfptr);
1966 fd = fileno(valfptr->f);
1968 else if (FIXNUM_P(val)) {
1969 fd = FIX2INT(val);
1971 else {
1972 rb_raise(rb_eTypeError, "neither IO nor file descriptor");
1975 GetOpenFile(sock, fptr);
1977 msg.msg_name = NULL;
1978 msg.msg_namelen = 0;
1980 /* Linux and Solaris doesn't work if msg_iov is NULL. */
1981 buf[0] = '\0';
1982 vec[0].iov_base = buf;
1983 vec[0].iov_len = 1;
1984 msg.msg_iov = vec;
1985 msg.msg_iovlen = 1;
1987 #if FD_PASSING_BY_MSG_CONTROL
1988 msg.msg_control = (caddr_t)&cmsg;
1989 msg.msg_controllen = CMSG_SPACE(sizeof(int));
1990 msg.msg_flags = 0;
1991 cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
1992 cmsg.hdr.cmsg_level = SOL_SOCKET;
1993 cmsg.hdr.cmsg_type = SCM_RIGHTS;
1994 cmsg.fd = fd;
1995 #else
1996 msg.msg_accrights = (caddr_t)&fd;
1997 msg.msg_accrightslen = sizeof(fd);
1998 #endif
2000 if (sendmsg(fileno(fptr->f), &msg, 0) == -1)
2001 rb_sys_fail("sendmsg(2)");
2003 return Qnil;
2004 #else
2005 rb_notimplement();
2006 return Qnil; /* not reached */
2007 #endif
2010 #if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
2011 static void
2012 thread_read_select(fd)
2013 int fd;
2015 fd_set fds;
2017 FD_ZERO(&fds);
2018 FD_SET(fd, &fds);
2019 rb_thread_select(fd+1, &fds, 0, 0, 0);
2021 #endif
2023 static VALUE
2024 unix_recv_io(argc, argv, sock)
2025 int argc;
2026 VALUE *argv;
2027 VALUE sock;
2029 #if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
2030 VALUE klass, mode;
2031 OpenFile *fptr;
2032 struct msghdr msg;
2033 struct iovec vec[2];
2034 char buf[1];
2036 int fd;
2037 #if FD_PASSING_BY_MSG_CONTROL
2038 struct {
2039 struct cmsghdr hdr;
2040 int fd;
2041 } cmsg;
2042 #endif
2044 rb_scan_args(argc, argv, "02", &klass, &mode);
2045 if (argc == 0)
2046 klass = rb_cIO;
2047 if (argc <= 1)
2048 mode = Qnil;
2050 GetOpenFile(sock, fptr);
2052 thread_read_select(fileno(fptr->f));
2054 msg.msg_name = NULL;
2055 msg.msg_namelen = 0;
2057 vec[0].iov_base = buf;
2058 vec[0].iov_len = sizeof(buf);
2059 msg.msg_iov = vec;
2060 msg.msg_iovlen = 1;
2062 #if FD_PASSING_BY_MSG_CONTROL
2063 msg.msg_control = (caddr_t)&cmsg;
2064 msg.msg_controllen = CMSG_SPACE(sizeof(int));
2065 msg.msg_flags = 0;
2066 cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
2067 cmsg.hdr.cmsg_level = SOL_SOCKET;
2068 cmsg.hdr.cmsg_type = SCM_RIGHTS;
2069 cmsg.fd = -1;
2070 #else
2071 msg.msg_accrights = (caddr_t)&fd;
2072 msg.msg_accrightslen = sizeof(fd);
2073 fd = -1;
2074 #endif
2076 if (recvmsg(fileno(fptr->f), &msg, 0) == -1)
2077 rb_sys_fail("recvmsg(2)");
2079 #if FD_PASSING_BY_MSG_CONTROL
2080 if (msg.msg_controllen != CMSG_SPACE(sizeof(int))) {
2081 rb_raise(rb_eSocket,
2082 "file descriptor was not passed (msg_controllen : %d != %d)",
2083 msg.msg_controllen, CMSG_SPACE(sizeof(int)));
2085 if (cmsg.hdr.cmsg_len != CMSG_SPACE(0) + sizeof(int)) {
2086 rb_raise(rb_eSocket,
2087 "file descriptor was not passed (cmsg_len : %d != %d)",
2088 cmsg.hdr.cmsg_len, CMSG_SPACE(0) + sizeof(int));
2090 if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
2091 rb_raise(rb_eSocket,
2092 "file descriptor was not passed (cmsg_level : %d != %d)",
2093 cmsg.hdr.cmsg_level, SOL_SOCKET);
2095 if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
2096 rb_raise(rb_eSocket,
2097 "file descriptor was not passed (cmsg_type : %d != %d)",
2098 cmsg.hdr.cmsg_type, SCM_RIGHTS);
2100 #else
2101 if (msg.msg_accrightslen != sizeof(fd)) {
2102 rb_raise(rb_eSocket,
2103 "file descriptor was not passed (accrightslen) : %d != %d",
2104 msg.msg_accrightslen, sizeof(fd));
2106 #endif
2108 #if FD_PASSING_BY_MSG_CONTROL
2109 fd = cmsg.fd;
2110 #endif
2112 if (klass == Qnil)
2113 return INT2FIX(fd);
2114 else {
2115 static ID for_fd = 0;
2116 int ff_argc;
2117 VALUE ff_argv[2];
2118 if (!for_fd)
2119 for_fd = rb_intern("for_fd");
2120 ff_argc = mode == Qnil ? 1 : 2;
2121 ff_argv[0] = INT2FIX(fd);
2122 ff_argv[1] = mode;
2123 return rb_funcall2(klass, for_fd, ff_argc, ff_argv);
2125 #else
2126 rb_notimplement();
2127 return Qnil; /* not reached */
2128 #endif
2131 static VALUE
2132 unix_accept(sock)
2133 VALUE sock;
2135 OpenFile *fptr;
2136 struct sockaddr_un from;
2137 socklen_t fromlen;
2139 GetOpenFile(sock, fptr);
2140 fromlen = sizeof(struct sockaddr_un);
2141 return s_accept(rb_cUNIXSocket, fileno(fptr->f),
2142 (struct sockaddr*)&from, &fromlen);
2146 * call-seq:
2147 * unixserver.accept_nonblock => unixsocket
2149 * Accepts an incoming connection using accept(2) after
2150 * O_NONBLOCK is set for the underlying file descriptor.
2151 * It returns an accepted UNIXSocket for the incoming connection.
2153 * === Example
2154 * require 'socket'
2155 * serv = UNIXServer.new("/tmp/sock")
2156 * begin
2157 * sock = serv.accept_nonblock
2158 * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
2159 * IO.select([serv])
2160 * retry
2161 * end
2162 * # sock is an accepted socket.
2164 * Refer to Socket#accept for the exceptions that may be thrown if the call
2165 * to UNIXServer#accept_nonblock fails.
2167 * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure,
2168 * including Errno::EAGAIN.
2170 * === See
2171 * * UNIXServer#accept
2172 * * Socket#accept
2174 static VALUE
2175 unix_accept_nonblock(sock)
2176 VALUE sock;
2178 OpenFile *fptr;
2179 struct sockaddr_un from;
2180 socklen_t fromlen;
2182 GetOpenFile(sock, fptr);
2183 fromlen = sizeof(from);
2184 return s_accept_nonblock(rb_cUNIXSocket, fptr,
2185 (struct sockaddr *)&from, &fromlen);
2188 static VALUE
2189 unix_sysaccept(sock)
2190 VALUE sock;
2192 OpenFile *fptr;
2193 struct sockaddr_un from;
2194 socklen_t fromlen;
2196 GetOpenFile(sock, fptr);
2197 fromlen = sizeof(struct sockaddr_un);
2198 return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen);
2201 static VALUE
2202 unixaddr(sockaddr, len)
2203 struct sockaddr_un *sockaddr;
2204 socklen_t len;
2206 return rb_assoc_new(rb_str_new2("AF_UNIX"),
2207 rb_str_new2(unixpath(sockaddr, len)));
2210 static VALUE
2211 unix_addr(sock)
2212 VALUE sock;
2214 OpenFile *fptr;
2215 struct sockaddr_un addr;
2216 socklen_t len = sizeof addr;
2218 GetOpenFile(sock, fptr);
2220 if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
2221 rb_sys_fail("getsockname(2)");
2222 return unixaddr(&addr, len);
2225 static VALUE
2226 unix_peeraddr(sock)
2227 VALUE sock;
2229 OpenFile *fptr;
2230 struct sockaddr_un addr;
2231 socklen_t len = sizeof addr;
2233 GetOpenFile(sock, fptr);
2235 if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
2236 rb_sys_fail("getpeername(2)");
2237 return unixaddr(&addr, len);
2239 #endif
2241 static void
2242 setup_domain_and_type(domain, dv, type, tv)
2243 VALUE domain, type;
2244 int *dv, *tv;
2246 VALUE tmp;
2247 char *ptr;
2249 tmp = rb_check_string_type(domain);
2250 if (!NIL_P(tmp)) {
2251 domain = tmp;
2252 rb_check_safe_obj(domain);
2253 ptr = RSTRING(domain)->ptr;
2254 if (strcmp(ptr, "AF_INET") == 0)
2255 *dv = AF_INET;
2256 #ifdef AF_UNIX
2257 else if (strcmp(ptr, "AF_UNIX") == 0)
2258 *dv = AF_UNIX;
2259 #endif
2260 #ifdef AF_ISO
2261 else if (strcmp(ptr, "AF_ISO") == 0)
2262 *dv = AF_ISO;
2263 #endif
2264 #ifdef AF_NS
2265 else if (strcmp(ptr, "AF_NS") == 0)
2266 *dv = AF_NS;
2267 #endif
2268 #ifdef AF_IMPLINK
2269 else if (strcmp(ptr, "AF_IMPLINK") == 0)
2270 *dv = AF_IMPLINK;
2271 #endif
2272 #ifdef PF_INET
2273 else if (strcmp(ptr, "PF_INET") == 0)
2274 *dv = PF_INET;
2275 #endif
2276 #ifdef PF_UNIX
2277 else if (strcmp(ptr, "PF_UNIX") == 0)
2278 *dv = PF_UNIX;
2279 #endif
2280 #ifdef PF_IMPLINK
2281 else if (strcmp(ptr, "PF_IMPLINK") == 0)
2282 *dv = PF_IMPLINK;
2283 else if (strcmp(ptr, "AF_IMPLINK") == 0)
2284 *dv = AF_IMPLINK;
2285 #endif
2286 #ifdef PF_AX25
2287 else if (strcmp(ptr, "PF_AX25") == 0)
2288 *dv = PF_AX25;
2289 #endif
2290 #ifdef PF_IPX
2291 else if (strcmp(ptr, "PF_IPX") == 0)
2292 *dv = PF_IPX;
2293 #endif
2294 else
2295 rb_raise(rb_eSocket, "unknown socket domain %s", ptr);
2297 else {
2298 *dv = NUM2INT(domain);
2300 tmp = rb_check_string_type(type);
2301 if (!NIL_P(tmp)) {
2302 type = tmp;
2303 rb_check_safe_obj(type);
2304 ptr = RSTRING(type)->ptr;
2305 if (strcmp(ptr, "SOCK_STREAM") == 0)
2306 *tv = SOCK_STREAM;
2307 else if (strcmp(ptr, "SOCK_DGRAM") == 0)
2308 *tv = SOCK_DGRAM;
2309 #ifdef SOCK_RAW
2310 else if (strcmp(ptr, "SOCK_RAW") == 0)
2311 *tv = SOCK_RAW;
2312 #endif
2313 #ifdef SOCK_SEQPACKET
2314 else if (strcmp(ptr, "SOCK_SEQPACKET") == 0)
2315 *tv = SOCK_SEQPACKET;
2316 #endif
2317 #ifdef SOCK_RDM
2318 else if (strcmp(ptr, "SOCK_RDM") == 0)
2319 *tv = SOCK_RDM;
2320 #endif
2321 #ifdef SOCK_PACKET
2322 else if (strcmp(ptr, "SOCK_PACKET") == 0)
2323 *tv = SOCK_PACKET;
2324 #endif
2325 else
2326 rb_raise(rb_eSocket, "unknown socket type %s", ptr);
2328 else {
2329 *tv = NUM2INT(type);
2333 static VALUE
2334 sock_initialize(sock, domain, type, protocol)
2335 VALUE sock, domain, type, protocol;
2337 int fd;
2338 int d, t;
2340 rb_secure(3);
2341 setup_domain_and_type(domain, &d, type, &t);
2342 fd = ruby_socket(d, t, NUM2INT(protocol));
2343 if (fd < 0) rb_sys_fail("socket(2)");
2345 return init_sock(sock, fd);
2348 static VALUE
2349 sock_s_socketpair(klass, domain, type, protocol)
2350 VALUE klass, domain, type, protocol;
2352 #if defined HAVE_SOCKETPAIR
2353 int d, t, p, sp[2];
2354 int ret;
2356 setup_domain_and_type(domain, &d, type, &t);
2357 p = NUM2INT(protocol);
2358 ret = socketpair(d, t, p, sp);
2359 if (ret < 0 && (errno == EMFILE || errno == ENFILE)) {
2360 rb_gc();
2361 ret = socketpair(d, t, p, sp);
2363 if (ret < 0) {
2364 rb_sys_fail("socketpair(2)");
2367 return rb_assoc_new(init_sock(rb_obj_alloc(klass), sp[0]),
2368 init_sock(rb_obj_alloc(klass), sp[1]));
2369 #else
2370 rb_notimplement();
2371 #endif
2374 #ifdef HAVE_SYS_UN_H
2375 static VALUE
2376 unix_s_socketpair(argc, argv, klass)
2377 int argc;
2378 VALUE *argv;
2379 VALUE klass;
2381 VALUE domain, type, protocol;
2382 domain = INT2FIX(PF_UNIX);
2384 rb_scan_args(argc, argv, "02", &type, &protocol);
2385 if (argc == 0)
2386 type = INT2FIX(SOCK_STREAM);
2387 if (argc <= 1)
2388 protocol = INT2FIX(0);
2390 return sock_s_socketpair(klass, domain, type, protocol);
2392 #endif
2395 * call-seq:
2396 * socket.connect(server_sockaddr) => 0
2398 * Requests a connection to be made on the given +server_sockaddr+. Returns 0 if
2399 * successful, otherwise an exception is raised.
2401 * === Parameter
2402 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
2404 * === Example:
2405 * # Pull down Google's web page
2406 * require 'socket'
2407 * include Socket::Constants
2408 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2409 * sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
2410 * socket.connect( sockaddr )
2411 * socket.write( "GET / HTTP/1.0\r\n\r\n" )
2412 * results = socket.read
2414 * === Unix-based Exceptions
2415 * On unix-based systems the following system exceptions may be raised if
2416 * the call to _connect_ fails:
2417 * * Errno::EACCES - search permission is denied for a component of the prefix
2418 * path or write access to the +socket+ is denided
2419 * * Errno::EADDRINUSE - the _sockaddr_ is already in use
2420 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
2421 * local machine
2422 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
2423 * the address family of the specified +socket+
2424 * * Errno::EALREADY - a connection is already in progress for the specified
2425 * socket
2426 * * Errno::EBADF - the +socket+ is not a valid file descriptor
2427 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
2428 * refused the connection request
2429 * * Errno::ECONNRESET - the remote host reset the connection request
2430 * * Errno::EFAULT - the _sockaddr_ cannot be accessed
2431 * * Errno::EHOSTUNREACH - the destination host cannot be reached (probably
2432 * because the host is down or a remote router cannot reach it)
2433 * * Errno::EINPROGRESS - the O_NONBLOCK is set for the +socket+ and the
2434 * connection cnanot be immediately established; the connection will be
2435 * established asynchronously
2436 * * Errno::EINTR - the attempt to establish the connection was interrupted by
2437 * delivery of a signal that was caught; the connection will be established
2438 * asynchronously
2439 * * Errno::EISCONN - the specified +socket+ is already connected
2440 * * Errno::EINVAL - the address length used for the _sockaddr_ is not a valid
2441 * length for the address family or there is an invalid family in _sockaddr_
2442 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
2443 * PATH_MAX
2444 * * Errno::ENETDOWN - the local interface used to reach the destination is down
2445 * * Errno::ENETUNREACH - no route to the network is present
2446 * * Errno::ENOBUFS - no buffer space is available
2447 * * Errno::ENOSR - there were insufficient STREAMS resources available to
2448 * complete the operation
2449 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
2450 * * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected
2451 * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket
2452 * bound to the specified peer address
2453 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
2454 * was made.
2456 * On unix-based systems if the address family of the calling +socket+ is
2457 * AF_UNIX the follow exceptions may be raised if the call to _connect_
2458 * fails:
2459 * * Errno::EIO - an i/o error occured while reading from or writing to the
2460 * file system
2461 * * Errno::ELOOP - too many symbolic links were encountered in translating
2462 * the pathname in _sockaddr_
2463 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
2464 * characters, or an entired pathname exceeded PATH_MAX characters
2465 * * Errno::ENOENT - a component of the pathname does not name an existing file
2466 * or the pathname is an empty string
2467 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
2468 * is not a directory
2470 * === Windows Exceptions
2471 * On Windows systems the following system exceptions may be raised if
2472 * the call to _connect_ fails:
2473 * * Errno::ENETDOWN - the network is down
2474 * * Errno::EADDRINUSE - the socket's local address is already in use
2475 * * Errno::EINTR - the socket was cancelled
2476 * * Errno::EINPROGRESS - a blocking socket is in progress or the service provider
2477 * is still processing a callback function. Or a nonblocking connect call is
2478 * in progress on the +socket+.
2479 * * Errno::EALREADY - see Errno::EINVAL
2480 * * Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as
2481 * ADDR_ANY TODO check ADDRANY TO INADDR_ANY
2482 * * Errno::EAFNOSUPPORT - addresses in the specified family cannot be used with
2483 * with this +socket+
2484 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
2485 * refused the connection request
2486 * * Errno::EFAULT - the socket's internal address or address length parameter
2487 * is too small or is not a valid part of the user space address
2488 * * Errno::EINVAL - the +socket+ is a listening socket
2489 * * Errno::EISCONN - the +socket+ is already connected
2490 * * Errno::ENETUNREACH - the network cannot be reached from this host at this time
2491 * * Errno::EHOSTUNREACH - no route to the network is present
2492 * * Errno::ENOBUFS - no buffer space is available
2493 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
2494 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
2495 * was made.
2496 * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the
2497 * connection cannot be completed immediately
2498 * * Errno::EACCES - the attempt to connect the datagram socket to the
2499 * broadcast address failed
2501 * === See
2502 * * connect manual pages on unix-based systems
2503 * * connect function in Microsoft's Winsock functions reference
2505 static VALUE
2506 sock_connect(sock, addr)
2507 VALUE sock, addr;
2509 OpenFile *fptr;
2510 int fd;
2512 StringValue(addr);
2513 addr = rb_str_new4(addr);
2514 GetOpenFile(sock, fptr);
2515 fd = fileno(fptr->f);
2516 if (ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0) < 0) {
2517 rb_sys_fail("connect(2)");
2520 return INT2FIX(0);
2524 * call-seq:
2525 * socket.connect_nonblock(server_sockaddr) => 0
2527 * Requests a connection to be made on the given +server_sockaddr+ after
2528 * O_NONBLOCK is set for the underlying file descriptor.
2529 * Returns 0 if successful, otherwise an exception is raised.
2531 * === Parameter
2532 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
2534 * === Example:
2535 * # Pull down Google's web page
2536 * require 'socket'
2537 * include Socket::Constants
2538 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
2539 * sockaddr = Socket.sockaddr_in(80, 'www.google.com')
2540 * begin
2541 * socket.connect_nonblock(sockaddr)
2542 * rescue Errno::EINPROGRESS
2543 * IO.select(nil, [socket])
2544 * begin
2545 * socket.connect_nonblock(sockaddr)
2546 * rescue Errno::EISCONN
2547 * end
2548 * end
2549 * socket.write("GET / HTTP/1.0\r\n\r\n")
2550 * results = socket.read
2552 * Refer to Socket#connect for the exceptions that may be thrown if the call
2553 * to _connect_nonblock_ fails.
2555 * Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
2556 * including Errno::EINPROGRESS.
2558 * === See
2559 * * Socket#connect
2561 static VALUE
2562 sock_connect_nonblock(sock, addr)
2563 VALUE sock, addr;
2565 OpenFile *fptr;
2566 int n;
2568 StringValue(addr);
2569 addr = rb_str_new4(addr);
2570 GetOpenFile(sock, fptr);
2571 rb_io_set_nonblock(fptr);
2572 n = connect(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len);
2573 if (n < 0) {
2574 rb_sys_fail("connect(2)");
2577 return INT2FIX(n);
2581 * call-seq:
2582 * socket.bind(server_sockaddr) => 0
2584 * Binds to the given +struct+ sockaddr.
2586 * === Parameter
2587 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
2589 * === Example
2590 * require 'socket'
2591 * include Socket::Constants
2592 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2593 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
2594 * socket.bind( sockaddr )
2596 * === Unix-based Exceptions
2597 * On unix-based based systems the following system exceptions may be raised if
2598 * the call to _bind_ fails:
2599 * * Errno::EACCES - the specified _sockaddr_ is protected and the current
2600 * user does not have permission to bind to it
2601 * * Errno::EADDRINUSE - the specified _sockaddr_ is already in use
2602 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
2603 * local machine
2604 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ isnot a valid address for
2605 * the family of the calling +socket+
2606 * * Errno::EBADF - the _sockaddr_ specified is not a valid file descriptor
2607 * * Errno::EFAULT - the _sockaddr_ argument cannot be accessed
2608 * * Errno::EINVAL - the +socket+ is already bound to an address, and the
2609 * protocol does not support binding to the new _sockaddr_ or the +socket+
2610 * has been shut down.
2611 * * Errno::EINVAL - the address length is not a valid length for the address
2612 * family
2613 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
2614 * PATH_MAX
2615 * * Errno::ENOBUFS - no buffer space is available
2616 * * Errno::ENOSR - there were insufficient STREAMS resources available to
2617 * complete the operation
2618 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
2619 * * Errno::EOPNOTSUPP - the socket type of the +socket+ does not support
2620 * binding to an address
2622 * On unix-based based systems if the address family of the calling +socket+ is
2623 * Socket::AF_UNIX the follow exceptions may be raised if the call to _bind_
2624 * fails:
2625 * * Errno::EACCES - search permission is denied for a component of the prefix
2626 * path or write access to the +socket+ is denided
2627 * * Errno::EDESTADDRREQ - the _sockaddr_ argument is a null pointer
2628 * * Errno::EISDIR - same as Errno::EDESTADDRREQ
2629 * * Errno::EIO - an i/o error occurred
2630 * * Errno::ELOOP - too many symbolic links were encountered in translating
2631 * the pathname in _sockaddr_
2632 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
2633 * characters, or an entired pathname exceeded PATH_MAX characters
2634 * * Errno::ENOENT - a component of the pathname does not name an existing file
2635 * or the pathname is an empty string
2636 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
2637 * is not a directory
2638 * * Errno::EROFS - the name would reside on a read only filesystem
2640 * === Windows Exceptions
2641 * On Windows systems the following system exceptions may be raised if
2642 * the call to _bind_ fails:
2643 * * Errno::ENETDOWN-- the network is down
2644 * * Errno::EACCES - the attempt to connect the datagram socket to the
2645 * broadcast address failed
2646 * * Errno::EADDRINUSE - the socket's local address is already in use
2647 * * Errno::EADDRNOTAVAIL - the specified address is not a valid address for this
2648 * computer
2649 * * Errno::EFAULT - the socket's internal address or address length parameter
2650 * is too small or is not a valid part of the user space addressed
2651 * * Errno::EINVAL - the +socket+ is already bound to an address
2652 * * Errno::ENOBUFS - no buffer space is available
2653 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
2655 * === See
2656 * * bind manual pages on unix-based systems
2657 * * bind function in Microsoft's Winsock functions reference
2659 static VALUE
2660 sock_bind(sock, addr)
2661 VALUE sock, addr;
2663 OpenFile *fptr;
2665 StringValue(addr);
2666 GetOpenFile(sock, fptr);
2667 if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
2668 rb_sys_fail("bind(2)");
2670 return INT2FIX(0);
2674 * call-seq:
2675 * socket.listen( int ) => 0
2677 * Listens for connections, using the specified +int+ as the backlog. A call
2678 * to _listen_ only applies if the +socket+ is of type SOCK_STREAM or
2679 * SOCK_SEQPACKET.
2681 * === Parameter
2682 * * +backlog+ - the maximum length of the queue for pending connections.
2684 * === Example 1
2685 * require 'socket'
2686 * include Socket::Constants
2687 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2688 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
2689 * socket.bind( sockaddr )
2690 * socket.listen( 5 )
2692 * === Example 2 (listening on an arbitary port, unix-based systems only):
2693 * require 'socket'
2694 * include Socket::Constants
2695 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2696 * socket.listen( 1 )
2698 * === Unix-based Exceptions
2699 * On unix based systems the above will work because a new +sockaddr+ struct
2700 * is created on the address ADDR_ANY, for an arbitrary port number as handed
2701 * off by the kernel. It will not work on Windows, because Windows requires that
2702 * the +socket+ is bound by calling _bind_ before it can _listen_.
2704 * If the _backlog_ amount exceeds the implementation-dependent maximum
2705 * queue length, the implementation's maximum queue length will be used.
2707 * On unix-based based systems the following system exceptions may be raised if the
2708 * call to _listen_ fails:
2709 * * Errno::EBADF - the _socket_ argument is not a valid file descriptor
2710 * * Errno::EDESTADDRREQ - the _socket_ is not bound to a local address, and
2711 * the protocol does not support listening on an unbound socket
2712 * * Errno::EINVAL - the _socket_ is already connected
2713 * * Errno::ENOTSOCK - the _socket_ argument does not refer to a socket
2714 * * Errno::EOPNOTSUPP - the _socket_ protocol does not support listen
2715 * * Errno::EACCES - the calling process does not have approriate privileges
2716 * * Errno::EINVAL - the _socket_ has been shut down
2717 * * Errno::ENOBUFS - insufficient resources are available in the system to
2718 * complete the call
2720 * === Windows Exceptions
2721 * On Windows systems the following system exceptions may be raised if
2722 * the call to _listen_ fails:
2723 * * Errno::ENETDOWN - the network is down
2724 * * Errno::EADDRINUSE - the socket's local address is already in use. This
2725 * usually occurs during the execution of _bind_ but could be delayed
2726 * if the call to _bind_ was to a partially wildcard address (involving
2727 * ADDR_ANY) and if a specific address needs to be commmitted at the
2728 * time of the call to _listen_
2729 * * Errno::EINPROGRESS - a Windows Sockets 1.1 call is in progress or the
2730 * service provider is still processing a callback function
2731 * * Errno::EINVAL - the +socket+ has not been bound with a call to _bind_.
2732 * * Errno::EISCONN - the +socket+ is already connected
2733 * * Errno::EMFILE - no more socket descriptors are available
2734 * * Errno::ENOBUFS - no buffer space is available
2735 * * Errno::ENOTSOC - +socket+ is not a socket
2736 * * Errno::EOPNOTSUPP - the referenced +socket+ is not a type that supports
2737 * the _listen_ method
2739 * === See
2740 * * listen manual pages on unix-based systems
2741 * * listen function in Microsoft's Winsock functions reference
2743 static VALUE
2744 sock_listen(sock, log)
2745 VALUE sock, log;
2747 OpenFile *fptr;
2748 int backlog;
2750 rb_secure(4);
2751 backlog = NUM2INT(log);
2752 GetOpenFile(sock, fptr);
2753 if (listen(fileno(fptr->f), backlog) < 0)
2754 rb_sys_fail("listen(2)");
2756 return INT2FIX(0);
2760 * call-seq:
2761 * socket.recvfrom(maxlen) => [mesg, sender_sockaddr]
2762 * socket.recvfrom(maxlen, flags) => [mesg, sender_sockaddr]
2764 * Receives up to _maxlen_ bytes from +socket+. _flags_ is zero or more
2765 * of the +MSG_+ options. The first element of the results, _mesg_, is the data
2766 * received. The second element, _sender_sockaddr_, contains protocol-specific information
2767 * on the sender.
2769 * === Parameters
2770 * * +maxlen+ - the number of bytes to receive from the socket
2771 * * +flags+ - zero or more of the +MSG_+ options
2773 * === Example
2774 * # In one file, start this first
2775 * require 'socket'
2776 * include Socket::Constants
2777 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2778 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
2779 * socket.bind( sockaddr )
2780 * socket.listen( 5 )
2781 * client, client_sockaddr = socket.accept
2782 * data = client.recvfrom( 20 )[0].chomp
2783 * puts "I only received 20 bytes '#{data}'"
2784 * sleep 1
2785 * socket.close
2787 * # In another file, start this second
2788 * require 'socket'
2789 * include Socket::Constants
2790 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2791 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
2792 * socket.connect( sockaddr )
2793 * socket.puts "Watch this get cut short!"
2794 * socket.close
2796 * === Unix-based Exceptions
2797 * On unix-based based systems the following system exceptions may be raised if the
2798 * call to _recvfrom_ fails:
2799 * * Errno::EAGAIN - the +socket+ file descriptor is marked as O_NONBLOCK and no
2800 * data is waiting to be received; or MSG_OOB is set and no out-of-band data
2801 * is available and either the +socket+ file descriptor is marked as
2802 * O_NONBLOCK or the +socket+ does not support blocking to wait for
2803 * out-of-band-data
2804 * * Errno::EWOULDBLOCK - see Errno::EAGAIN
2805 * * Errno::EBADF - the +socket+ is not a valid file descriptor
2806 * * Errno::ECONNRESET - a connection was forcibly closed by a peer
2807 * * Errno::EFAULT - the socket's internal buffer, address or address length
2808 * cannot be accessed or written
2809 * * Errno::EINTR - a signal interupted _recvfrom_ before any data was available
2810 * * Errno::EINVAL - the MSG_OOB flag is set and no out-of-band data is available
2811 * * Errno::EIO - an i/o error occurred while reading from or writing to the
2812 * filesystem
2813 * * Errno::ENOBUFS - insufficient resources were available in the system to
2814 * perform the operation
2815 * * Errno::ENOMEM - insufficient memory was available to fulfill the request
2816 * * Errno::ENOSR - there were insufficient STREAMS resources available to
2817 * complete the operation
2818 * * Errno::ENOTCONN - a receive is attempted on a connection-mode socket that
2819 * is not connected
2820 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
2821 * * Errno::EOPNOTSUPP - the specified flags are not supported for this socket type
2822 * * Errno::ETIMEDOUT - the connection timed out during connection establishment
2823 * or due to a transmission timeout on an active connection
2825 * === Windows Exceptions
2826 * On Windows systems the following system exceptions may be raised if
2827 * the call to _recvfrom_ fails:
2828 * * Errno::ENETDOWN - the network is down
2829 * * Errno::EFAULT - the internal buffer and from parameters on +socket+ are not
2830 * part of the user address space, or the internal fromlen parameter is
2831 * too small to accomodate the peer address
2832 * * Errno::EINTR - the (blocking) call was cancelled by an internal call to
2833 * the WinSock function WSACancelBlockingCall
2834 * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
2835 * the service provider is still processing a callback function
2836 * * Errno::EINVAL - +socket+ has not been bound with a call to _bind_, or an
2837 * unknown flag was specified, or MSG_OOB was specified for a socket with
2838 * SO_OOBINLINE enabled, or (for byte stream-style sockets only) the internal
2839 * len parameter on +socket+ was zero or negative
2840 * * Errno::EISCONN - +socket+ is already connected. The call to _recvfrom_ is
2841 * not permitted with a connected socket on a socket that is connetion
2842 * oriented or connectionless.
2843 * * Errno::ENETRESET - the connection has been broken due to the keep-alive
2844 * activity detecting a failure while the operation was in progress.
2845 * * Errno::EOPNOTSUPP - MSG_OOB was specified, but +socket+ is not stream-style
2846 * such as type SOCK_STREAM. OOB data is not supported in the communication
2847 * domain associated with +socket+, or +socket+ is unidirectional and
2848 * supports only send operations
2849 * * Errno::ESHUTDOWN - +socket+ has been shutdown. It is not possible to
2850 * call _recvfrom_ on a socket after _shutdown_ has been invoked.
2851 * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and a call to
2852 * _recvfrom_ would block.
2853 * * Errno::EMSGSIZE - the message was too large to fit into the specified buffer
2854 * and was truncated.
2855 * * Errno::ETIMEDOUT - the connection has been dropped, because of a network
2856 * failure or because the system on the other end went down without
2857 * notice
2858 * * Errno::ECONNRESET - the virtual circuit was reset by the remote side
2859 * executing a hard or abortive close. The application should close the
2860 * socket; it is no longer usable. On a UDP-datagram socket this error
2861 * indicates a previous send operation resulted in an ICMP Port Unreachable
2862 * message.
2864 static VALUE
2865 sock_recvfrom(argc, argv, sock)
2866 int argc;
2867 VALUE *argv;
2868 VALUE sock;
2870 return s_recvfrom(sock, argc, argv, RECV_SOCKET);
2874 * call-seq:
2875 * socket.recvfrom_nonblock(maxlen) => [mesg, sender_sockaddr]
2876 * socket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_sockaddr]
2878 * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
2879 * O_NONBLOCK is set for the underlying file descriptor.
2880 * _flags_ is zero or more of the +MSG_+ options.
2881 * The first element of the results, _mesg_, is the data received.
2882 * The second element, _sender_sockaddr_, contains protocol-specific information
2883 * on the sender.
2885 * When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns
2886 * an empty string as data.
2887 * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
2889 * === Parameters
2890 * * +maxlen+ - the number of bytes to receive from the socket
2891 * * +flags+ - zero or more of the +MSG_+ options
2893 * === Example
2894 * # In one file, start this first
2895 * require 'socket'
2896 * include Socket::Constants
2897 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
2898 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
2899 * socket.bind(sockaddr)
2900 * socket.listen(5)
2901 * client, client_sockaddr = socket.accept
2902 * begin
2903 * pair = client.recvfrom_nonblock(20)
2904 * rescue Errno::EAGAIN
2905 * IO.select([client])
2906 * retry
2907 * end
2908 * data = pair[0].chomp
2909 * puts "I only received 20 bytes '#{data}'"
2910 * sleep 1
2911 * socket.close
2913 * # In another file, start this second
2914 * require 'socket'
2915 * include Socket::Constants
2916 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
2917 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
2918 * socket.connect(sockaddr)
2919 * socket.puts "Watch this get cut short!"
2920 * socket.close
2922 * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
2923 * to _recvfrom_nonblock_ fails.
2925 * Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
2926 * including Errno::EAGAIN.
2928 * === See
2929 * * Socket#recvfrom
2931 static VALUE
2932 sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
2934 return s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
2938 * call-seq:
2939 * socket.accept => [ socket, string ]
2941 * Accepts an incoming connection returning an array containing a new
2942 * Socket object and a string holding the +struct+ sockaddr information about
2943 * the caller.
2945 * === Example
2946 * # In one script, start this first
2947 * require 'socket'
2948 * include Socket::Constants
2949 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2950 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
2951 * socket.bind( sockaddr )
2952 * socket.listen( 5 )
2953 * client, client_sockaddr = socket.accept
2954 * puts "The client said, '#{client.readline.chomp}'"
2955 * client.puts "Hello from script one!"
2956 * socket.close
2958 * # In another script, start this second
2959 * require 'socket'
2960 * include Socket::Constants
2961 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
2962 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
2963 * socket.connect( sockaddr )
2964 * socket.puts "Hello from script 2."
2965 * puts "The server said, '#{socket.readline.chomp}'"
2966 * socket.close
2968 * === Unix-based Exceptions
2969 * On unix-based based systems the following system exceptions may be raised if the
2970 * call to _accept_ fails:
2971 * * Errno::EAGAIN - O_NONBLOCK is set for the +socket+ file descriptor and no
2972 * connections are parent to be accepted
2973 * * Errno::EWOULDBLOCK - same as Errno::EAGAIN
2974 * * Errno::EBADF - the +socket+ is not a valid file descriptor
2975 * * Errno::ECONNABORTED - a connection has been aborted
2976 * * Errno::EFAULT - the socket's internal address or address length parameter
2977 * cannot be access or written
2978 * * Errno::EINTR - the _accept_ method was interrupted by a signal that was
2979 * caught before a valid connection arrived
2980 * * Errno::EINVAL - the +socket+ is not accepting connections
2981 * * Errno::EMFILE - OPEN_MAX file descriptors are currently open in the calling
2982 * process
2983 * * Errno::ENOBUFS - no buffer space is available
2984 * * Errno::ENOMEM - there was insufficient memory available to complete the
2985 * operation
2986 * * Errno::ENOSR - there was insufficient STREAMS resources available to
2987 * complete the operation
2988 * * Errno::ENFILE - the maximum number of file descriptors in the system are
2989 * already open
2990 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
2991 * * Errno::EOPNOTSUPP - the socket type for the calling +socket+ does not
2992 * support accept connections
2993 * * Errno::EPROTO - a protocol error has occurred
2995 * === Windows Exceptions
2996 * On Windows systems the following system exceptions may be raised if
2997 * the call to _accept_ fails:
2998 * * Errno::ECONNRESET - an incoming connection was indicated, but was
2999 * terminated by the remote peer prior to accepting the connection
3000 * * Errno::EFAULT - the socket's internal address or address length parameter
3001 * is too small or is not a valid part of the user space address
3002 * * Errno::EINVAL - the _listen_ method was not invoked prior to calling _accept_
3003 * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
3004 * the service provider is still processing a callback function
3005 * * Errno::EMFILE - the queue is not empty, upong etry to _accept_ and there are
3006 * no socket descriptors available
3007 * * Errno::ENETDOWN - the network is down
3008 * * Errno::ENOBUFS - no buffer space is available
3009 * * Errno::ENOTSOCK - +socket+ is not a socket
3010 * * Errno::EOPNOTSUPP - +socket+ is not a type that supports connection-oriented
3011 * service.
3012 * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and no connections are
3013 * present to be accepted
3015 * === See
3016 * * accept manual pages on unix-based systems
3017 * * accept function in Microsoft's Winsock functions reference
3019 static VALUE
3020 sock_accept(sock)
3021 VALUE sock;
3023 OpenFile *fptr;
3024 VALUE sock2;
3025 char buf[1024];
3026 socklen_t len = sizeof buf;
3028 GetOpenFile(sock, fptr);
3029 sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);
3031 return rb_assoc_new(sock2, rb_str_new(buf, len));
3035 * call-seq:
3036 * socket.accept_nonblock => [client_socket, client_sockaddr]
3038 * Accepts an incoming connection using accept(2) after
3039 * O_NONBLOCK is set for the underlying file descriptor.
3040 * It returns an array containg the accpeted socket
3041 * for the incoming connection, _client_socket_,
3042 * and a string that contains the +struct+ sockaddr information
3043 * about the caller, _client_sockaddr_.
3045 * === Example
3046 * # In one script, start this first
3047 * require 'socket'
3048 * include Socket::Constants
3049 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
3050 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
3051 * socket.bind(sockaddr)
3052 * socket.listen(5)
3053 * begin
3054 * client_socket, client_sockaddr = socket.accept_nonblock
3055 * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
3056 * IO.select([socket])
3057 * retry
3058 * end
3059 * puts "The client said, '#{client_socket.readline.chomp}'"
3060 * client_socket.puts "Hello from script one!"
3061 * socket.close
3063 * # In another script, start this second
3064 * require 'socket'
3065 * include Socket::Constants
3066 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
3067 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
3068 * socket.connect(sockaddr)
3069 * socket.puts "Hello from script 2."
3070 * puts "The server said, '#{socket.readline.chomp}'"
3071 * socket.close
3073 * Refer to Socket#accept for the exceptions that may be thrown if the call
3074 * to _accept_nonblock_ fails.
3076 * Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
3077 * including Errno::EAGAIN.
3079 * === See
3080 * * Socket#accept
3082 static VALUE
3083 sock_accept_nonblock(sock)
3084 VALUE sock;
3086 OpenFile *fptr;
3087 VALUE sock2;
3088 char buf[1024];
3089 socklen_t len = sizeof buf;
3091 GetOpenFile(sock, fptr);
3092 sock2 = s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)buf, &len);
3093 return rb_assoc_new(sock2, rb_str_new(buf, len));
3097 * call-seq:
3098 * socket.sysaccept => [client_socket_fd, client_sockaddr]
3100 * Accepts an incoming connection returnings an array containg the (integer)
3101 * file descriptor for the incoming connection, _client_socket_fd_,
3102 * and a string that contains the +struct+ sockaddr information
3103 * about the caller, _client_sockaddr_.
3105 * === Example
3106 * # In one script, start this first
3107 * require 'socket'
3108 * include Socket::Constants
3109 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
3110 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
3111 * socket.bind( sockaddr )
3112 * socket.listen( 5 )
3113 * client_fd, client_sockaddr = socket.sysaccept
3114 * client_socket = Socket.for_fd( client_fd )
3115 * puts "The client said, '#{client_socket.readline.chomp}'"
3116 * client_socket.puts "Hello from script one!"
3117 * socket.close
3119 * # In another script, start this second
3120 * require 'socket'
3121 * include Socket::Constants
3122 * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
3123 * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
3124 * socket.connect( sockaddr )
3125 * socket.puts "Hello from script 2."
3126 * puts "The server said, '#{socket.readline.chomp}'"
3127 * socket.close
3129 * Refer to Socket#accept for the exceptions that may be thrown if the call
3130 * to _sysaccept_ fails.
3132 * === See
3133 * * Socket#accept
3135 static VALUE
3136 sock_sysaccept(sock)
3137 VALUE sock;
3139 OpenFile *fptr;
3140 VALUE sock2;
3141 char buf[1024];
3142 socklen_t len = sizeof buf;
3144 GetOpenFile(sock, fptr);
3145 sock2 = s_accept(0,fileno(fptr->f),(struct sockaddr*)buf,&len);
3147 return rb_assoc_new(sock2, rb_str_new(buf, len));
3150 #ifdef HAVE_GETHOSTNAME
3151 static VALUE
3152 sock_gethostname(obj)
3153 VALUE obj;
3155 char buf[1024];
3157 rb_secure(3);
3158 if (gethostname(buf, (int)sizeof buf - 1) < 0)
3159 rb_sys_fail("gethostname");
3161 buf[sizeof buf - 1] = '\0';
3162 return rb_str_new2(buf);
3164 #else
3165 #ifdef HAVE_UNAME
3167 #include <sys/utsname.h>
3169 static VALUE
3170 sock_gethostname(obj)
3171 VALUE obj;
3173 struct utsname un;
3175 rb_secure(3);
3176 uname(&un);
3177 return rb_str_new2(un.nodename);
3179 #else
3180 static VALUE
3181 sock_gethostname(obj)
3182 VALUE obj;
3184 rb_notimplement();
3186 #endif
3187 #endif
3189 static VALUE
3190 make_addrinfo(res0)
3191 struct addrinfo *res0;
3193 VALUE base, ary;
3194 struct addrinfo *res;
3196 if (res0 == NULL) {
3197 rb_raise(rb_eSocket, "host not found");
3199 base = rb_ary_new();
3200 for (res = res0; res; res = res->ai_next) {
3201 ary = ipaddr(res->ai_addr);
3202 rb_ary_push(ary, INT2FIX(res->ai_family));
3203 rb_ary_push(ary, INT2FIX(res->ai_socktype));
3204 rb_ary_push(ary, INT2FIX(res->ai_protocol));
3205 rb_ary_push(base, ary);
3207 return base;
3210 /* Returns a String containing the binary value of a struct sockaddr. */
3211 VALUE
3212 sock_sockaddr(addr, len)
3213 struct sockaddr *addr;
3214 size_t len;
3216 char *ptr;
3218 switch (addr->sa_family) {
3219 case AF_INET:
3220 ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
3221 len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
3222 break;
3223 #ifdef INET6
3224 case AF_INET6:
3225 ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
3226 len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
3227 break;
3228 #endif
3229 default:
3230 rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
3231 break;
3233 return rb_str_new(ptr, len);
3237 * Document-class: IPSocket
3239 * IPSocket is the parent of TCPSocket and UDPSocket and implements
3240 * functionality common to them.
3242 * A number of APIs in IPSocket, Socket, and their descendants return an
3243 * address as an array. The members of that array are:
3244 * - address family: A string like "AF_INET" or "AF_INET6" if it is one of the
3245 * commonly used families, the string "unknown:#" (where `#' is the address
3246 * family number) if it is not one of the common ones. The strings map to
3247 * the Socket::AF_* constants.
3248 * - port: The port number.
3249 * - name: Either the canonical name from looking the address up in the DNS, or
3250 * the address in presentation format
3251 * - address: The address in presentation format (a dotted decimal string for
3252 * IPv4, a hex string for IPv6).
3254 * The address and port can be used directly to create sockets and to bind or
3255 * connect them to the address.
3259 * Document-class: Socket
3261 * Socket contains a number of generally useful singleton methods and
3262 * constants, as well as offering low-level interfaces that can be used to
3263 * develop socket applications using protocols other than TCP, UDP, and UNIX
3264 * domain sockets.
3268 * Document-method: gethostbyname
3269 * call-seq: Socket.gethostbyname(host) => hostent
3271 * Resolve +host+ and return name and address information for it, similarly to
3272 * gethostbyname(3). +host+ can be a domain name or the presentation format of
3273 * an address.
3275 * Returns an array of information similar to that found in a +struct hostent+:
3276 * - cannonical name: the cannonical name for host in the DNS, or a
3277 * string representing the address
3278 * - aliases: an array of aliases for the canonical name, there may be no aliases
3279 * - address family: usually one of Socket::AF_INET or Socket::AF_INET6
3280 * - address: a string, the binary value of the +struct sockaddr+ for this name, in
3281 * the indicated address family
3282 * - ...: if there are multiple addresses for this host, a series of
3283 * strings/+struct sockaddr+s may follow, not all necessarily in the same
3284 * address family. Note that the fact that they may not be all in the same
3285 * address family is a departure from the behaviour of gethostbyname(3).
3287 * Note: I believe that the fact that the multiple addresses returned are not
3288 * necessarily in the same address family may be a bug, since if this function
3289 * actually called gethostbyname(3), ALL the addresses returned in the trailing
3290 * address list (h_addr_list from struct hostent) would be of the same address
3291 * family! Examples from my system, OS X 10.3:
3293 * ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
3294 * and
3295 * ["ensemble.local", [], 30, "\376\200\000\004\000\000\000\000\002\003\223\377\376\255\010\214", "\300\250{\232" ]
3297 * Similar information can be returned by Socket.getaddrinfo if called as:
3299 * Socket.getaddrinfo(+host+, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
3301 * == Examples
3303 * Socket.gethostbyname "example.com"
3304 * => ["example.com", [], 2, "\300\000\"\246"]
3306 * This name has no DNS aliases, and a single IPv4 address.
3308 * Socket.gethostbyname "smtp.telus.net"
3309 * => ["smtp.svc.telus.net", ["smtp.telus.net"], 2, "\307\271\334\371"]
3311 * This name is an an alias so the canonical name is returned, as well as the
3312 * alias and a single IPv4 address.
3314 * Socket.gethostbyname "localhost"
3315 * => ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
3317 * This machine has no aliases, returns an IPv6 address, and has an additional IPv4 address.
3319 * +host+ can also be an IP address in presentation format, in which case a
3320 * reverse lookup is done on the address:
3322 * Socket.gethostbyname("127.0.0.1")
3323 * => ["localhost", [], 2, "\177\000\000\001"]
3325 * Socket.gethostbyname("192.0.34.166")
3326 * => ["www.example.com", [], 2, "\300\000\"\246"]
3329 * == See
3330 * See: Socket.getaddrinfo
3332 static VALUE
3333 sock_s_gethostbyname(obj, host)
3334 VALUE obj, host;
3336 rb_secure(3);
3337 return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
3340 static VALUE
3341 sock_s_gethostbyaddr(argc, argv)
3342 int argc;
3343 VALUE *argv;
3345 VALUE addr, type;
3346 struct hostent *h;
3347 struct sockaddr *sa;
3348 char **pch;
3349 VALUE ary, names;
3350 int t = AF_INET;
3352 rb_scan_args(argc, argv, "11", &addr, &type);
3353 sa = (struct sockaddr*)StringValuePtr(addr);
3354 if (!NIL_P(type)) {
3355 t = NUM2INT(type);
3357 #ifdef INET6
3358 else if (RSTRING(addr)->len == 16) {
3359 t = AF_INET6;
3361 #endif
3362 h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, t);
3363 if (h == NULL) {
3364 #ifdef HAVE_HSTRERROR
3365 extern int h_errno;
3366 rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
3367 #else
3368 rb_raise(rb_eSocket, "host not found");
3369 #endif
3371 ary = rb_ary_new();
3372 rb_ary_push(ary, rb_str_new2(h->h_name));
3373 names = rb_ary_new();
3374 rb_ary_push(ary, names);
3375 if (h->h_aliases != NULL) {
3376 for (pch = h->h_aliases; *pch; pch++) {
3377 rb_ary_push(names, rb_str_new2(*pch));
3380 rb_ary_push(ary, INT2NUM(h->h_addrtype));
3381 #ifdef h_addr
3382 for (pch = h->h_addr_list; *pch; pch++) {
3383 rb_ary_push(ary, rb_str_new(*pch, h->h_length));
3385 #else
3386 rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
3387 #endif
3389 return ary;
3393 * Document-method: getservbyname
3394 * call-seq: Socket.getservbyname(name, proto="tcp") => port
3396 * +name+ is a service name ("ftp", "telnet", ...) and proto is a protocol name
3397 * ("udp", "tcp", ...). '/etc/services' (or your system's equivalent) is
3398 * searched for a service for +name+ and +proto+, and the port number is
3399 * returned.
3401 * Note that unlike Socket.getaddrinfo, +proto+ may not be specified using the
3402 * Socket::SOCK_* constants, a string must must be used.
3404 static VALUE
3405 sock_s_getservbyaname(argc, argv)
3406 int argc;
3407 VALUE *argv;
3409 VALUE service, proto;
3410 struct servent *sp;
3411 int port;
3413 rb_scan_args(argc, argv, "11", &service, &proto);
3414 if (NIL_P(proto)) proto = rb_str_new2("tcp");
3415 StringValue(service);
3416 StringValue(proto);
3418 sp = getservbyname(StringValueCStr(service), StringValueCStr(proto));
3419 if (sp) {
3420 port = ntohs(sp->s_port);
3422 else {
3423 char *s = RSTRING(service)->ptr;
3424 char *end;
3426 port = strtoul(s, &end, 0);
3427 if (*end != '\0') {
3428 rb_raise(rb_eSocket, "no such service %s/%s", s, RSTRING(proto)->ptr);
3431 return INT2FIX(port);
3435 Documentation should explain the following:
3437 $ pp Socket.getaddrinfo("", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
3438 [["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]]
3440 $ pp Socket.getaddrinfo(nil, 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
3441 [["AF_INET6", 1, "::", "::", 30, 1, 6],
3442 ["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]]
3444 $ pp Socket.getaddrinfo("localhost", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
3445 [["AF_INET6", 1, "localhost", "::1", 30, 1, 6],
3446 ["AF_INET", 1, "localhost", "127.0.0.1", 2, 1, 6]]
3448 $ pp Socket.getaddrinfo("ensemble.local.", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
3449 [["AF_INET", 1, "localhost", "192.168.123.154", 2, 1, 6]]
3451 Does it?
3453 API suggestion: this method has too many arguments, it would be backwards compatible and easier
3454 to understand if limit args were accepted as :family=>..., :flags=>...
3458 * Document-method: getaddrinfo
3459 * call-seq: Socket.getaddrinfo(host, service, family=nil, socktype=nil, protocol=nil, flags=nil) => addrinfo
3461 * Return address information for +host+ and +port+. The remaining arguments
3462 * are hints that limit the address information returned.
3464 * This method corresponds closely to the POSIX.1g getaddrinfo() definition.
3466 * === Parameters
3467 * - +host+ is a host name or an address string (dotted decimal for IPv4, or a hex string
3468 * for IPv6) for which to return information. A nil is also allowed, its meaning
3469 * depends on +flags+, see below.
3470 * - +service+ is a service name ("http", "ssh", ...), or
3471 * a port number (80, 22, ...), see Socket.getservbyname for more
3472 * information. A nil is also allowed, meaning zero.
3473 * - +family+ limits the output to a specific address family, one of the
3474 * Socket::AF_* constants. Socket::AF_INET (IPv4) and Socket::AF_INET6 (IPv6)
3475 * are the most commonly used families. You will usually pass either nil or
3476 * Socket::AF_UNSPEC, allowing the IPv6 information to be returned first if
3477 * +host+ is reachable via IPv6, and IPv4 information otherwise. The two
3478 * strings "AF_INET" or "AF_INET6" are also allowed, they are converted to
3479 * their respective Socket::AF_* constants.
3480 * - +socktype+ limits the output to a specific type of socket, one of the
3481 * Socket::SOCK_* constants. Socket::SOCK_STREAM (for TCP) and
3482 * Socket::SOCK_DGRAM (for UDP) are the most commonly used socket types. If
3483 * nil, then information for all types of sockets supported by +service+ will
3484 * be returned. You will usually know what type of socket you intend to
3485 * create, and should pass that socket type in.
3486 * - +protocol+ limits the output to a specific protocol numpber, one of the
3487 * Socket::IPPROTO_* constants. It is usually implied by the socket type
3488 * (Socket::SOCK_STREAM => Socket::IPPROTO_TCP, ...), if you pass other than
3489 * nil you already know what this is for.
3490 * - +flags+ is one of the Socket::AI_* constants. They mean:
3491 * - Socket::AI_PASSIVE: when set, if +host+ is nil the 'any' address will be
3492 * returned, Socket::INADDR_ANY or 0 for IPv4, "0::0" or "::" for IPv6. This
3493 * address is suitable for use by servers that will bind their socket and do
3494 * a passive listen, thus the name of the flag. Otherwise the local or
3495 * loopback address will be returned, this is "127.0.0.1" for IPv4 and "::1'
3496 * for IPv6.
3497 * - ...
3500 * === Returns
3502 * Returns an array of arrays, where each subarray contains:
3503 * - address family, a string like "AF_INET" or "AF_INET6"
3504 * - port number, the port number for +service+
3505 * - host name, either a canonical name for +host+, or it's address in presentation
3506 * format if the address could not be looked up.
3507 * - host IP, the address of +host+ in presentation format
3508 * - address family, as a numeric value (one of the Socket::AF_* constants).
3509 * - socket type, as a numeric value (one of the Socket::SOCK_* constants).
3510 * - protocol number, as a numeric value (one of the Socket::IPPROTO_* constants).
3512 * The first four values are identical to what is commonly returned as an
3513 * address array, see IPSocket for more information.
3515 * === Examples
3517 * Not all input combinations are valid, and while there are many combinations,
3518 * only a few cases are common.
3520 * A typical client will call getaddrinfo with the +host+ and +service+ it
3521 * wants to connect to. It knows that it will attempt to connect with either
3522 * TCP or UDP, and specifies +socktype+ accordingly. It loops through all
3523 * returned addresses, and try to connect to them in turn:
3525 * addrinfo = Socket::getaddrinfo('www.example.com', 'www', nil, Socket::SOCK_STREAM)
3526 * addrinfo.each do |af, port, name, addr|
3527 * begin
3528 * sock = TCPSocket.new(addr, port)
3529 * # ...
3530 * exit 1
3531 * rescue
3532 * end
3533 * end
3535 * With UDP you don't know if connect suceeded, but if communication fails,
3536 * the next address can be tried.
3538 * A typical server will call getaddrinfo with a +host+ of nil, the +service+
3539 * it listens to, and a +flags+ of Socket::AI_PASSIVE. It will listen for
3540 * connections on the first returned address:
3541 * addrinfo = Socket::getaddrinfo(nil, 'www', nil, Socket::SOCK_STREAM, nil, Socket::AI_PASSIVE)
3542 * af, port, name, addr = addrinfo.first
3543 * sock = TCPServer(addr, port)
3544 * while( client = s.accept )
3545 * # ...
3546 * end
3548 static VALUE
3549 sock_s_getaddrinfo(argc, argv)
3550 int argc;
3551 VALUE *argv;
3553 VALUE host, port, family, socktype, protocol, flags, ret;
3554 char hbuf[1024], pbuf[1024];
3555 char *hptr, *pptr, *ap;
3556 struct addrinfo hints, *res;
3557 int error;
3559 host = port = family = socktype = protocol = flags = Qnil;
3560 rb_scan_args(argc, argv, "24", &host, &port, &family, &socktype, &protocol, &flags);
3561 if (NIL_P(host)) {
3562 hptr = NULL;
3564 else {
3565 strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
3566 hbuf[sizeof(hbuf) - 1] = '\0';
3567 hptr = hbuf;
3569 if (NIL_P(port)) {
3570 pptr = NULL;
3572 else if (FIXNUM_P(port)) {
3573 snprintf(pbuf, sizeof(pbuf), "%ld", FIX2LONG(port));
3574 pptr = pbuf;
3576 else {
3577 strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
3578 pbuf[sizeof(pbuf) - 1] = '\0';
3579 pptr = pbuf;
3582 MEMZERO(&hints, struct addrinfo, 1);
3583 if (NIL_P(family)) {
3584 hints.ai_family = PF_UNSPEC;
3586 else if (FIXNUM_P(family)) {
3587 hints.ai_family = FIX2INT(family);
3589 else if ((ap = StringValuePtr(family)) != 0) {
3590 if (strcmp(ap, "AF_INET") == 0) {
3591 hints.ai_family = PF_INET;
3593 #ifdef INET6
3594 else if (strcmp(ap, "AF_INET6") == 0) {
3595 hints.ai_family = PF_INET6;
3597 #endif
3600 if (!NIL_P(socktype)) {
3601 hints.ai_socktype = NUM2INT(socktype);
3603 if (!NIL_P(protocol)) {
3604 hints.ai_protocol = NUM2INT(protocol);
3606 if (!NIL_P(flags)) {
3607 hints.ai_flags = NUM2INT(flags);
3609 error = getaddrinfo(hptr, pptr, &hints, &res);
3610 if (error) {
3611 rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
3614 ret = make_addrinfo(res);
3615 freeaddrinfo(res);
3616 return ret;
3619 static VALUE
3620 sock_s_getnameinfo(argc, argv)
3621 int argc;
3622 VALUE *argv;
3624 VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
3625 char *hptr, *pptr;
3626 char hbuf[1024], pbuf[1024];
3627 int fl;
3628 struct addrinfo hints, *res = NULL, *r;
3629 int error;
3630 struct sockaddr_storage ss;
3631 struct sockaddr *sap;
3632 char *ap;
3634 sa = flags = Qnil;
3635 rb_scan_args(argc, argv, "11", &sa, &flags);
3637 fl = 0;
3638 if (!NIL_P(flags)) {
3639 fl = NUM2INT(flags);
3641 tmp = rb_check_string_type(sa);
3642 if (!NIL_P(tmp)) {
3643 sa = tmp;
3644 if (sizeof(ss) < RSTRING(sa)->len) {
3645 rb_raise(rb_eTypeError, "sockaddr length too big");
3647 memcpy(&ss, RSTRING(sa)->ptr, RSTRING(sa)->len);
3648 if (RSTRING(sa)->len != SA_LEN((struct sockaddr*)&ss)) {
3649 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
3651 sap = (struct sockaddr*)&ss;
3652 goto call_nameinfo;
3654 tmp = rb_check_array_type(sa);
3655 if (!NIL_P(tmp)) {
3656 sa = tmp;
3657 MEMZERO(&hints, struct addrinfo, 1);
3658 if (RARRAY(sa)->len == 3) {
3659 af = RARRAY(sa)->ptr[0];
3660 port = RARRAY(sa)->ptr[1];
3661 host = RARRAY(sa)->ptr[2];
3663 else if (RARRAY(sa)->len >= 4) {
3664 af = RARRAY(sa)->ptr[0];
3665 port = RARRAY(sa)->ptr[1];
3666 host = RARRAY(sa)->ptr[3];
3667 if (NIL_P(host)) {
3668 host = RARRAY(sa)->ptr[2];
3670 else {
3672 * 4th element holds numeric form, don't resolve.
3673 * see ipaddr().
3675 #ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
3676 hints.ai_flags |= AI_NUMERICHOST;
3677 #endif
3680 else {
3681 rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
3682 RARRAY(sa)->len);
3684 /* host */
3685 if (NIL_P(host)) {
3686 hptr = NULL;
3688 else {
3689 strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
3690 hbuf[sizeof(hbuf) - 1] = '\0';
3691 hptr = hbuf;
3693 /* port */
3694 if (NIL_P(port)) {
3695 strcpy(pbuf, "0");
3696 pptr = NULL;
3698 else if (FIXNUM_P(port)) {
3699 snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
3700 pptr = pbuf;
3702 else {
3703 strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
3704 pbuf[sizeof(pbuf) - 1] = '\0';
3705 pptr = pbuf;
3707 hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
3708 /* af */
3709 if (NIL_P(af)) {
3710 hints.ai_family = PF_UNSPEC;
3712 else if (FIXNUM_P(af)) {
3713 hints.ai_family = FIX2INT(af);
3715 else if ((ap = StringValuePtr(af)) != 0) {
3716 if (strcmp(ap, "AF_INET") == 0) {
3717 hints.ai_family = PF_INET;
3719 #ifdef INET6
3720 else if (strcmp(ap, "AF_INET6") == 0) {
3721 hints.ai_family = PF_INET6;
3723 #endif
3725 error = getaddrinfo(hptr, pptr, &hints, &res);
3726 if (error) goto error_exit_addr;
3727 sap = res->ai_addr;
3729 else {
3730 rb_raise(rb_eTypeError, "expecting String or Array");
3733 call_nameinfo:
3734 error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
3735 pbuf, sizeof(pbuf), fl);
3736 if (error) goto error_exit_name;
3737 if (res) {
3738 for (r = res->ai_next; r; r = r->ai_next) {
3739 char hbuf2[1024], pbuf2[1024];
3741 sap = r->ai_addr;
3742 error = getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
3743 pbuf2, sizeof(pbuf2), fl);
3744 if (error) goto error_exit_name;
3745 if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
3746 freeaddrinfo(res);
3747 rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
3750 freeaddrinfo(res);
3752 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
3754 error_exit_addr:
3755 if (res) freeaddrinfo(res);
3756 rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
3758 error_exit_name:
3759 if (res) freeaddrinfo(res);
3760 rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
3763 static VALUE
3764 sock_s_pack_sockaddr_in(self, port, host)
3765 VALUE self, port, host;
3767 struct addrinfo *res = sock_addrinfo(host, port, 0, 0);
3768 VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
3770 freeaddrinfo(res);
3771 OBJ_INFECT(addr, port);
3772 OBJ_INFECT(addr, host);
3774 return addr;
3777 static VALUE
3778 sock_s_unpack_sockaddr_in(self, addr)
3779 VALUE self, addr;
3781 struct sockaddr_in * sockaddr;
3782 VALUE host;
3784 sockaddr = (struct sockaddr_in*)StringValuePtr(addr);
3785 if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
3786 #ifdef INET6
3787 && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
3788 #endif
3790 #ifdef INET6
3791 rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
3792 #else
3793 rb_raise(rb_eArgError, "not an AF_INET sockaddr");
3794 #endif
3796 host = make_ipaddr((struct sockaddr*)sockaddr);
3797 OBJ_INFECT(host, addr);
3798 return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
3801 #ifdef HAVE_SYS_UN_H
3802 static VALUE
3803 sock_s_pack_sockaddr_un(self, path)
3804 VALUE self, path;
3806 struct sockaddr_un sockaddr;
3807 char *sun_path;
3808 VALUE addr;
3810 MEMZERO(&sockaddr, struct sockaddr_un, 1);
3811 sockaddr.sun_family = AF_UNIX;
3812 sun_path = StringValueCStr(path);
3813 if (sizeof(sockaddr.sun_path) <= strlen(sun_path)) {
3814 rb_raise(rb_eArgError, "too long unix socket path (max: %dbytes)",
3815 (int)sizeof(sockaddr.sun_path)-1);
3817 strncpy(sockaddr.sun_path, sun_path, sizeof(sockaddr.sun_path)-1);
3818 addr = rb_str_new((char*)&sockaddr, sizeof(sockaddr));
3819 OBJ_INFECT(addr, path);
3821 return addr;
3824 static VALUE
3825 sock_s_unpack_sockaddr_un(self, addr)
3826 VALUE self, addr;
3828 struct sockaddr_un * sockaddr;
3829 char *sun_path;
3830 VALUE path;
3832 sockaddr = (struct sockaddr_un*)StringValuePtr(addr);
3833 if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
3834 rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
3836 if (sizeof(struct sockaddr_un) < RSTRING(addr)->len) {
3837 rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
3838 RSTRING(addr)->len, sizeof(struct sockaddr_un));
3840 sun_path = unixpath(sockaddr, RSTRING(addr)->len);
3841 if (sizeof(struct sockaddr_un) == RSTRING(addr)->len &&
3842 sun_path == sockaddr->sun_path &&
3843 sun_path + strlen(sun_path) == RSTRING(addr)->ptr + RSTRING(addr)->len) {
3844 rb_raise(rb_eArgError, "sockaddr_un.sun_path not NUL terminated");
3846 path = rb_str_new2(sun_path);
3847 OBJ_INFECT(path, addr);
3848 return path;
3850 #endif
3852 static VALUE mConst;
3854 static void
3855 sock_define_const(name, value)
3856 char *name;
3857 int value;
3859 rb_define_const(rb_cSocket, name, INT2FIX(value));
3860 rb_define_const(mConst, name, INT2FIX(value));
3864 * Class +Socket+ provides access to the underlying operating system
3865 * socket implementations. It can be used to provide more operating system
3866 * specific functionality than the protocol-specific socket classes but at the
3867 * expense of greater complexity. In particular, the class handles addresses
3868 * using +struct sockaddr+ structures packed into Ruby strings, which can be
3869 * a joy to manipulate.
3871 * === Exception Handling
3872 * Ruby's implementation of +Socket+ causes an exception to be raised
3873 * based on the error generated by the system dependent implementation.
3874 * This is why the methods are documented in a way that isolate
3875 * Unix-based system exceptions from Windows based exceptions. If more
3876 * information on particular exception is needed please refer to the
3877 * Unix manual pages or the Windows WinSock reference.
3880 * === Documentation by
3881 * * Zach Dennis
3882 * * Sam Roberts
3883 * * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
3885 * Much material in this documentation is taken with permission from
3886 * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
3888 void
3889 Init_socket()
3891 rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
3893 rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
3894 rb_undef_method(rb_cBasicSocket, "initialize");
3896 rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
3897 bsock_do_not_rev_lookup, 0);
3898 rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
3899 bsock_do_not_rev_lookup_set, 1);
3900 rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
3902 rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
3903 rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
3904 rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
3905 rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, 3);
3906 rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
3907 rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
3908 rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
3909 rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
3910 rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
3911 rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
3913 rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
3914 rb_define_global_const("IPsocket", rb_cIPSocket);
3915 rb_define_method(rb_cIPSocket, "addr", ip_addr, 0);
3916 rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, 0);
3917 rb_define_method(rb_cIPSocket, "recvfrom", ip_recvfrom, -1);
3918 rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
3920 rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket);
3921 rb_define_global_const("TCPsocket", rb_cTCPSocket);
3922 rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1);
3923 rb_define_method(rb_cTCPSocket, "initialize", tcp_init, -1);
3925 #ifdef SOCKS
3926 rb_cSOCKSSocket = rb_define_class("SOCKSSocket", rb_cTCPSocket);
3927 rb_define_global_const("SOCKSsocket", rb_cSOCKSSocket);
3928 rb_define_method(rb_cSOCKSSocket, "initialize", socks_init, 2);
3929 #ifdef SOCKS5
3930 rb_define_method(rb_cSOCKSSocket, "close", socks_s_close, 0);
3931 #endif
3932 #endif
3934 rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
3935 rb_define_global_const("TCPserver", rb_cTCPServer);
3936 rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
3937 rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0);
3938 rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
3939 rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
3940 rb_define_method(rb_cTCPServer, "listen", sock_listen, 1);
3942 rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
3943 rb_define_global_const("UDPsocket", rb_cUDPSocket);
3944 rb_define_method(rb_cUDPSocket, "initialize", udp_init, -1);
3945 rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
3946 rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
3947 rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
3948 rb_define_method(rb_cUDPSocket, "recvfrom_nonblock", udp_recvfrom_nonblock, -1);
3950 #ifdef HAVE_SYS_UN_H
3951 rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
3952 rb_define_global_const("UNIXsocket", rb_cUNIXSocket);
3953 rb_define_method(rb_cUNIXSocket, "initialize", unix_init, 1);
3954 rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
3955 rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
3956 rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
3957 rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
3958 rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1);
3959 rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1);
3960 rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1);
3961 rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1);
3963 rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
3964 rb_define_global_const("UNIXserver", rb_cUNIXServer);
3965 rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
3966 rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
3967 rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, 0);
3968 rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
3969 rb_define_method(rb_cUNIXServer, "listen", sock_listen, 1);
3970 #endif
3972 rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
3974 rb_define_method(rb_cSocket, "initialize", sock_initialize, 3);
3975 rb_define_method(rb_cSocket, "connect", sock_connect, 1);
3976 rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
3977 rb_define_method(rb_cSocket, "bind", sock_bind, 1);
3978 rb_define_method(rb_cSocket, "listen", sock_listen, 1);
3979 rb_define_method(rb_cSocket, "accept", sock_accept, 0);
3980 rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
3981 rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
3983 rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
3984 rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
3986 rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3);
3987 rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3);
3988 rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
3989 rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
3990 rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
3991 rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyaname, -1);
3992 rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
3993 rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
3994 rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
3995 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
3996 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
3997 #ifdef HAVE_SYS_UN_H
3998 rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
3999 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
4000 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
4001 #endif
4003 /* constants */
4004 mConst = rb_define_module_under(rb_cSocket, "Constants");
4005 sock_define_const("SOCK_STREAM", SOCK_STREAM);
4006 sock_define_const("SOCK_DGRAM", SOCK_DGRAM);
4007 #ifdef SOCK_RAW
4008 sock_define_const("SOCK_RAW", SOCK_RAW);
4009 #endif
4010 #ifdef SOCK_RDM
4011 sock_define_const("SOCK_RDM", SOCK_RDM);
4012 #endif
4013 #ifdef SOCK_SEQPACKET
4014 sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET);
4015 #endif
4016 #ifdef SOCK_PACKET
4017 sock_define_const("SOCK_PACKET", SOCK_PACKET);
4018 #endif
4020 sock_define_const("AF_INET", AF_INET);
4021 #ifdef PF_INET
4022 sock_define_const("PF_INET", PF_INET);
4023 #endif
4024 #ifdef AF_UNIX
4025 sock_define_const("AF_UNIX", AF_UNIX);
4026 sock_define_const("PF_UNIX", PF_UNIX);
4027 #endif
4028 #ifdef AF_AX25
4029 sock_define_const("AF_AX25", AF_AX25);
4030 sock_define_const("PF_AX25", PF_AX25);
4031 #endif
4032 #ifdef AF_IPX
4033 sock_define_const("AF_IPX", AF_IPX);
4034 sock_define_const("PF_IPX", PF_IPX);
4035 #endif
4036 #ifdef AF_APPLETALK
4037 sock_define_const("AF_APPLETALK", AF_APPLETALK);
4038 sock_define_const("PF_APPLETALK", PF_APPLETALK);
4039 #endif
4040 #ifdef AF_UNSPEC
4041 sock_define_const("AF_UNSPEC", AF_UNSPEC);
4042 sock_define_const("PF_UNSPEC", PF_UNSPEC);
4043 #endif
4044 #ifdef INET6
4045 sock_define_const("AF_INET6", AF_INET6);
4046 #endif
4047 #ifdef INET6
4048 sock_define_const("PF_INET6", PF_INET6);
4049 #endif
4050 #ifdef AF_LOCAL
4051 sock_define_const("AF_LOCAL", AF_LOCAL);
4052 #endif
4053 #ifdef PF_LOCAL
4054 sock_define_const("PF_LOCAL", PF_LOCAL);
4055 #endif
4056 #ifdef AF_IMPLINK
4057 sock_define_const("AF_IMPLINK", AF_IMPLINK);
4058 #endif
4059 #ifdef PF_IMPLINK
4060 sock_define_const("PF_IMPLINK", PF_IMPLINK);
4061 #endif
4062 #ifdef AF_PUP
4063 sock_define_const("AF_PUP", AF_PUP);
4064 #endif
4065 #ifdef PF_PUP
4066 sock_define_const("PF_PUP", PF_PUP);
4067 #endif
4068 #ifdef AF_CHAOS
4069 sock_define_const("AF_CHAOS", AF_CHAOS);
4070 #endif
4071 #ifdef PF_CHAOS
4072 sock_define_const("PF_CHAOS", PF_CHAOS);
4073 #endif
4074 #ifdef AF_NS
4075 sock_define_const("AF_NS", AF_NS);
4076 #endif
4077 #ifdef PF_NS
4078 sock_define_const("PF_NS", PF_NS);
4079 #endif
4080 #ifdef AF_ISO
4081 sock_define_const("AF_ISO", AF_ISO);
4082 #endif
4083 #ifdef PF_ISO
4084 sock_define_const("PF_ISO", PF_ISO);
4085 #endif
4086 #ifdef AF_OSI
4087 sock_define_const("AF_OSI", AF_OSI);
4088 #endif
4089 #ifdef PF_OSI
4090 sock_define_const("PF_OSI", PF_OSI);
4091 #endif
4092 #ifdef AF_ECMA
4093 sock_define_const("AF_ECMA", AF_ECMA);
4094 #endif
4095 #ifdef PF_ECMA
4096 sock_define_const("PF_ECMA", PF_ECMA);
4097 #endif
4098 #ifdef AF_DATAKIT
4099 sock_define_const("AF_DATAKIT", AF_DATAKIT);
4100 #endif
4101 #ifdef PF_DATAKIT
4102 sock_define_const("PF_DATAKIT", PF_DATAKIT);
4103 #endif
4104 #ifdef AF_CCITT
4105 sock_define_const("AF_CCITT", AF_CCITT);
4106 #endif
4107 #ifdef PF_CCITT
4108 sock_define_const("PF_CCITT", PF_CCITT);
4109 #endif
4110 #ifdef AF_SNA
4111 sock_define_const("AF_SNA", AF_SNA);
4112 #endif
4113 #ifdef PF_SNA
4114 sock_define_const("PF_SNA", PF_SNA);
4115 #endif
4116 #ifdef AF_DEC
4117 sock_define_const("AF_DEC", AF_DEC);
4118 #endif
4119 #ifdef PF_DEC
4120 sock_define_const("PF_DEC", PF_DEC);
4121 #endif
4122 #ifdef AF_DLI
4123 sock_define_const("AF_DLI", AF_DLI);
4124 #endif
4125 #ifdef PF_DLI
4126 sock_define_const("PF_DLI", PF_DLI);
4127 #endif
4128 #ifdef AF_LAT
4129 sock_define_const("AF_LAT", AF_LAT);
4130 #endif
4131 #ifdef PF_LAT
4132 sock_define_const("PF_LAT", PF_LAT);
4133 #endif
4134 #ifdef AF_HYLINK
4135 sock_define_const("AF_HYLINK", AF_HYLINK);
4136 #endif
4137 #ifdef PF_HYLINK
4138 sock_define_const("PF_HYLINK", PF_HYLINK);
4139 #endif
4140 #ifdef AF_ROUTE
4141 sock_define_const("AF_ROUTE", AF_ROUTE);
4142 #endif
4143 #ifdef PF_ROUTE
4144 sock_define_const("PF_ROUTE", PF_ROUTE);
4145 #endif
4146 #ifdef AF_LINK
4147 sock_define_const("AF_LINK", AF_LINK);
4148 #endif
4149 #ifdef PF_LINK
4150 sock_define_const("PF_LINK", PF_LINK);
4151 #endif
4152 #ifdef AF_COIP
4153 sock_define_const("AF_COIP", AF_COIP);
4154 #endif
4155 #ifdef PF_COIP
4156 sock_define_const("PF_COIP", PF_COIP);
4157 #endif
4158 #ifdef AF_CNT
4159 sock_define_const("AF_CNT", AF_CNT);
4160 #endif
4161 #ifdef PF_CNT
4162 sock_define_const("PF_CNT", PF_CNT);
4163 #endif
4164 #ifdef AF_SIP
4165 sock_define_const("AF_SIP", AF_SIP);
4166 #endif
4167 #ifdef PF_SIP
4168 sock_define_const("PF_SIP", PF_SIP);
4169 #endif
4170 #ifdef AF_NDRV
4171 sock_define_const("AF_NDRV", AF_NDRV);
4172 #endif
4173 #ifdef PF_NDRV
4174 sock_define_const("PF_NDRV", PF_NDRV);
4175 #endif
4176 #ifdef AF_ISDN
4177 sock_define_const("AF_ISDN", AF_ISDN);
4178 #endif
4179 #ifdef PF_ISDN
4180 sock_define_const("PF_ISDN", PF_ISDN);
4181 #endif
4182 #ifdef AF_NATM
4183 sock_define_const("AF_NATM", AF_NATM);
4184 #endif
4185 #ifdef PF_NATM
4186 sock_define_const("PF_NATM", PF_NATM);
4187 #endif
4188 #ifdef AF_SYSTEM
4189 sock_define_const("AF_SYSTEM", AF_SYSTEM);
4190 #endif
4191 #ifdef PF_SYSTEM
4192 sock_define_const("PF_SYSTEM", PF_SYSTEM);
4193 #endif
4194 #ifdef AF_NETBIOS
4195 sock_define_const("AF_NETBIOS", AF_NETBIOS);
4196 #endif
4197 #ifdef PF_NETBIOS
4198 sock_define_const("PF_NETBIOS", PF_NETBIOS);
4199 #endif
4200 #ifdef AF_PPP
4201 sock_define_const("AF_PPP", AF_PPP);
4202 #endif
4203 #ifdef PF_PPP
4204 sock_define_const("PF_PPP", PF_PPP);
4205 #endif
4206 #ifdef AF_ATM
4207 sock_define_const("AF_ATM", AF_ATM);
4208 #endif
4209 #ifdef PF_ATM
4210 sock_define_const("PF_ATM", PF_ATM);
4211 #endif
4212 #ifdef AF_NETGRAPH
4213 sock_define_const("AF_NETGRAPH", AF_NETGRAPH);
4214 #endif
4215 #ifdef PF_NETGRAPH
4216 sock_define_const("PF_NETGRAPH", PF_NETGRAPH);
4217 #endif
4218 #ifdef AF_MAX
4219 sock_define_const("AF_MAX", AF_MAX);
4220 #endif
4221 #ifdef PF_MAX
4222 sock_define_const("PF_MAX", PF_MAX);
4223 #endif
4224 #ifdef AF_E164
4225 sock_define_const("AF_E164", AF_E164);
4226 #endif
4227 #ifdef PF_XTP
4228 sock_define_const("PF_XTP", PF_XTP);
4229 #endif
4230 #ifdef PF_RTIP
4231 sock_define_const("PF_RTIP", PF_RTIP);
4232 #endif
4233 #ifdef PF_PIP
4234 sock_define_const("PF_PIP", PF_PIP);
4235 #endif
4236 #ifdef PF_KEY
4237 sock_define_const("PF_KEY", PF_KEY);
4238 #endif
4240 sock_define_const("MSG_OOB", MSG_OOB);
4241 #ifdef MSG_PEEK
4242 sock_define_const("MSG_PEEK", MSG_PEEK);
4243 #endif
4244 #ifdef MSG_DONTROUTE
4245 sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
4246 #endif
4247 #ifdef MSG_EOR
4248 sock_define_const("MSG_EOR", MSG_EOR);
4249 #endif
4250 #ifdef MSG_TRUNC
4251 sock_define_const("MSG_TRUNC", MSG_TRUNC);
4252 #endif
4253 #ifdef MSG_CTRUNC
4254 sock_define_const("MSG_CTRUNC", MSG_CTRUNC);
4255 #endif
4256 #ifdef MSG_WAITALL
4257 sock_define_const("MSG_WAITALL", MSG_WAITALL);
4258 #endif
4259 #ifdef MSG_DONTWAIT
4260 sock_define_const("MSG_DONTWAIT", MSG_DONTWAIT);
4261 #endif
4262 #ifdef MSG_EOF
4263 sock_define_const("MSG_EOF", MSG_EOF);
4264 #endif
4265 #ifdef MSG_FLUSH
4266 sock_define_const("MSG_FLUSH", MSG_FLUSH);
4267 #endif
4268 #ifdef MSG_HOLD
4269 sock_define_const("MSG_HOLD", MSG_HOLD);
4270 #endif
4271 #ifdef MSG_SEND
4272 sock_define_const("MSG_SEND", MSG_SEND);
4273 #endif
4274 #ifdef MSG_HAVEMORE
4275 sock_define_const("MSG_HAVEMORE", MSG_HAVEMORE);
4276 #endif
4277 #ifdef MSG_RCVMORE
4278 sock_define_const("MSG_RCVMORE", MSG_RCVMORE);
4279 #endif
4280 #ifdef MSG_COMPAT
4281 sock_define_const("MSG_COMPAT", MSG_COMPAT);
4282 #endif
4284 sock_define_const("SOL_SOCKET", SOL_SOCKET);
4285 #ifdef SOL_IP
4286 sock_define_const("SOL_IP", SOL_IP);
4287 #endif
4288 #ifdef SOL_IPX
4289 sock_define_const("SOL_IPX", SOL_IPX);
4290 #endif
4291 #ifdef SOL_AX25
4292 sock_define_const("SOL_AX25", SOL_AX25);
4293 #endif
4294 #ifdef SOL_ATALK
4295 sock_define_const("SOL_ATALK", SOL_ATALK);
4296 #endif
4297 #ifdef SOL_TCP
4298 sock_define_const("SOL_TCP", SOL_TCP);
4299 #endif
4300 #ifdef SOL_UDP
4301 sock_define_const("SOL_UDP", SOL_UDP);
4302 #endif
4304 #ifdef IPPROTO_IP
4305 sock_define_const("IPPROTO_IP", IPPROTO_IP);
4306 #else
4307 sock_define_const("IPPROTO_IP", 0);
4308 #endif
4309 #ifdef IPPROTO_ICMP
4310 sock_define_const("IPPROTO_ICMP", IPPROTO_ICMP);
4311 #else
4312 sock_define_const("IPPROTO_ICMP", 1);
4313 #endif
4314 #ifdef IPPROTO_IGMP
4315 sock_define_const("IPPROTO_IGMP", IPPROTO_IGMP);
4316 #endif
4317 #ifdef IPPROTO_GGP
4318 sock_define_const("IPPROTO_GGP", IPPROTO_GGP);
4319 #endif
4320 #ifdef IPPROTO_TCP
4321 sock_define_const("IPPROTO_TCP", IPPROTO_TCP);
4322 #else
4323 sock_define_const("IPPROTO_TCP", 6);
4324 #endif
4325 #ifdef IPPROTO_EGP
4326 sock_define_const("IPPROTO_EGP", IPPROTO_EGP);
4327 #endif
4328 #ifdef IPPROTO_PUP
4329 sock_define_const("IPPROTO_PUP", IPPROTO_PUP);
4330 #endif
4331 #ifdef IPPROTO_UDP
4332 sock_define_const("IPPROTO_UDP", IPPROTO_UDP);
4333 #else
4334 sock_define_const("IPPROTO_UDP", 17);
4335 #endif
4336 #ifdef IPPROTO_IDP
4337 sock_define_const("IPPROTO_IDP", IPPROTO_IDP);
4338 #endif
4339 #ifdef IPPROTO_HELLO
4340 sock_define_const("IPPROTO_HELLO", IPPROTO_HELLO);
4341 #endif
4342 #ifdef IPPROTO_ND
4343 sock_define_const("IPPROTO_ND", IPPROTO_ND);
4344 #endif
4345 #ifdef IPPROTO_TP
4346 sock_define_const("IPPROTO_TP", IPPROTO_TP);
4347 #endif
4348 #ifdef IPPROTO_XTP
4349 sock_define_const("IPPROTO_XTP", IPPROTO_XTP);
4350 #endif
4351 #ifdef IPPROTO_EON
4352 sock_define_const("IPPROTO_EON", IPPROTO_EON);
4353 #endif
4354 #ifdef IPPROTO_BIP
4355 sock_define_const("IPPROTO_BIP", IPPROTO_BIP);
4356 #endif
4357 /**/
4358 #ifdef IPPROTO_RAW
4359 sock_define_const("IPPROTO_RAW", IPPROTO_RAW);
4360 #else
4361 sock_define_const("IPPROTO_RAW", 255);
4362 #endif
4363 #ifdef IPPROTO_MAX
4364 sock_define_const("IPPROTO_MAX", IPPROTO_MAX);
4365 #endif
4367 /* Some port configuration */
4368 #ifdef IPPORT_RESERVED
4369 sock_define_const("IPPORT_RESERVED", IPPORT_RESERVED);
4370 #else
4371 sock_define_const("IPPORT_RESERVED", 1024);
4372 #endif
4373 #ifdef IPPORT_USERRESERVED
4374 sock_define_const("IPPORT_USERRESERVED", IPPORT_USERRESERVED);
4375 #else
4376 sock_define_const("IPPORT_USERRESERVED", 5000);
4377 #endif
4378 /* Some reserved IP v.4 addresses */
4379 #ifdef INADDR_ANY
4380 sock_define_const("INADDR_ANY", INADDR_ANY);
4381 #else
4382 sock_define_const("INADDR_ANY", 0x00000000);
4383 #endif
4384 #ifdef INADDR_BROADCAST
4385 sock_define_const("INADDR_BROADCAST", INADDR_BROADCAST);
4386 #else
4387 sock_define_const("INADDR_BROADCAST", 0xffffffff);
4388 #endif
4389 #ifdef INADDR_LOOPBACK
4390 sock_define_const("INADDR_LOOPBACK", INADDR_LOOPBACK);
4391 #else
4392 sock_define_const("INADDR_LOOPBACK", 0x7F000001);
4393 #endif
4394 #ifdef INADDR_UNSPEC_GROUP
4395 sock_define_const("INADDR_UNSPEC_GROUP", INADDR_UNSPEC_GROUP);
4396 #else
4397 sock_define_const("INADDR_UNSPEC_GROUP", 0xe0000000);
4398 #endif
4399 #ifdef INADDR_ALLHOSTS_GROUP
4400 sock_define_const("INADDR_ALLHOSTS_GROUP", INADDR_ALLHOSTS_GROUP);
4401 #else
4402 sock_define_const("INADDR_ALLHOSTS_GROUP", 0xe0000001);
4403 #endif
4404 #ifdef INADDR_MAX_LOCAL_GROUP
4405 sock_define_const("INADDR_MAX_LOCAL_GROUP", INADDR_MAX_LOCAL_GROUP);
4406 #else
4407 sock_define_const("INADDR_MAX_LOCAL_GROUP", 0xe00000ff);
4408 #endif
4409 #ifdef INADDR_NONE
4410 sock_define_const("INADDR_NONE", INADDR_NONE);
4411 #else
4412 sock_define_const("INADDR_NONE", 0xffffffff);
4413 #endif
4414 /* IP [gs]etsockopt options */
4415 #ifdef IP_OPTIONS
4416 sock_define_const("IP_OPTIONS", IP_OPTIONS);
4417 #endif
4418 #ifdef IP_HDRINCL
4419 sock_define_const("IP_HDRINCL", IP_HDRINCL);
4420 #endif
4421 #ifdef IP_TOS
4422 sock_define_const("IP_TOS", IP_TOS);
4423 #endif
4424 #ifdef IP_TTL
4425 sock_define_const("IP_TTL", IP_TTL);
4426 #endif
4427 #ifdef IP_RECVOPTS
4428 sock_define_const("IP_RECVOPTS", IP_RECVOPTS);
4429 #endif
4430 #ifdef IP_RECVRETOPTS
4431 sock_define_const("IP_RECVRETOPTS", IP_RECVRETOPTS);
4432 #endif
4433 #ifdef IP_RECVDSTADDR
4434 sock_define_const("IP_RECVDSTADDR", IP_RECVDSTADDR);
4435 #endif
4436 #ifdef IP_RETOPTS
4437 sock_define_const("IP_RETOPTS", IP_RETOPTS);
4438 #endif
4439 #ifdef IP_MULTICAST_IF
4440 sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF);
4441 #endif
4442 #ifdef IP_MULTICAST_TTL
4443 sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL);
4444 #endif
4445 #ifdef IP_MULTICAST_LOOP
4446 sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP);
4447 #endif
4448 #ifdef IP_ADD_MEMBERSHIP
4449 sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP);
4450 #endif
4451 #ifdef IP_DROP_MEMBERSHIP
4452 sock_define_const("IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP);
4453 #endif
4454 #ifdef IP_DEFAULT_MULTICAST_TTL
4455 sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL);
4456 #endif
4457 #ifdef IP_DEFAULT_MULTICAST_LOOP
4458 sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP);
4459 #endif
4460 #ifdef IP_MAX_MEMBERSHIPS
4461 sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
4462 #endif
4463 #ifdef SO_DEBUG
4464 sock_define_const("SO_DEBUG", SO_DEBUG);
4465 #endif
4466 sock_define_const("SO_REUSEADDR", SO_REUSEADDR);
4467 #ifdef SO_REUSEPORT
4468 sock_define_const("SO_REUSEPORT", SO_REUSEPORT);
4469 #endif
4470 #ifdef SO_TYPE
4471 sock_define_const("SO_TYPE", SO_TYPE);
4472 #endif
4473 #ifdef SO_ERROR
4474 sock_define_const("SO_ERROR", SO_ERROR);
4475 #endif
4476 #ifdef SO_DONTROUTE
4477 sock_define_const("SO_DONTROUTE", SO_DONTROUTE);
4478 #endif
4479 #ifdef SO_BROADCAST
4480 sock_define_const("SO_BROADCAST", SO_BROADCAST);
4481 #endif
4482 #ifdef SO_SNDBUF
4483 sock_define_const("SO_SNDBUF", SO_SNDBUF);
4484 #endif
4485 #ifdef SO_RCVBUF
4486 sock_define_const("SO_RCVBUF", SO_RCVBUF);
4487 #endif
4488 #ifdef SO_KEEPALIVE
4489 sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
4490 #endif
4491 #ifdef SO_OOBINLINE
4492 sock_define_const("SO_OOBINLINE", SO_OOBINLINE);
4493 #endif
4494 #ifdef SO_NO_CHECK
4495 sock_define_const("SO_NO_CHECK", SO_NO_CHECK);
4496 #endif
4497 #ifdef SO_PRIORITY
4498 sock_define_const("SO_PRIORITY", SO_PRIORITY);
4499 #endif
4500 #ifdef SO_LINGER
4501 sock_define_const("SO_LINGER", SO_LINGER);
4502 #endif
4503 #ifdef SO_PASSCRED
4504 sock_define_const("SO_PASSCRED", SO_PASSCRED);
4505 #endif
4506 #ifdef SO_PEERCRED
4507 sock_define_const("SO_PEERCRED", SO_PEERCRED);
4508 #endif
4509 #ifdef SO_RCVLOWAT
4510 sock_define_const("SO_RCVLOWAT", SO_RCVLOWAT);
4511 #endif
4512 #ifdef SO_SNDLOWAT
4513 sock_define_const("SO_SNDLOWAT", SO_SNDLOWAT);
4514 #endif
4515 #ifdef SO_RCVTIMEO
4516 sock_define_const("SO_RCVTIMEO", SO_RCVTIMEO);
4517 #endif
4518 #ifdef SO_SNDTIMEO
4519 sock_define_const("SO_SNDTIMEO", SO_SNDTIMEO);
4520 #endif
4521 #ifdef SO_ACCEPTCONN
4522 sock_define_const("SO_ACCEPTCONN", SO_ACCEPTCONN);
4523 #endif
4524 #ifdef SO_USELOOPBACK
4525 sock_define_const("SO_USELOOPBACK", SO_USELOOPBACK);
4526 #endif
4527 #ifdef SO_ACCEPTFILTER
4528 sock_define_const("SO_ACCEPTFILTER", SO_ACCEPTFILTER);
4529 #endif
4530 #ifdef SO_DONTTRUNC
4531 sock_define_const("SO_DONTTRUNC", SO_DONTTRUNC);
4532 #endif
4533 #ifdef SO_WANTMORE
4534 sock_define_const("SO_WANTMORE", SO_WANTMORE);
4535 #endif
4536 #ifdef SO_WANTOOBFLAG
4537 sock_define_const("SO_WANTOOBFLAG", SO_WANTOOBFLAG);
4538 #endif
4539 #ifdef SO_NREAD
4540 sock_define_const("SO_NREAD", SO_NREAD);
4541 #endif
4542 #ifdef SO_NKE
4543 sock_define_const("SO_NKE", SO_NKE);
4544 #endif
4545 #ifdef SO_NOSIGPIPE
4546 sock_define_const("SO_NOSIGPIPE", SO_NOSIGPIPE);
4547 #endif
4549 #ifdef SO_SECURITY_AUTHENTICATION
4550 sock_define_const("SO_SECURITY_AUTHENTICATION", SO_SECURITY_AUTHENTICATION);
4551 #endif
4552 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
4553 sock_define_const("SO_SECURITY_ENCRYPTION_TRANSPORT", SO_SECURITY_ENCRYPTION_TRANSPORT);
4554 #endif
4555 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
4556 sock_define_const("SO_SECURITY_ENCRYPTION_NETWORK", SO_SECURITY_ENCRYPTION_NETWORK);
4557 #endif
4559 #ifdef SO_BINDTODEVICE
4560 sock_define_const("SO_BINDTODEVICE", SO_BINDTODEVICE);
4561 #endif
4562 #ifdef SO_ATTACH_FILTER
4563 sock_define_const("SO_ATTACH_FILTER", SO_ATTACH_FILTER);
4564 #endif
4565 #ifdef SO_DETACH_FILTER
4566 sock_define_const("SO_DETACH_FILTER", SO_DETACH_FILTER);
4567 #endif
4568 #ifdef SO_PEERNAME
4569 sock_define_const("SO_PEERNAME", SO_PEERNAME);
4570 #endif
4571 #ifdef SO_TIMESTAMP
4572 sock_define_const("SO_TIMESTAMP", SO_TIMESTAMP);
4573 #endif
4575 #ifdef SOPRI_INTERACTIVE
4576 sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
4577 #endif
4578 #ifdef SOPRI_NORMAL
4579 sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL);
4580 #endif
4581 #ifdef SOPRI_BACKGROUND
4582 sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND);
4583 #endif
4585 #ifdef IPX_TYPE
4586 sock_define_const("IPX_TYPE", IPX_TYPE);
4587 #endif
4589 #ifdef TCP_NODELAY
4590 sock_define_const("TCP_NODELAY", TCP_NODELAY);
4591 #endif
4592 #ifdef TCP_MAXSEG
4593 sock_define_const("TCP_MAXSEG", TCP_MAXSEG);
4594 #endif
4596 #ifdef EAI_ADDRFAMILY
4597 sock_define_const("EAI_ADDRFAMILY", EAI_ADDRFAMILY);
4598 #endif
4599 #ifdef EAI_AGAIN
4600 sock_define_const("EAI_AGAIN", EAI_AGAIN);
4601 #endif
4602 #ifdef EAI_BADFLAGS
4603 sock_define_const("EAI_BADFLAGS", EAI_BADFLAGS);
4604 #endif
4605 #ifdef EAI_FAIL
4606 sock_define_const("EAI_FAIL", EAI_FAIL);
4607 #endif
4608 #ifdef EAI_FAMILY
4609 sock_define_const("EAI_FAMILY", EAI_FAMILY);
4610 #endif
4611 #ifdef EAI_MEMORY
4612 sock_define_const("EAI_MEMORY", EAI_MEMORY);
4613 #endif
4614 #ifdef EAI_NODATA
4615 sock_define_const("EAI_NODATA", EAI_NODATA);
4616 #endif
4617 #ifdef EAI_NONAME
4618 sock_define_const("EAI_NONAME", EAI_NONAME);
4619 #endif
4620 #ifdef EAI_SERVICE
4621 sock_define_const("EAI_SERVICE", EAI_SERVICE);
4622 #endif
4623 #ifdef EAI_SOCKTYPE
4624 sock_define_const("EAI_SOCKTYPE", EAI_SOCKTYPE);
4625 #endif
4626 #ifdef EAI_SYSTEM
4627 sock_define_const("EAI_SYSTEM", EAI_SYSTEM);
4628 #endif
4629 #ifdef EAI_BADHINTS
4630 sock_define_const("EAI_BADHINTS", EAI_BADHINTS);
4631 #endif
4632 #ifdef EAI_PROTOCOL
4633 sock_define_const("EAI_PROTOCOL", EAI_PROTOCOL);
4634 #endif
4635 #ifdef EAI_MAX
4636 sock_define_const("EAI_MAX", EAI_MAX);
4637 #endif
4638 #ifdef AI_PASSIVE
4639 sock_define_const("AI_PASSIVE", AI_PASSIVE);
4640 #endif
4641 #ifdef AI_CANONNAME
4642 sock_define_const("AI_CANONNAME", AI_CANONNAME);
4643 #endif
4644 #ifdef AI_NUMERICHOST
4645 sock_define_const("AI_NUMERICHOST", AI_NUMERICHOST);
4646 #endif
4647 #ifdef AI_MASK
4648 sock_define_const("AI_MASK", AI_MASK);
4649 #endif
4650 #ifdef AI_ALL
4651 sock_define_const("AI_ALL", AI_ALL);
4652 #endif
4653 #ifdef AI_V4MAPPED_CFG
4654 sock_define_const("AI_V4MAPPED_CFG", AI_V4MAPPED_CFG);
4655 #endif
4656 #ifdef AI_ADDRCONFIG
4657 sock_define_const("AI_ADDRCONFIG", AI_ADDRCONFIG);
4658 #endif
4659 #ifdef AI_V4MAPPED
4660 sock_define_const("AI_V4MAPPED", AI_V4MAPPED);
4661 #endif
4662 #ifdef AI_DEFAULT
4663 sock_define_const("AI_DEFAULT", AI_DEFAULT);
4664 #endif
4665 #ifdef NI_MAXHOST
4666 sock_define_const("NI_MAXHOST", NI_MAXHOST);
4667 #endif
4668 #ifdef NI_MAXSERV
4669 sock_define_const("NI_MAXSERV", NI_MAXSERV);
4670 #endif
4671 #ifdef NI_NOFQDN
4672 sock_define_const("NI_NOFQDN", NI_NOFQDN);
4673 #endif
4674 #ifdef NI_NUMERICHOST
4675 sock_define_const("NI_NUMERICHOST", NI_NUMERICHOST);
4676 #endif
4677 #ifdef NI_NAMEREQD
4678 sock_define_const("NI_NAMEREQD", NI_NAMEREQD);
4679 #endif
4680 #ifdef NI_NUMERICSERV
4681 sock_define_const("NI_NUMERICSERV", NI_NUMERICSERV);
4682 #endif
4683 #ifdef NI_DGRAM
4684 sock_define_const("NI_DGRAM", NI_DGRAM);
4685 #endif
4686 #ifdef SHUT_RD
4687 sock_define_const("SHUT_RD", SHUT_RD);
4688 #else
4689 sock_define_const("SHUT_RD", 0);
4690 #endif
4691 #ifdef SHUT_WR
4692 sock_define_const("SHUT_WR", SHUT_WR);
4693 #else
4694 sock_define_const("SHUT_WR", 1);
4695 #endif
4696 #ifdef SHUT_RDWR
4697 sock_define_const("SHUT_RDWR", SHUT_RDWR);
4698 #else
4699 sock_define_const("SHUT_RDWR", 2);
4700 #endif