Flowdock
method

recv_io

Importance_0
recv_io(p1 = v1, p2 = v2) public

No documentation

This method has no description. You can help the Ruby community by adding new notes.

Hide source
static VALUE
unix_recv_io(int argc, VALUE *argv, VALUE sock)
{
#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
    VALUE klass, mode;
    rb_io_t *fptr;
    struct iomsg_arg arg;
    struct iovec vec[2];
    char buf[1];

    int fd;
#if FD_PASSING_BY_MSG_CONTROL
    struct {
        struct cmsghdr hdr;
        char pad[8+sizeof(int)+8];
    } cmsg;
#endif

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

    GetOpenFile(sock, fptr);

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

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

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

    arg.fd = fptr->fd;
    rb_thread_wait_fd(arg.fd);
    if ((int)BLOCKING_REGION(recvmsg_blocking, &arg) == -1)
        rb_sys_fail("recvmsg(2)");

#if FD_PASSING_BY_MSG_CONTROL
    if (arg.msg.msg_controllen < CMSG_LEN(sizeof(int))) {
        rb_raise(rb_eSocket,
                 "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
                 (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
    }
    if (CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) {
        rb_raise(rb_eSocket,
                 "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
                 (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
    }
    if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
        rb_raise(rb_eSocket,
                 "file descriptor was not passed (cmsg_len=%d, %d expected)",
                 (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
    }
    if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
        rb_raise(rb_eSocket,
                 "file descriptor was not passed (cmsg_level=%d, %d expected)",
                 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 expected)",
                 cmsg.hdr.cmsg_type, SCM_RIGHTS);
    }
#else
    if (arg.msg.msg_accrightslen != sizeof(fd)) {
        rb_raise(rb_eSocket,
                 "file descriptor was not passed (accrightslen) : %d != %d",
                 arg.msg.msg_accrightslen, (int)sizeof(fd));
    }
#endif

#if FD_PASSING_BY_MSG_CONTROL
    fd = *(int *)CMSG_DATA(&cmsg.hdr);
#endif

    if (klass == Qnil)
        return INT2FIX(fd);
    else {
        ID for_fd;
        int ff_argc;
        VALUE ff_argv[2];
        CONST_ID(for_fd, "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
}
Register or log in to add new notes.