示例#1
0
static void *
libev_ctx_add(void *ctx, const verto_ev *ev, verto_ev_flag *flags)
{
    ev_io *iow = NULL;
    ev_timer *timerw = NULL;
    ev_idle *idlew = NULL;
    ev_signal *signalw = NULL;
    ev_child *childw = NULL;
    ev_tstamp interval;
    int events = EV_NONE;

    *flags |= VERTO_EV_FLAG_PERSIST;
    switch (verto_get_type(ev)) {
        case VERTO_EV_TYPE_IO:
            if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ)
                events |= EV_READ;
            if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE)
                events |= EV_WRITE;
            setuptype(io, ev, libev_callback, verto_get_fd(ev), events);
        case VERTO_EV_TYPE_TIMEOUT:
            interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0;
            setuptype(timer, ev, libev_callback, interval, interval);
        case VERTO_EV_TYPE_IDLE:
            setuptype(idle, ev, libev_callback);
        case VERTO_EV_TYPE_SIGNAL:
            setuptype(signal, ev, libev_callback, verto_get_signal(ev));
        case VERTO_EV_TYPE_CHILD:
            *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */
            setuptype(child, ev, libev_callback, verto_get_proc(ev), 0);
        default:
            return NULL; /* Not supported */
    }
}
示例#2
0
static void *
libevent_ctx_add(void *ctx, const verto_ev *ev, verto_ev_flag *flags)
{
    struct event *priv = NULL;
    struct timeval *timeout = NULL;
    struct timeval tv;
    int libeventflags = 0;

    if (*flags & VERTO_EV_FLAG_PERSIST)
        libeventflags |= EV_PERSIST;

    switch (verto_get_type(ev)) {
    case VERTO_EV_TYPE_IO:
        if (*flags & VERTO_EV_FLAG_IO_READ)
            libeventflags |= EV_READ;
        if (*flags & VERTO_EV_FLAG_IO_WRITE)
            libeventflags |= EV_WRITE;
        priv = event_new(ctx, verto_get_fd(ev), libeventflags,
                         libevent_callback, (void *) ev);
        break;
    case VERTO_EV_TYPE_TIMEOUT:
        timeout = &tv;
        tv.tv_sec = verto_get_interval(ev) / 1000;
        tv.tv_usec = verto_get_interval(ev) % 1000 * 1000;
        priv = event_new(ctx, -1, EV_TIMEOUT | libeventflags,
                         libevent_callback, (void *) ev);
        break;
    case VERTO_EV_TYPE_SIGNAL:
        priv = event_new(ctx, verto_get_signal(ev),
                         EV_SIGNAL | libeventflags,
                         libevent_callback, (void *) ev);
        break;
    case VERTO_EV_TYPE_IDLE:
    case VERTO_EV_TYPE_CHILD:
    default:
        return NULL; /* Not supported */
    }

    if (!priv)
        return NULL;

    if (*flags & VERTO_EV_FLAG_PRIORITY_HIGH)
        event_priority_set(priv, 0);
    else if (*flags & VERTO_EV_FLAG_PRIORITY_MEDIUM)
        event_priority_set(priv, 1);
    else if (*flags & VERTO_EV_FLAG_PRIORITY_LOW)
        event_priority_set(priv, 2);

    event_add(priv, timeout);
    return priv;
}
示例#3
0
文件: read.c 项目: tlyu/libverto
static void
cb(verto_ctx *ctx, verto_ev *ev)
{
    unsigned char buff[DATALEN];
    int fd = 0;
    ssize_t bytes = 0;

    fd = verto_get_fd(ev);
    assert(fd == fds[0]);

    bytes = read(fd, buff, DATALEN);
    if (callcount++ == 0) {
        assert(bytes == DATALEN);
        close(fds[1]);
        fds[1] = -1;
    }
    else {
        assert(bytes != DATALEN);
        close(fd);
        fds[0] = -1;
        verto_del(ev);
        verto_break(ctx);
    }
}
示例#4
0
static verto_mod_ev *
glib_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags)
{
    verto_mod_ev *evpriv = NULL;
    verto_ev_type type = verto_get_type(ev);

    *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_PERSIST;
    *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_IO_CLOSE_FD;

    switch (type) {
        case VERTO_EV_TYPE_IO:
            evpriv = g_source_new(&funcs, sizeof(GIOSource));
            if (evpriv) {
                ((GIOSource*) evpriv)->fd.fd = verto_get_fd(ev);
                ((GIOSource*) evpriv)->autoclose =
                        *flags & VERTO_EV_FLAG_IO_CLOSE_FD;
                g_source_add_poll(evpriv, &((GIOSource*) evpriv)->fd);
            }
            break;
        case VERTO_EV_TYPE_TIMEOUT:
            evpriv = g_timeout_source_new(verto_get_interval(ev));
            break;
        case VERTO_EV_TYPE_IDLE:
            evpriv = g_idle_source_new();
            break;
        case VERTO_EV_TYPE_CHILD:
            evpriv = g_child_watch_source_new(verto_get_proc(ev));
            break;
        case VERTO_EV_TYPE_SIGNAL:
/* While glib has signal support in >=2.29, it does not support many
   common signals (like USR*). Therefore, signal support is disabled
   until they support them (should be soonish) */
#if GLIB_MAJOR_VERSION >= 999
#if GLIB_MINOR_VERSION >= 29
#ifdef G_OS_UNIX /* Not supported on Windows */
            evpriv = g_unix_signal_source_new(verto_get_signal(ev));
            break;
#endif
#endif /* GLIB_MINOR_VERSION >= 29 */
#endif /* GLIB_MAJOR_VERSION >= 2 */
        default:
            return NULL; /* Not supported */
    }

    if (!evpriv)
        goto error;

    if (type == VERTO_EV_TYPE_IO)
        g_source_set_callback(evpriv, (GSourceFunc) glib_callback_io,
                              (void *) ev, NULL);
    else if (type == VERTO_EV_TYPE_CHILD)
        g_source_set_callback(evpriv, (GSourceFunc) glib_callback_child,
                              (void *) ev, NULL);
    else
        g_source_set_callback(evpriv, glib_callback, (void *) ev, NULL);

    glib_ctx_set_flags(ctx, ev, evpriv);

    g_source_set_can_recurse(evpriv, FALSE);
    if (g_source_attach(evpriv, ctx->context) == 0)
        goto error;

    return evpriv;

    error:
        if (evpriv) {
            g_source_destroy(evpriv);
            g_source_unref(evpriv);
        }
        return NULL;
}
示例#5
0
static void *
glib_ctx_add(void *ctx, const verto_ev *ev, verto_ev_flag *flags)
{
    glib_ev *gev = NULL;
    GIOCondition cond = 0;
    verto_ev_type type = verto_get_type(ev);

    gev = g_new0(glib_ev, 1);
    if (!gev)
        return NULL;

    switch (type) {
        case VERTO_EV_TYPE_IO:
#ifdef WIN32
            gev->chan = g_io_channel_win32_new_socket(verto_get_fd(ev));
#else
            gev->chan = g_io_channel_unix_new(verto_get_fd(ev));
#endif
            if (!gev->chan)
                goto error;
            g_io_channel_set_close_on_unref(gev->chan, FALSE);

            if (*flags & VERTO_EV_FLAG_IO_READ)
                cond |= G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
            if (*flags & VERTO_EV_FLAG_IO_WRITE)
                cond |= G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
            gev->src = g_io_create_watch(gev->chan, cond);
            break;
        case VERTO_EV_TYPE_TIMEOUT:
            gev->src = g_timeout_source_new(verto_get_interval(ev));
            break;
        case VERTO_EV_TYPE_IDLE:
            gev->src = g_idle_source_new();
            break;
        case VERTO_EV_TYPE_CHILD:
            gev->src = g_child_watch_source_new(verto_get_proc(ev));
            *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */
            break;
        case VERTO_EV_TYPE_SIGNAL:
#if GLIB_MAJOR_VERSION >= 2
#if GLIB_MINOR_VERSION >= 29
#ifdef G_OS_UNIX /* Not supported on Windows */
            gev->src = g_unix_signal_source_new(verto_get_signal(ev));
            break;
#endif
#endif /* GLIB_MINOR_VERSION >= 29 */
#endif /* GLIB_MAJOR_VERSION >= 2 */
        default:
            return NULL; /* Not supported */
    }

    if (!gev->src)
        goto error;

    if (type == VERTO_EV_TYPE_IO)
        g_source_set_callback(gev->src, (GSourceFunc) glib_callback_io, (void *) ev, NULL);
    else if (type == VERTO_EV_TYPE_CHILD)
        g_source_set_callback(gev->src, (GSourceFunc) glib_callback_child, (void *) ev, NULL);
    else
        g_source_set_callback(gev->src, glib_callback, (void *) ev, NULL);

    if (*flags & VERTO_EV_FLAG_PRIORITY_HIGH)
        g_source_set_priority(gev->src, G_PRIORITY_HIGH);
    else if (*flags & VERTO_EV_FLAG_PRIORITY_MEDIUM)
        g_source_set_priority(gev->src, G_PRIORITY_DEFAULT_IDLE);
    else if (*flags & VERTO_EV_FLAG_PRIORITY_LOW)
        g_source_set_priority(gev->src, G_PRIORITY_LOW);

    g_source_set_can_recurse(gev->src, FALSE);
    if (g_source_attach(gev->src, ((glib_ev_ctx*) ctx)->context) == 0)
        goto error;

    return gev;

    error:
        if (gev) {
            if (gev->chan)
                g_io_channel_unref(gev->chan);
            if (gev->src) {
                g_source_destroy(gev->src);
                g_source_unref(gev->src);
            }
            g_free(gev);
        }
        return NULL;
}
示例#6
0
void accept_sock_conn(verto_ctx *vctx, verto_ev *ev)
{
    struct gp_conn *conn = NULL;
    int listen_fd;
    int fd = -1;
    int ret;

    conn = calloc(1, sizeof(struct gp_conn));
    if (!conn) {
        ret = ENOMEM;
        goto done;
    }
    conn->sock_ctx = verto_get_private(ev);
    conn->us.sd = -1;

    listen_fd = verto_get_fd(ev);
    fd = accept(listen_fd,
                (struct sockaddr *)&conn->us.sock_addr,
                &conn->us.sock_addr_len);
    if (fd == -1) {
        ret = errno;
        if (ret == EINTR) {
            /* let the event loop retry later */
            return;
        }
        goto done;
    }
    conn->us.sd = fd;

    ret = set_status_flags(fd, O_NONBLOCK);
    if (ret) {
        GPDEBUG("Failed to set O_NONBLOCK on %d!\n", fd);
        goto done;
    }

    ret = set_fd_flags(fd, FD_CLOEXEC);
    if (ret) {
        GPDEBUG("Failed to set FD_CLOEXEC on %d!\n", fd);
        goto done;
    }

    ret = get_peercred(fd, conn);
    if (ret) {
        goto done;
    }

    GPDEBUG("Client connected (fd = %d)", fd);
    if (conn->creds.type & CRED_TYPE_UNIX) {
        GPDEBUG(" (pid = %d) (uid = %d) (gid = %d)",
                conn->creds.ucred.pid,
                conn->creds.ucred.uid,
                conn->creds.ucred.gid);
    }
    if (conn->creds.type & CRED_TYPE_SELINUX) {
        GPDEBUG(" (context = %s)",
                SELINUX_context_str(conn->selinux_ctx));
    }
    GPDEBUG("\n");

    gp_setup_reader(vctx, conn);

    ret = 0;

done:
    if (ret) {
        GPERROR("Error connecting client: (%d:%s)",
                ret, gp_strerror(ret));
        gp_conn_free(conn);
    }
}
示例#7
0
static void gp_socket_write(verto_ctx *vctx, verto_ev *ev)
{
    struct gp_buffer *wbuf;
    struct iovec iov[2];
    uint32_t size;
    ssize_t wn;
    int vecs;
    int fd;

    fd = verto_get_fd(ev);
    wbuf = verto_get_private(ev);

    vecs = 0;

    if (wbuf->pos == 0) {
        /* first write, send the buffer size as packet header */
        size = wbuf->size | FRAGMENT_BIT;
        size = htonl(size);

        iov[0].iov_base = &size;
        iov[0].iov_len = sizeof(size);
        vecs = 1;
    }

    iov[vecs].iov_base = wbuf->data + wbuf->pos;
    iov[vecs].iov_len = wbuf->size - wbuf->pos;
    vecs++;

    errno = 0;
    wn = writev(fd, iov, vecs);
    if (wn == -1) {
        if (errno == EAGAIN || errno == EINTR) {
            /* try again later */
            gp_socket_schedule_write(vctx, wbuf);
        } else {
            /* error on socket, close and release it */
            gp_conn_free(wbuf->conn);
            gp_buffer_free(wbuf);
        }
        return;
    }
    if (vecs == 2) {
        if (wn < sizeof(size)) {
            /* don't bother trying to handle sockets that can't
             * buffer even 4 bytes */
            gp_conn_free(wbuf->conn);
            gp_buffer_free(wbuf);
            return;
        }
        wn -= sizeof(size);
    }

    wbuf->pos += wn;
    if (wbuf->size > wbuf->pos) {
        /* short write, reschedule */
        gp_socket_schedule_write(vctx, wbuf);
    } else {
        /* now setup again the reader */
        gp_setup_reader(vctx, wbuf->conn);
        /* all done, free write context */
        gp_buffer_free(wbuf);
    }
}
示例#8
0
static void gp_socket_read(verto_ctx *vctx, verto_ev *ev)
{
    struct gp_buffer *rbuf;
    uint32_t size;
    bool header = false;
    size_t rn;
    int ret;
    int fd;

    fd = verto_get_fd(ev);
    rbuf = verto_get_private(ev);

    if (rbuf->data == NULL) {
        header = true;
        /* new connection, need to read length first */
        rn = read(fd, &size, sizeof(uint32_t));
        if (rn == -1) {
            if (errno == EAGAIN || errno == EINTR) {
                /* spin again */
                ret = EAGAIN;
            } else {
                ret = EIO;
            }
            goto done;
        }
        if (rn != sizeof(uint32_t)) {
            /* client closed,
             * or we didn't get even 4 bytes,
             * close conn, not worth trying 1 byte reads at this time */
            ret = EIO;
            goto done;
        }

        /* allocate buffer for receiving data */
        rbuf->size = ntohl(size);

        /* FIXME: need to support multiple fragments */
        /* for now just make sure we have the last fragment bit
         * then remove it */
        if (rbuf->size & FRAGMENT_BIT) {
            rbuf->size &= ~FRAGMENT_BIT;
        } else {
            ret = EIO;
            goto done;
        }

        if (rbuf->size > MAX_RPC_SIZE) {
            /* req too big close conn. */
            ret = EIO;
            goto done;
        }

        rbuf->data = malloc(rbuf->size);
        if (!rbuf->data) {
            ret = ENOMEM;
            goto done;
        }
    }

    errno = 0;
    rn = read(fd, rbuf->data + rbuf->pos, rbuf->size - rbuf->pos);
    if (rn == -1) {
        if (errno == EAGAIN || errno == EINTR) {
            /* spin again */
            ret = EAGAIN;
        } else {
            ret = EIO;
        }
        goto done;
    }

    if (rn == 0) {
        if (!header) {
            /* client closed before the buffer was fully read */
            ret = EIO;
        } else {
            ret = EAGAIN;
        }
        goto done;
    }

    rbuf->pos += rn;

    if (rbuf->pos == rbuf->size) {
        /* got all data, hand over packet */
        ret = gp_query_new(rbuf->conn->sock_ctx->gpctx->workers, rbuf->conn,
                           rbuf->data, rbuf->size);
        if (ret != 0) {
            /* internal error, not much we can do */
            goto done;
        }

        /* we successfully handed over the data */
        rbuf->data = NULL;
        gp_buffer_free(rbuf);
        return;
    }

    ret = EAGAIN;

done:
    switch (ret) {
    case EAGAIN:
        gp_socket_schedule_read(vctx, rbuf);
        return;
    default:
        gp_conn_free(rbuf->conn);
        gp_buffer_free(rbuf);
    }
}