import gnome-remote-desktop-0.1.8-3.el8

This commit is contained in:
CentOS Sources 2020-11-03 06:46:41 -05:00 committed by Andrew Lukoshko
parent 6b48341019
commit 9ea614af72
16 changed files with 1000 additions and 1515 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/gnome-remote-desktop-0.1.6.tar.xz
SOURCES/gnome-remote-desktop-0.1.8.tar.xz

View File

@ -1 +1 @@
25504e6190dbfae00c7a648d1a4dd37c4ecc92b2 SOURCES/gnome-remote-desktop-0.1.6.tar.xz
3347257bd906cd0ca86887c692befd8d412afab1 SOURCES/gnome-remote-desktop-0.1.8.tar.xz

View File

@ -1,25 +0,0 @@
From 8f760d73df6011330cd09da7ca7b8a3f40c9a3ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 7 Aug 2018 13:35:43 +0200
Subject: [PATCH] meson.build: Bump pipewire requirement to 0.2.2
---
meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index 6951b89..34ec5ea 100644
--- a/meson.build
+++ b/meson.build
@@ -10,7 +10,7 @@ gnome = import('gnome')
glib_dep = dependency('glib-2.0')
gio_dep = dependency('gio-2.0')
gio_unix_dep = dependency('gio-unix-2.0')
-pipewire_dep = dependency('libpipewire-0.1')
+pipewire_dep = dependency('libpipewire-0.2', version: '>= 0.2.2')
systemd_dep = dependency('systemd')
libvncserver_dep = dependency('libvncserver')
libsecret_dep = dependency('libsecret-1')
--
2.17.1

View File

