In Files

  • socket/socket.c

UNIXSocket

Public Class Methods

new(p1) click to toggle source
 
               static VALUE
unix_init(sock, path)
    VALUE sock, path;
{
    return init_unixsock(sock, path, 0);
}
            
pair(p1 = v1, p2 = v2) click to toggle source
 
               static VALUE
unix_s_socketpair(argc, argv, klass)
    int argc;
    VALUE *argv;
    VALUE klass;
{
    VALUE domain, type, protocol;
    domain = INT2FIX(PF_UNIX);

    rb_scan_args(argc, argv, "02", &type, &protocol);
    if (argc == 0)
        type = INT2FIX(SOCK_STREAM);
    if (argc <= 1)
        protocol = INT2FIX(0);

    return sock_s_socketpair(klass, domain, type, protocol);
}
            
socketpair(p1 = v1, p2 = v2) click to toggle source
 
               static VALUE
unix_s_socketpair(argc, argv, klass)
    int argc;
    VALUE *argv;
    VALUE klass;
{
    VALUE domain, type, protocol;
    domain = INT2FIX(PF_UNIX);

    rb_scan_args(argc, argv, "02", &type, &protocol);
    if (argc == 0)
        type = INT2FIX(SOCK_STREAM);
    if (argc <= 1)
        protocol = INT2FIX(0);

    return sock_s_socketpair(klass, domain, type, protocol);
}
            

Public Instance Methods

addr() click to toggle source
 
               static VALUE
unix_addr(sock)
    VALUE sock;
{
    OpenFile *fptr;
    struct sockaddr_un addr;
    socklen_t len = sizeof addr;

    GetOpenFile(sock, fptr);

    if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
        rb_sys_fail("getsockname(2)");
    return unixaddr(&addr, len);
}
            
path() click to toggle source
 
               static VALUE
unix_path(sock)
    VALUE sock;
{
    OpenFile *fptr;

    GetOpenFile(sock, fptr);
    if (fptr->path == 0) {
        struct sockaddr_un addr;
        socklen_t len = sizeof(addr);
        if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
            rb_sys_fail(0);
        fptr->path = strdup(unixpath(&addr, len));
    }
    return rb_str_new2(fptr->path);
}
            
peeraddr() click to toggle source
 
               static VALUE
unix_peeraddr(sock)
    VALUE sock;
{
    OpenFile *fptr;
    struct sockaddr_un addr;
    socklen_t len = sizeof addr;

    GetOpenFile(sock, fptr);

    if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
        rb_sys_fail("getpeername(2)");
    return unixaddr(&addr, len);
}
            
recv_io(p1 = v1, p2 = v2) click to toggle source
 
               static VALUE
unix_recv_io(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
    VALUE klass, mode;
    OpenFile *fptr;
    struct msghdr msg;
    struct iovec vec[2];
    char buf[1];

    int fd;
#if FD_PASSING_BY_MSG_CONTROL
    struct {
        struct cmsghdr hdr;
        int fd;
    } cmsg;
#endif

    rb_scan_args(argc, argv, "02", &klass, &mode);
    if (argc == 0)
        klass = rb_cIO;
    if (argc <= 1)
        mode = Qnil;

    GetOpenFile(sock, fptr);

    thread_read_select(fileno(fptr->f));

    msg.msg_name = NULL;
    msg.msg_namelen = 0;

    vec[0].iov_base = buf;
    vec[0].iov_len = sizeof(buf);
    msg.msg_iov = vec;
    msg.msg_iovlen = 1;

#if FD_PASSING_BY_MSG_CONTROL
    msg.msg_control = (caddr_t)&cmsg;
    msg.msg_controllen = CMSG_SPACE(sizeof(int));
    msg.msg_flags = 0;
    cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
    cmsg.hdr.cmsg_level = SOL_SOCKET;
    cmsg.hdr.cmsg_type = SCM_RIGHTS;
    cmsg.fd = -1;
#else
    msg.msg_accrights = (caddr_t)&fd;
    msg.msg_accrightslen = sizeof(fd);
    fd = -1;
#endif

    if (recvmsg(fileno(fptr->f), &msg, 0) == -1)
        rb_sys_fail("recvmsg(2)");

#if FD_PASSING_BY_MSG_CONTROL
    if (msg.msg_controllen != CMSG_SPACE(sizeof(int))) {
      rb_raise(rb_eSocket,
          "file descriptor was not passed (msg_controllen : %d != %d)",
          msg.msg_controllen, CMSG_SPACE(sizeof(int)));
    }
    if (cmsg.hdr.cmsg_len != CMSG_SPACE(0) + sizeof(int)) {
      rb_raise(rb_eSocket,
          "file descriptor was not passed (cmsg_len : %d != %d)",
          cmsg.hdr.cmsg_len, CMSG_SPACE(0) + sizeof(int));
    }
    if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
      rb_raise(rb_eSocket,
          "file descriptor was not passed (cmsg_level : %d != %d)",
          cmsg.hdr.cmsg_level, SOL_SOCKET);
    }
    if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
      rb_raise(rb_eSocket,
          "file descriptor was not passed (cmsg_type : %d != %d)",
          cmsg.hdr.cmsg_type, SCM_RIGHTS);
    }
