Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abdceab188 | ||
|
|
fee97a5a02 | ||
|
|
77a99c9de2 |
8 changed files with 858 additions and 9 deletions
81
0001-vnc-Drop-frames-if-client-is-gone.patch
Normal file
81
0001-vnc-Drop-frames-if-client-is-gone.patch
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
From e607efe6584cffc3284776e5795af05bd28da10d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||||
Date: Wed, 9 Sep 2020 10:14:20 +0200
|
||||
Subject: [PATCH] vnc: Drop frames if client is gone
|
||||
|
||||
Frames from PipeWire are posted asynchronously from a I/O thread to the
|
||||
main thread where they are turned into VNC frame updates and cursor
|
||||
movements. On the other hand, sessions are closed asynchronously when
|
||||
the VNC client disappears. If a frame ended up on the main thread after
|
||||
a client disappeared but before the session and stream was closed, we'd
|
||||
try to turn the new frames into VNC updates without a client being
|
||||
available, causing use after free.
|
||||
|
||||
Fix this by dropping frames that happens during this time frame.
|
||||
|
||||
Closes: https://gitlab.gnome.org/GNOME/gnome-remote-desktop/-/issues/43
|
||||
(cherry picked from commit ab97841629f5f3f4fab9993b6255b6ae04828b9c)
|
||||
---
|
||||
src/grd-session-vnc.c | 7 +++++++
|
||||
src/grd-session-vnc.h | 2 ++
|
||||
src/grd-vnc-pipewire-stream.c | 8 ++++++++
|
||||
3 files changed, 17 insertions(+)
|
||||
|
||||
diff --git a/src/grd-session-vnc.c b/src/grd-session-vnc.c
|
||||
index 21735bf..3a8852d 100644
|
||||
--- a/src/grd-session-vnc.c
|
||||
+++ b/src/grd-session-vnc.c
|
||||
@@ -219,6 +219,12 @@ maybe_queue_close_session_idle (GrdSessionVnc *session_vnc)
|
||||
g_idle_add (close_session_idle, session_vnc);
|
||||
}
|
||||
|
||||
+gboolean
|
||||
+grd_session_vnc_is_client_gone (GrdSessionVnc *session_vnc)
|
||||
+{
|
||||
+ return !session_vnc->rfb_client;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
handle_client_gone (rfbClientPtr rfb_client)
|
||||
{
|
||||
@@ -229,6 +235,7 @@ handle_client_gone (rfbClientPtr rfb_client)
|
||||
grd_session_vnc_pause (session_vnc);
|
||||
|
||||
maybe_queue_close_session_idle (session_vnc);
|
||||
+ session_vnc->rfb_client = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
diff --git a/src/grd-session-vnc.h b/src/grd-session-vnc.h
|
||||
index a065857..ffd8653 100644
|
||||
--- a/src/grd-session-vnc.h
|
||||
+++ b/src/grd-session-vnc.h
|
||||
@@ -76,4 +76,6 @@ void grd_session_vnc_dispatch (GrdSessionVnc *session_vnc);
|
||||
|
||||
GrdVncServer * grd_session_vnc_get_vnc_server (GrdSessionVnc *session_vnc);
|
||||
|
||||
+gboolean grd_session_vnc_is_client_gone (GrdSessionVnc *session_vnc);
|
||||
+
|
||||
#endif /* GRD_SESSION_VNC_H */
|
||||
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
|
||||
index 1feaef1..71357f0 100644
|
||||
--- a/src/grd-vnc-pipewire-stream.c
|
||||
+++ b/src/grd-vnc-pipewire-stream.c
|
||||
@@ -287,6 +287,14 @@ do_render (struct spa_loop *loop,
|
||||
if (!frame)
|
||||
return 0;
|
||||
|
||||
+ if (grd_session_vnc_is_client_gone (stream->session))
|
||||
+ {
|
||||
+ g_free (frame->data);
|
||||
+ g_clear_pointer (&frame->rfb_cursor, rfbFreeCursor);
|
||||
+ g_free (frame);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if (frame->rfb_cursor)
|
||||
grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor);
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From 78c5bcb181fe2b0b9fc17eea696feac8b504df54 Mon Sep 17 00:00:00 2001
|
||||
From b38d39072dd34e1128b1d43c0d692606311d5753 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
|
||||
Subject: [PATCH 1/6] 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
|
||||
|
|
@ -14,7 +14,34 @@ 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,
|
||||
@@ -160,84 +160,77 @@ on_stream_state_changed (void *user_data,
|
||||
enum pw_stream_state state,
|
||||
const char *error)
|
||||
{
|
||||
g_debug ("Pipewire stream state changed from %s to %s",
|
||||
pw_stream_state_as_string (old),
|
||||
pw_stream_state_as_string (state));
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case PW_STREAM_STATE_ERROR:
|
||||
g_warning ("PipeWire stream error: %s", error);
|
||||
break;
|
||||
case PW_STREAM_STATE_PAUSED:
|
||||
case PW_STREAM_STATE_STREAMING:
|
||||
case PW_STREAM_STATE_UNCONNECTED:
|
||||
case PW_STREAM_STATE_CONNECTING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_param_changed (void *user_data,
|
||||
uint32_t id,
|
||||
const struct spa_pod *format)
|
||||
{
|
||||
GrdVncPipeWireStream *stream = GRD_VNC_PIPEWIRE_STREAM (user_data);
|
||||
uint8_t params_buffer[1024];
|
||||
struct spa_pod_builder pod_builder;
|
||||
int width;
|
||||
int height;
|
||||
|
|
@ -23,7 +50,14 @@ index 88c07be..261292a 100644
|
|||
const struct spa_pod *params[3];
|
||||
|
||||
if (!format || id != SPA_PARAM_Format)
|
||||
@@ -203,14 +201,9 @@ on_stream_param_changed (void *user_data,
|
||||
return;
|
||||
|
||||
spa_format_video_raw_parse (format, &stream->spa_format);
|
||||
|
||||
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
|
||||
|
||||
width = stream->spa_format.size.width;
|
||||
height = stream->spa_format.size.height;
|
||||
|
||||
grd_session_vnc_queue_resize_framebuffer (stream->session, width, height);
|
||||
|
||||
|
|
@ -38,7 +72,61 @@ index 88c07be..261292a 100644
|
|||
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (8, 1, 8),
|
||||
0);
|
||||
|
||||
@@ -319,6 +312,10 @@ process_buffer (GrdVncPipeWireStream *stream,
|
||||
params[1] = spa_pod_builder_add_object (
|
||||
&pod_builder,
|
||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||
SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Header),
|
||||
SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_header)),
|
||||
0);
|
||||
|
||||
params[2] = spa_pod_builder_add_object(
|
||||
&pod_builder,
|
||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||
SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor),
|
||||
SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int (CURSOR_META_SIZE (64,64),
|
||||
CURSOR_META_SIZE (1,1),
|
||||
CURSOR_META_SIZE (256,256)),
|
||||
0);
|
||||
|
||||
pw_stream_update_params (stream->pipewire_stream,
|
||||
params, G_N_ELEMENTS (params));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
spa_pixel_format_to_grd_pixel_format (uint32_t spa_format,
|
||||
GrdPixelFormat *out_format)
|
||||
{
|
||||
if (spa_format == SPA_VIDEO_FORMAT_RGBA)
|
||||
*out_format = GRD_PIXEL_FORMAT_RGBA8888;
|
||||
else
|
||||
@@ -292,101 +285,115 @@ do_render (struct spa_loop *loop,
|
||||
g_mutex_unlock (&stream->frame_mutex);
|
||||
|
||||
if (!frame)
|
||||
return 0;
|
||||
|
||||
if (frame->rfb_cursor)
|
||||
grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor);
|
||||
|
||||
if (frame->cursor_moved)
|
||||
{
|
||||
grd_session_vnc_move_cursor (stream->session,
|
||||
frame->cursor_x,
|
||||
frame->cursor_y);
|
||||
}
|
||||
|
||||
if (frame->data)
|
||||
grd_session_vnc_take_buffer (stream->session, frame->data);
|
||||
|
||||
g_free (frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GrdVncFrame *
|
||||
process_buffer (GrdVncPipeWireStream *stream,
|
||||
struct spa_buffer *buffer)
|
||||
{
|
||||
size_t size;
|
||||
uint8_t *map;
|
||||
void *src_data;
|
||||
|
|
@ -49,7 +137,40 @@ index 88c07be..261292a 100644
|
|||
struct spa_meta_cursor *spa_meta_cursor;
|
||||
g_autofree GrdVncFrame *frame = NULL;
|
||||
|
||||
@@ -359,7 +356,17 @@ process_buffer (GrdVncPipeWireStream *stream,
|
||||
frame = g_new0 (GrdVncFrame, 1);
|
||||
|
||||
if (buffer->datas[0].chunk->size == 0)
|
||||
{
|
||||
size = 0;
|
||||
map = NULL;
|
||||
src_data = 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);
|
||||
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = buffer->datas[0].fd;
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
|
||||
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
sync_dma_buf (fd, DMA_BUF_SYNC_START);
|
||||
|
||||
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_MemPtr)
|
||||
{
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
map = NULL;
|
||||
src_data = buffer->datas[0].data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -63,11 +184,38 @@ index 88c07be..261292a 100644
|
|||
+ {
|
||||
+ memcpy (((uint8_t *) frame->data) + y * dst_stride,
|
||||
+ ((uint8_t *) src_data) + y * src_stride,
|
||||
+ stream->spa_format.size.width * 4);
|
||||
+ dst_stride);
|
||||
+ }
|
||||
|
||||
if (map)
|
||||
{
|
||||
if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_END);
|
||||
munmap (map, size);
|
||||
}
|
||||
|
||||
spa_meta_cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor,
|
||||
sizeof *spa_meta_cursor);
|
||||
if (spa_meta_cursor && spa_meta_cursor_is_valid (spa_meta_cursor))
|
||||
{
|
||||
struct spa_meta_bitmap *spa_meta_bitmap;
|
||||
GrdPixelFormat format;
|
||||
|
||||
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 &&
|
||||
spa_meta_bitmap->size.width > 0 &&
|
||||
spa_meta_bitmap->size.height > 0 &&
|
||||
spa_pixel_format_to_grd_pixel_format (spa_meta_bitmap->format,
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
|
|
|||
151
0002-vnc-pipewire-stream-Properly-process-cursor-change-o.patch
Normal file
151
0002-vnc-pipewire-stream-Properly-process-cursor-change-o.patch
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
From 685bdbbcc909fa3beb5a4c910befcd1f44131bc3 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/6] 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.
|
||||
---
|
||||
src/grd-vnc-pipewire-stream.c | 31 +++++++++++++++++--------------
|
||||
1 file changed, 17 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
|
||||
index 261292a..763f5eb 100644
|
||||
--- a/src/grd-vnc-pipewire-stream.c
|
||||
+++ b/src/grd-vnc-pipewire-stream.c
|
||||
@@ -285,114 +285,117 @@ do_render (struct spa_loop *loop,
|
||||
g_mutex_unlock (&stream->frame_mutex);
|
||||
|
||||
if (!frame)
|
||||
return 0;
|
||||
|
||||
if (frame->rfb_cursor)
|
||||
grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor);
|
||||
|
||||
if (frame->cursor_moved)
|
||||
{
|
||||
grd_session_vnc_move_cursor (stream->session,
|
||||
frame->cursor_x,
|
||||
frame->cursor_y);
|
||||
}
|
||||
|
||||
if (frame->data)
|
||||
grd_session_vnc_take_buffer (stream->session, frame->data);
|
||||
|
||||
g_free (frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GrdVncFrame *
|
||||
process_buffer (GrdVncPipeWireStream *stream,
|
||||
struct spa_buffer *buffer)
|
||||
{
|
||||
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;
|
||||
|
||||
frame = g_new0 (GrdVncFrame, 1);
|
||||
|
||||
if (buffer->datas[0].chunk->size == 0)
|
||||
{
|
||||
- size = 0;
|
||||
map = NULL;
|
||||
src_data = 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);
|
||||
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = buffer->datas[0].fd;
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
|
||||
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
sync_dma_buf (fd, DMA_BUF_SYNC_START);
|
||||
|
||||
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_MemPtr)
|
||||
{
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
map = NULL;
|
||||
src_data = buffer->datas[0].data;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
+ int y;
|
||||
+
|
||||
+ 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)
|
||||
{
|
||||
if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_END);
|
||||
munmap (map, size);
|
||||
}
|
||||
|
||||
spa_meta_cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor,
|
||||
sizeof *spa_meta_cursor);
|
||||
if (spa_meta_cursor && spa_meta_cursor_is_valid (spa_meta_cursor))
|
||||
{
|
||||
struct spa_meta_bitmap *spa_meta_bitmap;
|
||||
GrdPixelFormat format;
|
||||
|
||||
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 &&
|
||||
spa_meta_bitmap->size.width > 0 &&
|
||||
spa_meta_bitmap->size.height > 0 &&
|
||||
--
|
||||
2.26.2
|
||||
|
||||
149
0003-session-vnc-Add-API-to-flush.patch
Normal file
149
0003-session-vnc-Add-API-to-flush.patch
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
From def96b6f225636b3b9edf1993ca2e1ba9ed82f30 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 3/6] 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.
|
||||
---
|
||||
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 a93a2e3..21735bf 100644
|
||||
--- a/src/grd-session-vnc.c
|
||||
+++ b/src/grd-session-vnc.c
|
||||
@@ -152,60 +152,66 @@ grd_session_vnc_queue_resize_framebuffer (GrdSessionVnc *session_vnc,
|
||||
if (session_vnc->rfb_client->preferredEncoding == -1)
|
||||
{
|
||||
session_vnc->pending_framebuffer_resize = TRUE;
|
||||
session_vnc->pending_framebuffer_width = width;
|
||||
session_vnc->pending_framebuffer_height = height;
|
||||
return;
|
||||
}
|
||||
|
||||
resize_vnc_framebuffer (session_vnc, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
grd_session_vnc_take_buffer (GrdSessionVnc *session_vnc,
|
||||
void *data)
|
||||
{
|
||||
if (session_vnc->pending_framebuffer_resize)
|
||||
{
|
||||
free (data);
|
||||
return;
|
||||
}
|
||||
|
||||
free (session_vnc->rfb_screen->frameBuffer);
|
||||
session_vnc->rfb_screen->frameBuffer = data;
|
||||
|
||||
rfbMarkRectAsModified (session_vnc->rfb_screen, 0, 0,
|
||||
session_vnc->rfb_screen->width,
|
||||
session_vnc->rfb_screen->height);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (session_vnc->close_session_idle_id)
|
||||
return;
|
||||
|
||||
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
|
||||
@@ -22,56 +22,58 @@
|
||||
|
||||
#ifndef GRD_SESSION_VNC_H
|
||||
#define GRD_SESSION_VNC_H
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib-object.h>
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
#include "grd-session.h"
|
||||
#include "grd-types.h"
|
||||
|
||||
#define GRD_TYPE_SESSION_VNC (grd_session_vnc_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GrdSessionVnc,
|
||||
grd_session_vnc,
|
||||
GRD, SESSION_VNC,
|
||||
GrdSession);
|
||||
|
||||
typedef gboolean (* GrdVncSocketGrabFunc) (GrdSessionVnc *session_vnc,
|
||||
GError **error);
|
||||
|
||||
GrdSessionVnc *grd_session_vnc_new (GrdVncServer *vnc_server,
|
||||
GSocketConnection *connection);
|
||||
|
||||
void grd_session_vnc_queue_resize_framebuffer (GrdSessionVnc *session_vnc,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
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);
|
||||
|
||||
void grd_session_vnc_move_cursor (GrdSessionVnc *session_vnc,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
int grd_session_vnc_get_fd (GrdSessionVnc *session_vnc);
|
||||
|
||||
int grd_session_vnc_get_framebuffer_stride (GrdSessionVnc *session_vnc);
|
||||
|
||||
rfbClientPtr grd_session_vnc_get_rfb_client (GrdSessionVnc *session_vnc);
|
||||
|
||||
void grd_session_vnc_grab_socket (GrdSessionVnc *session_vnc,
|
||||
GrdVncSocketGrabFunc grab_func);
|
||||
|
||||
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);
|
||||
|
||||
#endif /* GRD_SESSION_VNC_H */
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
From 8c92fe8bc6c3003aacdfd96fed2d82bc542f3f27 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 4/6] 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.
|
||||
---
|
||||
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 763f5eb..ec23b0a 100644
|
||||
--- a/src/grd-vnc-pipewire-stream.c
|
||||
+++ b/src/grd-vnc-pipewire-stream.c
|
||||
@@ -272,60 +272,62 @@ sync_dma_buf (int fd,
|
||||
static int
|
||||
do_render (struct spa_loop *loop,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
const void *data,
|
||||
size_t size,
|
||||
void *user_data)
|
||||
{
|
||||
GrdVncPipeWireStream *stream = GRD_VNC_PIPEWIRE_STREAM (user_data);
|
||||
GrdVncFrame *frame;
|
||||
|
||||
g_mutex_lock (&stream->frame_mutex);
|
||||
frame = g_steal_pointer (&stream->pending_frame);
|
||||
g_mutex_unlock (&stream->frame_mutex);
|
||||
|
||||
if (!frame)
|
||||
return 0;
|
||||
|
||||
if (frame->rfb_cursor)
|
||||
grd_session_vnc_set_cursor (stream->session, frame->rfb_cursor);
|
||||
|
||||
if (frame->cursor_moved)
|
||||
{
|
||||
grd_session_vnc_move_cursor (stream->session,
|
||||
frame->cursor_x,
|
||||
frame->cursor_y);
|
||||
}
|
||||
|
||||
if (frame->data)
|
||||
grd_session_vnc_take_buffer (stream->session, frame->data);
|
||||
+ else
|
||||
+ grd_session_vnc_flush (stream->session);
|
||||
|
||||
g_free (frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GrdVncFrame *
|
||||
process_buffer (GrdVncPipeWireStream *stream,
|
||||
struct spa_buffer *buffer)
|
||||
{
|
||||
size_t size;
|
||||
uint8_t *map;
|
||||
void *src_data;
|
||||
struct spa_meta_cursor *spa_meta_cursor;
|
||||
g_autofree GrdVncFrame *frame = NULL;
|
||||
|
||||
frame = g_new0 (GrdVncFrame, 1);
|
||||
|
||||
if (buffer->datas[0].chunk->size == 0)
|
||||
{
|
||||
map = NULL;
|
||||
src_data = 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);
|
||||
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
--
|
||||
2.26.2
|
||||
|
||||
105
0005-vnc-pipewire-stream-Correct-memcpy-size-calculation.patch
Normal file
105
0005-vnc-pipewire-stream-Correct-memcpy-size-calculation.patch
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
From 9ad54e84aaa5f5ddae5cb16a2726b314d6229076 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 27 Aug 2020 14:04:03 -0400
|
||||
Subject: [PATCH 5/6] vnc-pipewire-stream: Correct memcpy size calculation
|
||||
|
||||
commit 78c5bcb181fe2b0b9fc17eea696feac8b504df54 introduced code
|
||||
to try to account for a row stride mismatch between source and
|
||||
destination.
|
||||
|
||||
That commit, however, erroneously copies destination stride bytes
|
||||
from the source, which will lead to out of bounds access if the
|
||||
source has a smaller row stride.
|
||||
|
||||
This commit addresses the problem, by instead, copying just the
|
||||
pixel data, and none of the row margin.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/gnome-remote-desktop/-/merge_requests/18
|
||||
---
|
||||
src/grd-vnc-pipewire-stream.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
|
||||
index ec23b0a..b94e761 100644
|
||||
--- a/src/grd-vnc-pipewire-stream.c
|
||||
+++ b/src/grd-vnc-pipewire-stream.c
|
||||
@@ -330,73 +330,75 @@ process_buffer (GrdVncPipeWireStream *stream,
|
||||
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0);
|
||||
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = buffer->datas[0].fd;
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
|
||||
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
sync_dma_buf (fd, DMA_BUF_SYNC_START);
|
||||
|
||||
src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_MemPtr)
|
||||
{
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
map = NULL;
|
||||
src_data = buffer->datas[0].data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (src_data)
|
||||
{
|
||||
int src_stride;
|
||||
int dst_stride;
|
||||
+ int width;
|
||||
int height;
|
||||
int y;
|
||||
|
||||
src_stride = buffer->datas[0].chunk->stride;
|
||||
dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session);
|
||||
height = stream->spa_format.size.height;
|
||||
+ width = stream->spa_format.size.width;
|
||||
|
||||
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);
|
||||
+ width * 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (map)
|
||||
{
|
||||
if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_END);
|
||||
munmap (map, size);
|
||||
}
|
||||
|
||||
spa_meta_cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor,
|
||||
sizeof *spa_meta_cursor);
|
||||
if (spa_meta_cursor && spa_meta_cursor_is_valid (spa_meta_cursor))
|
||||
{
|
||||
struct spa_meta_bitmap *spa_meta_bitmap;
|
||||
GrdPixelFormat format;
|
||||
|
||||
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 &&
|
||||
spa_meta_bitmap->size.width > 0 &&
|
||||
--
|
||||
2.26.2
|
||||
|
||||
116
0006-vnc-pipewire-stream-Handle-mmap-failure-better.patch
Normal file
116
0006-vnc-pipewire-stream-Handle-mmap-failure-better.patch
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
From e8181aa61ca8e72ea607390b4368639d71d65700 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 28 Aug 2020 12:34:45 -0400
|
||||
Subject: [PATCH 6/6] vnc-pipewire-stream: Handle mmap failure better
|
||||
|
||||
Right now if mmap fails, we just sort of crash.
|
||||
|
||||
This commit changes the code to warn why it failed, and then
|
||||
continue marching along.
|
||||
---
|
||||
src/grd-vnc-pipewire-stream.c | 25 ++++++++++++++++++++++---
|
||||
1 file changed, 22 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
|
||||
index b94e761..1feaef1 100644
|
||||
--- a/src/grd-vnc-pipewire-stream.c
|
||||
+++ b/src/grd-vnc-pipewire-stream.c
|
||||
@@ -301,73 +301,92 @@ do_render (struct spa_loop *loop,
|
||||
grd_session_vnc_take_buffer (stream->session, frame->data);
|
||||
else
|
||||
grd_session_vnc_flush (stream->session);
|
||||
|
||||
g_free (frame);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GrdVncFrame *
|
||||
process_buffer (GrdVncPipeWireStream *stream,
|
||||
struct spa_buffer *buffer)
|
||||
{
|
||||
size_t size;
|
||||
uint8_t *map;
|
||||
void *src_data;
|
||||
struct spa_meta_cursor *spa_meta_cursor;
|
||||
g_autofree GrdVncFrame *frame = NULL;
|
||||
|
||||
frame = g_new0 (GrdVncFrame, 1);
|
||||
|
||||
if (buffer->datas[0].chunk->size == 0)
|
||||
{
|
||||
map = NULL;
|
||||
src_data = 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);
|
||||
- src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
+
|
||||
+ if (map != MAP_FAILED)
|
||||
+ {
|
||||
+ src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ g_warning ("Could not map memfd: %m");
|
||||
+ map = NULL;
|
||||
+ src_data = NULL;
|
||||
+ }
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = buffer->datas[0].fd;
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
|
||||
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
- sync_dma_buf (fd, DMA_BUF_SYNC_START);
|
||||
|
||||
- src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
+ if (map != MAP_FAILED)
|
||||
+ {
|
||||
+ sync_dma_buf (fd, DMA_BUF_SYNC_START);
|
||||
+ src_data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ g_warning ("Could not map dma-buf: %m");
|
||||
+ map = NULL;
|
||||
+ src_data = NULL;
|
||||
+ }
|
||||
}
|
||||
else if (buffer->datas[0].type == SPA_DATA_MemPtr)
|
||||
{
|
||||
size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset;
|
||||
map = NULL;
|
||||
src_data = buffer->datas[0].data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (src_data)
|
||||
{
|
||||
int src_stride;
|
||||
int dst_stride;
|
||||
int width;
|
||||
int height;
|
||||
int y;
|
||||
|
||||
src_stride = buffer->datas[0].chunk->stride;
|
||||
dst_stride = grd_session_vnc_get_framebuffer_stride (stream->session);
|
||||
height = stream->spa_format.size.height;
|
||||
width = stream->spa_format.size.width;
|
||||
|
||||
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,
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Name: gnome-remote-desktop
|
||||
Version: 0.1.8
|
||||
Release: 3%{?dist}
|
||||
Release: 5%{?dist}
|
||||
Summary: GNOME Remote Desktop screen share service
|
||||
|
||||
License: GPLv2+
|
||||
|
|
@ -12,7 +12,13 @@ Source0: https://gitlab.gnome.org/jadahl/gnome-remote-desktop/uploads/20e
|
|||
# Adds encryption support (requires patched LibVNCServer)
|
||||
Patch0: anon-tls-support.patch
|
||||
|
||||
Patch1: 0001-vnc-pipewire-stream-Handle-stride-mismatch.patch
|
||||
Patch10001: 0001-vnc-pipewire-stream-Handle-stride-mismatch.patch
|
||||
Patch10002: 0002-vnc-pipewire-stream-Properly-process-cursor-change-o.patch
|
||||
Patch10003: 0003-session-vnc-Add-API-to-flush.patch
|
||||
Patch10004: 0004-vnc-pipewire-stream-Flush-connection-if-no-new-pixel.patch
|
||||
Patch10005: 0005-vnc-pipewire-stream-Correct-memcpy-size-calculation.patch
|
||||
Patch10006: 0006-vnc-pipewire-stream-Handle-mmap-failure-better.patch
|
||||
Patch10007: 0001-vnc-Drop-frames-if-client-is-gone.patch
|
||||
|
||||
BuildRequires: git
|
||||
BuildRequires: gcc
|
||||
|
|
@ -71,6 +77,17 @@ GNOME desktop environment.
|
|||
|
||||
|
||||
%changelog
|
||||
* Wed Sep 16 2020 Jonas Ådahl <jadahl@redhat.com> - 0.1.8-5
|
||||
- Fix crash when reconnecting
|
||||
|
||||
* Thu Aug 27 2020 Ray Strode <rstrode@redhat.com> - 0.1.8-4
|
||||
- Fix other crash
|
||||
Related: #1844993
|
||||
|
||||
* Thu Aug 27 2020 Ray Strode <rstrode@redhat.com> - 0.1.8-3
|
||||
- Fix crash
|
||||
Related: #1844993
|
||||
|
||||
* Mon Jun 1 2020 Felipe Borges <feborges@redhat.com> - 0.1.8-2
|
||||
- Fix black screen issue in remote connections on Wayland
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue