Example #1
0
static void smartcard_init(void)
{
    ChannelCbs channel_cbs = { NULL, };
    ClientCbs client_cbs = { NULL, };
    uint32_t migration_flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;

    spice_assert(!g_smartcard_channel);

    channel_cbs.config_socket = smartcard_channel_client_config_socket;
    channel_cbs.on_disconnect = smartcard_channel_on_disconnect;
    channel_cbs.send_item = smartcard_channel_send_item;
    channel_cbs.hold_item = smartcard_channel_hold_pipe_item;
    channel_cbs.release_item = smartcard_channel_release_pipe_item;
    channel_cbs.alloc_recv_buf = smartcard_channel_alloc_msg_rcv_buf;
    channel_cbs.release_recv_buf = smartcard_channel_release_msg_rcv_buf;
    channel_cbs.handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark;
    channel_cbs.handle_migrate_data = smartcard_channel_client_handle_migrate_data;

    g_smartcard_channel = (SmartCardChannel*)red_channel_create(sizeof(SmartCardChannel),
                                             core, SPICE_CHANNEL_SMARTCARD, 0,
                                             FALSE /* handle_acks */,
                                             smartcard_channel_handle_message,
                                             &channel_cbs,
                                             migration_flags);

    if (!g_smartcard_channel) {
        spice_error("failed to allocate Smartcard Channel");
    }

    client_cbs.connect = smartcard_connect_client;
    red_channel_register_client_cbs(&g_smartcard_channel->base, &client_cbs);

    reds_register_channel(&g_smartcard_channel->base);
}
Example #2
0
SpiceCharDeviceState *spicevmc_device_connect(SpiceCharDeviceInstance *sin,
                                              uint8_t channel_type)
{
    static uint8_t id[256] = { 0, };
    SpiceVmcState *state;
    ChannelCbs channel_cbs = { NULL, };
    ClientCbs client_cbs = { NULL, };
    SpiceCharDeviceCallbacks char_dev_cbs = {NULL, };

    channel_cbs.config_socket = spicevmc_red_channel_client_config_socket;
    channel_cbs.on_disconnect = spicevmc_red_channel_client_on_disconnect;
    channel_cbs.send_item = spicevmc_red_channel_send_item;
    channel_cbs.hold_item = spicevmc_red_channel_hold_pipe_item;
    channel_cbs.release_item = spicevmc_red_channel_release_pipe_item;
    channel_cbs.alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf;
    channel_cbs.release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf;
    channel_cbs.handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark;
    channel_cbs.handle_migrate_data = spicevmc_channel_client_handle_migrate_data;

    state = (SpiceVmcState*)red_channel_create(sizeof(SpiceVmcState),
                                   core, channel_type, id[channel_type]++,
                                   FALSE /* handle_acks */,
                                   spicevmc_red_channel_client_handle_message,
                                   &channel_cbs,
                                   SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER);
    red_channel_init_outgoing_messages_window(&state->channel);

    client_cbs.connect = spicevmc_connect;
    red_channel_register_client_cbs(&state->channel, &client_cbs);

    char_dev_cbs.read_one_msg_from_device = spicevmc_chardev_read_msg_from_dev;
    char_dev_cbs.ref_msg_to_client = spicevmc_chardev_ref_msg_to_client;
    char_dev_cbs.unref_msg_to_client = spicevmc_chardev_unref_msg_to_client;
    char_dev_cbs.send_msg_to_client = spicevmc_chardev_send_msg_to_client;
    char_dev_cbs.send_tokens_to_client = spicevmc_char_dev_send_tokens_to_client;
    char_dev_cbs.remove_client = spicevmc_char_dev_remove_client;

    state->chardev_st = spice_char_device_state_create(sin,
                                                       0, /* tokens interval */
                                                       ~0, /* self tokens */
                                                       &char_dev_cbs,
                                                       state);
    state->chardev_sin = sin;

    reds_register_channel(&state->channel);
    return state->chardev_st;
}
Example #3
0
RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
{
    RedDispatcher *red_dispatcher;
    RedWorkerMessage message;
    WorkerInitData init_data;
    QXLDevInitInfo init_info;
    int r;
    RedChannel *display_channel;
    RedChannel *cursor_channel;
    sigset_t thread_sig_mask;
    sigset_t curr_sig_mask;
    ClientCbs client_cbs = { NULL, };

    quic_init();
    sw_canvas_init();
#ifdef USE_OPENGL
    gl_canvas_init();
#endif // USE_OPENGL

    red_dispatcher = spice_new0(RedDispatcher, 1);
    ring_init(&red_dispatcher->async_commands);
    spice_debug("red_dispatcher->async_commands.next %p", red_dispatcher->async_commands.next);
    dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL);
    init_data.qxl = red_dispatcher->qxl = qxl;
    init_data.id = qxl->id;
    init_data.red_dispatcher = red_dispatcher;
    init_data.pending = &red_dispatcher->pending;
    init_data.num_renderers = num_renderers;
    memcpy(init_data.renderers, renderers, sizeof(init_data.renderers));

    pthread_mutex_init(&red_dispatcher->async_lock, NULL);
    init_data.image_compression = image_compression;
    init_data.jpeg_state = jpeg_state;
    init_data.zlib_glz_state = zlib_glz_state;
    init_data.streaming_video = streaming_video;

    red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR;
    red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR;
    red_dispatcher->base.wakeup = qxl_worker_wakeup;
    red_dispatcher->base.oom = qxl_worker_oom;
    red_dispatcher->base.start = qxl_worker_start;
    red_dispatcher->base.stop = qxl_worker_stop;
    red_dispatcher->base.update_area = qxl_worker_update_area;
    red_dispatcher->base.add_memslot = qxl_worker_add_memslot;
    red_dispatcher->base.del_memslot = qxl_worker_del_memslot;
    red_dispatcher->base.reset_memslots = qxl_worker_reset_memslots;
    red_dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces;
    red_dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface;
    red_dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface;

    red_dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache;
    red_dispatcher->base.reset_cursor = qxl_worker_reset_cursor;
    red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait;
    red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands;

    qxl->st->qif->get_init_info(qxl, &init_info);

    init_data.memslot_id_bits = init_info.memslot_id_bits;
    init_data.memslot_gen_bits = init_info.memslot_gen_bits;
    init_data.num_memslots = init_info.num_memslots;
    init_data.num_memslots_groups = init_info.num_memslots_groups;
    init_data.internal_groupslot_id = init_info.internal_groupslot_id;
    init_data.n_surfaces = init_info.n_surfaces;

    num_active_workers = 1;

    sigfillset(&thread_sig_mask);
    sigdelset(&thread_sig_mask, SIGILL);
    sigdelset(&thread_sig_mask, SIGFPE);
    sigdelset(&thread_sig_mask, SIGSEGV);
    pthread_sigmask(SIG_SETMASK, &thread_sig_mask, &curr_sig_mask);
    if ((r = pthread_create(&red_dispatcher->worker_thread, NULL, red_worker_main, &init_data))) {
        spice_error("create thread failed %d", r);
    }
    pthread_sigmask(SIG_SETMASK, &curr_sig_mask, NULL);

    read_message(red_dispatcher->dispatcher.send_fd, &message);
    spice_assert(message == RED_WORKER_MESSAGE_READY);

    display_channel = red_dispatcher_display_channel_create(red_dispatcher);

    if (display_channel) {
        client_cbs.connect = red_dispatcher_set_display_peer;
        client_cbs.disconnect = red_dispatcher_disconnect_display_peer;
        client_cbs.migrate = red_dispatcher_display_migrate;
        red_channel_register_client_cbs(display_channel, &client_cbs);
        red_channel_set_data(display_channel, red_dispatcher);
        red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
        reds_register_channel(display_channel);
    }

    cursor_channel = red_dispatcher_cursor_channel_create(red_dispatcher);

    if (cursor_channel) {
        client_cbs.connect = red_dispatcher_set_cursor_peer;
        client_cbs.disconnect = red_dispatcher_disconnect_cursor_peer;
        client_cbs.migrate = red_dispatcher_cursor_migrate;
        red_channel_register_client_cbs(cursor_channel, &client_cbs);
        red_channel_set_data(cursor_channel, red_dispatcher);
        reds_register_channel(cursor_channel);
    }

    qxl->st->qif->attache_worker(qxl, &red_dispatcher->base);
    qxl->st->qif->set_compression_level(qxl, calc_compression_level());

    red_dispatcher->next = dispatchers;
    dispatchers = red_dispatcher;
    return red_dispatcher;
}