Compare commits

...

25 Commits

Author SHA1 Message Date
Matthew McClaskey
446d03d479 Merge branch 'master' into 'release/1.2.0'
Update release with latest changes

See merge request kasm-technologies/internal/KasmVNC!109
2023-08-21 17:52:45 +00:00
Matthew McClaskey
04f95d2b62 Merge branch 'feature/KASM-4796-add-unix-relay-to-config' into 'master'
Add network.unix_relay to yaml config

Closes KASM-4796

See merge request kasm-technologies/internal/KasmVNC!108
2023-08-17 09:38:43 +00:00
Dmitry Maksyoma
c0ed7d7b1a Add network.unix_relay to yaml config 2023-08-17 20:29:23 +12:00
Matt McClaskey
dda29172c1 update novnc ref 2023-08-16 11:05:35 -04:00
Matthew McClaskey
fa88480914 Merge branch 'bugfix/KASM-4765-fix-opensuse-datetime-dependency' into 'master'
OpenSuse: add missing dependency

Closes KASM-4765

See merge request kasm-technologies/internal/KasmVNC!107
2023-08-03 18:12:54 +00:00
Matt McClaskey
b4f6fafd73 update novnc ref 2023-08-03 14:08:57 -04:00
Dmitry Maksyoma
6a73d1cb49 OpenSuse: add missing dependency 2023-08-03 22:09:08 +12:00
Matthew McClaskey
6207b1b60f Merge branch 'bugfix/KASM-4757_watermark_default' into 'master'
KASM-4757 change KasmVNC defaults for watermark

Closes KASM-4757

See merge request kasm-technologies/internal/KasmVNC!105
2023-08-02 10:44:56 +00:00
mattmcclaskey
0923f300a0 KASM-4757 change KasmVNC defaults for watermark 2023-08-01 13:16:24 -04:00
Matthew McClaskey
7b8a4e8388 Merge branch 'feature/KASM-4034_unix_sockets' into 'master'
Add support for relaying unix sockets

Closes KASM-4034

See merge request kasm-technologies/internal/KasmVNC!90
2023-07-27 14:15:40 +00:00
Matthew McClaskey
b9e9a2d2a0 Merge branch 'feature/KASM-4489_watermark_time' into 'master'
Resolve KASM-4489 "Feature/ watermark time"

Closes KASM-4489

See merge request kasm-technologies/internal/KasmVNC!103
2023-07-26 23:55:06 +00:00
Lauri Kasanen
25a996cb97 Resolve KASM-4489 "Feature/ watermark time" 2023-07-26 23:55:06 +00:00
mattmcclaskey
6774cbf3a2 Merge branch 'master' into feature/KASM-4034_unix_sockets 2023-07-26 08:24:10 -04:00
Matthew McClaskey
fc0f2a3192 Merge branch 'bugfix/restart-crash' into 'master'
Blind guess at the reported crash

See merge request kasm-technologies/internal/KasmVNC!104
2023-07-26 12:03:33 +00:00
Ryan Kuba
9a14b07ba4 Merge branch 'bugfix/KASM-4151_gnome_blank' into 'master'
Implement the pixmaps-to-textures path so that mutter is happy. Note: tearing

Closes KASM-4151

See merge request kasm-technologies/internal/KasmVNC!96
2023-07-25 13:56:05 +00:00
Lauri Kasanen
0527c9f76e Add support for compositing 2023-07-25 13:56:05 +00:00
Lauri Kasanen
e41bc997a6 Blind guess at the reported crash 2023-07-12 17:16:28 +03:00
mattmcclaskey
75c51c1e93 rebase and fix merge conflicts 2023-06-30 12:51:01 -04:00
Matthew McClaskey
9450157af1 Merge branch 'feature/KASM-4421-new-distros' into 'master'
KASM-4421 update opensuse to 15.5, add bookworm Alpine 3.18 and Fedora 38

Closes KASM-4421

See merge request kasm-technologies/internal/KasmVNC!102
2023-06-13 18:37:05 +00:00
ryan.kuba
f9e46f5a13 KASM-4421 update opensuse to 15.5, add bookworm Alpine 3.18 and Fedora 38 2023-06-02 14:08:40 -04:00
Matthew McClaskey
13bafe3759 Merge branch 'feature/KASM-3663-host-tip-of-master-preview-builds' into 'master'
Resolve KASM-3663 "Feature/ host tip of master preview builds"

Closes KASM-3663

See merge request kasm-technologies/internal/KasmVNC!101
2023-06-02 17:12:27 +00:00
Dmitry Maksyoma
d5080eca8f Resolve KASM-3663 "Feature/ host tip of master preview builds" 2023-06-02 17:12:27 +00:00
Matthew McClaskey
4d3a9b749a Merge branch 'bump-version-bumps-xvnc-binary' into 'master'
bump-package-version: bump version emitted by Xvnc -version

See merge request kasm-technologies/internal/KasmVNC!100
2023-04-06 13:31:07 +00:00
Dmitry Maksyoma
12ba00f939 bump-package-version: bump version emitted by Xvnc -version 2023-04-07 00:34:29 +12:00
Lauri Kasanen
3bae812364 Add support for relaying unix sockets 2023-02-16 15:51:26 +02:00
59 changed files with 4575 additions and 21 deletions

View File

@@ -89,3 +89,26 @@ detect_revision() {
REVISION=$(echo "$package" | sed "s/_${arch}.\+//" | sed 's/.\++//')
}
make_index_html() {
local body=""
local bname
for f in "$@"; do
bname=$(basename "$f")
body="${body}<a href=/$f>$bname</a><br>"
done
cat <<EOF
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>KasmVNC preview build</title>
</head>
<body>
$body
</body>
</html>
EOF
}

View File

@@ -243,6 +243,43 @@ build_debian_bullseye_arm:
paths:
- output/
build_debian_bookworm:
stage: build
allow_failure: true
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package debian bookworm;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_debian_bookworm_arm:
stage: build
allow_failure: true
tags:
- oci-fixed-arm64
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package debian bookworm;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_kali_rolling:
stage: build
allow_failure: true
@@ -440,6 +477,42 @@ build_fedora_thirtyseven_arm:
paths:
- output/
build_fedora_thirtyeight:
stage: build
allow_failure: true
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package fedora thirtyeight;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_fedora_thirtyeight_arm:
stage: build
allow_failure: true
tags:
- oci-fixed-arm64
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package fedora thirtyeight;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_alpine_317:
stage: build
allow_failure: true
@@ -483,9 +556,49 @@ test:
script:
- bash builder/test-vncserver
build_alpine_318:
stage: build
allow_failure: true
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package alpine 318;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_alpine_318_arm:
stage: build
allow_failure: true
tags:
- oci-fixed-arm64
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package alpine 318;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
upload:
stage: upload
image: ubuntu:focal
artifacts:
paths:
- output/
before_script:
- . .ci/upload.sh
script:
@@ -502,6 +615,7 @@ upload:
done
- export S3_BUILD_DIRECTORY="kasmvnc/${CI_COMMIT_SHA}"
- export RELEASE_VERSION=$(.ci/next_release_version "$CI_COMMIT_REF_NAME")
- uploaded_files=()
- for package in `find output/ -type f -name '*.deb' -or -name '*.rpm' -or -name '*.tgz'`; do
prepare_upload_filename "$package";
upload_filename="${S3_BUILD_DIRECTORY}/$upload_filename";
@@ -510,4 +624,23 @@ upload:
upload_to_s3 "$package" "$upload_filename" "$S3_BUCKET";
UPLOAD_NAME=$(basename $upload_filename | sed 's#kasmvncserver_##' | sed -r 's#_([0-9]{1,3}\.){2}[0-9]{1,2}_\S+?([a-f0-9]{6})##' | sed -r 's#\.(deb|rpm|tgz)##');
curl --request POST --header "PRIVATE-TOKEN:${GITLAB_API_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/statuses/${CI_COMMIT_SHA}?state=success&name=${UPLOAD_NAME}&target_url=${S3_URL}";
uploaded_files+=("$upload_filename");
done
- make_index_html "${uploaded_files[@]}" > output/index.html;
upload_build_preview:
stage: upload
needs: ["upload"]
dependencies: ["upload"]
image: ubuntu:focal
before_script:
- . .ci/upload.sh
resource_group: upload_build_preview
only:
variables:
- $CI_COMMIT_BRANCH == 'master'
script:
- prepare_to_run_scripts_and_s3_uploads
- preview_builds_dir=kasmvnc/preview-builds
- upload_to_s3 "output/index.html" "$preview_builds_dir/index.html" "$S3_BUCKET"
- curl --request POST --header "PRIVATE-TOKEN:${GITLAB_API_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/statuses/${CI_COMMIT_SHA}?state=success&name=index.html&target_url=${S3_URL}";

