2009-01-16 23:11:27 -05:00
|
|
|
/************************************************
|
|
|
|
|
|
|
|
basicsocket.c -
|
|
|
|
|
|
|
|
created at: Thu Mar 31 12:21:29 JST 1994
|
|
|
|
|
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
|
|
|
|
|
|
|
************************************************/
|
|
|
|
|
|
|
|
#include "rubysocket.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* BasicSocket.for_fd(fd) => basicsocket
|
|
|
|
*
|
|
|
|
* Returns a socket object which contains the file descriptor, _fd_.
|
|
|
|
*
|
|
|
|
* # If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
|
|
|
|
* STDIN_SOCK = Socket.for_fd(STDIN.fileno)
|
|
|
|
* p STDIN_SOCK.remote_address
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_s_for_fd(VALUE klass, VALUE fd)
|
|
|
|
{
|
|
|
|
rb_io_t *fptr;
|
2009-03-01 01:30:41 -05:00
|
|
|
VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd));
|
2009-01-16 23:11:27 -05:00
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
|
|
|
|
|
|
|
return sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.shutdown([how]) => 0
|
|
|
|
*
|
|
|
|
* Calls shutdown(2) system call.
|
|
|
|
*
|
|
|
|
* s.shutdown(Socket::SHUT_RD) disallows further read.
|
|
|
|
*
|
|
|
|
* s.shutdown(Socket::SHUT_WR) disallows further write.
|
|
|
|
*
|
|
|
|
* s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
|
|
|
|
*
|
|
|
|
* _how_ can be symbol or string:
|
|
|
|
* - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD.
|
|
|
|
* - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR.
|
|
|
|
* - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR.
|
|
|
|
*
|
|
|
|
* UNIXSocket.pair {|s1, s2|
|
|
|
|
* s1.puts "ping"
|
|
|
|
* s1.shutdown(:WR)
|
|
|
|
* p s2.read #=> "ping\n"
|
|
|
|
* s2.puts "pong"
|
|
|
|
* s2.close
|
|
|
|
* p s1.read #=> "pong\n"
|
|
|
|
* }
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_shutdown(int argc, VALUE *argv, VALUE sock)
|
|
|
|
{
|
|
|
|
VALUE howto;
|
|
|
|
int how;
|
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "01", &howto);
|
|
|
|
if (howto == Qnil)
|
|
|
|
how = SHUT_RDWR;
|
|
|
|
else {
|
2009-03-01 01:30:41 -05:00
|
|
|
how = rsock_shutdown_how_arg(howto);
|
2009-01-16 23:11:27 -05:00
|
|
|
if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
|
|
|
|
rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GetOpenFile(sock, fptr);
|
|
|
|
if (shutdown(fptr->fd, how) == -1)
|
2013-04-05 22:39:44 -04:00
|
|
|
rb_sys_fail("shutdown(2)");
|
2009-01-16 23:11:27 -05:00
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.close_read => nil
|
|
|
|
*
|
2010-03-22 05:45:57 -04:00
|
|
|
* Disallows further read using shutdown system call.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* s1, s2 = UNIXSocket.pair
|
|
|
|
* s1.close_read
|
|
|
|
* s2.puts #=> Broken pipe (Errno::EPIPE)
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_close_read(VALUE sock)
|
|
|
|
{
|
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
|
|
|
shutdown(fptr->fd, 0);
|
|
|
|
if (!(fptr->mode & FMODE_WRITABLE)) {
|
|
|
|
return rb_io_close(sock);
|
|
|
|
}
|
|
|
|
fptr->mode &= ~FMODE_READABLE;
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.close_write => nil
|
|
|
|
*
|
2010-03-22 05:45:57 -04:00
|
|
|
* Disallows further write using shutdown system call.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* UNIXSocket.pair {|s1, s2|
|
|
|
|
* s1.print "ping"
|
|
|
|
* s1.close_write
|
|
|
|
* p s2.read #=> "ping"
|
|
|
|
* s2.print "pong"
|
|
|
|
* s2.close
|
|
|
|
* p s1.read #=> "pong"
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_close_write(VALUE sock)
|
|
|
|
{
|
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
|
|
|
if (!(fptr->mode & FMODE_READABLE)) {
|
|
|
|
return rb_io_close(sock);
|
|
|
|
}
|
|
|
|
shutdown(fptr->fd, 1);
|
|
|
|
fptr->mode &= ~FMODE_WRITABLE;
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Document-method: setsockopt
|
2010-01-31 03:39:05 -05:00
|
|
|
* call-seq:
|
|
|
|
* setsockopt(level, optname, optval)
|
|
|
|
* setsockopt(socketoption)
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* Sets a socket option. These are protocol and system specific, see your
|
2009-11-04 07:02:37 -05:00
|
|
|
* local system documentation for details.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* === Parameters
|
|
|
|
* * +level+ is an integer, usually one of the SOL_ constants such as
|
|
|
|
* Socket::SOL_SOCKET, or a protocol level.
|
2010-01-31 03:39:05 -05:00
|
|
|
* A string or symbol of the name, possibly without prefix, is also
|
|
|
|
* accepted.
|
2009-01-16 23:11:27 -05:00
|
|
|
* * +optname+ is an integer, usually one of the SO_ constants, such
|
|
|
|
* as Socket::SO_REUSEADDR.
|
2010-01-31 03:39:05 -05:00
|
|
|
* A string or symbol of the name, possibly without prefix, is also
|
|
|
|
* accepted.
|
2009-01-16 23:11:27 -05:00
|
|
|
* * +optval+ is the value of the option, it is passed to the underlying
|
|
|
|
* setsockopt() as a pointer to a certain number of bytes. How this is
|
|
|
|
* done depends on the type:
|
2016-10-26 02:11:23 -04:00
|
|
|
* - Integer: value is assigned to an int, and a pointer to the int is
|
2009-01-16 23:11:27 -05:00
|
|
|
* passed, with length of sizeof(int).
|
|
|
|
* - true or false: 1 or 0 (respectively) is assigned to an int, and the
|
2016-10-26 02:11:23 -04:00
|
|
|
* int is passed as for an Integer. Note that +false+ must be passed,
|
2009-01-16 23:11:27 -05:00
|
|
|
* not +nil+.
|
|
|
|
* - String: the string's data and length is passed to the socket.
|
2010-01-31 03:39:05 -05:00
|
|
|
* * +socketoption+ is an instance of Socket::Option
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* === Examples
|
|
|
|
*
|
|
|
|
* Some socket options are integers with boolean values, in this case
|
|
|
|
* #setsockopt could be called like this:
|
2010-04-22 04:04:13 -04:00
|
|
|
* sock.setsockopt(:SOCKET, :REUSEADDR, true)
|
2009-01-16 23:11:27 -05:00
|
|
|
* sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
2010-01-31 03:39:05 -05:00
|
|
|
* sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* Some socket options are integers with numeric values, in this case
|
|
|
|
* #setsockopt could be called like this:
|
2010-04-22 04:04:13 -04:00
|
|
|
* sock.setsockopt(:IP, :TTL, 255)
|
2009-01-16 23:11:27 -05:00
|
|
|
* sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
|
2010-04-22 04:04:13 -04:00
|
|
|
* sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* Option values may be structs. Passing them can be complex as it involves
|
|
|
|
* examining your system headers to determine the correct definition. An
|
|
|
|
* example is an +ip_mreq+, which may be defined in your system headers as:
|
|
|
|
* struct ip_mreq {
|
|
|
|
* struct in_addr imr_multiaddr;
|
|
|
|
* struct in_addr imr_interface;
|
|
|
|
* };
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* In this case #setsockopt could be called like this:
|
2010-03-22 05:45:57 -04:00
|
|
|
* optval = IPAddr.new("224.0.0.251").hton +
|
|
|
|
* IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton
|
2009-01-16 23:11:27 -05:00
|
|
|
* sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
2009-02-01 20:53:02 -05:00
|
|
|
bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
|
2009-01-16 23:11:27 -05:00
|
|
|
{
|
2009-02-01 20:53:02 -05:00
|
|
|
VALUE lev, optname, val;
|
2009-02-09 08:56:43 -05:00
|
|
|
int family, level, option;
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_io_t *fptr;
|
|
|
|
int i;
|
|
|
|
char *v;
|
|
|
|
int vlen;
|
|
|
|
|
2009-02-01 20:53:02 -05:00
|
|
|
if (argc == 1) {
|
|
|
|
lev = rb_funcall(argv[0], rb_intern("level"), 0);
|
|
|
|
optname = rb_funcall(argv[0], rb_intern("optname"), 0);
|
|
|
|
val = rb_funcall(argv[0], rb_intern("data"), 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_scan_args(argc, argv, "30", &lev, &optname, &val);
|
|
|
|
}
|
|
|
|
|
2009-02-09 08:56:43 -05:00
|
|
|
GetOpenFile(sock, fptr);
|
2015-07-01 21:58:14 -04:00
|
|
|
family = rsock_getfamily(fptr);
|
2009-03-01 01:30:41 -05:00
|
|
|
level = rsock_level_arg(family, lev);
|
|
|
|
option = rsock_optname_arg(family, level, optname);
|
2009-01-16 23:11:27 -05:00
|
|
|
|
|
|
|
switch (TYPE(val)) {
|
|
|
|
case T_FIXNUM:
|
|
|
|
i = FIX2INT(val);
|
|
|
|
goto numval;
|
|
|
|
case T_FALSE:
|
|
|
|
i = 0;
|
|
|
|
goto numval;
|
|
|
|
case T_TRUE:
|
|
|
|
i = 1;
|
|
|
|
numval:
|
2010-04-28 04:14:13 -04:00
|
|
|
v = (char*)&i; vlen = (int)sizeof(i);
|
2009-01-16 23:11:27 -05:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
StringValue(val);
|
|
|
|
v = RSTRING_PTR(val);
|
2013-04-06 03:58:51 -04:00
|
|
|
vlen = RSTRING_SOCKLEN(val);
|
2009-01-16 23:11:27 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-02-09 08:56:43 -05:00
|
|
|
rb_io_check_closed(fptr);
|
2009-01-16 23:11:27 -05:00
|
|
|
if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
|
2013-04-05 22:39:44 -04:00
|
|
|
rsock_sys_fail_path("setsockopt(2)", fptr->pathv);
|
2009-01-16 23:11:27 -05:00
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Document-method: getsockopt
|
2010-01-31 03:41:13 -05:00
|
|
|
* call-seq:
|
|
|
|
* getsockopt(level, optname) => socketoption
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* Gets a socket option. These are protocol and system specific, see your
|
2009-11-04 07:02:37 -05:00
|
|
|
* local system documentation for details. The option is returned as
|
2010-03-22 05:45:57 -04:00
|
|
|
* a Socket::Option object.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* === Parameters
|
|
|
|
* * +level+ is an integer, usually one of the SOL_ constants such as
|
|
|
|
* Socket::SOL_SOCKET, or a protocol level.
|
2010-01-31 03:39:05 -05:00
|
|
|
* A string or symbol of the name, possibly without prefix, is also
|
|
|
|
* accepted.
|
2009-01-16 23:11:27 -05:00
|
|
|
* * +optname+ is an integer, usually one of the SO_ constants, such
|
|
|
|
* as Socket::SO_REUSEADDR.
|
2010-01-31 03:39:05 -05:00
|
|
|
* A string or symbol of the name, possibly without prefix, is also
|
|
|
|
* accepted.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* === Examples
|
|
|
|
*
|
|
|
|
* Some socket options are integers with boolean values, in this case
|
|
|
|
* #getsockopt could be called like this:
|
2010-01-31 03:39:05 -05:00
|
|
|
*
|
|
|
|
* reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool
|
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
|
|
|
|
* optval = optval.unpack "i"
|
|
|
|
* reuseaddr = optval[0] == 0 ? false : true
|
|
|
|
*
|
|
|
|
* Some socket options are integers with numeric values, in this case
|
|
|
|
* #getsockopt could be called like this:
|
2010-01-31 03:39:05 -05:00
|
|
|
*
|
|
|
|
* ipttl = sock.getsockopt(:IP, :TTL).int
|
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
|
|
|
|
* ipttl = optval.unpack("i")[0]
|
|
|
|
*
|
|
|
|
* Option values may be structs. Decoding them can be complex as it involves
|
|
|
|
* examining your system headers to determine the correct definition. An
|
|
|
|
* example is a +struct linger+, which may be defined in your system headers
|
|
|
|
* as:
|
|
|
|
* struct linger {
|
|
|
|
* int l_onoff;
|
|
|
|
* int l_linger;
|
|
|
|
* };
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* In this case #getsockopt could be called like this:
|
2010-01-31 03:39:05 -05:00
|
|
|
*
|
|
|
|
* # Socket::Option knows linger structure.
|
|
|
|
* onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger
|
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
|
|
|
|
* onoff, linger = optval.unpack "ii"
|
2010-01-31 03:39:05 -05:00
|
|
|
* onoff = onoff == 0 ? false : true
|
2009-01-16 23:11:27 -05:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
|
|
|
|
{
|
|
|
|
int level, option;
|
|
|
|
socklen_t len;
|
|
|
|
char *buf;
|
|
|
|
rb_io_t *fptr;
|
2009-02-09 08:56:43 -05:00
|
|
|
int family;
|
2009-01-16 23:11:27 -05:00
|
|
|
|
2009-02-09 08:56:43 -05:00
|
|
|
GetOpenFile(sock, fptr);
|
2015-07-01 21:58:14 -04:00
|
|
|
family = rsock_getfamily(fptr);
|
2009-03-01 01:30:41 -05:00
|
|
|
level = rsock_level_arg(family, lev);
|
|
|
|
option = rsock_optname_arg(family, level, optname);
|
2009-01-16 23:11:27 -05:00
|
|
|
len = 256;
|
|
|
|
buf = ALLOCA_N(char,len);
|
|
|
|
|
2009-02-09 08:56:43 -05:00
|
|
|
rb_io_check_closed(fptr);
|
2009-02-08 10:12:27 -05:00
|
|
|
|
2009-01-16 23:11:27 -05:00
|
|
|
if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
|
2013-04-05 22:39:44 -04:00
|
|
|
rsock_sys_fail_path("getsockopt(2)", fptr->pathv);
|
2009-01-16 23:11:27 -05:00
|
|
|
|
2009-03-01 01:30:41 -05:00
|
|
|
return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
|
2009-04-18 10:10:06 -04:00
|
|
|
}
|
2009-01-16 23:11:27 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.getsockname => sockaddr
|
|
|
|
*
|
|
|
|
* Returns the local address of the socket as a sockaddr string.
|
|
|
|
*
|
|
|
|
* TCPServer.open("127.0.0.1", 15120) {|serv|
|
|
|
|
* p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
* }
|
2010-03-21 23:33:14 -04:00
|
|
|
*
|
2010-03-22 05:45:57 -04:00
|
|
|
* If Addrinfo object is preferred over the binary string,
|
|
|
|
* use BasicSocket#local_address.
|
2009-01-16 23:11:27 -05:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_getsockname(VALUE sock)
|
|
|
|
{
|
2013-02-24 12:51:17 -05:00
|
|
|
union_sockaddr buf;
|
2010-04-28 04:14:13 -04:00
|
|
|
socklen_t len = (socklen_t)sizeof buf;
|
2013-01-30 07:01:51 -05:00
|
|
|
socklen_t len0 = len;
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
2013-02-24 12:51:17 -05:00
|
|
|
if (getsockname(fptr->fd, &buf.addr, &len) < 0)
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_sys_fail("getsockname(2)");
|
2013-01-30 07:01:51 -05:00
|
|
|
if (len0 < len) len = len0;
|
2009-02-09 06:19:57 -05:00
|
|
|
return rb_str_new((char*)&buf, len);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.getpeername => sockaddr
|
|
|
|
*
|
|
|
|
* Returns the remote address of the socket as a sockaddr string.
|
|
|
|
*
|
|
|
|
* TCPServer.open("127.0.0.1", 1440) {|serv|
|
|
|
|
* c = TCPSocket.new("127.0.0.1", 1440)
|
|
|
|
* s = serv.accept
|
|
|
|
* p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
* }
|
|
|
|
*
|
2010-03-22 05:45:57 -04:00
|
|
|
* If Addrinfo object is preferred over the binary string,
|
|
|
|
* use BasicSocket#remote_address.
|
2010-03-21 23:33:14 -04:00
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_getpeername(VALUE sock)
|
|
|
|
{
|
2013-02-24 12:51:17 -05:00
|
|
|
union_sockaddr buf;
|
2010-04-28 04:14:13 -04:00
|
|
|
socklen_t len = (socklen_t)sizeof buf;
|
2013-01-30 07:01:51 -05:00
|
|
|
socklen_t len0 = len;
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
2013-02-24 12:51:17 -05:00
|
|
|
if (getpeername(fptr->fd, &buf.addr, &len) < 0)
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_sys_fail("getpeername(2)");
|
2013-01-30 07:01:51 -05:00
|
|
|
if (len0 < len) len = len0;
|
2009-02-10 09:31:21 -05:00
|
|
|
return rb_str_new((char*)&buf, len);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
2009-04-18 10:10:06 -04:00
|
|
|
#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
|
2009-02-10 20:22:08 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.getpeereid => [euid, egid]
|
|
|
|
*
|
|
|
|
* Returns the user and group on the peer of the UNIX socket.
|
|
|
|
* The result is a two element array which contains the effective uid and the effective gid.
|
|
|
|
*
|
|
|
|
* Socket.unix_server_loop("/tmp/sock") {|s|
|
2009-02-13 07:01:53 -05:00
|
|
|
* begin
|
2009-02-13 09:43:12 -05:00
|
|
|
* euid, egid = s.getpeereid
|
|
|
|
*
|
|
|
|
* # Check the connected client is myself or not.
|
|
|
|
* next if euid != Process.uid
|
|
|
|
*
|
|
|
|
* # do something about my resource.
|
|
|
|
*
|
2009-02-13 07:01:53 -05:00
|
|
|
* ensure
|
|
|
|
* s.close
|
|
|
|
* end
|
2009-02-10 20:22:08 -05:00
|
|
|
* }
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_getpeereid(VALUE self)
|
|
|
|
{
|
|
|
|
#if defined(HAVE_GETPEEREID)
|
|
|
|
rb_io_t *fptr;
|
|
|
|
uid_t euid;
|
|
|
|
gid_t egid;
|
|
|
|
GetOpenFile(self, fptr);
|
|
|
|
if (getpeereid(fptr->fd, &euid, &egid) == -1)
|
2013-04-05 22:39:44 -04:00
|
|
|
rb_sys_fail("getpeereid(3)");
|
2009-02-10 20:22:08 -05:00
|
|
|
return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
|
|
|
|
#elif defined(SO_PEERCRED) /* GNU/Linux */
|
|
|
|
rb_io_t *fptr;
|
|
|
|
struct ucred cred;
|
|
|
|
socklen_t len = sizeof(cred);
|
|
|
|
GetOpenFile(self, fptr);
|
|
|
|
if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
|
|
|
|
rb_sys_fail("getsockopt(SO_PEERCRED)");
|
|
|
|
return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
|
2009-02-12 07:43:04 -05:00
|
|
|
#elif defined(HAVE_GETPEERUCRED) /* Solaris */
|
|
|
|
rb_io_t *fptr;
|
|
|
|
ucred_t *uc = NULL;
|
|
|
|
VALUE ret;
|
|
|
|
GetOpenFile(self, fptr);
|
|
|
|
if (getpeerucred(fptr->fd, &uc) == -1)
|
2013-04-05 22:39:44 -04:00
|
|
|
rb_sys_fail("getpeerucred(3C)");
|
2009-02-12 07:43:04 -05:00
|
|
|
ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
|
|
|
|
ucred_free(uc);
|
|
|
|
return ret;
|
2009-02-10 20:22:08 -05:00
|
|
|
#endif
|
|
|
|
}
|
2009-04-18 10:10:06 -04:00
|
|
|
#else
|
|
|
|
#define bsock_getpeereid rb_f_notimplement
|
|
|
|
#endif
|
2009-02-10 20:22:08 -05:00
|
|
|
|
2009-01-16 23:11:27 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* bsock.local_address => addrinfo
|
|
|
|
*
|
2009-02-05 06:01:43 -05:00
|
|
|
* Returns an Addrinfo object for local address obtained by getsockname.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* Note that addrinfo.protocol is filled by 0.
|
|
|
|
*
|
2010-03-22 05:45:57 -04:00
|
|
|
* TCPSocket.open("www.ruby-lang.org", 80) {|s|
|
|
|
|
* p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP>
|
|
|
|
* }
|
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* TCPServer.open("127.0.0.1", 1512) {|serv|
|
2009-02-05 06:01:43 -05:00
|
|
|
* p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP>
|
2009-01-16 23:11:27 -05:00
|
|
|
* }
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_local_address(VALUE sock)
|
|
|
|
{
|
2013-02-24 12:51:17 -05:00
|
|
|
union_sockaddr buf;
|
2010-04-28 04:14:13 -04:00
|
|
|
socklen_t len = (socklen_t)sizeof buf;
|
2013-01-30 07:01:51 -05:00
|
|
|
socklen_t len0 = len;
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
2013-02-24 12:51:17 -05:00
|
|
|
if (getsockname(fptr->fd, &buf.addr, &len) < 0)
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_sys_fail("getsockname(2)");
|
2013-01-30 07:01:51 -05:00
|
|
|
if (len0 < len) len = len0;
|
2013-02-24 12:51:17 -05:00
|
|
|
return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* bsock.remote_address => addrinfo
|
|
|
|
*
|
2009-02-05 06:01:43 -05:00
|
|
|
* Returns an Addrinfo object for remote address obtained by getpeername.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* Note that addrinfo.protocol is filled by 0.
|
|
|
|
*
|
2010-03-22 05:45:57 -04:00
|
|
|
* TCPSocket.open("www.ruby-lang.org", 80) {|s|
|
|
|
|
* p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP>
|
|
|
|
* }
|
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* TCPServer.open("127.0.0.1", 1728) {|serv|
|
|
|
|
* c = TCPSocket.new("127.0.0.1", 1728)
|
|
|
|
* s = serv.accept
|
2009-02-05 06:01:43 -05:00
|
|
|
* p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP>
|
2009-01-16 23:11:27 -05:00
|
|
|
* }
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_remote_address(VALUE sock)
|
|
|
|
{
|
2013-02-24 12:51:17 -05:00
|
|
|
union_sockaddr buf;
|
2010-04-28 04:14:13 -04:00
|
|
|
socklen_t len = (socklen_t)sizeof buf;
|
2013-01-30 07:01:51 -05:00
|
|
|
socklen_t len0 = len;
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
2013-02-24 12:51:17 -05:00
|
|
|
if (getpeername(fptr->fd, &buf.addr, &len) < 0)
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_sys_fail("getpeername(2)");
|
2013-01-30 07:01:51 -05:00
|
|
|
if (len0 < len) len = len0;
|
2013-02-24 12:51:17 -05:00
|
|
|
return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-03-22 05:45:57 -04:00
|
|
|
* basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* send _mesg_ via _basicsocket_.
|
|
|
|
*
|
|
|
|
* _mesg_ should be a string.
|
|
|
|
*
|
|
|
|
* _flags_ should be a bitwise OR of Socket::MSG_* constants.
|
|
|
|
*
|
2010-03-22 05:45:57 -04:00
|
|
|
* _dest_sockaddr_ should be a packed sockaddr string or an addrinfo.
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* TCPSocket.open("localhost", 80) {|s|
|
|
|
|
* s.send "GET / HTTP/1.0\r\n\r\n", 0
|
|
|
|
* p s.read
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
VALUE
|
2009-03-01 01:30:41 -05:00
|
|
|
rsock_bsock_send(int argc, VALUE *argv, VALUE sock)
|
2009-01-16 23:11:27 -05:00
|
|
|
{
|
2009-03-01 01:30:41 -05:00
|
|
|
struct rsock_send_arg arg;
|
2009-01-16 23:11:27 -05:00
|
|
|
VALUE flags, to;
|
|
|
|
rb_io_t *fptr;
|
2017-01-16 16:42:05 -05:00
|
|
|
ssize_t n;
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_blocking_function_t *func;
|
2017-04-07 23:25:50 -04:00
|
|
|
const char *funcname;
|
2009-01-16 23:11:27 -05:00
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
|
|
|
|
|
|
|
|
StringValue(arg.mesg);
|
|
|
|
if (!NIL_P(to)) {
|
|
|
|
SockAddrStringValue(to);
|
|
|
|
to = rb_str_new4(to);
|
|
|
|
arg.to = (struct sockaddr *)RSTRING_PTR(to);
|
2013-04-06 03:58:51 -04:00
|
|
|
arg.tolen = RSTRING_SOCKLEN(to);
|
2009-03-01 01:30:41 -05:00
|
|
|
func = rsock_sendto_blocking;
|
2017-04-07 23:25:50 -04:00
|
|
|
funcname = "sendto(2)";
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
else {
|
2009-03-01 01:30:41 -05:00
|
|
|
func = rsock_send_blocking;
|
2017-04-07 23:25:50 -04:00
|
|
|
funcname = "send(2)";
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
GetOpenFile(sock, fptr);
|
|
|
|
arg.fd = fptr->fd;
|
|
|
|
arg.flags = NUM2INT(flags);
|
2014-01-18 09:13:22 -05:00
|
|
|
while (rsock_maybe_fd_writable(arg.fd),
|
2017-01-16 16:42:05 -05:00
|
|
|
(n = (ssize_t)BLOCKING_REGION_FD(func, &arg)) < 0) {
|
2009-01-16 23:11:27 -05:00
|
|
|
if (rb_io_wait_writable(arg.fd)) {
|
|
|
|
continue;
|
|
|
|
}
|
2017-04-07 23:25:50 -04:00
|
|
|
rb_sys_fail(funcname);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
2017-01-16 16:42:05 -05:00
|
|
|
return SSIZET2NUM(n);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.do_not_reverse_lookup => true or false
|
|
|
|
*
|
|
|
|
* Gets the do_not_reverse_lookup flag of _basicsocket_.
|
|
|
|
*
|
2016-10-04 23:57:32 -04:00
|
|
|
* require 'socket'
|
|
|
|
*
|
2015-07-08 01:05:27 -04:00
|
|
|
* BasicSocket.do_not_reverse_lookup = false
|
2009-01-16 23:11:27 -05:00
|
|
|
* TCPSocket.open("www.ruby-lang.org", 80) {|sock|
|
|
|
|
* p sock.do_not_reverse_lookup #=> false
|
2015-07-08 01:05:27 -04:00
|
|
|
* }
|
|
|
|
* BasicSocket.do_not_reverse_lookup = true
|
|
|
|
* TCPSocket.open("www.ruby-lang.org", 80) {|sock|
|
|
|
|
* p sock.do_not_reverse_lookup #=> true
|
2009-01-16 23:11:27 -05:00
|
|
|
* }
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_do_not_reverse_lookup(VALUE sock)
|
|
|
|
{
|
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
|
|
|
return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* basicsocket.do_not_reverse_lookup = bool
|
|
|
|
*
|
|
|
|
* Sets the do_not_reverse_lookup flag of _basicsocket_.
|
|
|
|
*
|
2015-07-08 01:05:27 -04:00
|
|
|
* TCPSocket.open("www.ruby-lang.org", 80) {|sock|
|
|
|
|
* p sock.do_not_reverse_lookup #=> true
|
|
|
|
* p sock.peeraddr #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
|
|
|
|
* sock.do_not_reverse_lookup = false
|
|
|
|
* p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "54.163.249.195"]
|
|
|
|
* }
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
|
|
|
|
{
|
|
|
|
rb_io_t *fptr;
|
|
|
|
|
|
|
|
GetOpenFile(sock, fptr);
|
|
|
|
if (RTEST(state)) {
|
|
|
|
fptr->mode |= FMODE_NOREVLOOKUP;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fptr->mode &= ~FMODE_NOREVLOOKUP;
|
|
|
|
}
|
|
|
|
return sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2015-06-15 16:02:43 -04:00
|
|
|
* basicsocket.recv(maxlen[, flags[, outbuf]]) => mesg
|
2009-01-16 23:11:27 -05:00
|
|
|
*
|
|
|
|
* Receives a message.
|
|
|
|
*
|
|
|
|
* _maxlen_ is the maximum number of bytes to receive.
|
|
|
|
*
|
|
|
|
* _flags_ should be a bitwise OR of Socket::MSG_* constants.
|
|
|
|
*
|
2015-06-15 16:02:43 -04:00
|
|
|
* _outbuf_ will contain only the received data after the method call
|
|
|
|
* even if it is not empty at the beginning.
|
|
|
|
*
|
2009-01-16 23:11:27 -05:00
|
|
|
* UNIXSocket.pair {|s1, s2|
|
|
|
|
* s1.puts "Hello World"
|
|
|
|
* p s2.recv(4) #=> "Hell"
|
|
|
|
* p s2.recv(4, Socket::MSG_PEEK) #=> "o Wo"
|
|
|
|
* p s2.recv(4) #=> "o Wo"
|
|
|
|
* p s2.recv(10) #=> "rld\n"
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_recv(int argc, VALUE *argv, VALUE sock)
|
|
|
|
{
|
2009-03-01 01:30:41 -05:00
|
|
|
return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
socket: avoid arg parsing in rsock_s_recvfrom_nonblock
* ext/socket/init.c (rsock_s_recvfrom_nonblock):
avoid arg parsing with C API
[ruby-core:71439] [Feature #11339]
* ext/socket/basicsocket.c (bsock_recv_nonblock):
adjust for above change, make private
* ext/socket/socket.c (sock_recvfrom_nonblock): ditto
* ext/socket/udpsocket.c (udp_recvfrom_nonblock): ditto
* ext/socket/lib/socket.rb (BasicSocket#recv_nonblock):
new wrapper for private method, move RDoc
(Socket#recvfrom_nonblock): ditto
(UDPSocket#recvfrom_nonblock): ditto
Note, not adding bm_recv_nonblock.rb to benchmark/ directory
since it is non-portable. It is only in this commit message.
Benchmark results + code
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52540) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52540) [x86_64-linux]
-----------------------------------------------------------
recv_nonblock
require 'socket'
nr = 1000000
msg = 'hello world'
buf = ''
size = msg.bytesize
UNIXSocket.pair(:SEQPACKET) do |a, b|
nr.times do
a.sendmsg(msg)
b.recv_nonblock(size, 0, buf, exception: false)
end
end
-----------------------------------------------------------
raw data:
[["recv_nonblock",
[[1.83511221408844,
1.8703329525887966,
1.8448856547474861,
1.859263762831688,
1.8331583738327026],
[1.5637447573244572,
1.4062932096421719,
1.4247371144592762,
1.4108827747404575,
1.4802536629140377]]]]
Elapsed time: 16.530452496 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
recv_nonblock 1.833 1.406
Speedup ratio: compare with the result of `a' (greater is better)
name b
recv_nonblock 1.304
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 18:25:03 -05:00
|
|
|
/* :nodoc: */
|
2009-01-16 23:11:27 -05:00
|
|
|
static VALUE
|
socket: avoid arg parsing in rsock_s_recvfrom_nonblock
* ext/socket/init.c (rsock_s_recvfrom_nonblock):
avoid arg parsing with C API
[ruby-core:71439] [Feature #11339]
* ext/socket/basicsocket.c (bsock_recv_nonblock):
adjust for above change, make private
* ext/socket/socket.c (sock_recvfrom_nonblock): ditto
* ext/socket/udpsocket.c (udp_recvfrom_nonblock): ditto
* ext/socket/lib/socket.rb (BasicSocket#recv_nonblock):
new wrapper for private method, move RDoc
(Socket#recvfrom_nonblock): ditto
(UDPSocket#recvfrom_nonblock): ditto
Note, not adding bm_recv_nonblock.rb to benchmark/ directory
since it is non-portable. It is only in this commit message.
Benchmark results + code
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52540) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52540) [x86_64-linux]
-----------------------------------------------------------
recv_nonblock
require 'socket'
nr = 1000000
msg = 'hello world'
buf = ''
size = msg.bytesize
UNIXSocket.pair(:SEQPACKET) do |a, b|
nr.times do
a.sendmsg(msg)
b.recv_nonblock(size, 0, buf, exception: false)
end
end
-----------------------------------------------------------
raw data:
[["recv_nonblock",
[[1.83511221408844,
1.8703329525887966,
1.8448856547474861,
1.859263762831688,
1.8331583738327026],
[1.5637447573244572,
1.4062932096421719,
1.4247371144592762,
1.4108827747404575,
1.4802536629140377]]]]
Elapsed time: 16.530452496 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
recv_nonblock 1.833 1.406
Speedup ratio: compare with the result of `a' (greater is better)
name b
recv_nonblock 1.304
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 18:25:03 -05:00
|
|
|
bsock_recv_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex)
|
2009-01-16 23:11:27 -05:00
|
|
|
{
|
socket: avoid arg parsing in rsock_s_recvfrom_nonblock
* ext/socket/init.c (rsock_s_recvfrom_nonblock):
avoid arg parsing with C API
[ruby-core:71439] [Feature #11339]
* ext/socket/basicsocket.c (bsock_recv_nonblock):
adjust for above change, make private
* ext/socket/socket.c (sock_recvfrom_nonblock): ditto
* ext/socket/udpsocket.c (udp_recvfrom_nonblock): ditto
* ext/socket/lib/socket.rb (BasicSocket#recv_nonblock):
new wrapper for private method, move RDoc
(Socket#recvfrom_nonblock): ditto
(UDPSocket#recvfrom_nonblock): ditto
Note, not adding bm_recv_nonblock.rb to benchmark/ directory
since it is non-portable. It is only in this commit message.
Benchmark results + code
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52540) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52540) [x86_64-linux]
-----------------------------------------------------------
recv_nonblock
require 'socket'
nr = 1000000
msg = 'hello world'
buf = ''
size = msg.bytesize
UNIXSocket.pair(:SEQPACKET) do |a, b|
nr.times do
a.sendmsg(msg)
b.recv_nonblock(size, 0, buf, exception: false)
end
end
-----------------------------------------------------------
raw data:
[["recv_nonblock",
[[1.83511221408844,
1.8703329525887966,
1.8448856547474861,
1.859263762831688,
1.8331583738327026],
[1.5637447573244572,
1.4062932096421719,
1.4247371144592762,
1.4108827747404575,
1.4802536629140377]]]]
Elapsed time: 16.530452496 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
recv_nonblock 1.833 1.406
Speedup ratio: compare with the result of `a' (greater is better)
name b
recv_nonblock 1.304
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 18:25:03 -05:00
|
|
|
return rsock_s_recvfrom_nonblock(sock, len, flg, str, ex, RECV_RECV);
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* BasicSocket.do_not_reverse_lookup => true or false
|
|
|
|
*
|
|
|
|
* Gets the global do_not_reverse_lookup flag.
|
|
|
|
*
|
|
|
|
* BasicSocket.do_not_reverse_lookup #=> false
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_do_not_rev_lookup(void)
|
|
|
|
{
|
2009-03-01 01:30:41 -05:00
|
|
|
return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* BasicSocket.do_not_reverse_lookup = bool
|
|
|
|
*
|
|
|
|
* Sets the global do_not_reverse_lookup flag.
|
|
|
|
*
|
|
|
|
* The flag is used for initial value of do_not_reverse_lookup for each socket.
|
|
|
|
*
|
|
|
|
* s1 = TCPSocket.new("localhost", 80)
|
|
|
|
* p s1.do_not_reverse_lookup #=> true
|
|
|
|
* BasicSocket.do_not_reverse_lookup = false
|
|
|
|
* s2 = TCPSocket.new("localhost", 80)
|
|
|
|
* p s2.do_not_reverse_lookup #=> false
|
|
|
|
* p s1.do_not_reverse_lookup #=> true
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
|
|
|
|
{
|
2009-03-01 01:30:41 -05:00
|
|
|
rsock_do_not_reverse_lookup = RTEST(val);
|
2009-01-16 23:11:27 -05:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-03-22 12:15:21 -04:00
|
|
|
rsock_init_basicsocket(void)
|
2009-01-16 23:11:27 -05:00
|
|
|
{
|
2011-08-15 19:08:39 -04:00
|
|
|
/*
|
|
|
|
* Document-class: BasicSocket < IO
|
|
|
|
*
|
|
|
|
* BasicSocket is the super class for all the Socket classes.
|
|
|
|
*/
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
|
|
|
|
rb_undef_method(rb_cBasicSocket, "initialize");
|
|
|
|
|
|
|
|
rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
|
|
|
|
bsock_do_not_rev_lookup, 0);
|
|
|
|
rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
|
|
|
|
bsock_do_not_rev_lookup_set, 1);
|
|
|
|
rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
|
|
|
|
|
|
|
|
rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
|
|
|
|
rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
|
|
|
|
rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
|
2009-02-01 20:53:02 -05:00
|
|
|
rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, -1);
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
|
|
|
|
rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
|
|
|
|
rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
|
2009-02-10 20:22:08 -05:00
|
|
|
rb_define_method(rb_cBasicSocket, "getpeereid", bsock_getpeereid, 0);
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0);
|
|
|
|
rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0);
|
2009-03-01 01:30:41 -05:00
|
|
|
rb_define_method(rb_cBasicSocket, "send", rsock_bsock_send, -1);
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
|
socket: avoid arg parsing in rsock_s_recvfrom_nonblock
* ext/socket/init.c (rsock_s_recvfrom_nonblock):
avoid arg parsing with C API
[ruby-core:71439] [Feature #11339]
* ext/socket/basicsocket.c (bsock_recv_nonblock):
adjust for above change, make private
* ext/socket/socket.c (sock_recvfrom_nonblock): ditto
* ext/socket/udpsocket.c (udp_recvfrom_nonblock): ditto
* ext/socket/lib/socket.rb (BasicSocket#recv_nonblock):
new wrapper for private method, move RDoc
(Socket#recvfrom_nonblock): ditto
(UDPSocket#recvfrom_nonblock): ditto
Note, not adding bm_recv_nonblock.rb to benchmark/ directory
since it is non-portable. It is only in this commit message.
Benchmark results + code
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52540) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52540) [x86_64-linux]
-----------------------------------------------------------
recv_nonblock
require 'socket'
nr = 1000000
msg = 'hello world'
buf = ''
size = msg.bytesize
UNIXSocket.pair(:SEQPACKET) do |a, b|
nr.times do
a.sendmsg(msg)
b.recv_nonblock(size, 0, buf, exception: false)
end
end
-----------------------------------------------------------
raw data:
[["recv_nonblock",
[[1.83511221408844,
1.8703329525887966,
1.8448856547474861,
1.859263762831688,
1.8331583738327026],
[1.5637447573244572,
1.4062932096421719,
1.4247371144592762,
1.4108827747404575,
1.4802536629140377]]]]
Elapsed time: 16.530452496 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
recv_nonblock 1.833 1.406
Speedup ratio: compare with the result of `a' (greater is better)
name b
recv_nonblock 1.304
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 18:25:03 -05:00
|
|
|
|
2009-01-16 23:11:27 -05:00
|
|
|
rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
|
|
|
|
rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
|
2010-03-21 06:50:52 -04:00
|
|
|
|
socket: avoid arg parsing in rsock_s_recvfrom_nonblock
* ext/socket/init.c (rsock_s_recvfrom_nonblock):
avoid arg parsing with C API
[ruby-core:71439] [Feature #11339]
* ext/socket/basicsocket.c (bsock_recv_nonblock):
adjust for above change, make private
* ext/socket/socket.c (sock_recvfrom_nonblock): ditto
* ext/socket/udpsocket.c (udp_recvfrom_nonblock): ditto
* ext/socket/lib/socket.rb (BasicSocket#recv_nonblock):
new wrapper for private method, move RDoc
(Socket#recvfrom_nonblock): ditto
(UDPSocket#recvfrom_nonblock): ditto
Note, not adding bm_recv_nonblock.rb to benchmark/ directory
since it is non-portable. It is only in this commit message.
Benchmark results + code
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52540) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52540) [x86_64-linux]
-----------------------------------------------------------
recv_nonblock
require 'socket'
nr = 1000000
msg = 'hello world'
buf = ''
size = msg.bytesize
UNIXSocket.pair(:SEQPACKET) do |a, b|
nr.times do
a.sendmsg(msg)
b.recv_nonblock(size, 0, buf, exception: false)
end
end
-----------------------------------------------------------
raw data:
[["recv_nonblock",
[[1.83511221408844,
1.8703329525887966,
1.8448856547474861,
1.859263762831688,
1.8331583738327026],
[1.5637447573244572,
1.4062932096421719,
1.4247371144592762,
1.4108827747404575,
1.4802536629140377]]]]
Elapsed time: 16.530452496 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
recv_nonblock 1.833 1.406
Speedup ratio: compare with the result of `a' (greater is better)
name b
recv_nonblock 1.304
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 18:25:03 -05:00
|
|
|
/* for ext/socket/lib/socket.rb use only: */
|
|
|
|
rb_define_private_method(rb_cBasicSocket,
|
|
|
|
"__recv_nonblock", bsock_recv_nonblock, 4);
|
|
|
|
|
socket (bsock_recvmsg_internal): avoid arg parsing
* ext/socket/ancdata.c (bsock_recvmsg_internal): avoid arg parsing
(rsock_bsock_recvmsg): adjust for above change
(rsock_bsock_recvmsg_nonblock): ditto
[ruby-core:71439] [Feature #11339]
* ext/socket/rubysocket.h: adjust prototypes for above
* ext/socket/basicsocket.c (rsock_init_basicsocket):
adjust private methods
* ext/socket/lib/socket.rb (BasicSocket#recvmsg): wrapper method
(BasicSocket#recvmsg_nonblock): ditto
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52550) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52550) [x86_64-linux]
-----------------------------------------------------------
recvmsg_nonblock
require 'socket'
nr = 1_000_000
i = 0
msg = '.'
buf = '.'
begin
r, w = UNIXSocket.pair(:SEQPACKET)
while i < nr
i += 1
w.sendmsg(msg)
r.recvmsg_nonblock(1, exception: false)
end
ensure
r.close
w.close
end
-----------------------------------------------------------
raw data:
[["recvmsg_nonblock",
[[3.721687912940979,
3.6072621569037437,
3.580637402832508,
3.614185404032469,
3.6029579415917397],
[2.4694008752703667,
2.4908322244882584,
2.5051278844475746,
2.5037173740565777,
2.548359278589487]]]]
Elapsed time: 30.646087052 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
recvmsg_nonblock 3.581 2.469
Speedup ratio: compare with the result of `a' (greater is better)
name b
recvmsg_nonblock 1.450
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52602 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 19:58:23 -05:00
|
|
|
/* in ancdata.c */
|
socket: avoid arg parsing in bsock_sendmsg_internal
* ext/socket/ancdata.c (bsock_sendmsg_internal): avoid arg parsing
[ruby-core:71439] [Feature #11339]
(rsock_bsock_sendmsg): make private, adjust for above
(rsock_bsock_sendmsg_nonblock): ditto
* ext/socket/rubysocket.h: adjust prototypes
(rsock_opt_false_p): remove
* ext/socket/basicsocket.c (rsock_init_basicsocket):
define private methods
* ext/socket/lib/socket.rb (BasicSocket#sendmsg): new wrapper
(BasicSocket#sendmsg_nonblock): ditto
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52550) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52550) [x86_64-linux]
-----------------------------------------------------------
sendmsg_nonblock
require 'socket'
nr = 1_000_000
i = 0
msg = '.'
buf = '.'
begin
r, w = UNIXSocket.pair(:SEQPACKET)
while i < nr
i += 1
w.sendmsg_nonblock(msg, exception: false)
r.recv(1, 0, buf)
end
ensure
r.close
w.close
end
-----------------------------------------------------------
raw data:
[["sendmsg_nonblock",
[[1.875997293740511,
1.8452614955604076,
1.8449317328631878,
1.8418389447033405,
1.869386937469244],
[1.5175109766423702,
1.4987873211503029,
1.4989623799920082,
1.47918451577425,
1.5017359890043736]]]]
Elapsed time: 16.775453245 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
sendmsg_nonblock 1.842 1.479
Speedup ratio: compare with the result of `a' (greater is better)
name b
sendmsg_nonblock 1.245
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52603 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 20:05:30 -05:00
|
|
|
rb_define_private_method(rb_cBasicSocket, "__sendmsg",
|
|
|
|
rsock_bsock_sendmsg, 4);
|
|
|
|
rb_define_private_method(rb_cBasicSocket, "__sendmsg_nonblock",
|
|
|
|
rsock_bsock_sendmsg_nonblock, 5);
|
socket (bsock_recvmsg_internal): avoid arg parsing
* ext/socket/ancdata.c (bsock_recvmsg_internal): avoid arg parsing
(rsock_bsock_recvmsg): adjust for above change
(rsock_bsock_recvmsg_nonblock): ditto
[ruby-core:71439] [Feature #11339]
* ext/socket/rubysocket.h: adjust prototypes for above
* ext/socket/basicsocket.c (rsock_init_basicsocket):
adjust private methods
* ext/socket/lib/socket.rb (BasicSocket#recvmsg): wrapper method
(BasicSocket#recvmsg_nonblock): ditto
target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52550) [x86_64-linux])
target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52550) [x86_64-linux]
-----------------------------------------------------------
recvmsg_nonblock
require 'socket'
nr = 1_000_000
i = 0
msg = '.'
buf = '.'
begin
r, w = UNIXSocket.pair(:SEQPACKET)
while i < nr
i += 1
w.sendmsg(msg)
r.recvmsg_nonblock(1, exception: false)
end
ensure
r.close
w.close
end
-----------------------------------------------------------
raw data:
[["recvmsg_nonblock",
[[3.721687912940979,
3.6072621569037437,
3.580637402832508,
3.614185404032469,
3.6029579415917397],
[2.4694008752703667,
2.4908322244882584,
2.5051278844475746,
2.5037173740565777,
2.548359278589487]]]]
Elapsed time: 30.646087052 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
recvmsg_nonblock 3.581 2.469
Speedup ratio: compare with the result of `a' (greater is better)
name b
recvmsg_nonblock 1.450
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52602 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-16 19:58:23 -05:00
|
|
|
rb_define_private_method(rb_cBasicSocket, "__recvmsg",
|
|
|
|
rsock_bsock_recvmsg, 4);
|
|
|
|
rb_define_private_method(rb_cBasicSocket, "__recvmsg_nonblock",
|
|
|
|
rsock_bsock_recvmsg_nonblock, 5);
|
2010-03-21 06:50:52 -04:00
|
|
|
|
2009-01-16 23:11:27 -05:00
|
|
|
}
|