Example #1
0
int main(int argc, char *argv[]) 
{
    errval_t err;

    printf("Child. will print out file descriptors\n");

    /* Inherit all the FDs sent over */
    err = get_inherited_fds();
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "could not get inherited FDs\n");
        return EXIT_FAILURE;
    }

    /* print out all of our FDs */
    int i;
    struct fdtab_entry *fde;
    for (i = MIN_FD; i < MAX_FD; i++) {
        fde = fdtab_get(i);
        if (fde->type != FDTAB_TYPE_AVAILABLE) {
            printf("fd[%d]: type: %d, handle: %p\n", i, fde->type, fde->handle);
        }
    }

    return EXIT_SUCCESS;
}
Example #2
0
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen)
{
    struct fdtab_entry *e = fdtab_get(sockfd);
    ssize_t ret = 0;

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        assert(!"NYI");
        return -1;
        break;

    case FDTAB_TYPE_LWIP_SOCKET:
        lwip_mutex_lock();
        ret = lwip_sendto(e->fd, buf, len, flags, dest_addr, addrlen);
        lwip_mutex_unlock();
        break;

    case FDTAB_TYPE_AVAILABLE:
        errno = EBADF;
        ret = -1;
        break;

    default:
        errno = ENOTSOCK;
        ret = -1;
        break;
    }

    return ret;
}
Example #3
0
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen)
{
    struct fdtab_entry *e = fdtab_get(sockfd);

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        assert(!"NYI");
        return -1;
        break;

    case FDTAB_TYPE_LWIP_SOCKET:
        lwip_mutex_lock();
        ssize_t ret = lwip_recvfrom(e->fd, buf, len, flags, src_addr, addrlen);
        lwip_mutex_unlock();
        return ret;

    case FDTAB_TYPE_AVAILABLE:
        errno = EBADF;
        return -1;

    default:
        errno = ENOTSOCK;
        return -1;
    }
}
Example #4
0
int close(int fd)
{
    int ret;
    struct fdtab_entry *e = fdtab_get(fd);
    if (e->type == FDTAB_TYPE_AVAILABLE) {
        return -1;
    }

    if (e->type == FDTAB_TYPE_LWIP_SOCKET) {
        if(e->inherited) {
            // Perform shallow close on lwip so that it will not terminate
            // the TCP session
            printf("close: Inherited socket, not closing completely\n");
            ret = 0;
        } else {
            ret = lwip_close(e->fd);
            if(ret < 0) {
                POSIXCOMPAT_DEBUG("[%d]error in lwip_close\n",
                        disp_get_domain_id());
                return -1;
            }
        }
        fdtab_free(fd);
    } else {
        ret = vfsfd_close(fd);
    }

    return ret;
}
Example #5
0
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
    struct fdtab_entry *e = fdtab_get(sockfd);
    ssize_t ret = 0;

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        assert(!"NYI");
        return -1;
        break;

    case FDTAB_TYPE_LWIP_SOCKET:
        assert(msg != NULL);
        assert(msg->msg_control == NULL);
        assert(msg->msg_controllen == 0);