@ -1,84 +0,0 @@
From add0ea34fd1d6835c99aebeb4e56b805b38e53ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 1 Oct 2018 18:02:39 +0200
Subject: [PATCH 1/2] session/vnc: Don't requeue close session idle
If being closed due to a PipeWire error, RFB will still process state
and invoke callbacks when cleaning up the RFB screen, meaning we'd
requeue the close session idle handler. Avoid this by avoiding
requeueing if there is already one queued, and don't mark is as unqueued
until after actually stopping the session.
---
src/grd-session-vnc.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index ce4dd29..3c98eeb 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -165,6 +165,16 @@ grd_session_vnc_draw_buffer (GrdSessionVnc *session_vnc,
rfbProcessEvents (session_vnc->rfb_screen, 0);
}
+static void
+maybe_queue_close_session_idle (GrdSessionVnc *session_vnc)
+{
+ if (session_vnc->close_session_idle_id)
+ return;
+
+ session_vnc->close_session_idle_id =
+ g_idle_add (close_session_idle, session_vnc);
+}
+
static void
handle_client_gone (rfbClientPtr rfb_client)
{
@@ -172,8 +182,7 @@ handle_client_gone (rfbClientPtr rfb_client)
g_debug ("VNC client gone");
- session_vnc->close_session_idle_id =
- g_idle_add (close_session_idle, session_vnc);
+ maybe_queue_close_session_idle (session_vnc);
}
static void
@@ -670,12 +679,6 @@ grd_session_vnc_stop (GrdSession *session)
g_debug ("Stopping VNC session");
- if (session_vnc->close_session_idle_id)
- {
- g_source_remove (session_vnc->close_session_idle_id);
- session_vnc->close_session_idle_id = 0;
- }
-
g_clear_object (&session_vnc->pipewire_stream);
grd_session_vnc_detach_source (session_vnc);
@@ -683,6 +686,12 @@ grd_session_vnc_stop (GrdSession *session)
g_clear_object (&session_vnc->connection);
g_clear_pointer (&session_vnc->rfb_screen->frameBuffer, g_free);
g_clear_pointer (&session_vnc->rfb_screen, (GDestroyNotify) rfbScreenCleanup);
+
+ if (session_vnc->close_session_idle_id)
+ {
+ g_source_remove (session_vnc->close_session_idle_id);
+ session_vnc->close_session_idle_id = 0;
+ }
}
static gboolean
@@ -703,8 +712,7 @@ on_pipwire_stream_closed (GrdVncPipeWireStream *stream,
{
g_warning ("PipeWire stream closed, closing client");
- session_vnc->close_session_idle_id =
- g_idle_add (close_session_idle, session_vnc);
+ maybe_queue_close_session_idle (session_vnc);
}
static void
--
2.17.1

View File

@ -0,0 +1,52 @@
From 7670167e578eb5c6e032cff38112edf85df142ee Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Tue, 16 Jun 2020 11:44:52 +0200
Subject: [PATCH 1/2] stream: log a warning on error
When we get an invalid buffer or we can't mmap() it, log a warning
and exit instead of carying on with invalid pointers and segfault.
---
src/grd-vnc-pipewire-stream.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index 261292a..91fb0a1 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -323,14 +323,18 @@ process_buffer (GrdVncPipeWireStream *stream,
if (buffer->datas[0].chunk->size == 0)
{
- size = 0;
- map = NULL;
- src_data = NULL;
+ g_warning ("Received empty buffer");
+ return NULL;
}
else if (buffer->datas[0].type == SPA_DATA_MemFd)
{
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0);
+ if (map == MAP_FAILED)
+ {
+ g_warning ("Failed to mmap buffer: %s", g_strerror (errno));
+ return NULL;
+ }
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
}
else if (buffer->datas[0].type == SPA_DATA_DmaBuf)
@@ -341,6 +345,11 @@ process_buffer (GrdVncPipeWireStream *stream,
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (map == MAP_FAILED)
+ {
+ g_warning ("Failed to mmap DMA buffer: %s", g_strerror (errno));
+ return NULL;
+ }
sync_dma_buf (fd, DMA_BUF_SYNC_START);
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
--
2.26.2

View File

@ -1,42 +0,0 @@
From 1467e4c26f47ad3747903392a026698a169870aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 10 Apr 2019 15:59:54 +0200
Subject: [PATCH] vnc: Allow overriding password with env var
For testing purposes. Also overrides VNC auth method setting.
---
src/grd-settings.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/grd-settings.c b/src/grd-settings.c
index c886b7e..d6c4a25 100644
--- a/src/grd-settings.c
+++ b/src/grd-settings.c
@@ -71,6 +71,12 @@ char *
grd_settings_get_vnc_password (GrdSettings *settings,
GError **error)
{
+ const char *test_password_override;
+
+ test_password_override = g_getenv ("GNOME_REMOTE_DESKTOP_TEST_VNC_PASSWORD");
+ if (test_password_override)
+ return g_strdup (test_password_override);
+
return secret_password_lookup_sync (GRD_VNC_PASSWORD_SCHEMA,
NULL, error,
NULL);
@@ -85,7 +91,10 @@ grd_settings_get_vnc_view_only (GrdSettings *settings)
GrdVncAuthMethod
grd_settings_get_vnc_auth_method (GrdSettings *settings)
{
- return settings->vnc.auth_method;
+ if (g_getenv ("GNOME_REMOTE_DESKTOP_TEST_VNC_PASSWORD"))
+ return GRD_VNC_AUTH_METHOD_PASSWORD;
+ else
+ return settings->vnc.auth_method;
}
GrdVncEncryption
--
2.21.0

View File

@ -1,47 +0,0 @@
From 23526b25b9a8088c7435563516bea96ed4408c13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 16:53:42 +0100
Subject: [PATCH] vnc: Unregister previously set security handlers on init
When we're starting a session, we're going to handle a new client
connection. However, any previous client that was ever run on in a
previous session would still have their "security handler" registered,
as such is a global permanent change in libvncserver right now.
To work around this, unregister all primary security handler (i.e.
'none' and 'password') when initializing the RFB screen. We'll set up
the preferred one when handling the new client.
---
src/grd-session-vnc.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index c5f83d8..2967415 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -28,6 +28,9 @@
#include <linux/input.h>
#include <rfb/rfb.h>
+/* Potential redeclaration of libVNCServer API to avoid build failure. */
+extern void rfbUnregisterPrimarySecurityHandlers (void);
+
#include "grd-context.h"
#include "grd-prompt.h"
#include "grd-settings.h"
@@ -564,6 +567,12 @@ init_vnc_session (GrdSessionVnc *session_vnc)
8, 3, 4);
session_vnc->rfb_screen = rfb_screen;
+ /*
+ * Unregister whatever security handler was used the last time; we'll set
+ * up new ones when authorizing the new client anyway.
+ */
+ rfbUnregisterPrimarySecurityHandlers ();
+
update_server_format (session_vnc);
socket = g_socket_connection_get_socket (session_vnc->connection);
--
2.23.0

View File

@ -0,0 +1,73 @@
From 78c5bcb181fe2b0b9fc17eea696feac8b504df54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 7 May 2020 15:48:22 +0200
Subject: [PATCH] vnc/pipewire-stream: Handle stride mismatch
The VNC server framebuffer assumes a particular stride; but there is no
guarantee that we'll get the same from PipeWire. Handle this gracefully
by coping row by row instead of the whole buffer.
---
src/grd-vnc-pipewire-stream.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index 88c07be..261292a 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -187,8 +187,6 @@ on_stream_param_changed (void *user_data,
struct spa_pod_builder pod_builder;
int width;
int height;
- int stride;
- int size;
const struct spa_pod *params[3];
if (!format || id != SPA_PARAM_Format)
@@ -203,14 +201,9 @@ on_stream_param_changed (void *user_data,
grd_session_vnc_queue_resize_framebuffer (stream->session, width, height);
- stride = grd_session_vnc_get_framebuffer_stride (stream->session);
- size = stride * height;
-
params[0] = spa_pod_builder_add_object (
&pod_builder,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
- SPA_PARAM_BUFFERS_size, SPA_POD_Int (size),
- SPA_PARAM_BUFFERS_stride, SPA_POD_Int (stride),
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (8, 1, 8),
0);
@@ -319,6 +312,10 @@ process_buffer (GrdVncPipeWireStream *stream,
size_t size;
uint8_t *map;
void *src_data;
+ int src_stride;
+ int dst_stride;
+ int height;
+ int y;
struct spa_meta_cursor *spa_meta_cursor;
g_autofree GrdVncFrame *frame = NULL;
@@ -359,7 +356,17 @@ process_buffer (GrdVncPipeWireStream *stream,
return NULL;
}
- frame->data = g_memdup (src_data, buffer->datas[0].maxsize);
+ src_stride = buffer->datas[0].chunk->stride;
+ dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session);
+ height = stream->spa_format.size.height;
+
+ frame->data = g_malloc (height * dst_stride);
+ for (y = 0; y < height; y++)
+ {
+ memcpy (((uint8_t *) frame->data) + y * dst_stride,
+ ((uint8_t *) src_data) + y * src_stride,
+ dst_stride);
+ }
if (map)
{
--
2.26.2

View File

@ -0,0 +1,25 @@
From 240d8694fbcdeb020e7f9c0f8f292a4679b88b30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 18 Jun 2020 13:14:04 +0200
Subject: [PATCH] vnc/pipewire-stream: Remove assert
Handle lack of frames gracefully.
---
src/grd-vnc-pipewire-stream.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index ee8ad5d..a3f5fb6 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -463,7 +463,6 @@ on_stream_process (void *user_data)
frame = process_buffer (stream, buffer->buffer);
- g_assert (frame);
g_mutex_lock (&stream->frame_mutex);
if (stream->pending_frame)
{
--
2.26.2

View File

@ -1,28 +0,0 @@
From 59188d81cf8936cd9f5400df040d875427251bf2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 1 Oct 2018 18:05:07 +0200
Subject: [PATCH 2/2] vnc-pipewire-stream: Close session when disconnected
When there is an active stream, and we're disconnected from PipeWire
(e.g. because it terminated), close the session.
---
src/grd-vnc-pipewire-stream.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index 66d66a0..d6454b8 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -392,6 +392,9 @@ on_state_changed (void *user_data,
}
break;
case PW_REMOTE_STATE_UNCONNECTED:
+ if (stream->pipewire_stream)
+ g_signal_emit (stream, signals[CLOSED], 0);
+ break;
case PW_REMOTE_STATE_CONNECTING:
break;
}
--
2.17.1

View File

@ -0,0 +1,62 @@
From f3efe25a5cb173bc63b380619b8673cd5ba99f6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 18 Jun 2020 11:35:44 +0200
Subject: [PATCH 2/2] vnc/pipewire-stream: Only try to copy frame pixels if
there are any
The producer might send empty frames with only cursor metadata, and in
this case we shouldn't try to copy any pixels, as there are no.
---
src/grd-vnc-pipewire-stream.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index 91fb0a1..ee8ad5d 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -312,9 +312,6 @@ process_buffer (GrdVncPipeWireStream *stream,
size_t size;
uint8_t *map;
void *src_data;
- int src_stride;
- int dst_stride;
- int height;
int y;
struct spa_meta_cursor *spa_meta_cursor;
g_autofree GrdVncFrame *frame = NULL;
@@ -365,16 +362,23 @@ process_buffer (GrdVncPipeWireStream *stream,
return NULL;
}
- src_stride = buffer->datas[0].chunk->stride;
- dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session);
- height = stream->spa_format.size.height;
-
- frame->data = g_malloc (height * dst_stride);
- for (y = 0; y < height; y++)
+ if (src_data)
{
- memcpy (((uint8_t *) frame->data) + y * dst_stride,
- ((uint8_t *) src_data) + y * src_stride,
- dst_stride);
+ int src_stride;
+ int dst_stride;
+ int height;
+
+ src_stride = buffer->datas[0].chunk->stride;
+ dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session);
+ height = stream->spa_format.size.height;
+
+ frame->data = g_malloc (height * dst_stride);
+ for (y = 0; y < height; y++)
+ {
+ memcpy (((uint8_t *) frame->data) + y * dst_stride,
+ ((uint8_t *) src_data) + y * src_stride,
+ dst_stride);
+ }
}
if (map)
--
2.26.2

View File

@ -1,7 +1,7 @@
From fcfef86768d3dc63a2e7da799beb011800dff2ad Mon Sep 17 00:00:00 2001
From 10843a1f3edffbb475c01835451d39ebe6153e44 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 14 Jun 2018 12:21:37 +0200
Subject: [PATCH] vnc: Add anonymous TLS encryption support
Subject: [PATCH 1/7] vnc: Add anonymous TLS encryption support
Add support for encrypting the VNC connection using anonymous TLS. In
effect this means that the channel is encrypted using TLS but that no
@ -12,24 +12,24 @@ VNC connection.
meson.build | 1 +
src/grd-enums.h | 6 +
src/grd-session-vnc.c | 98 +++-
src/grd-session-vnc.h | 16 +
src/grd-settings.c | 27 ++
src/grd-session-vnc.h | 15 +
src/grd-settings.c | 28 ++
src/grd-settings.h | 2 +
src/grd-vnc-server.c | 45 ++
src/grd-vnc-tls.c | 444 ++++++++++++++++++
src/grd-vnc-tls.h | 28 ++
src/meson.build | 5 +-
...g.gnome.desktop.remote-desktop.gschema.xml | 10 +
...nome.desktop.remote-desktop.gschema.xml.in | 10 +
11 files changed, 666 insertions(+), 16 deletions(-)
create mode 100644 src/grd-vnc-tls.c
create mode 100644 src/grd-vnc-tls.h
diff --git a/meson.build b/meson.build
index d8e20d2..f8c8cee 100644
index 1c96849..a24acfd 100644
--- a/meson.build
+++ b/meson.build
@@ -15,6 +15,7 @@ systemd_dep = dependency('systemd')
libvncserver_dep = dependency('libvncserver')
@@ -15,6 +15,7 @@ libvncserver_dep = dependency('libvncserver')
libvncclient_dep = dependency('libvncclient')
libsecret_dep = dependency('libsecret-1')
libnotify_dep = dependency('libnotify')
+gnutls_dep = dependency('gnutls')
@ -52,7 +52,7 @@ index ffab821..4333863 100644
+
#endif /* GRD_ENUMS_H */
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 5d40971..ce4dd29 100644
index 1f3f0e2..0cc2ea2 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -44,7 +44,9 @@ struct _GrdSessionVnc
@ -65,7 +65,7 @@ index 5d40971..ce4dd29 100644
GSource *source;
rfbScreenInfoPtr rfb_screen;
rfbClientPtr rfb_client;
@@ -465,12 +467,30 @@ check_rfb_password (rfbClientPtr rfb_client,
@@ -505,12 +507,30 @@ check_rfb_password (rfbClientPtr rfb_client,
}
}
@ -96,7 +96,7 @@ index 5d40971..ce4dd29 100644
static void
init_vnc_session (GrdSessionVnc *session_vnc)
{
@@ -509,33 +529,74 @@ init_vnc_session (GrdSessionVnc *session_vnc)
@@ -551,33 +571,74 @@ init_vnc_session (GrdSessionVnc *session_vnc)
rfbProcessEvents (rfb_screen, 0);
}
@ -185,7 +185,7 @@ index 5d40971..ce4dd29 100644
}
return G_SOURCE_CONTINUE;
@@ -548,7 +609,10 @@ grd_session_vnc_attach_source (GrdSessionVnc *session_vnc)
@@ -590,7 +651,10 @@ grd_session_vnc_attach_source (GrdSessionVnc *session_vnc)
socket = g_socket_connection_get_socket (session_vnc->connection);
session_vnc->source = g_socket_create_source (socket,
@ -197,7 +197,7 @@ index 5d40971..ce4dd29 100644
NULL);
g_source_set_callback (session_vnc->source,
(GSourceFunc) handle_socket_data,
@@ -574,8 +638,10 @@ grd_session_vnc_new (GrdVncServer *vnc_server,
@@ -616,8 +680,10 @@ grd_session_vnc_new (GrdVncServer *vnc_server,
"context", context,
NULL);
@ -208,7 +208,7 @@ index 5d40971..ce4dd29 100644
grd_session_vnc_attach_source (session_vnc);
init_vnc_session (session_vnc);
@@ -590,6 +656,8 @@ grd_session_vnc_dispose (GObject *object)
@@ -632,6 +698,8 @@ grd_session_vnc_dispose (GObject *object)
g_assert (!session_vnc->rfb_screen);
@ -218,18 +218,10 @@ index 5d40971..ce4dd29 100644
G_OBJECT_CLASS (grd_session_vnc_parent_class)->dispose (object);
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
index 6bd067a..33245bc 100644
index 14b5d12..46a8579 100644
--- a/src/grd-session-vnc.h
+++ b/src/grd-session-vnc.h
@@ -25,6 +25,7 @@
#include <gio/gio.h>
#include <glib-object.h>
+#include <rfb/rfb.h>
#include "grd-session.h"
#include "grd-types.h"
@@ -35,6 +36,9 @@ G_DECLARE_FINAL_TYPE (GrdSessionVnc,
@@ -36,6 +36,9 @@ G_DECLARE_FINAL_TYPE (GrdSessionVnc,
GRD, SESSION_VNC,
GrdSession);
@ -239,9 +231,9 @@ index 6bd067a..33245bc 100644
GrdSessionVnc *grd_session_vnc_new (GrdVncServer *vnc_server,
GSocketConnection *connection);
@@ -45,6 +49,18 @@ void grd_session_vnc_queue_resize_framebuffer (GrdSessionVnc *session_vnc,
void grd_session_vnc_draw_buffer (GrdSessionVnc *session_vnc,
void *data);
@@ -53,6 +56,18 @@ void grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc,
int x,
int y);
+int grd_session_vnc_get_fd (GrdSessionVnc *session_vnc);
+
@ -259,19 +251,19 @@ index 6bd067a..33245bc 100644
+
#endif /* GRD_SESSION_VNC_H */
diff --git a/src/grd-settings.c b/src/grd-settings.c
index a3a2afa..c886b7e 100644
index bdf8211..7324310 100644
--- a/src/grd-settings.c
+++ b/src/grd-settings.c
@@ -46,6 +46,7 @@ struct _GrdSettings
GSettings *settings;
@@ -48,6 +48,7 @@ struct _GrdSettings
gboolean view_only;
GrdVncAuthMethod auth_method;
int port;
+ GrdVncEncryption encryption;
} vnc;
};
@@ -87,6 +88,12 @@ grd_settings_get_vnc_auth_method (GrdSettings *settings)
return settings->vnc.auth_method;
@@ -120,6 +121,12 @@ grd_settings_get_vnc_auth_method (GrdSettings *settings)
return settings->vnc.auth_method;
}
+GrdVncEncryption
@ -283,7 +275,7 @@ index a3a2afa..c886b7e 100644
static void
update_vnc_view_only (GrdSettings *settings)
{
@@ -101,6 +108,13 @@ update_vnc_auth_method (GrdSettings *settings)
@@ -134,6 +141,13 @@ update_vnc_auth_method (GrdSettings *settings)
"auth-method");
}
@ -297,7 +289,7 @@ index a3a2afa..c886b7e 100644
static void
on_vnc_settings_changed (GSettings *vnc_settings,
const char *key,
@@ -116,6 +130,11 @@ on_vnc_settings_changed (GSettings *vnc_settings,
@@ -149,6 +163,11 @@ on_vnc_settings_changed (GSettings *vnc_settings,
update_vnc_auth_method (settings);
g_signal_emit (settings, signals[VNC_AUTH_METHOD_CHANGED], 0);
}
@ -309,15 +301,16 @@ index a3a2afa..c886b7e 100644
}
static void
@@ -137,6 +156,7 @@ grd_settings_init (GrdSettings *settings)
update_vnc_view_only (settings);
@@ -172,6 +191,8 @@ grd_settings_init (GrdSettings *settings)
update_vnc_auth_method (settings);
settings->vnc.port = GRD_VNC_SERVER_PORT;
+
+ update_vnc_encryption (settings);
}
static void
@@ -160,4 +180,11 @@ grd_settings_class_init (GrdSettingsClass *klass)
@@ -195,4 +216,11 @@ grd_settings_class_init (GrdSettingsClass *klass)
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
@ -330,10 +323,10 @@ index a3a2afa..c886b7e 100644
+ G_TYPE_NONE, 0);
}
diff --git a/src/grd-settings.h b/src/grd-settings.h
index 9b23b09..4bca403 100644
index e4e0c09..0575ec1 100644
--- a/src/grd-settings.h
+++ b/src/grd-settings.h
@@ -40,4 +40,6 @@ gboolean grd_settings_get_vnc_view_only (GrdSettings *settings);
@@ -45,4 +45,6 @@ gboolean grd_settings_get_vnc_view_only (GrdSettings *settings);
GrdVncAuthMethod grd_settings_get_vnc_auth_method (GrdSettings *settings);
@ -341,7 +334,7 @@ index 9b23b09..4bca403 100644
+
#endif /* GRD_SETTINGS_H */
diff --git a/src/grd-vnc-server.c b/src/grd-vnc-server.c
index a8fed02..769b7ec 100644
index a6d95cb..f9c68db 100644
--- a/src/grd-vnc-server.c
+++ b/src/grd-vnc-server.c
@@ -24,11 +24,13 @@
@ -356,9 +349,9 @@ index a8fed02..769b7ec 100644
#include "grd-session-vnc.h"
+#include "grd-vnc-tls.h"
#define GRD_VNC_SERVER_PORT 5900
@@ -131,6 +133,43 @@ on_incoming (GSocketService *service,
enum
@@ -130,6 +132,43 @@ on_incoming (GSocketService *service,
return TRUE;
}
@ -402,7 +395,7 @@ index a8fed02..769b7ec 100644
gboolean
grd_vnc_server_start (GrdVncServer *vnc_server,
GError **error)
@@ -219,12 +258,18 @@ static void
@@ -220,12 +259,18 @@ static void
grd_vnc_server_constructed (GObject *object)
{
GrdVncServer *vnc_server = GRD_VNC_SERVER (object);
@ -423,7 +416,7 @@ index a8fed02..769b7ec 100644
diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c
new file mode 100644
index 0000000..8fc0fc2
index 0000000..ec4758e
--- /dev/null
+++ b/src/grd-vnc-tls.c
@@ -0,0 +1,444 @@
@ -600,7 +593,7 @@ index 0000000..8fc0fc2
+grd_vnc_tls_session_free (GrdVncTlsSession *tls_session)
+{
+ g_clear_pointer (&tls_session->peek_buffer, g_free);
+ g_clear_pointer (&tls_session->tls_session, (GDestroyNotify) gnutls_deinit);
+ g_clear_pointer (&tls_session->tls_session, gnutls_deinit);
+ g_free (tls_session);
+}
+
@ -906,10 +899,10 @@ index 0000000..135ef8c
+
+#endif /* GRD_VNC_TLS_H */
diff --git a/src/meson.build b/src/meson.build
index 70e2102..b633ad7 100644
index 0f76fab..9d2f1ce 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -19,6 +19,8 @@ daemon_sources = files([
@@ -21,6 +21,8 @@ daemon_sources = files([
'grd-vnc-pipewire-stream.h',
'grd-vnc-server.c',
'grd-vnc-server.h',
@ -918,7 +911,7 @@ index 70e2102..b633ad7 100644
])
gen_daemon_sources = []
@@ -49,7 +51,8 @@ executable('gnome-remote-desktop-daemon',
@@ -51,7 +53,8 @@ executable('gnome-remote-desktop-daemon',
pipewire_dep,
libvncserver_dep,
libsecret_dep,
@ -928,10 +921,10 @@ index 70e2102..b633ad7 100644
include_directories: [configinc],
install: true,
install_dir: libexecdir)
diff --git a/src/org.gnome.desktop.remote-desktop.gschema.xml b/src/org.gnome.desktop.remote-desktop.gschema.xml
diff --git a/src/org.gnome.desktop.remote-desktop.gschema.xml.in b/src/org.gnome.desktop.remote-desktop.gschema.xml.in
index a5c2022..846e65b 100644
--- a/src/org.gnome.desktop.remote-desktop.gschema.xml
+++ b/src/org.gnome.desktop.remote-desktop.gschema.xml
--- a/src/org.gnome.desktop.remote-desktop.gschema.xml.in
+++ b/src/org.gnome.desktop.remote-desktop.gschema.xml.in
@@ -23,5 +23,15 @@
* password - by requiring the remote client to provide a known password
</description>
@ -949,5 +942,591 @@ index a5c2022..846e65b 100644
</schema>
</schemalist>
--
2.17.1
2.26.2
From aa54aeb43938250a4d27a99e62eb5628d3b55076 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:02:09 +0100
Subject: [PATCH 2/7] session-vnc: Add paused/resumed signals
Paused is when the socket sourec is detached, and resumed when attached.
Meant to be used by the TLS channel security to a attach/detach
out-of-socket source.
---
src/grd-session-vnc.c | 72 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 65 insertions(+), 7 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 0cc2ea2..076e25f 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -40,14 +40,27 @@
#define BGRX_SAMPLES_PER_PIXEL 3
#define BGRX_BYTES_PER_PIXEL 4
+enum
+{
+ PAUSED,
+ RESUMED,
+
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
struct _GrdSessionVnc
{
GrdSession parent;
GrdVncServer *vnc_server;
GSocketConnection *connection;
+
GList *socket_grabs;
GSource *source;
+ gboolean is_paused;
+
rfbScreenInfoPtr rfb_screen;
rfbClientPtr rfb_client;
@@ -73,7 +86,7 @@ struct _GrdSessionVnc
G_DEFINE_TYPE (GrdSessionVnc, grd_session_vnc, GRD_TYPE_SESSION);
static void
-grd_session_vnc_detach_source (GrdSessionVnc *session_vnc);
+grd_session_vnc_pause (GrdSessionVnc *session_vnc);
static gboolean
close_session_idle (gpointer user_data);
@@ -212,7 +225,8 @@ handle_client_gone (rfbClientPtr rfb_client)
g_debug ("VNC client gone");
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
+
maybe_queue_close_session_idle (session_vnc);
}
@@ -280,7 +294,7 @@ handle_new_client (rfbClientPtr rfb_client)
session_vnc->prompt_cancellable,
prompt_response_callback,
session_vnc);
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
return RFB_CLIENT_ON_HOLD;
case GRD_VNC_AUTH_METHOD_PASSWORD:
session_vnc->rfb_screen->passwordCheck = check_rfb_password;
@@ -498,7 +512,7 @@ check_rfb_password (rfbClientPtr rfb_client,
if (memcmp (challenge_encrypted, response_encrypted, len) == 0)
{
grd_session_start (GRD_SESSION (session_vnc));
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
return TRUE;
}
else
@@ -668,6 +682,36 @@ grd_session_vnc_detach_source (GrdSessionVnc *session_vnc)
g_clear_pointer (&session_vnc->source, g_source_destroy);
}
+gboolean
+grd_session_vnc_is_paused (GrdSessionVnc *session_vnc)
+{
+ return session_vnc->is_paused;
+}
+
+static void
+grd_session_vnc_pause (GrdSessionVnc *session_vnc)
+{
+ if (grd_session_vnc_is_paused (session_vnc))
+ return;
+
+ session_vnc->is_paused = TRUE;
+
+ grd_session_vnc_detach_source (session_vnc);
+ g_signal_emit (session_vnc, signals[PAUSED], 0);
+}
+
+static void
+grd_session_vnc_resume (GrdSessionVnc *session_vnc)
+{
+ if (!grd_session_vnc_is_paused (session_vnc))
+ return;
+
+ session_vnc->is_paused = FALSE;
+
+ grd_session_vnc_attach_source (session_vnc);
+ g_signal_emit (session_vnc, signals[RESUMED], 0);
+}
+
GrdSessionVnc *
grd_session_vnc_new (GrdVncServer *vnc_server,
GSocketConnection *connection)
@@ -685,6 +729,7 @@ grd_session_vnc_new (GrdVncServer *vnc_server,
grd_session_vnc_grab_socket (session_vnc, vnc_socket_grab_func);
grd_session_vnc_attach_source (session_vnc);
+ session_vnc->is_paused = FALSE;
init_vnc_session (session_vnc);
@@ -714,7 +759,7 @@ grd_session_vnc_stop (GrdSession *session)
g_clear_object (&session_vnc->pipewire_stream);
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
g_clear_object (&session_vnc->connection);
g_clear_pointer (&session_vnc->rfb_screen->frameBuffer, g_free);
@@ -770,8 +815,8 @@ grd_session_vnc_stream_ready (GrdSession *session,
G_CALLBACK (on_pipwire_stream_closed),
session_vnc);
- if (!session_vnc->source)
- grd_session_vnc_attach_source (session_vnc);
+ if (grd_session_vnc_is_paused (session_vnc))
+ grd_session_vnc_resume (session_vnc);
}
static void
@@ -790,4 +835,17 @@ grd_session_vnc_class_init (GrdSessionVncClass *klass)
session_class->stop = grd_session_vnc_stop;
session_class->stream_ready = grd_session_vnc_stream_ready;
+
+ signals[PAUSED] = g_signal_new ("paused",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ signals[RESUMED] = g_signal_new ("resumed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
}
--
2.26.2
From ed3d72cb8d08192831397903f0ba92f439751988 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:03:46 +0100
Subject: [PATCH 3/7] session-vnc: Add grd_session_vnc_dispatch() helper
To be used by the TLS channel security to dispatch when there is data
available that is not visible to the socket source.
---
src/grd-session-vnc.c | 26 ++++++++++++++++----------
src/grd-session-vnc.h | 2 ++
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 076e25f..8b8ce1b 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -622,6 +622,21 @@ vnc_socket_grab_func (GrdSessionVnc *session_vnc,
return TRUE;
}
+void
+grd_session_vnc_dispatch (GrdSessionVnc *session_vnc)
+{
+ GrdVncSocketGrabFunc grab_func;
+ g_autoptr (GError) error = NULL;
+
+ grab_func = g_list_first (session_vnc->socket_grabs)->data;
+ if (!grab_func (session_vnc, &error))
+ {
+ g_warning ("Error when reading socket: %s", error->message);
+
+ grd_session_stop (GRD_SESSION (session_vnc));
+ }
+}
+
static gboolean
handle_socket_data (GSocket *socket,
GIOCondition condition,
@@ -638,16 +653,7 @@ handle_socket_data (GSocket *socket,
}
else if (condition & G_IO_IN)
{
- GrdVncSocketGrabFunc grab_func;
- g_autoptr (GError) error = NULL;
-
- grab_func = g_list_first (session_vnc->socket_grabs)->data;
- if (!grab_func (session_vnc, &error))
- {
- g_warning ("Error when reading socket: %s", error->message);
-
- grd_session_stop (session);
- }
+ grd_session_vnc_dispatch (session_vnc);
}
else
{
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
index 46a8579..910b00c 100644
--- a/src/grd-session-vnc.h
+++ b/src/grd-session-vnc.h
@@ -68,6 +68,8 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc,
void grd_session_vnc_ungrab_socket (GrdSessionVnc *session_vnc,
GrdVncSocketGrabFunc grab_func);
+void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc);
+
GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc);
#endif /* GRD_SESSION_VNC_H */
--
2.26.2
From 44e6bec84a86064a7b3abbcbbcd07ebb525aca9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:05:13 +0100
Subject: [PATCH 4/7] vnc/tls: Add some logging
Uses the log utility from libvncserver as it is related to the RFB
protocol rather than the session itself.
---
src/grd-vnc-tls.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c
index ec4758e..ac6c35f 100644
--- a/src/grd-vnc-tls.c
+++ b/src/grd-vnc-tls.c
@@ -67,6 +67,7 @@ grd_vnc_tls_context_new (void)
tls_context = g_new0 (GrdVncTlsContext, 1);
+ rfbLog ("TLS: Initializing gnutls context\n");
gnutls_global_init ();
gnutls_anon_allocate_server_credentials (&tls_context->anon_credentials);
@@ -127,6 +128,7 @@ perform_anon_tls_handshake (GrdVncTlsSession *tls_session,
ret = gnutls_handshake (tls_session->tls_session);
if (ret != GNUTLS_E_SUCCESS && !gnutls_error_is_fatal (ret))
{
+ rfbLog ("TLS: More handshake pending\n");
tls_session->handshake_state = GRD_TLS_HANDSHAKE_STATE_DURING;
return TRUE;
}
@@ -140,6 +142,8 @@ perform_anon_tls_handshake (GrdVncTlsSession *tls_session,
return FALSE;
}
+ rfbLog ("TLS: Handshake finished");
+
tls_session->handshake_state = GRD_TLS_HANDSHAKE_STATE_FINISHED;
return TRUE;
}
@@ -373,6 +377,7 @@ perform_handshake (GrdSessionVnc *session_vnc,
break;
case GRD_TLS_HANDSHAKE_STATE_FINISHED:
grd_session_vnc_ungrab_socket (session_vnc, tls_handshake_grab_func);
+ rfbLog ("TLS: Sending post-channel security security list\n");
rfbSendSecurityTypeList (grd_session_vnc_get_rfb_client (session_vnc),
RFB_SECURITY_TAG_CHANNEL);
break;
@@ -387,6 +392,7 @@ tls_handshake_grab_func (GrdSessionVnc *session_vnc,
{
g_autoptr (GError) handshake_error = NULL;
+ rfbLog ("TLS: Continuing handshake\n");
if (!perform_handshake (session_vnc, &handshake_error))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -404,6 +410,8 @@ rfb_tls_security_handler (rfbClientPtr rfb_client)
GrdVncTlsSession *tls_session;
g_autoptr(GError) error = NULL;
+ rfbLog ("TLS: Setting up rfbClient for gnutls encrypted traffic\n");
+
tls_session = grd_vnc_tls_session_from_vnc_session (session_vnc);
if (!tls_session)
{
@@ -424,6 +432,7 @@ rfb_tls_security_handler (rfbClientPtr rfb_client)
grd_session_vnc_grab_socket (session_vnc, tls_handshake_grab_func);
}
+ rfbLog ("TLS: Performing handshake\n");
if (!perform_handshake (session_vnc, &error))
{
g_warning ("TLS handshake failed: %s", error->message);
--
2.26.2
From fc07db3b6fafec47e02ff81f0f893dcaf64ba988 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:07:40 +0100
Subject: [PATCH 5/7] vnc/tls: Dispatch also when data is pending outside of
the socket
gnutls may have data available in its buffers, and we have our own peek
buffer temporarly storing data later to be processed. This would missed
by the socket source, as it wouldn't get any notification about it from
epoll(). Deal with this by adding a custom source that dispatches as
long as there is data to read in those buffers.
---
src/grd-session-vnc.h | 2 +
src/grd-vnc-tls.c | 92 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 88 insertions(+), 6 deletions(-)
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
index 910b00c..294860e 100644
--- a/src/grd-session-vnc.h
+++ b/src/grd-session-vnc.h
@@ -68,6 +68,8 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc,
void grd_session_vnc_ungrab_socket (GrdSessionVnc *session_vnc,
GrdVncSocketGrabFunc grab_func);
+gboolean grd_session_vnc_is_paused (GrdSessionVnc *session_vnc);
+
void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc);
GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc);
diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c
index ac6c35f..8f65225 100644
--- a/src/grd-vnc-tls.c
+++ b/src/grd-vnc-tls.c
@@ -41,6 +41,12 @@ typedef enum _GrdTlsHandshakeState
GRD_TLS_HANDSHAKE_STATE_FINISHED
} GrdTlsHandshakeState;
+typedef struct _PeekBufferSource
+{
+ GSource parent;
+ GrdSessionVnc *session_vnc;
+} PeekBufferSource;
+
typedef struct _GrdVncTlsSession
{
GrdVncTlsContext *tls_context;
@@ -53,6 +59,8 @@ typedef struct _GrdVncTlsSession
char *peek_buffer;
int peek_buffer_size;
int peek_buffer_len;
+
+ GSource *peek_buffer_source;
} GrdVncTlsSession;
static gboolean
@@ -296,16 +304,14 @@ grd_vnc_tls_peek_at_socket (rfbClientPtr rfb_client,
peekable_len = MIN (len, tls_session->peek_buffer_len);
memcpy (buf, tls_session->peek_buffer, peekable_len);
+ fprintf(stderr, ":::: %s:%d %s() - peeked %d bytes, can peek %d bytes\n", __FILE__, __LINE__, __func__,
+ peekable_len, tls_session->peek_buffer_len);
return peekable_len;
}
-static rfbBool
-grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client)
+static gboolean
+grd_vnc_tls_session_has_pending_data (GrdVncTlsSession *tls_session)
{
- GrdSessionVnc *session_vnc = rfb_client->screen->screenData;
- GrdVncTlsSession *tls_session =
- grd_vnc_tls_session_from_vnc_session (session_vnc);
-
if (tls_session->peek_buffer_len > 0)
return TRUE;
@@ -315,6 +321,16 @@ grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client)
return FALSE;
}
+static rfbBool
+grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client)
+{
+ GrdSessionVnc *session_vnc = rfb_client->screen->screenData;
+ GrdVncTlsSession *tls_session =
+ grd_vnc_tls_session_from_vnc_session (session_vnc);
+
+ return grd_vnc_tls_session_has_pending_data (tls_session);
+}
+
static int
grd_vnc_tls_write_to_socket (rfbClientPtr rfb_client,
const char *buf,
@@ -403,6 +419,62 @@ tls_handshake_grab_func (GrdSessionVnc *session_vnc,
return TRUE;
}
+static gboolean
+peek_buffer_source_prepare (GSource *source,
+ int *timeout)
+{
+ PeekBufferSource *psource = (PeekBufferSource *) source;
+ GrdSessionVnc *session_vnc = psource->session_vnc;
+ GrdVncTlsSession *tls_session =
+ grd_vnc_tls_session_from_vnc_session (session_vnc);
+
+ return grd_vnc_tls_session_has_pending_data (tls_session);
+}
+
+static gboolean
+peek_buffer_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ PeekBufferSource *psource = (PeekBufferSource *) source;
+ GrdSessionVnc *session_vnc = psource->session_vnc;
+
+ grd_session_vnc_dispatch (session_vnc);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static GSourceFuncs peek_buffer_source_funcs = {
+ .prepare = peek_buffer_source_prepare,
+ .dispatch = peek_buffer_source_dispatch,
+};
+
+static void
+attach_peek_buffer_source (GrdSessionVnc *session_vnc)
+{
+ GrdVncTlsSession *tls_session;
+
+ tls_session = grd_vnc_tls_session_from_vnc_session (session_vnc);
+ tls_session->peek_buffer_source = g_source_new (&peek_buffer_source_funcs,
+ sizeof (PeekBufferSource));
+ ((PeekBufferSource *) tls_session->peek_buffer_source)->session_vnc =
+ session_vnc;
+ g_source_set_priority (tls_session->peek_buffer_source,
+ G_PRIORITY_DEFAULT + 1);
+
+ g_source_attach (tls_session->peek_buffer_source, NULL);
+}
+
+static void
+detach_peek_buffer_source (GrdSessionVnc *session_vnc)
+{
+ GrdVncTlsSession *tls_session;
+
+ tls_session = grd_vnc_tls_session_from_vnc_session (session_vnc);
+
+ g_clear_pointer (&tls_session->peek_buffer_source, g_source_destroy);
+}
+
static void
rfb_tls_security_handler (rfbClientPtr rfb_client)
{
@@ -429,6 +501,14 @@ rfb_tls_security_handler (rfbClientPtr rfb_client)
rfb_client->hasPendingOnSocket = grd_vnc_tls_has_pending_on_socket;
rfb_client->writeToSocket = grd_vnc_tls_write_to_socket;
+ if (!grd_session_vnc_is_paused (session_vnc))
+ attach_peek_buffer_source (session_vnc);
+
+ g_signal_connect (session_vnc, "paused",
+ G_CALLBACK (detach_peek_buffer_source), NULL);
+ g_signal_connect (session_vnc, "resumed",
+ G_CALLBACK (attach_peek_buffer_source), NULL);
+
grd_session_vnc_grab_socket (session_vnc, tls_handshake_grab_func);
}
--
2.26.2
From c582baab12c1e2dd2b512329da42880c40993df6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 16:48:00 +0100
Subject: [PATCH 6/7] session-vnc: Set our own password handling function up
front
libvncserver decides whether to register a auth security handler
depending on whether the password data is set or not. When we use the
prompt auth method, we don't want to ask for password, so set the
password data to NULL.
Also, to be a bit more in control of the password mechanism, always set
the password function up front, instead of just when the client uses the
password prompt.
---
src/grd-session-vnc.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 8b8ce1b..a93a2e3 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -91,11 +91,6 @@ grd_session_vnc_pause (GrdSessionVnc *session_vnc);
static gboolean
close_session_idle (gpointer user_data);
-static rfbBool
-check_rfb_password (rfbClientPtr rfb_client,
- const char *response_encrypted,
- int len);
-
static void
swap_uint8 (uint8_t *a,
uint8_t *b)
@@ -297,7 +292,6 @@ handle_new_client (rfbClientPtr rfb_client)
grd_session_vnc_pause (session_vnc);
return RFB_CLIENT_ON_HOLD;
case GRD_VNC_AUTH_METHOD_PASSWORD:
- session_vnc->rfb_screen->passwordCheck = check_rfb_password;
/*
* authPasswdData needs to be non NULL in libvncserver to trigger
* password authentication.
@@ -581,6 +575,8 @@ init_vnc_session (GrdSessionVnc *session_vnc)
rfb_screen->frameBuffer = g_malloc0 (screen_width * screen_height * 4);
memset (rfb_screen->frameBuffer, 0x1f, screen_width * screen_height * 4);
+ rfb_screen->passwordCheck = check_rfb_password;
+
rfbInitServer (rfb_screen);
rfbProcessEvents (rfb_screen, 0);
}
--
2.26.2
From b7fc232ee5272b430f28c33ebaacd501ff63a4dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 16:53:42 +0100
Subject: [PATCH 7/7] vnc: Unregister previously set security handlers on init
When we're starting a session, we're going to handle a new client
connection. However, any previous client that was ever run on in a
previous session would still have their "security handler" registered,
as such is a global permanent change in libvncserver right now.
To work around this, unregister all primary security handler (i.e.
'none' and 'password') when initializing the RFB screen. We'll set up
the preferred one when handling the new client.
---
src/grd-session-vnc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index a93a2e3..9fcbb69 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -555,6 +555,12 @@ init_vnc_session (GrdSessionVnc *session_vnc)
8, 3, 4);
session_vnc->rfb_screen = rfb_screen;
+ /*
+ * Unregister whatever security handler was used the last time; we'll set
+ * up new ones when authorizing the new client anyway.
+ */
+ rfbUnregisterPrimarySecurityHandlers ();
+
update_server_format (session_vnc);
socket = g_socket_connection_get_socket (session_vnc->connection);
--
2.26.2

View File

@ -0,0 +1,127 @@
From f97b689c5c67cee36025a7b0a9210deb8b373b03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 3 Jul 2020 17:03:52 +0200
Subject: [PATCH 1/3] session-vnc: Add API to flush
When no damage is to be reported, but e.g. cursor moved, we need to
flush, so add API to make this possible.
(cherry picked from commit 25e61a7ed3631687aed4310824e7810088e63b37)
---
src/grd-session-vnc.c | 6 ++++++
src/grd-session-vnc.h | 2 ++
2 files changed, 8 insertions(+)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 9fcbb69..7950d1e 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -179,6 +179,12 @@ grd_session_vnc_take_buffer (GrdSessionVnc *session_vnc,
rfbProcessEvents (session_vnc->rfb_screen, 0);
}
+void
+grd_session_vnc_flush (GrdSessionVnc *session_vnc)
+{
+ rfbProcessEvents (session_vnc->rfb_screen, 0);
+}
+
void
grd_session_vnc_set_cursor (GrdSessionVnc *session_vnc,
rfbCursorPtr rfb_cursor)
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
index 294860e..a065857 100644
--- a/src/grd-session-vnc.h
+++ b/src/grd-session-vnc.h
@@ -49,6 +49,8 @@ void grd_session_vnc_queue_resize_framebuffer (GrdSessionVnc *session_vnc,
void grd_session_vnc_take_buffer (GrdSessionVnc *session_vnc,
void *data);
+void grd_session_vnc_flush (GrdSessionVnc *session_vnc);
+
void grd_session_vnc_set_cursor (GrdSessionVnc *session_vnc,
rfbCursorPtr rfb_cursor);
--
2.26.2
From 8a050b66be76d73725ac7665295160ab6c40b0f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 3 Jul 2020 17:12:58 +0200
Subject: [PATCH 2/3] vnc-pipewire-stream: Properly process cursor-change-only
frames
Such frames will have the buffer data size set to 0, as it is empty, but
may contain metadata carrying the cursor update.
(cherry picked from commit c04762a450ea9a21730db26c296c1283e121dc08)
---
src/grd-vnc-pipewire-stream.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index a3f5fb6..7519377 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -312,7 +312,6 @@ process_buffer (GrdVncPipeWireStream *stream,
size_t size;
uint8_t *map;
void *src_data;
- int y;
struct spa_meta_cursor *spa_meta_cursor;
g_autofree GrdVncFrame *frame = NULL;
@@ -320,8 +319,8 @@ process_buffer (GrdVncPipeWireStream *stream,
if (buffer->datas[0].chunk->size == 0)
{
- g_warning ("Received empty buffer");
- return NULL;
+ map = NULL;
+ src_data = NULL;
}
else if (buffer->datas[0].type == SPA_DATA_MemFd)
{
@@ -367,6 +366,7 @@ process_buffer (GrdVncPipeWireStream *stream,
int src_stride;
int dst_stride;
int height;
+ int y;
src_stride = buffer->datas[0].chunk->stride;
dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session);
--
2.26.2
From eac6368d8411c586007df8b1a2d85df3da1b55c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 3 Jul 2020 17:13:58 +0200
Subject: [PATCH 3/3] vnc-pipewire-stream: Flush connection if no new pixel
buffer
Otherwise we'll wait on input until we flush out our new cursor move
only output.
(cherry picked from commit 3394e34c3c502d63636bb852c062855c46736a6f)
---
src/grd-vnc-pipewire-stream.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index 7519377..791b71d 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -299,6 +299,8 @@ do_render (struct spa_loop *loop,
if (frame->data)
grd_session_vnc_take_buffer (stream->session, frame->data);
+ else
+ grd_session_vnc_flush (stream->session);
g_free (frame);
--
2.26.2

View File

@ -1,492 +0,0 @@
From 08d9c7e41882e5e4821de2c9bc2035043f2ca1a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:02:09 +0100
Subject: [PATCH 1/4] session-vnc: Add paused/resumed signals
Paused is when the socket sourec is detached, and resumed when attached.
Meant to be used by the TLS channel security to a attach/detach
out-of-socket source.
---
src/grd-session-vnc.c | 72 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 65 insertions(+), 7 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index dcd8599..6be8330 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -40,14 +40,27 @@
#define BGRX_SAMPLES_PER_PIXEL 3
#define BGRX_BYTES_PER_PIXEL 4
+enum
+{
+ PAUSED,
+ RESUMED,
+
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
struct _GrdSessionVnc
{
GrdSession parent;
GrdVncServer *vnc_server;
GSocketConnection *connection;
+
GList *socket_grabs;
GSource *source;
+ gboolean is_paused;
+
rfbScreenInfoPtr rfb_screen;
rfbClientPtr rfb_client;
@@ -73,7 +86,7 @@ struct _GrdSessionVnc
G_DEFINE_TYPE (GrdSessionVnc, grd_session_vnc, GRD_TYPE_SESSION);
static void
-grd_session_vnc_detach_source (GrdSessionVnc *session_vnc);
+grd_session_vnc_pause (GrdSessionVnc *session_vnc);
static gboolean
close_session_idle (gpointer user_data);
@@ -215,7 +228,8 @@ handle_client_gone (rfbClientPtr rfb_client)
g_debug ("VNC client gone");
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
+
maybe_queue_close_session_idle (session_vnc);
}
@@ -283,7 +297,7 @@ handle_new_client (rfbClientPtr rfb_client)
session_vnc->prompt_cancellable,
prompt_response_callback,
session_vnc);
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
return RFB_CLIENT_ON_HOLD;
case GRD_VNC_AUTH_METHOD_PASSWORD:
session_vnc->rfb_screen->passwordCheck = check_rfb_password;
@@ -501,7 +515,7 @@ check_rfb_password (rfbClientPtr rfb_client,
if (memcmp (challenge_encrypted, response_encrypted, len) == 0)
{
grd_session_start (GRD_SESSION (session_vnc));
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
return TRUE;
}
else
@@ -670,6 +684,36 @@ grd_session_vnc_detach_source (GrdSessionVnc *session_vnc)
g_clear_pointer (&session_vnc->source, g_source_destroy);
}
+gboolean
+grd_session_vnc_is_paused (GrdSessionVnc *session_vnc)
+{
+ return session_vnc->is_paused;
+}
+
+static void
+grd_session_vnc_pause (GrdSessionVnc *session_vnc)
+{
+ if (grd_session_vnc_is_paused (session_vnc))
+ return;
+
+ session_vnc->is_paused = TRUE;
+
+ grd_session_vnc_detach_source (session_vnc);
+ g_signal_emit (session_vnc, signals[PAUSED], 0);
+}
+
+static void
+grd_session_vnc_resume (GrdSessionVnc *session_vnc)
+{
+ if (!grd_session_vnc_is_paused (session_vnc))
+ return;
+
+ session_vnc->is_paused = FALSE;
+
+ grd_session_vnc_attach_source (session_vnc);
+ g_signal_emit (session_vnc, signals[RESUMED], 0);
+}
+
GrdSessionVnc *
grd_session_vnc_new (GrdVncServer *vnc_server,
GSocketConnection *connection)
@@ -687,6 +731,7 @@ grd_session_vnc_new (GrdVncServer *vnc_server,
grd_session_vnc_grab_socket (session_vnc, vnc_socket_grab_func);
grd_session_vnc_attach_source (session_vnc);
+ session_vnc->is_paused = FALSE;
init_vnc_session (session_vnc);
@@ -716,7 +761,7 @@ grd_session_vnc_stop (GrdSession *session)
g_clear_object (&session_vnc->pipewire_stream);
- grd_session_vnc_detach_source (session_vnc);
+ grd_session_vnc_pause (session_vnc);
g_clear_object (&session_vnc->connection);
g_clear_pointer (&session_vnc->rfb_screen->frameBuffer, g_free);
@@ -772,8 +817,8 @@ grd_session_vnc_stream_ready (GrdSession *session,
G_CALLBACK (on_pipwire_stream_closed),
session_vnc);
- if (!session_vnc->source)
- grd_session_vnc_attach_source (session_vnc);
+ if (grd_session_vnc_is_paused (session_vnc))
+ grd_session_vnc_resume (session_vnc);
}
static void
@@ -792,4 +837,17 @@ grd_session_vnc_class_init (GrdSessionVncClass *klass)
session_class->stop = grd_session_vnc_stop;
session_class->stream_ready = grd_session_vnc_stream_ready;
+
+ signals[PAUSED] = g_signal_new ("paused",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ signals[RESUMED] = g_signal_new ("resumed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
}
--
2.23.0
From b27fe979adf4910f4173370091a06b6a945f83ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:03:46 +0100
Subject: [PATCH 2/4] session-vnc: Add grd_session_vnc_dispatch() helper
To be used by the TLS channel security to dispatch when there is data
available that is not visible to the socket source.
---
src/grd-session-vnc.c | 26 ++++++++++++++++----------
src/grd-session-vnc.h | 2 ++
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 6be8330..c5f83d8 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -624,6 +624,21 @@ vnc_socket_grab_func (GrdSessionVnc *session_vnc,
return TRUE;
}
+void
+grd_session_vnc_dispatch (GrdSessionVnc *session_vnc)
+{
+ GrdVncSocketGrabFunc grab_func;
+ g_autoptr (GError) error = NULL;
+
+ grab_func = g_list_first (session_vnc->socket_grabs)->data;
+ if (!grab_func (session_vnc, &error))
+ {
+ g_warning ("Error when reading socket: %s", error->message);
+
+ grd_session_stop (GRD_SESSION (session_vnc));
+ }
+}
+
static gboolean
handle_socket_data (GSocket *socket,
GIOCondition condition,
@@ -640,16 +655,7 @@ handle_socket_data (GSocket *socket,
}
else if (condition & G_IO_IN)
{
- GrdVncSocketGrabFunc grab_func;
- g_autoptr (GError) error = NULL;
-
- grab_func = g_list_first (session_vnc->socket_grabs)->data;
- if (!grab_func (session_vnc, &error))
- {
- g_warning ("Error when reading socket: %s", error->message);
-
- grd_session_stop (session);
- }
+ grd_session_vnc_dispatch (session_vnc);
}
else
{
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
index 789693e..e699d64 100644
--- a/src/grd-session-vnc.h
+++ b/src/grd-session-vnc.h
@@ -68,6 +68,8 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc,
void grd_session_vnc_ungrab_socket (GrdSessionVnc *session_vnc,
GrdVncSocketGrabFunc grab_func);
+void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc);
+
GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc);
#endif /* GRD_SESSION_VNC_H */
--
2.23.0
From bb4e67869e9226c7e10907d59fee3247b3a7fa8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:05:13 +0100
Subject: [PATCH 3/4] vnc/tls: Add some logging
Uses the log utility from libvncserver as it is related to the RFB
protocol rather than the session itself.
---
src/grd-vnc-tls.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c
index 8fc0fc2..fb24b34 100644
--- a/src/grd-vnc-tls.c
+++ b/src/grd-vnc-tls.c
@@ -67,6 +67,7 @@ grd_vnc_tls_context_new (void)
tls_context = g_new0 (GrdVncTlsContext, 1);
+ rfbLog ("TLS: Initializing gnutls context\n");
gnutls_global_init ();
gnutls_anon_allocate_server_credentials (&tls_context->anon_credentials);
@@ -127,6 +128,7 @@ perform_anon_tls_handshake (GrdVncTlsSession *tls_session,
ret = gnutls_handshake (tls_session->tls_session);
if (ret != GNUTLS_E_SUCCESS && !gnutls_error_is_fatal (ret))
{
+ rfbLog ("TLS: More handshake pending\n");
tls_session->handshake_state = GRD_TLS_HANDSHAKE_STATE_DURING;
return TRUE;
}
@@ -140,6 +142,8 @@ perform_anon_tls_handshake (GrdVncTlsSession *tls_session,
return FALSE;
}
+ rfbLog ("TLS: Handshake finished");
+
tls_session->handshake_state = GRD_TLS_HANDSHAKE_STATE_FINISHED;
return TRUE;
}
@@ -373,6 +377,7 @@ perform_handshake (GrdSessionVnc *session_vnc,
break;
case GRD_TLS_HANDSHAKE_STATE_FINISHED:
grd_session_vnc_ungrab_socket (session_vnc, tls_handshake_grab_func);
+ rfbLog ("TLS: Sending post-channel security security list\n");
rfbSendSecurityTypeList (grd_session_vnc_get_rfb_client (session_vnc),
RFB_SECURITY_TAG_CHANNEL);
break;
@@ -387,6 +392,7 @@ tls_handshake_grab_func (GrdSessionVnc *session_vnc,
{
g_autoptr (GError) handshake_error = NULL;
+ rfbLog ("TLS: Continuing handshake\n");
if (!perform_handshake (session_vnc, &handshake_error))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -404,6 +410,8 @@ rfb_tls_security_handler (rfbClientPtr rfb_client)
GrdVncTlsSession *tls_session;
g_autoptr(GError) error = NULL;
+ rfbLog ("TLS: Setting up rfbClient for gnutls encrypted traffic\n");
+
tls_session = grd_vnc_tls_session_from_vnc_session (session_vnc);
if (!tls_session)
{
@@ -424,6 +432,7 @@ rfb_tls_security_handler (rfbClientPtr rfb_client)
grd_session_vnc_grab_socket (session_vnc, tls_handshake_grab_func);
}
+ rfbLog ("TLS: Performing handshake\n");
if (!perform_handshake (session_vnc, &error))
{
g_warning ("TLS handshake failed: %s", error->message);
--
2.23.0
From 707425d19861295bb64e5558d1f81175d0327429 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 11:07:40 +0100
Subject: [PATCH 4/4] vnc/tls: Dispatch also when data is pending outside of
the socket
gnutls may have data available in its buffers, and we have our own peek
buffer temporarly storing data later to be processed. This would missed
by the socket source, as it wouldn't get any notification about it from
epoll(). Deal with this by adding a custom source that dispatches as
long as there is data to read in those buffers.
---
src/grd-session-vnc.h | 2 +
src/grd-vnc-tls.c | 92 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 88 insertions(+), 6 deletions(-)
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
index e699d64..5a74b5f 100644
--- a/src/grd-session-vnc.h
+++ b/src/grd-session-vnc.h
@@ -68,6 +68,8 @@ void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc,
void grd_session_vnc_ungrab_socket (GrdSessionVnc *session_vnc,
GrdVncSocketGrabFunc grab_func);
+gboolean grd_session_vnc_is_paused (GrdSessionVnc *session_vnc);
+
void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc);
GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc);
diff --git a/src/grd-vnc-tls.c b/src/grd-vnc-tls.c
index fb24b34..815b40b 100644
--- a/src/grd-vnc-tls.c
+++ b/src/grd-vnc-tls.c
@@ -41,6 +41,12 @@ typedef enum _GrdTlsHandshakeState
GRD_TLS_HANDSHAKE_STATE_FINISHED
} GrdTlsHandshakeState;
+typedef struct _PeekBufferSource
+{
+ GSource parent;
+ GrdSessionVnc *session_vnc;
+} PeekBufferSource;
+
typedef struct _GrdVncTlsSession
{
GrdVncTlsContext *tls_context;
@@ -53,6 +59,8 @@ typedef struct _GrdVncTlsSession
char *peek_buffer;
int peek_buffer_size;
int peek_buffer_len;
+
+ GSource *peek_buffer_source;
} GrdVncTlsSession;
static gboolean
@@ -296,16 +304,14 @@ grd_vnc_tls_peek_at_socket (rfbClientPtr rfb_client,
peekable_len = MIN (len, tls_session->peek_buffer_len);
memcpy (buf, tls_session->peek_buffer, peekable_len);
+ fprintf(stderr, ":::: %s:%d %s() - peeked %d bytes, can peek %d bytes\n", __FILE__, __LINE__, __func__,
+ peekable_len, tls_session->peek_buffer_len);
return peekable_len;
}
-static rfbBool
-grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client)
+static gboolean
+grd_vnc_tls_session_has_pending_data (GrdVncTlsSession *tls_session)
{
- GrdSessionVnc *session_vnc = rfb_client->screen->screenData;
- GrdVncTlsSession *tls_session =
- grd_vnc_tls_session_from_vnc_session (session_vnc);
-
if (tls_session->peek_buffer_len > 0)
return TRUE;
@@ -315,6 +321,16 @@ grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client)
return FALSE;
}
+static rfbBool
+grd_vnc_tls_has_pending_on_socket (rfbClientPtr rfb_client)
+{
+ GrdSessionVnc *session_vnc = rfb_client->screen->screenData;
+ GrdVncTlsSession *tls_session =
+ grd_vnc_tls_session_from_vnc_session (session_vnc);
+
+ return grd_vnc_tls_session_has_pending_data (tls_session);
+}
+
static int
grd_vnc_tls_write_to_socket (rfbClientPtr rfb_client,
const char *buf,
@@ -403,6 +419,62 @@ tls_handshake_grab_func (GrdSessionVnc *session_vnc,
return TRUE;
}
+static gboolean
+peek_buffer_source_prepare (GSource *source,
+ int *timeout)
+{
+ PeekBufferSource *psource = (PeekBufferSource *) source;
+ GrdSessionVnc *session_vnc = psource->session_vnc;
+ GrdVncTlsSession *tls_session =
+ grd_vnc_tls_session_from_vnc_session (session_vnc);
+
+ return grd_vnc_tls_session_has_pending_data (tls_session);
+}
+
+static gboolean
+peek_buffer_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ PeekBufferSource *psource = (PeekBufferSource *) source;
+ GrdSessionVnc *session_vnc = psource->session_vnc;
+
+ grd_session_vnc_dispatch (session_vnc);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static GSourceFuncs peek_buffer_source_funcs = {
+ .prepare = peek_buffer_source_prepare,
+ .dispatch = peek_buffer_source_dispatch,
+};
+
+static void
+attach_peek_buffer_source (GrdSessionVnc *session_vnc)
+{
+ GrdVncTlsSession *tls_session;
+
+ tls_session = grd_vnc_tls_session_from_vnc_session (session_vnc);
+ tls_session->peek_buffer_source = g_source_new (&peek_buffer_source_funcs,
+ sizeof (PeekBufferSource));
+ ((PeekBufferSource *) tls_session->peek_buffer_source)->session_vnc =
+ session_vnc;
+ g_source_set_priority (tls_session->peek_buffer_source,
+ G_PRIORITY_DEFAULT + 1);
+
+ g_source_attach (tls_session->peek_buffer_source, NULL);
+}
+
+static void
+detach_peek_buffer_source (GrdSessionVnc *session_vnc)
+{
+ GrdVncTlsSession *tls_session;
+
+ tls_session = grd_vnc_tls_session_from_vnc_session (session_vnc);
+
+ g_clear_pointer (&tls_session->peek_buffer_source, g_source_destroy);
+}
+
static void
rfb_tls_security_handler (rfbClientPtr rfb_client)
{
@@ -429,6 +501,14 @@ rfb_tls_security_handler (rfbClientPtr rfb_client)
rfb_client->hasPendingOnSocket = grd_vnc_tls_has_pending_on_socket;
rfb_client->writeToSocket = grd_vnc_tls_write_to_socket;
+ if (!grd_session_vnc_is_paused (session_vnc))
+ attach_peek_buffer_source (session_vnc);
+
+ g_signal_connect (session_vnc, "paused",
+ G_CALLBACK (detach_peek_buffer_source), NULL);
+ g_signal_connect (session_vnc, "resumed",
+ G_CALLBACK (attach_peek_buffer_source), NULL);
+
grd_session_vnc_grab_socket (session_vnc, tls_handshake_grab_func);
}
--
2.23.0

View File

@ -1,719 +0,0 @@
From b9221b1efcfe205409628bf365008e0b248725f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 23 Nov 2018 16:55:20 +0100
Subject: [PATCH 1/6] vnc: Detach source when client is gone
LibVNCServer will close the socket for us, so don't keep the socket
source attached after a client is gone. It's not fast enough to close it
in the idle function, as that means we'd get a G_IO_NVAL error when the
source is processed.
Fixes: https://gitlab.gnome.org/jadahl/gnome-remote-desktop/issues/23
---
src/grd-session-vnc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 3c98eeb..fbf41e2 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -182,6 +182,7 @@ handle_client_gone (rfbClientPtr rfb_client)
g_debug ("VNC client gone");
+ grd_session_vnc_detach_source (session_vnc);
maybe_queue_close_session_idle (session_vnc);
}
--
2.19.1
From 5ce2a1a6f80581d7d5b79b3a86f6707d22ad94ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 26 Nov 2018 16:37:12 +0100
Subject: [PATCH 2/6] session/vnc: Always set pixel format translate functions
Internally LibVNCServer uses RGBX, but we provide BGRX. Currently the
LibVNCServer API doesn't allow to override this, but internally, it
supports any order of the color components. We relied on this already,
to avoid an extra pixel conversion, but we failed to update the
conversion table.
Fixes: https://gitlab.gnome.org/jadahl/gnome-remote-desktop/issues/20
---
src/grd-session-vnc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index fbf41e2..c6be742 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -115,11 +115,13 @@ resize_vnc_framebuffer (GrdSessionVnc *session_vnc,
BGRX_BYTES_PER_PIXEL);
/*
- * Our format is hard coded to BGRX but LibVNCServer asusumes it's RGBX;
+ * Our format is hard coded to BGRX but LibVNCServer assumes it's RGBX;
* lets override that.
*/
+
swap_uint8 (&session_vnc->rfb_screen->serverFormat.redShift,
&session_vnc->rfb_screen->serverFormat.blueShift);
+ rfb_screen->setTranslateFunction (session_vnc->rfb_client);
}
void
--
2.19.1
From b3bb9ebb47a9883c1022a1ad3dc90aa9bb9c2d27 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 17 Dec 2018 13:12:38 +0100
Subject: [PATCH 3/6] session/vnc: Update server format earlier too
We update the server protocol to swap the blue and red shift levels, as
LibVNCServer only RGBX by default, but we pass BGRX. Doing this just
after resizing the framebuffer where the format is updated is too late
though, as for some reason LibVNCServer's tight encoding still gets it
wrong when encoding JPEG rects.
Fixes: https://gitlab.gnome.org/jadahl/gnome-remote-desktop/issues/20
---
src/grd-session-vnc.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index c6be742..b86c3a7 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -94,6 +94,19 @@ swap_uint8 (uint8_t *a,
*b = tmp;
}
+static void
+update_server_format (GrdSessionVnc *session_vnc)
+{
+ rfbScreenInfoPtr rfb_screen = session_vnc->rfb_screen;
+
+ /*
+ * Our format is hard coded to BGRX but LibVNCServer assumes it's RGBX;
+ * lets override that.
+ */
+ swap_uint8 (&rfb_screen->serverFormat.redShift,
+ &rfb_screen->serverFormat.blueShift);
+}
+
static void
resize_vnc_framebuffer (GrdSessionVnc *session_vnc,
int width,
@@ -114,13 +127,7 @@ resize_vnc_framebuffer (GrdSessionVnc *session_vnc,
BGRX_SAMPLES_PER_PIXEL,
BGRX_BYTES_PER_PIXEL);
- /*
- * Our format is hard coded to BGRX but LibVNCServer assumes it's RGBX;
- * lets override that.
- */
-
- swap_uint8 (&session_vnc->rfb_screen->serverFormat.redShift,
- &session_vnc->rfb_screen->serverFormat.blueShift);
+ update_server_format (session_vnc);
rfb_screen->setTranslateFunction (session_vnc->rfb_client);
}
@@ -517,6 +524,7 @@ init_vnc_session (GrdSessionVnc *session_vnc)
rfb_screen = rfbGetScreen (0, NULL,
screen_width, screen_height,
8, 3, 4);
+ update_server_format (session_vnc);
socket = g_socket_connection_get_socket (session_vnc->connection);
rfb_screen->inetdSock = g_socket_get_fd (socket);
--
2.19.1
From 930d1c127e4a2252e3288cd3c752debe88d938c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 17 Dec 2018 14:35:17 +0100
Subject: [PATCH 4/6] vnc: Request cursor sprite as PipeWire metadata
This allows sending cursor updates, including position and cursor
sprite, without having to embed it into the framebuffer. In effect, when
there is a hardware cursor in the compositor, moving the cursor will not
result in any actual frames being copied.
The actual cursor sprite sent over VNC is derived from the cursor sprite
used in the compositor. The conversion is lossy, as the VNC cursor
sprite is a 3 bits per pixel (transparen, white or black), and the cursor
sprite from the compositor is 32 bits per pixel.
This bumps the PipeWire requirement to 0.2.5.
---
meson.build | 2 +-
src/grd-session-vnc.c | 24 +++++++
src/grd-session-vnc.h | 7 ++
src/grd-session.c | 10 +++
src/grd-types.h | 5 ++
src/grd-vnc-cursor.c | 125 ++++++++++++++++++++++++++++++++++
src/grd-vnc-cursor.h | 37 ++++++++++
src/grd-vnc-pipewire-stream.c | 94 +++++++++++++++++++++++--
src/meson.build | 2 +
9 files changed, 299 insertions(+), 7 deletions(-)
create mode 100644 src/grd-vnc-cursor.c
create mode 100644 src/grd-vnc-cursor.h
diff --git a/meson.build b/meson.build
index cb0d5fe..b6bfb6f 100644
--- a/meson.build
+++ b/meson.build
@@ -10,7 +10,7 @@ gnome = import('gnome')
glib_dep = dependency('glib-2.0')
gio_dep = dependency('gio-2.0')
gio_unix_dep = dependency('gio-unix-2.0')
-pipewire_dep = dependency('libpipewire-0.2', version: '>= 0.2.2')
+pipewire_dep = dependency('libpipewire-0.2', version: '>= 0.2.5')
systemd_dep = dependency('systemd')
libvncserver_dep = dependency('libvncserver')
libsecret_dep = dependency('libsecret-1')
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index b86c3a7..247c130 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -174,6 +174,30 @@ grd_session_vnc_draw_buffer (GrdSessionVnc *session_vnc,
rfbProcessEvents (session_vnc->rfb_screen, 0);
}
+void
+grd_session_vnc_set_cursor (GrdSessionVnc *session_vnc,
+ rfbCursorPtr rfb_cursor)
+{
+ rfbSetCursor (session_vnc->rfb_screen, rfb_cursor);
+}
+
+void
+grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc,
+ int x,
+ int y)
+{
+ if (session_vnc->rfb_screen->cursorX == x ||
+ session_vnc->rfb_screen->cursorY == y)
+ return;
+
+ LOCK (session_vnc->rfb_screen->cursorMutex);
+ session_vnc->rfb_screen->cursorX = x;
+ session_vnc->rfb_screen->cursorY = y;
+ UNLOCK (session_vnc->rfb_screen->cursorMutex);
+
+ session_vnc->rfb_client->cursorWasMoved = TRUE;
+}
+
static void
maybe_queue_close_session_idle (GrdSessionVnc *session_vnc)
{
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
index 33245bc..789693e 100644
--- a/src/grd-session-vnc.h
+++ b/src/grd-session-vnc.h
@@ -51,6 +51,13 @@ void grd_session_vnc_draw_buffer (GrdSessionVnc *session_vnc,
int grd_session_vnc_get_fd (GrdSessionVnc *session_vnc);
+void grd_session_vnc_set_cursor (GrdSessionVnc *session_vnc,
+ rfbCursorPtr rfb_cursor);
+
+void grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc,
+ int x,
+ int y);
+
int grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc);
rfbClientPtr grd_session_vnc_get_rfb_client (GrdSessionVnc *session_vnc);
diff --git a/src/grd-session.c b/src/grd-session.c
index 212770b..3697584 100644
--- a/src/grd-session.c
+++ b/src/grd-session.c
@@ -47,6 +47,13 @@ enum
static guint signals[LAST_SIGNAL];
+typedef enum _GrdScreenCastCursorMode
+{
+ GRD_SCREEN_CAST_CURSOR_MODE_HIDDEN = 0,
+ GRD_SCREEN_CAST_CURSOR_MODE_EMBEDDED = 1,
+ GRD_SCREEN_CAST_CURSOR_MODE_METADATA = 2,
+} GrdScreenCastCursorMode;
+
typedef struct _GrdSessionPrivate
{
GrdContext *context;
@@ -296,6 +303,9 @@ on_screen_cast_session_proxy_acquired (GObject *object,
priv->screen_cast_session = session_proxy;
g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&properties_builder, "{sv}",
+ "cursor-mode",
+ g_variant_new_uint32 (GRD_SCREEN_CAST_CURSOR_MODE_METADATA));
/* TODO: Support something other than primary monitor */
grd_dbus_screen_cast_session_call_record_monitor (session_proxy,
diff --git a/src/grd-types.h b/src/grd-types.h
index af92c88..89dd22f 100644
--- a/src/grd-types.h
+++ b/src/grd-types.h
@@ -31,4 +31,9 @@ typedef struct _GrdPipeWireStream GrdPipeWireStream;
typedef struct _GrdPipeWireStreamMonitor GrdPipeWireStreamMonitor;
typedef struct _GrdVncServer GrdVncServer;
+typedef enum _GrdPixelFormat
+{
+ GRD_PIXEL_FORMAT_RGBA8888,
+} GrdPixelFormat;
+
#endif /* GRD_TYPES_H */
diff --git a/src/grd-vnc-cursor.c b/src/grd-vnc-cursor.c
new file mode 100644
index 0000000..c0cb1aa
--- /dev/null
+++ b/src/grd-vnc-cursor.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2018 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "grd-vnc-cursor.h"
+
+#include <glib.h>
+#include <stdint.h>
+
+static void
+get_pixel_components (uint32_t pixel,
+ GrdPixelFormat format,
+ uint8_t *a,
+ uint8_t *r,
+ uint8_t *g,
+ uint8_t *b)
+{
+ g_assert (format == GRD_PIXEL_FORMAT_RGBA8888);
+
+ *a = (pixel & 0xff000000) >> 24;
+ *b = (pixel & 0xff0000) >> 16;
+ *g = (pixel & 0xff00) >> 8;
+ *r = pixel & 0xff;
+}
+
+static gboolean
+is_practically_black (uint8_t r,
+ uint8_t g,
+ uint8_t b)
+{
+ if (r <= 0x62 &&
+ g <= 0x62 &&
+ b <= 0x62)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gboolean
+is_practically_opaque (uint8_t a)
+{
+ return a > 0xe0;
+}
+
+rfbCursorPtr
+grd_vnc_create_cursor (int width,
+ int height,
+ int stride,
+ GrdPixelFormat format,
+ uint8_t *buf)
+{
+ g_autofree char *cursor = NULL;
+ g_autofree char *mask = NULL;
+ int y;
+
+ g_return_val_if_fail (format == GRD_PIXEL_FORMAT_RGBA8888, NULL);
+
+ cursor = g_new0 (char, width * height);
+ mask = g_new0 (char, width * height);
+
+ for (y = 0; y < height; y++)
+ {
+ uint32_t *pixel_row;
+ int x;
+
+ pixel_row = (uint32_t *) &buf[y * stride];
+
+ for (x = 0; x < width; x++)
+ {
+ uint32_t pixel = pixel_row[x];
+ uint8_t a, r, g, b;
+
+ get_pixel_components (pixel,
+ format,
+ &a, &r, &g, &b);
+
+ if (is_practically_opaque (a))
+ {
+ if (is_practically_black (r, g, b))
+ cursor[y * width + x] = ' ';
+ else
+ cursor[y * width + x] = 'x';
+
+ mask[y * width + x] = 'x';
+ }
+ else
+ {
+ cursor[y * width + x] = ' ';
+ mask[y * width + x] = ' ';
+ }
+ }
+ }
+
+ return rfbMakeXCursor (width, height, cursor, mask);
+}
+
+rfbCursorPtr
+grd_vnc_create_empty_cursor (int width,
+ int height)
+{
+ g_autofree char *cursor = NULL;
+ cursor = g_new0 (char, width * height);
+
+ memset (cursor, ' ', width * height);
+
+ return rfbMakeXCursor (width, height, cursor, cursor);
+}
diff --git a/src/grd-vnc-cursor.h b/src/grd-vnc-cursor.h
new file mode 100644
index 0000000..36bd0fb
--- /dev/null
+++ b/src/grd-vnc-cursor.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#ifndef GRD_VNC_CURSOR_H
+#define GRD_VNC_CURSOR_H
+
+#include <rfb/rfb.h>
+
+#include "grd-types.h"
+
+rfbCursorPtr grd_vnc_create_cursor (int width,
+ int height,
+ int stride,
+ GrdPixelFormat format,
+ uint8_t *buf);
+
+rfbCursorPtr grd_vnc_create_empty_cursor (int width,
+ int height);
+
+#endif /* GRD_VNC_CURSOR_H */
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index d6454b8..c341887 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -28,6 +28,8 @@
#include <spa/param/video/format-utils.h>
#include <sys/mman.h>
+#include "grd-vnc-cursor.h"
+
enum
{
CLOSED,
@@ -43,6 +45,7 @@ typedef struct _GrdSpaType
struct spa_type_media_subtype media_subtype;
struct spa_type_format_video format_video;
struct spa_type_video_format video_format;
+ uint32_t meta_cursor;
} GrdSpaType;
typedef struct _GrdPipeWireSource
@@ -79,6 +82,11 @@ struct _GrdVncPipeWireStream
G_DEFINE_TYPE (GrdVncPipeWireStream, grd_vnc_pipewire_stream,
G_TYPE_OBJECT)
+#define CURSOR_META_SIZE(width, height) \
+ (sizeof(struct spa_meta_cursor) + \
+ sizeof(struct spa_meta_bitmap) + width * height * 4)
+
+
static void
init_spa_type (GrdSpaType *type,
struct spa_type_map *map)
@@ -87,6 +95,7 @@ init_spa_type (GrdSpaType *type,
spa_type_media_subtype_map (map, &type->media_subtype);
spa_type_format_video_map (map, &type->format_video);
spa_type_video_format_map (map, &type->video_format);
+ type->meta_cursor = spa_type_map_get_id (map, SPA_TYPE_META__Cursor);
}
static gboolean
@@ -196,7 +205,7 @@ on_stream_format_changed (void *user_data,
int height;
int stride;
int size;
- const struct spa_pod *params[2];
+ const struct spa_pod *params[3];
if (!format)
{
@@ -231,7 +240,29 @@ on_stream_format_changed (void *user_data,
":", pipewire_type->param_meta.type, "I", pipewire_type->meta.Header,
":", pipewire_type->param_meta.size, "i", sizeof(struct spa_meta_header));
- pw_stream_finish_format (stream->pipewire_stream, 0, params, 2);
+ params[2] = spa_pod_builder_object(
+ &pod_builder,
+ pipewire_type->param.idMeta, pipewire_type->param_meta.Meta,
+ ":", pipewire_type->param_meta.type, "I", stream->spa_type.meta_cursor,
+ ":", pipewire_type->param_meta.size, "iru", CURSOR_META_SIZE (64,64),
+ SPA_POD_PROP_MIN_MAX (CURSOR_META_SIZE (1,1),
+ CURSOR_META_SIZE (256,256)));
+
+ pw_stream_finish_format (stream->pipewire_stream, 0,
+ params, G_N_ELEMENTS (params));
+}
+
+static gboolean
+spa_pixel_format_to_grd_pixel_format (GrdSpaType *spa_type,
+ uint32_t spa_format,
+ GrdPixelFormat *out_format)
+{
+ if (spa_format == spa_type->video_format.RGBA)
+ *out_format = GRD_PIXEL_FORMAT_RGBA8888;
+ else
+ return FALSE;
+
+ return TRUE;
}
static int
@@ -243,12 +274,19 @@ do_render (struct spa_loop *loop,
void *user_data)
{
GrdVncPipeWireStream *stream = GRD_VNC_PIPEWIRE_STREAM (user_data);
+ GrdSpaType *spa_type = &stream->spa_type;
struct spa_buffer *buffer = ((struct spa_buffer **) data)[0];
uint8_t *map;
void *src_data;
+ struct spa_meta_cursor *spa_meta_cursor;
- if (buffer->datas[0].type == stream->pipewire_type->data.MemFd ||
- buffer->datas[0].type == stream->pipewire_type->data.DmaBuf)
+ if (buffer->datas[0].chunk->size == 0)
+ {
+ map = NULL;
+ src_data = NULL;
+ }
+ else if (buffer->datas[0].type == stream->pipewire_type->data.MemFd ||
+ buffer->datas[0].type == stream->pipewire_type->data.DmaBuf)
{
map = mmap (NULL, buffer->datas[0].maxsize + buffer->datas[0].mapoffset,
PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0);
@@ -264,7 +302,51 @@ do_render (struct spa_loop *loop,
return -EINVAL;
}
- grd_session_vnc_draw_buffer (stream->session, src_data);
+ spa_meta_cursor = spa_buffer_find_meta (buffer, spa_type->meta_cursor);
+ if (spa_meta_cursor && spa_meta_cursor_is_valid (spa_meta_cursor))
+ {
+ struct spa_meta_bitmap *spa_meta_bitmap;
+ GrdPixelFormat format;
+
+ spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
+ spa_meta_cursor->bitmap_offset,
+ struct spa_meta_bitmap);
+
+ if (spa_meta_bitmap->size.width > 0 &&
+ spa_meta_bitmap->size.height > 0 &&
+ spa_pixel_format_to_grd_pixel_format (spa_type,
+ spa_meta_bitmap->format,
+ &format))
+ {
+ uint8_t *buf;
+ rfbCursorPtr rfb_cursor;
+
+ buf = SPA_MEMBER (spa_meta_bitmap, spa_meta_bitmap->offset, uint8_t);
+ rfb_cursor = grd_vnc_create_cursor (spa_meta_bitmap->size.width,
+ spa_meta_bitmap->size.height,
+ spa_meta_bitmap->stride,
+ format,
+ buf);
+ rfb_cursor->xhot = spa_meta_cursor->hotspot.x;
+ rfb_cursor->yhot = spa_meta_cursor->hotspot.y;
+
+ grd_session_vnc_set_cursor (stream->session, rfb_cursor);
+ }
+ else
+ {
+ rfbCursorPtr empty_cursor;
+
+ empty_cursor = grd_vnc_create_empty_cursor (1, 1);
+ grd_session_vnc_set_cursor (stream->session, empty_cursor);
+ }
+
+ grd_session_vnc_move_cursor (stream->session,
+ spa_meta_cursor->position.x,
+ spa_meta_cursor->position.y);
+ }
+
+ if (src_data)
+ grd_session_vnc_draw_buffer (stream->session, src_data);
if (map)
munmap (map, buffer->datas[0].maxsize + buffer->datas[0].mapoffset);
@@ -306,7 +388,7 @@ connect_to_stream (GrdVncPipeWireStream *stream,
struct spa_rectangle max_rect;
struct spa_fraction min_framerate;
struct spa_fraction max_framerate;
- const struct spa_pod *params[1];
+ const struct spa_pod *params[2];
int ret;
pipewire_stream = pw_stream_new (stream->pipewire_remote,
diff --git a/src/meson.build b/src/meson.build
index b633ad7..31c7221 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -15,6 +15,8 @@ daemon_sources = files([
'grd-stream.c',
'grd-stream.h',
'grd-types.h',
+ 'grd-vnc-cursor.c',
+ 'grd-vnc-cursor.h',
'grd-vnc-pipewire-stream.c',
'grd-vnc-pipewire-stream.h',
'grd-vnc-server.c',
--
2.19.1
From 6aff333ef474abfe18e0da964032e08e6cda2cd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 3 Jan 2019 18:07:33 +0100
Subject: [PATCH 5/6] session/vnc: Set rfbScreenPtr pointer earlier
Otherwise the format update_server_format() function doesn't find it.
---
src/grd-session-vnc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
index 247c130..dcd8599 100644
--- a/src/grd-session-vnc.c
+++ b/src/grd-session-vnc.c
@@ -548,6 +548,8 @@ init_vnc_session (GrdSessionVnc *session_vnc)
rfb_screen = rfbGetScreen (0, NULL,
screen_width, screen_height,
8, 3, 4);
+ session_vnc->rfb_screen = rfb_screen;
+
update_server_format (session_vnc);
socket = g_socket_connection_get_socket (session_vnc->connection);
@@ -567,8 +569,6 @@ init_vnc_session (GrdSessionVnc *session_vnc)
rfb_screen->frameBuffer = g_malloc0 (screen_width * screen_height * 4);
memset (rfb_screen->frameBuffer, 0x1f, screen_width * screen_height * 4);
- session_vnc->rfb_screen = rfb_screen;
-
rfbInitServer (rfb_screen);
rfbProcessEvents (rfb_screen, 0);
}
--
2.19.1
From 5d9ffd0efe8b32d95c1a566f431e7d14fa95f3fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 3 Jan 2019 18:08:52 +0100
Subject: [PATCH 6/6] vnc-pipewire-stream: Assume no bitmap offset means no
bitmap change
This is according to the agreed semantics:
https://github.com/PipeWire/pipewire/commit/8984c6f48d2106f143d3f6d5df976f788ecfde30
---
src/grd-vnc-pipewire-stream.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index c341887..cee569a 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -308,11 +308,19 @@ do_render (struct spa_loop *loop,
struct spa_meta_bitmap *spa_meta_bitmap;
GrdPixelFormat format;
- spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
- spa_meta_cursor->bitmap_offset,
- struct spa_meta_bitmap);
+ if (spa_meta_cursor->bitmap_offset)
+ {
+ spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
+ spa_meta_cursor->bitmap_offset,
+ struct spa_meta_bitmap);
+ }
+ else
+ {
+ spa_meta_bitmap = NULL;
+ }
- if (spa_meta_bitmap->size.width > 0 &&
+ if (spa_meta_bitmap &&
+ spa_meta_bitmap->size.width > 0 &&
spa_meta_bitmap->size.height > 0 &&
spa_pixel_format_to_grd_pixel_format (spa_type,
spa_meta_bitmap->format,
@@ -332,7 +340,7 @@ do_render (struct spa_loop *loop,
grd_session_vnc_set_cursor (stream->session, rfb_cursor);
}
- else
+ else if (spa_meta_bitmap)
{
rfbCursorPtr empty_cursor;
--
2.19.1

View File

@ -1,35 +1,27 @@
%global systemd_unit gnome-remote-desktop.service
Name: gnome-remote-desktop
Version: 0.1.6
Release: 8%{?dist}
Version: 0.1.8
Release: 3%{?dist}
Summary: GNOME Remote Desktop screen share service
License: GPLv2+
URL: https://gitlab.gnome.org/jadahl/gnome-remote-desktop
Source0: https://gitlab.gnome.org/jadahl/gnome-remote-desktop/uploads/c6862c12f0b741714d5a27e0693322fe/gnome-remote-desktop-0.1.6.tar.xz
Source0: https://gitlab.gnome.org/jadahl/gnome-remote-desktop/uploads/20e4965351cdbd8dc32ff9801e884b91/gnome-remote-desktop-0.1.8.tar.xz
# Adds encryption support (requires patched LibVNCServer)
Patch0: 0001-vnc-Add-anonymous-TLS-encryption-support.patch
# Fix black screen on Wayland
Patch1: 0001-vnc-pipewire-stream-Handle-stride-mismatch.patch
# Align pipewire requirement with Fedora
Patch1: 0001-meson.build-Bump-pipewire-requirement-to-0.2.2.patch
# Anon TLS encryption support
Patch2: anon-tls-support.patch
# Crash fix (rhbz#1627469)
Patch2: 0001-session-vnc-Don-t-requeue-close-session-idle.patch
Patch3: 0002-vnc-pipewire-stream-Close-session-when-disconnected.patch
# Don't crash on metadata only buffers (#1847062)
Patch3: 0001-stream-log-a-warning-on-error.patch
Patch4: 0002-vnc-pipewire-stream-Only-try-to-copy-frame-pixels-if.patch
Patch5: 0001-vnc-pipewire-stream-Remove-assert.patch
# Backport various fixes (rhbz#1659118)
Patch4: rhel8.0.0-backports.patch
# Backport password override, for testing (rhbz#1713330)
Patch5: 0001-vnc-Allow-overriding-password-with-env-var.patch
# Fix initial black content issue (rhbz#1765448)
Patch6: fix-initial-black-screen.patch
# Handle auth settings changes (rhbz#1684729)
Patch7: 0001-vnc-Unregister-previously-set-security-handlers-on-i.patch
# Cursor only frame fixes (#1837406)
Patch6: cursor-only-frame-fixes.patch
BuildRequires: git
BuildRequires: gcc
@ -37,7 +29,7 @@ BuildRequires: meson >= 0.36.0
BuildRequires: pkgconfig
BuildRequires: pkgconfig(glib-2.0) >= 2.32
BuildRequires: pkgconfig(gio-unix-2.0) >= 2.32
BuildRequires: pkgconfig(libpipewire-0.2) >= 0.2.5
BuildRequires: pkgconfig(libpipewire-0.3) >= 0.3.4
BuildRequires: pkgconfig(libvncserver) >= 0.9.11-7
BuildRequires: pkgconfig(libsecret-1)
BuildRequires: pkgconfig(libnotify)
@ -47,7 +39,7 @@ BuildRequires: python3-devel
%{?systemd_requires}
BuildRequires: systemd
Requires: pipewire >= 0.2.5
Requires: pipewire >= 0.3.4
%description
GNOME Remote Desktop is a remote desktop and screen sharing service for the
@ -89,6 +81,18 @@ GNOME desktop environment.
%changelog
* Wed Jul 15 2020 Jonas Ådahl <jadahl@redhat.com> - 0.1.8-3
- Backport cursor only frame fixes
Related: #1837406
* Thu Jun 18 2020 Jonas Ådahl <jadahl@redhat.com> - 0.1.8-2
- Don't crash on metadata only buffers
Resolves: #1847062
* Wed May 20 2020 Jonas Ådahl <jadahl@redhat.com> - 0.1.8-1
- Rebase to 0.1.8
Resolves: #1837406
* Wed Nov 27 2019 Jonas Ådahl <jadahl@redhat.com> - 0.1.6-8
- Update patch to handle older libvncserver at build time
Resolves: #1684729