[Spice-commits] 2 commits - server/Makefile.am server/common-graphics-channel.c server/common-graphics-channel.h server/cursor-channel-client.c server/cursor-channel.c server/cursor-channel.h server/display-channel.c server/display-channel.h server/inputs-channel-client.c server/inputs-channel.c server/inputs-channel.h server/main-channel.c server/main-channel.h server/red-worker.c server/red-worker.h

Frediano Ziglio fziglio at kemper.freedesktop.org
Fri Oct 14 11:08:37 UTC 2016


 server/Makefile.am               |    2 
 server/common-graphics-channel.c |  129 +++++++++++++++++++++++++++++++++++++++
 server/common-graphics-channel.h |   89 ++++++++++++++++++++++++++
 server/cursor-channel-client.c   |    1 
 server/cursor-channel.c          |   20 +++---
 server/cursor-channel.h          |    6 +
 server/display-channel.c         |   11 +--
 server/display-channel.h         |    8 +-
 server/inputs-channel-client.c   |    2 
 server/inputs-channel.c          |   18 ++---
 server/inputs-channel.h          |    2 
 server/main-channel.c            |    2 
 server/main-channel.h            |    2 
 server/red-worker.c              |  115 +---------------------------------
 server/red-worker.h              |   63 -------------------
 15 files changed, 270 insertions(+), 200 deletions(-)

New commits:
commit efe49fa275dfb6140d6d9e7f7bed499c8d46211a
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Tue Oct 11 17:28:58 2016 -0500

    Use macros for casting Channel types
    
    In preparation for converting RedChannel to GObject, switch to using
    RED_CHANNEL()-type macros for casting. For now they just do a regular
    cast, but it helps reduce the size of the GObject patch to make it
    easier to review.
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/common-graphics-channel.c b/server/common-graphics-channel.c
index 625162c..bcf7279 100644
--- a/server/common-graphics-channel.c
+++ b/server/common-graphics-channel.c
@@ -122,7 +122,7 @@ CommonGraphicsChannel* common_graphics_channel_new(RedsState *server,
                                         migration_flags);
     spice_return_val_if_fail(channel, NULL);
 
-    common = (CommonGraphicsChannel *)channel;
+    common = COMMON_GRAPHICS_CHANNEL(channel);
     common->qxl = qxl;
     return common;
 }
diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index d064ee3..a4d5b58 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -28,6 +28,8 @@
 #include "reds.h"
 #include "red-qxl.h"
 
