/* 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);
    }
}
Example #2
0
/* 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);
}