#else
    if (msg.msg_accrightslen != sizeof(fd)) {
        rb_raise(rb_eSocket,
            "file descriptor was not passed (accrightslen) : %d != %d",
            msg.msg_accrightslen, sizeof(fd));
    }
#endif

#if FD_PASSING_BY_MSG_CONTROL
    fd = cmsg.fd;
#endif

    if (klass == Qnil)
        return INT2FIX(fd);
    else {
        static ID for_fd = 0;
        int ff_argc;
        VALUE ff_argv[2];
        if (!for_fd)
            for_fd = rb_intern("for_fd");
        ff_argc = mode == Qnil ? 1 : 2;
        ff_argv[0] = INT2FIX(fd);
        ff_argv[1] = mode;
        return rb_funcall2(klass, for_fd, ff_argc, ff_argv);
    }
#else
    rb_notimplement();
    return Qnil;                /* not reached */
#endif
}
            
recvfrom(*args) click to toggle source
 
               static VALUE
unix_recvfrom(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    return s_recvfrom(sock, argc, argv, RECV_UNIX);
}
            
send_io(p1) click to toggle source
 
               static VALUE
unix_send_io(sock, val)
    VALUE sock, val;
{
#if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
    int fd;
    OpenFile *fptr;
    struct msghdr msg;
    struct iovec vec[1];
    char buf[1];

#if FD_PASSING_BY_MSG_CONTROL
    struct {
        struct cmsghdr hdr;
        int fd;
    } cmsg;
#endif

    if (rb_obj_is_kind_of(val, rb_cIO)) {
        OpenFile *valfptr;
        GetOpenFile(val, valfptr);
        fd = fileno(valfptr->f);
    }
    else if (FIXNUM_P(val)) {
        fd = FIX2INT(val);
    }
    else {
        rb_raise(rb_eTypeError, "neither IO nor file descriptor");
    }

    GetOpenFile(sock, fptr);

    msg.msg_name = NULL;
    msg.msg_namelen = 0;

    /* Linux and Solaris doesn't work if msg_iov is NULL. */
    buf[0] = '\0';
    vec[0].iov_base = buf;
    vec[0].iov_len = 1;
    msg.msg_iov = vec;
    msg.msg_iovlen = 1;

#if FD_PASSING_BY_MSG_CONTROL
    msg.msg_control = (caddr_t)&cmsg;
    msg.msg_controllen = CMSG_SPACE(sizeof(int));
    msg.msg_flags = 0;
    cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
    cmsg.hdr.cmsg_level = SOL_SOCKET;
    cmsg.hdr.cmsg_type = SCM_RIGHTS;
    cmsg.fd = fd;
#else
    msg.msg_accrights = (caddr_t)&fd;
    msg.msg_accrightslen = sizeof(fd);
#endif

    if (sendmsg(fileno(fptr->f), &msg, 0) == -1)
        rb_sys_fail("sendmsg(2)");

    return Qnil;
#else
    rb_notimplement();
    return Qnil;                /* not reached */
#endif
}