Commit deaeb3f7 authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Samuel Thibault
Browse files

slirp: use polling callbacks, drop glib requirement



It would be legitimate to use libslirp without glib. Let's
add_poll/get_revents pair of callbacks to provide the same
functionality.

Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
parent 6e513a78
Loading
Loading
Loading
Loading
+69 −3
Original line number Diff line number Diff line
@@ -211,6 +211,71 @@ static const SlirpCb slirp_cb = {
    .notify = qemu_notify_event,
};

static int slirp_poll_to_gio(int events)
{
    int ret = 0;

    if (events & SLIRP_POLL_IN) {
        ret |= G_IO_IN;
    }
    if (events & SLIRP_POLL_OUT) {
        ret |= G_IO_OUT;
    }
    if (events & SLIRP_POLL_PRI) {
        ret |= G_IO_PRI;
    }
    if (events & SLIRP_POLL_ERR) {
        ret |= G_IO_ERR;
    }
    if (events & SLIRP_POLL_HUP) {
        ret |= G_IO_HUP;
    }

    return ret;
}

static int net_slirp_add_poll(int fd, int events, void *opaque)
{
    GArray *pollfds = opaque;
    GPollFD pfd = {
        .fd = fd,
        .events = slirp_poll_to_gio(events),
    };
    int idx = pollfds->len;
    g_array_append_val(pollfds, pfd);
    return idx;
}

static int slirp_gio_to_poll(int events)
{
    int ret = 0;

    if (events & G_IO_IN) {
        ret |= SLIRP_POLL_IN;
    }
    if (events & G_IO_OUT) {
        ret |= SLIRP_POLL_OUT;
    }
    if (events & G_IO_PRI) {
        ret |= SLIRP_POLL_PRI;
    }
    if (events & G_IO_ERR) {
        ret |= SLIRP_POLL_ERR;
    }
    if (events & G_IO_HUP) {
        ret |= SLIRP_POLL_HUP;
    }

    return ret;
}

static int net_slirp_get_revents(int idx, void *opaque)
{
    GArray *pollfds = opaque;

    return slirp_gio_to_poll(g_array_index(pollfds, GPollFD, idx).revents);
}

static void net_slirp_poll_notify(Notifier *notifier, void *data)
{
    MainLoopPoll *poll = data;
@@ -218,12 +283,13 @@ static void net_slirp_poll_notify(Notifier *notifier, void *data)

    switch (poll->state) {
    case MAIN_LOOP_POLL_FILL:
        slirp_pollfds_fill(s->slirp, poll->pollfds, &poll->timeout);
        slirp_pollfds_fill(s->slirp, &poll->timeout,
                           net_slirp_add_poll, poll->pollfds);
        break;
    case MAIN_LOOP_POLL_OK:
    case MAIN_LOOP_POLL_ERR:
        slirp_pollfds_poll(s->slirp, poll->pollfds,
                           poll->state == MAIN_LOOP_POLL_ERR);
        slirp_pollfds_poll(s->slirp, poll->state == MAIN_LOOP_POLL_ERR,
                           net_slirp_get_revents, poll->pollfds);
        break;
    default:
        g_assert_not_reached();
+14 −3
Original line number Diff line number Diff line
#ifndef LIBSLIRP_H
#define LIBSLIRP_H

#include <glib.h>
#include <stdint.h>
#include <stdbool.h>

@@ -15,8 +14,18 @@

typedef struct Slirp Slirp;

enum {
    SLIRP_POLL_IN  = 1 << 0,
    SLIRP_POLL_OUT = 1 << 1,
    SLIRP_POLL_PRI = 1 << 2,
    SLIRP_POLL_ERR = 1 << 3,
    SLIRP_POLL_HUP = 1 << 4,
};

typedef ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
typedef void (*SlirpTimerCb)(void *opaque);
typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque);
typedef int (*SlirpGetREventsCb)(int idx, void *opaque);

/*
 * Callbacks from slirp
@@ -63,9 +72,11 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                  void *opaque);
void slirp_cleanup(Slirp *slirp);

void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout);
void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
                        SlirpAddPollCb add_poll, void *opaque);

void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error);
void slirp_pollfds_poll(Slirp *slirp, int select_error,
                        SlirpGetREventsCb get_revents, void *opaque);

void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);

+26 −46
Original line number Diff line number Diff line
@@ -386,7 +386,8 @@ static void slirp_update_timeout(Slirp *slirp, uint32_t *timeout)
    *timeout = t;
}

void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout)
void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
                        SlirpAddPollCb add_poll, void *opaque)
{
    struct socket *so, *so_next;

@@ -428,12 +429,8 @@ void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout)
         * Set for reading sockets which are accepting
         */
        if (so->so_state & SS_FACCEPTCONN) {
            GPollFD pfd = {
                .fd = so->s,
                .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
            };
            so->pollfds_idx = pollfds->len;
            g_array_append_val(pollfds, pfd);
            so->pollfds_idx = add_poll(so->s,
                SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
            continue;
        }

@@ -441,12 +438,8 @@ void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout)
         * Set for writing sockets which are connecting
         */
        if (so->so_state & SS_ISFCONNECTING) {
            GPollFD pfd = {
                .fd = so->s,
                .events = G_IO_OUT | G_IO_ERR,
            };
            so->pollfds_idx = pollfds->len;
            g_array_append_val(pollfds, pfd);
            so->pollfds_idx = add_poll(so->s,
                SLIRP_POLL_OUT | SLIRP_POLL_ERR, opaque);
            continue;
        }

@@ -455,7 +448,7 @@ void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout)
         * we have something to send
         */
        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
            events |= G_IO_OUT | G_IO_ERR;
            events |= SLIRP_POLL_OUT | SLIRP_POLL_ERR;
        }

        /*
@@ -464,16 +457,12 @@ void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout)
         */
        if (CONN_CANFRCV(so) &&
            (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
            events |= G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI;
            events |= SLIRP_POLL_IN | SLIRP_POLL_HUP |
                      SLIRP_POLL_ERR | SLIRP_POLL_PRI;
        }

        if (events) {
            GPollFD pfd = {
                .fd = so->s,
                .events = events,
            };
            so->pollfds_idx = pollfds->len;
            g_array_append_val(pollfds, pfd);
            so->pollfds_idx = add_poll(so->s, events, opaque);
        }
    }

