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); }