mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-09 05:51:00 +00:00
Move CommonGraphicsChannel to a new file
Move out of red-worker.c. This requires a little bit of minor refactoring to avoid accessing some RedWorker internals in the constructor function, etc. Acked-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
parent
c5758b6890
commit
bcb8503659
@ -77,6 +77,8 @@ libserver_la_SOURCES = \
|
||||
cache-item.h \
|
||||
char-device.c \
|
||||
char-device.h \
|
||||
common-graphics-channel.c \
|
||||
common-graphics-channel.h \
|
||||
demarshallers.h \
|
||||
event-loop.c \
|
||||
glz-encoder.c \
|
||||
|
||||
129
server/common-graphics-channel.c
Normal file
129
server/common-graphics-channel.c
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
Copyright (C) 2009-2016 Red Hat, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include "common-graphics-channel.h"
|
||||
#include "dcc.h"
|
||||
#include "main-channel-client.h"
|
||||
|
||||
static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
|
||||
{
|
||||
RedChannel *channel = red_channel_client_get_channel(rcc);
|
||||
CommonGraphicsChannel *common = SPICE_CONTAINEROF(channel, CommonGraphicsChannel, base);
|
||||
|
||||
/* SPICE_MSGC_MIGRATE_DATA is the only client message whose size is dynamic */
|
||||
if (type == SPICE_MSGC_MIGRATE_DATA) {
|
||||
return spice_malloc(size);
|
||||
}
|
||||
|
||||
if (size > CHANNEL_RECEIVE_BUF_SIZE) {
|
||||
spice_critical("unexpected message size %u (max is %d)", size, CHANNEL_RECEIVE_BUF_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
return common->recv_buf;
|
||||
}
|
||||
|
||||
static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
|
||||
uint8_t* msg)
|
||||
{
|
||||
if (type == SPICE_MSGC_MIGRATE_DATA) {
|
||||
free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int common_channel_config_socket(RedChannelClient *rcc)
|
||||
{
|
||||
RedClient *client = red_channel_client_get_client(rcc);
|
||||
MainChannelClient *mcc = red_client_get_main(client);
|
||||
RedsStream *stream = red_channel_client_get_stream(rcc);
|
||||
int flags;
|
||||
int delay_val;
|
||||
gboolean is_low_bandwidth;
|
||||
|
||||
if ((flags = fcntl(stream->socket, F_GETFL)) == -1) {
|
||||
spice_warning("accept failed, %s", strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (fcntl(stream->socket, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
spice_warning("accept failed, %s", strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// TODO - this should be dynamic, not one time at channel creation
|
||||
is_low_bandwidth = main_channel_client_is_low_bandwidth(mcc);
|
||||
delay_val = is_low_bandwidth ? 0 : 1;
|
||||
/* FIXME: Using Nagle's Algorithm can lead to apparent delays, depending
|
||||
* on the delayed ack timeout on the other side.
|
||||
* Instead of using Nagle's, we need to implement message buffering on
|
||||
* the application level.
|
||||
* see: http://www.stuartcheshire.org/papers/NagleDelayedAck/
|
||||
*/
|
||||
if (setsockopt(stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
|
||||
sizeof(delay_val)) == -1) {
|
||||
if (errno != ENOTSUP) {
|
||||
spice_warning("setsockopt failed, %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
// TODO: move wide/narrow ack setting to red_channel.
|
||||
red_channel_client_ack_set_client_window(rcc,
|
||||
is_low_bandwidth ?
|
||||
WIDE_CLIENT_ACK_WINDOW : NARROW_CLIENT_ACK_WINDOW);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CommonGraphicsChannel* common_graphics_channel_new(RedsState *server,
|
||||
QXLInstance *qxl,
|
||||
const SpiceCoreInterfaceInternal *core,
|
||||
int size, uint32_t channel_type,
|
||||
int migration_flags,
|
||||
ChannelCbs *channel_cbs,
|
||||
channel_handle_parsed_proc handle_parsed)
|
||||
{
|
||||
RedChannel *channel = NULL;
|
||||
CommonGraphicsChannel *common;
|
||||
|
||||
spice_return_val_if_fail(channel_cbs, NULL);
|
||||
spice_return_val_if_fail(!channel_cbs->alloc_recv_buf, NULL);
|
||||
spice_return_val_if_fail(!channel_cbs->release_recv_buf, NULL);
|
||||
|
||||
if (!channel_cbs->config_socket)
|
||||
channel_cbs->config_socket = common_channel_config_socket;
|
||||
channel_cbs->alloc_recv_buf = common_alloc_recv_buf;
|
||||
channel_cbs->release_recv_buf = common_release_recv_buf;
|
||||
|
||||
channel = red_channel_create_parser(size, server,
|
||||
core, channel_type,
|
||||
qxl->id, TRUE /* handle_acks */,
|
||||
spice_get_client_channel_parser(channel_type, NULL),
|
||||
handle_parsed,
|
||||
channel_cbs,
|
||||
migration_flags);
|
||||
spice_return_val_if_fail(channel, NULL);
|
||||
|
||||
common = (CommonGraphicsChannel *)channel;
|
||||
common->qxl = qxl;
|
||||
return common;
|
||||
}
|
||||
|
||||
89
server/common-graphics-channel.h
Normal file
89
server/common-graphics-channel.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright (C) 2009-2016 Red Hat, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_GRAPHICS_CHANNEL_H
|
||||
#define _COMMON_GRAPHICS_CHANNEL_H
|
||||
|
||||
#include "red-channel.h"
|
||||
#include "red-channel-client.h"
|
||||
|
||||
int common_channel_config_socket(RedChannelClient *rcc);
|
||||
|
||||
#define COMMON_CLIENT_TIMEOUT (NSEC_PER_SEC * 30)
|
||||
|
||||
#define CHANNEL_RECEIVE_BUF_SIZE 1024
|
||||
typedef struct CommonGraphicsChannel {
|
||||
RedChannel base; // Must be the first thing
|
||||
|
||||
QXLInstance *qxl;
|
||||
uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE];
|
||||
int during_target_migrate; /* TRUE when the client that is associated with the channel
|
||||
is during migration. Turned off when the vm is started.
|
||||
The flag is used to avoid sending messages that are artifacts
|
||||
of the transition from stopped vm to loaded vm (e.g., recreation
|
||||
of the primary surface) */
|
||||
} CommonGraphicsChannel;
|
||||
|
||||
#define COMMON_GRAPHICS_CHANNEL(Channel) ((CommonGraphicsChannel*)(Channel))
|
||||
|
||||
enum {
|
||||
RED_PIPE_ITEM_TYPE_VERB = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
|
||||
RED_PIPE_ITEM_TYPE_INVAL_ONE,
|
||||
|
||||
RED_PIPE_ITEM_TYPE_COMMON_LAST
|
||||
};
|
||||
|
||||
typedef struct RedVerbItem {
|
||||
RedPipeItem base;
|
||||
uint16_t verb;
|
||||
} RedVerbItem;
|
||||
|
||||
static inline void red_marshall_verb(RedChannelClient *rcc, RedVerbItem *item)
|
||||
{
|
||||
red_channel_client_init_send_data(rcc, item->verb, NULL);
|
||||
}
|
||||
|
||||
static inline void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb)
|
||||
{
|
||||
RedVerbItem *item = spice_new(RedVerbItem, 1);
|
||||
|
||||
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_VERB);
|
||||
item->verb = verb;
|
||||
red_channel_client_pipe_add(rcc, &item->base);
|
||||
}
|
||||
|
||||
static inline void red_pipe_add_verb_proxy(RedChannelClient *rcc, gpointer data)
|
||||
{
|
||||
uint16_t verb = GPOINTER_TO_UINT(data);
|
||||
red_pipe_add_verb(rcc, verb);
|
||||
}
|
||||
|
||||
|
||||
static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb)
|
||||
{
|
||||
red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy, GUINT_TO_POINTER(verb));
|
||||
}
|
||||
|
||||
CommonGraphicsChannel* common_graphics_channel_new(RedsState *server,
|
||||
QXLInstance *qxl,
|
||||
const SpiceCoreInterfaceInternal *core,
|
||||
int size, uint32_t channel_type,
|
||||
int migration_flags,
|
||||
ChannelCbs *channel_cbs,
|
||||
channel_handle_parsed_proc handle_parsed);
|
||||
|
||||
#endif /* _COMMON_GRAPHICS_CHANNEL_H */
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#include <common/generated_server_marshallers.h>
|
||||
|
||||
#include "common-graphics-channel.h"
|
||||
#include "red-channel-client.h"
|
||||
#include "cache-item.h"
|
||||
#include "cursor-channel.h"
|
||||
|
||||
@ -22,9 +22,11 @@
|
||||
#include <glib.h>
|
||||
#include <common/generated_server_marshallers.h>
|
||||
|
||||
#include "common-graphics-channel.h"
|
||||
#include "cursor-channel.h"
|
||||
#include "cursor-channel-client.h"
|
||||
#include "reds.h"
|
||||
#include "red-qxl.h"
|
||||
|
||||
enum {
|
||||
RED_PIPE_ITEM_TYPE_CURSOR = RED_PIPE_ITEM_TYPE_COMMON_LAST,
|
||||
@ -306,7 +308,8 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
|
||||
red_channel_client_begin_send_message(rcc);
|
||||
}
|
||||
|
||||
CursorChannel* cursor_channel_new(RedWorker *worker)
|
||||
CursorChannel* cursor_channel_new(RedsState *server, QXLInstance *qxl,
|
||||
const SpiceCoreInterfaceInternal *core)
|
||||
{
|
||||
CursorChannel *cursor_channel;
|
||||
CommonGraphicsChannel *channel = NULL;
|
||||
@ -316,9 +319,10 @@ CursorChannel* cursor_channel_new(RedWorker *worker)
|
||||
};
|
||||
|
||||
spice_info("create cursor channel");
|
||||
channel = red_worker_new_channel(worker, sizeof(CursorChannel), "cursor_channel",
|
||||
SPICE_CHANNEL_CURSOR, 0,
|
||||
&cbs, red_channel_client_handle_message);
|
||||
channel = common_graphics_channel_new(server, qxl, core,
|
||||
sizeof(CursorChannel),
|
||||
SPICE_CHANNEL_CURSOR, 0,
|
||||
&cbs, red_channel_client_handle_message);
|
||||
|
||||
cursor_channel = (CursorChannel *)channel;
|
||||
cursor_channel->priv->cursor_visible = TRUE;
|
||||
|
||||
@ -18,7 +18,8 @@
|
||||
#ifndef CURSOR_CHANNEL_H_
|
||||
# define CURSOR_CHANNEL_H_
|
||||
|
||||
#include "red-worker.h"
|
||||
#include "common-graphics-channel.h"
|
||||
#include "red-parse-qxl.h"
|
||||
|
||||
/**
|
||||
* This type it's a RedChannel class which implement cursor (mouse)
|
||||
@ -39,7 +40,8 @@ typedef struct CursorChannel CursorChannel;
|
||||
* provided as helper functions and should only be called from the
|
||||
* CursorChannel thread.
|
||||
*/
|
||||
CursorChannel* cursor_channel_new (RedWorker *worker);
|
||||
CursorChannel* cursor_channel_new (RedsState *server, QXLInstance *qxl,
|
||||
const SpiceCoreInterfaceInternal *core);
|
||||
|
||||
/**
|
||||
* Cause the channel to disconnect all clients
|
||||
|
||||
@ -1903,7 +1903,9 @@ static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t su
|
||||
return display->priv->surfaces[surface_id].context.canvas;
|
||||
}
|
||||
|
||||
DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
|
||||
DisplayChannel* display_channel_new(RedsState *reds,
|
||||
QXLInstance *qxl,
|
||||
const SpiceCoreInterfaceInternal *core,
|
||||
int migrate, int stream_video,
|
||||
GArray *video_codecs,
|
||||
uint32_t n_surfaces)
|
||||
@ -1922,9 +1924,8 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
|
||||
};
|
||||
|
||||
spice_info("create display channel");
|
||||
display = (DisplayChannel *)red_worker_new_channel(
|
||||
worker, sizeof(*display), "display_channel",
|
||||
SPICE_CHANNEL_DISPLAY,
|
||||
display = (DisplayChannel *)common_graphics_channel_new(
|
||||
reds, qxl, core, sizeof(*display), SPICE_CHANNEL_DISPLAY,
|
||||
SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER,
|
||||
&cbs, dcc_handle_message);
|
||||
spice_return_val_if_fail(display, NULL);
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
#include "stream.h"
|
||||
#include "dcc.h"
|
||||
#include "image-encoders.h"
|
||||
#include "common-graphics-channel.h"
|
||||
|
||||
typedef struct DependItem {
|
||||
Drawable *drawable;
|
||||
@ -230,8 +231,9 @@ typedef struct RedUpgradeItem {
|
||||
} RedUpgradeItem;
|
||||
|
||||
|
||||
DisplayChannel* display_channel_new (SpiceServer *reds,
|
||||
RedWorker *worker,
|
||||
DisplayChannel* display_channel_new (RedsState *reds,
|
||||
QXLInstance *qxl,
|
||||
const SpiceCoreInterfaceInternal *core,
|
||||
int migrate,
|
||||
int stream_video,
|
||||
GArray *video_codecs,
|
||||
|
||||
@ -91,39 +91,12 @@ struct RedWorker {
|
||||
RedRecord *record;
|
||||
};
|
||||
|
||||
static RedsState* red_worker_get_server(RedWorker *worker);
|
||||
|
||||
static int display_is_connected(RedWorker *worker)
|
||||
{
|
||||
return (worker->display_channel && red_channel_is_connected(
|
||||
&worker->display_channel->common.base));
|
||||
}
|
||||
|
||||
static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
|
||||
{
|
||||
RedChannel *channel = red_channel_client_get_channel(rcc);
|
||||
CommonGraphicsChannel *common = SPICE_CONTAINEROF(channel, CommonGraphicsChannel, base);
|
||||
|
||||
/* SPICE_MSGC_MIGRATE_DATA is the only client message whose size is dynamic */
|
||||
if (type == SPICE_MSGC_MIGRATE_DATA) {
|
||||
return spice_malloc(size);
|
||||
}
|
||||
|
||||
if (size > CHANNEL_RECEIVE_BUF_SIZE) {
|
||||
spice_critical("unexpected message size %u (max is %d)", size, CHANNEL_RECEIVE_BUF_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
return common->recv_buf;
|
||||
}
|
||||
|
||||
static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
|
||||
uint8_t* msg)
|
||||
{
|
||||
if (type == SPICE_MSGC_MIGRATE_DATA) {
|
||||
free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void red_drawable_unref(RedDrawable *red_drawable)
|
||||
{
|
||||
if (--red_drawable->refs) {
|
||||
@ -401,82 +374,6 @@ static void flush_all_qxl_commands(RedWorker *worker)
|
||||
flush_cursor_commands(worker);
|
||||
}
|
||||
|
||||
int common_channel_config_socket(RedChannelClient *rcc)
|
||||
{
|
||||
RedClient *client = red_channel_client_get_client(rcc);
|
||||
MainChannelClient *mcc = red_client_get_main(client);
|
||||
RedsStream *stream = red_channel_client_get_stream(rcc);
|
||||
int flags;
|
||||
int delay_val;
|
||||
gboolean is_low_bandwidth;
|
||||
|
||||
if ((flags = fcntl(stream->socket, F_GETFL)) == -1) {
|
||||
spice_warning("accept failed, %s", strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (fcntl(stream->socket, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
spice_warning("accept failed, %s", strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// TODO - this should be dynamic, not one time at channel creation
|
||||
is_low_bandwidth = main_channel_client_is_low_bandwidth(mcc);
|
||||
delay_val = is_low_bandwidth ? 0 : 1;
|
||||
/* FIXME: Using Nagle's Algorithm can lead to apparent delays, depending
|
||||
* on the delayed ack timeout on the other side.
|
||||
* Instead of using Nagle's, we need to implement message buffering on
|
||||
* the application level.
|
||||
* see: http://www.stuartcheshire.org/papers/NagleDelayedAck/
|
||||
*/
|
||||
if (setsockopt(stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
|
||||
sizeof(delay_val)) == -1) {
|
||||
if (errno != ENOTSUP) {
|
||||
spice_warning("setsockopt failed, %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
// TODO: move wide/narrow ack setting to red_channel.
|
||||
red_channel_client_ack_set_client_window(rcc,
|
||||
is_low_bandwidth ?
|
||||
WIDE_CLIENT_ACK_WINDOW : NARROW_CLIENT_ACK_WINDOW);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CommonGraphicsChannel *red_worker_new_channel(RedWorker *worker, int size,
|
||||
const char *name,
|
||||
uint32_t channel_type, int migration_flags,
|
||||
ChannelCbs *channel_cbs,
|
||||
channel_handle_parsed_proc handle_parsed)
|
||||
{
|
||||
RedChannel *channel = NULL;
|
||||
CommonGraphicsChannel *common;
|
||||
|
||||
spice_return_val_if_fail(worker, NULL);
|
||||
spice_return_val_if_fail(channel_cbs, NULL);
|
||||
spice_return_val_if_fail(!channel_cbs->alloc_recv_buf, NULL);
|
||||
spice_return_val_if_fail(!channel_cbs->release_recv_buf, NULL);
|
||||
|
||||
if (!channel_cbs->config_socket)
|
||||
channel_cbs->config_socket = common_channel_config_socket;
|
||||
channel_cbs->alloc_recv_buf = common_alloc_recv_buf;
|
||||
channel_cbs->release_recv_buf = common_release_recv_buf;
|
||||
|
||||
channel = red_channel_create_parser(size, red_worker_get_server(worker),
|
||||
&worker->core, channel_type,
|
||||
worker->qxl->id, TRUE /* handle_acks */,
|
||||
spice_get_client_channel_parser(channel_type, NULL),
|
||||
handle_parsed,
|
||||
channel_cbs,
|
||||
migration_flags);
|
||||
spice_return_val_if_fail(channel, NULL);
|
||||
red_channel_set_stat_node(channel, stat_add_node(red_worker_get_server(worker),
|
||||
worker->stat, name, TRUE));
|
||||
|
||||
common = (CommonGraphicsChannel *)channel;
|
||||
common->qxl = worker->qxl;
|
||||
return common;
|
||||
}
|
||||
|
||||
static void guest_set_client_capabilities(RedWorker *worker)
|
||||
{
|
||||
int i;
|
||||
@ -1465,18 +1362,21 @@ RedWorker* red_worker_new(QXLInstance *qxl,
|
||||
|
||||
worker->event_timeout = INF_EVENT_WAIT;
|
||||
|
||||
worker->cursor_channel = cursor_channel_new(worker);
|
||||
worker->cursor_channel = cursor_channel_new(reds, qxl,
|
||||
&worker->core);
|
||||
channel = RED_CHANNEL(worker->cursor_channel);
|
||||
red_channel_set_stat_node(channel, stat_add_node(reds, worker->stat, "cursor_channel", TRUE));
|
||||
red_channel_register_client_cbs(channel, client_cursor_cbs, dispatcher);
|
||||
reds_register_channel(reds, channel);
|
||||
|
||||
// TODO: handle seemless migration. Temp, setting migrate to FALSE
|
||||
worker->display_channel = display_channel_new(reds, worker, FALSE,
|
||||
worker->display_channel = display_channel_new(reds, qxl, &worker->core, FALSE,
|
||||
reds_get_streaming_video(reds),
|
||||
reds_get_video_codecs(reds),
|
||||
init_info.n_surfaces);
|
||||
|
||||
channel = RED_CHANNEL(worker->display_channel);
|
||||
red_channel_set_stat_node(channel, stat_add_node(reds, worker->stat, "display_channel", TRUE));
|
||||
red_channel_register_client_cbs(channel, client_display_cbs, dispatcher);
|
||||
red_channel_set_cap(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
|
||||
red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
|
||||
@ -1526,8 +1426,3 @@ bool red_worker_run(RedWorker *worker)
|
||||
|
||||
return r == 0;
|
||||
}
|
||||
|
||||
static RedsState* red_worker_get_server(RedWorker *worker)
|
||||
{
|
||||
return red_qxl_get_server(worker->qxl->st);
|
||||
}
|
||||
|
||||
@ -25,63 +25,6 @@
|
||||
|
||||
typedef struct RedWorker RedWorker;
|
||||
|
||||
int common_channel_config_socket(RedChannelClient *rcc);
|
||||
|
||||
#define COMMON_CLIENT_TIMEOUT (NSEC_PER_SEC * 30)
|
||||
|
||||
#define CHANNEL_RECEIVE_BUF_SIZE 1024
|
||||
typedef struct CommonGraphicsChannel {
|
||||
RedChannel base; // Must be the first thing
|
||||
|
||||
QXLInstance *qxl;
|
||||
uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE];
|
||||
int during_target_migrate; /* TRUE when the client that is associated with the channel
|
||||
is during migration. Turned off when the vm is started.
|
||||
The flag is used to avoid sending messages that are artifacts
|
||||
of the transition from stopped vm to loaded vm (e.g., recreation
|
||||
of the primary surface) */
|
||||
} CommonGraphicsChannel;
|
||||
|
||||
#define COMMON_GRAPHICS_CHANNEL(Channel) ((CommonGraphicsChannel*)(Channel))
|
||||
|
||||
enum {
|
||||
RED_PIPE_ITEM_TYPE_VERB = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
|
||||
RED_PIPE_ITEM_TYPE_INVAL_ONE,
|
||||
|
||||
RED_PIPE_ITEM_TYPE_COMMON_LAST
|
||||
};
|
||||
|
||||
typedef struct RedVerbItem {
|
||||
RedPipeItem base;
|
||||
uint16_t verb;
|
||||
} RedVerbItem;
|
||||
|
||||
static inline void red_marshall_verb(RedChannelClient *rcc, RedVerbItem *item)
|
||||
{
|
||||
red_channel_client_init_send_data(rcc, item->verb, NULL);
|
||||
}
|
||||
|
||||
static inline void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb)
|
||||
{
|
||||
RedVerbItem *item = spice_new(RedVerbItem, 1);
|
||||
|
||||
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_VERB);
|
||||
item->verb = verb;
|
||||
red_channel_client_pipe_add(rcc, &item->base);
|
||||
}
|
||||
|
||||
static inline void red_pipe_add_verb_proxy(RedChannelClient *rcc, gpointer data)
|
||||
{
|
||||
uint16_t verb = GPOINTER_TO_UINT(data);
|
||||
red_pipe_add_verb(rcc, verb);
|
||||
}
|
||||
|
||||
|
||||
static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb)
|
||||
{
|
||||
red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy, GUINT_TO_POINTER(verb));
|
||||
}
|
||||
|
||||
RedWorker* red_worker_new(QXLInstance *qxl,
|
||||
const ClientCbs *client_cursor_cbs,
|
||||
const ClientCbs *client_display_cbs);
|
||||
@ -89,10 +32,4 @@ bool red_worker_run(RedWorker *worker);
|
||||
|
||||
void red_drawable_unref(RedDrawable *red_drawable);
|
||||
|
||||
CommonGraphicsChannel *red_worker_new_channel(RedWorker *worker, int size,
|
||||
const char *name,
|
||||
uint32_t channel_type, int migration_flags,
|
||||
ChannelCbs *channel_cbs,
|
||||
channel_handle_parsed_proc handle_parsed);
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user