In Files

  • socket/socket.c

BasicSocket

Public Class Methods

do_not_reverse_lookup() click to toggle source
 
               static VALUE
bsock_do_not_rev_lookup(void)
{
    return do_not_reverse_lookup?Qtrue:Qfalse;
}
            
do_not_reverse_lookup=(p1) click to toggle source
 
               static VALUE
bsock_do_not_rev_lookup_set(VALUE self, VALUE 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(VALUE klass, VALUE 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(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(fptr->fd, 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(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(fptr->fd, 1);
    fptr->mode &= ~FMODE_WRITABLE;

    return Qnil;
}
            
do_not_reverse_lookup() click to toggle source
 
               static VALUE
bsock_do_not_reverse_lookup(VALUE sock)
{
    rb_io_t *fptr;

    GetOpenFile(sock, fptr);
    return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
}
            
do_not_reverse_lookup=(p1) click to toggle source
 
               static VALUE
bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
{
    rb_io_t *fptr;

    rb_secure(4);
    GetOpenFile(sock, fptr);
    if (RTEST(state)) {
        fptr->mode |= FMODE_NOREVLOOKUP;
    }
    else {
        fptr->mode &= ~FMODE_NOREVLOOKUP;
    }
    return sock;
}
            
getpeername() click to toggle source
 
               static VALUE
bsock_getpeername(VALUE sock)
{
    char buf[1024];
    socklen_t len = sizeof buf;
    rb_io_t *fptr;

    GetOpenFile(sock, fptr);
    if (getpeername(fptr->fd, (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(VALUE sock)
{
    char buf[1024];
    socklen_t len = sizeof buf;
    rb_io_t *fptr;

    GetOpenFile(sock, fptr);
    if (getsockname(fptr->fd, (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(VALUE sock, VALUE lev, VALUE 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);
    if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
        rb_sys_fail_path(fptr->pathv);

    return rb_str_new(buf, len);
#else
    rb_notimplement();
#endif
}
            
recv(*args) click to toggle source
 
               static VALUE
bsock_recv(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]) # emulate blocking recv.
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::EWOULDBLOCK.

See

 
               static VALUE
bsock_recv_nonblock(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(int argc, VALUE *argv, VALUE sock)
{
    struct send_arg arg;
    VALUE flags, to;
    rb_io_t *fptr;
    int n;
    rb_blocking_function_t *func;

    rb_secure(4);
    rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);

    StringValue(arg.mesg);
    if (!NIL_P(to)) {
        StringValue(to);
        to = rb_str_new4(to);
        arg.to = (struct sockaddr *)RSTRING_PTR(to);
        arg.tolen = RSTRING_LEN(to);
        func = sendto_blocking;
    }
    else {
        func = send_blocking;
    }
    GetOpenFile(sock, fptr);
    arg.fd = fptr->fd;
    arg.flags = NUM2INT(flags);
    while (rb_thread_fd_writable(arg.fd),
           (n = (int)BLOCKING_REGION(func, &arg)) < 0) {
        if (rb_io_wait_writable(arg.fd)) {
            continue;
        }
        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(VALUE sock, VALUE lev, VALUE optname, VALUE 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_PTR(val);
        vlen = RSTRING_LEN(val);
        break;
    }

#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))

    GetOpenFile(sock, fptr);
    if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
        rb_sys_fail_path(fptr->pathv);

    return INT2FIX(0);
}
            
shutdown(p1 = v1) click to toggle source
 
               static VALUE
bsock_shutdown(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(fptr->fd, how) == -1)
        rb_sys_fail(0);

    return INT2FIX(0);
}
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus