예제 #1
0
파일: test-stream.c 프로젝트: fgouget/spice
int main(int argc, char *argv[])
{
    RedsStream *st[2];
    int sv[2];
    int ret, fd = -1;
    char c;

    spice_return_val_if_fail(server_init() == 0, -1);

    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) == -1) {
        spice_error("socketpair failed %s", strerror(errno));
        return -1;
    }

    st[0] = reds_stream_new(server, sv[0]);
    spice_assert(reds_stream_is_plain_unix(st[0]));
    st[1] = reds_stream_new(server, sv[1]);
    spice_assert(reds_stream_is_plain_unix(st[1]));

    /* send stdin, for the fun of it */
    ret = reds_stream_send_msgfd(st[0], 0);
    spice_assert(ret == 1);
    ret = sock_fd_read(sv[1], &c, 1, &fd);
    spice_assert(c == '@');
    spice_assert(ret == 1);
    spice_assert(fd != -1);
    close(fd);

    /* send invalid fd behaviour */
    ret = reds_stream_send_msgfd(st[0], -1);
    spice_assert(ret == 1);
    ret = sock_fd_read(sv[1], &c, 1, &fd);
    spice_assert(c == '@');
    spice_assert(ret == 1);
    spice_assert(fd == -1);

    /* batch test */
    ret = reds_stream_send_msgfd(st[0], 0);
    spice_assert(ret == 1);
    ret = reds_stream_send_msgfd(st[0], 0);
    spice_assert(ret == 1);
    ret = sock_fd_read(sv[1], &c, 1, &fd);
    spice_assert(c == '@');
    spice_assert(ret == 1);
    spice_assert(fd != -1);
    close(fd);
    ret = sock_fd_read(sv[1], &c, 1, &fd);
    spice_assert(c == '@');
    spice_assert(ret == 1);
    spice_assert(fd != -1);
    close(fd);

    reds_stream_free(st[0]);
    reds_stream_free(st[1]);

    return 0;
}
예제 #2
0
파일: spicevmc.c 프로젝트: Fantu/spice
static void spicevmc_connect(RedChannel *channel, RedClient *client,
    RedsStream *stream, int migration, int num_common_caps,
    uint32_t *common_caps, int num_caps, uint32_t *caps)
{
    RedChannelClient *rcc;
    SpiceVmcState *state;
    SpiceCharDeviceInstance *sin;
    SpiceCharDeviceInterface *sif;

    state = SPICE_CONTAINEROF(channel, SpiceVmcState, channel);
    sin = state->chardev_sin;
    sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);

    if (state->rcc) {
        spice_printerr("channel client %d:%d (%p) already connected, refusing second connection",
                       channel->type, channel->id, state->rcc);
        // TODO: notify client in advance about the in use channel using
        // SPICE_MSG_MAIN_CHANNEL_IN_USE (for example)
        reds_stream_free(stream);
        return;
    }

    rcc = red_channel_client_create(sizeof(RedChannelClient), channel, client, stream,
                                    FALSE,
                                    num_common_caps, common_caps,
                                    num_caps, caps);
    if (!rcc) {
        return;
    }
    state->rcc = rcc;
    red_channel_client_ack_zero_messages_window(rcc);

    if (strcmp(sin->subtype, "port") == 0) {
        spicevmc_port_send_init(rcc);
    }

    if (!spice_char_device_client_add(state->chardev_st, client, FALSE, 0, ~0, ~0,
                                      red_channel_client_waits_for_migrate_data(rcc))) {
        spice_warning("failed to add client to spicevmc");
        red_channel_client_disconnect(rcc);
        return;
    }

    if (sif->state) {
        sif->state(sin, 1);
    }
}
예제 #3
0
static void snd_disconnect_channel(SndChannel *channel)
{
    SndWorker *worker;

    if (!channel) {
        spice_debug("not connected");
        return;
    }
    spice_debug("%p", channel);
    worker = channel->worker;
    if (channel->stream) {
        channel->cleanup(channel);
        red_channel_client_disconnect(worker->connection->channel_client);
        core->watch_remove(channel->stream->watch);
        channel->stream->watch = NULL;
        reds_stream_free(channel->stream);
        channel->stream = NULL;
        spice_marshaller_destroy(channel->send_data.marshaller);
    }
    snd_channel_put(channel);
    worker->connection = NULL;
}