/* coroutine context */ G_GNUC_INTERNAL void spice_channel_handle_migrate(SpiceChannel *channel, spice_msg_in *in) { spice_msg_out *out; spice_msg_in *data = NULL; SpiceMsgMigrate *mig = spice_msg_in_parsed(in); spice_channel *c = channel->priv; SPICE_DEBUG("%s: channel %s flags %u", __FUNCTION__, c->name, mig->flags); if (mig->flags & SPICE_MIGRATE_NEED_FLUSH) { /* iterate_write is blocking and flushing all pending write */ SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel); out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MIGRATE_FLUSH_MARK); spice_msg_out_send_internal(out); spice_msg_out_unref(out); SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel); } if (mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) { spice_channel_recv_msg(channel, get_msg_handler, &data); if (!data || data->header.type != SPICE_MSG_MIGRATE_DATA) { g_warning("expected SPICE_MSG_MIGRATE_DATA, got %d", data->header.type); } } spice_session_channel_migrate(c->session, channel); if (mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) { out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MIGRATE_DATA); spice_marshaller_add(out->marshaller, data->data, data->header.size); spice_msg_out_send_internal(out); spice_msg_out_unref(out); } }
/* coroutine context */ G_GNUC_INTERNAL void spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in) { SpiceMsgOut *out; SpiceMsgIn *data = NULL; SpiceMsgMigrate *mig = spice_msg_in_parsed(in); SpiceChannelPrivate *c = channel->priv; g_message("spice_channel_handle_migrate.\n"); CHANNEL_DEBUG(channel, "%s: flags %u", __FUNCTION__, mig->flags); if (mig->flags & SPICE_MIGRATE_NEED_FLUSH) { g_message("++++++++++++ SPICE_MIGRATE_NEED_FLUSH.\n"); /* if peer version > 1: pushing the mark msg before all other messgages and sending it, * and only it */ if (c->peer_hdr.major_version == 1) { /* iterate_write is blocking and flushing all pending write */ SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel); } out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MIGRATE_FLUSH_MARK); spice_msg_out_send_internal(out); } if (mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) { g_message("+++++++++++ SPICE_MIGRATE_NEED_DATA_TRANSFER.\n"); spice_channel_recv_msg(channel, get_msg_handler, &data); if (!data) { g_critical("expected SPICE_MSG_MIGRATE_DATA, got empty message"); goto end; } else if (spice_header_get_msg_type(data->header, c->use_mini_header) != SPICE_MSG_MIGRATE_DATA) { g_critical("expected SPICE_MSG_MIGRATE_DATA, got %d", spice_header_get_msg_type(data->header, c->use_mini_header)); goto end; } } /* swapping channels sockets */ spice_session_channel_migrate(c->session, channel); /* pushing the MIGRATE_DATA before all other pending messages */ if ((mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) && (data != NULL)) { out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MIGRATE_DATA); spice_marshaller_add(out->marshaller, data->data, spice_header_get_msg_size(data->header, c->use_mini_header)); spice_msg_out_send_internal(out); } end: if (data) spice_msg_in_unref(data); }
/* coroutine context */ static void spice_channel_iterate_read(SpiceChannel *channel) { spice_channel *c = channel->priv; /* TODO: get rid of state, and use coroutine state */ switch (c->state) { case SPICE_CHANNEL_STATE_LINK_HDR: spice_channel_recv_link_hdr(channel); break; case SPICE_CHANNEL_STATE_LINK_MSG: spice_channel_recv_link_msg(channel); break; case SPICE_CHANNEL_STATE_AUTH: spice_channel_recv_auth(channel); break; case SPICE_CHANNEL_STATE_READY: spice_channel_recv_msg(channel, (handler_msg_in)SPICE_CHANNEL_GET_CLASS(channel)->handle_msg, NULL); break; default: g_critical("unknown state %d", c->state); } }