1
/************************************************
5
created at: Thu Mar 31 12:21:29 JST 1994
7
Copyright (C) 1993-2007 Yukihiro Matsumoto
9
************************************************/
11
#include "rubysocket.h"
15
* BasicSocket.for_fd(fd) => basicsocket
17
* Returns a socket object which contains the file descriptor, _fd_.
19
* # If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
20
* STDIN_SOCK = Socket.for_fd(STDIN.fileno)
21
* p STDIN_SOCK.remote_address
25
bsock_s_for_fd(VALUE klass, VALUE fd)
28
VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd));
30
GetOpenFile(sock, fptr);
37
* basicsocket.shutdown([how]) => 0
39
* Calls shutdown(2) system call.
41
* s.shutdown(Socket::SHUT_RD) disallows further read.
43
* s.shutdown(Socket::SHUT_WR) disallows further write.
45
* s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
47
* _how_ can be symbol or string:
48
* - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD.
49
* - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR.
50
* - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR.
52
* UNIXSocket.pair {|s1, s2|
55
* p s2.read #=> "ping\n"
58
* p s1.read #=> "pong\n"
63
bsock_shutdown(int argc, VALUE *argv, VALUE sock)
69
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
70
rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
72
rb_scan_args(argc, argv, "01", &howto);
76
how = rsock_shutdown_how_arg(howto);
77
if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
78
rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
81
GetOpenFile(sock, fptr);
82
if (shutdown(fptr->fd, how) == -1)
90
* basicsocket.close_read => nil
92
* Disallows further read using shutdown system call.
94
* s1, s2 = UNIXSocket.pair
96
* s2.puts #=> Broken pipe (Errno::EPIPE)
99
bsock_close_read(VALUE sock)
103
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
104
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
106
GetOpenFile(sock, fptr);
107
shutdown(fptr->fd, 0);
108
if (!(fptr->mode & FMODE_WRITABLE)) {
109
return rb_io_close(sock);
111
fptr->mode &= ~FMODE_READABLE;
118
* basicsocket.close_write => nil
120
* Disallows further write using shutdown system call.
122
* UNIXSocket.pair {|s1, s2|
125
* p s2.read #=> "ping"
128
* p s1.read #=> "pong"
132
bsock_close_write(VALUE sock)
136
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
137
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
139
GetOpenFile(sock, fptr);
140
if (!(fptr->mode & FMODE_READABLE)) {
141
return rb_io_close(sock);
143
shutdown(fptr->fd, 1);
144
fptr->mode &= ~FMODE_WRITABLE;
150
* Document-method: setsockopt
152
* setsockopt(level, optname, optval)
153
* setsockopt(socketoption)
155
* Sets a socket option. These are protocol and system specific, see your
156
* local system documentation for details.
159
* * +level+ is an integer, usually one of the SOL_ constants such as
160
* Socket::SOL_SOCKET, or a protocol level.
161
* A string or symbol of the name, possibly without prefix, is also
163
* * +optname+ is an integer, usually one of the SO_ constants, such
164
* as Socket::SO_REUSEADDR.
165
* A string or symbol of the name, possibly without prefix, is also
167
* * +optval+ is the value of the option, it is passed to the underlying
168
* setsockopt() as a pointer to a certain number of bytes. How this is
169
* done depends on the type:
170
* - Fixnum: value is assigned to an int, and a pointer to the int is
171
* passed, with length of sizeof(int).
172
* - true or false: 1 or 0 (respectively) is assigned to an int, and the
173
* int is passed as for a Fixnum. Note that +false+ must be passed,
175
* - String: the string's data and length is passed to the socket.
176
* * +socketoption+ is an instance of Socket::Option
180
* Some socket options are integers with boolean values, in this case
181
* #setsockopt could be called like this:
182
* sock.setsockopt(:SOCKET, :REUSEADDR, true)
183
* sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
184
* sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
186
* Some socket options are integers with numeric values, in this case
187
* #setsockopt could be called like this:
188
* sock.setsockopt(:IP, :TTL, 255)
189
* sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
190
* sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
192
* Option values may be structs. Passing them can be complex as it involves
193
* examining your system headers to determine the correct definition. An
194
* example is an +ip_mreq+, which may be defined in your system headers as:
196
* struct in_addr imr_multiaddr;
197
* struct in_addr imr_interface;
200
* In this case #setsockopt could be called like this:
201
* optval = IPAddr.new("224.0.0.251").hton +
202
* IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton
203
* sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
207
bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
209
VALUE lev, optname, val;
210
int family, level, option;
217
lev = rb_funcall(argv[0], rb_intern("level"), 0);
218
optname = rb_funcall(argv[0], rb_intern("optname"), 0);
219
val = rb_funcall(argv[0], rb_intern("data"), 0);
222
rb_scan_args(argc, argv, "30", &lev, &optname, &val);
226
GetOpenFile(sock, fptr);
227
family = rsock_getfamily(fptr->fd);
228
level = rsock_level_arg(family, lev);
229
option = rsock_optname_arg(family, level, optname);
241
v = (char*)&i; vlen = (int)sizeof(i);
245
v = RSTRING_PTR(val);
246
vlen = RSTRING_LENINT(val);
250
#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
252
rb_io_check_closed(fptr);
253
if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
254
rb_sys_fail_path(fptr->pathv);
259
#if !defined(__BEOS__)
261
* Document-method: getsockopt
263
* getsockopt(level, optname) => socketoption
265
* Gets a socket option. These are protocol and system specific, see your
266
* local system documentation for details. The option is returned as
267
* a Socket::Option object.
270
* * +level+ is an integer, usually one of the SOL_ constants such as
271
* Socket::SOL_SOCKET, or a protocol level.
272
* A string or symbol of the name, possibly without prefix, is also
274
* * +optname+ is an integer, usually one of the SO_ constants, such
275
* as Socket::SO_REUSEADDR.
276
* A string or symbol of the name, possibly without prefix, is also
281
* Some socket options are integers with boolean values, in this case
282
* #getsockopt could be called like this:
284
* reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool
286
* optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
287
* optval = optval.unpack "i"
288
* reuseaddr = optval[0] == 0 ? false : true
290
* Some socket options are integers with numeric values, in this case
291
* #getsockopt could be called like this:
293
* ipttl = sock.getsockopt(:IP, :TTL).int
295
* optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
296
* ipttl = optval.unpack("i")[0]
298
* Option values may be structs. Decoding them can be complex as it involves
299
* examining your system headers to determine the correct definition. An
300
* example is a +struct linger+, which may be defined in your system headers
307
* In this case #getsockopt could be called like this:
309
* # Socket::Option knows linger structure.
310
* onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger
312
* optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
313
* onoff, linger = optval.unpack "ii"
314
* onoff = onoff == 0 ? false : true
317
bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
325
GetOpenFile(sock, fptr);
326
family = rsock_getfamily(fptr->fd);
327
level = rsock_level_arg(family, lev);
328
option = rsock_optname_arg(family, level, optname);
330
buf = ALLOCA_N(char,len);
332
rb_io_check_closed(fptr);
334
if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
335
rb_sys_fail_path(fptr->pathv);
337
return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
340
#define bsock_getsockopt rb_f_notimplement
345
* basicsocket.getsockname => sockaddr
347
* Returns the local address of the socket as a sockaddr string.
349
* TCPServer.open("127.0.0.1", 15120) {|serv|
350
* p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
353
* If Addrinfo object is preferred over the binary string,
354
* use BasicSocket#local_address.
357
bsock_getsockname(VALUE sock)
359
struct sockaddr_storage buf;
360
socklen_t len = (socklen_t)sizeof buf;
363
GetOpenFile(sock, fptr);
364
if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
365
rb_sys_fail("getsockname(2)");
366
return rb_str_new((char*)&buf, len);
371
* basicsocket.getpeername => sockaddr
373
* Returns the remote address of the socket as a sockaddr string.
375
* TCPServer.open("127.0.0.1", 1440) {|serv|
376
* c = TCPSocket.new("127.0.0.1", 1440)
378
* p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
381
* If Addrinfo object is preferred over the binary string,
382
* use BasicSocket#remote_address.
386
bsock_getpeername(VALUE sock)
388
struct sockaddr_storage buf;
389
socklen_t len = (socklen_t)sizeof buf;
392
GetOpenFile(sock, fptr);
393
if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
394
rb_sys_fail("getpeername(2)");
395
return rb_str_new((char*)&buf, len);
398
#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
401
* basicsocket.getpeereid => [euid, egid]
403
* Returns the user and group on the peer of the UNIX socket.
404
* The result is a two element array which contains the effective uid and the effective gid.
406
* Socket.unix_server_loop("/tmp/sock") {|s|
408
* euid, egid = s.getpeereid
410
* # Check the connected client is myself or not.
411
* next if euid != Process.uid
413
* # do something about my resource.
422
bsock_getpeereid(VALUE self)
424
#if defined(HAVE_GETPEEREID)
428
GetOpenFile(self, fptr);
429
if (getpeereid(fptr->fd, &euid, &egid) == -1)
430
rb_sys_fail("getpeereid");
431
return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
432
#elif defined(SO_PEERCRED) /* GNU/Linux */
435
socklen_t len = sizeof(cred);
436
GetOpenFile(self, fptr);
437
if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
438
rb_sys_fail("getsockopt(SO_PEERCRED)");
439
return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
440
#elif defined(HAVE_GETPEERUCRED) /* Solaris */
444
GetOpenFile(self, fptr);
445
if (getpeerucred(fptr->fd, &uc) == -1)
446
rb_sys_fail("getpeerucred");
447
ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
453
#define bsock_getpeereid rb_f_notimplement
458
* bsock.local_address => addrinfo
460
* Returns an Addrinfo object for local address obtained by getsockname.
462
* Note that addrinfo.protocol is filled by 0.
464
* TCPSocket.open("www.ruby-lang.org", 80) {|s|
465
* p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP>
468
* TCPServer.open("127.0.0.1", 1512) {|serv|
469
* p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP>
474
bsock_local_address(VALUE sock)
476
struct sockaddr_storage buf;
477
socklen_t len = (socklen_t)sizeof buf;
480
GetOpenFile(sock, fptr);
481
if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
482
rb_sys_fail("getsockname(2)");
483
return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
488
* bsock.remote_address => addrinfo
490
* Returns an Addrinfo object for remote address obtained by getpeername.
492
* Note that addrinfo.protocol is filled by 0.
494
* TCPSocket.open("www.ruby-lang.org", 80) {|s|
495
* p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP>
498
* TCPServer.open("127.0.0.1", 1728) {|serv|
499
* c = TCPSocket.new("127.0.0.1", 1728)
501
* p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP>
506
bsock_remote_address(VALUE sock)
508
struct sockaddr_storage buf;
509
socklen_t len = (socklen_t)sizeof buf;
512
GetOpenFile(sock, fptr);
513
if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
514
rb_sys_fail("getpeername(2)");
515
return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
520
* basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent
522
* send _mesg_ via _basicsocket_.
524
* _mesg_ should be a string.
526
* _flags_ should be a bitwise OR of Socket::MSG_* constants.
528
* _dest_sockaddr_ should be a packed sockaddr string or an addrinfo.
530
* TCPSocket.open("localhost", 80) {|s|
531
* s.send "GET / HTTP/1.0\r\n\r\n", 0
536
rsock_bsock_send(int argc, VALUE *argv, VALUE sock)
538
struct rsock_send_arg arg;
542
rb_blocking_function_t *func;
545
rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
547
StringValue(arg.mesg);
549
SockAddrStringValue(to);
550
to = rb_str_new4(to);
551
arg.to = (struct sockaddr *)RSTRING_PTR(to);
552
arg.tolen = (socklen_t)RSTRING_LENINT(to);
553
func = rsock_sendto_blocking;
556
func = rsock_send_blocking;
558
GetOpenFile(sock, fptr);
560
arg.flags = NUM2INT(flags);
561
while (rb_thread_fd_writable(arg.fd),
562
(n = (int)BLOCKING_REGION(func, &arg)) < 0) {
563
if (rb_io_wait_writable(arg.fd)) {
566
rb_sys_fail("send(2)");
573
* basicsocket.do_not_reverse_lookup => true or false
575
* Gets the do_not_reverse_lookup flag of _basicsocket_.
577
* TCPSocket.open("www.ruby-lang.org", 80) {|sock|
578
* p sock.do_not_reverse_lookup #=> false
579
* p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
580
* sock.do_not_reverse_lookup = true
581
* p sock.peeraddr #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
585
bsock_do_not_reverse_lookup(VALUE sock)
589
GetOpenFile(sock, fptr);
590
return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
595
* basicsocket.do_not_reverse_lookup = bool
597
* Sets the do_not_reverse_lookup flag of _basicsocket_.
599
* BasicSocket.do_not_reverse_lookup = false
600
* p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> false
601
* BasicSocket.do_not_reverse_lookup = true
602
* p TCPSocket.new("127.0.0.1", 80).do_not_reverse_lookup #=> true
606
bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
611
GetOpenFile(sock, fptr);
613
fptr->mode |= FMODE_NOREVLOOKUP;
616
fptr->mode &= ~FMODE_NOREVLOOKUP;
623
* basicsocket.recv(maxlen) => mesg
624
* basicsocket.recv(maxlen, flags) => mesg
626
* Receives a message.
628
* _maxlen_ is the maximum number of bytes to receive.
630
* _flags_ should be a bitwise OR of Socket::MSG_* constants.
632
* UNIXSocket.pair {|s1, s2|
633
* s1.puts "Hello World"
634
* p s2.recv(4) #=> "Hell"
635
* p s2.recv(4, Socket::MSG_PEEK) #=> "o Wo"
636
* p s2.recv(4) #=> "o Wo"
637
* p s2.recv(10) #=> "rld\n"
641
bsock_recv(int argc, VALUE *argv, VALUE sock)
643
return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
648
* basicsocket.recv_nonblock(maxlen) => mesg
649
* basicsocket.recv_nonblock(maxlen, flags) => mesg
651
* Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
652
* O_NONBLOCK is set for the underlying file descriptor.
653
* _flags_ is zero or more of the +MSG_+ options.
654
* The result, _mesg_, is the data received.
656
* When recvfrom(2) returns 0, Socket#recv_nonblock returns
657
* an empty string as data.
658
* The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
661
* * +maxlen+ - the number of bytes to receive from the socket
662
* * +flags+ - zero or more of the +MSG_+ options
665
* serv = TCPServer.new("127.0.0.1", 0)
666
* af, port, host, addr = serv.addr
667
* c = TCPSocket.new(addr, port)
670
* begin # emulate blocking recv.
671
* p s.recv_nonblock(10) #=> "aaa"
672
* rescue IO::WaitReadable
677
* Refer to Socket#recvfrom for the exceptions that may be thrown if the call
678
* to _recv_nonblock_ fails.
680
* BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
681
* including Errno::EWOULDBLOCK.
683
* If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
684
* it is extended by IO::WaitReadable.
685
* So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock.
692
bsock_recv_nonblock(int argc, VALUE *argv, VALUE sock)
694
return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
699
* BasicSocket.do_not_reverse_lookup => true or false
701
* Gets the global do_not_reverse_lookup flag.
703
* BasicSocket.do_not_reverse_lookup #=> false
706
bsock_do_not_rev_lookup(void)
708
return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
713
* BasicSocket.do_not_reverse_lookup = bool
715
* Sets the global do_not_reverse_lookup flag.
717
* The flag is used for initial value of do_not_reverse_lookup for each socket.
719
* s1 = TCPSocket.new("localhost", 80)
720
* p s1.do_not_reverse_lookup #=> true
721
* BasicSocket.do_not_reverse_lookup = false
722
* s2 = TCPSocket.new("localhost", 80)
723
* p s2.do_not_reverse_lookup #=> false
724
* p s1.do_not_reverse_lookup #=> true
728
bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
731
rsock_do_not_reverse_lookup = RTEST(val);
736
* BasicSocket is the super class for the all socket classes.
739
rsock_init_basicsocket(void)
741
rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
742
rb_undef_method(rb_cBasicSocket, "initialize");
744
rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
745
bsock_do_not_rev_lookup, 0);
746
rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
747
bsock_do_not_rev_lookup_set, 1);
748
rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
750
rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
751
rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
752
rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
753
rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, -1);
754
rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
755
rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
756
rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
757
rb_define_method(rb_cBasicSocket, "getpeereid", bsock_getpeereid, 0);
758
rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0);
759
rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0);
760
rb_define_method(rb_cBasicSocket, "send", rsock_bsock_send, -1);
761
rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
762
rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
763
rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
764
rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
766
rb_define_method(rb_cBasicSocket, "sendmsg", rsock_bsock_sendmsg, -1); /* in ancdata.c */
767
rb_define_method(rb_cBasicSocket, "sendmsg_nonblock", rsock_bsock_sendmsg_nonblock, -1); /* in ancdata.c */
768
rb_define_method(rb_cBasicSocket, "recvmsg", rsock_bsock_recvmsg, -1); /* in ancdata.c */
769
rb_define_method(rb_cBasicSocket, "recvmsg_nonblock", rsock_bsock_recvmsg_nonblock, -1); /* in ancdata.c */