View File

@@ -154,6 +154,9 @@ find_package(PNG REQUIRED)
# Check for libjpeg
find_package(JPEG REQUIRED)
find_package(Freetype REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS})
# Staticly link libjpeg-turbo
set(JPEG_LIBRARIES "-Wl,-Bstatic -lturbojpeg -Wl,-Bdynamic")
# Warn if it doesn't seem to be the accelerated libjpeg that's found

View File

@@ -15,6 +15,11 @@ bump_deb() {
builder/bump-package-version-deb "$new_version"
}
bump_xvnc_binary() {
local cmd="s/#define XVNCVERSION.\+$/#define XVNCVERSION \"KasmVNC $new_version\"/"
sed -i -e "$cmd" unix/xserver/hw/vnc/xvnc.c
}
new_version="$1"
if [[ -z "$new_version" ]]; then
@@ -25,5 +30,6 @@ fi
cd "$(dirname "$0")/.."
update_version_to_meet_packaging_standards
bump_xvnc_binary
bump_rpm
bump_deb

View File

@@ -0,0 +1,7 @@
FROM alpine:3.18
RUN apk add shadow bash
RUN useradd -m docker && echo "docker:docker" | chpasswd
USER docker

View File

@@ -0,0 +1,82 @@
FROM alpine:3.18
ENV KASMVNC_BUILD_OS alpine
ENV KASMVNC_BUILD_OS_CODENAME 318
ENV XORG_VER 1.20.14
RUN \
echo "**** install build deps ****" && \
apk add \
alpine-release \
alpine-sdk \
autoconf \
automake \
bash \
ca-certificates \
cmake \
coreutils \
curl \
eudev-dev \
font-cursor-misc \
font-misc-misc \
font-util-dev \
git \
grep \
jq \
libdrm-dev \
libepoxy-dev \
libjpeg-turbo-dev \
libjpeg-turbo-static \
libpciaccess-dev \
libtool \
libwebp-dev \
libx11-dev \
libxau-dev \
libxcb-dev \
libxcursor-dev \
libxcvt-dev \
libxdmcp-dev \
libxext-dev \
libxfont2-dev \
libxkbfile-dev \
libxrandr-dev \
libxshmfence-dev \
libxtst-dev \
mesa-dev \
mesa-dri-gallium \
meson \
nettle-dev \
openssl-dev \
pixman-dev \
procps \
shadow \
tar \
tzdata \
wayland-dev \
wayland-protocols \
xcb-util-dev \
xcb-util-image-dev \
xcb-util-keysyms-dev \
xcb-util-renderutil-dev \
xcb-util-wm-dev \
xinit \
xkbcomp \
xkbcomp-dev \
xkeyboard-config \
xorgproto \
xorg-server-common \
xorg-server-dev \
xtrans
ENV SCRIPTS_DIR=/tmp/scripts
COPY builder/scripts $SCRIPTS_DIR
RUN $SCRIPTS_DIR/build-webp
RUN $SCRIPTS_DIR/build-libjpeg-turbo
RUN useradd -m docker && echo "docker:docker" | chpasswd
COPY --chown=docker:docker . /src/
USER docker
ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -0,0 +1,38 @@
FROM debian:bookworm-slim
ENV KASMVNC_BUILD_OS debian
ENV KASMVNC_BUILD_OS_CODENAME bookworm
ENV XORG_VER 1.20.10
ENV DEBIAN_FRONTEND noninteractive
RUN \
echo "**** add all sources ****" && \
echo "deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
echo "deb-src http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb-src http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://deb.debian.org/debian bookworm-backports main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb-src http://deb.debian.org/debian bookworm-backports main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://security.debian.org/debian-security/ bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb-src http://security.debian.org/debian-security/ bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
rm -f /etc/apt/sources.list.d/debian.sources
RUN apt-get update && \
apt-get -y install sudo
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata
RUN apt-get update && apt-get -y build-dep xorg-server libxfont-dev
RUN apt-get update && apt-get -y install cmake git libgnutls28-dev vim wget tightvncserver curl
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev
ENV SCRIPTS_DIR=/tmp/scripts
COPY builder/scripts $SCRIPTS_DIR
RUN $SCRIPTS_DIR/build-webp
RUN $SCRIPTS_DIR/build-libjpeg-turbo
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
COPY --chown=docker:docker . /src/
USER docker
ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -0,0 +1,19 @@
FROM debian:bookworm
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
apt-get -y install vim build-essential devscripts equivs
# Install build-deps for the package.
COPY ./debian/control /tmp
RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control
ARG L_UID
RUN if [ "$L_UID" -eq 0 ]; then \
useradd -m docker; \
else \
useradd -m docker -u $L_UID;\
fi
USER docker

View File

@@ -0,0 +1,57 @@
FROM debian:bookworm-slim
ENV DISPLAY=:1 \
VNC_PORT=8443 \
VNC_RESOLUTION=1280x720 \
MAX_FRAME_RATE=24 \
VNCOPTIONS="-PreferBandwidth -DynamicQualityMin=4 -DynamicQualityMax=7" \
HOME=/home/user \
TERM=xterm \
STARTUPDIR=/dockerstartup \
INST_SCRIPTS=/dockerstartup/install \
KASM_RX_HOME=/dockerstartup/kasmrx \
DEBIAN_FRONTEND=noninteractive \
VNC_COL_DEPTH=24 \
VNC_RESOLUTION=1280x1024 \
VNC_PW=vncpassword \
VNC_USER=user \
VNC_VIEW_ONLY_PW=vncviewonlypassword \
LD_LIBRARY_PATH=/usr/local/lib/ \
OMP_WAIT_POLICY=PASSIVE \
SHELL=/bin/bash \
SINGLE_APPLICATION=0 \
KASMVNC_BUILD_OS=debian \
KASMVNC_BUILD_OS_CODENAME=buster
EXPOSE $VNC_PORT
WORKDIR $HOME
### REQUIRED STUFF ###
RUN apt-get update && apt-get install -y supervisor xfce4 xfce4-terminal dbus-x11 xterm libnss-wrapper gettext wget
RUN apt-get purge -y pm-utils xscreensaver*
RUN apt-get update && apt-get install -y vim less
RUN apt-get update && apt-get -y install lsb-release
RUN echo 'source $STARTUPDIR/generate_container_user' >> $HOME/.bashrc
RUN mkdir -p $STARTUPDIR
COPY builder/startup/ $STARTUPDIR
### START CUSTOM STUFF ####
COPY ./builder/scripts/ /tmp/scripts/
COPY ./debian/changelog /tmp
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/
RUN /tmp/scripts/install_kasmvncserver_package
### END CUSTOM STUFF ###
RUN chown -R 1000:0 $HOME
USER 1000:ssl-cert
WORKDIR $HOME
ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ]

View File