#if 0
        // XXX: Copy all buffers into one. Should instead have an lwIP interface for this.
        size_t totalsize = 0;
        for(int i = 0; i < msg->msg_iovlen; i++) {
            totalsize += msg->msg_iov[i].iov_len;
        }

        char *buf = malloc(totalsize);

        size_t pos = 0;
        for(int i = 0; i < msg->msg_iovlen; i++) {
            memcpy(&buf[pos], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
            pos += msg->msg_iov[i].iov_len;
        }

        lwip_mutex_lock();
        ret = lwip_sendto(e->fd, buf, totalsize, flags, msg->msg_name,
                          msg->msg_namelen);
        lwip_mutex_unlock();
        free(buf);
#else
        lwip_mutex_lock();
        ret = lwip_sendmsg(e->fd, msg, flags);
        lwip_mutex_unlock();
#endif

        break;

    case FDTAB_TYPE_AVAILABLE:
        errno = EBADF;
        ret = -1;
        break;

    default:
        errno = ENOTSOCK;
        ret = -1;
        break;
    }

    return ret;
}
Example #6
0
off_t vfsfd_lseek(int fd, off_t offset, int whence)
{
    struct fdtab_entry *e = fdtab_get(fd);
    switch(e->type) {
    case FDTAB_TYPE_FILE:
        {
            enum vfs_seekpos vfs_whence;
            errval_t err;
            size_t retpos;

            switch(whence) {
            case SEEK_SET:
                vfs_whence = VFS_SEEK_SET;
                break;

            case SEEK_CUR:
                vfs_whence = VFS_SEEK_CUR;
                break;

            case SEEK_END:
                vfs_whence = VFS_SEEK_END;
                break;

            default:
                return -1;
            }

            err = vfs_seek((vfs_handle_t)e->handle, vfs_whence, offset);
            if(err_is_fail(err)) {
                DEBUG_ERR(err, "vfs_seek");
                return -1;
            }

            err = vfs_tell((vfs_handle_t)e->handle, &retpos);
            if(err_is_fail(err)) {
                DEBUG_ERR(err, "vfs_tell");
                return -1;
            }

            VFSFD_DEBUG("lseek(%d, %lld, %d) = %lu\n",
                         fd, offset, whence, retpos);

            return retpos;
        }
        break;

    default:
        return -1;
    }
}
Example #7
0
int ioctl(int fd, unsigned long request,  ...)
{
    va_list arg;
    va_start(arg, request);

    struct fdtab_entry *e = fdtab_get(fd);

    switch (e->type) {
    case FDTAB_TYPE_AVAILABLE:
        {
            errno = EBADF;
            return -1;
        }

    case FDTAB_TYPE_PTS:
        {
            struct _pty *state = e->handle;
            switch (request) {
                case TIOCGWINSZ: /* get window size */
                    {
                        struct winsize *w = va_arg(arg, struct winsize *);
                        memcpy(w, &state->winsize, sizeof(struct winsize));
                        return 0;
                    }

                case TIOCSWINSZ: /* set window size */
                    {
                        struct winsize *w = va_arg(arg, struct winsize *);
                        memcpy(&state->winsize, w, sizeof(struct winsize));
                        return 0;
                    }

                default:
                    assert(!"NYI");
                    errno = EINVAL;
                    return -1;
            }
        }

    default:
        {
            assert("NYI");
            return -1;
        }
    }

    va_end(arg);
}
Example #8
0
int close(int fd)
{
    int ret;
    struct fdtab_entry *e = fdtab_get(fd);
    if (e->type == FDTAB_TYPE_AVAILABLE) {
        return -1;
    }

    // Might need to remove from epoll list
    if(e->epoll_fd != -1) {
        ret = epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
        assert(ret == 0);
    }

    switch(e->type) {
    case FDTAB_TYPE_LWIP_SOCKET:
        if (e->inherited) {
            // Perform shallow close on lwip so that it will not terminate
            // the TCP session
            printf("close: Inherited socket, not closing completely\n");
            ret = 0;
        } else {
            ret = lwip_close(e->fd);
            if(ret < 0) {
                POSIXCOMPAT_DEBUG("[%d]error in lwip_close\n",
                                  disp_get_domain_id());
                return -1;
            }
        }
        fdtab_free(fd);
        break;

    case FDTAB_TYPE_PTM:
        ret = ptm_close(fd);
        break;

    case FDTAB_TYPE_PTS:
        ret = pts_close(fd);
        break;

    default:
        ret = vfsfd_close(fd);
    }

    return ret;
}
Example #9
0
int listen(int sockfd, int backlog)
{
    struct fdtab_entry *e = fdtab_get(sockfd);

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        POSIXCOMPAT_DEBUG("listen(%d, %d)\n", sockfd, backlog);
        struct _unix_socket *us = e->handle;

        errval_t err =
            unixsock_export(us, unixsock_listening, unixsock_connected,
                            get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
        if(err_is_fail(err)) {
            DEBUG_ERR(err, "unixsock_export failed");
            return -1;
        }
        while(us->u.passive.listen_iref == NULL_IREF) {
            // XXX: Should wait only on monitor
            event_dispatch(get_default_waitset());
        }

        us->passive = true;
        us->u.passive.max_backlog = backlog;
        us->u.passive.backlog = calloc(backlog, sizeof(struct unixsock_binding *));

        char str[128];
        snprintf(str, 128, "%"PRIuIREF, us->u.passive.listen_iref);
        err = vfs_write(us->vfs_handle, str, strlen(str), NULL);
        if(err_is_fail(err)) {
            USER_PANIC_ERR(err, "vfs_write");
        }
        break;

    case FDTAB_TYPE_LWIP_SOCKET:
        lwip_mutex_lock();
        int ret = lwip_listen(e->fd, backlog);
        lwip_mutex_unlock();
        return ret;

    default:
        return -1;
    }

    return 0;
}
Example #10
0
int fsync(int fd)
{
    struct fdtab_entry *e = fdtab_get(fd);

    switch(e->type) {
    case FDTAB_TYPE_FILE:
      {
	errval_t err = vfs_flush((vfs_handle_t)e->handle);
	if(err_is_fail(err)) {
	  return -1;
	}
      }
      break;

    default:
      errno = EINVAL;
      return -1;
    }

    return 0;
}
Example #11
0
/**
 * \brief Find the pathname of a terminal.
 */