+#define CURSOR_CHANNEL(channel) ((CursorChannel*)(channel))
+
 enum {
     RED_PIPE_ITEM_TYPE_CURSOR = RED_PIPE_ITEM_TYPE_COMMON_LAST,
     RED_PIPE_ITEM_TYPE_CURSOR_INIT,
@@ -170,7 +172,7 @@ static void cursor_fill(CursorChannelClient *ccc, SpiceCursor *red_cursor,
 
 void cursor_channel_disconnect(CursorChannel *cursor_channel)
 {
-    RedChannel *channel = (RedChannel *)cursor_channel;
+    RedChannel *channel = RED_CHANNEL(cursor_channel);
 
     if (!channel || !red_channel_is_connected(channel)) {
         return;
@@ -198,7 +200,7 @@ static void red_marshall_cursor_init(CursorChannelClient *ccc, SpiceMarshaller *
     AddBufInfo info;
 
     spice_assert(rcc);
-    cursor_channel = (CursorChannel*)red_channel_client_get_channel(rcc);
+    cursor_channel = CURSOR_CHANNEL(red_channel_client_get_channel(rcc));
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INIT, NULL);
     msg.visible = cursor_channel->priv->cursor_visible;
@@ -324,7 +326,7 @@ CursorChannel* cursor_channel_new(RedsState *server, QXLInstance *qxl,
                                           SPICE_CHANNEL_CURSOR, 0,
                                           &cbs, red_channel_client_handle_message);
 
-    cursor_channel = (CursorChannel *)channel;
+    cursor_channel = CURSOR_CHANNEL(channel);
     cursor_channel->priv->cursor_visible = TRUE;
     cursor_channel->priv->mouse_mode = SPICE_MOUSE_MODE_SERVER;
 
diff --git a/server/display-channel.c b/server/display-channel.c
index 93744a4..b9e2b93 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1924,10 +1924,10 @@ DisplayChannel* display_channel_new(RedsState *reds,
     };
 
     spice_info("create display channel");
-    display = (DisplayChannel *)common_graphics_channel_new(
+    display = DISPLAY_CHANNEL(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);
+        &cbs, dcc_handle_message));
     spice_return_val_if_fail(display, NULL);
     display->priv->pub = display;
 
diff --git a/server/display-channel.h b/server/display-channel.h
index 936768e..3762e54 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -45,6 +45,8 @@
 #include "image-encoders.h"
 #include "common-graphics-channel.h"
 
+#define DISPLAY_CHANNEL(channel) ((DisplayChannel*)(channel))
+
 typedef struct DependItem {
     Drawable *drawable;
     RingItem ring_item;
diff --git a/server/inputs-channel-client.c b/server/inputs-channel-client.c
index 76de382..4ab2457 100644
--- a/server/inputs-channel-client.c
+++ b/server/inputs-channel-client.c
@@ -110,7 +110,7 @@ void inputs_channel_client_handle_migrate_data(InputsChannelClient *icc,
 
 void inputs_channel_client_on_mouse_motion(InputsChannelClient *icc)
 {
-    InputsChannel *inputs_channel = (InputsChannel *)red_channel_client_get_channel(RED_CHANNEL_CLIENT(icc));
+    InputsChannel *inputs_channel = INPUTS_CHANNEL(red_channel_client_get_channel(RED_CHANNEL_CLIENT(icc)));
 
     if (++icc->priv->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
         !inputs_channel_is_src_during_migrate(inputs_channel)) {
diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index 840d5e9..85ca155 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -151,7 +151,7 @@ static uint8_t *inputs_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                  uint16_t type,
                                                  uint32_t size)
 {
-    InputsChannel *inputs_channel = (InputsChannel*)red_channel_client_get_channel(rcc);
+    InputsChannel *inputs_channel = INPUTS_CHANNEL(red_channel_client_get_channel(rcc));
 
     if (size > RECEIVE_BUF_SIZE) {
         spice_printerr("error: too large incoming message");
@@ -259,7 +259,7 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
             red_channel_client_init_send_data(rcc, SPICE_MSG_INPUTS_MOUSE_MOTION_ACK, base);
             break;
         case RED_PIPE_ITEM_MIGRATE_DATA:
-            ((InputsChannel*)red_channel_client_get_channel(rcc))->src_during_migrate = FALSE;
+            INPUTS_CHANNEL(red_channel_client_get_channel(rcc))->src_during_migrate = FALSE;
             inputs_channel_client_send_migrate_data(rcc, m, base);
             break;
         default:
@@ -272,7 +272,7 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
 static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type,
                                         void *message)
 {
-    InputsChannel *inputs_channel = (InputsChannel *)red_channel_client_get_channel(rcc);
+    InputsChannel *inputs_channel = INPUTS_CHANNEL(red_channel_client_get_channel(rcc));
     InputsChannelClient *icc = INPUTS_CHANNEL_CLIENT(rcc);
     uint32_t i;
     RedsState *reds = red_channel_get_server(&inputs_channel->base);
@@ -458,13 +458,13 @@ static void inputs_channel_on_disconnect(RedChannelClient *rcc)
     if (!rcc) {
         return;
     }
-    inputs_release_keys((InputsChannel*)red_channel_client_get_channel(rcc));
+    inputs_release_keys(INPUTS_CHANNEL(red_channel_client_get_channel(rcc)));
 }
 
 static void inputs_pipe_add_init(RedChannelClient *rcc)
 {
     RedInputsInitPipeItem *item = spice_malloc(sizeof(RedInputsInitPipeItem));
-    InputsChannel *inputs = (InputsChannel*)red_channel_client_get_channel(rcc);
+    InputsChannel *inputs = INPUTS_CHANNEL(red_channel_client_get_channel(rcc));
 
     red_pipe_item_init(&item->base, RED_PIPE_ITEM_INPUTS_INIT);
     item->modifiers = kbd_get_leds(inputs_channel_get_keyboard(inputs));
@@ -511,7 +511,7 @@ static void inputs_connect(RedChannel *channel, RedClient *client,
 
 static void inputs_migrate(RedChannelClient *rcc)
 {
-    InputsChannel *inputs = (InputsChannel*)red_channel_client_get_channel(rcc);
+    InputsChannel *inputs = INPUTS_CHANNEL(red_channel_client_get_channel(rcc));
     inputs->src_during_migrate = TRUE;
     red_channel_client_default_migrate(rcc);
 }
@@ -548,7 +548,7 @@ static int inputs_channel_handle_migrate_data(RedChannelClient *rcc,
                                               void *message)
 {
     InputsChannelClient *icc = INPUTS_CHANNEL_CLIENT(rcc);
-    InputsChannel *inputs = (InputsChannel*)red_channel_client_get_channel(rcc);
+    InputsChannel *inputs = INPUTS_CHANNEL(red_channel_client_get_channel(rcc));
     SpiceMigrateDataHeader *header;
     SpiceMigrateDataInputs *mig_data;
 
@@ -580,7 +580,7 @@ InputsChannel* inputs_channel_new(RedsState *reds)
     channel_cbs.handle_migrate_data = inputs_channel_handle_migrate_data;
     channel_cbs.handle_migrate_flush_mark = inputs_channel_handle_migrate_flush_mark;
 
-    inputs = (InputsChannel *)red_channel_create_parser(
+    inputs = INPUTS_CHANNEL(red_channel_create_parser(
                                     sizeof(InputsChannel),
                                     reds,
                                     reds_get_core_interface(reds),
@@ -589,7 +589,7 @@ InputsChannel* inputs_channel_new(RedsState *reds)
                                     spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL),
                                     inputs_channel_handle_parsed,
                                     &channel_cbs,
-                                    SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER);
+                                    SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER));
 
     if (!inputs) {
         spice_error("failed to allocate Inputs Channel");
diff --git a/server/inputs-channel.h b/server/inputs-channel.h
index e8f92cc..ae84eed 100644
--- a/server/inputs-channel.h
+++ b/server/inputs-channel.h
@@ -26,6 +26,8 @@
 
 #include "red-channel.h"
 
+#define INPUTS_CHANNEL(channel) ((InputsChannel*)(channel))
+
 typedef struct InputsChannel InputsChannel;
 
 InputsChannel* inputs_channel_new(RedsState *reds);
diff --git a/server/main-channel.c b/server/main-channel.c
index bf84694..a1b8e31 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -329,7 +329,7 @@ MainChannel* main_channel_new(RedsState *reds)
     client_cbs.migrate = main_channel_client_migrate;
     red_channel_register_client_cbs(channel, &client_cbs, NULL);
 
-    return (MainChannel *)channel;
+    return MAIN_CHANNEL(channel);
 }
 
 static int main_channel_connect_semi_seamless(MainChannel *main_channel)
diff --git a/server/main-channel.h b/server/main-channel.h
index 868a14a..e0858d0 100644
--- a/server/main-channel.h
+++ b/server/main-channel.h
@@ -25,6 +25,8 @@
 #include "red-channel.h"
 #include "main-channel-client.h"
 
+#define MAIN_CHANNEL(channel) ((MainChannel*)(channel))
+
 // TODO: Defines used to calculate receive buffer size, and also by reds.c
 // other options: is to make a reds_main_consts.h, to duplicate defines.
 #define REDS_AGENT_WINDOW_SIZE 10
commit bcb8503659ce281d1a07fc506df9dc8830b03775
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Tue Oct 11 17:28:57 2016 -0500

    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 at redhat.com>

diff --git a/server/Makefile.am b/server/Makefile.am
index f217399..036abcd 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -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				\
diff --git a/server/common-graphics-channel.c b/server/common-graphics-channel.c
new file mode 100644
index 0000000..625162c
--- /dev/null
+++ b/server/common-graphics-channel.c
@@ -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;
+}
+
diff --git a/server/common-graphics-channel.h b/server/common-graphics-channel.h
new file mode 100644
index 0000000..b9473d8
--- /dev/null
+++ b/server/common-graphics-channel.h
@@ -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 */
diff --git a/server/cursor-channel-client.c b/server/cursor-channel-client.c
index 25082d7..90778ed 100644
--- a/server/cursor-channel-client.c
+++ b/server/cursor-channel-client.c
@@ -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"
diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index 5b21a05..d064ee3 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -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;
diff --git a/server/cursor-channel.h b/server/cursor-channel.h
index 6149e2d..bbc4868 100644
--- a/server/cursor-channel.h
+++ b/server/cursor-channel.h
@@ -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
diff --git a/server/display-channel.c b/server/display-channel.c
index b9366b5..93744a4 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -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);
diff --git a/server/display-channel.h b/server/display-channel.h
index bbae6f1..936768e 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -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,
diff --git a/server/red-worker.c b/server/red-worker.c
index b3f6c12..2dfa8e4 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -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);
-}
diff --git a/server/red-worker.h b/server/red-worker.h
index 7d68678..dc2ff24 100644
--- a/server/red-worker.h
+++ b/server/red-worker.h
@@ -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


More information about the Spice-commits mailing list