@@ -508,12 +497,8 @@ void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout)
         * (XXX <= 4 ?)
         */
        if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
            GPollFD pfd = {
                .fd = so->s,
                .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
            };
            so->pollfds_idx = pollfds->len;
            g_array_append_val(pollfds, pfd);
            so->pollfds_idx = add_poll(so->s,
                SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
        }
    }

@@ -538,19 +523,16 @@ void slirp_pollfds_fill(Slirp *slirp, GArray *pollfds, uint32_t *timeout)
        }

        if (so->so_state & SS_ISFCONNECTED) {
            GPollFD pfd = {
                .fd = so->s,
                .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
            };
            so->pollfds_idx = pollfds->len;
            g_array_append_val(pollfds, pfd);
            so->pollfds_idx = add_poll(so->s,
                SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
        }
    }

    slirp_update_timeout(slirp, timeout);
}

void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error)
void slirp_pollfds_poll(Slirp *slirp, int select_error,
                        SlirpGetREventsCb get_revents, void *opaque)
{
    struct socket *so, *so_next;
    int ret;
@@ -587,8 +569,7 @@ void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error)

            revents = 0;
            if (so->pollfds_idx != -1) {
                revents = g_array_index(pollfds, GPollFD,
                                        so->pollfds_idx).revents;
                revents = get_revents(so->pollfds_idx, opaque);
            }

            if (so->so_state & SS_NOFDREF || so->s == -1) {
@@ -598,9 +579,9 @@ void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error)
            /*
             * Check for URG data
             * This will soread as well, so no need to
             * test for G_IO_IN below if this succeeds
             * test for SLIRP_POLL_IN below if this succeeds
             */
            if (revents & G_IO_PRI) {
            if (revents & SLIRP_POLL_PRI) {
                ret = sorecvoob(so);
                if (ret < 0) {
                    /* Socket error might have resulted in the socket being
@@ -611,7 +592,8 @@ void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error)
            /*
             * Check sockets for reading
             */
            else if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) {
            else if (revents &
                     (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR)) {
                /*
                 * Check for incoming connections
                 */
@@ -636,7 +618,7 @@ void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error)
             * Check sockets for writing
             */
            if (!(so->so_state & SS_NOFDREF) &&
                (revents & (G_IO_OUT | G_IO_ERR))) {
                (revents & (SLIRP_POLL_OUT | SLIRP_POLL_ERR))) {
                /*
                 * Check for non-blocking, still-connecting sockets
                 */
@@ -689,12 +671,11 @@ void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error)

            revents = 0;
            if (so->pollfds_idx != -1) {
                revents = g_array_index(pollfds, GPollFD,
                                        so->pollfds_idx).revents;
                revents = get_revents(so->pollfds_idx, opaque);
            }

            if (so->s != -1 &&
                (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
                (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
                sorecvfrom(so);
            }
        }
@@ -710,12 +691,11 @@ void slirp_pollfds_poll(Slirp *slirp, GArray *pollfds, int select_error)

            revents = 0;
            if (so->pollfds_idx != -1) {
                revents = g_array_index(pollfds, GPollFD,
                                        so->pollfds_idx).revents;
                revents = get_revents(so->pollfds_idx, opaque);
            }

            if (so->s != -1 &&
                (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
                (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
                icmp_receive(so);
            }
        }