rebase and fix merge conflicts

This commit is contained in:
mattmcclaskey
2023-06-30 12:51:01 -04:00
99 changed files with 2467 additions and 329 deletions

View File

@@ -8,6 +8,8 @@ use Data::Dumper;
use Hash::Merge::Simple;
use KasmVNC::Utils;
our $logger;
sub merge {
my @configsToMerge = map { $_->{data} } @_;
my $mergedConfig = Hash::Merge::Simple::merge(@configsToMerge) // {};
@@ -31,7 +33,13 @@ sub load {
failIfConfigNotReadable($self->{filename});
$self->{data} = YAML::Tiny->read($self->{filename})->[0];
$logger->debug("Loading config " . $self->{filename});
my $yamlDocuments = YAML::Tiny->read($self->{filename});
unless (defined $yamlDocuments) {
die "Couldn't load config: $self->{filename}. Probable reason: No newline at end of file\n";
}
$self->{data} = $yamlDocuments->[0];
}
sub get {

View File

@@ -8,9 +8,18 @@ use Data::Dumper;
sub new {
my ($class, $args) = @_;
my $self = bless {
level => $args->{level} // "warn"
}, $class;
}
sub debug {
my $self = shift;
return unless ($self->{level} eq "debug");
say { *STDERR } @_;
}
sub warn {
my $self = shift;

View File

@@ -5,6 +5,9 @@ desktop:
height: 768
allow_resize: true
pixel_depth: 24
gpu:
hw3d: false
drinode: /dev/dri/renderD128
network:
protocol: http
@@ -84,9 +87,13 @@ data_loss_prevention:
keyboard:
enabled: true
rate_limit: unlimited
# "verbose" SETTING LOGS YOUR PRIVATE INFORMATION. Keypresses and clipboard
# content.
watermark:
# image: /etc/kasmvnc/picture.png
# location: 10,10
# tint: 255,20,20,128
# repeat_spacing: 10
logging:
# "verbose" SETTING LOGS YOUR PRIVATE INFORMATION. Keypresses and clipboard content
level: off
encoding:

View File

@@ -1171,6 +1171,7 @@ sub DefineFilePathsAndStuff {
$KasmVNC::Users::vncPasswdBin = $exedir . "kasmvncpasswd";
$KasmVNC::Users::logger = $logger;
$KasmVNC::Config::logger = $logger;
$vncSystemConfigDir = "/etc/kasmvnc";
if ($ENV{KASMVNC_DEVELOPMENT}) {
@@ -1720,6 +1721,50 @@ sub DefineConfigToCLIConversion {
$value;
}
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkImage',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.image",
type => KasmVNC::ConfigKey::ANY
})
]
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkLocation',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.location",
type => KasmVNC::ConfigKey::ANY,
validator => KasmVNC::PatternValidator->new({
pattern => qr/^\d+,\d+$/,
errorMessage => "Must be an x and y offset separated by a comma: 10,10"
})
})
]
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkTint',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.tint",
type => KasmVNC::ConfigKey::ANY,
validator => KasmVNC::PatternValidator->new({
pattern => qr/^\d{1,3},\d{1,3},\d{1,3},\d{1,3}$/,
errorMessage => "Must be RBGA formatted: 255,255,255,128"
})
})
]
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkRepeatSpace',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.repeat_spacing",
type => KasmVNC::ConfigKey::INT
})
]
}),
KasmVNC::CliOption->new({
name => 'DLP_Log',
configKeys => [
@@ -1979,7 +2024,7 @@ sub DefineConfigToCLIConversion {
$self = shift;
my @values = @{ listify($self->configValues()) };
my $valuesStr = "";
foreach $value (@values) {
$valuesStr = $valuesStr . "-http-header '$value' "
@@ -2242,6 +2287,39 @@ sub DefineConfigToCLIConversion {
isPresent($value) && $value ne 'auto';
}
}),
KasmVNC::CliOption->new({
name => 'hw3d',
configKeys => [
KasmVNC::ConfigKey->new({
name => "desktop.gpu.hw3d",
type => KasmVNC::ConfigKey::BOOLEAN
})
],
toStringSub => sub {
$self = shift;
my $value = $self->configValue();
switch($value) {
case 'true' {
$valuesStr = '-hw3d ';
}
case 'false' {
$valuesStr = ' ';
}
}
return $valuesStr;
}
}),
KasmVNC::CliOption->new({
name => 'drinode',
configKeys => [
KasmVNC::ConfigKey->new({
name => "desktop.gpu.drinode",
type => KasmVNC::ConfigKey::ANY
})
]
}),
);
%cliArgMap = map { ("-" . $_->{name}) => $_ } @xvncOptions;
@@ -2754,5 +2832,6 @@ sub SetAppSettingsFromConfigAndCli {
}
sub InitLogger {
$logger = KasmVNC::Logger->new();
my $debugEnabled = any { $_ eq "-debug" } @ARGV;
$logger = KasmVNC::Logger->new({ level => $debugEnabled ? "debug" : "warn" });
}

4
unix/xserver/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/*
!/hw
/hw/*
!/hw/vnc

View File

@@ -30,10 +30,14 @@ bin_PROGRAMS = Xvnc
man1_MANS = Xvnc.man
Xvnc_SOURCES = xvnc.c \
Xvnc_SOURCES = xvnc.c dri3.c \
$(top_srcdir)/Xi/stubs.c $(top_srcdir)/mi/miinitext.c \
$(top_srcdir)/fb/fbcmap_mi.c buildtime.c
if DRI3
XVNC_SYS_LIBS += -lgbm
endif
# Xvnc contains no C++ sources so automake doesn't understand that we
# need to use the C++ compiler to link things. This is the upstream
# recommendation for coaxing automake.
@@ -44,7 +48,8 @@ Xvnc_CPPFLAGS = $(XVNC_CPPFLAGS) -DKASMVNC -DNO_MODULE_EXTS \
-DXVNCEXTRAVERSION="\".$(KASMVNC_COMMIT_ID)\"" \
-DXFree86Server -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \
-DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(KASMVNC_SRCDIR)/common -I$(KASMVNC_SRCDIR)/unix/common \
-I$(top_srcdir)/include ${XSERVERLIBS_CFLAGS} -I$(includedir)
-I$(top_srcdir)/include ${XSERVERLIBS_CFLAGS} -I$(includedir) \
-I$(top_srcdir)/dri3 @LIBDRM_CFLAGS@
Xvnc_LDADD = $(XVNC_LIBS) libvnccommon.la $(COMMON_LIBS) \
$(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XVNC_SYS_LIBS) -lX11 -lwebp -lssl -lcrypto -lcrypt

View File

@@ -286,6 +286,15 @@ be either \fB0\fP (off), \fB1\fP (always) or \fB2\fP (auto). Default is
\fB2\fP.
.
.TP
.B \-hw3d
Enable hardware 3d acceleration. Default is software (llvmpipe usually).
.
.TP
.B \-drinode \fIpath\fP
Use another path instead of /dev/dri/renderD128. You may need this if you have
more than one GPU.
.
.TP
.B \-ZlibLevel \fIlevel\fP
Zlib compression level for ZRLE encoding (it does not affect Tight encoding).
Acceptable values are between 0 and 9. Default is to use the standard
@@ -346,6 +355,28 @@ Log clipboard and keyboard actions. Info logs just clipboard direction and size,
verbose adds the contents for both.
.
.TP
.B \-DLP_WatermarkImage \fIpath/to/file.png\fP
Add a watermark. The PNG file should be greyscale, black is treated as transparent
and white as opaque.
.
.TP
.B \-DLP_WatermarkLocation \fIx,y\fP
Place the watermark at this position from the corner. Positive numbers are from top-left,
negative from bottom-right. Negative numbers count from the bottom-right edge of the image.
If not set, the watermark will be centered. Cannot be used together with repeat.
.
.TP
.B \-DLP_WatermarkRepeatSpace \fInum\fP
If set, repeat the watermark over the entire image, with \fBnum\fP pixels between
repetitions. Cannot be used together with location.
.
.TP
.B \-DLP_WatermarkTint \fIr,g,b,a\fP
Tint the greyscale watermark by this color. Default is 255,255,255,255 - full white.
The color components can be used to colorize the greyscale watermark, and the alpha
can be used to make it fainter.
.
.TP
.B \-selfBench
Run a set of self-benchmarks and exit.
.

279
unix/xserver/hw/vnc/dri3.c Normal file
View File

@@ -0,0 +1,279 @@
/* Copyright (c) 2023 Kasm
*
* This 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 software 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 software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifdef DRI3
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <X11/X.h>
#include <X11/Xmd.h>
#include <dri3.h>
#include <drm_fourcc.h>
#include <fb.h>
#include <gcstruct.h>
#include <gbm.h>
extern const char *driNode;
static struct priv_t {
struct gbm_device *gbm;
int fd;
} priv;
struct gbm_pixmap {
struct gbm_bo *bo;
};
typedef struct gbm_pixmap gbm_pixmap;
static DevPrivateKeyRec dri3_pixmap_private_key;
static struct timeval start;
static int
xvnc_dri3_open_client(ClientPtr client,
ScreenPtr screen,
RRProviderPtr provider,
int *pfd)
{
int fd = open(driNode, O_RDWR | O_CLOEXEC);
if (fd < 0)
return BadAlloc;
*pfd = fd;
return Success;
}
static uint32_t
gbm_format_for_depth(CARD8 depth)
{
switch (depth) {
case 16:
return GBM_FORMAT_RGB565;
case 24:
return GBM_FORMAT_XRGB8888;
case 30:
return GBM_FORMAT_ARGB2101010;
default:
ErrorF("unexpected depth: %d\n", depth);
/* fallthrough */
case 32:
return GBM_FORMAT_ARGB8888;
}
}
static void dri3_pixmap_set_private(PixmapPtr pixmap, gbm_pixmap *gp)
{
dixSetPrivate(&pixmap->devPrivates, &dri3_pixmap_private_key, gp);
}
static gbm_pixmap *gbm_pixmap_get(PixmapPtr pixmap)
{
return dixLookupPrivate(&pixmap->devPrivates, &dri3_pixmap_private_key);
}
static PixmapPtr
create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, CARD8 depth)
{
PixmapPtr pixmap;
gbm_pixmap *gp = calloc(1, sizeof(gbm_pixmap));
if (!gp)
return NULL;
pixmap = screen->CreatePixmap(screen, gbm_bo_get_width(bo), gbm_bo_get_height(bo),
depth, CREATE_PIXMAP_USAGE_SCRATCH);
if (!pixmap)
return NULL;
gp->bo = bo;
dri3_pixmap_set_private(pixmap, gp);
return pixmap;
}
static PixmapPtr
xvnc_pixmap_from_fds(ScreenPtr screen, CARD8 num_fds, const int *fds,
CARD16 width, CARD16 height,
const CARD32 *strides, const CARD32 *offsets,
CARD8 depth, CARD8 bpp, uint64_t modifier)
{
struct gbm_bo *bo = NULL;
PixmapPtr pixmap;
if (width == 0 || height == 0 || num_fds == 0 ||
depth < 15 || bpp != BitsPerPixel(depth) ||
strides[0] < width * bpp / 8)
return NULL;
if (num_fds == 1) {
struct gbm_import_fd_data data;
data.fd = fds[0];
data.width = width;
data.height = height;
data.stride = strides[0];
data.format = gbm_format_for_depth(depth);
bo = gbm_bo_import(priv.gbm, GBM_BO_IMPORT_FD, &data,
GBM_BO_USE_RENDERING);
if (!bo)
return NULL;
} else {
return NULL;
}
pixmap = create_pixmap_for_bo(screen, bo, depth);
if (pixmap == NULL) {
gbm_bo_destroy(bo);
return NULL;
}
return pixmap;
}
static int
xvnc_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
uint32_t *strides, uint32_t *offsets,
uint64_t *modifier)
{
gbm_pixmap *gp = gbm_pixmap_get(pixmap);
if (!gp)
return 0;
fds[0] = gbm_bo_get_fd(gp->bo);
strides[0] = gbm_bo_get_stride(gp->bo);
offsets[0] = 0;
*modifier = DRM_FORMAT_MOD_INVALID;
return 1;
}
static Bool
xvnc_get_formats(ScreenPtr screen,
CARD32 *num_formats, CARD32 **formats)
{
ErrorF("xvnc_get_formats\n");
return FALSE;
}
static Bool
xvnc_get_modifiers(ScreenPtr screen, uint32_t format,
uint32_t *num_modifiers, uint64_t **modifiers)
{
ErrorF("xvnc_get_modifiers\n");
return FALSE;
}
static Bool
xvnc_get_drawable_modifiers(DrawablePtr draw, uint32_t format,
uint32_t *num_modifiers, uint64_t **modifiers)
{
ErrorF("xvnc_get_drawable_modifiers\n");
return FALSE;
}
static const dri3_screen_info_rec xvnc_dri3_info = {
.version = 2,
.open = NULL,
.pixmap_from_fds = xvnc_pixmap_from_fds,
.fds_from_pixmap = xvnc_fds_from_pixmap,
.open_client = xvnc_dri3_open_client,
.get_formats = xvnc_get_formats,
.get_modifiers = xvnc_get_modifiers,
.get_drawable_modifiers = xvnc_get_drawable_modifiers,
};
void xvnc_sync_dri3_pixmap(PixmapPtr pixmap)
{
// There doesn't seem to be a good hook or sync point, so we do it manually
// here, right before Present copies from the pixmap
DrawablePtr pDraw;
GCPtr gc;
void *ptr;
uint32_t stride, w, h;
void *opaque = NULL;
// We may not be running on hw if there's a compositor using PRESENT on llvmpipe
if (!driNode)
return;
gbm_pixmap *gp = gbm_pixmap_get(pixmap);
if (!gp) {
//ErrorF("Present tried to copy from a non-dri3 pixmap\n");
return;
}
w = gbm_bo_get_width(gp->bo);
h = gbm_bo_get_height(gp->bo);
ptr = gbm_bo_map(gp->bo, 0, 0, w, h,
GBM_BO_TRANSFER_READ, &stride, &opaque);
if (!ptr) {
ErrorF("gbm map failed, errno %d\n", errno);
return;
}
pDraw = &pixmap->drawable;
if ((gc = GetScratchGC(pDraw->depth, pDraw->pScreen))) {
ValidateGC(pDraw, gc);
//gc->ops->PutImage(pDraw, gc, pDraw->depth, 0, 0, w, h, 0, ZPixmap, data);
fbPutZImage(pDraw, fbGetCompositeClip(gc), gc->alu, fbGetGCPrivate(gc)->pm,
0, 0, w, h, ptr, stride / sizeof(FbStip));
FreeScratchGC(gc);
}
gbm_bo_unmap(gp->bo, opaque);
}
void xvnc_init_dri3(void)
{
memset(&priv, 0, sizeof(priv));
gettimeofday(&start, NULL);
if (!dixRegisterPrivateKey(&dri3_pixmap_private_key, PRIVATE_PIXMAP, 0))
FatalError("dix\n");
if (!driNode)
driNode = "/dev/dri/renderD128";
priv.fd = open(driNode, O_RDWR | O_CLOEXEC);
if (!priv.fd)
FatalError("Failed to open %s\n", driNode);
priv.gbm = gbm_create_device(priv.fd);
if (!priv.gbm)
FatalError("Failed to create gbm\n");
if (!dri3_screen_init(screenInfo.screens[0], &xvnc_dri3_info))
FatalError("Couldn't init dri3\n");
}
#endif // DRI3

