summaryrefslogtreecommitdiffstats
path: root/server/usbredir.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/usbredir.c')
-rw-r--r--server/usbredir.c87
1 files changed, 49 insertions, 38 deletions
diff --git a/server/usbredir.c b/server/usbredir.c
index 096a381b..f6b0fe8b 100644
--- a/server/usbredir.c
+++ b/server/usbredir.c
@@ -38,6 +38,7 @@ typedef struct UsbRedirPipeItem {
typedef struct UsbRedirState {
Channel channel;
RedChannel *red_channel;
+ RedChannelClient *rcc;
SpiceCharDeviceState chardev_st;
SpiceCharDeviceInstance *chardev_sin;
UsbRedirPipeItem *pipe_item;
@@ -81,46 +82,46 @@ static void usbredir_chardev_wakeup(SpiceCharDeviceInstance *sin)
} while (n > 0);
}
-static int usbredir_red_channel_config_socket(RedChannel *red_channel)
+static int usbredir_red_channel_config_socket(RedChannelClient *rcc)
{
return TRUE;
}
-static void usbredir_red_channel_disconnect(RedChannel *red_channel)
+static void usbredir_red_channel_disconnect(RedChannelClient *rcc)
{
UsbRedirState *state;
SpiceCharDeviceInstance *sin;
SpiceCharDeviceInterface *sif;
- if (!red_channel) {
+ if (!rcc) {
return;
}
- state = SPICE_CONTAINEROF(red_channel, UsbRedirChannel, base)->state;
+ state = SPICE_CONTAINEROF(rcc->channel, UsbRedirChannel, base)->state;
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
- red_channel_destroy(red_channel);
- state->red_channel = NULL;
+ red_channel_client_destroy(rcc);
+ state->rcc = NULL;
if (sif->state) {
sif->state(sin, 0);
}
}
-static int usbredir_red_channel_handle_message(RedChannel *red_channel,
+static int usbredir_red_channel_client_handle_message(RedChannelClient *rcc,
SpiceDataHeader *header, uint8_t *msg)
{
UsbRedirState *state;
SpiceCharDeviceInstance *sin;
SpiceCharDeviceInterface *sif;
- state = SPICE_CONTAINEROF(red_channel, UsbRedirChannel, base)->state;
+ state = SPICE_CONTAINEROF(rcc->channel, UsbRedirChannel, base)->state;
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
if (header->type != SPICE_MSGC_USBREDIR_DATA) {
- return red_channel_handle_message(red_channel, header->size,
- header->type, msg);
+ return red_channel_client_handle_message(rcc, header->size,
+ header->type, msg);
}
/*
@@ -132,12 +133,12 @@ static int usbredir_red_channel_handle_message(RedChannel *red_channel,
return TRUE;
}
-static uint8_t *usbredir_red_channel_alloc_msg_rcv_buf(RedChannel *red_channel,
+static uint8_t *usbredir_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
SpiceDataHeader *msg_header)
{
UsbRedirState *state;
- state = SPICE_CONTAINEROF(red_channel, UsbRedirChannel, base)->state;
+ state = SPICE_CONTAINEROF(rcc->channel, UsbRedirChannel, base)->state;
if (msg_header->size > state->rcv_buf_size) {
state->rcv_buf = spice_realloc(state->rcv_buf, msg_header->size);
@@ -147,30 +148,30 @@ static uint8_t *usbredir_red_channel_alloc_msg_rcv_buf(RedChannel *red_channel,
return state->rcv_buf;
}
-static void usbredir_red_channel_release_msg_rcv_buf(RedChannel *red_channel,
+static void usbredir_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
SpiceDataHeader *msg_header, uint8_t *msg)
{
/* NOOP, we re-use the buffer every time and only free it on destruction */
}
-static void usbredir_red_channel_hold_pipe_item(RedChannel *red_channel,
+static void usbredir_red_channel_hold_pipe_item(RedChannelClient *rcc,
PipeItem *item)
{
/* NOOP */
}
-static void usbredir_red_channel_send_item(RedChannel *red_channel,
+static void usbredir_red_channel_send_item(RedChannelClient *rcc,
PipeItem *item)
{
UsbRedirPipeItem *i = SPICE_CONTAINEROF(item, UsbRedirPipeItem, base);
- SpiceMarshaller *m = red_channel_get_marshaller(red_channel);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
- red_channel_init_send_data(red_channel, SPICE_MSG_USBREDIR_DATA, item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_USBREDIR_DATA, item);
spice_marshaller_add_ref(m, i->buf, i->buf_used);
- red_channel_begin_send_message(red_channel);
+ red_channel_client_begin_send_message(rcc);
}
-static void usbredir_red_channel_release_pipe_item(RedChannel *red_channel,
+static void usbredir_red_channel_release_pipe_item(RedChannelClient *rcc,
PipeItem *item, int item_pushed)
{
free(item);
@@ -188,30 +189,38 @@ static void usbredir_link(Channel *channel, RedsStream *stream, int migration,
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
- if (state->red_channel) {
- WARN("channel %d:%d already connected, refusing second connection\n",
- channel->type, channel->id);
+ if (state->rcc) {
+ WARN("channel client %d:%d (%p) already connected, refusing second connection\n",
+ 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;
}
- state->red_channel = red_channel_create(sizeof(UsbRedirChannel),
- stream, core,
- migration, FALSE /* handle_acks */,
- usbredir_red_channel_config_socket,
- usbredir_red_channel_disconnect,
- usbredir_red_channel_handle_message,
- usbredir_red_channel_alloc_msg_rcv_buf,
- usbredir_red_channel_release_msg_rcv_buf,
- usbredir_red_channel_hold_pipe_item,
- usbredir_red_channel_send_item,
- usbredir_red_channel_release_pipe_item,
- NULL,
- NULL,
- NULL);
+ if (!state->red_channel) {
+ state->red_channel = red_channel_create(sizeof(UsbRedirChannel),
+ core, migration, FALSE /* handle_acks */,
+ usbredir_red_channel_config_socket,
+ usbredir_red_channel_disconnect,
+ usbredir_red_channel_client_handle_message,
+ usbredir_red_channel_alloc_msg_rcv_buf,
+ usbredir_red_channel_release_msg_rcv_buf,
+ usbredir_red_channel_hold_pipe_item,
+ usbredir_red_channel_send_item,
+ usbredir_red_channel_release_pipe_item,
+ NULL,
+ NULL,
+ NULL);
+ }
if (!state->red_channel) {
return;
}
+ state->rcc = red_channel_client_create(sizeof(RedChannelClient), state->red_channel, stream);
+ if (!state->rcc) {
+ red_printf("failed to create usbredir channel client\n");
+ return;
+ }
red_channel_init_outgoing_messages_window(state->red_channel);
redir_chan = SPICE_CONTAINEROF(state->red_channel, UsbRedirChannel, base);
redir_chan->state = state;
@@ -225,7 +234,9 @@ static void usbredir_shutdown(Channel *channel)
{
UsbRedirState *state = SPICE_CONTAINEROF(channel, UsbRedirState, channel);
- usbredir_red_channel_disconnect(state->red_channel);
+ usbredir_red_channel_disconnect(state->rcc);
+ red_channel_destroy(state->red_channel);
+ state->red_channel = NULL;
}
static void usbredir_migrate(Channel *channel)
@@ -264,7 +275,7 @@ void usbredir_device_disconnect(SpiceCharDeviceInstance *sin)
reds_unregister_channel(&state->channel);
- usbredir_red_channel_disconnect(state->red_channel);
+ usbredir_red_channel_disconnect(state->rcc);
free(state->pipe_item);
free(state->rcv_buf);