char *ttyname(int fd)
{
    struct fdtab_entry *e = fdtab_get(fd);

    switch(e->type) {
    case FDTAB_TYPE_AVAILABLE:
        {
            errno = EBADF;
            return NULL;
        }

    case FDTAB_TYPE_PTS:
        {
            struct _pty *pty = e->handle;
            return pty->ptsname;
        }

    case FDTAB_TYPE_PTM:
    case FDTAB_TYPE_STDIN:
    case FDTAB_TYPE_STDOUT:
    case FDTAB_TYPE_STDERR:
        {
            /*
             * We do not create a file in the filesystem for these types of
             * file descriptors.
             */
            assert(!"NYI");
            return NULL;
        }

    default:
        {
            errno = ENOTTY;
            return 0;
        }
    }
}
Example #12
0
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
    struct fdtab_entry *e = fdtab_get(sockfd);

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        assert(addrlen >= sizeof(struct sockaddr_un));
        assert(addr->sa_family == AF_UNIX);
        struct _unix_socket *us = e->handle;
        memcpy(&us->sockaddr, addr, sizeof(struct sockaddr_un));

        POSIXCOMPAT_DEBUG("bind(%d, %p (%s), %u)\n", sockfd, addr,
                          us->sockaddr.sun_path, addrlen);

        // XXX: Should fail if file already exists

        // Create socket file
        errval_t err = vfs_create(us->sockaddr.sun_path, &us->vfs_handle);
        if(err_is_fail(err)) {
            DEBUG_ERR(err, "vfs_create");
            return -1;
        }
        break;

    case FDTAB_TYPE_LWIP_SOCKET:
        lwip_mutex_lock();
        int ret = lwip_bind(e->fd, addr, addrlen);
        lwip_mutex_unlock();
        return ret;

    default:
        return -1;
    }

    return 0;
}
Example #13
0
static errval_t get_inherited_fds(void) 
{
    errval_t err;

    /* Map the FD buffer into our address space.
     * It stays there since the FD data structures will remain in there and be 
     * referenced from the FD table.
     */
    struct capref frame = {
        .cnode = cnode_task,
        .slot = TASKCN_SLOT_FDSPAGE,
    };

    void *fdspg;
    err = vspace_map_one_frame(&fdspg, FDS_SIZE, frame, NULL, NULL);
    if (err_is_fail(err)) {
        return err_push(err, SPAWN_ERR_MAP_FDSPG_TO_SELF);
    }

    /* Set up to read the table */
    char *p = fdspg;
    printf("fds at: %p\n", p);

    int num_fds = *((int*)p);
    printf("num fds: %d\n", num_fds);

    struct fd_store *fd;
    p += sizeof(int);
    fd = (struct fd_store*)p;
    p += (sizeof(struct fd_store)*num_fds);

    /* Process all the FDs passed in the buffer */
    int i;
    for (i = 0; i < num_fds; i++, fd++) {

        /* add each to our fd table - replacing any fds already there */
        struct fdtab_entry fde;
        fde.type = fd->type;
        fde.handle = fd->handle;

        if (fdtab_get(fd->num)->type != FDTAB_TYPE_AVAILABLE) {
            fdtab_free(fd->num);
        }
        fdtab_alloc_from(&fde, fd->num);

        /* print out some info about the FD */

        char *s = "";
        switch (fd->type) {
        case FDTAB_TYPE_AVAILABLE:
            s = "available";
            break;
        case FDTAB_TYPE_FILE:
            s = "file";
            break;
        case FDTAB_TYPE_UNIX_SOCKET:
            s = "unix socket";
            break;
        case FDTAB_TYPE_STDIN:
            s = "stdin";
            break;
        case FDTAB_TYPE_STDOUT:
            s = "stdout";
            break;
        case FDTAB_TYPE_STDERR:
            s = "stderr";
            break;
        case FDTAB_TYPE_LWIP_SOCKET:
            s = "lwip socket";
            break;
        case FDTAB_TYPE_EPOLL_INSTANCE:
            s = "epoll instance";
            break;
        case FDTAB_TYPE_PTM:
            s = "pseudo-terminal master";
            break;
        case FDTAB_TYPE_PTS:
            s = "pseudo-terminal slave";
            break;
        }
        printf("fd_store %d: num: %d, type: %d:%s handle: %p\n", 
               i, fd->num, fd->type, s, fd->handle);

        switch (fd->type) {
        case FDTAB_TYPE_FILE:
            print_file_fd((void*)(p + (genpaddr_t)fd->handle));
            break;
        case FDTAB_TYPE_UNIX_SOCKET:
            print_unixsock_fd((void*)(p + (genpaddr_t)fd->handle));
            break;
        default:
            printf("[no handle data]\n");
            break;
        }

    }

    return SYS_ERR_OK;

}
Example #14
0
//XXX: flags are ignored...
int vfsfd_open(const char *pathname, int flags)
{
    vfs_handle_t vh;
    errval_t err;

    char *path = vfs_path_mkabs(pathname);
    assert(path != NULL);

    // If O_CREAT was given, we use vfs_create()
    if(flags & O_CREAT) {
        // If O_EXCL was also given, we check whether we can open() first
        if(flags & O_EXCL) {
            err = vfs_open(path, &vh);
            if(err_is_ok(err)) {
                vfs_close(vh);
                errno = EEXIST;
                return -1;
            }
            assert(err_no(err) == FS_ERR_NOTFOUND);
        }

        err = vfs_create(path, &vh);
    } else {
        // Regular open()
        err = vfs_open(path, &vh);
    }

    free(path);
    if (err_is_fail(err)) {
        VFSFD_DEBUG("open('%s') failed\n", pathname);

        switch(err_no(err)) {
        case FS_ERR_NOTFOUND:
            errno = ENOENT;
            break;

        default:
#ifdef VFSFD_DEBUG_ENABLED
            DEBUG_ERR(err, "vfs_open");
#endif
            break;
        }

        return -1;
    }

    struct fdtab_entry e = {
        .type = FDTAB_TYPE_FILE,
        .handle = vh,
        .epoll_fd = -1,
    };
    int fd = fdtab_alloc(&e);
    VFSFD_DEBUG("open(%s) as fd %d\n", pathname, fd);
    if (fd < 0) {
        vfs_close(vh);
        return -1;
    } else {
        return fd;
    }
}


