1 /************************************************
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 ************************************************/
18 #include <sys/types.h>
30 # include <net/socket.h>
32 # include <sys/socket.h>
33 # define pseudo_AF_FTIP pseudo_AF_RTIP /* workaround for NetBSD and etc. */
35 #include <netinet/in.h>
36 #ifdef HAVE_NETINET_IN_SYSTM_H
37 # include <netinet/in_systm.h>
39 #ifdef HAVE_NETINET_TCP_H
40 # include <netinet/tcp.h>
42 #ifdef HAVE_NETINET_UDP_H
43 # include <netinet/udp.h>
45 #ifdef HAVE_ARPA_INET_H
46 # include <arpa/inet.h>
55 #if defined(HAVE_FCNTL)
56 #ifdef HAVE_SYS_SELECT_H
57 #include <sys/select.h>
59 #ifdef HAVE_SYS_TYPES_H
60 #include <sys/types.h>
62 #ifdef HAVE_SYS_TIME_H
70 #define EWOULDBLOCK EAGAIN
72 #ifndef HAVE_GETADDRINFO
73 # include "addrinfo.h"
81 static int do_not_reverse_lookup
= 0;
83 VALUE rb_cBasicSocket
;
94 static VALUE rb_eSocket
;
97 VALUE rb_cSOCKSSocket
;
106 #define INET_CLIENT 0
107 #define INET_SERVER 1
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
{
122 unsigned char ss_len
; /* address length */
123 unsigned char ss_family
; /* address family */
125 unsigned short ss_family
;
127 char __ss_pad1
[_SS_PAD1SIZE
];
128 double __ss_align
; /* force desired structure storage alignment */
129 char __ss_pad2
[_SS_PAD2SIZE
];
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
,
141 /* should not happen */
146 ruby_getaddrinfo(nodename
, servname
, hints
, res
)
149 struct addrinfo
*hints
;
150 struct addrinfo
**res
;
152 struct addrinfo tmp_hints
;
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
);
165 if (tmp_hints
.ai_family
== PF_UNSPEC
) {
176 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
181 ruby_getaddrinfo__aix(nodename
, servname
, hints
, res
)
184 struct addrinfo
*hints
;
185 struct addrinfo
**res
;
187 int error
= getaddrinfo(nodename
, servname
, hints
, res
);
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
;
200 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
202 ruby_getnameinfo__aix(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
)
203 const struct sockaddr
*sa
;
211 struct sockaddr_in6
*sa6
;
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
);
224 return getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
);
227 #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
228 ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
230 # define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
233 # define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
237 #ifdef HAVE_CLOSESOCKET
239 #define close closesocket
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
);
259 bsock_s_for_fd(klass
, fd
)
263 VALUE sock
= init_sock(rb_obj_alloc(klass
), NUM2INT(fd
));
265 GetOpenFile(sock
, fptr
);
271 bsock_shutdown(argc
, argv
, sock
)
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
);
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)
300 bsock_close_read(sock
)
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
;
319 bsock_close_write(sock
)
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
;
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.
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,
357 * - String: the string's data and length is passed to the socket.
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:
373 * struct in_addr imr_multiaddr;
374 * struct in_addr imr_interface;
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)
383 bsock_setsockopt(sock
, lev
, optname
, val
)
384 VALUE sock
, lev
, optname
, val
;
393 level
= NUM2INT(lev
);
394 option
= NUM2INT(optname
);
406 v
= (char*)&i
; vlen
= sizeof(i
);
410 v
= RSTRING(val
)->ptr
;
411 vlen
= RSTRING(val
)->len
;
415 GetOpenFile(sock
, fptr
);
416 if (setsockopt(fileno(fptr
->f
), level
, option
, v
, vlen
) < 0)
417 rb_sys_fail(fptr
->path
);
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.
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.
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
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"
463 bsock_getsockopt(sock
, lev
, optname
)
464 VALUE sock
, lev
, optname
;
466 #if !defined(__BEOS__)
472 level
= NUM2INT(lev
);
473 option
= NUM2INT(optname
);
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
);
489 bsock_getsockname(sock
)
493 socklen_t len
= sizeof buf
;
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
);
503 bsock_getpeername(sock
)
507 socklen_t len
= sizeof buf
;
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
);
517 bsock_send(argc
, argv
, sock
)
529 rb_scan_args(argc
, argv
, "21", &mesg
, &flags
, &to
);
532 if (!NIL_P(to
)) StringValue(to
);
533 GetOpenFile(sock
, fptr
);
534 f
= GetWriteFile(fptr
);
536 rb_thread_fd_writable(fd
);
540 n
= sendto(fd
, RSTRING(mesg
)->ptr
, RSTRING(mesg
)->len
, NUM2INT(flags
),
541 (struct sockaddr
*)RSTRING(to
)->ptr
, RSTRING(to
)->len
);
546 n
= send(fd
, RSTRING(mesg
)->ptr
, RSTRING(mesg
)->len
, NUM2INT(flags
));
550 if (rb_io_wait_writable(fd
)) {
553 rb_sys_fail("send(2)");
558 static VALUE ipaddr
_((struct sockaddr
*));
560 static VALUE unixaddr
_((struct sockaddr_un
*, socklen_t
));
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 */
571 s_recvfrom(sock
, argc
, argv
, from
)
575 enum sock_recv_type from
;
580 socklen_t alen
= sizeof buf
;
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
);
602 rb_thread_wait_fd(fd
);
604 slen
= recvfrom(fd
, RSTRING(str
)->ptr
, buflen
, flags
, (struct sockaddr
*)buf
, &alen
);
606 rb_str_unlocktmp(str
);
609 if (rb_io_wait_readable(fd
)) {
612 rb_sys_fail("recvfrom(2)");
614 if (slen
< RSTRING(str
)->len
) {
615 RSTRING(str
)->len
= slen
;
616 RSTRING(str
)->ptr
[slen
] = '\0';
624 if (alen
!= sizeof(struct sockaddr_in
)) {
625 rb_raise(rb_eTypeError
, "sockaddr size differs - should not happen");
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
));
631 return rb_assoc_new(str
, Qnil
);
635 return rb_assoc_new(str
, unixaddr((struct sockaddr_un
*)buf
, alen
));
638 return rb_assoc_new(str
, rb_str_new(buf
, alen
));
640 rb_bug("s_recvfrom called with bad value");
645 s_recvfrom_nonblock(VALUE sock
, int argc
, VALUE
*argv
, enum sock_recv_type from
)
650 socklen_t alen
= sizeof buf
;
657 rb_scan_args(argc
, argv
, "11", &len
, &flg
);
659 if (flg
== Qnil
) flags
= 0;
660 else flags
= NUM2INT(flg
);
661 buflen
= NUM2INT(len
);
664 /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
665 It is not portable, though. */
666 flags
|= MSG_DONTWAIT
;
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
);
682 rb_sys_fail("recvfrom(2)");
684 if (slen
< RSTRING(str
)->len
) {
685 RSTRING(str
)->len
= slen
;
686 RSTRING(str
)->ptr
[slen
] = '\0';
694 if (alen
) /* connection-oriented socket may not return a from result */
695 addr
= ipaddr((struct sockaddr
*)buf
);
699 addr
= rb_str_new(buf
, alen
);
703 rb_bug("s_recvfrom_nonblock called with bad value");
705 return rb_assoc_new(str
, addr
);
709 bsock_recv(argc
, argv
, sock
)
714 return s_recvfrom(sock
, argc
, argv
, RECV_RECV
);
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.
732 * * +maxlen+ - the number of bytes to receive from the socket
733 * * +flags+ - zero or more of the +MSG_+ options
736 * serv = TCPServer.new("127.0.0.1", 0)
737 * af, port, host, addr = serv.addr
738 * c = TCPSocket.new(addr, port)
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.
755 bsock_recv_nonblock(argc
, argv
, sock
)
760 return s_recvfrom_nonblock(sock
, argc
, argv
, RECV_RECV
);
764 bsock_do_not_rev_lookup()
766 return do_not_reverse_lookup
?Qtrue
:Qfalse
;
770 bsock_do_not_rev_lookup_set(self
, val
)
774 do_not_reverse_lookup
= RTEST(val
);
779 make_ipaddr0(addr
, buf
, len
)
780 struct sockaddr
*addr
;
786 error
= getnameinfo(addr
, SA_LEN(addr
), buf
, len
, NULL
, 0, NI_NUMERICHOST
);
788 rb_raise(rb_eSocket
, "getnameinfo: %s", gai_strerror(error
));
794 struct sockaddr
*addr
;
798 make_ipaddr0(addr
, buf
, sizeof(buf
));
799 return rb_str_new2(buf
);
803 make_inetaddr(host
, buf
, 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
);
823 if (!p
|| *p
== '\0')
826 (void)strtoul(p
, &ep
, 10);
827 if (ep
&& *ep
== '\0')
834 host_str(host
, hbuf
, len
)
842 else if (rb_obj_is_kind_of(host
, rb_cInteger
)) {
843 long i
= NUM2LONG(host
);
845 make_inetaddr(htonl(i
), hbuf
, len
);
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
));
870 port_str(port
, pbuf
, len
)
878 else if (FIXNUM_P(port
)) {
879 snprintf(pbuf
, len
, "%ld", FIX2LONG(port
));
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
));
902 static struct addrinfo
*
903 sock_addrinfo(host
, port
, socktype
, flags
)
907 struct addrinfo hints
;
908 struct addrinfo
* res
= NULL
;
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
);
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__)
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
;
954 struct sockaddr
*sockaddr
;
956 VALUE family
, port
, addr1
, addr2
;
959 char hbuf
[1024], pbuf
[1024];
961 switch (sockaddr
->sa_family
) {
963 family
= rb_str_new2("AF_UNSPEC");
966 family
= rb_str_new2("AF_INET");
970 family
= rb_str_new2("AF_INET6");
975 family
= rb_str_new2("AF_LOCAL");
979 family
= rb_str_new2("AF_UNIX");
983 sprintf(pbuf
, "unknown:%d", sockaddr
->sa_family
);
984 family
= rb_str_new2(pbuf
);
988 if (!do_not_reverse_lookup
) {
989 error
= getnameinfo(sockaddr
, SA_LEN(sockaddr
), hbuf
, sizeof(hbuf
),
992 addr1
= rb_str_new2(hbuf
);
995 error
= getnameinfo(sockaddr
, SA_LEN(sockaddr
), hbuf
, sizeof(hbuf
),
996 pbuf
, sizeof(pbuf
), NI_NUMERICHOST
| NI_NUMERICSERV
);
998 rb_raise(rb_eSocket
, "getnameinfo: %s", gai_strerror(error
));
1000 addr2
= rb_str_new2(hbuf
);
1001 if (addr1
== Qnil
) {
1004 port
= INT2FIX(atoi(pbuf
));
1005 ary
= rb_ary_new3(4, family
, port
, addr1
, addr2
);
1011 ruby_socket(domain
, type
, proto
)
1012 int domain
, type
, proto
;
1016 fd
= socket(domain
, type
, proto
);
1018 if (errno
== EMFILE
|| errno
== ENFILE
) {
1020 fd
= socket(domain
, type
, proto
);
1027 wait_connectable(fd
)
1031 socklen_t sockerrlen
;
1042 rb_thread_select(fd
+1, 0, &fds_w
, &fds_e
, 0);
1044 if (FD_ISSET(fd
, &fds_w
)) {
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) {
1052 continue; /* workaround for winsock */
1063 #define WAIT_IN_PROGRESS 10
1066 #define WAIT_IN_PROGRESS 10
1069 /* returns correct error */
1070 #define WAIT_IN_PROGRESS 0
1072 #ifndef WAIT_IN_PROGRESS
1073 /* BSD origin code apparently has a problem */
1074 #define WAIT_IN_PROGRESS 1
1078 ruby_connect(fd
, sockaddr
, len
, socks
)
1080 struct sockaddr
*sockaddr
;
1086 #if WAIT_IN_PROGRESS > 0
1087 int wait_in_progress
= -1;
1089 socklen_t sockerrlen
;
1092 #if defined(HAVE_FCNTL)
1093 # if defined(F_GETFL)
1094 mode
= fcntl(fd
, F_GETFL
, 0);
1100 # define NONBLOCKING O_NDELAY
1103 # define NONBLOCKING O_NBIO
1105 # define NONBLOCKING O_NONBLOCK
1111 fcntl(fd
, F_SETFL
, mode
|NONBLOCKING
);
1112 #endif /* HAVE_FCNTL */
1115 #if defined(SOCKS) && !defined(SOCKS5)
1117 status
= Rconnect(fd
, sockaddr
, len
);
1122 status
= connect(fd
, sockaddr
, len
);
1130 #if WAIT_IN_PROGRESS > 0
1131 sockerrlen
= sizeof(sockerr
);
1132 status
= getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, (void *)&sockerr
, &sockerrlen
);
1143 #if WAIT_IN_PROGRESS > 0
1144 wait_in_progress
= WAIT_IN_PROGRESS
;
1146 status
= wait_connectable(fd
);
1153 #if WAIT_IN_PROGRESS > 0
1155 if (wait_in_progress
-- > 0) {
1157 * connect() after EINPROGRESS returns EINVAL on
1158 * some platforms, need to check true error
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
);
1185 fcntl(fd
, F_SETFL
, mode
);
1196 struct addrinfo
*res
;
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
);
1221 init_inetsock_internal(arg
)
1222 struct inetsock_arg
*arg
;
1224 int type
= arg
->type
;
1225 struct addrinfo
*res
;
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);
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)";
1248 if (type
== INET_SERVER
) {
1249 #if !defined(_WIN32) && !defined(__CYGWIN__)
1251 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
,
1252 (char*)&status
, sizeof(status
));
1254 status
= bind(fd
, res
->ai_addr
, res
->ai_addrlen
);
1255 syscall
= "bind(2)";
1258 if (arg
->local
.res
) {
1259 status
= bind(fd
, arg
->local
.res
->ai_addr
, arg
->local
.res
->ai_addrlen
);
1260 syscall
= "bind(2)";
1264 status
= ruby_connect(fd
, res
->ai_addr
, res
->ai_addrlen
,
1265 (type
== INET_SOCKS
));
1266 syscall
= "connect(2)";
1278 rb_sys_fail(syscall
);
1283 if (type
== INET_SERVER
)
1286 /* create new instance */
1287 return init_sock(arg
->sock
, fd
);
1291 init_inetsock(sock
, remote_host
, remote_serv
, local_host
, local_serv
, type
)
1292 VALUE sock
, remote_host
, remote_serv
, local_host
, local_serv
;
1295 struct inetsock_arg arg
;
1297 arg
.remote
.host
= remote_host
;
1298 arg
.remote
.serv
= remote_serv
;
1300 arg
.local
.host
= local_host
;
1301 arg
.local
.serv
= local_serv
;
1305 return rb_ensure(init_inetsock_internal
, (VALUE
)&arg
,
1306 inetsock_cleanup
, (VALUE
)&arg
);
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.
1318 tcp_init(argc
, argv
, 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
);
1335 socks_init(sock
, host
, serv
)
1336 VALUE sock
, host
, serv
;
1345 return init_inetsock(sock
, host
, serv
, Qnil
, Qnil
, INET_SOCKS
);
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
);
1366 struct hostent_arg
{
1368 struct addrinfo
* addr
;
1369 VALUE (*ipaddr
)_((struct sockaddr
*, size_t));
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
;
1385 char hbuf
[NI_MAXHOST
];
1388 if (addr
->ai_canonname
) {
1389 hostp
= addr
->ai_canonname
;
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
));
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
));
1423 make_hostent(host
, addr
, ipaddr
)
1425 struct addrinfo
* addr
;
1426 VALUE (*ipaddr
)_((struct sockaddr
*, size_t));
1428 struct hostent_arg arg
;
1432 arg
.ipaddr
= ipaddr
;
1433 return rb_ensure(make_hostent_internal
, (VALUE
)&arg
,
1434 RUBY_METHOD_FUNC(freeaddrinfo
), (VALUE
)addr
);
1438 tcp_sockaddr(addr
, len
)
1439 struct sockaddr
*addr
;
1442 return make_ipaddr(addr
);
1446 tcp_s_gethostbyname(obj
, host
)
1450 return make_hostent(host
, sock_addrinfo(host
, Qnil
, SOCK_STREAM
, AI_CANONNAME
), tcp_sockaddr
);
1454 tcp_svr_init(argc
, argv
, sock
)
1461 if (rb_scan_args(argc
, argv
, "11", &arg1
, &arg2
) == 2)
1462 return init_inetsock(sock
, arg1
, arg2
, Qnil
, Qnil
, INET_SERVER
);
1464 return init_inetsock(sock
, Qnil
, arg1
, Qnil
, Qnil
, INET_SERVER
);
1468 s_accept_nonblock(VALUE klass
, OpenFile
*fptr
, struct sockaddr
*sockaddr
, socklen_t
*len
)
1473 rb_io_set_nonblock(fptr
);
1474 fd2
= accept(fileno(fptr
->f
), (struct sockaddr
*)sockaddr
, len
);
1476 rb_sys_fail("accept(2)");
1478 return init_sock(rb_obj_alloc(klass
), fd2
);
1482 s_accept(klass
, fd
, sockaddr
, len
)
1485 struct sockaddr
*sockaddr
;
1493 rb_thread_wait_fd(fd
);
1494 #if defined(_nec_ews)
1495 fd2
= accept(fd
, sockaddr
, len
);
1498 fd2
= accept(fd
, sockaddr
, len
);
1512 if (!rb_io_wait_readable(fd
)) break;
1518 if (!klass
) return INT2NUM(fd2
);
1519 return init_sock(rb_obj_alloc(klass
), fd2
);
1527 struct sockaddr_storage from
;
1530 GetOpenFile(sock
, fptr
);
1531 fromlen
= sizeof(from
);
1532 return s_accept(rb_cTCPSocket
, fileno(fptr
->f
),
1533 (struct sockaddr
*)&from
, &fromlen
);
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.
1546 * serv = TCPServer.new(2202)
1548 * sock = serv.accept_nonblock
1549 * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
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.
1562 * * TCPServer#accept
1566 tcp_accept_nonblock(sock
)
1570 struct sockaddr_storage from
;
1573 GetOpenFile(sock
, fptr
);
1574 fromlen
= sizeof(from
);
1575 return s_accept_nonblock(rb_cTCPSocket
, fptr
,
1576 (struct sockaddr
*)&from
, &fromlen
);
1584 struct sockaddr_storage from
;
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
;
1599 unixsock_connect_internal(arg
)
1600 struct unixsock_arg
*arg
;
1602 return (VALUE
)ruby_connect(arg
->fd
, arg
->sockaddr
, sizeof(*arg
->sockaddr
),
1607 init_unixsock(sock
, path
, server
)
1612 struct sockaddr_un sockaddr
;
1616 SafeStringValue(path
);
1617 fd
= ruby_socket(AF_UNIX
, SOCK_STREAM
, 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
));
1631 status
= bind(fd
, (struct sockaddr
*)&sockaddr
, sizeof(sockaddr
));
1635 struct unixsock_arg arg
;
1636 arg
.sockaddr
= &sockaddr
;
1638 status
= rb_protect(unixsock_connect_internal
, (VALUE
)&arg
, &prot
);
1647 rb_sys_fail(sockaddr
.sun_path
);
1650 if (server
) listen(fd
, 5);
1652 init_sock(sock
, fd
);
1653 GetOpenFile(sock
, fptr
);
1655 fptr
->path
= strdup(RSTRING(path
)->ptr
);
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
);
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
);
1693 ip_recvfrom(argc
, argv
, sock
)
1698 return s_recvfrom(sock
, argc
, argv
, RECV_IP
);
1702 ip_s_getaddress(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
);
1712 return make_ipaddr((struct sockaddr
*)&addr
);
1716 udp_init(argc
, argv
, sock
)
1722 int socktype
= AF_INET
;
1726 if (rb_scan_args(argc
, argv
, "01", &arg
) == 1) {
1727 socktype
= NUM2INT(arg
);
1729 fd
= ruby_socket(socktype
, SOCK_DGRAM
, 0);
1731 rb_sys_fail("socket(2) - udp");
1734 return init_sock(sock
, fd
);
1739 struct addrinfo
*res
;
1744 udp_connect_internal(arg
)
1745 struct udp_arg
*arg
;
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) {
1759 udp_connect(sock
, host
, port
)
1760 VALUE sock
, host
, port
;
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)");
1777 udp_bind(sock
, host
, port
)
1778 VALUE sock
, host
, port
;
1781 struct addrinfo
*res0
, *res
;
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) {
1794 rb_sys_fail("bind(2)");
1799 udp_send(argc
, argv
, sock
)
1804 VALUE mesg
, flags
, host
, port
;
1808 struct addrinfo
*res0
, *res
;
1810 if (argc
== 2 || argc
== 3) {
1811 return bsock_send(argc
, argv
, sock
);
1814 rb_scan_args(argc
, argv
, "4", &mesg
, &flags
, &host
, &port
);
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
) {
1822 n
= sendto(fileno(f
), RSTRING(mesg
)->ptr
, RSTRING(mesg
)->len
, NUM2INT(flags
),
1823 res
->ai_addr
, res
->ai_addrlen
);
1828 if (rb_io_wait_writable(fileno(f
))) {
1833 rb_sys_fail("sendto(2)");
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.
1853 * * +maxlen+ - the number of bytes to receive from the socket
1854 * * +flags+ - zero or more of the +MSG_+ options
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))
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.
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
1885 unix_init(sock
, path
)
1888 return init_unixsock(sock
, path
, 0);
1892 unixpath(struct sockaddr_un
*sockaddr
, socklen_t len
)
1894 if (sockaddr
->sun_path
< (char*)sockaddr
+ len
)
1895 return sockaddr
->sun_path
;
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)
1912 fptr
->path
= strdup(unixpath(&addr
, len
));
1914 return rb_str_new2(fptr
->path
);
1918 unix_svr_init(sock
, path
)
1921 return init_unixsock(sock
, path
, 1);
1925 unix_recvfrom(argc
, argv
, 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
1936 #define FD_PASSING_BY_MSG_CONTROL 0
1939 #if defined(HAVE_ST_MSG_ACCRIGHTS)
1940 #define FD_PASSING_BY_MSG_ACCRIGHTS 1
1942 #define FD_PASSING_BY_MSG_ACCRIGHTS 0
1946 unix_send_io(sock
, val
)
1949 #if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
1953 struct iovec vec
[1];
1956 #if FD_PASSING_BY_MSG_CONTROL
1963 if (rb_obj_is_kind_of(val
, rb_cIO
)) {
1965 GetOpenFile(val
, valfptr
);
1966 fd
= fileno(valfptr
->f
);
1968 else if (FIXNUM_P(val
)) {
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. */
1982 vec
[0].iov_base
= buf
;
1987 #if FD_PASSING_BY_MSG_CONTROL
1988 msg
.msg_control
= (caddr_t
)&cmsg
;
1989 msg
.msg_controllen
= CMSG_SPACE(sizeof(int));
1991 cmsg
.hdr
.cmsg_len
= CMSG_LEN(sizeof(int));
1992 cmsg
.hdr
.cmsg_level
= SOL_SOCKET
;
1993 cmsg
.hdr
.cmsg_type
= SCM_RIGHTS
;
1996 msg
.msg_accrights
= (caddr_t
)&fd
;
1997 msg
.msg_accrightslen
= sizeof(fd
);
2000 if (sendmsg(fileno(fptr
->f
), &msg
, 0) == -1)
2001 rb_sys_fail("sendmsg(2)");
2006 return Qnil
; /* not reached */
2010 #if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
2012 thread_read_select(fd
)
2019 rb_thread_select(fd
+1, &fds
, 0, 0, 0);
2024 unix_recv_io(argc
, argv
, sock
)
2029 #if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
2033 struct iovec vec
[2];
2037 #if FD_PASSING_BY_MSG_CONTROL
2044 rb_scan_args(argc
, argv
, "02", &klass
, &mode
);
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
);
2062 #if FD_PASSING_BY_MSG_CONTROL
2063 msg
.msg_control
= (caddr_t
)&cmsg
;
2064 msg
.msg_controllen
= CMSG_SPACE(sizeof(int));
2066 cmsg
.hdr
.cmsg_len
= CMSG_LEN(sizeof(int));
2067 cmsg
.hdr
.cmsg_level
= SOL_SOCKET
;
2068 cmsg
.hdr
.cmsg_type
= SCM_RIGHTS
;
2071 msg
.msg_accrights
= (caddr_t
)&fd
;
2072 msg
.msg_accrightslen
= sizeof(fd
);
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
);
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
));
2108 #if FD_PASSING_BY_MSG_CONTROL
2115 static ID for_fd
= 0;
2119 for_fd
= rb_intern("for_fd");
2120 ff_argc
= mode
== Qnil
? 1 : 2;
2121 ff_argv
[0] = INT2FIX(fd
);
2123 return rb_funcall2(klass
, for_fd
, ff_argc
, ff_argv
);
2127 return Qnil
; /* not reached */
2136 struct sockaddr_un from
;
2139 GetOpenFile(sock
, fptr
);
2140 fromlen
= sizeof(struct sockaddr_un
);
2141 return s_accept(rb_cUNIXSocket
, fileno(fptr
->f
),
2142 (struct sockaddr
*)&from
, &fromlen
);
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.
2155 * serv = UNIXServer.new("/tmp/sock")
2157 * sock = serv.accept_nonblock
2158 * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
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.
2171 * * UNIXServer#accept
2175 unix_accept_nonblock(sock
)
2179 struct sockaddr_un from
;
2182 GetOpenFile(sock
, fptr
);
2183 fromlen
= sizeof(from
);
2184 return s_accept_nonblock(rb_cUNIXSocket
, fptr
,
2185 (struct sockaddr
*)&from
, &fromlen
);
2189 unix_sysaccept(sock
)
2193 struct sockaddr_un from
;
2196 GetOpenFile(sock
, fptr
);
2197 fromlen
= sizeof(struct sockaddr_un
);
2198 return s_accept(0, fileno(fptr
->f
), (struct sockaddr
*)&from
, &fromlen
);
2202 unixaddr(sockaddr
, len
)
2203 struct sockaddr_un
*sockaddr
;
2206 return rb_assoc_new(rb_str_new2("AF_UNIX"),
2207 rb_str_new2(unixpath(sockaddr
, len
)));
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
);
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
);
2242 setup_domain_and_type(domain
, dv
, type
, tv
)
2249 tmp
= rb_check_string_type(domain
);
2252 rb_check_safe_obj(domain
);
2253 ptr
= RSTRING(domain
)->ptr
;
2254 if (strcmp(ptr
, "AF_INET") == 0)
2257 else if (strcmp(ptr
, "AF_UNIX") == 0)
2261 else if (strcmp(ptr
, "AF_ISO") == 0)
2265 else if (strcmp(ptr
, "AF_NS") == 0)
2269 else if (strcmp(ptr
, "AF_IMPLINK") == 0)
2273 else if (strcmp(ptr
, "PF_INET") == 0)
2277 else if (strcmp(ptr
, "PF_UNIX") == 0)
2281 else if (strcmp(ptr
, "PF_IMPLINK") == 0)
2283 else if (strcmp(ptr
, "AF_IMPLINK") == 0)
2287 else if (strcmp(ptr
, "PF_AX25") == 0)
2291 else if (strcmp(ptr
, "PF_IPX") == 0)
2295 rb_raise(rb_eSocket
, "unknown socket domain %s", ptr
);
2298 *dv
= NUM2INT(domain
);
2300 tmp
= rb_check_string_type(type
);
2303 rb_check_safe_obj(type
);
2304 ptr
= RSTRING(type
)->ptr
;
2305 if (strcmp(ptr
, "SOCK_STREAM") == 0)
2307 else if (strcmp(ptr
, "SOCK_DGRAM") == 0)
2310 else if (strcmp(ptr
, "SOCK_RAW") == 0)
2313 #ifdef SOCK_SEQPACKET
2314 else if (strcmp(ptr
, "SOCK_SEQPACKET") == 0)
2315 *tv
= SOCK_SEQPACKET
;
2318 else if (strcmp(ptr
, "SOCK_RDM") == 0)
2322 else if (strcmp(ptr
, "SOCK_PACKET") == 0)
2326 rb_raise(rb_eSocket
, "unknown socket type %s", ptr
);
2329 *tv
= NUM2INT(type
);
2334 sock_initialize(sock
, domain
, type
, protocol
)
2335 VALUE sock
, domain
, type
, protocol
;
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
);
2349 sock_s_socketpair(klass
, domain
, type
, protocol
)
2350 VALUE klass
, domain
, type
, protocol
;
2352 #if defined HAVE_SOCKETPAIR
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
)) {
2361 ret
= socketpair(d
, t
, p
, sp
);
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]));
2374 #ifdef HAVE_SYS_UN_H
2376 unix_s_socketpair(argc
, argv
, klass
)
2381 VALUE domain
, type
, protocol
;
2382 domain
= INT2FIX(PF_UNIX
);
2384 rb_scan_args(argc
, argv
, "02", &type
, &protocol
);
2386 type
= INT2FIX(SOCK_STREAM
);
2388 protocol
= INT2FIX(0);
2390 return sock_s_socketpair(klass
, domain
, type
, protocol
);
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.
2402 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
2405 * # Pull down Google's web page
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
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
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
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
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
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_
2459 * * Errno::EIO - an i/o error occured while reading from or writing to the
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
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
2502 * * connect manual pages on unix-based systems
2503 * * connect function in Microsoft's Winsock functions reference
2506 sock_connect(sock
, 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)");
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.
2532 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
2535 * # Pull down Google's web page
2537 * include Socket::Constants
2538 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
2539 * sockaddr = Socket.sockaddr_in(80, 'www.google.com')
2541 * socket.connect_nonblock(sockaddr)
2542 * rescue Errno::EINPROGRESS
2543 * IO.select(nil, [socket])
2545 * socket.connect_nonblock(sockaddr)
2546 * rescue Errno::EISCONN
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.
2562 sock_connect_nonblock(sock
, 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
);
2574 rb_sys_fail("connect(2)");
2582 * socket.bind(server_sockaddr) => 0
2584 * Binds to the given +struct+ sockaddr.
2587 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
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
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
2613 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
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_
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
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
2656 * * bind manual pages on unix-based systems
2657 * * bind function in Microsoft's Winsock functions reference
2660 sock_bind(sock
, 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)");
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
2682 * * +backlog+ - the maximum length of the queue for pending connections.
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):
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
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
2740 * * listen manual pages on unix-based systems
2741 * * listen function in Microsoft's Winsock functions reference
2744 sock_listen(sock
, log
)
2751 backlog
= NUM2INT(log
);
2752 GetOpenFile(sock
, fptr
);
2753 if (listen(fileno(fptr
->f
), backlog
) < 0)
2754 rb_sys_fail("listen(2)");
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
2770 * * +maxlen+ - the number of bytes to receive from the socket
2771 * * +flags+ - zero or more of the +MSG_+ options
2774 * # In one file, start this first
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}'"
2787 * # In another file, start this second
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!"
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
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
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
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
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
2865 sock_recvfrom(argc
, argv
, sock
)
2870 return s_recvfrom(sock
, argc
, argv
, RECV_SOCKET
);
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
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.
2890 * * +maxlen+ - the number of bytes to receive from the socket
2891 * * +flags+ - zero or more of the +MSG_+ options
2894 * # In one file, start this first
2896 * include Socket::Constants
2897 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
2898 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
2899 * socket.bind(sockaddr)
2901 * client, client_sockaddr = socket.accept
2903 * pair = client.recvfrom_nonblock(20)
2904 * rescue Errno::EAGAIN
2905 * IO.select([client])
2908 * data = pair[0].chomp
2909 * puts "I only received 20 bytes '#{data}'"
2913 * # In another file, start this second
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!"
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.
2932 sock_recvfrom_nonblock(int argc
, VALUE
*argv
, VALUE sock
)
2934 return s_recvfrom_nonblock(sock
, argc
, argv
, RECV_SOCKET
);
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
2946 * # In one script, start this first
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!"
2958 * # In another script, start this second
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}'"
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
2983 * * Errno::ENOBUFS - no buffer space is available
2984 * * Errno::ENOMEM - there was insufficient memory available to complete the
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
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
3012 * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and no connections are
3013 * present to be accepted
3016 * * accept manual pages on unix-based systems
3017 * * accept function in Microsoft's Winsock functions reference
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
));
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_.
3046 * # In one script, start this first
3048 * include Socket::Constants
3049 * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
3050 * sockaddr = Socket.sockaddr_in(2200, 'localhost')
3051 * socket.bind(sockaddr)
3054 * client_socket, client_sockaddr = socket.accept_nonblock
3055 * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
3056 * IO.select([socket])
3059 * puts "The client said, '#{client_socket.readline.chomp}'"
3060 * client_socket.puts "Hello from script one!"
3063 * # In another script, start this second
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}'"
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.
3083 sock_accept_nonblock(sock
)
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
));
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_.
3106 * # In one script, start this first
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!"
3119 * # In another script, start this second
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}'"
3129 * Refer to Socket#accept for the exceptions that may be thrown if the call
3130 * to _sysaccept_ fails.
3136 sock_sysaccept(sock
)
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
3152 sock_gethostname(obj
)
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
);
3167 #include <sys/utsname.h>
3170 sock_gethostname(obj
)
3177 return rb_str_new2(un
.nodename
);
3181 sock_gethostname(obj
)
3191 struct addrinfo
*res0
;
3194 struct addrinfo
*res
;
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
);
3210 /* Returns a String containing the binary value of a struct sockaddr. */
3212 sock_sockaddr(addr
, len
)
3213 struct sockaddr
*addr
;
3218 switch (addr
->sa_family
) {
3220 ptr
= (char*)&((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
;
3221 len
= sizeof(((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
);
3225 ptr
= (char*)&((struct sockaddr_in6
*)addr
)->sin6_addr
.s6_addr
;
3226 len
= sizeof(((struct sockaddr_in6
*)addr
)->sin6_addr
.s6_addr
);
3230 rb_raise(rb_eSocket
, "unknown socket family:%d", addr
->sa_family
);
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
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
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"]
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)
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"]
3330 * See: Socket.getaddrinfo
3333 sock_s_gethostbyname(obj
, host
)
3337 return make_hostent(host
, sock_addrinfo(host
, Qnil
, SOCK_STREAM
, AI_CANONNAME
), sock_sockaddr
);
3341 sock_s_gethostbyaddr(argc
, argv
)
3347 struct sockaddr
*sa
;
3352 rb_scan_args(argc
, argv
, "11", &addr
, &type
);
3353 sa
= (struct sockaddr
*)StringValuePtr(addr
);
3358 else if (RSTRING(addr
)->len
== 16) {
3362 h
= gethostbyaddr(RSTRING(addr
)->ptr
, RSTRING(addr
)->len
, t
);
3364 #ifdef HAVE_HSTRERROR
3366 rb_raise(rb_eSocket
, "%s", (char*)hstrerror(h_errno
));
3368 rb_raise(rb_eSocket
, "host not found");
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
));
3382 for (pch
= h
->h_addr_list
; *pch
; pch
++) {
3383 rb_ary_push(ary
, rb_str_new(*pch
, h
->h_length
));
3386 rb_ary_push(ary
, rb_str_new(h
->h_addr
, h
->h_length
));
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
3401 * Note that unlike Socket.getaddrinfo, +proto+ may not be specified using the
3402 * Socket::SOCK_* constants, a string must must be used.
3405 sock_s_getservbyaname(argc
, argv
)
3409 VALUE service
, proto
;
3413 rb_scan_args(argc
, argv
, "11", &service
, &proto
);
3414 if (NIL_P(proto
)) proto
= rb_str_new2("tcp");
3415 StringValue(service
);
3418 sp
= getservbyname(StringValueCStr(service
), StringValueCStr(proto
));
3420 port
= ntohs(sp
->s_port
);
3423 char *s
= RSTRING(service
)->ptr
;
3426 port
= strtoul(s
, &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]]
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.
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'
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.
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|
3528 * sock = TCPSocket.new(addr, port)
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 )
3549 sock_s_getaddrinfo(argc
, 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
;
3559 host
= port
= family
= socktype
= protocol
= flags
= Qnil
;
3560 rb_scan_args(argc
, argv
, "24", &host
, &port
, &family
, &socktype
, &protocol
, &flags
);
3565 strncpy(hbuf
, StringValuePtr(host
), sizeof(hbuf
));
3566 hbuf
[sizeof(hbuf
) - 1] = '\0';
3572 else if (FIXNUM_P(port
)) {
3573 snprintf(pbuf
, sizeof(pbuf
), "%ld", FIX2LONG(port
));
3577 strncpy(pbuf
, StringValuePtr(port
), sizeof(pbuf
));
3578 pbuf
[sizeof(pbuf
) - 1] = '\0';
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
;
3594 else if (strcmp(ap
, "AF_INET6") == 0) {
3595 hints
.ai_family
= PF_INET6
;
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
);
3611 rb_raise(rb_eSocket
, "getaddrinfo: %s", gai_strerror(error
));
3614 ret
= make_addrinfo(res
);
3620 sock_s_getnameinfo(argc
, argv
)
3624 VALUE sa
, af
= Qnil
, host
= Qnil
, port
= Qnil
, flags
, tmp
;
3626 char hbuf
[1024], pbuf
[1024];
3628 struct addrinfo hints
, *res
= NULL
, *r
;
3630 struct sockaddr_storage ss
;
3631 struct sockaddr
*sap
;
3635 rb_scan_args(argc
, argv
, "11", &sa
, &flags
);
3638 if (!NIL_P(flags
)) {
3639 fl
= NUM2INT(flags
);
3641 tmp
= rb_check_string_type(sa
);
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
;
3654 tmp
= rb_check_array_type(sa
);
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];
3668 host
= RARRAY(sa
)->ptr
[2];
3672 * 4th element holds numeric form, don't resolve.
3675 #ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
3676 hints
.ai_flags
|= AI_NUMERICHOST
;
3681 rb_raise(rb_eArgError
, "array size should be 3 or 4, %ld given",
3689 strncpy(hbuf
, StringValuePtr(host
), sizeof(hbuf
));
3690 hbuf
[sizeof(hbuf
) - 1] = '\0';
3698 else if (FIXNUM_P(port
)) {
3699 snprintf(pbuf
, sizeof(pbuf
), "%ld", NUM2LONG(port
));
3703 strncpy(pbuf
, StringValuePtr(port
), sizeof(pbuf
));
3704 pbuf
[sizeof(pbuf
) - 1] = '\0';
3707 hints
.ai_socktype
= (fl
& NI_DGRAM
) ? SOCK_DGRAM
: SOCK_STREAM
;
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
;
3720 else if (strcmp(ap
, "AF_INET6") == 0) {
3721 hints
.ai_family
= PF_INET6
;
3725 error
= getaddrinfo(hptr
, pptr
, &hints
, &res
);
3726 if (error
) goto error_exit_addr
;
3730 rb_raise(rb_eTypeError
, "expecting String or Array");
3734 error
= getnameinfo(sap
, SA_LEN(sap
), hbuf
, sizeof(hbuf
),
3735 pbuf
, sizeof(pbuf
), fl
);
3736 if (error
) goto error_exit_name
;
3738 for (r
= res
->ai_next
; r
; r
= r
->ai_next
) {
3739 char hbuf2
[1024], pbuf2
[1024];
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) {
3747 rb_raise(rb_eSocket
, "sockaddr resolved to multiple nodename");
3752 return rb_assoc_new(rb_str_new2(hbuf
), rb_str_new2(pbuf
));
3755 if (res
) freeaddrinfo(res
);
3756 rb_raise(rb_eSocket
, "getaddrinfo: %s", gai_strerror(error
));
3759 if (res
) freeaddrinfo(res
);
3760 rb_raise(rb_eSocket
, "getnameinfo: %s", gai_strerror(error
));
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
);
3771 OBJ_INFECT(addr
, port
);
3772 OBJ_INFECT(addr
, host
);
3778 sock_s_unpack_sockaddr_in(self
, addr
)
3781 struct sockaddr_in
* sockaddr
;
3784 sockaddr
= (struct sockaddr_in
*)StringValuePtr(addr
);
3785 if (((struct sockaddr
*)sockaddr
)->sa_family
!= AF_INET
3787 && ((struct sockaddr
*)sockaddr
)->sa_family
!= AF_INET6
3791 rb_raise(rb_eArgError
, "not an AF_INET/AF_INET6 sockaddr");
3793 rb_raise(rb_eArgError
, "not an AF_INET sockaddr");
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
3803 sock_s_pack_sockaddr_un(self
, path
)
3806 struct sockaddr_un sockaddr
;
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
);
3825 sock_s_unpack_sockaddr_un(self
, addr
)
3828 struct sockaddr_un
* sockaddr
;
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
);
3852 static VALUE mConst
;
3855 sock_define_const(name
, 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
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.
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);
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);
3930 rb_define_method(rb_cSOCKSSocket
, "close", socks_s_close
, 0);
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);
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);
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
);
4008 sock_define_const("SOCK_RAW", SOCK_RAW
);
4011 sock_define_const("SOCK_RDM", SOCK_RDM
);
4013 #ifdef SOCK_SEQPACKET
4014 sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET
);
4017 sock_define_const("SOCK_PACKET", SOCK_PACKET
);
4020 sock_define_const("AF_INET", AF_INET
);
4022 sock_define_const("PF_INET", PF_INET
);
4025 sock_define_const("AF_UNIX", AF_UNIX
);
4026 sock_define_const("PF_UNIX", PF_UNIX
);
4029 sock_define_const("AF_AX25", AF_AX25
);
4030 sock_define_const("PF_AX25", PF_AX25
);
4033 sock_define_const("AF_IPX", AF_IPX
);
4034 sock_define_const("PF_IPX", PF_IPX
);
4037 sock_define_const("AF_APPLETALK", AF_APPLETALK
);
4038 sock_define_const("PF_APPLETALK", PF_APPLETALK
);
4041 sock_define_const("AF_UNSPEC", AF_UNSPEC
);
4042 sock_define_const("PF_UNSPEC", PF_UNSPEC
);
4045 sock_define_const("AF_INET6", AF_INET6
);
4048 sock_define_const("PF_INET6", PF_INET6
);
4051 sock_define_const("AF_LOCAL", AF_LOCAL
);
4054 sock_define_const("PF_LOCAL", PF_LOCAL
);
4057 sock_define_const("AF_IMPLINK", AF_IMPLINK
);
4060 sock_define_const("PF_IMPLINK", PF_IMPLINK
);
4063 sock_define_const("AF_PUP", AF_PUP
);
4066 sock_define_const("PF_PUP", PF_PUP
);
4069 sock_define_const("AF_CHAOS", AF_CHAOS
);
4072 sock_define_const("PF_CHAOS", PF_CHAOS
);
4075 sock_define_const("AF_NS", AF_NS
);
4078 sock_define_const("PF_NS", PF_NS
);
4081 sock_define_const("AF_ISO", AF_ISO
);
4084 sock_define_const("PF_ISO", PF_ISO
);
4087 sock_define_const("AF_OSI", AF_OSI
);
4090 sock_define_const("PF_OSI", PF_OSI
);
4093 sock_define_const("AF_ECMA", AF_ECMA
);
4096 sock_define_const("PF_ECMA", PF_ECMA
);
4099 sock_define_const("AF_DATAKIT", AF_DATAKIT
);
4102 sock_define_const("PF_DATAKIT", PF_DATAKIT
);
4105 sock_define_const("AF_CCITT", AF_CCITT
);
4108 sock_define_const("PF_CCITT", PF_CCITT
);
4111 sock_define_const("AF_SNA", AF_SNA
);
4114 sock_define_const("PF_SNA", PF_SNA
);
4117 sock_define_const("AF_DEC", AF_DEC
);
4120 sock_define_const("PF_DEC", PF_DEC
);
4123 sock_define_const("AF_DLI", AF_DLI
);
4126 sock_define_const("PF_DLI", PF_DLI
);
4129 sock_define_const("AF_LAT", AF_LAT
);
4132 sock_define_const("PF_LAT", PF_LAT
);
4135 sock_define_const("AF_HYLINK", AF_HYLINK
);
4138 sock_define_const("PF_HYLINK", PF_HYLINK
);
4141 sock_define_const("AF_ROUTE", AF_ROUTE
);
4144 sock_define_const("PF_ROUTE", PF_ROUTE
);
4147 sock_define_const("AF_LINK", AF_LINK
);
4150 sock_define_const("PF_LINK", PF_LINK
);
4153 sock_define_const("AF_COIP", AF_COIP
);
4156 sock_define_const("PF_COIP", PF_COIP
);
4159 sock_define_const("AF_CNT", AF_CNT
);
4162 sock_define_const("PF_CNT", PF_CNT
);
4165 sock_define_const("AF_SIP", AF_SIP
);
4168 sock_define_const("PF_SIP", PF_SIP
);
4171 sock_define_const("AF_NDRV", AF_NDRV
);
4174 sock_define_const("PF_NDRV", PF_NDRV
);
4177 sock_define_const("AF_ISDN", AF_ISDN
);
4180 sock_define_const("PF_ISDN", PF_ISDN
);
4183 sock_define_const("AF_NATM", AF_NATM
);
4186 sock_define_const("PF_NATM", PF_NATM
);
4189 sock_define_const("AF_SYSTEM", AF_SYSTEM
);
4192 sock_define_const("PF_SYSTEM", PF_SYSTEM
);
4195 sock_define_const("AF_NETBIOS", AF_NETBIOS
);
4198 sock_define_const("PF_NETBIOS", PF_NETBIOS
);
4201 sock_define_const("AF_PPP", AF_PPP
);
4204 sock_define_const("PF_PPP", PF_PPP
);
4207 sock_define_const("AF_ATM", AF_ATM
);
4210 sock_define_const("PF_ATM", PF_ATM
);
4213 sock_define_const("AF_NETGRAPH", AF_NETGRAPH
);
4216 sock_define_const("PF_NETGRAPH", PF_NETGRAPH
);
4219 sock_define_const("AF_MAX", AF_MAX
);
4222 sock_define_const("PF_MAX", PF_MAX
);
4225 sock_define_const("AF_E164", AF_E164
);
4228 sock_define_const("PF_XTP", PF_XTP
);
4231 sock_define_const("PF_RTIP", PF_RTIP
);
4234 sock_define_const("PF_PIP", PF_PIP
);
4237 sock_define_const("PF_KEY", PF_KEY
);
4240 sock_define_const("MSG_OOB", MSG_OOB
);
4242 sock_define_const("MSG_PEEK", MSG_PEEK
);
4244 #ifdef MSG_DONTROUTE
4245 sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE
);
4248 sock_define_const("MSG_EOR", MSG_EOR
);
4251 sock_define_const("MSG_TRUNC", MSG_TRUNC
);
4254 sock_define_const("MSG_CTRUNC", MSG_CTRUNC
);
4257 sock_define_const("MSG_WAITALL", MSG_WAITALL
);
4260 sock_define_const("MSG_DONTWAIT", MSG_DONTWAIT
);
4263 sock_define_const("MSG_EOF", MSG_EOF
);
4266 sock_define_const("MSG_FLUSH", MSG_FLUSH
);
4269 sock_define_const("MSG_HOLD", MSG_HOLD
);
4272 sock_define_const("MSG_SEND", MSG_SEND
);
4275 sock_define_const("MSG_HAVEMORE", MSG_HAVEMORE
);
4278 sock_define_const("MSG_RCVMORE", MSG_RCVMORE
);
4281 sock_define_const("MSG_COMPAT", MSG_COMPAT
);
4284 sock_define_const("SOL_SOCKET", SOL_SOCKET
);
4286 sock_define_const("SOL_IP", SOL_IP
);
4289 sock_define_const("SOL_IPX", SOL_IPX
);
4292 sock_define_const("SOL_AX25", SOL_AX25
);
4295 sock_define_const("SOL_ATALK", SOL_ATALK
);
4298 sock_define_const("SOL_TCP", SOL_TCP
);
4301 sock_define_const("SOL_UDP", SOL_UDP
);
4305 sock_define_const("IPPROTO_IP", IPPROTO_IP
);
4307 sock_define_const("IPPROTO_IP", 0);
4310 sock_define_const("IPPROTO_ICMP", IPPROTO_ICMP
);
4312 sock_define_const("IPPROTO_ICMP", 1);
4315 sock_define_const("IPPROTO_IGMP", IPPROTO_IGMP
);
4318 sock_define_const("IPPROTO_GGP", IPPROTO_GGP
);
4321 sock_define_const("IPPROTO_TCP", IPPROTO_TCP
);
4323 sock_define_const("IPPROTO_TCP", 6);
4326 sock_define_const("IPPROTO_EGP", IPPROTO_EGP
);
4329 sock_define_const("IPPROTO_PUP", IPPROTO_PUP
);
4332 sock_define_const("IPPROTO_UDP", IPPROTO_UDP
);
4334 sock_define_const("IPPROTO_UDP", 17);
4337 sock_define_const("IPPROTO_IDP", IPPROTO_IDP
);
4339 #ifdef IPPROTO_HELLO
4340 sock_define_const("IPPROTO_HELLO", IPPROTO_HELLO
);
4343 sock_define_const("IPPROTO_ND", IPPROTO_ND
);
4346 sock_define_const("IPPROTO_TP", IPPROTO_TP
);
4349 sock_define_const("IPPROTO_XTP", IPPROTO_XTP
);
4352 sock_define_const("IPPROTO_EON", IPPROTO_EON
);
4355 sock_define_const("IPPROTO_BIP", IPPROTO_BIP
);
4359 sock_define_const("IPPROTO_RAW", IPPROTO_RAW
);
4361 sock_define_const("IPPROTO_RAW", 255);
4364 sock_define_const("IPPROTO_MAX", IPPROTO_MAX
);
4367 /* Some port configuration */
4368 #ifdef IPPORT_RESERVED
4369 sock_define_const("IPPORT_RESERVED", IPPORT_RESERVED
);
4371 sock_define_const("IPPORT_RESERVED", 1024);
4373 #ifdef IPPORT_USERRESERVED
4374 sock_define_const("IPPORT_USERRESERVED", IPPORT_USERRESERVED
);
4376 sock_define_const("IPPORT_USERRESERVED", 5000);
4378 /* Some reserved IP v.4 addresses */
4380 sock_define_const("INADDR_ANY", INADDR_ANY
);
4382 sock_define_const("INADDR_ANY", 0x00000000);
4384 #ifdef INADDR_BROADCAST
4385 sock_define_const("INADDR_BROADCAST", INADDR_BROADCAST
);
4387 sock_define_const("INADDR_BROADCAST", 0xffffffff);
4389 #ifdef INADDR_LOOPBACK
4390 sock_define_const("INADDR_LOOPBACK", INADDR_LOOPBACK
);
4392 sock_define_const("INADDR_LOOPBACK", 0x7F000001);
4394 #ifdef INADDR_UNSPEC_GROUP
4395 sock_define_const("INADDR_UNSPEC_GROUP", INADDR_UNSPEC_GROUP
);
4397 sock_define_const("INADDR_UNSPEC_GROUP", 0xe0000000);
4399 #ifdef INADDR_ALLHOSTS_GROUP
4400 sock_define_const("INADDR_ALLHOSTS_GROUP", INADDR_ALLHOSTS_GROUP
);
4402 sock_define_const("INADDR_ALLHOSTS_GROUP", 0xe0000001);
4404 #ifdef INADDR_MAX_LOCAL_GROUP
4405 sock_define_const("INADDR_MAX_LOCAL_GROUP", INADDR_MAX_LOCAL_GROUP
);
4407 sock_define_const("INADDR_MAX_LOCAL_GROUP", 0xe00000ff);
4410 sock_define_const("INADDR_NONE", INADDR_NONE
);
4412 sock_define_const("INADDR_NONE", 0xffffffff);
4414 /* IP [gs]etsockopt options */
4416 sock_define_const("IP_OPTIONS", IP_OPTIONS
);
4419 sock_define_const("IP_HDRINCL", IP_HDRINCL
);
4422 sock_define_const("IP_TOS", IP_TOS
);
4425 sock_define_const("IP_TTL", IP_TTL
);
4428 sock_define_const("IP_RECVOPTS", IP_RECVOPTS
);
4430 #ifdef IP_RECVRETOPTS
4431 sock_define_const("IP_RECVRETOPTS", IP_RECVRETOPTS
);
4433 #ifdef IP_RECVDSTADDR
4434 sock_define_const("IP_RECVDSTADDR", IP_RECVDSTADDR
);
4437 sock_define_const("IP_RETOPTS", IP_RETOPTS
);
4439 #ifdef IP_MULTICAST_IF
4440 sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF
);
4442 #ifdef IP_MULTICAST_TTL
4443 sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL
);
4445 #ifdef IP_MULTICAST_LOOP
4446 sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP
);
4448 #ifdef IP_ADD_MEMBERSHIP
4449 sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP
);
4451 #ifdef IP_DROP_MEMBERSHIP
4452 sock_define_const("IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP
);
4454 #ifdef IP_DEFAULT_MULTICAST_TTL
4455 sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL
);
4457 #ifdef IP_DEFAULT_MULTICAST_LOOP
4458 sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP
);
4460 #ifdef IP_MAX_MEMBERSHIPS
4461 sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS
);
4464 sock_define_const("SO_DEBUG", SO_DEBUG
);
4466 sock_define_const("SO_REUSEADDR", SO_REUSEADDR
);
4468 sock_define_const("SO_REUSEPORT", SO_REUSEPORT
);
4471 sock_define_const("SO_TYPE", SO_TYPE
);
4474 sock_define_const("SO_ERROR", SO_ERROR
);
4477 sock_define_const("SO_DONTROUTE", SO_DONTROUTE
);
4480 sock_define_const("SO_BROADCAST", SO_BROADCAST
);
4483 sock_define_const("SO_SNDBUF", SO_SNDBUF
);
4486 sock_define_const("SO_RCVBUF", SO_RCVBUF
);
4489 sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE
);
4492 sock_define_const("SO_OOBINLINE", SO_OOBINLINE
);
4495 sock_define_const("SO_NO_CHECK", SO_NO_CHECK
);
4498 sock_define_const("SO_PRIORITY", SO_PRIORITY
);
4501 sock_define_const("SO_LINGER", SO_LINGER
);
4504 sock_define_const("SO_PASSCRED", SO_PASSCRED
);
4507 sock_define_const("SO_PEERCRED", SO_PEERCRED
);
4510 sock_define_const("SO_RCVLOWAT", SO_RCVLOWAT
);
4513 sock_define_const("SO_SNDLOWAT", SO_SNDLOWAT
);
4516 sock_define_const("SO_RCVTIMEO", SO_RCVTIMEO
);
4519 sock_define_const("SO_SNDTIMEO", SO_SNDTIMEO
);
4521 #ifdef SO_ACCEPTCONN
4522 sock_define_const("SO_ACCEPTCONN", SO_ACCEPTCONN
);
4524 #ifdef SO_USELOOPBACK
4525 sock_define_const("SO_USELOOPBACK", SO_USELOOPBACK
);
4527 #ifdef SO_ACCEPTFILTER
4528 sock_define_const("SO_ACCEPTFILTER", SO_ACCEPTFILTER
);
4531 sock_define_const("SO_DONTTRUNC", SO_DONTTRUNC
);
4534 sock_define_const("SO_WANTMORE", SO_WANTMORE
);
4536 #ifdef SO_WANTOOBFLAG
4537 sock_define_const("SO_WANTOOBFLAG", SO_WANTOOBFLAG
);
4540 sock_define_const("SO_NREAD", SO_NREAD
);
4543 sock_define_const("SO_NKE", SO_NKE
);
4546 sock_define_const("SO_NOSIGPIPE", SO_NOSIGPIPE
);
4549 #ifdef SO_SECURITY_AUTHENTICATION
4550 sock_define_const("SO_SECURITY_AUTHENTICATION", SO_SECURITY_AUTHENTICATION
);
4552 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
4553 sock_define_const("SO_SECURITY_ENCRYPTION_TRANSPORT", SO_SECURITY_ENCRYPTION_TRANSPORT
);
4555 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
4556 sock_define_const("SO_SECURITY_ENCRYPTION_NETWORK", SO_SECURITY_ENCRYPTION_NETWORK
);
4559 #ifdef SO_BINDTODEVICE
4560 sock_define_const("SO_BINDTODEVICE", SO_BINDTODEVICE
);
4562 #ifdef SO_ATTACH_FILTER
4563 sock_define_const("SO_ATTACH_FILTER", SO_ATTACH_FILTER
);
4565 #ifdef SO_DETACH_FILTER
4566 sock_define_const("SO_DETACH_FILTER", SO_DETACH_FILTER
);
4569 sock_define_const("SO_PEERNAME", SO_PEERNAME
);
4572 sock_define_const("SO_TIMESTAMP", SO_TIMESTAMP
);
4575 #ifdef SOPRI_INTERACTIVE
4576 sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE
);
4579 sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL
);
4581 #ifdef SOPRI_BACKGROUND
4582 sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND
);
4586 sock_define_const("IPX_TYPE", IPX_TYPE
);
4590 sock_define_const("TCP_NODELAY", TCP_NODELAY
);
4593 sock_define_const("TCP_MAXSEG", TCP_MAXSEG
);
4596 #ifdef EAI_ADDRFAMILY
4597 sock_define_const("EAI_ADDRFAMILY", EAI_ADDRFAMILY
);
4600 sock_define_const("EAI_AGAIN", EAI_AGAIN
);
4603 sock_define_const("EAI_BADFLAGS", EAI_BADFLAGS
);
4606 sock_define_const("EAI_FAIL", EAI_FAIL
);
4609 sock_define_const("EAI_FAMILY", EAI_FAMILY
);
4612 sock_define_const("EAI_MEMORY", EAI_MEMORY
);
4615 sock_define_const("EAI_NODATA", EAI_NODATA
);
4618 sock_define_const("EAI_NONAME", EAI_NONAME
);
4621 sock_define_const("EAI_SERVICE", EAI_SERVICE
);
4624 sock_define_const("EAI_SOCKTYPE", EAI_SOCKTYPE
);
4627 sock_define_const("EAI_SYSTEM", EAI_SYSTEM
);
4630 sock_define_const("EAI_BADHINTS", EAI_BADHINTS
);
4633 sock_define_const("EAI_PROTOCOL", EAI_PROTOCOL
);
4636 sock_define_const("EAI_MAX", EAI_MAX
);
4639 sock_define_const("AI_PASSIVE", AI_PASSIVE
);
4642 sock_define_const("AI_CANONNAME", AI_CANONNAME
);
4644 #ifdef AI_NUMERICHOST
4645 sock_define_const("AI_NUMERICHOST", AI_NUMERICHOST
);
4648 sock_define_const("AI_MASK", AI_MASK
);
4651 sock_define_const("AI_ALL", AI_ALL
);
4653 #ifdef AI_V4MAPPED_CFG
4654 sock_define_const("AI_V4MAPPED_CFG", AI_V4MAPPED_CFG
);
4656 #ifdef AI_ADDRCONFIG
4657 sock_define_const("AI_ADDRCONFIG", AI_ADDRCONFIG
);
4660 sock_define_const("AI_V4MAPPED", AI_V4MAPPED
);
4663 sock_define_const("AI_DEFAULT", AI_DEFAULT
);
4666 sock_define_const("NI_MAXHOST", NI_MAXHOST
);
4669 sock_define_const("NI_MAXSERV", NI_MAXSERV
);
4672 sock_define_const("NI_NOFQDN", NI_NOFQDN
);
4674 #ifdef NI_NUMERICHOST
4675 sock_define_const("NI_NUMERICHOST", NI_NUMERICHOST
);
4678 sock_define_const("NI_NAMEREQD", NI_NAMEREQD
);
4680 #ifdef NI_NUMERICSERV
4681 sock_define_const("NI_NUMERICSERV", NI_NUMERICSERV
);
4684 sock_define_const("NI_DGRAM", NI_DGRAM
);
4687 sock_define_const("SHUT_RD", SHUT_RD
);
4689 sock_define_const("SHUT_RD", 0);
4692 sock_define_const("SHUT_WR", SHUT_WR
);
4694 sock_define_const("SHUT_WR", 1);
4697 sock_define_const("SHUT_RDWR", SHUT_RDWR
);
4699 sock_define_const("SHUT_RDWR", 2);