@@ -0,0 +1,19 @@
FROM fedora:38
ENV STARTUPDIR=/dockerstartup
RUN dnf install -y xterm
RUN dnf install -y vim less
RUN yum install -y redhat-lsb-core
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/*.rpm /tmp/
RUN dnf localinstall -y /tmp/*.rpm
RUN mkdir -p $STARTUPDIR
COPY startup/vnc_startup_barebones.sh $STARTUPDIR
RUN useradd -m foo
USER foo:kasmvnc-cert
ENTRYPOINT "/$STARTUPDIR/vnc_startup_barebones.sh"

View File

@@ -0,0 +1,86 @@
FROM fedora:38
ENV KASMVNC_BUILD_OS fedora
ENV KASMVNC_BUILD_OS_CODENAME thirtyeight
ENV XORG_VER 1.20.14
RUN \
echo "**** install build deps ****" && \
dnf group install -y \
"C Development Tools and Libraries" \
"Development Tools" && \
dnf install -y \
autoconf \
automake \
bison \
byacc \
bzip2 \
cmake \
diffutils \
doxygen \
file \
flex \
fop \
gcc \
gcc-c++ \
git \
glibc-devel \
libdrm-devel \
libepoxy-devel \
libmd-devel \
libpciaccess-devel \
libtool \
libwebp-devel \
libX11-devel \
libXau-devel \
libxcb-devel \
libXcursor-devel \
libxcvt-devel \
libXdmcp-devel \
libXext-devel \
libXfont2-devel \
libxkbfile-devel \
libXrandr-devel \
libxshmfence-devel \
libXtst-devel \
mesa-libEGL-devel \
mesa-libgbm-devel \
mesa-libGL-devel \
meson \
mingw64-binutils \
mt-st \
nettle-devel \
openssl-devel \
patch \
pixman-devel \
wayland-devel \
wget \
which \
xcb-util-devel \
xcb-util-image-devel \
xcb-util-keysyms-devel \
xcb-util-renderutil-devel \
xcb-util-wm-devel \
xinit \
xkbcomp \
xkbcomp-devel \
xkeyboard-config \
xmlto \
xorg-x11-font-utils \
xorg-x11-proto-devel \
xorg-x11-server-common \
xorg-x11-server-devel \
xorg-x11-xtrans-devel \
xsltproc
ENV SCRIPTS_DIR=/tmp/scripts
COPY builder/scripts $SCRIPTS_DIR
RUN $SCRIPTS_DIR/build-webp
RUN $SCRIPTS_DIR/build-libjpeg-turbo
RUN useradd -m docker && echo "docker:docker" | chpasswd
COPY --chown=docker:docker . /src/
USER docker
ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -0,0 +1,13 @@
FROM fedora:38
RUN dnf install -y fedora-packager fedora-review
RUN dnf install -y tree vim less
RUN dnf install -y redhat-lsb-core
RUN dnf install -y dnf-plugins-core
COPY fedora/*.spec /tmp
RUN dnf builddep -y /tmp/*.spec
RUN useradd -m docker && echo "docker:docker" | chpasswd
USER docker

View File

@@ -0,0 +1,62 @@
FROM fedora:38
ENV DISPLAY=:1 \
VNC_PORT=8443 \
VNC_RESOLUTION=1280x720 \
MAX_FRAME_RATE=24 \
VNCOPTIONS="-PreferBandwidth -DynamicQualityMin=4 -DynamicQualityMax=7" \
HOME=/home/user \
TERM=xterm \
STARTUPDIR=/dockerstartup \
INST_SCRIPTS=/dockerstartup/install \
KASM_RX_HOME=/dockerstartup/kasmrx \
DEBIAN_FRONTEND=noninteractive \
VNC_COL_DEPTH=24 \
VNC_RESOLUTION=1280x1024 \
VNC_PW=vncpassword \
VNC_USER=user \
VNC_VIEW_ONLY_PW=vncviewonlypassword \
LD_LIBRARY_PATH=/usr/local/lib/ \
OMP_WAIT_POLICY=PASSIVE \
SHELL=/bin/bash \
SINGLE_APPLICATION=0 \
KASMVNC_BUILD_OS=fedora \
KASMVNC_BUILD_OS_CODENAME=thirtythree
EXPOSE $VNC_PORT
WORKDIR $HOME
### REQUIRED STUFF ###
RUN dnf install -y openssl xterm gettext wget
RUN dnf install -y nss_wrapper
RUN dnf install -y xorg-x11-xauth xkeyboard-config
# xorg-x11-server-Xorg
# RUN dnf install -y @xfce-desktop-environment
RUN dnf erase -y pm-utils xscreensaver*
RUN dnf install -y redhat-lsb-core
RUN dnf install -y vim less
RUN dnf install -y @xfce-desktop-environment
RUN echo 'source $STARTUPDIR/generate_container_user' >> $HOME/.bashrc
RUN mkdir -p $STARTUPDIR
COPY builder/startup/ $STARTUPDIR
### START CUSTOM STUFF ####
COPY ./builder/scripts/ /tmp/scripts/
COPY ./fedora/kasmvncserver.spec /tmp
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/*.rpm /tmp/
# RUN dnf remove -y tigervnc-server-minimal
RUN /tmp/scripts/install_kasmvncserver_package
### END CUSTOM STUFF ###
RUN chown -R 1000:0 $HOME
USER 1000:kasmvnc-cert
WORKDIR $HOME
ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ]

View File

@@ -1,4 +1,4 @@
FROM opensuse/leap:15.3
FROM opensuse/leap:15.5
ENV STARTUPDIR=/dockerstartup

View File

@@ -1,4 +1,4 @@
FROM opensuse/leap:15.3
FROM opensuse/leap:15.5
ENV KASMVNC_BUILD_OS opensuse
ENV KASMVNC_BUILD_OS_CODENAME 15

View File

@@ -1,4 +1,4 @@
FROM opensuse/leap:15.3
FROM opensuse/leap:15.5
ENV KASMVNC_BUILD_OS opensuse
ENV KASMVNC_BUILD_OS_CODENAME 15

View File

@@ -58,7 +58,8 @@ RUN echo 'alias tv="./run-specs spec/vncserver_yaml_validation_spec.py"' >> ~/.b
RUN echo 'alias ty="./run-specs spec/vncserver_*spec.py"' >> ~/.bashrc
RUN echo 'alias ta="./run-specs"' >> ~/.bashrc
RUN echo 'alias vd="vncserver -dry-run"' >> ~/.bashrc
ENV SET_PASSWORD_FUNC 'sp() { echo -e "$VNC_PW\\n$VNC_PW\\n" | kasmvncpasswd -w -u $USER $HOME/.kasmpasswd; }'
RUN echo 'alias ss="sp; vncserver -select-de xfce"' >> ~/.bashrc
ENV SET_PASSWORD_FUNC 'sp() { echo -e "$VNC_PW\\n$VNC_PW\\n" | kasmvncpasswd -w -u $VNC_USER $HOME/.kasmpasswd; }'
RUN echo $SET_PASSWORD_FUNC >> ~/.bashrc
ENV LC_ALL=C.UTF-8

View File

@@ -7,7 +7,7 @@ License: GPLv2+
URL: https://github.com/kasmtech/KasmVNC
BuildRequires: rsync
Requires: xorg-x11-xauth, xorg-x11-xkb-utils, xkeyboard-config, xorg-x11-server-utils, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny
Requires: xorg-x11-xauth, xorg-x11-xkb-utils, xkeyboard-config, xorg-x11-server-utils, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, perl-DateTime-TimeZone
Conflicts: tigervnc-server, tigervnc-server-minimal
%description

View File

@@ -0,0 +1,17 @@
# - Find freetype
# Find the freetype libraries
#
# This module defines the following variables:
# FREETYPE_FOUND - True if freetype is found
# FREETYPE_INCLUDE_DIRS - include directories
#
find_package(PkgConfig)
pkg_check_modules(PC_FREETYPE freetype2)
find_path(FREETYPE_INCLUDE_DIRS NAMES ft2build.h HINTS ${PC_FREETYPE_INCLUDE_DIRS})
include(FindPackageHandleStandardArgs)
set(FPHSA_NAME_MISMATCHED 1)
find_package_handle_standard_args(freetype DEFAULT_MSG FREETYPE_INCLUDE_DIRS)
unset(FPHSA_NAME_MISMATCHED)
mark_as_advanced(FREETYPE_INCLUDE_DIRS)

View File

@@ -88,6 +88,9 @@ namespace rfb {
virtual void clearLocalClipboards() {}
virtual void receivedUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len) {}
protected:
virtual ~SDesktop() {}
};

View File

@@ -98,6 +98,9 @@ namespace rfb {
virtual void udpUpgrade(const char *resp) = 0;
virtual void udpDowngrade(const bool) = 0;
virtual void subscribeUnixRelay(const char *name) = 0;
virtual void unixRelay(const char *name, const rdr::U8 *buf, const unsigned len) = 0;
ConnParams cp;
};
}

View File

@@ -100,6 +100,12 @@ void SMsgReader::readMsg()
case msgTypeUpgradeToUdp:
readUpgradeToUdp();
break;
case msgTypeSubscribeUnixRelay:
readSubscribeUnixRelay();
break;
case msgTypeUnixRelay:
readUnixRelay();
break;
default:
fprintf(stderr, "unknown message type %d\n", msgType);
throw Exception("unknown message type");
@@ -357,3 +363,42 @@ void SMsgReader::readUpgradeToUdp()
handler->udpUpgrade(resp);
}
void SMsgReader::readSubscribeUnixRelay()
{
const rdr::U8 namelen = is->readU8();
char name[64];
if (namelen >= sizeof(name)) {
vlog.error("Ignoring subscribe with too large name");
is->skip(namelen);
return;
}
is->readBytes(name, namelen);
name[namelen] = '\0';
handler->subscribeUnixRelay(name);
}
void SMsgReader::readUnixRelay()
{
const rdr::U8 namelen = is->readU8();
char name[64];
if (namelen >= sizeof(name)) {
vlog.error("Ignoring relay packet with too large name");
is->skip(namelen);
return;
}
is->readBytes(name, namelen);
name[namelen] = '\0';
const rdr::U32 len = is->readU32();
rdr::U8 buf[1024 * 1024];
if (len >= sizeof(buf)) {
vlog.error("Ignoring relay packet with too large data");
is->skip(len);
return ;
}
is->readBytes(buf, len);
handler->unixRelay(name, buf, len);
}

View File

@@ -65,6 +65,9 @@ namespace rfb {
void readUpgradeToUdp();
void readSubscribeUnixRelay();
void readUnixRelay();
SMsgHandler* handler;
rdr::InStream* is;
};

View File

@@ -749,3 +749,29 @@ void SMsgWriter::writeUdpUpgrade(const char *resp)
endMsg();
}
void SMsgWriter::writeSubscribeUnixRelay(const bool success, const char *msg)
{
startMsg(msgTypeSubscribeUnixRelay);
const rdr::U8 len = strlen(msg);
os->writeU8(success);
os->writeU8(len);
os->writeBytes(msg, len);
endMsg();
}
void SMsgWriter::writeUnixRelay(const char *name, const rdr::U8 *buf, const unsigned len)
{
startMsg(msgTypeUnixRelay);
const rdr::U8 namelen = strlen(name);
os->writeU8(namelen);
os->writeBytes(name, namelen);
os->writeU32(len);
os->writeBytes(buf, len);
endMsg();
}

View File

@@ -129,6 +129,9 @@ namespace rfb {
void writeUdpUpgrade(const char *resp);
void writeSubscribeUnixRelay(const bool success, const char *msg);
void writeUnixRelay(const char *name, const rdr::U8 *buf, const unsigned len);
protected:
void startMsg(int type);
void endMsg();

View File

@@ -189,6 +189,18 @@ rfb::IntParameter rfb::Server::DLP_WatermarkRepeatSpace
("DLP_WatermarkRepeatSpace",
"Number of pixels between repeats of the watermark",
0, 0, 4096);
rfb::IntParameter rfb::Server::DLP_WatermarkFontSize
("DLP_WatermarkFontSize",
"Font size for -DLP_WatermarkText",
48, 8, 256);
rfb::IntParameter rfb::Server::DLP_WatermarkTimeOffset
("DLP_WatermarkTimeOffset",
"Offset from UTC for -DLP_WatermarkText",
0, -24, 24);
rfb::IntParameter rfb::Server::DLP_WatermarkTimeOffsetMinutes
("DLP_WatermarkTimeOffsetMinutes",
"Offset from UTC for -DLP_WatermarkText, minutes",
0, -24 * 60, 24 * 60);
rfb::StringParameter rfb::Server::DLP_WatermarkImage
("DLP_WatermarkImage",
"PNG file to use as a watermark",
@@ -201,6 +213,14 @@ rfb::StringParameter rfb::Server::DLP_WatermarkTint
("DLP_WatermarkTint",
"Tint the greyscale watermark by this color.",
"255,255,255,255");
rfb::StringParameter rfb::Server::DLP_WatermarkText
("DLP_WatermarkText",
"Use this text instead of an image for the watermark, with strftime time formatting",
"");
rfb::StringParameter rfb::Server::DLP_WatermarkFont
("DLP_WatermarkFont",
"Use this font for -DLP_WatermarkText instead of the bundled one",
"");
rfb::StringParameter rfb::Server::maxVideoResolution
("MaxVideoResolution",

View File

@@ -49,12 +49,17 @@ namespace rfb {
static IntParameter DLP_ClipDelay;
static IntParameter DLP_KeyRateLimit;
static IntParameter DLP_WatermarkRepeatSpace;
static IntParameter DLP_WatermarkFontSize;
static IntParameter DLP_WatermarkTimeOffset;
static IntParameter DLP_WatermarkTimeOffsetMinutes;
static StringParameter DLP_ClipLog;
static StringParameter DLP_Region;
static StringParameter DLP_Clip_Types;
static StringParameter DLP_WatermarkImage;
static StringParameter DLP_WatermarkLocation;
static StringParameter DLP_WatermarkTint;
static StringParameter DLP_WatermarkText;
static StringParameter DLP_WatermarkFont;
static BoolParameter DLP_RegionAllowClick;
static BoolParameter DLP_RegionAllowRelease;
static IntParameter jpegVideoQuality;

View File

@@ -51,6 +51,8 @@ static Cursor emptyCursor(0, 0, Point(0, 0), NULL);
extern rfb::BoolParameter disablebasicauth;
extern "C" char unixrelaynames[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
bool reverse)
: upgradingToUdp(false), sock(s), reverseConnection(reverse),
@@ -73,6 +75,10 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
memset(bstats_total, 0, sizeof(bstats_total));
gettimeofday(&connStart, NULL);
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++)
unixRelaySubscriptions[i][0] = '\0';
// Check their permissions, if applicable
kasmpasswdpath[0] = '\0';
wordexp_t wexp;
@@ -1789,3 +1795,54 @@ void VNCSConnectionST::udpDowngrade(const bool byServer)
vlog.info("Client %s downgrading from udp by %s", sock->getPeerAddress(),
byServer ? "the server" : "its own request");
}
void VNCSConnectionST::subscribeUnixRelay(const char *name)
{
bool read, write, owner;
if (!getPerms(read, write, owner) || !write) {
// Need write permissions to subscribe
writer()->writeSubscribeUnixRelay(false, "No permissions");
vlog.info("Client tried to subscribe to unix channel %s without permissions", name);
return;
}
unsigned i;
bool found = false;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!strcmp(name, unixrelaynames[i])) {
found = true;
break;
}
}
if (!found) {
writer()->writeSubscribeUnixRelay(false, "No such unix channel");
vlog.info("Client tried to subscribe to nonexistent unix channel %s", name);
return;
}
writer()->writeSubscribeUnixRelay(true, "Ok");
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!unixRelaySubscriptions[i][0]) {
strcpy(unixRelaySubscriptions[i], name);
break;
}
}
}
void VNCSConnectionST::unixRelay(const char *name, const rdr::U8 *buf, const unsigned len)
{
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!strcmp(unixRelaySubscriptions[i], name)) {
server->desktop->receivedUnixRelayData(name, buf, len);
return;
}
}
}
void VNCSConnectionST::sendUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len)
{
writer()->writeUnixRelay(name, buf, len);
}

View File

@@ -33,6 +33,7 @@
#include <rfb/EncodeManager.h>
#include <rfb/SConnection.h>
#include <rfb/Timer.h>
#include <rfb/unixRelayLimits.h>
namespace rfb {
class VNCServerST;
@@ -200,6 +201,18 @@ namespace rfb {
bool upgradingToUdp;
bool isSubscribedToUnixRelay(const char *name) const {
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!strcmp(unixRelaySubscriptions[i], name))
return true;
}
return false;
}
virtual void sendUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len);
private:
// SConnection callbacks
@@ -222,6 +235,8 @@ namespace rfb {
virtual void handleClipboardAnnounce(bool available);
virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]);
virtual void udpUpgrade(const char *resp);
virtual void subscribeUnixRelay(const char *name);
virtual void unixRelay(const char *name, const rdr::U8 *buf, const unsigned len);
virtual void supportsLocalCursor();
virtual void supportsFence();
virtual void supportsContinuousUpdates();
@@ -324,6 +339,8 @@ namespace rfb {
bool frameTracking;
uint32_t udpFramesSinceFull;
char unixRelaySubscriptions[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
bool complainedAboutNoViewRights;
};
}

View File

@@ -974,6 +974,11 @@ void VNCServerST::writeUpdate()
blackOut();
}
if (watermarkData && Server::DLP_WatermarkText[0] && watermarkTextNeedsUpdate(true)) {
// If using a text watermark, we have to mark everything as changed...
refreshClients();
}
comparer->getUpdateInfo(&ui, pb->getRect());
toCheck = ui.changed.union_(ui.copied);
@@ -1248,3 +1253,15 @@ void VNCServerST::refreshClients()
(*i)->add_changed_all();
}
}
void VNCServerST::sendUnixRelayData(const char name[],
const unsigned char *buf, const unsigned len)
{
// For each client subscribed to this channel, send the data to them
std::list<VNCSConnectionST*>::iterator i;
for (i = clients.begin(); i != clients.end(); i++) {
if ((*i)->isSubscribedToUnixRelay(name)) {
(*i)->sendUnixRelayData(name, buf, len);
}
}
}

View File

@@ -198,6 +198,7 @@ namespace rfb {
const char mimes[][32]);
void refreshClients();
void sendUnixRelayData(const char name[], const unsigned char *buf, const unsigned len);
protected:

View File

@@ -20,10 +20,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <zlib.h>
#include <rfb/LogWriter.h>
#include <rfb/ServerCore.h>
#include <rfb/VNCServerST.h>
#include "font.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include "Watermark.h"
@@ -36,6 +40,10 @@ watermarkInfo_t watermarkInfo;
uint8_t *watermarkData, *watermarkUnpacked, *watermarkTmp;
uint32_t watermarkDataLen;
static uint16_t rw, rh;
static time_t lastUpdate;
static FT_Library ft = NULL;
static FT_Face face;
#define MAXW 4096
#define MAXH 4096
@@ -92,15 +100,151 @@ static bool loadimage(const char path[]) {
return true;
}
// Note: w and h are absolute
static void str(uint8_t *buf, const char *txt, const uint32_t x_, const uint32_t y_,
const uint32_t w, const uint32_t h,
const uint32_t stride) {
unsigned ucs[256], i, ucslen;
unsigned len = strlen(txt);
i = 0;
ucslen = 0;
while (len > 0 && txt[i]) {
size_t ret = rfb::utf8ToUCS4(&txt[i], len, &ucs[ucslen]);
i += ret;
len -= ret;
ucslen++;
}
uint32_t x, y;
x = x_;
y = y_;
for (i = 0; i < ucslen; i++) {
if (FT_Load_Char(face, ucs[i], FT_LOAD_RENDER))
continue;
const FT_Bitmap * const map = &(face->glyph->bitmap);
if (FT_HAS_KERNING(face) && i) {
FT_Vector delta;
FT_Get_Kerning(face, ucs[i - 1], ucs[i], ft_kerning_default, &delta);
x += delta.x >> 6;
}
uint32_t row, col;
for (row = 0; row < (uint32_t) map->rows; row++) {
int ny = row + y - face->glyph->bitmap_top;
if (ny < 0)
continue;
if ((unsigned) ny >= h)
continue;
uint8_t *dst = (uint8_t *) buf;
dst += ny * stride + x;
const uint8_t *src = map->buffer + map->pitch * row;
for (col = 0; col < (uint32_t) map->width; col++) {
if (col + x >= w)
continue;
const uint8_t out = (src[col] + 8) >> 4;
dst[col] = out < 16 ? out : 15;
}
}
x += face->glyph->advance.x >> 6;
}
}
static uint32_t drawnwidth(const char *txt) {
unsigned ucs[256], i, ucslen;
unsigned len = strlen(txt);
i = 0;
ucslen = 0;
while (len > 0 && txt[i]) {
size_t ret = rfb::utf8ToUCS4(&txt[i], len, &ucs[ucslen]);
i += ret;
len -= ret;
ucslen++;
}
uint32_t x;
x = 0;
for (i = 0; i < ucslen; i++) {
if (FT_Load_Char(face, ucs[i], FT_LOAD_DEFAULT))
continue;
if (FT_HAS_KERNING(face) && i) {
FT_Vector delta;
FT_Get_Kerning(face, ucs[i - 1], ucs[i], ft_kerning_default, &delta);
x += delta.x >> 6;
}
x += face->glyph->advance.x >> 6;
}
return x;
}
static bool drawtext(const char fmt[], const int16_t utcOff, const char fontpath[],
const uint8_t fontsize) {
char buf[PATH_MAX];
if (!ft) {
if (FT_Init_FreeType(&ft))
abort();
if (fontpath[0]) {
if (FT_New_Face(ft, fontpath, 0, &face))
abort();
} else {
if (FT_New_Memory_Face(ft, font_otf, sizeof(font_otf), 0, &face))
abort();
}
FT_Set_Pixel_Sizes(face, fontsize, fontsize);
}
time_t now = lastUpdate = time(NULL);
now += utcOff * 60;
struct tm *tm = gmtime(&now);
size_t len = strftime(buf, PATH_MAX, fmt, tm);
if (!len)
return false;
free(watermarkInfo.src);
const uint32_t h = fontsize + 4;
const uint32_t w = drawnwidth(buf);
watermarkInfo.w = w;
watermarkInfo.h = h;
watermarkInfo.src = (uint8_t *) calloc(w, h);
str(watermarkInfo.src, buf, 0, fontsize, w, h, w);
return true;
}
bool watermarkInit() {
memset(&watermarkInfo, 0, sizeof(watermarkInfo_t));
watermarkData = watermarkUnpacked = watermarkTmp = NULL;
rw = rh = 0;
if (!Server::DLP_WatermarkImage[0])
if (!Server::DLP_WatermarkImage[0] && !Server::DLP_WatermarkText[0])
return true;
if (!loadimage(Server::DLP_WatermarkImage))
if (Server::DLP_WatermarkImage[0] && Server::DLP_WatermarkText[0]) {
vlog.error("WatermarkImage and WatermarkText can't be used together");
return false;
}
if (Server::DLP_WatermarkImage[0] && !loadimage(Server::DLP_WatermarkImage))
return false;
if (Server::DLP_WatermarkText[0] &&
!drawtext(Server::DLP_WatermarkText,
Server::DLP_WatermarkTimeOffset * 60 + Server::DLP_WatermarkTimeOffsetMinutes,
Server::DLP_WatermarkFont, Server::DLP_WatermarkFontSize))
return false;
if (Server::DLP_WatermarkRepeatSpace && Server::DLP_WatermarkLocation[0]) {
@@ -136,10 +280,22 @@ bool watermarkInit() {
}
// update the screen-size rendered watermark whenever the screen is resized
// or if using text, every frame
void VNCServerST::updateWatermark() {
if (rw == pb->width() &&
rh == pb->height())
return;
rh == pb->height()) {
if (Server::DLP_WatermarkImage[0])
return;
if (!watermarkTextNeedsUpdate(false))
return;
}
if (Server::DLP_WatermarkText[0] && watermarkTextNeedsUpdate(false)) {
drawtext(Server::DLP_WatermarkText,
Server::DLP_WatermarkTimeOffset * 60 + Server::DLP_WatermarkTimeOffsetMinutes,
Server::DLP_WatermarkFont, Server::DLP_WatermarkFontSize);
}
rw = pb->width();
rh = pb->height();
@@ -246,3 +402,15 @@ void packWatermark(const Region &changed) {
watermarkDataLen = destLen;
}
// Limit changes to once per second
bool watermarkTextNeedsUpdate(const bool early) {
static time_t now;
// We're called a couple times per frame, only grab the
// time on the first time so it doesn't change inside a frame
if (early)
now = time(NULL);
return now != lastUpdate;
}

View File

@@ -36,6 +36,7 @@ extern watermarkInfo_t watermarkInfo;
bool watermarkInit();
void packWatermark(const rfb::Region &changed); // filter and pack the watermark for sending
bool watermarkTextNeedsUpdate(const bool early);
extern uint8_t *watermarkData;
extern uint32_t watermarkDataLen;

3107
common/rfb/font.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,8 @@ namespace rfb {
const int msgTypeRequestFrameStats = 179;
const int msgTypeBinaryClipboard = 180;
const int msgTypeUpgradeToUdp = 181;
const int msgTypeSubscribeUnixRelay = 182;
const int msgTypeUnixRelay = 183;
const int msgTypeServerFence = 248;
@@ -54,6 +56,8 @@ namespace rfb {
// same as the other direction
//const int msgTypeBinaryClipboard = 180;
//const int msgTypeUpgradeToUdp = 181;
//const int msgTypeSubscribeUnixRelay = 182;
//const int msgTypeUnixRelay = 183;
const int msgTypeClientFence = 248;

View File

@@ -0,0 +1,7 @@
#ifndef UNIX_RELAY_LIMITS_H
#define UNIX_RELAY_LIMITS_H
#define MAX_UNIX_RELAYS 4
#define MAX_UNIX_RELAY_NAME_LEN 64
#endif

2
debian/control vendored
View File

@@ -14,7 +14,7 @@ Architecture: amd64 arm64
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, ssl-cert, xauth,
x11-xkb-utils, xkb-data, procps, libswitch-perl, libyaml-tiny-perl,
libhash-merge-simple-perl, libscalar-list-utils-perl, liblist-moreutils-perl,
libtry-tiny-perl, libgbm1
libtry-tiny-perl, libdatetime-timezone-perl, libgbm1
Provides: vnc-server
Description: KasmVNC provides remote web-based access to a Desktop or application.
While VNC is in the name, KasmVNC differs from other VNC variants such

View File

@@ -7,7 +7,7 @@ License: GPLv2+
URL: https://github.com/kasmtech/KasmVNC
BuildRequires: rsync
Requires: xorg-x11-xauth, xkeyboard-config, xkbcomp, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, mesa-libgbm, libxshmfence
Requires: xorg-x11-xauth, xkeyboard-config, xkbcomp, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, perl-DateTime-TimeZone, mesa-libgbm, libxshmfence
Conflicts: tigervnc-server, tigervnc-server-minimal
%description

Submodule kasmweb updated: 3873a59941...2b7e3321ae

View File

@@ -7,7 +7,7 @@ License: GPLv2+
URL: https://github.com/kasmtech/KasmVNC
BuildRequires: rsync
Requires: xauth, hostname, libxkbcommon-x11-0, xkeyboard-config, x11-tools, openssl, perl, libpixman-1-0, libjpeg8, libgomp1, libXfont2-2, libXdmcp6, libglvnd, xkbcomp, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, libgbm1, libxshmfence1
Requires: xauth, hostname, libxkbcommon-x11-0, xkeyboard-config, x11-tools, openssl, perl, libpixman-1-0, libjpeg8, libgomp1, libXfont2-2, libXdmcp6, libglvnd, xkbcomp, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, perl-DateTime, perl-DateTime-TimeZone, libgbm1, libxshmfence1
Conflicts: tigervnc, tigervnc-x11vnc
%description

View File

@@ -7,7 +7,7 @@ License: GPLv2+
URL: https://github.com/kasmtech/KasmVNC
BuildRequires: rsync
Requires: xorg-x11-xauth, xorg-x11-xkb-utils, xkeyboard-config, xorg-x11-server-utils, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, hostname, mesa-libgbm, libxshmfence
Requires: xorg-x11-xauth, xorg-x11-xkb-utils, xkeyboard-config, xorg-x11-server-utils, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, perl-DateTime-TimeZone, hostname, mesa-libgbm, libxshmfence
Conflicts: tigervnc-server, tigervnc-server-minimal
%description

View File

@@ -7,7 +7,7 @@ License: GPLv2+
URL: https://github.com/kasmtech/KasmVNC
BuildRequires: rsync
Requires: xorg-x11-xauth, xkeyboard-config, xorg-x11-server-utils, xkbcomp, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, hostname, mesa-libgbm, libxshmfence
Requires: xorg-x11-xauth, xkeyboard-config, xorg-x11-server-utils, xkbcomp, openssl, perl, perl-Switch, perl-YAML-Tiny, perl-Hash-Merge-Simple, perl-Scalar-List-Utils, perl-List-MoreUtils, perl-Try-Tiny, perl-DateTime-TimeZone, hostname, mesa-libgbm, libxshmfence
Conflicts: tigervnc-server, tigervnc-server-minimal
%description

View File

@@ -2,7 +2,7 @@ import os
import re
import shutil
from os.path import expanduser
from mamba import description, context, fcontext, it, fit, before, after
from mamba import description, context, fcontext, it, fit, _it, before, after
from expects import expect, equal, contain, match
from helper.spec_helper import start_xvnc, kill_xvnc, run_cmd, clean_env, \
@@ -268,6 +268,18 @@ with description('YAML to CLI') as self:
completed_process.stdout)
expect(cli_option).to(equal("-geometry '1024x768'"))
with it("allows wide utf characters"):
write_config('''
data_loss_prevention:
watermark:
text:
template: "星街すいせい"
''')
completed_process = run_vncserver()
cli_option = pick_cli_option('DLP_WatermarkText',
completed_process.stdout)
expect(cli_option).to(equal("-DLP_WatermarkText '星街すいせい'"))
with it("ignores empty section override"):
write_config('''
security:

9
t Normal file
View File

@@ -0,0 +1,9 @@
use DateTime::TimeZone;
my $timezone = $ARGV[0];
if (DateTime::TimeZone->is_valid_name($timezone)) {
print "Valid timezone\n";
} else {
print "Invalid timezone\n";
}

11
t2 Normal file
View File

@@ -0,0 +1,11 @@
use DateTime;
use DateTime::TimeZone;
#my $timezone_name = 'America/New_York';
my $timezone_name = 'UTC';
my $dt = DateTime->now(time_zone => $timezone_name);
my $offset = $dt->offset();
print "Timezone: $timezone_name\n";
print "Offset: $offset seconds\n";

View File

@@ -0,0 +1,37 @@
package KasmVNC::CallbackValidator;
use strict;
use warnings;
use v5.10;
use Data::Dumper;
use KasmVNC::Utils;
sub new {
my ($class, $args) = @_;
my $self = bless {
isValidCallback => $args->{isValidCallback},
errorMessage => $args->{errorMessage}
}, $class;
}
sub validate {
my $self = shift;
$self->{configKey} = shift;
my @values = @{ listify($self->{configKey}->value()) };
foreach my $value (@values) {
$self->validateValue($value);
}
}
sub validateValue {
my $self = shift;
my $value = shift;
unless ($self->{isValidCallback}($value)) {
$self->{configKey}->addErrorMessage($self->{errorMessage});
}
}
1;

View File

@@ -35,7 +35,7 @@ sub new {
},
toStringSub => $args->{toStringSub} || sub {
my $self = shift;
my $derivedValue = $self->deriveValue();
if (defined($derivedValue)) {
return "-$self->{name} " . "'$derivedValue'";

View File

@@ -45,6 +45,8 @@ sub isPresent {
sub deriveBoolean {
my $value = shift;
return $value if containsWideSymbols($value);
switch($value) {
case 'true' {
return 1;
@@ -63,4 +65,12 @@ sub printStackTrace {
print { *STDERR } $trace->as_string;
}
sub containsWideSymbols {
my $string = shift;
return 1 unless defined($string);
$string =~ /[^\x00-\xFF]/;
}
1;

View File

@@ -23,6 +23,9 @@ network:
pem_certificate: /etc/ssl/certs/ssl-cert-snakeoil.pem
pem_key: /etc/ssl/private/ssl-cert-snakeoil.key
require_ssl: true
# unix_relay:
# name:
# path:
user_session:
# session_type: shared
@@ -92,6 +95,11 @@ data_loss_prevention:
# location: 10,10
# tint: 255,20,20,128
# repeat_spacing: 10
#text:
# template: "${USER} %H:%M"
# font: auto
# font_size: 48
# timezone_name: Australia/Adelaide
logging:
# "verbose" SETTING LOGS YOUR PRIVATE INFORMATION. Keypresses and clipboard content
level: off

View File

@@ -27,6 +27,7 @@
use v5.10;
use warnings;
use utf8;
sub DEVENV() { $ENV{KASMVNC_DEVELOPMENT} };
use if DEVENV, Devel::StackTrace;
@@ -38,11 +39,14 @@ use List::Util qw(first);
use List::MoreUtils qw(any uniq);
use Data::Dumper;
use Try::Tiny;
use DateTime;
use DateTime::TimeZone;
use KasmVNC::CliOption;
use KasmVNC::ConfigKey;
use KasmVNC::PatternValidator;
use KasmVNC::EnumValidator;
use KasmVNC::CallbackValidator;
use KasmVNC::Config;
use KasmVNC::Users;
use KasmVNC::TextOption;
@@ -56,6 +60,7 @@ use constant {
OPTIONAL_ARG_VALUE => 2
};
UseUtfStdio();
InitLogger();
CheckWeCanRunInThisEnvironment();
@@ -1397,6 +1402,24 @@ sub DefineConfigToCLIConversion {
})
]
}),
KasmVNC::CliOption->new({
name => 'UnixRelay',
configKeys => [
KasmVNC::ConfigKey->new({
name => "network.unix_relay.name",
type => KasmVNC::ConfigKey::ANY
}),
KasmVNC::ConfigKey->new({
name => "network.unix_relay.path",
type => KasmVNC::ConfigKey::ANY
})
],
deriveValueSub => sub {
my $self = shift;
$self->{"network.unix_relay.name"} . ":" . $self->{"network.unix_relay.path"};
},
}),
KasmVNC::CliOption->new({
name => 'AlwaysShared',
configKeys => [
@@ -1765,6 +1788,79 @@ sub DefineConfigToCLIConversion {
})
]
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkText',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.text.template",
validator => KasmVNC::CallbackValidator->new({
isValidCallback => sub {
my $value = shift;
isBlank(ConfigValue("data_loss_prevention.watermark.image"));
},
errorMessage => "Watermark image and text can't be used at the same time"
}),
})
]
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkFont',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.text.font",
type => KasmVNC::ConfigKey::ANY
})
],
isActiveSub => sub {
$self = shift;
my $value = $self->configValue();
isPresent($value) && $value ne "auto";
}
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkFontSize',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.text.font_size",
validator => KasmVNC::CallbackValidator->new({
isValidCallback => sub {
my $value = shift;
return 0 unless $value =~ /^\d+$/;
$value >= 8 && $value <= 256;
},
errorMessage => "must be in range 8..256"
}),
})
]
}),
KasmVNC::CliOption->new({
name => 'DLP_WatermarkTimeOffsetMinutes',
configKeys => [
KasmVNC::ConfigKey->new({
name => "data_loss_prevention.watermark.text.timezone_name",
validator => KasmVNC::CallbackValidator->new({
isValidCallback => sub {
my $timezone_name = shift;
DateTime::TimeZone->is_valid_name($timezone_name);
},
errorMessage => "must be a valid timezone name like Australia/Adelaide"
})
})
],
deriveValueSub => sub {
my $self = shift;
my $timezone_name = $self->configValue();
my $dt = DateTime->now(time_zone => $timezone_name);
my $offset_in_seconds = $dt->offset();
$offset_in_seconds/60;
}
}),
KasmVNC::CliOption->new({
name => 'DLP_Log',
configKeys => [
@@ -2835,3 +2931,7 @@ sub InitLogger {
my $debugEnabled = any { $_ eq "-debug" } @ARGV;
$logger = KasmVNC::Logger->new({ level => $debugEnabled ? "debug" : "warn" });
}
sub UseUtfStdio {
use open qw( :std :encoding(UTF-8) );
}

View File

@@ -52,7 +52,8 @@ Xvnc_CPPFLAGS = $(XVNC_CPPFLAGS) -DKASMVNC -DNO_MODULE_EXTS \
-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
$(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XVNC_SYS_LIBS) -lX11 -lwebp -lssl -lcrypto -lcrypt \
-lfreetype
Xvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) -fopenmp

View File

@@ -29,6 +29,8 @@
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <sys/utsname.h>
@@ -51,6 +53,7 @@ extern "C" {
void vncSetGlueContext(int screenIndex);
extern int wakeuppipe[2];
extern struct sockaddr_un unixrelayclients[MAX_UNIX_RELAYS];
}
using namespace rfb;
@@ -323,6 +326,26 @@ void XserverDesktop::handleSocketEvent(int fd, bool read, bool write)
return;
}
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (unixrelays[i] == -1)
break;
if (fd == unixrelays[i]) {
do {
struct sockaddr_un client;
socklen_t addrlen = sizeof(struct sockaddr_un);
const ssize_t len = recvfrom(unixrelays[i], unixbuf, sizeof(unixbuf),
MSG_DONTWAIT,
(struct sockaddr *) &client, &addrlen);
if (len <= 0)
break;
memcpy(&unixrelayclients[i], &client, addrlen);
server->sendUnixRelayData(unixrelaynames[i], unixbuf, len);
} while (1);
return;
}
}
if (handleListenerEvent(fd, &listeners, server))
return;
}
@@ -557,3 +580,21 @@ bool XserverDesktop::handleTimeout(Timer* t)
return false;
}
void XserverDesktop::receivedUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len)
{
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (unixrelays[i] == -1)
break;
if (strcmp(name, unixrelaynames[i]))
continue;
if (sendto(unixrelays[i], buf, len, 0,
(struct sockaddr *) &unixrelayclients[i], sizeof(struct sockaddr_un)) == -1)
vlog.error("Error writing unix relay data to %s", name);
break;
}
}

View File

@@ -110,6 +110,9 @@ public:
const char* userName,
char** reason);
virtual void receivedUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len);
protected:
bool handleListenerEvent(int fd,
std::list<network::SocketListener*>* sockets,
@@ -138,5 +141,7 @@ private:
rfb::Point oldCursorPos;
bool resizing;
uint8_t unixbuf[1024 * 1024];
};
#endif

View File

@@ -89,6 +89,11 @@ Use IPv4 for incoming and outgoing connections. Default is on.
Use IPv6 for incoming and outgoing connections. Default is on.
.
.TP
.B \-UnixRelay \fIname:path\fP
Create a local named unix socket, for relaying data. May be given multiple times.
Example: -UnixRelay audio:/tmp/audiosock
.
.TP
.B \-rfbunixpath \fIpath\fP
Specifies the path of a Unix domain socket on which Xvnc listens for
connections from viewers, instead of listening on a TCP port.
@@ -243,6 +248,8 @@ Default \fB-1\fP.
.B \-WebpVideoQuality \fInum\fP
The WEBP quality to use when in video mode.
Default \fB-1\fP.
.
.TP
.B \-MaxVideoResolution \fI1920x1080\fP
When in video mode, downscale the screen to max this size. Keeps aspect ratio.
Default \fB1920x1080\fP.
@@ -372,6 +379,28 @@ The color components can be used to colorize the greyscale watermark, and the al
can be used to make it fainter.
.
.TP
.B \-DLP_WatermarkText \fI"foo %H:%M"\fP
Instead of an image, render this text as the watermark. Takes time formatting options
for \fBstrftime\fP.
.
.TP
.B \-DLP_WatermarkFont \fI/path/to/font.ttf\fP
Use a different font for -DLP_WatermarkText than the bundled one. TTF and OTF fonts
are accepted.
.
.TP
.B \-DLP_WatermarkFontSize \fI48\fP
Font size for -DLP_WatermarkText. Default \fI48\fP.
.
.TP
.B \-DLP_WatermarkTimeOffset \fI0\fP
Time offset from UTC, hours. Default \fI0\fP.
.
.TP
.B \-DLP_WatermarkTimeOffsetMinutes \fI0\fP
Time offset from UTC, minutes. Default \fI0\fP.
.
.TP
.B \-selfBench
Run a set of self-benchmarks and exit.
.

View File

@@ -55,6 +55,15 @@ typedef struct gbm_pixmap gbm_pixmap;
static DevPrivateKeyRec dri3_pixmap_private_key;
static struct timeval start;
#define MAX_TEXPIXMAPS 32
static PixmapPtr texpixmaps[MAX_TEXPIXMAPS];
static uint32_t num_texpixmaps;
static CARD32 update_texpixmaps(OsTimerPtr timer, CARD32 time, void *arg);
static OsTimerPtr texpixmaptimer;
void xvnc_sync_dri3_textures(void);
void xvnc_sync_dri3_pixmap(PixmapPtr pixmap);
void xvnc_init_dri3(void);
static int
@@ -99,6 +108,29 @@ static gbm_pixmap *gbm_pixmap_get(PixmapPtr pixmap)
return dixLookupPrivate(&pixmap->devPrivates, &dri3_pixmap_private_key);
}
static void add_texpixmap(PixmapPtr pix)
{
uint32_t i;
for (i = 0; i < MAX_TEXPIXMAPS; i++) {
if (texpixmaps[i] == pix)
return;
}
for (i = 0; i < MAX_TEXPIXMAPS; i++) {
if (!texpixmaps[i]) {
texpixmaps[i] = pix;
pix->refcnt++;
num_texpixmaps++;
// start if not running
if (!texpixmaptimer)
texpixmaptimer = TimerSet(NULL, 0, 16, update_texpixmaps, NULL);
return;
}
}
ErrorF("Max number of texpixmaps reached\n");
}
static PixmapPtr
create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, CARD8 depth)
{
@@ -164,14 +196,33 @@ xvnc_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
uint64_t *modifier)
{
gbm_pixmap *gp = gbm_pixmap_get(pixmap);
if (!gp)
return 0;
if (!gp) {
gp = calloc(1, sizeof(gbm_pixmap));
if (!gp)
return 0;
gp->bo = gbm_bo_create(priv.gbm,
pixmap->drawable.width,
pixmap->drawable.height,
gbm_format_for_depth(pixmap->drawable.depth),
(pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ?
GBM_BO_USE_LINEAR : 0) |
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
if (!gp->bo) {
ErrorF("Failed to create bo\n");
return 0;
}
dri3_pixmap_set_private(pixmap, gp);
}
fds[0] = gbm_bo_get_fd(gp->bo);
strides[0] = gbm_bo_get_stride(gp->bo);
offsets[0] = 0;
*modifier = DRM_FORMAT_MOD_INVALID;
add_texpixmap(pixmap);
return 1;
}
@@ -219,12 +270,13 @@ void xvnc_sync_dri3_pixmap(PixmapPtr pixmap)
void *ptr;
uint32_t stride, w, h;
void *opaque = NULL;
gbm_pixmap *gp;
// 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);
gp = gbm_pixmap_get(pixmap);
if (!gp) {
//ErrorF("Present tried to copy from a non-dri3 pixmap\n");
return;
@@ -252,6 +304,69 @@ void xvnc_sync_dri3_pixmap(PixmapPtr pixmap)
gbm_bo_unmap(gp->bo, opaque);
}
void xvnc_sync_dri3_textures(void)
{
// Sync the tracked pixmaps into their textures (bos)
// This is a bit of an ugly solution, but we don't know
// when the pixmaps have changed nor when the textures are read.
//
// This is called both from the global damage report and the timer,
// to account for cases that do not use the damage report.
uint32_t i, y;
gbm_pixmap *gp;
uint8_t *src, *dst;
uint32_t srcstride, dststride;
void *opaque = NULL;
for (i = 0; i < MAX_TEXPIXMAPS; i++) {
if (!texpixmaps[i])
continue;
if (texpixmaps[i]->refcnt == 1) {
// We are the only user left, delete it
texpixmaps[i]->drawable.pScreen->DestroyPixmap(texpixmaps[i]);
texpixmaps[i] = NULL;
num_texpixmaps--;
continue;
}
gp = gbm_pixmap_get(texpixmaps[i]);
opaque = NULL;
dst = gbm_bo_map(gp->bo, 0, 0,
texpixmaps[i]->drawable.width,
texpixmaps[i]->drawable.height,
GBM_BO_TRANSFER_WRITE, &dststride, &opaque);
if (!dst) {
ErrorF("gbm map failed, errno %d\n", errno);
continue;
}
srcstride = texpixmaps[i]->devKind;
src = texpixmaps[i]->devPrivate.ptr;
for (y = 0; y < texpixmaps[i]->drawable.height; y++) {
memcpy(dst, src, srcstride);
dst += dststride;
src += srcstride;
}
gbm_bo_unmap(gp->bo, opaque);
}
}
static CARD32 update_texpixmaps(OsTimerPtr timer, CARD32 time, void *arg)
{
xvnc_sync_dri3_textures();
if (!num_texpixmaps) {
TimerFree(texpixmaptimer);
texpixmaptimer = NULL;
return 0;
}
return 16; // Reschedule next tick
}
void xvnc_init_dri3(void)
{
memset(&priv, 0, sizeof(priv));

View File

@@ -241,6 +241,14 @@ void vncExtensionInit(void)
fcntl(wakeuppipe[0], F_SETFL, flags | O_NONBLOCK);
vncSetNotifyFd(wakeuppipe[0], 0, true, false);
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (unixrelays[i] == -1)
break;
vncSetNotifyFd(unixrelays[i], 0, true, false);
vlog.info("Listening to unix relay socket %s", unixrelaynames[i]);
}
initialised = true;
}

View File

@@ -23,6 +23,8 @@
#include <stddef.h>
#include <sys/select.h>
#include <rfb/unixRelayLimits.h>
// Only from C++
#ifdef __cplusplus
namespace rfb { class StringParameter; };
@@ -106,6 +108,9 @@ void vncRefreshScreenLayout(int scrIdx);
int vncOverrideParam(const char *nameAndValue);
extern int unixrelays[MAX_UNIX_RELAYS];
extern char unixrelaynames[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
#ifdef __cplusplus
}
#endif

View File

@@ -61,8 +61,11 @@ from the X Consortium.
#include "input.h"
#include "mipointer.h"
#include "micmap.h"
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#ifndef WIN32
#include <sys/param.h>
@@ -163,6 +166,73 @@ static char displayNumStr[16];
static int vncVerbose = DEFAULT_LOG_VERBOSITY;
int unixrelays[MAX_UNIX_RELAYS];
char unixrelaynames[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
struct sockaddr_un unixrelayclients[MAX_UNIX_RELAYS];
static unsigned addrelay(const char * const arg)
{
const char *ptr = strchr(arg, ':');
if (!ptr) {
ErrorF("Invalid unixrelay\n");
return 1;
}
const unsigned namelen = ptr - arg;
if (namelen >= MAX_UNIX_RELAY_NAME_LEN) {
ErrorF("Unix relay name too long\n");
return 1;
}
unsigned i;
unsigned char found = 0;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (unixrelays[i] == -1) {
found = 1;
break;
}
}
if (!found) {
ErrorF("Too many unix relays\n");
return 1;
}
memcpy(unixrelaynames[i], arg, namelen);
unixrelaynames[i][namelen] = '\0';
unixrelays[i] = socket(AF_UNIX, SOCK_DGRAM, 0);
if (unixrelays[i] < 0) {
ErrorF("Failed to create unix sock\n");
return 1;
}
ptr++;
struct sockaddr_un sa;
if (strlen(ptr) >= sizeof(sa.sun_path)) {
ErrorF("Unix relay path too long\n");
return 1;
}
sa.sun_family = AF_UNIX;
strcpy(sa.sun_path, ptr);
// SO_REUSEADDR doesn't exist for unix sockets, if the socket exists
// (from our previous run), we need to delete it first. Check it's a
// socket so we don't delete wrong files
struct stat st;
if (stat(ptr, &st) == 0) {
if (S_ISSOCK(st.st_mode))
unlink(ptr);
}
if (bind(unixrelays[i], (struct sockaddr *) &sa, sizeof(struct sockaddr_un))) {
ErrorF("Failed to bind unix sock\n");
return 1;
}
return 0;
}
char *extra_headers = NULL;
unsigned extra_headers_len = 0;
@@ -374,6 +444,7 @@ void ddxUseMsg(void)
ErrorF("-inetd has been launched from inetd\n");
ErrorF("-http-header name=val append this header to all HTTP responses\n");
ErrorF("-noclipboard disable clipboard settings modification via vncconfig utility\n");
ErrorF("-unixrelay name:path create a local named unix relay socket\n");
ErrorF("-verbose [n] verbose startup messages\n");
ErrorF("-quiet minimal startup messages\n");
ErrorF("-version show the server version\n");
@@ -426,6 +497,13 @@ ddxProcessArgument(int argc, char *argv[], int i)
vfbInitializeDefaultScreens();
vfbInitializePixmapDepths();
unsigned r;
for (r = 0; r < MAX_UNIX_RELAYS; r++) {
unixrelays[r] = -1;
unixrelaynames[r][0] = '\0';
}
firstTime = FALSE;
vncInitRFB();
}
@@ -692,6 +770,16 @@ ddxProcessArgument(int argc, char *argv[], int i)
return 1;
}
if (strcasecmp(argv[i], "-unixrelay") == 0)
{
fail_unless_args(argc, i, 1);
++i;
if (addrelay(argv[i]))
return 0;
return 2;
}
if (!strcmp(argv[i], "-verbose")) {
if (++i < argc && argv[i]) {
char *end;
@@ -1916,6 +2004,8 @@ InitOutput(ScreenInfo *scrInfo, int argc, char **argv)
#else
FatalError("DRI3 disabled at compile time\n");
#endif
} else {
driNode = NULL;
}
} /* end InitOutput */

View File

@@ -111,3 +111,23 @@ Index: xserver/mi/miinitext.c
gc = GetScratchGC(drawable->depth, screen);
if (update) {
ChangeGCVal changes[2];
--- xserver.orig/damageext/damageext.c 2019-02-26 21:28:50.000000000 +0200
+++ xserver/damageext/damageext.c 2023-03-21 12:52:58.411647186 +0200
@@ -87,6 +87,8 @@
*h = draw->height;
}
+void xvnc_sync_dri3_textures(void);
+
static void
DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
{
@@ -97,6 +99,8 @@
damageGetGeometry(pDrawable, &x, &y, &w, &h);
+ xvnc_sync_dri3_textures();
+
UpdateCurrentTimeIf();
ev = (xDamageNotifyEvent) {
.type = DamageEventBase + XDamageNotify,