int vfsfd_read(int fd, void *buf, size_t len)
{
    struct fdtab_entry *e = fdtab_get(fd);
    size_t retlen = 0;
    switch(e->type) {
    case FDTAB_TYPE_FILE:
        {
            errval_t err = vfs_read((vfs_handle_t)e->handle, buf, len, &retlen);
            VFSFD_DEBUG("%d : read(%d, %d) = %lu\n", disp_get_domain_id(), fd, len, retlen);
            if (err_is_fail(err)) {
                DEBUG_ERR(err, "error in vfs_read");
                return -1;
            }
        }
        break;

    case FDTAB_TYPE_STDIN:
        retlen = terminal_read((char *)buf, len);
        break;

    case FDTAB_TYPE_STDOUT:
    case FDTAB_TYPE_STDERR:
    case FDTAB_TYPE_AVAILABLE:
    default:
        return -1;
    }

    return retlen;
}

int vfsfd_write(int fd, const void *buf, size_t len)
{
    struct fdtab_entry *e = fdtab_get(fd);
    if (e->type == FDTAB_TYPE_AVAILABLE) {
        return -1;
    }

    size_t retlen = 0;

    switch(e->type) {
    case FDTAB_TYPE_FILE:
        {
            errval_t err = vfs_write((vfs_handle_t)e->handle, buf, len, &retlen);
            VFSFD_DEBUG("write(%d, %d) = %lu\n", fd, len, retlen);
            if (err_is_fail(err)) {
                DEBUG_ERR(err, "error in vfs_write");
                return -1;
            }
        }
        break;

    case FDTAB_TYPE_STDOUT:
        /* only support writting to terminal */
        retlen = terminal_write((const char*) buf, len);
        break;

    case FDTAB_TYPE_STDERR:
        retlen = terminal_write((const char*) buf, len);
        break;

    case FDTAB_TYPE_STDIN:
    case FDTAB_TYPE_AVAILABLE:
    default:
        return -1;
    }

    return retlen;
}

