Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Jonas Ådahl
abdceab188 Fix crash when reconnecting 2020-09-16 11:18:50 +02:00
Ray Strode
fee97a5a02 Fix other crash
Related: #1844993
2020-08-28 18:04:45 -04:00
Ray Strode
77a99c9de2 add missing changelog entry
Related: #1844993
2020-08-27 14:54:03 -04:00
8 changed files with 858 additions and 9 deletions

View 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

View file

@ -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

View 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

View 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

View file

@ -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

View 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

View 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

View file

@ -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