IO
static VALUE
bsock_do_not_rev_lookup()
{
return do_not_reverse_lookup?Qtrue:Qfalse;
}
static VALUE
bsock_close_read(sock)
VALUE sock;
{
OpenFile *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
}
GetOpenFile(sock, fptr);
shutdown(fileno(fptr->f), 0);
if (!(fptr->mode & FMODE_WRITABLE)) {
return rb_io_close(sock);
}
fptr->mode &= ~FMODE_READABLE;
return Qnil;
}
static VALUE
bsock_close_write(sock)
VALUE sock;
{
OpenFile *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
}
GetOpenFile(sock, fptr);
if (!(fptr->mode & FMODE_READABLE)) {
return rb_io_close(sock);
}
shutdown(fileno(fptr->f2), 1);
fptr->mode &= ~FMODE_WRITABLE;
return Qnil;
}
static VALUE
bsock_getpeername(sock)
VALUE sock;
{
char buf[1024];
socklen_t len = sizeof buf;
OpenFile *fptr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
rb_sys_fail("getpeername(2)");
return rb_str_new(buf, len);
}
static VALUE
bsock_getsockname(sock)
VALUE sock;
{
char buf[1024];
socklen_t len = sizeof buf;
OpenFile *fptr;
GetOpenFile(sock, fptr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
rb_sys_fail("getsockname(2)");
return rb_str_new(buf, len);
}
Gets a socket option. These are protocol and system specific, see your local sytem documentation for details. The option is returned as a String with the data being the binary value of the socket option.
level is an integer, usually one of the SOL_ constants such as
Socket::SOL_SOCKET, or a protocol level.
optname is an integer, usually one of the SO_ constants, such
as Socket::SO_REUSEADDR.
Some socket options are integers with boolean values, in this case getsockopt could be called like this:
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:
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; };
In this case getsockopt could be called like this:
optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER) onoff, linger = optval.unpack "ii"
static VALUE
bsock_getsockopt(sock, lev, optname)
VALUE sock, lev, optname;
{
#if !defined(__BEOS__)
int level, option;
socklen_t len;
char *buf;
OpenFile *fptr;
level = NUM2INT(lev);
option = NUM2INT(optname);
len = 256;
buf = ALLOCA_N(char,len);
GetOpenFile(sock, fptr);
GetOpenFile(sock, fptr);
if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0)
rb_sys_fail(fptr->path);
return rb_str_new(buf, len);
#else
rb_notimplement();
#endif
}
static VALUE
bsock_recv(argc, argv, sock)
int argc;
VALUE *argv;
VALUE sock;
{
return s_recvfrom(sock, argc, argv, RECV_RECV);
}
Receives up to maxlen bytes from socket using
recvfrom(2) after O_NONBLOCK is set for the underlying file descriptor.
flags is zero or more of the MSG_ options. The
result, mesg, is the data received.
When recvfrom(2) returns 0, #recv_nonblock returns an empty string as data. The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
maxlen - the number of bytes to receive from the socket
flags - zero or more of the MSG_ options
serv = TCPServer.new("127.0.0.1", 0) af, port, host, addr = serv.addr c = TCPSocket.new(addr, port) s = serv.accept c.send "aaa", 0 IO.select([s]) p s.recv_nonblock(10) #=> "aaa"
Refer to Socket#recvfrom for the exceptions that may be thrown if the call to recv_nonblock fails.
#recv_nonblock may raise any error corresponding to recvfrom(2) failure, including Errno::EAGAIN.
static VALUE
bsock_recv_nonblock(argc, argv, sock)
int argc;
VALUE *argv;
VALUE sock;
{
return s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
}
static VALUE
bsock_send(argc, argv, sock)
int argc;
VALUE *argv;
VALUE sock;
{
VALUE mesg, to;
VALUE flags;
OpenFile *fptr;
FILE *f;
int fd, n;
rb_secure(4);
rb_scan_args(argc, argv, "21", &mesg, &flags, &to);
StringValue(mesg);
if (!NIL_P(to)) StringValue(to);
GetOpenFile(sock, fptr);
f = GetWriteFile(fptr);
fd = fileno(f);
rb_thread_fd_writable(fd);
retry:
if (!NIL_P(to)) {
TRAP_BEG;
n = sendto(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
(struct sockaddr*)RSTRING(to)->ptr, RSTRING(to)->len);
TRAP_END;
}
else {
TRAP_BEG;
n = send(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags));
TRAP_END;
}
if (n < 0) {
if (rb_io_wait_writable(fd)) {
goto retry;
}
rb_sys_fail("send(2)");
}
return INT2FIX(n);
}
Sets a socket option. These are protocol and system specific, see your local sytem documentation for details.
level is an integer, usually one of the SOL_ constants such as
Socket::SOL_SOCKET, or a protocol level.
optname is an integer, usually one of the SO_ constants, such
as Socket::SO_REUSEADDR.
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:
Fixnum: value is assigned to an int, and a pointer to the int is passed, with length of sizeof(int).
true or false: 1 or 0 (respectively) is assigned to an int, and the int is
passed as for a Fixnum. Note that false must be passed, not
nil.
String: the string's data and length is passed to the socket.
Some socket options are integers with boolean values, in this case setsockopt could be called like this:
sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
Some socket options are integers with numeric values, in this case setsockopt could be called like this:
sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
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; };
In this case setsockopt could be called like this:
optval = IPAddr.new("224.0.0.251") + Socket::INADDR_ANY sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
static VALUE
bsock_setsockopt(sock, lev, optname, val)
VALUE sock, lev, optname, val;
{
int level, option;
OpenFile *fptr;
int i;
char *v;
int vlen;
rb_secure(2);
level = NUM2INT(lev);
option = NUM2INT(optname);
switch (TYPE(val)) {
case T_FIXNUM:
i = FIX2INT(val);
goto numval;
case T_FALSE:
i = 0;
goto numval;
case T_TRUE:
i = 1;
numval:
v = (char*)&i; vlen = sizeof(i);
break;
default:
StringValue(val);
v = RSTRING(val)->ptr;
vlen = RSTRING(val)->len;
break;
}
GetOpenFile(sock, fptr);
if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0)
rb_sys_fail(fptr->path);
return INT2FIX(0);
}
static VALUE
bsock_shutdown(argc, argv, sock)
int argc;
VALUE *argv;
VALUE sock;
{
VALUE howto;
int how;
OpenFile *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
}
rb_scan_args(argc, argv, "01", &howto);
if (howto == Qnil)
how = 2;
else {
how = NUM2INT(howto);
if (how < 0 || 2 < how) {
rb_raise(rb_eArgError, "`how' should be either 0, 1, 2");
}
}
GetOpenFile(sock, fptr);
if (shutdown(fileno(fptr->f), how) == -1)
rb_sys_fail(0);
return INT2FIX(0);
}