int vfsfd_close(int fd)
{
    errval_t err;
    struct fdtab_entry *e = fdtab_get(fd);
    if (e->type == FDTAB_TYPE_AVAILABLE) {
        return -1;
    }

    VFSFD_DEBUG("close(%d)\n", fd);

    switch(e->type) {
    case FDTAB_TYPE_FILE:
        err = vfs_close((vfs_handle_t)e->handle);
        if (err_is_fail(err)) {
            DEBUG_ERR(err, "error in vfs_close");
            return -1;
        }
        break;

    case FDTAB_TYPE_STDIN:
    case FDTAB_TYPE_STDOUT:
    case FDTAB_TYPE_STDERR:
        // XXX: Should call fclose() when closing last FD
        break;

    default:
        return -1;
    } // end switch

    fdtab_free(fd);
    return 0;
}
Example #15
0
ssize_t recv(int sockfd, void *buf, size_t len, int flags)
{
    struct fdtab_entry *e = fdtab_get(sockfd);

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        {
            struct _unix_socket *us = e->handle;

            // XXX: Don't support flags
            assert(flags == 0);

            thread_mutex_lock(&us->mutex);

            if(us->passive
               || us->u.active.mode != _UNIX_SOCKET_MODE_CONNECTED) {
                errno = ENOTCONN;
                thread_mutex_unlock(&us->mutex);
                return -1;
            }

            if(us->recv_buf_valid == 0) {
                // No more data
                if(us->nonblocking) {
                    errno = EAGAIN;
                    thread_mutex_unlock(&us->mutex);
                    return -1;
                } else {
                    struct waitset ws;
                    errval_t err;

                    waitset_init(&ws);

                    err = us->u.active.binding->change_waitset
                        (us->u.active.binding, &ws);
                    if(err_is_fail(err)) {
                        USER_PANIC_ERR(err, "change_waitset");
                    }

                    while(us->recv_buf_valid == 0) {
                        err = event_dispatch(&ws);
                        if(err_is_fail(err)) {
                            USER_PANIC_ERR(err, "waitset_destroy");
                        }
                    }

                    // XXX: Assume it was on the default waitset
                    err = us->u.active.binding->change_waitset
                        (us->u.active.binding, get_default_waitset());
                    if(err_is_fail(err)) {
                        USER_PANIC_ERR(err, "change_waitset");
                    }

                    err = waitset_destroy(&ws);
                    if(err_is_fail(err)) {
                        USER_PANIC_ERR(err, "waitset_destroy");
                    }
                }
            }

            size_t recved = 0;
            while(recved < len && us->recv_list != NULL) {
                struct _unix_socket_recv *usr = us->recv_list;
                size_t consume = MIN(len - recved, usr->size - usr->consumed);

                memcpy(buf + recved, &usr->msg[usr->consumed], consume);
                usr->consumed += consume;
                us->recv_buf_valid -= consume;
                recved += consume;

                if(usr->consumed == usr->size) {
                    us->recv_list = usr->next;
                    if(us->recv_list == NULL) {
                        us->recv_list_end = NULL;
                    }
                    free(usr->msg);
                    free(usr);
                } else {
                    assert(recved == len);
                }
            }

            thread_mutex_unlock(&us->mutex);
            return recved;
        }

    case FDTAB_TYPE_LWIP_SOCKET:
        lwip_mutex_lock();
        ssize_t ret = lwip_recv(e->fd, buf, len, flags);
        lwip_mutex_unlock();
        return ret;

    case FDTAB_TYPE_AVAILABLE:
        errno = EBADF;
        return -1;

    default:
        errno = ENOTSOCK;
        return -1;
    }
}
Example #16
0
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
{
    struct fdtab_entry *e = fdtab_get(sockfd);

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        {
            struct _unix_socket *us = e->handle;

            // XXX: Don't support flags
            assert(flags == 0);

            thread_mutex_lock(&us->mutex);

            if(us->passive
               || us->u.active.mode != _UNIX_SOCKET_MODE_CONNECTED) {
                errno = ENOTCONN;
                thread_mutex_unlock(&us->mutex);
                return -1;
            }

            if(us->send_buf != NULL) {
                if(us->nonblocking) {
                    errno = EAGAIN;
                    thread_mutex_unlock(&us->mutex);
                    return -1;
                } else {
                    assert(!"NYI");
                }
            }

            // Bleh. Gotta copy here. I can't just wait until the
            // message is fully sent, as that might block
            // indefinitely.
            us->send_buf = malloc(len);
            memcpy(us->send_buf, buf, len);

            struct event_closure ec = {
                .handler = unixsock_sent,
                .arg = us,
            };
            errval_t err = us->u.active.binding->tx_vtbl.
                send(us->u.active.binding, ec, us->send_buf, len);
            if(err_is_fail(err)) {
                USER_PANIC_ERR(err, "unixsock->send");
                thread_mutex_unlock(&us->mutex);
                return -1;
            }

            // Wait until all data sent if blocking
            if(!us->nonblocking) {
                struct waitset ws;
                waitset_init(&ws);

                err = us->u.active.binding->change_waitset
                    (us->u.active.binding, &ws);
                if(err_is_fail(err)) {
                    USER_PANIC_ERR(err, "change_waitset");
                }

                while(us->send_buf != NULL) {
                    err = event_dispatch(&ws);
                    if(err_is_fail(err)) {
                        USER_PANIC_ERR(err, "waitset_destroy");
                    }
                }

                // XXX: Assume it was on the default waitset
                err = us->u.active.binding->change_waitset
                    (us->u.active.binding, get_default_waitset());
                if(err_is_fail(err)) {
                    USER_PANIC_ERR(err, "change_waitset");
                }

                err = waitset_destroy(&ws);
                if(err_is_fail(err)) {
                    USER_PANIC_ERR(err, "waitset_destroy");
                }
            }

            // XXX: We send all or nothing
            thread_mutex_unlock(&us->mutex);
            return len;
        }

    case FDTAB_TYPE_LWIP_SOCKET:
        lwip_mutex_lock();
        ssize_t ret = lwip_send(e->fd, buf, len, flags);
        lwip_mutex_unlock();
        return ret;

    case FDTAB_TYPE_AVAILABLE:
        errno = EBADF;
        return -1;

    default:
        errno = ENOTSOCK;
        return -1;
    }
}
Example #17
0
                        return -1;
                    }
                }

                return newfd;
            }

    default:
        return -1;
    }
}

