In Files

  • socket/socket.c

BasicSocket

Public Class Methods

do_not_reverse_lookup() click to toggle source
 
               static VALUE
bsock_do_not_rev_lookup()
{
    return do_not_reverse_lookup?Qtrue:Qfalse;
}
            
do_not_reverse_lookup=(p1) click to toggle source
 
               static VALUE
bsock_do_not_rev_lookup_set(self, val)
    VALUE self, val;
{
    rb_secure(4);
    do_not_reverse_lookup = RTEST(val);
    return val;
}
            
for_fd(p1) click to toggle source
 
               static VALUE
bsock_s_for_fd(klass, fd)
    VALUE klass, fd;
{
    rb_io_t *fptr;
    VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));

    GetOpenFile(sock, fptr);

    return sock;
}
            

Public Instance Methods

close_read() click to toggle source
 
               static VALUE
bsock_close_read(sock)
    VALUE sock;
{
    rb_io_t *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;
}
            
close_write() click to toggle source
 
               static VALUE
bsock_close_write(sock)
    VALUE sock;
{
    rb_io_t *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;
}
            
getpeername() click to toggle source
 
               static VALUE
bsock_getpeername(sock)
    VALUE sock;
{
    char buf[1024];
    socklen_t len = sizeof buf;
    rb_io_t *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);
}
            
getsockname() click to toggle source
 
               static VALUE
bsock_getsockname(sock)
    VALUE sock;
{
    char buf[1024];
    socklen_t len = sizeof buf;
    rb_io_t *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);
}
            
getsockopt(level, optname) click to toggle source

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.

Parameters

  • 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.

Examples

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;
    rb_io_t *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
}
            
recv(*args) click to toggle source
 
               static VALUE
bsock_recv(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    return s_recvfrom(sock, argc, argv, RECV_RECV);
}
            
recv_nonblock(maxlen) => mesg click to toggle source
recv_nonblock(maxlen, flags) => mesg

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.

Parameters

  • maxlen - the number of bytes to receive from the socket

  • flags - zero or more of the MSG_ options

Example

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.

See

 
               static VALUE
bsock_recv_nonblock(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    return s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
}
            
send(p1, p2, p3 = v3) click to toggle source
 
               static VALUE
bsock_send(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    VALUE mesg, to;
    VALUE flags;
    rb_io_t *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);
}
            
setsockopt(level, optname, optval) click to toggle source

Sets a socket option. These are protocol and system specific, see your local sytem documentation for details.

Parameters

  • 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.

Examples

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;
    rb_io_t *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);
}
            
shutdown(p1 = v1) click to toggle source
 
               static VALUE
bsock_shutdown(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    VALUE howto;
    int how;
    rb_io_t *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);
}