View File

@@ -37,6 +37,7 @@
#include <rfb/Hostname.h>
#include <rfb/Region.h>
#include <rfb/ledStates.h>
#include <rfb/Watermark.h>
#include <network/iceip.h>
#include <network/TcpSocket.h>
#include <network/UnixSocket.h>
@@ -232,6 +233,9 @@ void vncExtensionInit(void)
dummyY < 16)
vncFatalError("Invalid value to %s", Server::maxVideoResolution.getName());
if (!watermarkInit())
vncFatalError("Invalid watermark params");
pipe(wakeuppipe);
const int flags = fcntl(wakeuppipe[0], F_GETFL, 0);
fcntl(wakeuppipe[0], F_SETFL, flags | O_NONBLOCK);

View File

@@ -51,7 +51,7 @@ struct dlp_mimetype_t {
char mime[32];
};
unsigned dlp_num_mimetypes();
unsigned dlp_num_mimetypes(void);
const char *dlp_get_mimetype(const unsigned i);
extern int vncInetdSock;
@@ -70,7 +70,7 @@ int vncGetSendPrimary(void);
void vncUpdateDesktopName(void);
void vncAnnounceClipboard(int available);
void vncClearBinaryClipboardData();
void vncClearBinaryClipboardData(void);
void vncSendBinaryClipboardData(const char* mime, const unsigned char *data,
const unsigned len);
void vncGetBinaryClipboardData(const char *mime, const unsigned char **ptr,

View File

@@ -75,6 +75,12 @@ from the X Consortium.
#include <sys/ipc.h>
#include <sys/shm.h>
#endif /* HAS_SHM */
#ifdef MITSHM
#include "shmint.h"
#endif
#ifdef HAVE_XSHMFENCE
#include <misyncshm.h>
#endif
#include "dix.h"
#include "os.h"
#include "miline.h"
@@ -90,7 +96,7 @@ from the X Consortium.
#include "version-config.h"
#include "site.h"
#define XVNCVERSION "KasmVNC 0.9"
#define XVNCVERSION "KasmVNC 1.1.0"
#define XVNCCOPYRIGHT ("Copyright (C) 1999-2018 KasmVNC Team and many others (see README.me)\n" \
"See http://kasmweb.com for information on KasmVNC.\n")
@@ -152,6 +158,8 @@ typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB } fbMemType;
static fbMemType fbmemtype = NORMAL_MEMORY_FB;
static int lastScreen = -1;
static Bool Render = TRUE;
static Bool hw3d = FALSE;
const char *driNode = NULL;
static Bool displaySpecified = FALSE;
static char displayNumStr[16];
@@ -420,6 +428,8 @@ void ddxUseMsg(void)
ErrorF("+/-render turn on/off RENDER extension support"
"(default on)\n");
#endif
ErrorF("-hw3d enable hardware 3d acceleration\n");
ErrorF("-drinode path use another card than /dev/dri/renderD128\n");
ErrorF("-linebias n adjust thin line pixelization\n");
ErrorF("-blackpixel n pixel value for black\n");
ErrorF("-whitepixel n pixel value for white\n");
@@ -560,6 +570,20 @@ ddxProcessArgument(int argc, char *argv[], int i)
return 1;
}
if (strcmp (argv[i], "-hw3d") == 0)
{
hw3d = TRUE;
return 1;
}
if (strcmp (argv[i], "-drinode") == 0)
{
fail_unless_args(argc, i, 1);
++i;
driNode = argv[i];
return 2;
}
if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
{
Pixel pix;
@@ -1563,7 +1587,7 @@ int vncRandRCreateScreenOutputs(int scrIdx, int extraOutputs)
/* Creating and modifying modes, used by XserverDesktop and init here */
int vncRandRCanCreateModes()
int vncRandRCanCreateModes(void)
{
return 1;
}
@@ -1772,6 +1796,15 @@ vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
ret = fbPictureInit (pScreen, 0, 0);
#endif
#ifdef MITSHM
ShmRegisterFbFuncs(pScreen);
#endif
#ifdef HAVE_XSHMFENCE
if (!miSyncShmScreenInit(pScreen))
return FALSE;
#endif
if (!ret) return FALSE;
#if XORG < 110
@@ -1871,8 +1904,8 @@ static void vfbClientStateChange(CallbackListPtr *a, void *b, void *c) {
dispatchException &= ~DE_RESET;
}
}
#if XORG >= 113
#if XORG >= 113 && XORG < 120
#ifdef GLXEXT
extern void GlxExtensionInit(void);
@@ -1884,6 +1917,10 @@ static ExtensionModule glxExt = {
#endif
#endif
#ifdef DRI3
extern void xvnc_init_dri3(void);
#endif
void
InitOutput(ScreenInfo *scrInfo, int argc, char **argv)
{
@@ -1960,6 +1997,14 @@ InitOutput(ScreenInfo *scrInfo, int argc, char **argv)
if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
FatalError("AddCallback failed\n");
}
if (hw3d) {
#ifdef DRI3
xvnc_init_dri3();
#else
FatalError("DRI3 disabled at compile time\n");
#endif
}
} /* end InitOutput */
/* this is just to get the server to link on AIX */

