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; }
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); } }
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; }