int getsockopt(int sockfd, int level, int optname, void *restrict optval,
               socklen_t *restrict optlen)
{
    struct fdtab_entry *e = fdtab_get(sockfd);

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        {
            /* struct _unix_socket *us = e->handle; */

            switch(level) {
            case SOL_SOCKET:
                switch(optname) {
                case SO_ERROR:
                    {
                        int *val = optval;

                        if(*optlen < sizeof(int)) {
                            // XXX: Store nothing if we can't store it all
Example #18
0
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
    struct fdtab_entry *mye = fdtab_get(epfd);
    assert(mye->type == FDTAB_TYPE_EPOLL_INSTANCE);
    struct _epoll_fd *efd = mye->handle;
    int ret = 0;

    if(op != EPOLL_CTL_DEL) {
        assert(!(event->events & EPOLLRDHUP));
        assert(!(event->events & EPOLLPRI));
        assert(!(event->events & EPOLLERR));
        assert(!(event->events & EPOLLHUP));
        assert(!(event->events & EPOLLET));
        assert(!(event->events & EPOLLONESHOT));
    }

    switch(op) {
    case EPOLL_CTL_ADD:
        // Add event/FD to events/FDs list
    {
        // Check that it's not already in the list
        /* for(struct _epoll_events_list *i = efd->events; i != NULL; i = i->next) { */
        /*     assert(i->fd != fd); */
        /* } */

        struct fdtab_entry *e = fdtab_get(fd);
        if(e->epoll_fd == epfd) {
            errno = EEXIST;
            ret = -1;
            break;
        }
        assert(e->epoll_fd == -1);
        e->epoll_fd = epfd;
        struct _epoll_events_list *li = &e->epoll_events;
        li->prev = NULL;
        li->next = efd->events;
        if(li->next != NULL) {
            li->next->prev = li;
        }
        li->event = *event;
        li->fd = fd;
        efd->events = li;
    }
    break;

    case EPOLL_CTL_DEL:
    {
#if 0
        struct _epoll_events_list *lasti = NULL, *i;
        for(i = efd->events; i != NULL; i = i->next) {
            if(i->fd == fd) {
                if(lasti == NULL) {
                    // First entry in list
                    efd->events = i->next;
                } else {
                    // Anywhere else
                    lasti->next = i->next;
                }

                free(i);

                struct fdtab_entry *e = fdtab_get(fd);
                assert(e->epoll_fd != -1);
                e->epoll_fd = -1;
                break;
            }

            lasti = i;
        }

        if(i == NULL) {
            errno = ENOENT;
            ret = -1;
        }
#else
        struct fdtab_entry *e = fdtab_get(fd);
        assert(e->epoll_fd != -1);
        e->epoll_fd = -1;
        if(&e->epoll_events == efd->events) {
            // First entry in list -- update head
            efd->events = e->epoll_events.next;
        }
        if(e->epoll_events.next != NULL) {
            e->epoll_events.next->prev = e->epoll_events.prev;
        }
        if(e->epoll_events.prev != NULL) {
            e->epoll_events.prev->next = e->epoll_events.next;
        }
#endif
    }
    break;

    case EPOLL_CTL_MOD:
    {
        struct _epoll_events_list *i;
        for(i = efd->events; i != NULL; i = i->next) {
            if(i->fd == fd) {
                // Found
                i->event = *event;
                break;
            }
        }

        if(i == NULL) {
            errno = ENOENT;
            ret = -1;
        }
    }
    break;

    default:
        errno = EINVAL;
        return -1;
    }

    return ret;
}
Example #19
0
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
    struct fdtab_entry *e = fdtab_get(sockfd);
    POSIXCOMPAT_DEBUG("%s:%s:%d: accept(sockfd=%d , e->type=%d)\n",
           __FILE__, __FUNCTION__, __LINE__, sockfd, e->type);

    switch(e->type) {
    case FDTAB_TYPE_UNIX_SOCKET:
        {
            struct _unix_socket *us = e->handle;
            int i;

            if(!us->passive) {
                return -1;
            }

            for(;;) {
                for(i = 0; i < us->u.passive.max_backlog; i++) {
                    if(us->u.passive.backlog[i] != NULL) {
                        break;
                    }
                }

                if(i != us->u.passive.max_backlog) {
                    // Found a pending connection
                    break;
                }

                if(us->nonblocking) {
                    errno = EAGAIN;
                    return -1;
                }

                // XXX: This should wait only on the monitor
                event_dispatch(get_default_waitset());
            }

            // XXX: Using socket() to create new socket. Probably dangerous.
            int newfd = socket(AF_UNIX, us->type, us->protocol);
            assert(newfd != -1);
            struct _unix_socket *newus = fdtab_get(newfd)->handle;
            newus->u.active.binding = us->u.passive.backlog[i];
            newus->u.active.mode = _UNIX_SOCKET_MODE_CONNECTED;
            memcpy(&newus->sockaddr, &us->sockaddr, sizeof(struct sockaddr_un));

            // Associate binding with new socket and remove from backlog
            assert(newus->u.active.binding->st == NULL);
            newus->u.active.binding->st = newus;
            us->u.passive.backlog[i] = NULL;

            if(addr != NULL) {
                assert(addrlen != NULL);

                // TODO: Should request address from peer (if peer is bound)

                if(*addrlen > sizeof(struct sockaddr_un)) {
                    *addrlen = sizeof(struct sockaddr_un);
                }

                memcpy(addr, &newus->peer, *addrlen);
            }

            return newfd;
        }

	case FDTAB_TYPE_LWIP_SOCKET:
            {
                lwip_mutex_lock();
                int newfd = lwip_accept(e->fd, addr, addrlen);
                lwip_mutex_unlock();

                if(newfd != -1) {
                    struct fdtab_entry newe;
                    newe.type = FDTAB_TYPE_LWIP_SOCKET;
                    newe.fd = newfd;
                    newe.inherited = false;
                    newe.epoll_fd = -1;

                    newfd = fdtab_alloc(&newe);
                    POSIXCOMPAT_DEBUG("accept(%d, _, _) as fd %d\n", sockfd, newfd);
                    if (newfd < 0) {
                        return -1;
                    }
                }

                return newfd;
            }

    default:
        return -1;
    }
}
Example #20
0
int epoll_wait(int epfd, struct epoll_event *events,
               int maxevents, int timeout)
{
    struct fdtab_entry *mye = fdtab_get(epfd);
    assert(mye->type == FDTAB_TYPE_EPOLL_INSTANCE);
    struct _epoll_fd *efd = mye->handle;
    struct monitor_binding *mb = get_monitor_binding();
    errval_t err;

    /* waitset_init(&efd->ws); */
    assert(maxevents >= 1);

    for(struct _epoll_events_list *i = efd->events; i != NULL; i = i->next) {
        struct fdtab_entry *e = fdtab_get(i->fd);
        struct epoll_event *event = &i->event;

        switch (e->type) {
        case FDTAB_TYPE_LWIP_SOCKET:
        {
            int retval;

            lwip_mutex_lock();
            if(event->events & EPOLLIN) {
                retval = lwip_sock_waitset_register_read(e->fd, &efd->ws);
                assert(retval == 0);
            }
            if(event->events & EPOLLOUT) {
                retval = lwip_sock_waitset_register_write(e->fd, &efd->ws);
                assert(retval == 0);
            }
            lwip_mutex_unlock();
        }
        break;

        case FDTAB_TYPE_UNIX_SOCKET:
        {
            struct _unix_socket *us = e->handle;

            if(event->events & EPOLLIN) {
                if (us->passive) { /* passive side */
                    int j;

                    /* Check for pending connection requests. */
                    for (j = 0; j < us->u.passive.max_backlog; j++)
                    {
                        if (us->u.passive.backlog[j] != NULL) {
                            break;
                        }
                    }

                    /*
                     * If there are not pending connection request
                     * wait on monitor binding.
                     */
                    if (j == us->u.passive.max_backlog) {
                        /* wait on monitor */
                        err = mb->change_waitset(mb, &efd->ws);
                        if (err_is_fail(err)) {
                            USER_PANIC_ERR(err, "change_waitset");
                        }
                    }
                }
            }

            if(event->events & EPOLLOUT) {
                assert(!us->passive);

                if(us->u.active.mode == _UNIX_SOCKET_MODE_CONNECTING) {
                    /* wait on monitor */
                    err = mb->change_waitset(mb, &efd->ws);
                    if (err_is_fail(err)) {
                        USER_PANIC_ERR(err, "change_waitset");
                    }
                }
            }

            assert(event->events & (EPOLLIN | EPOLLOUT));

            // Change waitset
            err = us->u.active.binding->change_waitset
                  (us->u.active.binding, &efd->ws);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "change waitset");
            }

        }
        break;

        default:
        {
            fprintf(stderr, "change waitset on FD type %d NYI.\n",
                    e->type);
            assert(!"NYI");
            errno = EBADF;
            return -1;
        }
        }
    }

    // Timeout handling
    struct timeout_event toe = {
        .fired = false
    };
    struct deferred_event timeout_event;
    if (timeout > 0) {
        deferred_event_init(&timeout_event);
        err = deferred_event_register(&timeout_event, &efd->ws, timeout,
                                      MKCLOSURE(timeout_fired, &toe));
        if (err_is_fail(err)) {
            errno = EINVAL;
            return -1;
        }
    }

    int retevents = 0;
    while(!toe.fired && retevents == 0) {
        if(timeout == 0) {
            // Just poll once, don't block
            err = event_dispatch_non_block(&efd->ws);
            assert(err_is_ok(err) || err_no(err) == LIB_ERR_NO_EVENT);
            toe.fired = true;
        } else {
            err = event_dispatch(&efd->ws);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "Error in event_dispatch.");
            }
        }

        // Return ready file descriptors
        for(struct _epoll_events_list *i = efd->events; i != NULL; i = i->next) {
            struct epoll_event *event = &i->event;
            struct fdtab_entry *e = fdtab_get(i->fd);

            assert(retevents < maxevents);
            events[retevents] = *event;
            events[retevents].events = 0;

            // Check errors (hangup)
            {
                switch (e->type) {
                case FDTAB_TYPE_LWIP_SOCKET:
                {
                    lwip_mutex_lock();
                    if (!lwip_sock_is_open(e->fd)) {
                        events[retevents].events |= EPOLLHUP;
                    }
                    lwip_mutex_unlock();
                }
                break;

                default:
                    // No-Op
                    break;
                }
            }

            // Check readable FDs
            if(event->events & EPOLLIN) {
                switch (e->type) {
                case FDTAB_TYPE_LWIP_SOCKET:
                {
                    lwip_mutex_lock();
                    if (lwip_sock_ready_read(e->fd)) {
                        events[retevents].events |= EPOLLIN;
                    }
                    lwip_mutex_unlock();
                }
                break;

                case FDTAB_TYPE_UNIX_SOCKET:
                {
                    struct _unix_socket *us = e->handle;

                    if (us->passive) { /* passive side */
                        /* Check for pending connection requests. */
                        for (int j = 0; j < us->u.passive.max_backlog; j++)
                        {
                            if (us->u.passive.backlog[j] != NULL) {
                                events[retevents].events |= EPOLLIN;
                                break;
                            }
                        }
                    } else { /* active side */
                        /* Check for incoming data. */
                        if (us->recv_buf_valid > 0) {
                            events[retevents].events |= EPOLLIN;
                        }
                    }
                }
                break;

                default:
                {
                    fprintf(stderr, "epoll_wait() on FD type %d NYI.\n",
                            e->type);
                    assert(!"NYI");
                    errno = EBADF;
                    return -1;
                }
                }
            }

            // Check writeable FDs
            if(event->events & EPOLLOUT) {
                switch (e->type) {
                case FDTAB_TYPE_LWIP_SOCKET:
                {
                    lwip_mutex_lock();
                    if (lwip_sock_ready_write(e->fd)) {
                        events[retevents].events |= EPOLLOUT;
                    }
                    lwip_mutex_unlock();
                }
                break;

                case FDTAB_TYPE_UNIX_SOCKET:
                {
                    struct _unix_socket *us = e->handle;
                    assert(!us->passive);

                    switch (us->u.active.mode) {
                    case _UNIX_SOCKET_MODE_CONNECTING:
                        break;

                    case _UNIX_SOCKET_MODE_CONNECTED:
                        if (us->send_buf == NULL) {
                            events[retevents].events |= EPOLLOUT;
                        }
                        break;
                    }
                }
                break;

                default:
                {
                    fprintf(stderr, "epoll_wait() on FD type %d NYI.\n",
                            e->type);
                    assert(!"NYI");
                    errno = EBADF;
                    return -1;
                }
                }
            }

            // If any events were returned, go to next entry in array
            if(events[retevents].events != 0) {
                retevents++;
            }
        }
    }

    // Remove timeout from waitset if it was set and not fired
    if(timeout > 0 && !toe.fired) {
        deferred_event_cancel(&timeout_event);
    }

    // Restore old waitsets
    for(struct _epoll_events_list *i = efd->events; i != NULL; i = i->next) {
        struct fdtab_entry *e = fdtab_get(i->fd);
        struct epoll_event *event = &i->event;

        switch (e->type) {
        case FDTAB_TYPE_LWIP_SOCKET:
        {
            lwip_mutex_lock();
            if(event->events & EPOLLIN) {
                err = lwip_sock_waitset_deregister_read(e->fd);
                if (err_is_fail(err) &&
                        err_no(err) != LIB_ERR_CHAN_NOT_REGISTERED) {
                    USER_PANIC_ERR(err, "error deregister read channel for "
                                   "lwip socket");
                }
            }
            if(event->events & EPOLLOUT) {
                err = lwip_sock_waitset_deregister_write(e->fd);
                if (err_is_fail(err) &&
                        err_no(err) != LIB_ERR_CHAN_NOT_REGISTERED) {
                    USER_PANIC_ERR(err, "error deregister write channel for "
                                   "lwip socket");
                }
            }
            lwip_mutex_unlock();
        }
        break;

        case FDTAB_TYPE_UNIX_SOCKET:
        {
            // NYI
        }
        break;

        default:
        {
            fprintf(stderr, "change waitset on FD type %d NYI.\n",
                    e->type);
            assert(!"NYI");
            errno = EBADF;
            return -1;
        }
        }
    }

    return retevents;
}

int epoll_pwait(int epfd, struct epoll_event *events,
                int maxevents, int timeout,
                const sigset_t *sigmask)
{
    assert(!"NYI");
}