View File

@@ -80,3 +80,34 @@ Index: xserver/mi/miinitext.c
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
{ShapeExtensionInit, "SHAPE", NULL},
#ifdef MITSHM
--- xserver.orig/dri3/Makefile.am 2019-02-26 21:28:50.000000000 +0200
+++ xserver/dri3/Makefile.am 2023-01-18 11:55:45.315851638 +0200
@@ -1,7 +1,7 @@
noinst_LTLIBRARIES = libdri3.la
AM_CFLAGS = \
-DHAVE_XORG_CONFIG_H \
- @DIX_CFLAGS@ @XORG_CFLAGS@
+ @DIX_CFLAGS@ @XORG_CFLAGS@ @LIBDRM_CFLAGS@
libdri3_la_SOURCES = \
dri3.h \
--- xserver.orig/present/present.c 2019-02-26 21:28:50.000000000 +0200
+++ xserver/present/present.c 2023-01-20 11:32:27.175493594 +0200
@@ -27,6 +27,8 @@
#include "present_priv.h"
#include <gcstruct.h>
+void xvnc_sync_dri3_pixmap(PixmapPtr pixmap);
+
/*
* Returns:
* TRUE if the first MSC value is equal to or after the second one
@@ -79,6 +81,8 @@
ScreenPtr screen = drawable->pScreen;
GCPtr gc;
+ xvnc_sync_dri3_pixmap(pixmap);
+
gc = GetScratchGC(drawable->depth, screen);
if (update) {
ChangeGCVal changes[2];