Compare commits

..

2 Commits

Author SHA1 Message Date
Dmitry Maksyoma
0df8de241e More XDG work I'll probably never need 2021-07-01 20:08:49 +12:00
Dmitry Maksyoma
905a65b0cd Proof of concept xdg-portal KDE + Firefox 2021-06-18 07:53:27 +12:00
143 changed files with 1024 additions and 13954 deletions

View File

@@ -1,72 +1,34 @@
#!/bin/bash #!/bin/bash
is_kasmvnc() {
local package="$1";
echo "$package" | grep -q 'kasmvncserver_'
}
detect_deb_package_arch() {
local deb_package="$1"
echo "$deb_package" | sed -e 's/.\+_\([^.]\+\)\.\(d\?\)deb/\1/'
}
find_deb_package() {
local dbgsym_package="$1"
echo "$dbgsym_package" | sed -e 's/-dbgsym//; s/ddeb/deb/'
}
fetch_xvnc_md5sum() {
local deb_package="$1"
deb_package=$(realpath "$deb_package")
local tmpdir=$(mktemp -d)
cd "$tmpdir"
dpkg-deb -e "$deb_package"
cat DEBIAN/md5sums | grep bin/Xkasmvnc | cut -d' ' -f 1
}
function prepare_upload_filename() { function prepare_upload_filename() {
local package="$1"; local package="$1";
if ! is_kasmvnc "$package"; then
export upload_filename="$package"
return
fi
.ci/detect_os_arch_package_format "$package" > /tmp/os_arch_package_format; .ci/detect_os_arch_package_format "$package" > /tmp/os_arch_package_format;
source /tmp/os_arch_package_format; source /tmp/os_arch_package_format;
detect_release_branch detect_release_branch
detect_revision "$package" "$OS_ARCH"
if [ -n "$REVISION" ]; then
REVISION="_${REVISION}"
fi
if [ -n "$RELEASE_BRANCH" ]; then if [ -n "$RELEASE_BRANCH" ]; then
export upload_filename="kasmvncserver_${PACKAGE_OS}_${RELEASE_VERSION}${REVISION}_${OS_ARCH}.${PACKAGE_FORMAT}"; export upload_filename="kasmvncserver_${PACKAGE_OS}_${RELEASE_VERSION}_${OS_ARCH}.${PACKAGE_FORMAT}";
else else
export SANITIZED_BRANCH="$(echo $CI_COMMIT_REF_NAME | sed 's/\//_/g')"; export SANITIZED_BRANCH="$(echo $CI_COMMIT_REF_NAME | sed 's/\//_/g')";
export upload_filename="kasmvncserver_${PACKAGE_OS}_${RELEASE_VERSION}_${SANITIZED_BRANCH}_${CI_COMMIT_SHA:0:6}${REVISION}_${OS_ARCH}.${PACKAGE_FORMAT}"; export upload_filename="kasmvncserver_${PACKAGE_OS}_${RELEASE_VERSION}_${SANITIZED_BRANCH}_${CI_COMMIT_SHA:0:6}_${OS_ARCH}.${PACKAGE_FORMAT}";
fi fi
}; };
function upload_to_s3() { function upload_to_s3() {
local package="$1"; local package="$1";
local upload_filename="$2"; local upload_filename="$2";
local s3_bucket="$3";
# Transfer to S3 # Transfer to S3
python3 amazon-s3-bitbucket-pipelines-python/s3_upload.py "${s3_bucket}" "$package" "${upload_filename}"; python3 amazon-s3-bitbucket-pipelines-python/s3_upload.py "${S3_BUCKET}" "$package" "${S3_BUILD_DIRECTORY}/${upload_filename}";
# Use the Gitlab API to tell Gitlab where the artifact was stored # Use the Gitlab API to tell Gitlab where the artifact was stored
export S3_URL="https://${s3_bucket}.s3.amazonaws.com/${upload_filename}"; export S3_URL="https://${S3_BUCKET}.s3.amazonaws.com/${S3_BUILD_DIRECTORY}/${upload_filename}";
export BUILD_STATUS="{\"key\":\"doc\", \"state\":\"SUCCESSFUL\", \"name\":\"${upload_filename}\", \"url\":\"${S3_URL}\"}";
curl --request POST --header "PRIVATE-TOKEN:${GITLAB_API_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/statuses/${CI_COMMIT_SHA}?state=success&name=build-url&target_url=${S3_URL}";
}; };
function prepare_to_run_scripts_and_s3_uploads() { function prepare_to_run_scripts_and_s3_uploads() {
export DEBIAN_FRONTEND=noninteractive; export DEBIAN_FRONTEND=noninteractive;
apt-get update; apt-get update;
apt-get install -y ruby2.7 git wget; apt-get install -y ruby2.7 git;
apt-get install -y python3 python3-pip python3-boto3 curl pkg-config libxmlsec1-dev; apt-get install -y python3 python3-pip python3-boto3 curl pkg-config libxmlsec1-dev;
git clone https://bitbucket.org/awslabs/amazon-s3-bitbucket-pipelines-python.git; git clone https://bitbucket.org/awslabs/amazon-s3-bitbucket-pipelines-python.git;
}; };
@@ -76,16 +38,3 @@ detect_release_branch() {
export RELEASE_BRANCH=1; export RELEASE_BRANCH=1;
fi fi
} }
detect_revision() {
local package="$1"
local arch="$2"
REVISION=
if ! echo "$package" | grep -q '+'; then
return
fi
REVISION=$(echo "$package" | sed "s/_${arch}.\+//" | sed 's/.\++//')
}

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
builder/build

1
.gitignore vendored
View File

@@ -21,4 +21,3 @@ debian/files
debian/kasmvncserver.substvars debian/kasmvncserver.substvars
debian/kasmvncserver/ debian/kasmvncserver/
.pc .pc
.vscode/

View File

@@ -3,370 +3,93 @@ services:
- docker:dind - docker:dind
variables: variables:
KASMVNC_COMMIT_ID: $CI_COMMIT_SHA
GITLAB_SHARED_DIND_DIR: /builds/$CI_PROJECT_PATH/shared GITLAB_SHARED_DIND_DIR: /builds/$CI_PROJECT_PATH/shared
GIT_SUBMODULE_STRATEGY: normal GIT_SUBMODULE_STRATEGY: normal
GIT_FETCH_EXTRA_FLAGS: --tags GIT_FETCH_EXTRA_FLAGS: --tags
# E.g. BUILD_JOBS: build_debian_buster,build_ubuntu_bionic. This will include
# arm builds, because build_debian_buster_arm matches build_debian_buster.
# "BUILD_JOBS: none" won't build any build jobs, nor www.
BUILD_JOBS: all
stages: stages:
- www
- build - build
- upload - upload
.prepare_build: &prepare_build .prepare_build: &prepare_build
- ls -l
- pwd - pwd
- apk add bash - apk add bash
- mkdir -p "$GITLAB_SHARED_DIND_DIR" && chmod 777 "$GITLAB_SHARED_DIND_DIR" - mkdir -p "$GITLAB_SHARED_DIND_DIR" && chmod 777 "$GITLAB_SHARED_DIND_DIR"
.prepare_www: &prepare_www
- tar -zxf output/www/kasm_www.tar.gz -C builder/
.prepare_artfacts: &prepare_artfacts .prepare_artfacts: &prepare_artfacts
- mkdir output
- cp -r builder/build/* output/ - cp -r builder/build/* output/
- rm output/*.tar.gz - rm output/*.tar.gz
build_www:
stage: www
allow_failure: false
before_script:
- *prepare_build
script:
- webpacked_www=$PWD/builder/www
- src_www=kasmweb
- docker build -t kasmweb/www -f builder/dockerfile.www.build .
- docker run --rm -v $PWD/builder/www:/build kasmweb/www:latest
- mkdir -p output/www
- cd builder
- tar -zcvf ../output/www/kasm_www.tar.gz www
only:
variables:
- $BUILD_JOBS !~ /^none$/
artifacts:
paths:
- output/
build_ubuntu_bionic: build_ubuntu_bionic:
stage: build stage: build
allow_failure: true
before_script: before_script:
- *prepare_build - *prepare_build
- *prepare_www
after_script: after_script:
- *prepare_artfacts - *prepare_artfacts
script: script:
- bash builder/build-package ubuntu bionic - bash builder/build-package ubuntu bionic
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_ubuntu_bionic_arm:
stage: build
allow_failure: false
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package ubuntu bionic
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_ubuntu_bionic_libjpeg_turbo:
stage: build
allow_failure: false
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package ubuntu bionic +libjpeg-turbo_latest
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts: artifacts:
paths: paths:
- output/ - output/
build_ubuntu_focal: build_ubuntu_focal:
stage: build stage: build
allow_failure: true
before_script: before_script:
- *prepare_build - *prepare_build
- *prepare_www
after_script: after_script:
- *prepare_artfacts - *prepare_artfacts
script: script:
- bash builder/build-package ubuntu focal; - bash builder/build-package ubuntu focal;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_ubuntu_focal_arm:
stage: build
allow_failure: true
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package ubuntu focal;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_ubuntu_jammy:
stage: build
allow_failure: true
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package ubuntu jammy;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_ubuntu_jammy_arm:
stage: build
allow_failure: true
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package ubuntu jammy;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts: artifacts:
paths: paths:
- output/ - output/
build_debian_buster: build_debian_buster:
stage: build stage: build
allow_failure: true
before_script: before_script:
- *prepare_build - *prepare_build
- *prepare_www
after_script: after_script:
- *prepare_artfacts - *prepare_artfacts
script: script:
- bash builder/build-package debian buster; - bash builder/build-package debian buster;
only:
variables:
- $CI_COMMIT_MESSAGE =~ /\[full [cC][Ii]\]/ || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_debian_buster_arm:
stage: build
allow_failure: true
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package debian buster;
only:
variables:
- $CI_COMMIT_MESSAGE =~ /\[full [cC][Ii]\]/ || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts: artifacts:
paths: paths:
- output/ - output/
build_debian_bullseye: build_debian_bullseye:
stage: build stage: build
allow_failure: true
before_script: before_script:
- *prepare_build - *prepare_build
- *prepare_www
after_script: after_script:
- *prepare_artfacts - *prepare_artfacts
script: script:
- bash builder/build-package debian bullseye; - bash builder/build-package debian bullseye;
only:
variables:
- $CI_COMMIT_MESSAGE =~ /\[full [cC][Ii]\]/ || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_debian_bullseye_arm:
stage: build
allow_failure: true
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package debian bullseye;
only:
variables:
- $CI_COMMIT_MESSAGE =~ /\[full [cC][Ii]\]/ || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts: artifacts:
paths: paths:
- output/ - output/
build_kali_rolling: build_kali_rolling:
stage: build stage: build
allow_failure: true
before_script: before_script:
- *prepare_build - *prepare_build
- *prepare_www
after_script: after_script:
- *prepare_artfacts - *prepare_artfacts
script: script:
- bash builder/build-package kali kali-rolling; - bash builder/build-package kali kali-rolling;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_kali_rolling_arm:
stage: build
allow_failure: true
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package kali kali-rolling;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts: artifacts:
paths: paths:
- output/ - output/
build_centos7: build_centos7:
stage: build stage: build
allow_failure: true
before_script: before_script:
- *prepare_build - *prepare_build
- *prepare_www
after_script: after_script:
- *prepare_artfacts - *prepare_artfacts
script: script:
- bash builder/build-package centos core - bash builder/build-package centos core
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_oracle_8:
stage: build
allow_failure: true
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package oracle 8;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_oracle_8_arm:
stage: build
allow_failure: true
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package oracle 8;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_opensuse_15:
stage: build
allow_failure: true
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package opensuse 15;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts:
paths:
- output/
build_opensuse_15_arm:
stage: build
allow_failure: true
tags:
- arm
before_script:
- *prepare_build
- *prepare_www
after_script:
- *prepare_artfacts
script:
- bash builder/build-package opensuse 15;
only:
variables:
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
artifacts: artifacts:
paths: paths:
- output/ - output/
@@ -377,25 +100,12 @@ upload:
before_script: before_script:
- . .ci/upload.sh - . .ci/upload.sh
script: script:
- prepare_to_run_scripts_and_s3_uploads
- S3_CRASHPAD_BUILD_DIRECTORY="kasmvnc/crashpad/${CI_COMMIT_SHA}"
- for dbgsym_package in `find output/ -type f -name '*dbgsym*deb'`; do
deb_package=$(find_deb_package "$dbgsym_package");
xvnc_md5sum=$(fetch_xvnc_md5sum "$deb_package");
upload_filename="${S3_CRASHPAD_BUILD_DIRECTORY}/${xvnc_md5sum}/kasmvncserver-dbgsym.deb";
echo;
echo "File to upload $upload_filename";
upload_to_s3 "$dbgsym_package" "$upload_filename" "$S3_BUCKET";
rm "$dbgsym_package";
done
- export S3_BUILD_DIRECTORY="kasmvnc/${CI_COMMIT_SHA}" - export S3_BUILD_DIRECTORY="kasmvnc/${CI_COMMIT_SHA}"
- prepare_to_run_scripts_and_s3_uploads
- export RELEASE_VERSION=$(.ci/next_release_version "$CI_COMMIT_REF_NAME") - export RELEASE_VERSION=$(.ci/next_release_version "$CI_COMMIT_REF_NAME")
- for package in `find output/ -type f -name '*.deb' -or -name '*.rpm'`; do - for package in `find output/ -type f -name 'kasmvncserver_*.deb' -or -name '*.rpm'`; do
prepare_upload_filename "$package"; prepare_upload_filename "$package";
upload_filename="${S3_BUILD_DIRECTORY}/$upload_filename";
echo; echo;
echo "File to upload $upload_filename"; echo "File to upload $upload_filename";
upload_to_s3 "$package" "$upload_filename" "$S3_BUCKET"; upload_to_s3 "$package" "$upload_filename";
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)##');
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}";
done done

2
.gitmodules vendored
View File

@@ -1,4 +1,4 @@
[submodule "kasmweb"] [submodule "kasmweb"]
path = kasmweb path = kasmweb
url = https://github.com/kasmtech/noVNC.git url = https://github.com/kasmtech/noVNC.git
branch = release/0.9.3.2 branch = master

View File

@@ -16,7 +16,6 @@ include(CheckLibraryExists)
include(CheckTypeSize) include(CheckTypeSize)
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
include(CheckCXXSourceCompiles) include(CheckCXXSourceCompiles)
include(CheckCXXCompilerFlag)
include(CheckCSourceRuns) include(CheckCSourceRuns)
include(CMakeMacroLibtoolFile) include(CMakeMacroLibtoolFile)
@@ -209,9 +208,6 @@ if(ENABLE_PAM)
endif() endif()
set(HAVE_PAM ${ENABLE_PAM}) set(HAVE_PAM ${ENABLE_PAM})
# Check for SSE2
check_cxx_compiler_flag(-msse2 COMPILER_SUPPORTS_SSE2)
# Generate config.h and make sure the source finds it # Generate config.h and make sure the source finds it
configure_file(config.h.in config.h) configure_file(config.h.in config.h)
add_definitions(-DHAVE_CONFIG_H) add_definitions(-DHAVE_CONFIG_H)

View File

@@ -1,108 +0,0 @@
# Debugging
In the case where KasmVNC crashes and a backtrace is produced. Developers need a way to make the backtrace useful for debugging. This document covers where the backtrace is logged and how to use a debug symbol package and gdb to gain more information from the backtrace, such as filename, function name, and line number.
## Test Symbolization
If you want to induce a crash to test that you can symbolize a backtrace you can start KasmVNC and then issue the following command.
killall -SEGV Xvnc
This will cause KasmVNC to terminate with a backtrace similar to the following. You will find the backtrace in the log file at $HOME/.vnc/$HOSTNAME:$DISPLAY.log where HOME is your user's profile path, HOSTNAME is the hostname of the system, and DISPLAY is the assigned display number for the session.
(EE)
(EE) Backtrace:
(EE) 0: /usr/bin/Xvnc (xorg_backtrace+0x4d) [0x5e48dd]
(EE) 1: /usr/bin/Xvnc (0x400000+0x1e8259) [0x5e8259]
(EE) 2: /lib/x86_64-linux-gnu/libpthread.so.0 (0x7f5a57ef6000+0x12980) [0x7f5a57f08980]
(EE) 3: /lib/x86_64-linux-gnu/libc.so.6 (epoll_wait+0x57) [0x7f5a552eca47]
(EE) 4: /usr/bin/Xvnc (ospoll_wait+0x37) [0x5e8d07]
(EE) 5: /usr/bin/Xvnc (WaitForSomething+0x1c3) [0x5e2813]
(EE) 6: /usr/bin/Xvnc (Dispatch+0xa7) [0x597007]
(EE) 7: /usr/bin/Xvnc (dix_main+0x36e) [0x59b1fe]
(EE) 8: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xe7) [0x7f5a551ecbf7]
(EE) 9: /usr/bin/Xvnc (_start+0x2a) [0x46048a]
(EE)
(EE) Received signal 11 sent by process 17182, uid 0
(EE)
Fatal server error:
(EE) Caught signal 11 (Segmentation fault). Server aborting
(EE)
## Debug Symbol Package
In order to make use of this backtrace, you will need to symbolize the backtrace. Each build of KasmVNC produced by our pipelines comes with a corresponding debug symbol package that can be downloaded. You need two pieces of information to get the package, the git commit ID of KasmVNC and the MD5 sum of Xkasmvnc binary on your system.
The git commit ID can be found using Xvnc -version:
ubuntu@matt-dev-vm-1:~$ Xvnc -version
Xvnc KasmVNC 0.9.94002f39917dca0ad82ac0c29a75c723b538b32b - built Feb 17 2022 15:21:01
Copyright (C) 1999-2018 KasmVNC Team and many others (see README.me)
See http://kasmweb.com for information on KasmVNC.
Underlying X server release 12010000, The X.Org Foundation
The MD5 sum can be obtained using the md5sum command:
md5sum /usr/bin/Xkasmvnc
57ee7028239c5a737c0aeee4a34138c3 /usr/bin/Xkasmvnc
With these two pieces of information, you can get the debug symbol package at https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/crashpad/[COMMITID]/[MD5SUM]/kasmvncserver-dbgsym.deb, in the above example it would be.
[https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/crashpad/94002f39917dca0ad82ac0c29a75c723b538b32b/57ee7028239c5a737c0aeee4a34138c3/kasmvncserver-dbgsym.deb](https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/crashpad/94002f39917dca0ad82ac0c29a75c723b538b32b/57ee7028239c5a737c0aeee4a34138c3/kasmvncserver-dbgsym.deb "https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/crashpad/94002f39917dca0ad82ac0c29a75c723b538b32b/57ee7028239c5a737c0aeee4a34138c3/kasmvncserver-dbgsym.deb")
Use wget or curl to download the debug symbol package and then install it.
wget https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/crashpad/94002f39917dca0ad82ac0c29a75c723b538b32b/57ee7028239c5a737c0aeee4a34138c3/kasmvncserver-dbgsym.deb
sudo dpkg -i kasmvncserver-dbgsym.deb
## Symbolize a Backtrace
With the KasmVNC binary and debug symbol package installed on the system, you can use gdb or addr2line to get more information, such as the filename, function name, and line number that the backtrace line is referring to.
Here is a single line from a backtrace. The following example shows how to retrieve additional information that can help with debugging the crash.
(EE) 8: /usr/bin/Xvnc (0x400000+0x13e674) [**0x53e674**]
echo info line ***0x53eaaa** | gdb -q /usr/bin/Xkasmvnc
(gdb) Line 223 of "/src/common/network/webudp/Wu.cpp" starts at address 0x53e674 <WuClientSendPendingDTLS(WuClient*, Wu const*, Wu const*)+68>
The following script will search the provide file for a backtrace and symbolize the entire backtrace.
#!/bin/bash
FILENAME=$1
grep "(EE)" $FILENAME | while read -r line ; do
BACKTRACE=$(echo $line | grep -Po '\[[0-9a-f]x[a-f0-9]{1,}' | sed -r 's#\[##')
echo $line
if ! [ -z $BACKTRACE ] ; then
SYMBOLIZED=$(echo "info line *${BACKTRACE}" | gdb /usr/bin/Xkasmvnc | grep "(gdb)" | grep -vP "\(gdb\)\s*quit$")
echo " ${SYMBOLIZED}"
fi
done
Using this script on the above example backtrace produces the following output.
ubuntu@hostname-1:~$ bash symbolize.sh ~/.vnc/hostname-1\:10.log
(EE)
(EE) Backtrace:
(EE) 0: /usr/bin/Xvnc (xorg_backtrace+0x4d) [0x5e48dd]
(gdb) Line 130 of "backtrace.c" starts at address 0x5e48dd <xorg_backtrace+77> and ends at 0x5e4900 <xorg_backtrace+112>.
(EE) 1: /usr/bin/Xvnc (0x400000+0x1e8259) [0x5e8259]
(gdb) Line 138 of "osinit.c" starts at address 0x5e8259 <OsSigHandler+41> and ends at 0x5e8275 <OsSigHandler+69>.
(EE) 2: /lib/x86_64-linux-gnu/libpthread.so.0 (0x7f5a57ef6000+0x12980) [0x7f5a57f08980]
(gdb) No line number information available for address 0x7f5a57f08980
(EE) 3: /lib/x86_64-linux-gnu/libc.so.6 (epoll_wait+0x57) [0x7f5a552eca47]
(gdb) No line number information available for address 0x7f5a552eca47
(EE) 4: /usr/bin/Xvnc (ospoll_wait+0x37) [0x5e8d07]
(gdb) Line 643 of "ospoll.c" starts at address 0x5e8d07 <ospoll_wait+55> and ends at 0x5e8d09 <ospoll_wait+57>.
(EE) 5: /usr/bin/Xvnc (WaitForSomething+0x1c3) [0x5e2813]
(gdb) Line 210 of "WaitFor.c" starts at address 0x5e2813 <WaitForSomething+451> and ends at 0x5e2819 <WaitForSomething+457>.
(EE) 6: /usr/bin/Xvnc (Dispatch+0xa7) [0x597007]
(gdb) Line 421 of "dispatch.c" starts at address 0x596ffb <Dispatch+155> and ends at 0x59700b <Dispatch+171>.
(EE) 7: /usr/bin/Xvnc (dix_main+0x36e) [0x59b1fe]
(gdb) Line 278 of "main.c" starts at address 0x59b1fe <dix_main+878> and ends at 0x59b203 <dix_main+883>.
(EE) 8: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xe7) [0x7f5a551ecbf7]
(gdb) No line number information available for address 0x7f5a551ecbf7
(EE) 9: /usr/bin/Xvnc (_start+0x2a) [0x46048a]
(gdb) No line number information available for address 0x46048a <_start+42>
(EE)
(EE) Received signal 11 sent by process 17182, uid 0
(EE)
(EE) Caught signal 11 (Segmentation fault). Server aborting
(EE)

View File

@@ -1,11 +1,11 @@
# KasmVNC - Linux Web Remote Desktop # KasmVNC - Linux Web Remote Desktop
<a href="https://kasmweb.com"><img src="https://kasm-static-content.s3.amazonaws.com/logo_kasm.png" width="300"><a/> [![Kasm Technologies](https://kasm-static-content.s3.amazonaws.com/368_kasm_logo_.jpg "Kasm Logo")](https://kasmweb.com)
[Kasm Technologies](https://www.kasmweb.com) developed Kasm Workspaces, the Containerized Streaming Platform. Kasm has open-sourced the Workspace docker images, which include containerized [full desktops and apps](https://github.com/kasmtech/workspaces-images) and [base images](https://github.com/kasmtech/workspaces-core-images) intended for developers to create custimized streaming containers. These containers can be used standalone or within the [Kasm Workspaces Platform](https://www.kasmweb.com) which provides a full Enterprise feature set. KasmVNC is used as the streaming tech for our container images, however, you can use KasmVNC for individual servers. While the term VNC is in the name, KasmVNC is not intended to remain compliant with the RFB spec and has different goals than other VNC projects: [Kasm Technologies LLC](https://www.kasmweb.com) developed Kasm Server, a Containerized Desktop Infrastructure (CDI) solution. Kasm started with TigerVNC and eventually forked it to create KasmVNC. KasmVNC is used within the overal Kasm CDI infrastructure, however, you can use KasmVNC for individual servers. KasmVNC has different goals than TigerVNC:
- Web-based - KasmVNC is designed to provide a web accessible remote desktop. It comes with a web server and websocket server built in. There is no need to install other components. Simply run and navigate to your desktop's URL on the port you specify. While you can still tun on the legacy VNC port, it is disabled by default. - Web-based - KasmVNC is designed to provide a web accessible remote desktop. It comes with a web server and websocket server built in. There is no need to install other components. Simply run and navigate to your desktop's URL on the port you specify. While you can still tun on the legacy VNC port, it is disabled by default.
- Security - The RFB specification (VNC) limits the password field to 8 characters, so while the client may take a longer password, only the first 8 characters are sent. KasmVNC defaults to HTTPS with HTTP Basic Auth and disables the legacy VNC authentication method which is not sufficiently secure for internet accessible systems. - Security - KasmVNC defaults to HTTPS and allows for HTTP Basic Auth. VNC Password authentication is limited by specification to 8 characters and is not suffecient for use on an internet accessible remote desktop. Our goal is to create a by default secure, web based experience.
- Simplicity - KasmVNC aims at being simple to deploy and configure. - Simplicity - KasmVNC aims at being simple to deploy and configure.
# New Features! # New Features!
@@ -42,11 +42,10 @@ Future Goals:
#### Debian-based #### Debian-based
```sh ```sh
# Please choose the package for your distro here (under Assets): wget -qO- https://github.com/kasmtech/KasmVNC/releases/download/v0.9.1-beta/kasmvncserver_0.9.1~beta-1_amd64.deb
# https://github.com/kasmtech/KasmVNC/releases
wget <package_url>
sudo apt-get install ./kasmvncserver_*.deb sudo dpkg -i kasmvncserver_0.9.1~beta-1_amd64.deb
sudo apt-get -f install
# We provide an example script to run KasmVNC at # # We provide an example script to run KasmVNC at #
# /usr/share/doc/kasmvncserver/examples/kasmvncserver-easy-start. It runs a VNC # /usr/share/doc/kasmvncserver/examples/kasmvncserver-easy-start. It runs a VNC
@@ -92,13 +91,11 @@ The options for vncserver:
| interface | Which interface to bind the web server to. | | interface | Which interface to bind the web server to. |
### Development ### Development
Would you like to contribute to KasmVNC? Please reachout to us at info@kasmweb.com. We have investigated or are working on the following, if you have experience in these fields and would like to help please let us know. Would you like to contribute to KasmVNC? Please reachout to us at info@kasmweb.com
Real-time H264 encoding using NVIDIA and Intel encoding technology. We need help, especially in packaging KasmVNC for various operating systems. We would love to have standard debian or RMP packages and host our own repo, however, that all requires a lot of experience, proper testing, and pipeline development for automated builds.
Windows version of KasmVNC. We have been able to get it to compile for Windows and increased the performance, but still not releasable. Experienced Windows developers with a background in cross compiling would help. We also need help with Windows, which is not currently supported. While KasmVNC can technically be built for Windows 10, it is unusably slow, due to all the changes that occured in Windows since the original Windows support was added in the chain of VNC forked projects.
ARM version of KasmVNC, we have had requests for this and at one point we did have an ARM build of KasmVNC but it takes dev cycles to mainain and bring it back to life.
### Compiling From Source ### Compiling From Source
See the [builder/README.md](https://github.com/kasmtech/KasmVNC/blob/master/builder/README.md). We containerize our build systems to ensure highly repeatable builds. See the [builder/README.md](https://github.com/kasmtech/KasmVNC/blob/master/builder/README.md). We containerize our build systems to ensure highly repeatable builds.

View File

@@ -3,17 +3,8 @@ Docker CE
# Build a deb/rpm package # Build a deb/rpm package
``` ```
# builder/build-package <os> <os_codename> <build_tag> # builder/build-package <os> <os_codename>
# os_codename is what "lsb_release -c" outputs, e.g. buster, focal. # os_codename is what "lsb_release -c" outputs, e.g. buster, focal.
#
# build_tag allows building multiple versions of deb package (rpm not supported)
# targeting a single distro release (e.g. Ubuntu Bionic). If build_tag is given,
# the package name will include build_tag as part of Debian revision. For
# example:
# * with build_tag: kasmvncserver_0.9.1~beta-1+libjpeg-turbo-latest_amd64.deb
# * without build_tag: kasmvncserver_0.9.1~beta-1_amd64.deb
# You need to have .build and .deb.build for the build_tag.
#
# Packages will be placed under builder/build/ # Packages will be placed under builder/build/
builder/build-package ubuntu bionic builder/build-package ubuntu bionic
@@ -79,63 +70,3 @@ packages installed with XFCE.
``` ```
builder/test-deb-barebones ubuntu focal builder/test-deb-barebones ubuntu focal
``` ```
# Preparing a release
Deb and rpm packages need their versions bumped to the new release version. It
can be done with:
```
builder/bump-package-version 0.9.4-beta
```
This will update corresponding package files, use `git diff` to see changes.
If you've ran the command and curious about Debian version specifics, here's an
explanation:
Deb version will be `0.9.4~beta-1`. `~` (and not `-`) is required by packaging
guidelines, and `-1` is Debian package revision for `0.9.4` upstream release. If
a Debian-specific patch was later added on top of `0.9.4`, it'd be `-2` for the
next Debian version. Rpm has a corresponding revision in its .spec file.
# CI development
S3 upload code is extracted to various files in `.ci`. It's possible to iterate
locally by doing stuff like this:
```
bash -c '
. .ci/upload.sh;
prepare_upload_filename "bionic/kasmvncserver_0.9.1~beta-1+libjpeg-turbo-latest_amd64.deb";
echo $upload_filename;'
```
# ARM
KasmVNC is supported on ARM, however, the build process needs to be broken into two parts with one occuring on a x64 system and the other on an ARM system. All our testing and official builds are done on AWS Graviton instances.
### Build www code on x86 System
The www code is webpacked for performance and thus requires building. There are NPM packages, phantomjs, which do not have an ARM build. Therefore, this must be built on x86 and then copied over to the ARM system for final packaging.
```
cd ~/KasmVNC
mkdir builder/www
sudo docker build -t kasmweb/www -f builder/dockerfile.www.build .
sudo docker run --rm -v $PWD/builder/www:/build kasmweb/www:latest
cd builder
tar -zcvf /tmp/kasm_www.tar.gz www
```
Now transfer ```kasm_www.tar.gz``` to the ARM system.
### Build KasmVNC ARM
These instructions assume KasmVNC has been cloned at $HOME and ```kasm_www.tar.gz``` has been placed at $HOME as well, adjust for your environment.
```
cd ~
tar -zxf kasm_www.tar.gz -C KasmVNC/builder/
cd KasmVNC
sudo builder/build-package ubuntu bionic
```
The resulting deb package can be found under ~/KasmVNC/builder/build/bionic
Replace ```bionic``` with ```focal``` to build for Ubuntu 20.04LTS. At this time, only Ubuntu Bionic has been tested, however, other Debian based builds we support should also work.

View File

@@ -5,17 +5,12 @@ set -e
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
. builder/os_ver_cli.sh . builder/os_ver_cli.sh
L_UID=$(id -u) #Ubuntu already has UID env var, but this should work on all Linix systems docker build -t debbuilder_${os}:${os_codename} -f \
L_GID=$(id -g) builder/dockerfile.${os}_${os_codename}.deb.build .
builder_image=debbuilder_${os}:${os_codename}${build_tag_for_images}
docker build --build-arg KASMVNC_PACKAGE_DIR="builder/build/${os_codename}" \
--build-arg L_UID="$L_UID" \
-t "$builder_image" -f \
builder/dockerfile.${os}_${os_codename}${build_tag}.deb.build .
deb_output_dir=$(cd .. && echo $PWD) deb_output_dir=$(cd .. && echo $PWD)
docker run --rm -v "$deb_output_dir":/src -e BUILD_TAG="$build_tag" \ L_UID=$(id -u) #Ubuntu already has UID env var, but this should work on all Linix systems
--user "$L_UID:$L_GID" \ L_GID=$(id -g)
"$builder_image" /bin/bash -c \ docker run --rm -v "$deb_output_dir":/src --user $L_UID:$L_GID \
debbuilder_${os}:${os_codename} /bin/bash -c \
'/src/*/builder/build-deb-inside-docker' '/src/*/builder/build-deb-inside-docker'

View File

@@ -2,33 +2,13 @@
set -e set -e
prepare_docker_copy_of_debian_dir_and_cd_to_id() { cd "$(dirname "$0")/.."
cd "$(dirname "$0")/.."
local mounted_src_dir="$PWD"
local docker_src_dir="$HOME/src"
mkdir "$docker_src_dir"
cd "$docker_src_dir"
cp -a "$mounted_src_dir/debian/" .
ln -s "$mounted_src_dir/builder" .
}
prepare_docker_copy_of_debian_dir_and_cd_to_id
os=$(lsb_release -is | tr '[:upper:]' '[:lower:]') os=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
os_codename=$(lsb_release -cs) os_codename=$(lsb_release -cs)
os_dir="builder/build/${os_codename}" os_dir="builder/build/${os_codename}"
if [ "$BUILD_TAG" = "+libjpeg-turbo_latest" ]; then
echo 'libjpeg 62 libjpeg-turbo (>= 2.1.1)' > debian/shlibs.local
debian_revision="$(echo $BUILD_TAG | tr _ -)"
sed -i -e "1 s/)/$debian_revision)/" debian/changelog
fi
dpkg-buildpackage -us -uc -b dpkg-buildpackage -us -uc -b
mkdir -p "$os_dir" mkdir -p "$os_dir"
cp ../*dbgsym*deb "$os_dir"
cp ../*.deb "$os_dir" cp ../*.deb "$os_dir"
lintian ../*.deb || true lintian ../*.deb || true

View File

@@ -4,7 +4,6 @@ set -e
os="$1" os="$1"
codename="$2" codename="$2"
build_tag="$3"
detect_package_format() { detect_package_format() {
package_format=rpm package_format=rpm
@@ -13,17 +12,8 @@ detect_package_format() {
fi fi
} }
warn_build_tag_not_supported_for_rpm_and_exit() {
if [[ "$build_tag" && "$package_format" = "rpm" ]]; then
echo >&2 "<build_tag> isn't supported for rpm"
exit 1
fi
}
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
detect_package_format detect_package_format
warn_build_tag_not_supported_for_rpm_and_exit builder/build-tarball "$os" "$codename"
builder/build-${package_format} "$os" "$codename"
builder/build-tarball "$os" "$codename" "$build_tag"
builder/build-${package_format} "$os" "$codename" "$build_tag"

View File

@@ -2,18 +2,8 @@
set -e set -e
warn_build_tag_not_supported_for_rpm_and_exit() {
local build_tag="$1"
if [[ -n "$build_tag" ]]; then
echo >&2 "<build_tag> isn't supported for rpm"
exit 1
fi
}
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
. builder/os_ver_cli.sh . builder/os_ver_cli.sh
warn_build_tag_not_supported_for_rpm_and_exit "$build_tag"
docker build -t kasmvnc_rpmbuilder_${os}:${os_codename} -f \ docker build -t kasmvnc_rpmbuilder_${os}:${os_codename} -f \
builder/dockerfile.${os}_${os_codename}.rpm.build . builder/dockerfile.${os}_${os_codename}.rpm.build .

View File

@@ -8,7 +8,7 @@ prepare_build_env() {
} }
copy_spec_and_tar_with_binaries() { copy_spec_and_tar_with_binaries() {
cp /tmp/kasmvncserver.spec ~/rpmbuild/SPECS/ cp /src/centos/kasmvncserver.spec ~/rpmbuild/SPECS/
cp /src/builder/build/kasmvnc.${os}_${os_codename}.tar.gz \ cp /src/builder/build/kasmvnc.${os}_${os_codename}.tar.gz \
~/rpmbuild/SOURCES/ ~/rpmbuild/SOURCES/
} }
@@ -20,13 +20,8 @@ copy_rpm_to_build_dir() {
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
if [ -z ${KASMVNC_BUILD_OS_CODENAME+x} ]; then os=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
os=$(lsb_release -is | tr '[:upper:]' '[:lower:]') os_codename=$(lsb_release -cs | tr '[:upper:]' '[:lower:]')
os_codename=$(lsb_release -cs | tr '[:upper:]' '[:lower:]')
else
os=${KASMVNC_BUILD_OS}
os_codename=${KASMVNC_BUILD_OS_CODENAME}
fi
os_dir="build/${os}_${os_codename}" os_dir="build/${os}_${os_codename}"
prepare_build_env prepare_build_env

View File

@@ -12,13 +12,6 @@ build_www_dir() {
fi fi
} }
move_libjpeg_turbo_to_os_specific_dir() {
chown $L_UID:$L_GID $shared_with_docker_dir/${os_codename}/*
mkdir -p $PWD/builder/build/${os_codename}/
mv $shared_with_docker_dir/${os_codename}/libjpeg-turbo*.deb \
$PWD/builder/build/${os_codename}/
}
shared_with_docker_dir=${GITLAB_SHARED_DIND_DIR:-/tmp} shared_with_docker_dir=${GITLAB_SHARED_DIND_DIR:-/tmp}
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
@@ -26,22 +19,13 @@ cd "$(dirname "$0")/.."
build_www_dir build_www_dir
builder_image=kasmvncbuilder:$os_codename${build_tag_for_images} docker build -t kasmvncbuilder:$os_codename \
docker build -t "$builder_image" \ -f builder/dockerfile.${os}_${os_codename}.build .
-f builder/dockerfile.${os}_${os_codename}${build_tag}.build .
mkdir -p builder/build mkdir -p builder/build
docker run -v $shared_with_docker_dir:/build -e BUILD_TAG="$build_tag" \ docker run -v $shared_with_docker_dir:/build --rm kasmvncbuilder:$os_codename
-e KASMVNC_COMMIT_ID="$KASMVNC_COMMIT_ID" \
--rm "$builder_image"
L_GID=$(id -g) L_GID=$(id -g)
L_UID=$(id -u) L_UID=$(id -u)
tarball_name="kasmvnc.${os}_${os_codename}.tar.gz" tarball_name="kasmvnc.${os}_${os_codename}.tar.gz"
tarball_name_with_build_tag="kasmvnc.${os}_${os_codename}${build_tag}.tar.gz"
chown $L_UID:$L_GID $shared_with_docker_dir/$tarball_name chown $L_UID:$L_GID $shared_with_docker_dir/$tarball_name
mv $shared_with_docker_dir/$tarball_name \ mv $shared_with_docker_dir/$tarball_name $PWD/builder/build/
$PWD/builder/build/"$tarball_name_with_build_tag"
if [ "$build_tag" = "+libjpeg-turbo_latest" ]; then
move_libjpeg_turbo_to_os_specific_dir
fi

View File

@@ -1,6 +1,4 @@
#!/bin/bash #!/bin/sh -e
set -e
detect_quilt() { detect_quilt() {
if which quilt 1>/dev/null; then if which quilt 1>/dev/null; then
@@ -9,36 +7,11 @@ detect_quilt() {
fi fi
} }
ensure_crashpad_can_fetch_line_number_by_address() {
if [ ! -f /etc/centos-release ]; then
export LDFLAGS="$LDFLAGS -no-pie"
fi
}
fail_on_gcc_12() {
if [[ -n "$CC" && -n "$CXX" ]]; then
return;
fi
if gcc --version | head -1 | grep -q 12; then
cat >&2 <<EOF
Error: gcc 12 detected. It has a bug causing the build to fail because of a
-Warray-bounds bug. Please use gcc 11 in the build Dockerfile:
ENV CC=gcc-11
ENV CXX=g++-11
RUN <install gcc 11>
EOF
exit 1
fi
}
# For build-dep to work, the apt sources need to have the source server # For build-dep to work, the apt sources need to have the source server
#sudo apt-get build-dep xorg-server #sudo apt-get build-dep xorg-server
#sudo apt-get install cmake git libjpeg-dev libgnutls-dev #sudo apt-get install cmake git libjpeg-dev libgnutls-dev
fail_on_gcc_12
# Ubuntu applies a million patches, but here we use upstream to simplify matters # Ubuntu applies a million patches, but here we use upstream to simplify matters
cd /tmp cd /tmp
# default to the version of x in Ubuntu 18.04, otherwise caller will need to specify # default to the version of x in Ubuntu 18.04, otherwise caller will need to specify
@@ -57,36 +30,28 @@ sed -i -e '/find_package(FLTK/s@^@#@' \
-e '/add_subdirectory(tests/s@^@#@' \ -e '/add_subdirectory(tests/s@^@#@' \
CMakeLists.txt CMakeLists.txt
cmake -D CMAKE_BUILD_TYPE=RelWithDebInfo . -DBUILD_VIEWER:BOOL=OFF cmake -D CMAKE_BUILD_TYPE=RelWithDebInfo .
make -j5 make -j5
tar -C unix/xserver -xf /tmp/xorg-server-${XORG_VER}.tar.bz2 --strip-components=1 tar -C unix/xserver -xvf /tmp/xorg-server-${XORG_VER}.tar.bz2 --strip-components=1
cd unix/xserver cd unix/xserver
patch -Np1 -i ../xserver${XORG_PATCH}.patch patch -Np1 -i ../xserver${XORG_PATCH}.patch
case "$XORG_VER" in if [[ $XORG_VER =~ ^1\.20\..*$ ]]; then
1.20.*) patch -Np1 -i ../xserver120.7.patch
if [ -f ../xserver120.7.patch ]; then fi
patch -Np1 -i ../xserver120.7.patch
fi ;;
esac
autoreconf -i autoreconf -i
# Configuring Xorg is long and has many distro-specific paths. # Configuring Xorg is long and has many distro-specific paths.
# The distro paths start after prefix and end with the font path, # The distro paths start after prefix and end with the font path,
# everything after that is based on BUILDING.txt to remove unneeded # everything after that is based on BUILDING.txt to remove unneeded
# components. # components.
ensure_crashpad_can_fetch_line_number_by_address
# remove gl check for opensuse
if [ "${KASMVNC_BUILD_OS}" == "opensuse" ]; then
sed -i 's/LIBGL="gl >= 7.1.0"/LIBGL="gl >= 1.1"/g' configure
fi
./configure --prefix=/opt/kasmweb \ ./configure --prefix=/opt/kasmweb \
--with-xkb-path=/usr/share/X11/xkb \ --with-xkb-path=/usr/share/X11/xkb \
--with-xkb-output=/var/lib/xkb \ --with-xkb-output=/var/lib/xkb \
--with-xkb-bin-directory=/usr/bin \ --with-xkb-bin-directory=/usr/bin \
--with-default-font-path="/usr/share/fonts/X11/misc,/usr/share/fonts/X11/cyrillic,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,built-ins" \ --with-default-font-path="/usr/share/fonts/X11/misc,/usr/share/fonts/X11/cyrillic,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,built-ins" \
--without-dtrace --disable-dri \ --with-pic --without-dtrace --disable-dri \
--disable-static \ --disable-static \
--disable-xinerama --disable-xvfb --disable-xnest --disable-xorg \ --disable-xinerama --disable-xvfb --disable-xnest --disable-xorg \
--disable-dmx --disable-xwin --disable-xephyr --disable-kdrive \ --disable-dmx --disable-xwin --disable-xephyr --disable-kdrive \
@@ -107,8 +72,6 @@ mkdir lib
cd lib cd lib
if [ -d /usr/lib/x86_64-linux-gnu/dri ]; then if [ -d /usr/lib/x86_64-linux-gnu/dri ]; then
ln -s /usr/lib/x86_64-linux-gnu/dri dri ln -s /usr/lib/x86_64-linux-gnu/dri dri
elif [ -d /usr/lib/aarch64-linux-gnu/dri ]; then
ln -s /usr/lib/aarch64-linux-gnu/dri dri
else else
ln -s /usr/lib64/dri dri ln -s /usr/lib64/dri dri
fi fi
@@ -117,13 +80,7 @@ cd /src
detect_quilt detect_quilt
if [ -n "$QUILT_PRESENT" ]; then if [ -n "$QUILT_PRESENT" ]; then
quilt push -a quilt push -a
echo 'Patches applied!'
fi fi
make servertarball make servertarball
cp kasmvnc*.tar.gz /build/kasmvnc.${KASMVNC_BUILD_OS}_${KASMVNC_BUILD_OS_CODENAME}.tar.gz cp kasmvnc*.tar.gz /build/kasmvnc.${KASMVNC_BUILD_OS}_${KASMVNC_BUILD_OS_CODENAME}.tar.gz
if [ "$BUILD_TAG" = "+libjpeg-turbo_latest" ]; then
mkdir -p /build/${KASMVNC_BUILD_OS_CODENAME}/
cp /libjpeg-turbo/libjpeg*.deb /build/${KASMVNC_BUILD_OS_CODENAME}/
fi

View File

@@ -15,3 +15,4 @@ cd /build
rm *.md rm *.md
rm AUTHORS rm AUTHORS
rm vnc.html rm vnc.html
rm vnc_lite.html

View File

@@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -eo pipefail
update_version_to_meet_packaging_standards() {
new_version=$(echo "$new_version" |
sed -e 's/\([0-9]\)-\([a-zA-Z]\)/\1~\2/')
}
bump_rpm() {
builder/bump-package-version-rpm "$new_version"
}
bump_deb() {
builder/bump-package-version-deb "$new_version"
}
new_version="$1"
if [[ -z "$new_version" ]]; then
echo >&2 "Usage: $(basename "$0") <new_version>"
exit 1
fi
cd "$(dirname "$0")/.."
update_version_to_meet_packaging_standards
bump_rpm
bump_deb

View File

@@ -1,23 +0,0 @@
#!/bin/bash
set -eo pipefail
new_version="$1"
add_debian_revision_to_new_version() {
echo "$new_version-1"
}
bump_deb() {
local image="debbump_package_version:dev"
local L_UID=$(id -u)
local L_GID=$(id -g)
local debian_version=$(add_debian_revision_to_new_version)
docker build -t "$image" -f builder/dockerfile.bump-package-version .
docker run --rm -v "$PWD":/src --user "$L_UID:$L_GID" \
"$image" /bin/bash -c \
"cd /src && builder/bump-package-version-inside-docker-deb $debian_version"
}
bump_deb

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
new_version="$1"
update_version() {
dch --newversion $new_version 'New upstream release.'
}
mark_as_released() {
dch --release ""
}
update_version
mark_as_released

View File

@@ -1,32 +0,0 @@
#!/bin/bash
set -eo pipefail
new_version="$1"
specs="centos/kasmvncserver.spec
oracle/kasmvncserver.spec
opensuse/kasmvncserver.spec"
bump_version() {
sed -i "s/^Version:.\+/Version: $new_version/" "$1"
}
detect_release_version() {
release_version=$(sed -ne 's/^Release:\s\+//p' "$1" | sed -e 's/%.\+$//')
}
bump_changelog() {
detect_release_version "$1"
local date=$(date +'%a %b %d %Y')
local changelog_version="$new_version-$release_version"
local new_changelog_entry="* $date KasmTech <info@kasmweb.com> - $changelog_version\n- Upstream release"
sed -i -e "s/%changelog/%changelog\n$new_changelog_entry/" "$1"
}
IFS=$'\n'
for spec_file in $specs; do
bump_version $spec_file
bump_changelog $spec_file
done

View File

@@ -1,6 +0,0 @@
FROM debian:buster
ENV DEBEMAIL="Kasm Technologies LLC <info@kasmweb.com>"
RUN apt-get update && \
apt-get -y install vim devscripts

View File

@@ -3,7 +3,6 @@ FROM centos:centos7
ENV KASMVNC_BUILD_OS centos ENV KASMVNC_BUILD_OS centos
ENV KASMVNC_BUILD_OS_CODENAME core ENV KASMVNC_BUILD_OS_CODENAME core
RUN yum install -y ca-certificates
RUN yum install -y build-dep xorg-server libxfont-dev sudo RUN yum install -y build-dep xorg-server libxfont-dev sudo
RUN yum install -y gcc cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver RUN yum install -y gcc cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver
RUN yum install -y libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev openssl-devel RUN yum install -y libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev openssl-devel
@@ -11,21 +10,20 @@ RUN yum install -y make
RUN yum group install -y "Development Tools" RUN yum group install -y "Development Tools"
RUN yum install -y xorg-x11-server-devel zlib-devel libjpeg-turbo-devel RUN yum install -y xorg-x11-server-devel zlib-devel libjpeg-turbo-devel
RUN yum install -y libxkbfile-devel libXfont2-devel xorg-x11-font-utils \ RUN yum install -y libxkbfile-devel libXfont2-devel xorg-x11-font-utils \
xorg-x11-xtrans-devel xorg-x11-xkb-utils-devel libXrandr-devel pam-devel \ xorg-x11-xtrans-devel xorg-x11-xkb-utils-devel
gnutls-devel libX11-devel libXtst-devel libXcursor-devel
RUN yum install -y mesa-dri-drivers RUN yum install -y mesa-dri-drivers
RUN yum install -y ca-certificates
# Additions for webp # Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-* RUN cd /tmp && tar -xzvf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \ RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make && make install make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd RUN useradd -m docker && echo "docker:docker" | chpasswd
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker
ENTRYPOINT ["/src/builder/build.sh"] ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -13,18 +13,19 @@ RUN apt-get update && \
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata 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 build-dep xorg-server libxfont-dev
RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev RUN apt-get update && apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev
# Additions for webp # Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-* RUN cd /tmp && tar -xzvf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \ RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make && make install make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker
ENTRYPOINT ["/src/builder/build.sh"] ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -9,11 +9,4 @@ RUN apt-get update && \
COPY ./debian/control /tmp COPY ./debian/control /tmp
RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control
ARG L_UID USER 1000
RUN if [ "$L_UID" -eq 0 ]; then \
useradd -m docker; \
else \
useradd -m docker -u $L_UID;\
fi
USER docker

View File

@@ -42,8 +42,8 @@ COPY startup/ $STARTUPDIR
### START CUSTOM STUFF #### ### START CUSTOM STUFF ####
ARG KASMVNC_PACKAGE_DIR ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/ COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp
RUN rm -f /tmp/kasmvncserver_*+*.deb; dpkg -i /tmp/*.deb; apt-get -yf install RUN dpkg -i /tmp/*.deb; apt-get -yf install
### END CUSTOM STUFF ### ### END CUSTOM STUFF ###

View File

@@ -1,8 +1,8 @@
FROM debian:buster-slim FROM debian:buster-slim
ARG KASMVNC_PACKAGE_DIR ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/ COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp
RUN rm -f /tmp/kasmvncserver_*+*.deb; apt-get update && dpkg -i /tmp/*.deb; apt-get -yf install RUN apt-get update && dpkg -i /tmp/*.deb; apt-get -yf install
RUN apt-get update && apt-get -y install xterm RUN apt-get update && apt-get -y install xterm
COPY startup/deb/kasmvncserver-easy-start /usr/local/bin COPY startup/deb/kasmvncserver-easy-start /usr/local/bin

View File

@@ -13,18 +13,19 @@ RUN apt-get update && \
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata 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 build-dep xorg-server libxfont-dev
RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev RUN apt-get update && apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev
# Additions for webp # Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-* RUN cd /tmp && tar -xzvf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \ RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make && make install make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker
ENTRYPOINT ["/src/builder/build.sh"] ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -9,11 +9,4 @@ RUN apt-get update && \
COPY ./debian/control /tmp COPY ./debian/control /tmp
RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control
ARG L_UID USER 1000
RUN if [ "$L_UID" -eq 0 ]; then \
useradd -m docker; \
else \
useradd -m docker -u $L_UID;\
fi
USER docker

View File

@@ -34,6 +34,11 @@ RUN apt-get purge -y pm-utils xscreensaver*
RUN apt-get update && apt-get install -y vim less RUN apt-get update && apt-get install -y vim less
RUN apt-get update && apt-get -y install lsb-release RUN apt-get update && apt-get -y install lsb-release
RUN apt-get update && apt-get -y install xdg-desktop-portal firefox-esr
COPY ./xdg-desktop-portal-gtk_1.2.0-1_amd64.deb /tmp
RUN apt-get install -y /tmp/xdg-*.deb
# RUN apt-get install -y xdg-desktop-portal-gtk
RUN echo 'source $STARTUPDIR/generate_container_user' >> $HOME/.bashrc RUN echo 'source $STARTUPDIR/generate_container_user' >> $HOME/.bashrc
RUN mkdir -p $STARTUPDIR RUN mkdir -p $STARTUPDIR
@@ -42,13 +47,17 @@ COPY startup/ $STARTUPDIR
### START CUSTOM STUFF #### ### START CUSTOM STUFF ####
ARG KASMVNC_PACKAGE_DIR ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/ COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp
RUN rm -f /tmp/kasmvncserver_*+*.deb; dpkg -i /tmp/*.deb; apt-get -yf install RUN dpkg -i /tmp/*.deb; apt-get -yf install
### END CUSTOM STUFF ### ### END CUSTOM STUFF ###
RUN sed -i -e 's/about:home/postimages.org/' /usr/lib/firefox-esr/browser/defaults/preferences/firefox.js
RUN sed -i -e '/browser.startup.firstrunSkipsHomepage/d' /usr/lib/firefox-esr/browser/defaults/preferences/firefox.js
RUN echo 'pref("browser.startup.firstrunSkipsHomepage", false);' >> /usr/lib/firefox-esr/browser/defaults/preferences/firefox.js
RUN chown -R 1000:0 $HOME RUN chown -R 1000:0 $HOME
USER 1000:ssl-cert USER 1000:ssl-cert
WORKDIR $HOME WORKDIR $HOME
ENV GTK_USE_PORTAL=1
ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ] ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ]

View File

@@ -18,21 +18,21 @@ RUN dnf install -y make
RUN dnf group install -y "Development Tools" RUN dnf group install -y "Development Tools"
RUN dnf install -y xorg-x11-server-devel zlib-devel libjpeg-turbo-devel RUN dnf install -y xorg-x11-server-devel zlib-devel libjpeg-turbo-devel
RUN dnf install -y libxkbfile-devel libXfont2-devel xorg-x11-font-utils \ RUN dnf install -y libxkbfile-devel libXfont2-devel xorg-x11-font-utils \
xorg-x11-xtrans-devel xorg-x11-xkb-utils-devel libXrandr-devel libXtst-devel \ xorg-x11-xtrans-devel xorg-x11-xkb-utils-devel
libXcursor-devel
RUN dnf install -y mesa-dri-drivers RUN dnf install -y mesa-dri-drivers
RUN dnf install -y bzip2 redhat-lsb-core RUN dnf install -y bzip2 redhat-lsb-core
# Additions for webp # Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-* RUN cd /tmp && tar -xzvf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \ RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make && make install make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd RUN useradd -m docker && echo "docker:docker" | chpasswd
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker
ENTRYPOINT ["/src/builder/build.sh"] ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -4,8 +4,6 @@ ENV KASMVNC_BUILD_OS kali
ENV KASMVNC_BUILD_OS_CODENAME kali-rolling ENV KASMVNC_BUILD_OS_CODENAME kali-rolling
ENV XORG_VER 1.20.10 ENV XORG_VER 1.20.10
ENV DEBIAN_FRONTEND noninteractive ENV DEBIAN_FRONTEND noninteractive
ENV CC=gcc-11
ENV CXX=g++-11
RUN grep '^deb' /etc/apt/sources.list | sed 's#^deb#deb-src#' >> /etc/apt/sources.list RUN grep '^deb' /etc/apt/sources.list | sed 's#^deb#deb-src#' >> /etc/apt/sources.list
@@ -14,20 +12,20 @@ RUN apt-get update && \
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata 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 build-dep xorg-server libxfont-dev
RUN apt-get update && apt-get -y install gcc-11 g++-11
RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev RUN apt-get update && apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev
# Additions for webp # Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-* RUN cd /tmp && tar -xzvf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \ RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make -j$(nproc) && make install make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker
ENTRYPOINT ["/src/builder/build.sh"] ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -9,11 +9,4 @@ RUN apt-get update && \
COPY ./debian/control /tmp COPY ./debian/control /tmp
RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control
ARG L_UID USER 1000
RUN if [ "$L_UID" -eq 0 ]; then \
useradd -m docker; \
else \
useradd -m docker -u $L_UID;\
fi
USER docker

View File

@@ -42,8 +42,8 @@ COPY startup/ $STARTUPDIR
### START CUSTOM STUFF #### ### START CUSTOM STUFF ####
ARG KASMVNC_PACKAGE_DIR ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/ COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp
RUN rm -f /tmp/kasmvncserver_*+*.deb; dpkg -i /tmp/*.deb; apt-get -yf install RUN dpkg -i /tmp/*.deb; apt-get -yf install
### END CUSTOM STUFF ### ### END CUSTOM STUFF ###

View File

@@ -1,39 +0,0 @@
FROM opensuse/leap:15.3
# base tools
RUN zypper -n install -y \
less \
vim \
xterm
# deps and rpm install
RUN zypper -n install -y \
libglvnd \
libgnutls30 \
libgomp1 \
libjpeg8 \
libnettle6 \
libpixman-1-0 \
libXdmcp6 \
libXfont2-2 \
libxkbcommon-x11-0 \
openssl \
perl \
x11-tools \
xauth \
xkbcomp \
xkeyboard-config && \
mkdir -p /etc/pki/tls/private
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/*.rpm /tmp
RUN zypper install -y --allow-unsigned-rpm /tmp/*.rpm
RUN useradd -m foo
USER foo:kasmvnc-cert
RUN mkdir ~/.vnc && echo '/usr/bin/xterm &' >> ~/.vnc/xstartup && \
chmod +x ~/.vnc/xstartup
ENTRYPOINT bash -c "echo -e \"$VNC_PW\n$VNC_PW\n\" | kasmvncpasswd -w -u \"$VNC_USER\" && vncserver :1 -interface 0.0.0.0 && vncserver -kill :1 && vncserver :1 -depth 24 -geometry 1280x1050 -websocketPort 6901 -cert /etc/pki/tls/private/kasmvnc.pem -sslOnly -FrameRate=24 -interface 0.0.0.0 -httpd /usr/share/kasmvnc/www && tail -f $HOME/.vnc/*.log "

View File

@@ -1,59 +0,0 @@
FROM opensuse/leap:15.3
ENV KASMVNC_BUILD_OS opensuse
ENV KASMVNC_BUILD_OS_CODENAME 15
ENV XORG_VER 1.20.3
# Install depends
RUN zypper install -ny \
bdftopcf \
bigreqsproto-devel \
cmake \
ffmpeg-4-libavcodec-devel \
fonttosfnt \
font-util \
gcc \
gcc-c++ \
giflib-devel \
git \
gzip \
lbzip2 \
libbz2-devel \
libGLw-devel \
libgnutls-devel \
libjpeg8-devel \
libopenssl-devel \
libpng16-devel \
libtiff-devel \
libXfont2-devel \
libxkbcommon-x11-devel \
make \
Mesa-dri \
Mesa-libglapi-devel \
mkfontdir \
mkfontscale \
patch \
tigervnc \
wget \
xcmiscproto-devel \
xorg-x11-devel \
xorg-x11-server-sdk \
xorg-x11-util-devel \
zlib-devel
# Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \
make && make install
RUN useradd -u 1000 docker && \
groupadd -g 1000 docker && \
usermod -a -G docker docker
COPY --chown=docker:docker . /src/
USER docker
ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -1,24 +0,0 @@
FROM opensuse/leap:15.3
ENV KASMVNC_BUILD_OS opensuse
ENV KASMVNC_BUILD_OS_CODENAME 15
RUN zypper -n install -y \
gpg* \
less \
lsb-release \
rng-tools \
rpm-build \
rpmdevtools \
rpmlint \
tree \
vim
COPY opensuse/*.spec /tmp
RUN zypper -n install $(grep BuildRequires /tmp/*.spec | cut -d' ' -f2 | xargs)
RUN useradd -u 1000 -m -d /home/docker docker && \
groupadd -g 1000 docker && \
usermod -a -G docker docker
USER docker

View File

@@ -1,20 +0,0 @@
FROM oraclelinux:8
RUN dnf install -y \
less \
redhat-lsb-core \
vim \
xterm
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/*.rpm /tmp
RUN dnf localinstall -y /tmp/*.rpm
RUN useradd -m foo
USER foo:kasmvnc-cert
RUN mkdir ~/.vnc && echo '/usr/bin/xterm &' >> ~/.vnc/xstartup && \
chmod +x ~/.vnc/xstartup
ENTRYPOINT bash -c "echo -e \"$VNC_PW\n$VNC_PW\n\" | kasmvncpasswd -w -u \"$VNC_USER\" && vncserver :1 -interface 0.0.0.0 && vncserver -kill :1 && vncserver :1 -depth 24 -geometry 1280x1050 -websocketPort 8443 -cert /etc/pki/tls/private/kasmvnc.pem -sslOnly -FrameRate=24 -interface 0.0.0.0 -httpd /usr/share/kasmvnc/www && tail -f $HOME/.vnc/*.log "

View File

@@ -1,61 +0,0 @@
FROM oraclelinux:8
ENV KASMVNC_BUILD_OS oracle
ENV KASMVNC_BUILD_OS_CODENAME 8
ENV XORG_VER 1.20.10
# Install from stock repos
RUN dnf install -y \
bzip2-devel \
ca-certificates \
cmake \
dnf-plugins-core \
gcc \
gcc-c++ \
git \
gnutls-devel \
libjpeg-turbo-devel \
libpng-devel \
libtiff-devel \
make \
mesa-dri-drivers \
openssl-devel \
openssl-devel \
patch \
tigervnc-server \
wget \
xorg-x11-font-utils \
zlib-devel
# Enable additional repos (epel, powertools, and fusion)
RUN dnf config-manager --set-enabled ol8_codeready_builder
RUN dnf install -y oracle-epel-release-el8
RUN dnf install -y --nogpgcheck https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm
# Install from new repos
RUN dnf install -y \
ffmpeg-devel \
giflib-devel \
lbzip2 \
libXfont2-devel \
libxkbfile-devel \
xorg-x11-server-devel \
xorg-x11-xkb-utils-devel \
xorg-x11-xtrans-devel \
libXrandr-devel \
libXtst-devel \
libXcursor-devel
# Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \
make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd
COPY --chown=docker:docker . /src/
USER docker
ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -1,21 +0,0 @@
FROM oraclelinux:8
ENV KASMVNC_BUILD_OS oracle
ENV KASMVNC_BUILD_OS_CODENAME 8
RUN dnf install -y \
gpg* \
less \
redhat-lsb-core \
rng-tools \
rpm* \
rpmlint \
tree \
vim
COPY oracle/*.spec /tmp
RUN dnf builddep -y /tmp/*.spec
RUN useradd -m docker && echo "docker:docker" | chpasswd
USER docker

View File

@@ -14,7 +14,8 @@ RUN cd /tmp/libwebp-1.0.2 && ./configure && make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker

View File

@@ -1,39 +0,0 @@
FROM ubuntu:18.04
ENV KASMVNC_BUILD_OS ubuntu
ENV KASMVNC_BUILD_OS_CODENAME bionic
ENV XORG_VER 1.20.10
RUN sed -i 's$# deb-src$deb-src$' /etc/apt/sources.list
RUN apt-get update && \
apt-get -y install sudo
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
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev
RUN apt-get update && apt-get install -y cmake nasm gcc
RUN git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git
RUN export MAKEFLAGS=-j`nproc`; cd libjpeg-turbo && cmake -G"Unix Makefiles" && make deb
RUN export MAKEFLAGS=-j`nproc`; cd libjpeg-turbo && cmake -DCMAKE_INSTALL_PREFIX=/usr/local -G"Unix Makefiles" && make && make install
# Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \
make && make install
# Fix for older required libs
#RUN cd /tmp && wget http://launchpadlibrarian.net/347526424/libxfont1-dev_1.5.2-4ubuntu2_amd64.deb && \
# wget http://launchpadlibrarian.net/347526425/libxfont1_1.5.2-4ubuntu2_amd64.deb && \
# dpkg -i libxfont1_1.5.2-4ubuntu2_amd64.deb && \
# dpkg -i libxfont1-dev_1.5.2-4ubuntu2_amd64.deb
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

@@ -1,23 +0,0 @@
FROM ubuntu:bionic
RUN apt-get update && \
apt-get -y install vim build-essential devscripts equivs
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/libjpeg-turbo*deb /tmp
RUN apt-get install /tmp/libjpeg-turbo*deb
# Install build-deps for the package.
COPY ./debian/control /tmp
RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control
ENV LD_LIBRARY_PATH="/opt/libjpeg-turbo/lib64/:$LD_LIBRARY_PATH"
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

@@ -1,58 +0,0 @@
FROM ubuntu:bionic
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=/opt/libjpeg-turbo/lib64/:/usr/local/lib/ \
OMP_WAIT_POLICY=PASSIVE \
SHELL=/bin/bash \
SINGLE_APPLICATION=0 \
KASMVNC_BUILD_OS=ubuntu \
KASMVNC_BUILD_OS_CODENAME=bionic
EXPOSE $VNC_PORT
WORKDIR $HOME
### REQUIRED STUFF ###
RUN apt-get update && apt-get install -y supervisor xfce4 xfce4-terminal 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 startup/ $STARTUPDIR
### START CUSTOM STUFF ####
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/libjpeg-turbo_*.deb /tmp
RUN apt-get install /tmp/libjpeg-turbo*deb
ARG BUILD_DEBIAN_REVISION
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*$BUILD_DEBIAN_REVISION*.deb /tmp
RUN dpkg -i /tmp/*.deb; apt-get -yf install
### END CUSTOM STUFF ###
RUN chown -R 1000:0 $HOME
USER 1000:ssl-cert
WORKDIR $HOME
ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ]

View File

@@ -11,11 +11,11 @@ RUN apt-get update && \
RUN apt-get update && apt-get -y build-dep xorg-server libxfont-dev RUN apt-get update && apt-get -y build-dep xorg-server libxfont-dev
RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev RUN apt-get update && apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev
# Additions for webp # Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-* RUN cd /tmp && tar -xzvf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \ RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make && make install make && make install
@@ -28,7 +28,8 @@ RUN cd /tmp/libwebp-1.0.2 && \
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker
ENTRYPOINT ["/src/builder/build.sh"] ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -7,11 +7,4 @@ RUN apt-get update && \
COPY ./debian/control /tmp COPY ./debian/control /tmp
RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control
ARG L_UID USER 1000
RUN if [ "$L_UID" -eq 0 ]; then \
useradd -m docker; \
else \
useradd -m docker -u $L_UID;\
fi
USER docker

View File

@@ -33,6 +33,7 @@ RUN apt-get update && apt-get install -y supervisor xfce4 xfce4-terminal xterm l
RUN apt-get purge -y pm-utils xscreensaver* RUN apt-get purge -y pm-utils xscreensaver*
RUN apt-get update && apt-get install -y vim less RUN apt-get update && apt-get install -y vim less
RUN apt-get update && apt-get -y install lsb-release RUN apt-get update && apt-get -y install lsb-release
RUN apt-get update && apt-get -y install xdg-desktop-portal xdg-desktop-portal-gtk firefox
RUN echo 'source $STARTUPDIR/generate_container_user' >> $HOME/.bashrc RUN echo 'source $STARTUPDIR/generate_container_user' >> $HOME/.bashrc
@@ -42,13 +43,17 @@ COPY startup/ $STARTUPDIR
### START CUSTOM STUFF #### ### START CUSTOM STUFF ####
ARG KASMVNC_PACKAGE_DIR ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/ COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp
RUN rm -f /tmp/kasmvncserver_*+*.deb; dpkg -i /tmp/*.deb; apt-get -yf install RUN dpkg -i /tmp/*.deb; apt-get -yf install
### END CUSTOM STUFF ### ### END CUSTOM STUFF ###
RUN echo 'pref("browser.startup.firstrunSkipsHomepage", false);' >> /usr/lib/firefox/browser/defaults/preferences/syspref.js
RUN echo 'pref("browser.startup.homepage", "postimages.org");' >> /usr/lib/firefox/browser/defaults/preferences/syspref.js
RUN chown -R 1000:0 $HOME RUN chown -R 1000:0 $HOME
USER 1000:ssl-cert USER 1000:ssl-cert
WORKDIR $HOME WORKDIR $HOME
ENV GTK_USE_PORTAL=1
ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ] ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ]

View File

@@ -1,8 +1,8 @@
FROM ubuntu:focal FROM ubuntu:focal
ARG KASMVNC_PACKAGE_DIR ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/ COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp
RUN rm -f /tmp/kasmvncserver_*+*.deb; apt-get update && dpkg -i /tmp/*.deb; apt-get -yf install RUN apt-get update && dpkg -i /tmp/*.deb; apt-get -yf install
RUN apt-get update && apt-get -y install xterm lsb-release RUN apt-get update && apt-get -y install xterm lsb-release
RUN useradd -m foo && addgroup foo ssl-cert RUN useradd -m foo && addgroup foo ssl-cert

View File

@@ -13,18 +13,19 @@ RUN apt-get update && \
RUN apt-get update && apt-get install -y --no-install-recommends tzdata RUN apt-get update && 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 build-dep xorg-server libxfont-dev
RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver RUN apt-get update && apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev RUN apt-get update && apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev
# Additions for webp # Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-* RUN cd /tmp && tar -xzvf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \ RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make && make install make && make install
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
COPY --chown=docker:docker . /src/ COPY . /src
RUN chown -R docker:docker /src
USER docker USER docker
ENTRYPOINT ["/src/builder/build.sh"] ENTRYPOINT ["/src/builder/build.sh"]

View File

@@ -9,11 +9,4 @@ RUN apt-get update && \
COPY ./debian/control /tmp COPY ./debian/control /tmp
RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control RUN apt-get update && echo YYY | mk-build-deps --install --remove /tmp/control
ARG L_UID USER 1000
RUN if [ "$L_UID" -eq 0 ]; then \
useradd -m docker; \
else \
useradd -m docker -u $L_UID;\
fi
USER docker

View File

@@ -42,8 +42,8 @@ COPY startup/ $STARTUPDIR
### START CUSTOM STUFF #### ### START CUSTOM STUFF ####
ARG KASMVNC_PACKAGE_DIR ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/ COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp
RUN rm -f /tmp/kasmvncserver_*+*.deb; dpkg -i /tmp/*.deb; apt-get -yf install RUN dpkg -i /tmp/*.deb; apt-get -yf install
RUN mkdir ~/.vnc && echo '/usr/bin/xfce4-session &' >> ~/.vnc/xstartup && \ RUN mkdir ~/.vnc && echo '/usr/bin/xfce4-session &' >> ~/.vnc/xstartup && \
chmod +x ~/.vnc/xstartup chmod +x ~/.vnc/xstartup

View File

@@ -1,30 +0,0 @@
FROM ubuntu:jammy
ENV KASMVNC_BUILD_OS ubuntu
ENV KASMVNC_BUILD_OS_CODENAME jammy
ENV XORG_VER 1.20.8
ENV DEBIAN_FRONTEND noninteractive
RUN sed -i 's$# deb-src$deb-src$' /etc/apt/sources.list
RUN apt-get update && \
apt-get -y install sudo
RUN apt-get update && 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 libjpeg-dev libgnutls28-dev vim wget tightvncserver
RUN apt-get update && apt-get -y install libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-dev libxrandr-dev libxcursor-dev
# Additions for webp
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
RUN cd /tmp && tar -xzf /tmp/libwebp-*
RUN cd /tmp/libwebp-1.0.2 && \
./configure --enable-static --disable-shared && \
make && make install
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

@@ -1,19 +0,0 @@
FROM ubuntu:jammy
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

@@ -1,57 +0,0 @@
FROM ubuntu:jammy
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=ubuntu \
KASMVNC_BUILD_OS_CODENAME=bionic
EXPOSE $VNC_PORT
WORKDIR $HOME
### REQUIRED STUFF ###
RUN apt-get update && apt-get install -y supervisor xfce4 xfce4-terminal 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 startup/ $STARTUPDIR
### START CUSTOM STUFF ####
ARG KASMVNC_PACKAGE_DIR
COPY $KASMVNC_PACKAGE_DIR/kasmvncserver_*.deb /tmp/
RUN rm -f /tmp/kasmvncserver_*+*.deb; dpkg -i /tmp/*.deb; apt-get -yf install
RUN mkdir ~/.vnc && echo '/usr/bin/xfce4-session &' >> ~/.vnc/xstartup && \
chmod +x ~/.vnc/xstartup
### END CUSTOM STUFF ###
RUN chown -R 1000:0 $HOME
USER 1000:ssl-cert
WORKDIR $HOME
ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ]

View File

@@ -1,51 +0,0 @@
FROM ubuntu:jammy
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=ubuntu \
KASMVNC_BUILD_OS_CODENAME=jammy
EXPOSE $VNC_PORT
WORKDIR $HOME
### REQUIRED STUFF ###
RUN apt-get update && apt-get install -y supervisor xfce4 xfce4-terminal xterm libnss-wrapper gettext libjpeg-dev wget
RUN apt-get purge -y pm-utils xscreensaver*
RUN echo 'source $STARTUPDIR/generate_container_user' >> $HOME/.bashrc
RUN mkdir -p $STARTUPDIR
COPY startup/ $STARTUPDIR
### START CUSTOM STUFF ####
COPY build/kasmvnc.${KASMVNC_BUILD_OS}_${KASMVNC_BUILD_OS_CODENAME}.tar.gz /tmp/
RUN tar -xzvf /tmp/kasmvnc.${KASMVNC_BUILD_OS}_${KASMVNC_BUILD_OS_CODENAME}.tar.gz --strip 1 -C /
### END CUSTOM STUFF ###
RUN chown -R 1000:0 $HOME
USER 1000
WORKDIR $HOME
ENTRYPOINT [ "/dockerstartup/vnc_startup.sh" ]

View File

@@ -3,11 +3,6 @@ default_os_codename=bionic
os=${1:-$default_os} os=${1:-$default_os}
os_codename=${2:-$default_os_codename} os_codename=${2:-$default_os_codename}
build_tag="${3:-}"
if [[ -n "$build_tag" ]]; then
build_tag_for_images="_${build_tag#+}"
build_debian_revision="$(echo $build_tag | tr _ -)"
fi
os_image="$os:$os_codename" os_image="$os:$os_codename"
echo "Building for $os_image" echo "Building for $os_image"

View File

@@ -88,6 +88,8 @@ detect_www_dir
detect_cert_location detect_cert_location
[ -n "$KASMVNC_VERBOSE_LOGGING" ] && verbose_logging_option="-log *:stderr:100" [ -n "$KASMVNC_VERBOSE_LOGGING" ] && verbose_logging_option="-log *:stderr:100"
# dbus-daemon --session --address=systemd: --nofork --nopidfile --syslog-only &
echo -e "start vncserver with param: VNC_COL_DEPTH=$VNC_COL_DEPTH, VNC_RESOLUTION=$VNC_RESOLUTION\n..." echo -e "start vncserver with param: VNC_COL_DEPTH=$VNC_COL_DEPTH, VNC_RESOLUTION=$VNC_RESOLUTION\n..."
vncserver $DISPLAY -depth $VNC_COL_DEPTH -geometry $VNC_RESOLUTION -FrameRate=$MAX_FRAME_RATE -websocketPort $VNC_PORT $cert_option -sslOnly -interface 0.0.0.0 $VNCOPTIONS $package_www_dir_option $verbose_logging_option #&> $STARTUPDIR/no_vnc_startup.log vncserver $DISPLAY -depth $VNC_COL_DEPTH -geometry $VNC_RESOLUTION -FrameRate=$MAX_FRAME_RATE -websocketPort $VNC_PORT $cert_option -sslOnly -interface 0.0.0.0 $VNCOPTIONS $package_www_dir_option $verbose_logging_option #&> $STARTUPDIR/no_vnc_startup.log

View File

@@ -5,12 +5,10 @@ set -e
cd "$(dirname "$0")" cd "$(dirname "$0")"
. ./os_ver_cli.sh . ./os_ver_cli.sh
tester_image=kasmvnctester_${os}:$os_codename${build_tag_for_images}
docker build --build-arg KASMVNC_PACKAGE_DIR="build/${os_codename}" \ docker build --build-arg KASMVNC_PACKAGE_DIR="build/${os_codename}" \
--build-arg BUILD_DEBIAN_REVISION="$build_debian_revision" \ -t kasmvnctester_${os}:$os_codename \
-t "$tester_image" \ -f dockerfile.${os}_${os_codename}.deb.test .
-f dockerfile.${os}_${os_codename}${build_tag}.deb.test .
docker run -it -p 443:8443 --rm \ docker run -it -p 443:8443 --rm \
-e KASMVNC_VERBOSE_LOGGING=$KASMVNC_VERBOSE_LOGGING \ -e KASMVNC_VERBOSE_LOGGING=$KASMVNC_VERBOSE_LOGGING \
-e "VNC_USER=foo" -e "VNC_PW=foobar" \ -e "VNC_USER=foo" -e "VNC_PW=foobar" \
"$tester_image" kasmvnctester_${os}:$os_codename

View File

@@ -1,5 +1,5 @@
Name: kasmvncserver Name: kasmvncserver
Version: 0.9.3~beta Version: 0.9.1~beta
Release: 1%{?dist} Release: 1%{?dist}
Summary: VNC server accessible from a web browser Summary: VNC server accessible from a web browser
@@ -53,7 +53,6 @@ cp $SRC_BIN/Xvnc $DESTDIR/usr/bin;
cp $SRC_BIN/vncserver $DESTDIR/usr/bin; cp $SRC_BIN/vncserver $DESTDIR/usr/bin;
cp $SRC_BIN/vncconfig $DESTDIR/usr/bin; cp $SRC_BIN/vncconfig $DESTDIR/usr/bin;
cp $SRC_BIN/kasmvncpasswd $DESTDIR/usr/bin; cp $SRC_BIN/kasmvncpasswd $DESTDIR/usr/bin;
cp $SRC_BIN/kasmxproxy $DESTDIR/usr/bin;
cd $DESTDIR/usr/bin && ln -s kasmvncpasswd vncpasswd; cd $DESTDIR/usr/bin && ln -s kasmvncpasswd vncpasswd;
cp -r $SRC/share/doc/kasmvnc*/* $DESTDIR/usr/share/doc/kasmvncserver/ cp -r $SRC/share/doc/kasmvnc*/* $DESTDIR/usr/share/doc/kasmvncserver/
rsync -r --exclude '.git*' --exclude po2js --exclude xgettext-html \ rsync -r --exclude '.git*' --exclude po2js --exclude xgettext-html \
@@ -63,10 +62,8 @@ cp $SRC/man/man1/Xvnc.1 $DESTDIR/usr/share/man/man1/;
cp $SRC/share/man/man1/vncserver.1 $DST_MAN; cp $SRC/share/man/man1/vncserver.1 $DST_MAN;
cp $SRC/share/man/man1/vncconfig.1 $DST_MAN; cp $SRC/share/man/man1/vncconfig.1 $DST_MAN;
cp $SRC/share/man/man1/vncpasswd.1 $DST_MAN; cp $SRC/share/man/man1/vncpasswd.1 $DST_MAN;
cp $SRC/share/man/man1/kasmxproxy.1 $DST_MAN;
cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1; cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
%files %files
/usr/bin/* /usr/bin/*
/usr/share/man/man1/* /usr/share/man/man1/*
@@ -76,7 +73,6 @@ cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
%doc /usr/share/doc/kasmvncserver/README.md %doc /usr/share/doc/kasmvncserver/README.md
%changelog %changelog
* Tue Mar 22 2022 KasmTech <info@kasmweb.com> - 0.9.3~beta-1
* Fri Feb 12 2021 KasmTech <info@kasmweb.com> - 0.9.1~beta-1 * Fri Feb 12 2021 KasmTech <info@kasmweb.com> - 0.9.1~beta-1
- Initial release of the rpm package. - Initial release of the rpm package.

View File

@@ -1,85 +0,0 @@
/* Copyright (C) 2021 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_CONFIG_H
#include <config.h>
#endif
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <map>
#include <string>
#include <network/Blacklist.h>
#include <rfb/Blacklist.h>
static std::map<std::string, unsigned> hits;
static std::map<std::string, time_t> blacklist;
static pthread_mutex_t hitmutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t blmutex = PTHREAD_MUTEX_INITIALIZER;
unsigned char bl_isBlacklisted(const char *addr) {
const unsigned char count = blacklist.count(addr);
if (!count)
return 0;
const time_t now = time(NULL);
const unsigned timeout = rfb::Blacklist::initialTimeout;
if (pthread_mutex_lock(&blmutex))
abort();
if (now - timeout > blacklist[addr]) {
blacklist.erase(addr);
pthread_mutex_unlock(&blmutex);
if (pthread_mutex_lock(&hitmutex))
abort();
hits.erase(addr);
pthread_mutex_unlock(&hitmutex);
return 0;
} else {
blacklist[addr] = now;
pthread_mutex_unlock(&blmutex);
return 1;
}
}
void bl_addFailure(const char *addr) {
if (!rfb::Blacklist::threshold)
return;
if (pthread_mutex_lock(&hitmutex))
abort();
const unsigned num = ++hits[addr];
pthread_mutex_unlock(&hitmutex);
if (num >= (unsigned) rfb::Blacklist::threshold) {
if (pthread_mutex_lock(&blmutex))
abort();
blacklist[addr] = time(NULL);
pthread_mutex_unlock(&blmutex);
}
}

View File

@@ -1,33 +0,0 @@
/* Copyright (C) 2021 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.
*/
#ifndef __NETWORK_BLACKLIST_H__
#define __NETWORK_BLACKLIST_H__
#ifdef __cplusplus
extern "C" {
#endif
unsigned char bl_isBlacklisted(const char *);
void bl_addFailure(const char *);
#ifdef __cplusplus
} // extern C
#endif
#endif // __NETWORK_TCP_SOCKET_H__

View File

@@ -2,11 +2,8 @@ include_directories(${CMAKE_SOURCE_DIR}/common ${CMAKE_SOURCE_DIR}/unix/kasmvncp
set(NETWORK_SOURCES set(NETWORK_SOURCES
GetAPIMessager.cxx GetAPIMessager.cxx
Blacklist.cxx
Socket.cxx Socket.cxx
TcpSocket.cxx TcpSocket.cxx
cJSON.c
jsonescape.c
websocket.c websocket.c
websockify.c websockify.c
${CMAKE_SOURCE_DIR}/unix/kasmvncpasswd/kasmpasswd.c) ${CMAKE_SOURCE_DIR}/unix/kasmvncpasswd/kasmpasswd.c)

View File

@@ -21,12 +21,9 @@
#include <kasmpasswd.h> #include <kasmpasswd.h>
#include <pthread.h> #include <pthread.h>
#include <network/GetAPIEnums.h>
#include <rfb/PixelBuffer.h> #include <rfb/PixelBuffer.h>
#include <rfb/PixelFormat.h> #include <rfb/PixelFormat.h>
#include <stdint.h> #include <stdint.h>
#include <map>
#include <string>
#include <vector> #include <vector>
namespace network { namespace network {
@@ -37,48 +34,21 @@ namespace network {
// from main thread // from main thread
void mainUpdateScreen(rfb::PixelBuffer *pb); void mainUpdateScreen(rfb::PixelBuffer *pb);
void mainUpdateBottleneckStats(const char userid[], const char stats[]);
void mainClearBottleneckStats(const char userid[]);
void mainUpdateServerFrameStats(uint8_t changedPerc, uint32_t all,
uint32_t jpeg, uint32_t webp, uint32_t analysis,
uint32_t jpegarea, uint32_t webparea,
uint16_t njpeg, uint16_t nwebp,
uint16_t enc, uint16_t scale, uint16_t shot,
uint16_t w, uint16_t h);
void mainUpdateClientFrameStats(const char userid[], uint32_t render, uint32_t all,
uint32_t ping);
void mainUpdateUserInfo(const uint8_t ownerConn, const uint8_t numUsers);
// from network threads // from network threads
uint8_t *netGetScreenshot(uint16_t w, uint16_t h, uint8_t *netGetScreenshot(uint16_t w, uint16_t h,
const uint8_t q, const bool dedup, const uint8_t q, const bool dedup,
uint32_t &len, uint8_t *staging); uint32_t &len, uint8_t *staging);
uint8_t netAddUser(const char name[], const char pw[], uint8_t netAddUser(const char name[], const char pw[], const bool write);
const bool read, const bool write, const bool owner);
uint8_t netRemoveUser(const char name[]); uint8_t netRemoveUser(const char name[]);
uint8_t netUpdateUser(const char name[], const uint64_t mask, uint8_t netGiveControlTo(const char name[]);
const char password[],
const bool read, const bool write, const bool owner);
uint8_t netAddOrUpdateUser(const struct kasmpasswd_entry_t *entry);
void netGetUsers(const char **ptr);
void netGetBottleneckStats(char *buf, uint32_t len);
void netGetFrameStats(char *buf, uint32_t len);
void netResetFrameStatsCall();
uint8_t netServerFrameStatsReady();
enum USER_ACTION { enum USER_ACTION {
NONE, //USER_ADD, - handled locally for interactivity
WANT_FRAME_STATS_SERVERONLY, USER_REMOVE,
WANT_FRAME_STATS_ALL, USER_GIVE_CONTROL,
WANT_FRAME_STATS_OWNER,
WANT_FRAME_STATS_SPECIFIC,
}; };
uint8_t netRequestFrameStats(USER_ACTION what, const char *client);
uint8_t netOwnerConnected();
uint8_t netNumActiveUsers();
uint8_t netGetClientFrameStatsNum();
struct action_data { struct action_data {
enum USER_ACTION action; enum USER_ACTION action;
kasmpasswd_entry_t data; kasmpasswd_entry_t data;
@@ -98,40 +68,6 @@ namespace network {
std::vector<uint8_t> cachedJpeg; std::vector<uint8_t> cachedJpeg;
uint16_t cachedW, cachedH; uint16_t cachedW, cachedH;
uint8_t cachedQ; uint8_t cachedQ;
std::map<std::string, std::string> bottleneckStats;
pthread_mutex_t statMutex;
struct clientFrameStats_t {
uint32_t render;
uint32_t all;
uint32_t ping;
};
struct serverFrameStats_t {
uint32_t all;
uint32_t jpeg;
uint32_t webp;
uint32_t analysis;
uint32_t jpegarea;
uint32_t webparea;
uint16_t njpeg;
uint16_t nwebp;
uint16_t enc;
uint16_t scale;
uint16_t shot;
uint16_t w;
uint16_t h;
uint8_t changedPerc;
uint8_t inprogress;
};
std::map<std::string, clientFrameStats_t> clientFrameStats;
serverFrameStats_t serverFrameStats;
pthread_mutex_t frameStatMutex;
uint8_t ownerConnected;
uint8_t activeUsers;
pthread_mutex_t userInfoMutex;
}; };
} }

View File

@@ -1,30 +0,0 @@
/* Copyright (C) 2021 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.
*/
#ifndef __NETWORK_GET_API_ENUMS_H__
#define __NETWORK_GET_API_ENUMS_H__
// Enums that need accessibility from both C and C++.
enum USER_UPDATE_MASK {
USER_UPDATE_WRITE_MASK = 1 << 0,
USER_UPDATE_OWNER_MASK = 1 << 1,
USER_UPDATE_PASSWORD_MASK = 1 << 2,
USER_UPDATE_READ_MASK = 1 << 3,
};
#endif

View File

@@ -20,9 +20,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <network/GetAPI.h> #include <network/GetAPI.h>
#include <network/jsonescape.h>
#include <rfb/ConnParams.h> #include <rfb/ConnParams.h>
#include <rfb/EncodeManager.h>
#include <rfb/LogWriter.h> #include <rfb/LogWriter.h>
#include <rfb/JpegCompressor.h> #include <rfb/JpegCompressor.h>
#include <rfb/xxhash.h> #include <rfb/xxhash.h>
@@ -34,6 +32,10 @@ using namespace rfb;
static LogWriter vlog("GetAPIMessager"); static LogWriter vlog("GetAPIMessager");
PixelBuffer *progressiveBilinearScale(const PixelBuffer *pb,
const uint16_t tgtw, const uint16_t tgth,
const float tgtdiff);
struct TightJPEGConfiguration { struct TightJPEGConfiguration {
int quality; int quality;
int subsampling; int subsampling;
@@ -54,16 +56,10 @@ static const struct TightJPEGConfiguration conf[10] = {
GetAPIMessager::GetAPIMessager(const char *passwdfile_): passwdfile(passwdfile_), GetAPIMessager::GetAPIMessager(const char *passwdfile_): passwdfile(passwdfile_),
screenW(0), screenH(0), screenHash(0), screenW(0), screenH(0), screenHash(0),
cachedW(0), cachedH(0), cachedQ(0), cachedW(0), cachedH(0), cachedQ(0) {
ownerConnected(0), activeUsers(0) {
pthread_mutex_init(&screenMutex, NULL); pthread_mutex_init(&screenMutex, NULL);
pthread_mutex_init(&userMutex, NULL); pthread_mutex_init(&userMutex, NULL);
pthread_mutex_init(&statMutex, NULL);
pthread_mutex_init(&frameStatMutex, NULL);
pthread_mutex_init(&userInfoMutex, NULL);
serverFrameStats.inprogress = 0;
} }
// from main thread // from main thread
@@ -99,78 +95,6 @@ void GetAPIMessager::mainUpdateScreen(rfb::PixelBuffer *pb) {
pthread_mutex_unlock(&screenMutex); pthread_mutex_unlock(&screenMutex);
} }
void GetAPIMessager::mainUpdateBottleneckStats(const char userid[], const char stats[]) {
if (pthread_mutex_trylock(&statMutex))
return;
bottleneckStats[userid] = stats;
pthread_mutex_unlock(&statMutex);
}
void GetAPIMessager::mainClearBottleneckStats(const char userid[]) {
if (pthread_mutex_lock(&statMutex))
return;
bottleneckStats.erase(userid);
pthread_mutex_unlock(&statMutex);
}
void GetAPIMessager::mainUpdateServerFrameStats(uint8_t changedPerc,
uint32_t all, uint32_t jpeg, uint32_t webp, uint32_t analysis,
uint32_t jpegarea, uint32_t webparea,
uint16_t njpeg, uint16_t nwebp,
uint16_t enc, uint16_t scale, uint16_t shot,
uint16_t w, uint16_t h) {
if (pthread_mutex_lock(&frameStatMutex))
return;
serverFrameStats.changedPerc = changedPerc;
serverFrameStats.all = all;
serverFrameStats.jpeg = jpeg;
serverFrameStats.webp = webp;
serverFrameStats.analysis = analysis;
serverFrameStats.jpegarea = jpegarea;
serverFrameStats.webparea = webparea;
serverFrameStats.njpeg = njpeg;
serverFrameStats.nwebp = nwebp;
serverFrameStats.enc = enc;
serverFrameStats.scale = scale;
serverFrameStats.shot = shot;
serverFrameStats.w = w;
serverFrameStats.h = h;
pthread_mutex_unlock(&frameStatMutex);
}
void GetAPIMessager::mainUpdateClientFrameStats(const char userid[], uint32_t render,
uint32_t all, uint32_t ping) {
if (pthread_mutex_lock(&frameStatMutex))
return;
clientFrameStats_t s;
s.render = render;
s.all = all;
s.ping = ping;
clientFrameStats[userid] = s;
pthread_mutex_unlock(&frameStatMutex);
}
void GetAPIMessager::mainUpdateUserInfo(const uint8_t ownerConn, const uint8_t numUsers) {
if (pthread_mutex_lock(&userInfoMutex))
return;
ownerConnected = ownerConn;
activeUsers = numUsers;
pthread_mutex_unlock(&userInfoMutex);
}
// from network threads // from network threads
uint8_t *GetAPIMessager::netGetScreenshot(uint16_t w, uint16_t h, uint8_t *GetAPIMessager::netGetScreenshot(uint16_t w, uint16_t h,
const uint8_t q, const bool dedup, const uint8_t q, const bool dedup,
@@ -264,9 +188,10 @@ uint8_t *GetAPIMessager::netGetScreenshot(uint16_t w, uint16_t h,
return ret; return ret;
} }
uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[], #define USERNAME_LEN sizeof(((struct kasmpasswd_entry_t *)0)->user)
const bool read, const bool write, #define PASSWORD_LEN sizeof(((struct kasmpasswd_entry_t *)0)->password)
const bool owner) {
uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[], const bool write) {
if (strlen(name) >= USERNAME_LEN) { if (strlen(name) >= USERNAME_LEN) {
vlog.error("Username too long"); vlog.error("Username too long");
return 0; return 0;
@@ -280,17 +205,14 @@ uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[],
if (!passwdfile) if (!passwdfile)
return 0; return 0;
uint8_t ret = 1;
action_data act; action_data act;
memcpy(act.data.user, name, USERNAME_LEN); memcpy(act.data.user, name, USERNAME_LEN);
act.data.user[USERNAME_LEN - 1] = '\0'; act.data.user[USERNAME_LEN - 1] = '\0';
memcpy(act.data.password, pw, PASSWORD_LEN); memcpy(act.data.password, pw, PASSWORD_LEN);
act.data.password[PASSWORD_LEN - 1] = '\0'; act.data.password[PASSWORD_LEN - 1] = '\0';
act.data.owner = owner; act.data.owner = 0;
act.data.write = write; act.data.write = write;
act.data.read = read;
if (pthread_mutex_lock(&userMutex)) if (pthread_mutex_lock(&userMutex))
return 0; return 0;
@@ -302,9 +224,8 @@ uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[],
struct kasmpasswd_t *set = readkasmpasswd(passwdfile); struct kasmpasswd_t *set = readkasmpasswd(passwdfile);
unsigned s; unsigned s;
for (s = 0; s < set->num; s++) { for (s = 0; s < set->num; s++) {
if (!strcmp(set->entries[s].user, name)) { if (!strcmp(set->entries[s].user, act.data.user)) {
vlog.error("Can't create user %s, already exists", name); vlog.error("Can't create user %s, already exists", act.data.user);
ret = 0;
goto out; goto out;
} }
} }
@@ -315,14 +236,11 @@ uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[],
set->entries[s] = act.data; set->entries[s] = act.data;
writekasmpasswd(passwdfile, set); writekasmpasswd(passwdfile, set);
vlog.info("User %s created", name); vlog.info("User %s created", act.data.user);
out: out:
pthread_mutex_unlock(&userMutex); pthread_mutex_unlock(&userMutex);
free(set->entries); return 1;
free(set);
return ret;
} }
uint8_t GetAPIMessager::netRemoveUser(const char name[]) { uint8_t GetAPIMessager::netRemoveUser(const char name[]) {
@@ -331,404 +249,12 @@ uint8_t GetAPIMessager::netRemoveUser(const char name[]) {
return 0; return 0;
} }
if (pthread_mutex_lock(&userMutex))
return 0;
struct kasmpasswd_t *set = readkasmpasswd(passwdfile);
bool found = false;
unsigned s;
for (s = 0; s < set->num; s++) {
if (!strcmp(set->entries[s].user, name)) {
set->entries[s].user[0] = '\0';
found = true;
break;
}
}
if (found) {
writekasmpasswd(passwdfile, set);
vlog.info("User %s removed", name);
} else {
vlog.error("Tried to remove nonexistent user %s", name);
pthread_mutex_unlock(&userMutex);
free(set->entries);
free(set);
return 0;
}
pthread_mutex_unlock(&userMutex);
free(set->entries);
free(set);
return 1;
}
uint8_t GetAPIMessager::netUpdateUser(const char name[], const uint64_t mask,
const char password[],
const bool read, const bool write, const bool owner) {
if (strlen(name) >= USERNAME_LEN) {
vlog.error("Username too long");
return 0;
}
if (strlen(password) >= PASSWORD_LEN) {
vlog.error("Password too long");
return 0;
}
if (!mask) {
vlog.error("Update_user without any updates?");
return 0;
}
if (pthread_mutex_lock(&userMutex))
return 0;
struct kasmpasswd_t *set = readkasmpasswd(passwdfile);
bool found = false;
unsigned s;
for (s = 0; s < set->num; s++) {
if (!strcmp(set->entries[s].user, name)) {
if (mask & USER_UPDATE_READ_MASK)
set->entries[s].read = read;
if (mask & USER_UPDATE_WRITE_MASK)
set->entries[s].write = write;
if (mask & USER_UPDATE_OWNER_MASK)
set->entries[s].owner = owner;
if (mask & USER_UPDATE_PASSWORD_MASK)
strcpy(set->entries[s].password, password);
found = true;
break;
}
}
if (found) {
writekasmpasswd(passwdfile, set);
vlog.info("User %s permissions updated", name);
} else {
vlog.error("Tried to update nonexistent user %s", name);
pthread_mutex_unlock(&userMutex);
free(set->entries);
free(set);
return 0;
}
pthread_mutex_unlock(&userMutex);
free(set->entries);
free(set);
return 1;
}
uint8_t GetAPIMessager::netAddOrUpdateUser(const struct kasmpasswd_entry_t *entry) {
if (pthread_mutex_lock(&userMutex))
return 0;
struct kasmpasswd_t *set = readkasmpasswd(passwdfile);
unsigned s;
bool updated = false;
for (s = 0; s < set->num; s++) {
if (!strcmp(set->entries[s].user, entry->user)) {
set->entries[s] = *entry;
updated = true;
vlog.info("User %s updated", entry->user);
break;
}
}
if (!updated) {
s = set->num++;
set->entries = (struct kasmpasswd_entry_t *) realloc(set->entries,
set->num * sizeof(struct kasmpasswd_entry_t));
set->entries[s] = *entry;
vlog.info("User %s created", entry->user);
}
writekasmpasswd(passwdfile, set);
pthread_mutex_unlock(&userMutex);
free(set->entries);
free(set);
return 1;
}
void GetAPIMessager::netGetUsers(const char **outptr) {
/*
[
{ "user": "username", "write": true, "owner": true },
{ "user": "username", "write": true, "owner": true }
]
*/
char *buf;
char escapeduser[USERNAME_LEN * 2];
if (pthread_mutex_lock(&userMutex)) {
*outptr = (char *) calloc(1, 1);
return;
}
struct kasmpasswd_t *set = readkasmpasswd(passwdfile);
buf = (char *) calloc(set->num, 80);
FILE *f = fmemopen(buf, set->num * 80, "w");
fprintf(f, "[\n");
unsigned s;
for (s = 0; s < set->num; s++) {
JSON_escape(set->entries[s].user, escapeduser);
fprintf(f, " { \"user\": \"%s\", \"read\": %s, \"write\": %s, \"owner\": %s }",
escapeduser,
set->entries[s].read ? "true" : "false",
set->entries[s].write ? "true" : "false",
set->entries[s].owner ? "true" : "false");
if (s == set->num - 1)
fprintf(f, "\n");
else
fprintf(f, ",\n");
}
free(set->entries);
free(set);
fprintf(f, "]\n");
fclose(f);
pthread_mutex_unlock(&userMutex);
*outptr = buf;
}
void GetAPIMessager::netGetBottleneckStats(char *buf, uint32_t len) {
/*
{
"username.1": {
"192.168.100.2:14908": [ 100, 100, 100, 100 ],
"192.168.100.3:14918": [ 100, 100, 100, 100 ]
},
"username.2": {
"192.168.100.5:14904": [ 100, 100, 100, 100 ]
}
}
*/
std::map<std::string, std::string>::const_iterator it;
const char *prev = NULL;
FILE *f;
if (pthread_mutex_lock(&statMutex)) {
buf[0] = 0;
return;
}
// Conservative estimate
if (len < bottleneckStats.size() * 60) {
buf[0] = 0;
goto out;
}
f = fmemopen(buf, len, "w");
fprintf(f, "{\n");
for (it = bottleneckStats.begin(); it != bottleneckStats.end(); it++) {
// user@127.0.0.1_1627311208.791752::websocket
const char *id = it->first.c_str();
const char *data = it->second.c_str();
const char *at = strchr(id, '@');
if (!at)
continue;
const unsigned userlen = at - id;
if (prev && !strncmp(prev, id, userlen)) {
// Same user
fprintf(f, ",\n\t\t\"%s\": %s", at + 1, data);
} else {
// New one
if (prev) {
fprintf(f, "\n\t},\n");
}
fprintf(f, "\t\"%.*s\": {\n", userlen, id);
fprintf(f, "\t\t\"%s\": %s", at + 1, data);
}
prev = id;
}
if (!bottleneckStats.size())
fprintf(f, "}\n");
else
fprintf(f, "\n\t}\n}\n");
fclose(f);
out:
pthread_mutex_unlock(&statMutex);
}
void GetAPIMessager::netGetFrameStats(char *buf, uint32_t len) {
/*
{
"frame" : {
"resx": 1024,
"resy": 1280,
"changed": 75,
"server_time": 23
},
"server_side" : [
{ "process_name": "Analysis", "time": 20 },
{ "process_name": "TightWEBPEncoder", "time": 20, "count": 64, "area": 12 },
{ "process_name": "TightJPEGEncoder", "time": 20, "count": 64, "area": 12 }
],
"client_side" : [
{
"client": "123.1.2.1:1211",
"client_time": 20,
"ping": 20,
"processes" : [
{ "process_name": "scanRenderQ", "time": 20 }
]
}
}
}
*/
std::map<std::string, clientFrameStats_t>::const_iterator it;
unsigned i = 0;
FILE *f;
if (pthread_mutex_lock(&frameStatMutex)) {
buf[0] = 0;
return;
}
const unsigned num = clientFrameStats.size();
// Conservative estimate
if (len < 1024) {
buf[0] = 0;
goto out;
}
f = fmemopen(buf, len, "w");
fprintf(f, "{\n");
fprintf(f, "\t\"frame\" : {\n"
"\t\t\"resx\": %u,\n"
"\t\t\"resy\": %u,\n"
"\t\t\"changed\": %u,\n"
"\t\t\"server_time\": %u\n"
"\t},\n",
serverFrameStats.w,
serverFrameStats.h,
serverFrameStats.changedPerc,
serverFrameStats.all);
fprintf(f, "\t\"server_side\" : [\n"
"\t\t{ \"process_name\": \"Analysis\", \"time\": %u },\n"
"\t\t{ \"process_name\": \"Screenshot\", \"time\": %u },\n"
"\t\t{ \"process_name\": \"Encoding_total\", \"time\": %u, \"videoscaling\": %u },\n"
"\t\t{ \"process_name\": \"TightJPEGEncoder\", \"time\": %u, \"count\": %u, \"area\": %u },\n"
"\t\t{ \"process_name\": \"TightWEBPEncoder\", \"time\": %u, \"count\": %u, \"area\": %u }\n"
"\t],\n",
serverFrameStats.analysis,
serverFrameStats.shot,
serverFrameStats.enc,
serverFrameStats.scale,
serverFrameStats.jpeg,
serverFrameStats.njpeg,
serverFrameStats.jpegarea,
serverFrameStats.webp,
serverFrameStats.nwebp,
serverFrameStats.webparea);
fprintf(f, "\t\"client_side\" : [\n");
for (it = clientFrameStats.begin(); it != clientFrameStats.end(); it++, i++) {
const char *id = it->first.c_str();
const clientFrameStats_t &s = it->second;
fprintf(f, "\t\t\{\n"
"\t\t\t\"client\": \"%s\",\n"
"\t\t\t\"client_time\": %u,\n"
"\t\t\t\"ping\": %u,\n"
"\t\t\t\"processes\" : [\n"
"\t\t\t\t{ \"process_name\": \"scanRenderQ\", \"time\": %u }\n"
"\t\t\t]\n"
"\t\t}",
id,
s.all,
s.ping,
s.render);
if (i == num - 1)
fprintf(f, "\n");
else
fprintf(f, ",\n");
}
fprintf(f, "\t]\n}\n");
fclose(f);
serverFrameStats.inprogress = 0;
out:
pthread_mutex_unlock(&frameStatMutex);
}
void GetAPIMessager::netResetFrameStatsCall() {
if (pthread_mutex_lock(&frameStatMutex))
return;
serverFrameStats.inprogress = 0;
pthread_mutex_unlock(&frameStatMutex);
}
uint8_t GetAPIMessager::netRequestFrameStats(USER_ACTION what, const char *client) {
// Return 1 for success
action_data act; action_data act;
act.action = what; act.action = USER_REMOVE;
if (client) {
strncpy(act.data.password, client, PASSWORD_LEN);
act.data.password[PASSWORD_LEN - 1] = '\0';
}
// In progress already? memcpy(act.data.user, name, USERNAME_LEN);
bool fail = false; act.data.user[USERNAME_LEN - 1] = '\0';
if (pthread_mutex_lock(&frameStatMutex))
return 0;
if (serverFrameStats.inprogress) {
fail = true;
vlog.error("Frame stats request already in progress, refusing another");
} else {
clientFrameStats.clear();
memset(&serverFrameStats, 0, sizeof(serverFrameStats_t));
serverFrameStats.inprogress = 1;
}
pthread_mutex_unlock(&frameStatMutex);
if (fail)
return 0;
// Send it in
if (pthread_mutex_lock(&userMutex)) if (pthread_mutex_lock(&userMutex))
return 0; return 0;
@@ -739,54 +265,24 @@ uint8_t GetAPIMessager::netRequestFrameStats(USER_ACTION what, const char *clien
return 1; return 1;
} }
uint8_t GetAPIMessager::netOwnerConnected() { uint8_t GetAPIMessager::netGiveControlTo(const char name[]) {
uint8_t ret; if (strlen(name) >= USERNAME_LEN) {
vlog.error("Username too long");
return 0;
}
if (pthread_mutex_lock(&userInfoMutex)) action_data act;
act.action = USER_GIVE_CONTROL;
memcpy(act.data.user, name, USERNAME_LEN);
act.data.user[USERNAME_LEN - 1] = '\0';
if (pthread_mutex_lock(&userMutex))
return 0; return 0;
ret = ownerConnected; actionQueue.push_back(act);
pthread_mutex_unlock(&userInfoMutex); pthread_mutex_unlock(&userMutex);
return ret; return 1;
}
uint8_t GetAPIMessager::netNumActiveUsers() {
uint8_t ret;
if (pthread_mutex_lock(&userInfoMutex))
return 0;
ret = activeUsers;
pthread_mutex_unlock(&userInfoMutex);
return ret;
}
uint8_t GetAPIMessager::netGetClientFrameStatsNum() {
uint8_t ret;
if (pthread_mutex_lock(&frameStatMutex))
return 0;
ret = clientFrameStats.size();
pthread_mutex_unlock(&frameStatMutex);
return ret;
}
uint8_t GetAPIMessager::netServerFrameStatsReady() {
uint8_t ret;
if (pthread_mutex_lock(&frameStatMutex))
return 0;
ret = serverFrameStats.w != 0;
pthread_mutex_unlock(&frameStatMutex);
return ret;
} }

View File

@@ -40,8 +40,6 @@
#include <unistd.h> #include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <wordexp.h> #include <wordexp.h>
#include <sys/types.h>
#include <unistd.h>
#include "websocket.h" #include "websocket.h"
#include <network/GetAPI.h> #include <network/GetAPI.h>
@@ -443,10 +441,10 @@ static uint8_t *screenshotCb(void *messager, uint16_t w, uint16_t h, const uint8
} }
static uint8_t adduserCb(void *messager, const char name[], const char pw[], static uint8_t adduserCb(void *messager, const char name[], const char pw[],
const uint8_t read, const uint8_t write, const uint8_t owner) const uint8_t write)
{ {
GetAPIMessager *msgr = (GetAPIMessager *) messager; GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netAddUser(name, pw, read, write, owner); return msgr->netAddUser(name, pw, write);
} }
static uint8_t removeCb(void *messager, const char name[]) static uint8_t removeCb(void *messager, const char name[])
@@ -455,93 +453,12 @@ static uint8_t removeCb(void *messager, const char name[])
return msgr->netRemoveUser(name); return msgr->netRemoveUser(name);
} }
static uint8_t updateUserCb(void *messager, const char name[], const uint64_t mask, static uint8_t givecontrolCb(void *messager, const char name[])
const char password[],
const uint8_t read, const uint8_t write, const uint8_t owner)
{ {
GetAPIMessager *msgr = (GetAPIMessager *) messager; GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netUpdateUser(name, mask, password, read, write, owner); return msgr->netGiveControlTo(name);
} }
static uint8_t addOrUpdateUserCb(void *messager, const struct kasmpasswd_entry_t *entry)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netAddOrUpdateUser(entry);
}
static void getUsersCb(void *messager, const char **ptr)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
msgr->netGetUsers(ptr);
}
static void bottleneckStatsCb(void *messager, char *buf, uint32_t len)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
msgr->netGetBottleneckStats(buf, len);
}
static void frameStatsCb(void *messager, char *buf, uint32_t len)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
msgr->netGetFrameStats(buf, len);
}
static void resetFrameStatsCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
msgr->netResetFrameStatsCall();
}
static uint8_t requestFrameStatsNoneCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netRequestFrameStats(GetAPIMessager::WANT_FRAME_STATS_SERVERONLY, NULL);
}
static uint8_t requestFrameStatsOwnerCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netRequestFrameStats(GetAPIMessager::WANT_FRAME_STATS_OWNER, NULL);
}
static uint8_t requestFrameStatsAllCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netRequestFrameStats(GetAPIMessager::WANT_FRAME_STATS_ALL, NULL);
}
static uint8_t requestFrameStatsOneCb(void *messager, const char *client)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netRequestFrameStats(GetAPIMessager::WANT_FRAME_STATS_SPECIFIC, client);
}
static uint8_t ownerConnectedCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netOwnerConnected();
}
static uint8_t numActiveUsersCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netNumActiveUsers();
}
static uint8_t getClientFrameStatsNumCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netGetClientFrameStatsNum();
}
static uint8_t serverFrameStatsReadyCb(void *messager)
{
GetAPIMessager *msgr = (GetAPIMessager *) messager;
return msgr->netServerFrameStatsReady();
}
WebsocketListener::WebsocketListener(const struct sockaddr *listenaddr, WebsocketListener::WebsocketListener(const struct sockaddr *listenaddr,
socklen_t listenaddrlen, socklen_t listenaddrlen,
bool sslonly, const char *cert, const char *certkey, bool sslonly, const char *cert, const char *certkey,
@@ -586,7 +503,7 @@ WebsocketListener::WebsocketListener(const struct sockaddr *listenaddr,
if (bind(sock, &sa.u.sa, listenaddrlen) == -1) { if (bind(sock, &sa.u.sa, listenaddrlen) == -1) {
int e = errorNumber; int e = errorNumber;
closesocket(sock); closesocket(sock);
throw SocketException("failed to bind socket, is someone else on our -websocketPort?", e); throw SocketException("failed to bind socket", e);
} }
listen(sock); // sets the internal fd listen(sock); // sets the internal fd
@@ -596,16 +513,13 @@ WebsocketListener::WebsocketListener(const struct sockaddr *listenaddr,
// //
internalSocket = socket(AF_UNIX, SOCK_STREAM, 0); internalSocket = socket(AF_UNIX, SOCK_STREAM, 0);
char sockname[32];
sprintf(sockname, ".KasmVNCSock%u", getpid());
struct sockaddr_un addr; struct sockaddr_un addr;
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, sockname); strcpy(addr.sun_path, ".KasmVNCSock");
addr.sun_path[0] = '\0'; addr.sun_path[0] = '\0';
if (bind(internalSocket, (struct sockaddr *) &addr, if (bind(internalSocket, (struct sockaddr *) &addr,
sizeof(sa_family_t) + strlen(sockname))) { sizeof(sa_family_t) + sizeof(".KasmVNCSock"))) {
throw SocketException("failed to bind socket", errorNumber); throw SocketException("failed to bind socket", errorNumber);
} }
@@ -633,22 +547,7 @@ WebsocketListener::WebsocketListener(const struct sockaddr *listenaddr,
settings.screenshotCb = screenshotCb; settings.screenshotCb = screenshotCb;
settings.adduserCb = adduserCb; settings.adduserCb = adduserCb;
settings.removeCb = removeCb; settings.removeCb = removeCb;
settings.updateUserCb = updateUserCb; settings.givecontrolCb = givecontrolCb;
settings.addOrUpdateUserCb = addOrUpdateUserCb;
settings.getUsersCb = getUsersCb;
settings.bottleneckStatsCb = bottleneckStatsCb;
settings.frameStatsCb = frameStatsCb;
settings.resetFrameStatsCb = resetFrameStatsCb;
settings.requestFrameStatsNoneCb = requestFrameStatsNoneCb;
settings.requestFrameStatsOwnerCb = requestFrameStatsOwnerCb;
settings.requestFrameStatsAllCb = requestFrameStatsAllCb;
settings.requestFrameStatsOneCb = requestFrameStatsOneCb;
settings.ownerConnectedCb = ownerConnectedCb;
settings.numActiveUsersCb = numActiveUsersCb;
settings.getClientFrameStatsNumCb = getClientFrameStatsNumCb;
settings.serverFrameStatsReadyCb = serverFrameStatsReadyCb;
pthread_t tid; pthread_t tid;
pthread_create(&tid, NULL, start_server, NULL); pthread_create(&tid, NULL, start_server, NULL);
@@ -931,8 +830,6 @@ void network::createWebsocketListeners(std::list<SocketListener*> *listeners,
freeaddrinfo(ai); freeaddrinfo(ai);
throw; throw;
} }
freeaddrinfo(ai);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,295 +0,0 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// 2fc55f6 from Jan 20, 2022
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 15
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,25 +0,0 @@
/* Copyright (C) 2022 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.
*/
#ifndef NETWORK_DATELOG_H
#define NETWORK_DATELOG_H
// 2022-05-18 19:51:26
#define DATELOGFMT "%Y-%m-%d %H:%M:%S"
#endif

View File

@@ -1,179 +0,0 @@
/* Copyright (C) 2022 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jsonescape.h"
#include "cJSON.h"
void JSON_escape(const char *in, char *out) {
for (; *in; in++) {
if (in[0] == '\b') {
*out++ = '\\';
*out++ = 'b';
} else if (in[0] == '\f') {
*out++ = '\\';
*out++ = 'f';
} else if (in[0] == '\n') {
*out++ = '\\';
*out++ = 'n';
} else if (in[0] == '\r') {
*out++ = '\\';
*out++ = 'r';
} else if (in[0] == '\t') {
*out++ = '\\';
*out++ = 't';
} else if (in[0] == '"') {
*out++ = '\\';
*out++ = '"';
} else if (in[0] == '\\') {
*out++ = '\\';
*out++ = '\\';
} else {
*out++ = *in;
}
}
*out = '\0';
}
void JSON_unescape(const char *in, char *out) {
for (; *in; in++) {
if (in[0] == '\\' && in[1] == 'b') {
*out++ = '\b';
in++;
} else if (in[0] == '\\' && in[1] == 'f') {
*out++ = '\f';
in++;
} else if (in[0] == '\\' && in[1] == 'n') {
*out++ = '\n';
in++;
} else if (in[0] == '\\' && in[1] == 'r') {
*out++ = '\r';
in++;
} else if (in[0] == '\\' && in[1] == 't') {
*out++ = '\t';
in++;
} else if (in[0] == '\\' && in[1] == '"') {
*out++ = '"';
in++;
} else if (in[0] == '\\' && in[1] == '\\') {
*out++ = '\\';
in++;
} else {
*out++ = *in;
}
}
*out = '\0';
}
struct kasmpasswd_t *parseJsonUsers(const char *data) {
cJSON *json = cJSON_Parse(data);
if (!json)
return NULL;
if (!(json->type & cJSON_Array))
return NULL;
struct kasmpasswd_t *set = calloc(sizeof(struct kasmpasswd_t), 1);
set->num = cJSON_GetArraySize(json);
set->entries = calloc(sizeof(struct kasmpasswd_entry_t), set->num);
cJSON *cur;
unsigned s, len;
for (cur = json->child, s = 0; cur; cur = cur->next, s++) {
if (!(cur->type & cJSON_Object))
goto fail;
cJSON *e;
struct kasmpasswd_entry_t * const entry = &set->entries[s];
entry->user[0] = '\0';
entry->password[0] = '\0';
entry->write = entry->owner = 0;
for (e = cur->child; e; e = e->next) {
#define field(x) if (!strcmp(x, e->string))
field("user") {
if (!(e->type & cJSON_String))
goto fail;
len = strlen(e->valuestring);
//printf("Val '%.*s'\n", len, start);
if (len >= USERNAME_LEN)
goto fail;
memcpy(entry->user, e->valuestring, len);
entry->user[len] = '\0';
} else field("password") {
if (!(e->type & cJSON_String))
goto fail;
len = strlen(e->valuestring);
//printf("Val '%.*s'\n", len, start);
if (len >= PASSWORD_LEN)
goto fail;
memcpy(entry->password, e->valuestring, len);
entry->password[len] = '\0';
} else field("write") {
if (!(e->type & (cJSON_False | cJSON_True)))
goto fail;
if (e->type & cJSON_True)
entry->write = 1;
} else field("owner") {
if (!(e->type & (cJSON_False | cJSON_True)))
goto fail;
if (e->type & cJSON_True)
entry->owner = 1;
} else field("read") {
if (!(e->type & (cJSON_False | cJSON_True)))
goto fail;
if (e->type & cJSON_True)
entry->read = 1;
} else {
//printf("Unknown field '%.*s'\n", len, start);
goto fail;
}
#undef field
}
}
cJSON_Delete(json);
return set;
fail:
free(set->entries);
free(set);
cJSON_Delete(json);
return NULL;
}

View File

@@ -1,38 +0,0 @@
/* Copyright (C) 2022 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.
*/
#ifndef __NETWORK_JSON_ESCAPE_H__
#define __NETWORK_JSON_ESCAPE_H__
#include <kasmpasswd.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void JSON_escape(const char *in, char *out);
void JSON_unescape(const char *in, char *out);
struct kasmpasswd_t *parseJsonUsers(const char *data);
#ifdef __cplusplus
} // extern C
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,5 @@
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <stdint.h> #include <stdint.h>
#include "GetAPIEnums.h"
#include "datelog.h"
#define BUFSIZE 65536 #define BUFSIZE 65536
#define DBUFSIZE (BUFSIZE * 3) / 4 - 20 #define DBUFSIZE (BUFSIZE * 3) / 4 - 20
@@ -67,8 +65,6 @@ struct wspass_t {
char ip[64]; char ip[64];
}; };
struct kasmpasswd_entry_t;
typedef struct { typedef struct {
int verbose; int verbose;
int listen_sock; int listen_sock;
@@ -85,26 +81,9 @@ typedef struct {
const uint8_t dedup, const uint8_t dedup,
uint32_t *len, uint8_t *staging); uint32_t *len, uint8_t *staging);
uint8_t (*adduserCb)(void *messager, const char name[], const char pw[], uint8_t (*adduserCb)(void *messager, const char name[], const char pw[],
const uint8_t read, const uint8_t write, const uint8_t owner); const uint8_t write);
uint8_t (*removeCb)(void *messager, const char name[]); uint8_t (*removeCb)(void *messager, const char name[]);
uint8_t (*updateUserCb)(void *messager, const char name[], const uint64_t mask, uint8_t (*givecontrolCb)(void *messager, const char name[]);
const char password[],
const uint8_t read, const uint8_t write, const uint8_t owner);
uint8_t (*addOrUpdateUserCb)(void *messager, const struct kasmpasswd_entry_t *entry);
void (*bottleneckStatsCb)(void *messager, char *buf, uint32_t len);
void (*frameStatsCb)(void *messager, char *buf, uint32_t len);
void (*resetFrameStatsCb)(void *messager);
uint8_t (*requestFrameStatsNoneCb)(void *messager);
uint8_t (*requestFrameStatsOwnerCb)(void *messager);
uint8_t (*requestFrameStatsAllCb)(void *messager);
uint8_t (*requestFrameStatsOneCb)(void *messager, const char *client);
uint8_t (*ownerConnectedCb)(void *messager);
uint8_t (*numActiveUsersCb)(void *messager);
void (*getUsersCb)(void *messager, const char **buf);
uint8_t (*getClientFrameStatsNumCb)(void *messager);
uint8_t (*serverFrameStatsReadyCb)(void *messager);
} settings_t; } settings_t;
#ifdef __cplusplus #ifdef __cplusplus
@@ -121,24 +100,18 @@ ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len);
//int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize); //int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
//int b64_pton(char const *src, u_char *target, size_t targsize); //int b64_pton(char const *src, u_char *target, size_t targsize);
void wslog(char *logbuf, const unsigned websocket, const uint8_t debug);
extern __thread unsigned wsthread_handler_id; extern __thread unsigned wsthread_handler_id;
#define gen_handler_msg(stream, ...) \ #define gen_handler_msg(stream, ...) \
if (settings.verbose) { \ if (settings.verbose) { \
char logbuf[2][1024]; \ fprintf(stream, " websocket %d: ", wsthread_handler_id); \
wslog(logbuf[0], wsthread_handler_id, 1); \ fprintf(stream, __VA_ARGS__); \
sprintf(logbuf[1], __VA_ARGS__); \
fprintf(stream, "%s%s", logbuf[0], logbuf[1]); \
} }
#define wserr(...) \ #define wserr(...) \
{ \ { \
char logbuf[2][1024]; \ fprintf(stderr, " websocket %d: ", wsthread_handler_id); \
wslog(logbuf[0], wsthread_handler_id, 0); \ fprintf(stderr, __VA_ARGS__); \
sprintf(logbuf[1], __VA_ARGS__); \
fprintf(stderr, "%s%s", logbuf[0], logbuf[1]); \
} }
#define handler_msg(...) gen_handler_msg(stderr, __VA_ARGS__); #define handler_msg(...) gen_handler_msg(stderr, __VA_ARGS__);

View File

@@ -21,7 +21,6 @@
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h>
#include "websocket.h" #include "websocket.h"
/* /*
@@ -44,11 +43,11 @@ static void do_proxy(ws_ctx_t *ws_ctx, int target) {
int maxfd, client = ws_ctx->sockfd; int maxfd, client = ws_ctx->sockfd;
unsigned int opcode, left, ret; unsigned int opcode, left, ret;
unsigned int tout_start, tout_end, cout_start, cout_end; unsigned int tout_start, tout_end, cout_start, cout_end;
unsigned int tin_end; unsigned int tin_start, tin_end;
ssize_t len, bytes; ssize_t len, bytes;
tout_start = tout_end = cout_start = cout_end = tout_start = tout_end = cout_start = cout_end =
tin_end = 0; tin_start = tin_end = 0;
maxfd = client > target ? client+1 : target+1; maxfd = client > target ? client+1 : target+1;
while (1) { while (1) {
@@ -165,7 +164,7 @@ static void do_proxy(ws_ctx_t *ws_ctx, int target) {
} }
if (FD_ISSET(client, &rlist)) { if (FD_ISSET(client, &rlist)) {
bytes = ws_recv(ws_ctx, ws_ctx->tin_buf + tin_end, BUFSIZE-1-tin_end); bytes = ws_recv(ws_ctx, ws_ctx->tin_buf + tin_end, BUFSIZE-1);
if (pipe_error) { break; } if (pipe_error) { break; }
if (bytes <= 0) { if (bytes <= 0) {
handler_emsg("client closed connection\n"); handler_emsg("client closed connection\n");
@@ -180,13 +179,13 @@ static void do_proxy(ws_ctx_t *ws_ctx, int target) {
printf("\n"); printf("\n");
*/ */
if (ws_ctx->hybi) { if (ws_ctx->hybi) {
len = decode_hybi(ws_ctx->tin_buf, len = decode_hybi(ws_ctx->tin_buf + tin_start,
tin_end, tin_end-tin_start,
ws_ctx->tout_buf, BUFSIZE-1, ws_ctx->tout_buf, BUFSIZE-1,
&opcode, &left); &opcode, &left);
} else { } else {
len = decode_hixie(ws_ctx->tin_buf, len = decode_hixie(ws_ctx->tin_buf + tin_start,
tin_end, tin_end-tin_start,
ws_ctx->tout_buf, BUFSIZE-1, ws_ctx->tout_buf, BUFSIZE-1,
&opcode, &left); &opcode, &left);
} }
@@ -208,13 +207,10 @@ static void do_proxy(ws_ctx_t *ws_ctx, int target) {
break; break;
} }
if (left) { if (left) {
const unsigned tin_start = tin_end - left; tin_start = tin_end - left;
//handler_emsg("partial frame from client, %u left, start %u end %u, lens %lu %lu\n", //printf("partial frame from client");
// left, tin_start, tin_end, bytes, len);
memmove(ws_ctx->tin_buf, ws_ctx->tin_buf + tin_start, left);
tin_end = left;
} else { } else {
//handler_emsg("handled %lu/%lu bytes\n", bytes, len); tin_start = 0;
tin_end = 0; tin_end = 0;
} }
@@ -227,12 +223,9 @@ static void do_proxy(ws_ctx_t *ws_ctx, int target) {
void proxy_handler(ws_ctx_t *ws_ctx) { void proxy_handler(ws_ctx_t *ws_ctx) {
char sockname[32];
sprintf(sockname, ".KasmVNCSock%u", getpid());
struct sockaddr_un addr; struct sockaddr_un addr;
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, sockname); strcpy(addr.sun_path, ".KasmVNCSock");
addr.sun_path[0] = '\0'; addr.sun_path[0] = '\0';
struct timeval tv; struct timeval tv;
@@ -250,7 +243,7 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
handler_msg("connecting to VNC target\n"); handler_msg("connecting to VNC target\n");
if (connect(tsock, (struct sockaddr *) &addr, if (connect(tsock, (struct sockaddr *) &addr,
sizeof(sa_family_t) + strlen(sockname)) < 0) { sizeof(sa_family_t) + sizeof(".KasmVNCSock")) < 0) {
handler_emsg("Could not connect to target: %s\n", handler_emsg("Could not connect to target: %s\n",
strerror(errno)); strerror(errno));

View File

@@ -48,7 +48,6 @@ set(RFB_SOURCES
Security.cxx Security.cxx
SecurityServer.cxx SecurityServer.cxx
SecurityClient.cxx SecurityClient.cxx
SelfBench.cxx
SSecurityPlain.cxx SSecurityPlain.cxx
SSecurityStack.cxx SSecurityStack.cxx
SSecurityVncAuth.cxx SSecurityVncAuth.cxx
@@ -64,7 +63,6 @@ set(RFB_SOURCES
VNCServerST.cxx VNCServerST.cxx
ZRLEEncoder.cxx ZRLEEncoder.cxx
ZRLEDecoder.cxx ZRLEDecoder.cxx
cpuid.cxx
encodings.cxx encodings.cxx
util.cxx util.cxx
xxhash.c) xxhash.c)
@@ -98,27 +96,6 @@ if(GNUTLS_FOUND)
) )
endif() endif()
# SSE2
set(SSE2_SOURCES
scale_sse2.cxx)
set(SCALE_DUMMY_SOURCES
scale_dummy.cxx)
if(COMPILER_SUPPORTS_SSE2)
set_source_files_properties(${SSE2_SOURCES} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} -msse2)
set(RFB_SOURCES
${RFB_SOURCES}
${SSE2_SOURCES}
)
else()
set(RFB_SOURCES
${RFB_SOURCES}
${SCALE_DUMMY_SOURCES}
)
endif()
add_library(rfb STATIC ${RFB_SOURCES}) add_library(rfb STATIC ${RFB_SOURCES})
target_link_libraries(rfb ${RFB_LIBRARIES}) target_link_libraries(rfb ${RFB_LIBRARIES})

View File

@@ -695,8 +695,6 @@ bool ComparingUpdateTracker::compare(bool skipScrollDetection, const Region &ski
std::vector<Rect> rects; std::vector<Rect> rects;
std::vector<Rect>::iterator i; std::vector<Rect>::iterator i;
changedPerc = 100;
if (!enabled) if (!enabled)
return false; return false;
@@ -751,13 +749,8 @@ bool ComparingUpdateTracker::compare(bool skipScrollDetection, const Region &ski
for (i = rects.begin(); i != rects.end(); i++) for (i = rects.begin(); i != rects.end(); i++)
totalPixels += i->area(); totalPixels += i->area();
newChanged.get_rects(&rects); newChanged.get_rects(&rects);
unsigned newchangedarea = 0; for (i = rects.begin(); i != rects.end(); i++)
for (i = rects.begin(); i != rects.end(); i++) {
missedPixels += i->area(); missedPixels += i->area();
newchangedarea += i->area();
}
changedPerc = newchangedarea * 100 / fb->area();
if (changed.equals(newChanged)) if (changed.equals(newChanged))
return false; return false;

View File

@@ -48,8 +48,6 @@ namespace rfb {
virtual void getUpdateInfo(UpdateInfo* info, const Region& cliprgn); virtual void getUpdateInfo(UpdateInfo* info, const Region& cliprgn);
virtual void clear(); virtual void clear();
rdr::U8 changedPerc;
private: private:
void compareRect(const Rect& r, Region* newchanged, const Region &skipCursorArea); void compareRect(const Rect& r, Region* newchanged, const Region &skipCursorArea);
PixelBuffer* fb; PixelBuffer* fb;

View File

@@ -298,11 +298,6 @@ size_t Congestion::getBandwidth()
return congWindow * 1000 / safeBaseRTT; return congWindow * 1000 / safeBaseRTT;
} }
unsigned Congestion::getPingTime() const
{
return safeBaseRTT;
}
void Congestion::debugTrace(const char* filename, int fd) void Congestion::debugTrace(const char* filename, int fd)
{ {
#ifdef CONGESTION_TRACE #ifdef CONGESTION_TRACE

View File

@@ -51,8 +51,6 @@ namespace rfb {
// per second. // per second.
size_t getBandwidth(); size_t getBandwidth();
unsigned getPingTime() const;
// debugTrace() writes the current congestion window, as well as the // debugTrace() writes the current congestion window, as well as the
// congestion window of the underlying TCP layer, to the specified // congestion window of the underlying TCP layer, to the specified
// file // file

View File

@@ -37,7 +37,6 @@ ConnParams::ConnParams()
width(0), height(0), useCopyRect(false), width(0), height(0), useCopyRect(false),
supportsLocalCursor(false), supportsLocalXCursor(false), supportsLocalCursor(false), supportsLocalXCursor(false),
supportsLocalCursorWithAlpha(false), supportsLocalCursorWithAlpha(false),
supportsVMWareCursor(false),
supportsCursorPosition(false), supportsCursorPosition(false),
supportsDesktopResize(false), supportsExtendedDesktopSize(false), supportsDesktopResize(false), supportsExtendedDesktopSize(false),
supportsDesktopRename(false), supportsLastRect(false), supportsDesktopRename(false), supportsLastRect(false),
@@ -124,7 +123,6 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
useCopyRect = false; useCopyRect = false;
supportsLocalCursor = false; supportsLocalCursor = false;
supportsLocalCursorWithAlpha = false; supportsLocalCursorWithAlpha = false;
supportsVMWareCursor = false;
supportsDesktopResize = false; supportsDesktopResize = false;
supportsExtendedDesktopSize = false; supportsExtendedDesktopSize = false;
supportsLocalXCursor = false; supportsLocalXCursor = false;
@@ -155,9 +153,6 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
case pseudoEncodingCursorWithAlpha: case pseudoEncodingCursorWithAlpha:
supportsLocalCursorWithAlpha = true; supportsLocalCursorWithAlpha = true;
break; break;
case pseudoEncodingVMwareCursor:
supportsVMWareCursor = true;
break;
case pseudoEncodingDesktopSize: case pseudoEncodingDesktopSize:
supportsDesktopResize = true; supportsDesktopResize = true;
break; break;

View File

@@ -102,7 +102,6 @@ namespace rfb {
bool supportsLocalCursor; bool supportsLocalCursor;
bool supportsLocalXCursor; bool supportsLocalXCursor;
bool supportsLocalCursorWithAlpha; bool supportsLocalCursorWithAlpha;
bool supportsVMWareCursor;
bool supportsCursorPosition; bool supportsCursorPosition;
bool supportsDesktopResize; bool supportsDesktopResize;
bool supportsExtendedDesktopSize; bool supportsExtendedDesktopSize;

View File

@@ -22,12 +22,10 @@
#include <omp.h> #include <omp.h>
#include <stdlib.h> #include <stdlib.h>
#include <rfb/cpuid.h>
#include <rfb/EncCache.h> #include <rfb/EncCache.h>
#include <rfb/EncodeManager.h> #include <rfb/EncodeManager.h>
#include <rfb/Encoder.h> #include <rfb/Encoder.h>
#include <rfb/Palette.h> #include <rfb/Palette.h>
#include <rfb/scale_sse2.h>
#include <rfb/SConnection.h> #include <rfb/SConnection.h>
#include <rfb/ServerCore.h> #include <rfb/ServerCore.h>
#include <rfb/SMsgWriter.h> #include <rfb/SMsgWriter.h>
@@ -361,8 +359,6 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
changed = changed_; changed = changed_;
gettimeofday(&start, NULL); gettimeofday(&start, NULL);
memset(&jpegstats, 0, sizeof(codecstats_t));
memset(&webpstats, 0, sizeof(codecstats_t));
if (allowLossy && activeEncoders[encoderFullColour] == encoderTightWEBP) { if (allowLossy && activeEncoders[encoderFullColour] == encoderTightWEBP) {
const unsigned rate = 1024 * 1000 / rfb::Server::frameRate; const unsigned rate = 1024 * 1000 / rfb::Server::frameRate;
@@ -897,7 +893,7 @@ void EncodeManager::updateVideoStats(const std::vector<Rect> &rects, const Pixel
} }
} }
PixelBuffer *rfb::nearestScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, static PixelBuffer *nearestScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h,
const float diff) const float diff)
{ {
ManagedPixelBuffer *newpb = new ManagedPixelBuffer(pb->getPF(), w, h); ManagedPixelBuffer *newpb = new ManagedPixelBuffer(pb->getPF(), w, h);
@@ -922,7 +918,7 @@ PixelBuffer *rfb::nearestScale(const PixelBuffer *pb, const uint16_t w, const ui
return newpb; return newpb;
} }
PixelBuffer *rfb::bilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, static PixelBuffer *bilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h,
const float diff) const float diff)
{ {
ManagedPixelBuffer *newpb = new ManagedPixelBuffer(pb->getPF(), w, h); ManagedPixelBuffer *newpb = new ManagedPixelBuffer(pb->getPF(), w, h);
@@ -970,68 +966,10 @@ PixelBuffer *rfb::bilinearScale(const PixelBuffer *pb, const uint16_t w, const u
return newpb; return newpb;
} }
PixelBuffer *rfb::progressiveBilinearScale(const PixelBuffer *pb, PixelBuffer *progressiveBilinearScale(const PixelBuffer *pb,
const uint16_t tgtw, const uint16_t tgth, const uint16_t tgtw, const uint16_t tgth,
const float tgtdiff) const float tgtdiff)
{ {
if (supportsSSE2()) {
if (tgtdiff >= 0.5f) {
ManagedPixelBuffer *newpb = new ManagedPixelBuffer(pb->getPF(), tgtw, tgth);
int oldstride, newstride;
const rdr::U8 *oldpx = pb->getBuffer(pb->getRect(), &oldstride);
rdr::U8 *newpx = newpb->getBufferRW(newpb->getRect(), &newstride);
SSE2_scale(oldpx, tgtw, tgth, newpx, oldstride, newstride, tgtdiff);
return newpb;
}
PixelBuffer *newpb;
uint16_t neww, newh, oldw, oldh;
bool del = false;
do {
oldw = pb->getRect().width();
oldh = pb->getRect().height();
neww = oldw / 2;
newh = oldh / 2;
newpb = new ManagedPixelBuffer(pb->getPF(), neww, newh);
int oldstride, newstride;
const rdr::U8 *oldpx = pb->getBuffer(pb->getRect(), &oldstride);
rdr::U8 *newpx = ((ManagedPixelBuffer *) newpb)->getBufferRW(newpb->getRect(),
&newstride);
SSE2_halve(oldpx, neww, newh, newpx, oldstride, newstride);
if (del)
delete pb;
del = true;
pb = newpb;
} while (tgtw * 2 < neww);
// Final, non-halving step
if (tgtw != neww || tgth != newh) {
oldw = pb->getRect().width();
oldh = pb->getRect().height();
newpb = new ManagedPixelBuffer(pb->getPF(), tgtw, tgth);
int oldstride, newstride;
const rdr::U8 *oldpx = pb->getBuffer(pb->getRect(), &oldstride);
rdr::U8 *newpx = ((ManagedPixelBuffer *) newpb)->getBufferRW(newpb->getRect(),
&newstride);
SSE2_scale(oldpx, tgtw, tgth, newpx, oldstride, newstride, tgtw / (float) oldw);
if (del)
delete pb;
}
return newpb;
} // SSE2
if (tgtdiff >= 0.5f) if (tgtdiff >= 0.5f)
return bilinearScale(pb, tgtw, tgth, tgtdiff); return bilinearScale(pb, tgtw, tgth, tgtdiff);
@@ -1076,7 +1014,6 @@ void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb,
std::vector<uint8_t> isWebp, fromCache; std::vector<uint8_t> isWebp, fromCache;
std::vector<Palette> palettes; std::vector<Palette> palettes;
std::vector<std::vector<uint8_t> > compresseds; std::vector<std::vector<uint8_t> > compresseds;
std::vector<uint32_t> ms;
uint32_t i; uint32_t i;
if (rfb::Server::rectThreads > 0) if (rfb::Server::rectThreads > 0)
@@ -1141,13 +1078,9 @@ void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb,
palettes.resize(subrects.size()); palettes.resize(subrects.size());
compresseds.resize(subrects.size()); compresseds.resize(subrects.size());
scaledrects.resize(subrects.size()); scaledrects.resize(subrects.size());
ms.resize(subrects.size());
// In case the current resolution is above the max video res, and video was detected, // In case the current resolution is above the max video res, and video was detected,
// scale to that res, keeping aspect ratio // scale to that res, keeping aspect ratio
struct timeval scalestart;
gettimeofday(&scalestart, NULL);
const PixelBuffer *scaledpb = NULL; const PixelBuffer *scaledpb = NULL;
if (videoDetected && if (videoDetected &&
(maxVideoX < pb->getRect().width() || maxVideoY < pb->getRect().height())) { (maxVideoX < pb->getRect().width() || maxVideoY < pb->getRect().height())) {
@@ -1196,25 +1129,15 @@ void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb,
} }
} }
} }
scalingTime = msSince(&scalestart);
#pragma omp parallel for schedule(dynamic, 1) #pragma omp parallel for schedule(dynamic, 1)
for (i = 0; i < subrects.size(); ++i) { for (i = 0; i < subrects.size(); ++i) {
encoderTypes[i] = getEncoderType(subrects[i], pb, &palettes[i], compresseds[i], encoderTypes[i] = getEncoderType(subrects[i], pb, &palettes[i], compresseds[i],
&isWebp[i], &fromCache[i], &isWebp[i], &fromCache[i],
scaledpb, scaledrects[i], ms[i]); scaledpb, scaledrects[i]);
checkWebpFallback(start); checkWebpFallback(start);
} }
for (i = 0; i < subrects.size(); ++i) {
if (encoderTypes[i] == encoderFullColour) {
if (isWebp[i])
webpstats.ms += ms[i];
else
jpegstats.ms += ms[i];
}
}
if (start) { if (start) {
encodingTime = msSince(start); encodingTime = msSince(start);
@@ -1255,8 +1178,7 @@ void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb,
uint8_t EncodeManager::getEncoderType(const Rect& rect, const PixelBuffer *pb, uint8_t EncodeManager::getEncoderType(const Rect& rect, const PixelBuffer *pb,
Palette *pal, std::vector<uint8_t> &compressed, Palette *pal, std::vector<uint8_t> &compressed,
uint8_t *isWebp, uint8_t *fromCache, uint8_t *isWebp, uint8_t *fromCache,
const PixelBuffer *scaledpb, const Rect& scaledrect, const PixelBuffer *scaledpb, const Rect& scaledrect) const
uint32_t &ms) const
{ {
struct RectInfo info; struct RectInfo info;
unsigned int maxColours = 256; unsigned int maxColours = 256;
@@ -1309,12 +1231,9 @@ uint8_t EncodeManager::getEncoderType(const Rect& rect, const PixelBuffer *pb,
*isWebp = 0; *isWebp = 0;
*fromCache = 0; *fromCache = 0;
ms = 0;
if (type == encoderFullColour) { if (type == encoderFullColour) {
uint32_t len; uint32_t len;
const void *data; const void *data;
struct timeval start;
gettimeofday(&start, NULL);
if (encCache->enabled && if (encCache->enabled &&
(data = encCache->get(activeEncoders[encoderFullColour], (data = encCache->get(activeEncoders[encoderFullColour],
@@ -1355,8 +1274,6 @@ uint8_t EncodeManager::getEncoderType(const Rect& rect, const PixelBuffer *pb,
compressed, compressed,
videoDetected); videoDetected);
} }
ms = msSince(&start);
} }
delete ppb; delete ppb;
@@ -1375,15 +1292,10 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb,
encoder = startRect(rect, type, compressed.size() == 0, isWebp); encoder = startRect(rect, type, compressed.size() == 0, isWebp);
if (compressed.size()) { if (compressed.size()) {
if (isWebp) { if (isWebp)
((TightWEBPEncoder *) encoder)->writeOnly(compressed); ((TightWEBPEncoder *) encoder)->writeOnly(compressed);
webpstats.area += rect.area(); else
webpstats.rects++;
} else {
((TightJPEGEncoder *) encoder)->writeOnly(compressed); ((TightJPEGEncoder *) encoder)->writeOnly(compressed);
jpegstats.area += rect.area();
jpegstats.rects++;
}
} else { } else {
if (encoder->flags & EncoderUseNativePF) { if (encoder->flags & EncoderUseNativePF) {
ppb = preparePixelBuffer(rect, pb, false); ppb = preparePixelBuffer(rect, pb, false);

View File

@@ -68,24 +68,9 @@ namespace rfb {
const RenderedCursor* renderedCursor, const RenderedCursor* renderedCursor,
size_t maxUpdateSize); size_t maxUpdateSize);
void clearEncodingTime() {
encodingTime = 0;
};
unsigned getEncodingTime() const { unsigned getEncodingTime() const {
return encodingTime; return encodingTime;
}; };
unsigned getScalingTime() const {
return scalingTime;
};
struct codecstats_t {
uint32_t ms;
uint32_t area;
uint32_t rects;
};
codecstats_t jpegstats, webpstats;
protected: protected:
void doUpdate(bool allowLossy, const Region& changed, void doUpdate(bool allowLossy, const Region& changed,
@@ -120,8 +105,7 @@ namespace rfb {
uint8_t getEncoderType(const Rect& rect, const PixelBuffer *pb, Palette *pal, uint8_t getEncoderType(const Rect& rect, const PixelBuffer *pb, Palette *pal,
std::vector<uint8_t> &compressed, uint8_t *isWebp, std::vector<uint8_t> &compressed, uint8_t *isWebp,
uint8_t *fromCache, uint8_t *fromCache,
const PixelBuffer *scaledpb, const Rect& scaledrect, const PixelBuffer *scaledpb, const Rect& scaledrect) const;
uint32_t &ms) const;
virtual bool handleTimeout(Timer* t); virtual bool handleTimeout(Timer* t);
bool checkSolidTile(const Rect& r, const rdr::U8* colourValue, bool checkSolidTile(const Rect& r, const rdr::U8* colourValue,
@@ -199,7 +183,6 @@ namespace rfb {
bool webpTookTooLong; bool webpTookTooLong;
unsigned encodingTime; unsigned encodingTime;
unsigned maxEncodingTime, framesSinceEncPrint; unsigned maxEncodingTime, framesSinceEncPrint;
unsigned scalingTime;
EncCache *encCache; EncCache *encCache;
@@ -215,13 +198,6 @@ namespace rfb {
virtual rdr::U8* getBufferRW(const Rect& r, int* stride); virtual rdr::U8* getBufferRW(const Rect& r, int* stride);
}; };
}; };
PixelBuffer *nearestScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h,
const float diff);
PixelBuffer *bilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h,
const float diff);
PixelBuffer *progressiveBilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h,
const float diff);
} }
#endif #endif

View File

@@ -36,12 +36,9 @@ namespace rfb {
rdr::U32 __unused_attr keycode, rdr::U32 __unused_attr keycode,
bool __unused_attr down) { } bool __unused_attr down) { }
virtual void pointerEvent(const Point& __unused_attr pos, virtual void pointerEvent(const Point& __unused_attr pos,
const Point& __unused_attr abspos,
int __unused_attr buttonMask, int __unused_attr buttonMask,
const bool __unused_attr skipClick, const bool __unused_attr skipClick,
const bool __unused_attr skipRelease, const bool __unused_attr skipRelease) { }
int scrollX,
int scrollY) { }
virtual void clientCutText(const char* __unused_attr str, virtual void clientCutText(const char* __unused_attr str,
int __unused_attr len) { } int __unused_attr len) { }
}; };

View File

@@ -20,14 +20,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/time.h>
#include <os/Mutex.h> #include <os/Mutex.h>
#include <network/datelog.h>
#include <rfb/util.h> #include <rfb/util.h>
#include <rfb/Logger_file.h> #include <rfb/Logger_file.h>
#include <rfb/LogWriter.h>
using namespace rfb; using namespace rfb;
@@ -58,28 +55,14 @@ void Logger_File::write(int level, const char *logname, const char *message)
if (!m_file) return; if (!m_file) return;
} }
struct timeval tv; time_t current = time(0);
gettimeofday(&tv, NULL); if (current != m_lastLogTime) {
m_lastLogTime = current;
if (tv.tv_sec != m_lastLogTime) {
m_lastLogTime = tv.tv_sec;
// fprintf(m_file, "\n%s", ctime(&m_lastLogTime)); // fprintf(m_file, "\n%s", ctime(&m_lastLogTime));
} }
char timebuf[128]; fprintf(m_file," %s:", logname);
struct tm local; int column = strlen(logname) + 2;
localtime_r(&tv.tv_sec, &local);
strftime(timebuf, sizeof(timebuf), DATELOGFMT, &local);
const unsigned msec = tv.tv_usec / 1000;
const char *levelname = "PRIO";
if (level >= LogWriter::LEVEL_INFO)
levelname = "INFO";
if (level >= LogWriter::LEVEL_DEBUG)
levelname = "DEBUG";
int column = fprintf(m_file, " %s,%03u [%s] %s:", timebuf, msec, levelname, logname);
if (column < indent) { if (column < indent) {
fprintf(m_file,"%*s",indent-column,""); fprintf(m_file,"%*s",indent-column,"");
column = indent; column = indent;

View File

@@ -216,7 +216,7 @@ void SConnection::processSecurityMsg()
bool done = ssecurity->processMsg(this); bool done = ssecurity->processMsg(this);
if (done) { if (done) {
state_ = RFBSTATE_QUERYING; state_ = RFBSTATE_QUERYING;
//setAccessRights(ssecurity->getAccessRights()); setAccessRights(ssecurity->getAccessRights());
queryConnection(ssecurity->getUserName()); queryConnection(ssecurity->getUserName());
} }
} catch (AuthFailureException& e) { } catch (AuthFailureException& e) {
@@ -284,28 +284,74 @@ void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings)
} }
SMsgHandler::setEncodings(nEncodings, encodings); SMsgHandler::setEncodings(nEncodings, encodings);
if (cp.supportsExtendedClipboard) {
rdr::U32 sizes[] = { 0 };
writer()->writeClipboardCaps(rfb::clipboardUTF8 |
rfb::clipboardRequest |
rfb::clipboardPeek |
rfb::clipboardNotify |
rfb::clipboardProvide,
sizes);
}
} }
void SConnection::clearBinaryClipboard() void SConnection::clientCutText(const char* str, int len)
{ {
binaryClipboard.clear(); hasLocalClipboard = false;
strFree(clientClipboard);
clientClipboard = NULL;
clientClipboard = latin1ToUTF8(str);
handleClipboardAnnounce(true);
} }
void SConnection::addBinaryClipboard(const char mime[], const rdr::U8 *data, void SConnection::handleClipboardRequest(rdr::U32 flags)
const rdr::U32 len, const rdr::U32 id)
{ {
binaryClipboard_t bin; if (!(flags & rfb::clipboardUTF8))
strncpy(bin.mime, mime, sizeof(bin.mime)); return;
bin.mime[sizeof(bin.mime) - 1] = '\0'; if (!hasLocalClipboard)
return;
bin.data.resize(len); handleClipboardRequest();
memcpy(&bin.data[0], data, len);
bin.id = id;
binaryClipboard.push_back(bin);
} }
void SConnection::handleClipboardPeek(rdr::U32 flags)
{
if (!hasLocalClipboard)
return;
if (cp.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(rfb::clipboardUTF8);
}
void SConnection::handleClipboardNotify(rdr::U32 flags)
{
strFree(clientClipboard);
clientClipboard = NULL;
if (flags & rfb::clipboardUTF8) {
handleClipboardAnnounce(true);
hasLocalClipboard = false;
} else {
handleClipboardAnnounce(false);
}
}
void SConnection::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
if (!(flags & rfb::clipboardUTF8))
return;
strFree(clientClipboard);
clientClipboard = NULL;
clientClipboard = convertLF((const char*)data[0], lengths[0]);
handleClipboardData(clientClipboard, strlen(clientClipboard));
}
void SConnection::supportsQEMUKeyEvent() void SConnection::supportsQEMUKeyEvent()
{ {
@@ -399,13 +445,56 @@ void SConnection::enableContinuousUpdates(bool enable,
{ {
} }
void SConnection::handleClipboardRequest()
{
}
void SConnection::handleClipboardAnnounce(bool available) void SConnection::handleClipboardAnnounce(bool available)
{ {
} }
void SConnection::handleClipboardData(const char* data, int len)
{
}
void SConnection::requestClipboard()
{
if (clientClipboard != NULL) {
handleClipboardData(clientClipboard, strlen(clientClipboard));
return;
}
if (cp.supportsExtendedClipboard &&
(cp.clipboardFlags() & rfb::clipboardRequest))
writer()->writeClipboardRequest(rfb::clipboardUTF8);
}
void SConnection::announceClipboard(bool available) void SConnection::announceClipboard(bool available)
{ {
hasLocalClipboard = available; hasLocalClipboard = available;
if (cp.supportsExtendedClipboard &&
(cp.clipboardFlags() & rfb::clipboardNotify))
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
else {
if (available)
handleClipboardRequest();
}
}
void SConnection::sendClipboardData(const char* data, int len)
{
if (cp.supportsExtendedClipboard &&
(cp.clipboardFlags() & rfb::clipboardProvide)) {
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));
writer()->writeServerCutText(latin1.buf, strlen(latin1.buf));
}
} }
void SConnection::writeFakeColourMap(void) void SConnection::writeFakeColourMap(void)

View File

@@ -28,7 +28,6 @@
#include <rdr/OutStream.h> #include <rdr/OutStream.h>
#include <rfb/SMsgHandler.h> #include <rfb/SMsgHandler.h>
#include <rfb/SecurityServer.h> #include <rfb/SecurityServer.h>
#include <vector>
namespace rfb { namespace rfb {
@@ -74,9 +73,14 @@ namespace rfb {
virtual void setEncodings(int nEncodings, const rdr::S32* encodings); virtual void setEncodings(int nEncodings, const rdr::S32* encodings);
virtual void clearBinaryClipboard(); virtual void clientCutText(const char* str, int len);
virtual void addBinaryClipboard(const char mime[], const rdr::U8 *data,
const rdr::U32 len, const rdr::U32 id); virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);
virtual void supportsQEMUKeyEvent(); virtual void supportsQEMUKeyEvent();
@@ -123,11 +127,25 @@ namespace rfb {
virtual void enableContinuousUpdates(bool enable, virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h); int x, int y, int w, int h);
// handleClipboardRequest() is called whenever the client requests
// the server to send over its clipboard data. It will only be
// called after the server has first announced a clipboard change
// via announceClipboard().
virtual void handleClipboardRequest();
// handleClipboardAnnounce() is called to indicate a change in the // handleClipboardAnnounce() is called to indicate a change in the
// clipboard on the client. Call requestClipboard() to access the // clipboard on the client. Call requestClipboard() to access the
// actual data. // actual data.
virtual void handleClipboardAnnounce(bool available); virtual void handleClipboardAnnounce(bool available);
// handleClipboardData() is called when the client has sent over
// the clipboard data as a result of a previous call to
// requestClipboard(). Note that this function might never be
// called if the clipboard data was no longer available when the
// client received the request.
virtual void handleClipboardData(const char* data, int len);
virtual void add_changed_all() {} virtual void add_changed_all() {}
// setAccessRights() allows a security package to limit the access rights // setAccessRights() allows a security package to limit the access rights
@@ -144,14 +162,26 @@ namespace rfb {
static const AccessRights AccessDefault; // The default rights, INCLUDING FUTURE ONES static const AccessRights AccessDefault; // The default rights, INCLUDING FUTURE ONES
static const AccessRights AccessNoQuery; // Connect without local user accepting static const AccessRights AccessNoQuery; // Connect without local user accepting
static const AccessRights AccessFull; // All of the available AND FUTURE rights static const AccessRights AccessFull; // All of the available AND FUTURE rights
virtual void setAccessRights(AccessRights ar) = 0;
// Other methods // Other methods
// requestClipboard() will result in a request to the client to
// transfer its clipboard data. A call to handleClipboardData()
// will be made once the data is available.
virtual void requestClipboard();
// announceClipboard() informs the client of changes to the // announceClipboard() informs the client of changes to the
// clipboard on the server. The client may later request the // clipboard on the server. The client may later request the
// clipboard data via handleClipboardRequest(). // clipboard data via handleClipboardRequest().
virtual void announceClipboard(bool available); virtual void announceClipboard(bool available);
// sendClipboardData() transfers the clipboard data to the client
// and should be called whenever the client has requested the
// clipboard via handleClipboardRequest().
virtual void sendClipboardData(const char* data, int len);
// authenticated() returns true if the client has authenticated // authenticated() returns true if the client has authenticated
// successfully. // successfully.
bool authenticated() { return (state_ == RFBSTATE_INITIALISATION || bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
@@ -191,20 +221,12 @@ namespace rfb {
rdr::S32 getPreferredEncoding() { return preferredEncoding; } rdr::S32 getPreferredEncoding() { return preferredEncoding; }
struct binaryClipboard_t {
char mime[32];
rdr::U32 id;
std::vector<unsigned char> data;
};
protected: protected:
void setState(stateEnum s) { state_ = s; } void setState(stateEnum s) { state_ = s; }
void setReader(SMsgReader *r) { reader_ = r; } void setReader(SMsgReader *r) { reader_ = r; }
void setWriter(SMsgWriter *w) { writer_ = w; } void setWriter(SMsgWriter *w) { writer_ = w; }
std::vector<binaryClipboard_t> binaryClipboard;
private: private:
void writeFakeColourMap(void); void writeFakeColourMap(void);

View File

@@ -78,13 +78,23 @@ namespace rfb {
// the relevant RFB protocol messages from clients. // the relevant RFB protocol messages from clients.
// See InputHandler for method signatures. // See InputHandler for method signatures.
// handleClipboardRequest() is called whenever a client requests
// the server to send over its clipboard data. It will only be
// called after the server has first announced a clipboard change
// via VNCServer::announceClipboard().
virtual void handleClipboardRequest() {}
// handleClipboardAnnounce() is called to indicate a change in the // handleClipboardAnnounce() is called to indicate a change in the
// clipboard on a client. Call VNCServer::requestClipboard() to // clipboard on a client. Call VNCServer::requestClipboard() to
// access the actual data. // access the actual data.
virtual void handleClipboardAnnounce(bool __unused_attr available) {} virtual void handleClipboardAnnounce(bool __unused_attr available) {}
virtual void handleClipboardAnnounceBinary(const unsigned __unused_attr num, // handleClipboardData() is called when a client has sent over
const char __unused_attr mimes[][32]) {} // the clipboard data as a result of a previous call to
// VNCServer::requestClipboard(). Note that this function might
// never be called if the clipboard data was no longer available
// when the client received the request.
virtual void handleClipboardData(const char* __unused_attr data, int len __unused_attr) {}
protected: protected:
virtual ~SDesktop() {} virtual ~SDesktop() {}

View File

@@ -64,16 +64,26 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
supportsQEMUKeyEvent(); supportsQEMUKeyEvent();
} }
void SMsgHandler::handleClipboardAnnounceBinary(const unsigned, const char mimes[][32]) void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
cp.setClipboardCaps(flags, lengths);
}
void SMsgHandler::handleClipboardRequest(rdr::U32 flags)
{ {
} }
void SMsgHandler::clearBinaryClipboard() void SMsgHandler::handleClipboardPeek(rdr::U32 flags)
{ {
} }
void SMsgHandler::addBinaryClipboard(const char mime[], const rdr::U8 *data, void SMsgHandler::handleClipboardNotify(rdr::U32 flags)
const rdr::U32 len, const rdr::U32 id) {
}
void SMsgHandler::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{ {
} }

View File

@@ -54,13 +54,16 @@ namespace rfb {
virtual void enableContinuousUpdates(bool enable, virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h) = 0; int x, int y, int w, int h) = 0;
virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]); virtual void handleClipboardCaps(rdr::U32 flags,
virtual void clearBinaryClipboard(); const rdr::U32* lengths);
virtual void addBinaryClipboard(const char mime[], const rdr::U8 *data, virtual void handleClipboardRequest(rdr::U32 flags);
const rdr::U32 len, const rdr::U32 id); virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);
virtual void sendStats(const bool toClient = true) = 0; virtual void sendStats() = 0;
virtual void handleFrameStats(rdr::U32 all, rdr::U32 render) = 0;
virtual bool canChangeKasmSettings() const = 0; virtual bool canChangeKasmSettings() const = 0;

View File

@@ -35,6 +35,8 @@ using namespace rfb;
static LogWriter vlog("SMsgReader"); static LogWriter vlog("SMsgReader");
static IntParameter maxCutText("MaxCutText", "Maximum permitted length of an incoming clipboard update", 256*1024);
SMsgReader::SMsgReader(SMsgHandler* handler_, rdr::InStream* is_) SMsgReader::SMsgReader(SMsgHandler* handler_, rdr::InStream* is_)
: handler(handler_), is(is_) : handler(handler_), is(is_)
{ {
@@ -78,12 +80,6 @@ void SMsgReader::readMsg()
case msgTypeRequestStats: case msgTypeRequestStats:
readRequestStats(); readRequestStats();
break; break;
case msgTypeFrameStats:
readFrameStats();
break;
case msgTypeBinaryClipboard:
readBinaryClipboard();
break;
case msgTypeKeyEvent: case msgTypeKeyEvent:
readKeyEvent(); readKeyEvent();
break; break;
@@ -224,10 +220,7 @@ void SMsgReader::readPointerEvent()
int mask = is->readU8(); int mask = is->readU8();
int x = is->readU16(); int x = is->readU16();
int y = is->readU16(); int y = is->readU16();
int scrollX = is->readS16(); handler->pointerEvent(Point(x, y), mask, false, false);
int scrollY = is->readS16();
handler->pointerEvent(Point(x, y), Point(0, 0), mask, false, false, scrollX, scrollY);
} }
@@ -242,54 +235,109 @@ void SMsgReader::readClientCutText()
readExtendedClipboard(slen); readExtendedClipboard(slen);
return; return;
} }
is->skip(len); if (len > (size_t)maxCutText) {
vlog.error("Client sent old cuttext msg, ignoring"); is->skip(len);
} vlog.error("Cut text too long (%d bytes) - ignoring", len);
return;
void SMsgReader::readBinaryClipboard()
{
const rdr::U8 num = is->readU8();
rdr::U8 i, valid = 0;
char tmpmimes[num][32];
handler->clearBinaryClipboard();
for (i = 0; i < num; i++) {
const rdr::U8 mimelen = is->readU8();
if (mimelen > 32 - 1) {
vlog.error("Mime too long (%u)", mimelen);
}
char mime[mimelen + 1];
mime[mimelen] = '\0';
is->readBytes(mime, mimelen);
strncpy(tmpmimes[valid], mime, 32);
tmpmimes[valid][31] = '\0';
const rdr::U32 len = is->readU32();
CharArray ca(len);
is->readBytes(ca.buf, len);
if (rfb::Server::DLP_ClipAcceptMax && len > (unsigned) rfb::Server::DLP_ClipAcceptMax) {
vlog.info("DLP: refused to receive binary clipboard, too large");
continue;
}
vlog.debug("Received binary clipboard, type %s, %u bytes", mime, len);
handler->addBinaryClipboard(mime, (rdr::U8 *) ca.buf, len, 0);
valid++;
} }
CharArray ca(len+1);
handler->handleClipboardAnnounceBinary(valid, tmpmimes); ca.buf[len] = 0;
is->readBytes(ca.buf, len);
handler->clientCutText(ca.buf, len);
} }
void SMsgReader::readExtendedClipboard(rdr::S32 len) void SMsgReader::readExtendedClipboard(rdr::S32 len)
{ {
rdr::U32 flags;
rdr::U32 action;
if (len < 4) if (len < 4)
throw Exception("Invalid extended clipboard message"); throw Exception("Invalid extended clipboard message");
vlog.error("Client sent old cuttext msg, ignoring"); if (len > maxCutText) {
is->skip(len); vlog.error("Extended clipboard message too long (%d bytes) - ignoring", len);
is->skip(len);
return;
}
flags = is->readU32();
action = flags & clipboardActionMask;
if (action & clipboardCaps) {
int i;
size_t num;
rdr::U32 lengths[16];
num = 0;
for (i = 0;i < 16;i++) {
if (flags & (1 << i))
num++;
}
if (len < (rdr::S32)(4 + 4*num))
throw Exception("Invalid extended clipboard message");
num = 0;
for (i = 0;i < 16;i++) {
if (flags & (1 << i))
lengths[num++] = is->readU32();
}
handler->handleClipboardCaps(flags, lengths);
} else if (action == clipboardProvide) {
rdr::ZlibInStream zis;
int i;
size_t num;
size_t lengths[16];
rdr::U8* buffers[16];
zis.setUnderlying(is, len - 4);
num = 0;
for (i = 0;i < 16;i++) {
if (!(flags & 1 << i))
continue;
lengths[num] = zis.readU32();
if (lengths[num] > (size_t)maxCutText) {
vlog.error("Extended clipboard data too long (%d bytes) - ignoring",
(unsigned)lengths[num]);
zis.skip(lengths[num]);
flags &= ~(1 << i);
continue;
}
buffers[num] = new rdr::U8[lengths[num]];
zis.readBytes(buffers[num], lengths[num]);
num++;
}
zis.flushUnderlying();
zis.setUnderlying(NULL, 0);
handler->handleClipboardProvide(flags, lengths, buffers);
num = 0;
for (i = 0;i < 16;i++) {
if (!(flags & 1 << i))
continue;
delete [] buffers[num++];
}
} else {
switch (action) {
case clipboardRequest:
handler->handleClipboardRequest(flags);
break;
case clipboardPeek:
handler->handleClipboardPeek(flags);
break;
case clipboardNotify:
handler->handleClipboardNotify(flags);
break;
default:
throw Exception("Invalid extended clipboard action");
}
}
} }
void SMsgReader::readRequestStats() void SMsgReader::readRequestStats()
@@ -298,14 +346,6 @@ void SMsgReader::readRequestStats()
handler->sendStats(); handler->sendStats();
} }
void SMsgReader::readFrameStats()
{
is->skip(3);
rdr::U32 all = is->readU32();
rdr::U32 render = is->readU32();
handler->handleFrameStats(all, render);
}
void SMsgReader::readQEMUMessage() void SMsgReader::readQEMUMessage()
{ {
int subType = is->readU8(); int subType = is->readU8();

View File

@@ -57,8 +57,6 @@ namespace rfb {
void readClientCutText(); void readClientCutText();
void readExtendedClipboard(rdr::S32 len); void readExtendedClipboard(rdr::S32 len);
void readRequestStats(); void readRequestStats();
void readFrameStats();
void readBinaryClipboard();
void readQEMUMessage(); void readQEMUMessage();
void readQEMUKeyEvent(); void readQEMUKeyEvent();

View File

@@ -43,7 +43,6 @@ SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
needSetDesktopSize(false), needExtendedDesktopSize(false), needSetDesktopSize(false), needExtendedDesktopSize(false),
needSetDesktopName(false), needSetCursor(false), needSetDesktopName(false), needSetCursor(false),
needSetXCursor(false), needSetCursorWithAlpha(false), needSetXCursor(false), needSetCursorWithAlpha(false),
needSetVMWareCursor(false),
needCursorPos(false), needCursorPos(false),
needLEDState(false), needQEMUKeyEvent(false) needLEDState(false), needQEMUKeyEvent(false)
{ {
@@ -85,24 +84,118 @@ void SMsgWriter::writeBell()
endMsg(); endMsg();
} }
void SMsgWriter::writeBinaryClipboard(const std::vector<SConnection::binaryClipboard_t> &b) void SMsgWriter::writeServerCutText(const char* str, int len)
{ {
startMsg(msgTypeBinaryClipboard); startMsg(msgTypeServerCutText);
os->pad(3);
os->writeU32(len);
os->writeBytes(str, len);
endMsg();
}
os->writeU8(b.size()); void SMsgWriter::writeClipboardCaps(rdr::U32 caps,
rdr::U8 i; const rdr::U32* lengths)
for (i = 0; i < b.size(); i++) { {
const rdr::U32 id = b[i].id; size_t i, count;
os->writeU32(id);
const rdr::U8 mimelen = strlen(b[i].mime); if (!cp->supportsExtendedClipboard)
os->writeU8(mimelen); throw Exception("Client does not support extended clipboard");
os->writeBytes(b[i].mime, mimelen);
os->writeU32(b[i].data.size()); count = 0;
os->writeBytes(&b[i].data[0], b[i].data.size()); for (i = 0;i < 16;i++) {
if (caps & (1 << i))
count++;
} }
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-(4 + 4 * count));
os->writeU32(caps | clipboardCaps);
count = 0;
for (i = 0;i < 16;i++) {
if (caps & (1 << i))
os->writeU32(lengths[count++]);
}
endMsg();
}
void SMsgWriter::writeClipboardRequest(rdr::U32 flags)
{
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardRequest))
throw Exception("Client does not support clipboard \"request\" action");
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardRequest);
endMsg();
}
void SMsgWriter::writeClipboardPeek(rdr::U32 flags)
{
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardPeek))
throw Exception("Client does not support clipboard \"peek\" action");
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardPeek);
endMsg();
}
void SMsgWriter::writeClipboardNotify(rdr::U32 flags)
{
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardNotify))
throw Exception("Client does not support clipboard \"notify\" action");
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardNotify);
endMsg();
}
void SMsgWriter::writeClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
rdr::MemOutStream mos;
rdr::ZlibOutStream zos;
int i, count;
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardProvide))
throw Exception("Client does not support clipboard \"provide\" action");
zos.setUnderlying(&mos);
count = 0;
for (i = 0;i < 16;i++) {
if (!(flags & (1 << i)))
continue;
zos.writeU32(lengths[count]);
zos.writeBytes(data[count], lengths[count]);
count++;
}
zos.flush();
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-(4 + mos.length()));
os->writeU32(flags | clipboardProvide);
os->writeBytes(mos.data(), mos.length());
endMsg(); endMsg();
} }
@@ -115,12 +208,6 @@ void SMsgWriter::writeStats(const char* str, int len)
endMsg(); endMsg();
} }
void SMsgWriter::writeRequestFrameStats()
{
startMsg(msgTypeRequestFrameStats);
endMsg();
}
void SMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[]) void SMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
{ {
if (!cp->supportsFence) if (!cp->supportsFence)
@@ -228,16 +315,6 @@ bool SMsgWriter::writeSetCursorWithAlpha()
return true; return true;
} }
bool SMsgWriter::writeSetVMwareCursor()
{
if (!cp->supportsVMWareCursor)
return false;
needSetVMWareCursor = true;
return true;
}
void SMsgWriter::writeCursorPos() void SMsgWriter::writeCursorPos()
{ {
if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition)) if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition))
@@ -272,7 +349,7 @@ bool SMsgWriter::needFakeUpdate()
{ {
if (needSetDesktopName) if (needSetDesktopName)
return true; return true;
if (needSetCursor || needSetXCursor || needSetCursorWithAlpha || needSetVMWareCursor) if (needSetCursor || needSetXCursor || needSetCursorWithAlpha)
return true; return true;
if (needCursorPos) if (needCursorPos)
return true; return true;
@@ -328,8 +405,6 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
nRects++; nRects++;
if (needSetCursorWithAlpha) if (needSetCursorWithAlpha)
nRects++; nRects++;
if (needSetVMWareCursor)
nRects++;
if (needCursorPos) if (needCursorPos)
nRects++; nRects++;
if (needLEDState) if (needLEDState)
@@ -447,15 +522,6 @@ void SMsgWriter::writePseudoRects()
needSetCursorWithAlpha = false; needSetCursorWithAlpha = false;
} }
if (needSetVMWareCursor) {
const Cursor& cursor = cp->cursor();
writeSetVMwareCursorRect(cursor.width(), cursor.height(),
cursor.hotspot().x, cursor.hotspot().y,
cursor.getBuffer());
needSetVMWareCursor = false;
}
if (needCursorPos) { if (needCursorPos) {
const Point& cursorPos = cp->cursorPos(); const Point& cursorPos = cp->cursorPos();
@@ -646,28 +712,6 @@ void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height,
} }
} }
void SMsgWriter::writeSetVMwareCursorRect(int width, int height,
int hotspotX, int hotspotY,
const rdr::U8* data)
{
if (!cp->supportsVMWareCursor)
throw Exception("Client does not support local cursors");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeSetVMwareCursorRect: nRects out of sync");
os->writeS16(hotspotX);
os->writeS16(hotspotY);
os->writeU16(width);
os->writeU16(height);
os->writeU32(pseudoEncodingVMwareCursor);
os->writeU8(1); // Alpha cursor
os->pad(1);
// FIXME: Should alpha be premultiplied?
os->writeBytes(data, width*height*4);
}
void SMsgWriter::writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY) void SMsgWriter::writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY)
{ {
if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition)) if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition))

View File

@@ -26,8 +26,6 @@
#include <rdr/types.h> #include <rdr/types.h>
#include <rfb/encodings.h> #include <rfb/encodings.h>
#include <rfb/ScreenSet.h> #include <rfb/ScreenSet.h>
#include <rfb/SConnection.h>
#include <vector>
namespace rdr { class OutStream; } namespace rdr { class OutStream; }
@@ -56,13 +54,17 @@ namespace rfb {
// writeBell() and writeServerCutText() do the obvious thing. // writeBell() and writeServerCutText() do the obvious thing.
void writeBell(); void writeBell();
void writeServerCutText(const char* str, int len);
void writeBinaryClipboard(const std::vector<SConnection::binaryClipboard_t> &b); void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths);
void writeClipboardRequest(rdr::U32 flags);
void writeClipboardPeek(rdr::U32 flags);
void writeClipboardNotify(rdr::U32 flags);
void writeClipboardProvide(rdr::U32 flags, const size_t* lengths,
const rdr::U8* const* data);
void writeStats(const char* str, int len); void writeStats(const char* str, int len);
void writeRequestFrameStats();
// writeFence() sends a new fence request or response to the client. // writeFence() sends a new fence request or response to the client.
void writeFence(rdr::U32 flags, unsigned len, const char data[]); void writeFence(rdr::U32 flags, unsigned len, const char data[]);
@@ -88,7 +90,6 @@ namespace rfb {
bool writeSetCursor(); bool writeSetCursor();
bool writeSetXCursor(); bool writeSetXCursor();
bool writeSetCursorWithAlpha(); bool writeSetCursorWithAlpha();
bool writeSetVMwareCursor();
// Notifies the client that the cursor pointer was moved by the server. // Notifies the client that the cursor pointer was moved by the server.
void writeCursorPos(); void writeCursorPos();
@@ -148,9 +149,6 @@ namespace rfb {
void writeSetCursorWithAlphaRect(int width, int height, void writeSetCursorWithAlphaRect(int width, int height,
int hotspotX, int hotspotY, int hotspotX, int hotspotY,
const rdr::U8* data); const rdr::U8* data);
void writeSetVMwareCursorRect(int width, int height,
int hotspotX, int hotspotY,
const rdr::U8* data);
void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY); void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY);
void writeLEDStateRect(rdr::U8 state); void writeLEDStateRect(rdr::U8 state);
void writeQEMUKeyEventRect(); void writeQEMUKeyEventRect();
@@ -167,7 +165,6 @@ namespace rfb {
bool needSetCursor; bool needSetCursor;
bool needSetXCursor; bool needSetXCursor;
bool needSetCursorWithAlpha; bool needSetCursorWithAlpha;
bool needSetVMWareCursor;
bool needCursorPos; bool needCursorPos;
bool needLEDState; bool needLEDState;
bool needQEMUKeyEvent; bool needQEMUKeyEvent;

View File

@@ -1,197 +0,0 @@
/* Copyright (C) 2021 Kasm Web
*
* 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.
*/
#include <rfb/ComparingUpdateTracker.h>
#include <rfb/EncodeManager.h>
#include <rfb/LogWriter.h>
#include <rfb/SConnection.h>
#include <rfb/ServerCore.h>
#include <rfb/PixelBuffer.h>
#include <rfb/TightJPEGEncoder.h>
#include <rfb/TightWEBPEncoder.h>
#include <rfb/util.h>
#include <sys/time.h>
#include <stdint.h>
#include <stdlib.h>
using namespace rfb;
static LogWriter vlog("SelfBench");
static const PixelFormat pfRGBX(32, 24, false, true, 255, 255, 255, 0, 8, 16);
#define RUNS 64
#define W 1600
#define H 1200
void SelfBench() {
unsigned i, runs;
struct timeval start;
ManagedPixelBuffer f1(pfRGBX, W, H);
ManagedPixelBuffer f2(pfRGBX, W, H);
ManagedPixelBuffer screen(pfRGBX, W, H);
int stride;
rdr::U8 *f1ptr = f1.getBufferRW(f1.getRect(), &stride);
rdr::U8 *f2ptr = f2.getBufferRW(f2.getRect(), &stride);
rdr::U8 * const screenptr = screen.getBufferRW(screen.getRect(), &stride);
rdr::U8 * const f1orig = f1ptr;
rdr::U8 * const f2orig = f2ptr;
for (i = 0; i < W * H * 4; i += 4) {
f1ptr[0] = rand();
f1ptr[1] = rand();
f1ptr[2] = rand();
f2ptr[0] = rand();
f2ptr[1] = rand();
f2ptr[2] = rand();
f1ptr += 4;
f2ptr += 4;
}
vlog.info("Running micro-benchmarks (single-threaded, runs depending on task)");
// Encoding
std::vector<uint8_t> vec;
TightJPEGEncoder jpeg(NULL);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
jpeg.compressOnly(&f1, 8, vec, false);
}
vlog.info("Jpeg compression at quality 8 took %u ms (%u runs)", msSince(&start), runs);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
jpeg.compressOnly(&f1, 4, vec, false);
}
vlog.info("Jpeg compression at quality 4 took %u ms (%u runs)", msSince(&start), runs);
TightWEBPEncoder webp(NULL);
gettimeofday(&start, NULL);
runs = RUNS / 8;
for (i = 0; i < runs; i++) {
webp.compressOnly(&f1, 8, vec, false);
}
vlog.info("Webp compression at quality 8 took %u ms (%u runs)", msSince(&start), runs);
gettimeofday(&start, NULL);
runs = RUNS / 4;
for (i = 0; i < runs; i++) {
webp.compressOnly(&f1, 4, vec, false);
}
vlog.info("Webp compression at quality 4 took %u ms (%u runs)", msSince(&start), runs);
// Scaling
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
PixelBuffer *pb = nearestScale(&f1, W * 0.8, H * 0.8, 0.8);
delete pb;
}
vlog.info("Nearest scaling to 80%% took %u ms (%u runs)", msSince(&start), runs);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
PixelBuffer *pb = nearestScale(&f1, W * 0.4, H * 0.4, 0.4);
delete pb;
}
vlog.info("Nearest scaling to 40%% took %u ms (%u runs)", msSince(&start), runs);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
PixelBuffer *pb = bilinearScale(&f1, W * 0.8, H * 0.8, 0.8);
delete pb;
}
vlog.info("Bilinear scaling to 80%% took %u ms (%u runs)", msSince(&start), runs);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
PixelBuffer *pb = bilinearScale(&f1, W * 0.4, H * 0.4, 0.4);
delete pb;
}
vlog.info("Bilinear scaling to 40%% took %u ms (%u runs)", msSince(&start), runs);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
PixelBuffer *pb = progressiveBilinearScale(&f1, W * 0.8, H * 0.8, 0.8);
delete pb;
}
vlog.info("Progressive bilinear scaling to 80%% took %u ms (%u runs)", msSince(&start), runs);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
PixelBuffer *pb = progressiveBilinearScale(&f1, W * 0.4, H * 0.4, 0.4);
delete pb;
}
vlog.info("Progressive bilinear scaling to 40%% took %u ms (%u runs)", msSince(&start), runs);
// Analysis
ComparingUpdateTracker *comparer = new ComparingUpdateTracker(&screen);
Region cursorReg;
Server::detectScrolling.setParam(false);
Server::detectHorizontal.setParam(false);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
memcpy(screenptr, i % 2 ? f1orig : f2orig, W * H * 4);
comparer->compare(true, cursorReg);
}
vlog.info("Analysis took %u ms (%u runs) (incl. memcpy overhead)", msSince(&start), runs);
Server::detectScrolling.setParam(true);
gettimeofday(&start, NULL);
runs = RUNS;
for (i = 0; i < runs; i++) {
memcpy(screenptr, i % 2 ? f1orig : f2orig, W * H * 4);
comparer->compare(false, cursorReg);
}
vlog.info("Analysis w/ scroll detection took %u ms (%u runs) (incl. memcpy overhead)", msSince(&start), runs);
Server::detectHorizontal.setParam(true);
delete comparer;
comparer = new ComparingUpdateTracker(&screen);
gettimeofday(&start, NULL);
runs = RUNS / 2;
for (i = 0; i < runs; i++) {
memcpy(screenptr, i % 2 ? f1orig : f2orig, W * H * 4);
comparer->compare(false, cursorReg);
}
vlog.info("Analysis w/ horizontal scroll detection took %u ms (%u runs) (incl. memcpy overhead)", msSince(&start), runs);
exit(0);
}

View File

@@ -113,10 +113,6 @@ rfb::BoolParameter rfb::Server::ignoreClientSettingsKasm
("IgnoreClientSettingsKasm", ("IgnoreClientSettingsKasm",
"Ignore the additional client settings exposed in Kasm.", "Ignore the additional client settings exposed in Kasm.",
false); false);
rfb::BoolParameter rfb::Server::selfBench
("SelfBench",
"Run self-benchmarks and exit.",
false);
rfb::IntParameter rfb::Server::dynamicQualityMin rfb::IntParameter rfb::Server::dynamicQualityMin
("DynamicQualityMin", ("DynamicQualityMin",
"The minimum dynamic JPEG quality, 0 = low, 9 = high", "The minimum dynamic JPEG quality, 0 = low, 9 = high",
@@ -149,15 +145,15 @@ rfb::IntParameter rfb::Server::webpVideoQuality
rfb::IntParameter rfb::Server::DLP_ClipSendMax rfb::IntParameter rfb::Server::DLP_ClipSendMax
("DLP_ClipSendMax", ("DLP_ClipSendMax",
"Limit clipboard bytes to send to clients in one transaction", "Limit clipboard bytes to send to clients in one transaction",
0, 0, INT_MAX); 10000, 0, INT_MAX);
rfb::IntParameter rfb::Server::DLP_ClipAcceptMax rfb::IntParameter rfb::Server::DLP_ClipAcceptMax
("DLP_ClipAcceptMax", ("DLP_ClipAcceptMax",
"Limit clipboard bytes to receive from clients in one transaction", "Limit clipboard bytes to receive from clients in one transaction",
0, 0, INT_MAX); 10000, 0, INT_MAX);
rfb::IntParameter rfb::Server::DLP_ClipDelay rfb::IntParameter rfb::Server::DLP_ClipDelay
("DLP_ClipDelay", ("DLP_ClipDelay",
"This many milliseconds must pass between clipboard actions", "This many milliseconds must pass between clipboard actions",
0, 0, INT_MAX); 1000, 0, INT_MAX);
rfb::IntParameter rfb::Server::DLP_KeyRateLimit rfb::IntParameter rfb::Server::DLP_KeyRateLimit
("DLP_KeyRateLimit", ("DLP_KeyRateLimit",
"Reject keyboard presses over this many per second", "Reject keyboard presses over this many per second",
@@ -171,10 +167,6 @@ rfb::StringParameter rfb::Server::DLP_Region
("DLP_Region", ("DLP_Region",
"Black out anything outside this region", "Black out anything outside this region",
""); "");
rfb::StringParameter rfb::Server::DLP_Clip_Types
("DLP_ClipTypes",
"Allowed binary clipboard mimetypes",
"text/html,image/png");
rfb::BoolParameter rfb::Server::DLP_RegionAllowClick rfb::BoolParameter rfb::Server::DLP_RegionAllowClick
("DLP_RegionAllowClick", ("DLP_RegionAllowClick",

View File

@@ -50,7 +50,6 @@ namespace rfb {
static IntParameter DLP_KeyRateLimit; static IntParameter DLP_KeyRateLimit;
static StringParameter DLP_ClipLog; static StringParameter DLP_ClipLog;
static StringParameter DLP_Region; static StringParameter DLP_Region;
static StringParameter DLP_Clip_Types;
static BoolParameter DLP_RegionAllowClick; static BoolParameter DLP_RegionAllowClick;
static BoolParameter DLP_RegionAllowRelease; static BoolParameter DLP_RegionAllowRelease;
static IntParameter jpegVideoQuality; static IntParameter jpegVideoQuality;
@@ -75,8 +74,8 @@ namespace rfb {
static BoolParameter detectScrolling; static BoolParameter detectScrolling;
static BoolParameter detectHorizontal; static BoolParameter detectHorizontal;
static BoolParameter ignoreClientSettingsKasm; static BoolParameter ignoreClientSettingsKasm;
static BoolParameter selfBench;
static PresetParameter preferBandwidth; static PresetParameter preferBandwidth;
}; };
}; };

View File

@@ -71,12 +71,12 @@ static const struct TightWEBPConfiguration conf[10] = {
{ 24, 0 }, // 1 { 24, 0 }, // 1
{ 30, 0 }, // 2 { 30, 0 }, // 2
{ 37, 0 }, // 3 { 37, 0 }, // 3
{ 42, 0 }, // 4 { 42, 1 }, // 4
{ 65, 0 }, // 5 { 65, 1 }, // 5
{ 78, 0 }, // 6 { 78, 1 }, // 6
{ 85, 0 }, // 7 { 85, 2 }, // 7
{ 88, 0 }, // 8 { 88, 3 }, // 8
{ 100, 0 } // 9 { 100, 4 } // 9
}; };
@@ -143,7 +143,7 @@ void TightWEBPEncoder::compressOnly(const PixelBuffer* pb, const uint8_t quality
method = conf[qualityIn].method; method = conf[qualityIn].method;
} else { } else {
quality = 8; quality = 8;
method = 0; method = 4;
} }
WebPConfigInit(&cfg); WebPConfigInit(&cfg);
@@ -214,7 +214,7 @@ void TightWEBPEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
method = conf[qualityLevel].method; method = conf[qualityLevel].method;
} else { } else {
quality = 8; quality = 8;
method = 0; method = 4;
} }
WebPConfigInit(&cfg); WebPConfigInit(&cfg);
@@ -265,7 +265,7 @@ rdr::U32 TightWEBPEncoder::benchmark() const
rdr::U8* buffer; rdr::U8* buffer;
struct timeval start; struct timeval start;
int stride, i; int stride, i;
const uint8_t quality = 8, method = 2; const uint8_t quality = 8, method = 4;
WebPConfig cfg; WebPConfig cfg;
WebPPicture pic; WebPPicture pic;
WebPMemoryWriter wrt; WebPMemoryWriter wrt;

View File

@@ -17,7 +17,6 @@
* USA. * USA.
*/ */
#include <network/GetAPI.h>
#include <network/TcpSocket.h> #include <network/TcpSocket.h>
#include <rfb/ComparingUpdateTracker.h> #include <rfb/ComparingUpdateTracker.h>
@@ -57,13 +56,12 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
inProcessMessages(false), inProcessMessages(false),
pendingSyncFence(false), syncFence(false), fenceFlags(0), pendingSyncFence(false), syncFence(false), fenceFlags(0),
fenceDataLen(0), fenceData(NULL), congestionTimer(this), fenceDataLen(0), fenceData(NULL), congestionTimer(this),
losslessTimer(this), kbdLogTimer(this), binclipTimer(this), losslessTimer(this), kbdLogTimer(this), server(server_), updates(false),
server(server_), updates(false),
updateRenderedCursor(false), removeRenderedCursor(false), updateRenderedCursor(false), removeRenderedCursor(false),
continuousUpdates(false), encodeManager(this, &server_->encCache), continuousUpdates(false), encodeManager(this, &server_->encCache),
needsPermCheck(false), pointerEventTime(0), needsPermCheck(false), pointerEventTime(0),
clientHasCursor(false), clientHasCursor(false),
accessRights(AccessDefault), startTime(time(0)), frameTracking(false) accessRights(AccessDefault), startTime(time(0))
{ {
setStreams(&sock->inStream(), &sock->outStream()); setStreams(&sock->inStream(), &sock->outStream());
peerEndpoint.buf = sock->getPeerEndpoint(); peerEndpoint.buf = sock->getPeerEndpoint();
@@ -76,7 +74,7 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
kasmpasswdpath[0] = '\0'; kasmpasswdpath[0] = '\0';
wordexp_t wexp; wordexp_t wexp;
if (!wordexp(rfb::Server::kasmPasswordFile, &wexp, WRDE_NOCMD)) if (!wordexp(rfb::Server::kasmPasswordFile, &wexp, WRDE_NOCMD))
strncpy(kasmpasswdpath, wexp.we_wordv[0], 4095); strncpy(kasmpasswdpath, wexp.we_wordv[0], 4096);
kasmpasswdpath[4095] = '\0'; kasmpasswdpath[4095] = '\0';
wordfree(&wexp); wordfree(&wexp);
@@ -87,16 +85,10 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
user[at - peerEndpoint.buf] = '\0'; user[at - peerEndpoint.buf] = '\0';
} }
bool read, write, owner; bool write, owner;
if (!getPerms(read, write, owner)) { if (!getPerms(write, owner) || !write) {
accessRights &= ~(WRITER_PERMS | AccessView);
}
if (!write) {
accessRights &= ~WRITER_PERMS; accessRights &= ~WRITER_PERMS;
} }
if (!read) {
accessRights &= ~AccessView;
}
// Configure the socket // Configure the socket
setSocketTimeouts(); setSocketTimeouts();
@@ -106,9 +98,6 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
gettimeofday(&lastKeyEvent, NULL); gettimeofday(&lastKeyEvent, NULL);
server->clients.push_front(this); server->clients.push_front(this);
if (server->apimessager)
server->apimessager->mainUpdateUserInfo(checkOwnerConn(), server->clients.size());
} }
@@ -139,11 +128,6 @@ VNCSConnectionST::~VNCSConnectionST()
server->clients.remove(this); server->clients.remove(this);
delete [] fenceData; delete [] fenceData;
if (server->apimessager) {
server->apimessager->mainUpdateUserInfo(checkOwnerConn(), server->clients.size());
server->apimessager->mainClearBottleneckStats(peerEndpoint.buf);
}
} }
@@ -367,18 +351,17 @@ char *percentEncode4(const uint16_t *str, const unsigned len) {
} }
static void cliplog(const char *str, const int len, const int origlen, static void cliplog(const char *str, const int len, const int origlen,
const char *dir, const char *client, const unsigned id) { const char *dir, const char *client) {
if (Server::DLP_ClipLog[0] == 'o') if (Server::DLP_ClipLog[0] == 'o')
return; return;
if (Server::DLP_ClipLog[0] == 'i') { if (Server::DLP_ClipLog[0] == 'i') {
vlog.info("DLP: client %s: %s %u (%u requested) clipboard bytes, id %u", client, dir, vlog.info("DLP: client %s: %s %u (%u requested) clipboard bytes", client, dir, len, origlen);
len, origlen, id);
} else { } else {
// URL-encode it // URL-encode it
char *enc = percentEncode(str, len); char *enc = percentEncode(str, len);
vlog.info("DLP: client %s: %s %u (%u requested) clipboard bytes, id %u: '%s'", vlog.info("DLP: client %s: %s %u (%u requested) clipboard bytes: '%s'",
client, dir, len, origlen, id, enc); client, dir, len, origlen, enc);
free(enc); free(enc);
} }
} }
@@ -421,6 +404,18 @@ static void keylog(unsigned keysym, const char *client) {
flushKeylog(client); flushKeylog(client);
} }
void VNCSConnectionST::requestClipboardOrClose()
{
try {
if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::acceptCutText) return;
if (state() != RFBSTATE_NORMAL) return;
requestClipboard();
} catch(rdr::Exception& e) {
close(e.str());
}
}
void VNCSConnectionST::announceClipboardOrClose(bool available) void VNCSConnectionST::announceClipboardOrClose(bool available)
{ {
try { try {
@@ -433,53 +428,29 @@ void VNCSConnectionST::announceClipboardOrClose(bool available)
} }
} }
void VNCSConnectionST::clearBinaryClipboardData() void VNCSConnectionST::sendClipboardDataOrClose(const char* data)
{
clearBinaryClipboard();
}
void VNCSConnectionST::sendBinaryClipboardDataOrClose(const char* mime,
const unsigned char *data,
const unsigned len,
const unsigned id)
{ {
try { try {
if (!(accessRights & AccessCutText)) return; if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::sendCutText) return; if (!rfb::Server::sendCutText) return;
if (rfb::Server::DLP_ClipSendMax && len > (unsigned) rfb::Server::DLP_ClipSendMax) { if (msSince(&lastClipboardOp) < (unsigned) rfb::Server::DLP_ClipDelay) {
vlog.info("DLP: client %s: refused to send binary clipboard, too large", vlog.info("DLP: client %s: refused to send clipboard, too soon",
sock->getPeerAddress()); sock->getPeerAddress());
return; return;
} }
int len = strlen(data);
cliplog((const char *) data, len, len, "sent", sock->getPeerAddress(), const int origlen = len;
id); if (rfb::Server::DLP_ClipSendMax && len > rfb::Server::DLP_ClipSendMax)
len = rfb::Server::DLP_ClipSendMax;
cliplog(data, len, origlen, "sent", sock->getPeerAddress());
if (state() != RFBSTATE_NORMAL) return; if (state() != RFBSTATE_NORMAL) return;
sendClipboardData(data, len);
addBinaryClipboard(mime, data, len, id); gettimeofday(&lastClipboardOp, NULL);
binclipTimer.start(100);
} catch(rdr::Exception& e) { } catch(rdr::Exception& e) {
close(e.str()); close(e.str());
} }
} }
void VNCSConnectionST::getBinaryClipboardData(const char* mime, const unsigned char **data,
unsigned *len)
{
unsigned i;
for (i = 0; i < binaryClipboard.size(); i++) {
if (!strcmp(binaryClipboard[i].mime, mime)) {
*data = &binaryClipboard[i].data[0];
*len = binaryClipboard[i].data.size();
return;
}
}
vlog.error("Binary clipboard data for mime %s not found", mime);
*data = (const unsigned char *) "";
*len = 1;
}
void VNCSConnectionST::setDesktopNameOrClose(const char *name) void VNCSConnectionST::setDesktopNameOrClose(const char *name)
{ {
try { try {
@@ -596,7 +567,6 @@ bool VNCSConnectionST::needRenderedCursor()
return false; return false;
if (!cp.supportsLocalCursorWithAlpha && if (!cp.supportsLocalCursorWithAlpha &&
!cp.supportsVMWareCursor &&
!cp.supportsLocalCursor && !cp.supportsLocalXCursor) !cp.supportsLocalCursor && !cp.supportsLocalXCursor)
return true; return true;
if (!server->cursorPos.equals(pointerEventPos) && if (!server->cursorPos.equals(pointerEventPos) &&
@@ -712,58 +682,14 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf)
setCursor(); setCursor();
} }
void VNCSConnectionST::pointerEvent(const Point& pos, const Point& abspos, int buttonMask, const bool skipClick, const bool skipRelease, int scrollX, int scrollY) void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease)
{ {
pointerEventTime = lastEventTime = time(0); pointerEventTime = lastEventTime = time(0);
server->lastUserInputTime = lastEventTime; server->lastUserInputTime = lastEventTime;
if (!(accessRights & AccessPtrEvents)) { if (!(accessRights & AccessPtrEvents)) return;
// This particular event is lost, but it's a corner case - you removed write access
// from yourself, then added it back. The intended use is for multiple clients,
// where the leader removes and adds back access for others, not himself.
recheckPerms();
return;
}
if (!rfb::Server::acceptPointerEvents) return; if (!rfb::Server::acceptPointerEvents) return;
if (!server->pointerClient || server->pointerClient == this) { if (!server->pointerClient || server->pointerClient == this) {
Point newpos = pos; pointerEventPos = pos;
if (pos.x & 0x4000) {
newpos.x &= ~0x4000;
newpos.y &= ~0x4000;
if (newpos.x & 0x8000) {
newpos.x &= ~0x8000;
newpos.x = -newpos.x;
}
if (newpos.y & 0x8000) {
newpos.y &= ~0x8000;
newpos.y = -newpos.y;
}
if (newpos.x < 0) {
if (pointerEventPos.x + newpos.x >= 0)
pointerEventPos.x += newpos.x;
else
pointerEventPos.x = 0;
} else {
pointerEventPos.x += newpos.x;
if (pointerEventPos.x >= cp.width)
pointerEventPos.x = cp.width;
}
if (newpos.y < 0) {
if (pointerEventPos.y + newpos.y >= 0)
pointerEventPos.y += newpos.y;
else
pointerEventPos.y = 0;
} else {
pointerEventPos.y += newpos.y;
if (pointerEventPos.y >= cp.height)
pointerEventPos.y = cp.height;
}
} else {
pointerEventPos = pos;
}
if (buttonMask) if (buttonMask)
server->pointerClient = this; server->pointerClient = this;
else else
@@ -784,7 +710,7 @@ void VNCSConnectionST::pointerEvent(const Point& pos, const Point& abspos, int b
} }
} }
server->desktop->pointerEvent(newpos, pointerEventPos, buttonMask, skipclick, skiprelease, scrollX, scrollY); server->desktop->pointerEvent(pointerEventPos, buttonMask, skipclick, skiprelease);
} }
} }
@@ -1078,6 +1004,12 @@ void VNCSConnectionST::enableContinuousUpdates(bool enable,
} }
} }
void VNCSConnectionST::handleClipboardRequest()
{
if (!(accessRights & AccessCutText)) return;
server->handleClipboardRequest(this);
}
void VNCSConnectionST::handleClipboardAnnounce(bool available) void VNCSConnectionST::handleClipboardAnnounce(bool available)
{ {
if (!(accessRights & AccessCutText)) return; if (!(accessRights & AccessCutText)) return;
@@ -1085,21 +1017,25 @@ void VNCSConnectionST::handleClipboardAnnounce(bool available)
server->handleClipboardAnnounce(this, available); server->handleClipboardAnnounce(this, available);
} }
void VNCSConnectionST::handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]) void VNCSConnectionST::handleClipboardData(const char* data, int len)
{ {
if (!(accessRights & AccessCutText)) return; if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::acceptCutText) return; if (!rfb::Server::acceptCutText) return;
server->handleClipboardAnnounceBinary(this, num, mimes); if (msSince(&lastClipboardOp) < (unsigned) rfb::Server::DLP_ClipDelay) {
vlog.info("DLP: client %s: refused to receive clipboard, too soon",
const unsigned tolog = server->clipboardId++; sock->getPeerAddress());
if (Server::DLP_ClipLog[0] == 'o')
return; return;
vlog.info("DLP: client %s: %s %u clipboard mimes, id %u", }
sock->getPeerAddress(), "received", const int origlen = len;
num, tolog); if (rfb::Server::DLP_ClipAcceptMax && len > rfb::Server::DLP_ClipAcceptMax)
len = rfb::Server::DLP_ClipAcceptMax;
cliplog(data, len, origlen, "received", sock->getPeerAddress());
gettimeofday(&lastClipboardOp, NULL);
server->handleClipboardData(this, data, len);
} }
// supportsLocalCursor() is called whenever the status of // supportsLocalCursor() is called whenever the status of
// cp.supportsLocalCursor has changed. If the client does now support local // cp.supportsLocalCursor has changed. If the client does now support local
// cursor, we make sure that the old server-side rendered cursor is cleaned up // cursor, we make sure that the old server-side rendered cursor is cleaned up
@@ -1143,8 +1079,6 @@ bool VNCSConnectionST::handleTimeout(Timer* t)
writeFramebufferUpdate(); writeFramebufferUpdate();
else if (t == &kbdLogTimer) else if (t == &kbdLogTimer)
flushKeylog(sock->getPeerAddress()); flushKeylog(sock->getPeerAddress());
else if (t == &binclipTimer)
writeBinaryClipboard();
} catch (rdr::Exception& e) { } catch (rdr::Exception& e) {
close(e.str()); close(e.str());
} }
@@ -1166,12 +1100,11 @@ bool VNCSConnectionST::isShiftPressed()
return false; return false;
} }
bool VNCSConnectionST::getPerms(bool &read, bool &write, bool &owner) const bool VNCSConnectionST::getPerms(bool &write, bool &owner) const
{ {
bool found = false; bool found = false;
if (disablebasicauth) { if (disablebasicauth) {
// We're running without basicauth // We're running without basicauth
read = true;
write = true; write = true;
return true; return true;
} }
@@ -1180,14 +1113,8 @@ bool VNCSConnectionST::getPerms(bool &read, bool &write, bool &owner) const
unsigned i; unsigned i;
for (i = 0; i < set->num; i++) { for (i = 0; i < set->num; i++) {
if (!strcmp(set->entries[i].user, user)) { if (!strcmp(set->entries[i].user, user)) {
read = set->entries[i].read;
write = set->entries[i].write; write = set->entries[i].write;
owner = set->entries[i].owner; owner = set->entries[i].owner;
// Writer can always read
if (write)
read = true;
found = true; found = true;
break; break;
} }
@@ -1257,7 +1184,6 @@ bool VNCSConnectionST::isCongested()
void VNCSConnectionST::writeFramebufferUpdate() void VNCSConnectionST::writeFramebufferUpdate()
{ {
congestion.updatePosition(sock->outStream().length()); congestion.updatePosition(sock->outStream().length());
encodeManager.clearEncodingTime();
// We're in the middle of processing a command that's supposed to be // We're in the middle of processing a command that's supposed to be
// synchronised. Allowing an update to slip out right now might violate // synchronised. Allowing an update to slip out right now might violate
@@ -1285,38 +1211,24 @@ void VNCSConnectionST::writeFramebufferUpdate()
if (needsPermCheck) { if (needsPermCheck) {
needsPermCheck = false; needsPermCheck = false;
bool read, write, owner, ret; bool write, owner, ret;
ret = getPerms(read, write, owner); ret = getPerms(write, owner);
if (!ret) { if (!ret) {
close("User was deleted"); close("User was deleted");
return; return;
} } else if (!write) {
if (!write) {
accessRights &= ~WRITER_PERMS; accessRights &= ~WRITER_PERMS;
} else { } else {
accessRights |= WRITER_PERMS; accessRights |= WRITER_PERMS;
} }
if (!read) {
accessRights &= ~AccessView;
} else {
accessRights |= AccessView;
}
} }
if (!(accessRights & AccessView))
return;
// Updates often consists of many small writes, and in continuous // Updates often consists of many small writes, and in continuous
// mode, we will also have small fence messages around the update. We // mode, we will also have small fence messages around the update. We
// need to aggregate these in order to not clog up TCP's congestion // need to aggregate these in order to not clog up TCP's congestion
// window. // window.
sock->cork(true); sock->cork(true);
if (frameTracking)
writer()->writeRequestFrameStats();
// First take care of any updates that cannot contain framebuffer data // First take care of any updates that cannot contain framebuffer data
// changes. // changes.
writeNoDataUpdate(); writeNoDataUpdate();
@@ -1520,18 +1432,6 @@ void VNCSConnectionST::writeDataUpdate()
requested.clear(); requested.clear();
} }
void VNCSConnectionST::writeBinaryClipboard()
{
if (msSince(&lastClipboardOp) < (unsigned) rfb::Server::DLP_ClipDelay) {
vlog.info("DLP: client %s: refused to send binary clipboard, too soon",
sock->getPeerAddress());
return;
}
writer()->writeBinaryClipboard(binaryClipboard);
gettimeofday(&lastClipboardOp, NULL);
}
void VNCSConnectionST::screenLayoutChange(rdr::U16 reason) void VNCSConnectionST::screenLayoutChange(rdr::U16 reason)
{ {
@@ -1559,7 +1459,7 @@ static void pruneStatList(std::list<struct timeval> &list, const struct timeval
} }
} }
void VNCSConnectionST::sendStats(const bool toClient) { void VNCSConnectionST::sendStats() {
char buf[1024]; char buf[1024];
struct timeval now; struct timeval now;
@@ -1598,28 +1498,8 @@ void VNCSConnectionST::sendStats(const bool toClient) {
#undef ten #undef ten
if (toClient) { vlog.info("Sending client stats:\n%s\n", buf);
vlog.info("Sending client stats:\n%s\n", buf); writer()->writeStats(buf, strlen(buf));
writer()->writeStats(buf, strlen(buf));
} else if (server->apimessager) {
server->apimessager->mainUpdateBottleneckStats(peerEndpoint.buf, buf);
}
}
void VNCSConnectionST::handleFrameStats(rdr::U32 all, rdr::U32 render)
{
if (server->apimessager) {
const char *at = strchr(peerEndpoint.buf, '@');
if (!at)
at = peerEndpoint.buf;
else
at++;
server->apimessager->mainUpdateClientFrameStats(at, render, all,
congestion.getPingTime());
}
frameTracking = false;
} }
// setCursor() is called whenever the cursor has changed shape or pixel format. // setCursor() is called whenever the cursor has changed shape or pixel format.
@@ -1640,13 +1520,11 @@ void VNCSConnectionST::setCursor()
clientHasCursor = true; clientHasCursor = true;
} }
if (!writer()->writeSetVMwareCursor()) { if (!writer()->writeSetCursorWithAlpha()) {
if (!writer()->writeSetCursorWithAlpha()) { if (!writer()->writeSetCursor()) {
if (!writer()->writeSetCursor()) { if (!writer()->writeSetXCursor()) {
if (!writer()->writeSetXCursor()) { // No client support
// No client support return;
return;
}
} }
} }
} }
@@ -1733,15 +1611,3 @@ int VNCSConnectionST::getStatus()
return 4; return 4;
} }
bool VNCSConnectionST::checkOwnerConn() const
{
std::list<VNCSConnectionST*>::const_iterator it;
for (it = server->clients.begin(); it != server->clients.end(); it++) {
bool read, write, owner;
if ((*it)->getPerms(read, write, owner) && owner)
return true;
}
return false;
}

View File

@@ -77,12 +77,9 @@ namespace rfb {
void bellOrClose(); void bellOrClose();
void setDesktopNameOrClose(const char *name); void setDesktopNameOrClose(const char *name);
void setLEDStateOrClose(unsigned int state); void setLEDStateOrClose(unsigned int state);
void requestClipboardOrClose();
void announceClipboardOrClose(bool available); void announceClipboardOrClose(bool available);
void clearBinaryClipboardData(); void sendClipboardDataOrClose(const char* data);
void sendBinaryClipboardDataOrClose(const char* mime, const unsigned char *data,
const unsigned len, const unsigned id);
void getBinaryClipboardData(const char* mime, const unsigned char **data,
unsigned *len);
// checkIdleTimeout() returns the number of milliseconds left until the // checkIdleTimeout() returns the number of milliseconds left until the
// idle timeout expires. If it has expired, the connection is closed and // idle timeout expires. If it has expired, the connection is closed and
@@ -167,35 +164,6 @@ namespace rfb {
void setStatus(int status); void setStatus(int status);
int getStatus(); int getStatus();
virtual void sendStats(const bool toClient = true);
virtual void handleFrameStats(rdr::U32 all, rdr::U32 render);
bool is_owner() const {
bool read, write, owner;
if (getPerms(read, write, owner) && owner)
return true;
return false;
}
void setFrameTracking() {
frameTracking = true;
}
EncodeManager::codecstats_t getJpegStats() const {
return encodeManager.jpegstats;
}
EncodeManager::codecstats_t getWebpStats() const {
return encodeManager.webpstats;
}
unsigned getEncodingTime() const {
return encodeManager.getEncodingTime();
}
unsigned getScalingTime() const {
return encodeManager.getScalingTime();
}
private: private:
// SConnection callbacks // SConnection callbacks
@@ -207,7 +175,7 @@ namespace rfb {
virtual void queryConnection(const char* userName); virtual void queryConnection(const char* userName);
virtual void clientInit(bool shared); virtual void clientInit(bool shared);
virtual void setPixelFormat(const PixelFormat& pf); virtual void setPixelFormat(const PixelFormat& pf);
virtual void pointerEvent(const Point& pos, const Point& abspos,int buttonMask, const bool skipClick, const bool skipRelease, int scrollX, int scrollY); virtual void pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
virtual void framebufferUpdateRequest(const Rect& r, bool incremental); virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
virtual void setDesktopSize(int fb_width, int fb_height, virtual void setDesktopSize(int fb_width, int fb_height,
@@ -215,18 +183,33 @@ namespace rfb {
virtual void fence(rdr::U32 flags, unsigned len, const char data[]); virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
virtual void enableContinuousUpdates(bool enable, virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h); int x, int y, int w, int h);
virtual void handleClipboardRequest();
virtual void handleClipboardAnnounce(bool available); virtual void handleClipboardAnnounce(bool available);
virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]); virtual void handleClipboardData(const char* data, int len);
virtual void supportsLocalCursor(); virtual void supportsLocalCursor();
virtual void supportsFence(); virtual void supportsFence();
virtual void supportsContinuousUpdates(); virtual void supportsContinuousUpdates();
virtual void supportsLEDState(); virtual void supportsLEDState();
virtual void sendStats();
virtual bool canChangeKasmSettings() const { virtual bool canChangeKasmSettings() const {
return (accessRights & (AccessPtrEvents | AccessKeyEvents)) == return (accessRights & (AccessPtrEvents | AccessKeyEvents)) ==
(AccessPtrEvents | AccessKeyEvents); (AccessPtrEvents | AccessKeyEvents);
} }
// setAccessRights() allows a security package to limit the access rights
// of a VNCSConnectioST to the server. These access rights are applied
// such that the actual rights granted are the minimum of the server's
// default access settings and the connection's access settings.
virtual void setAccessRights(AccessRights ar) {
accessRights = ar;
bool write, owner;
if (!getPerms(write, owner) || !write)
accessRights &= ~WRITER_PERMS;
needsPermCheck = false;
}
// Timer callbacks // Timer callbacks
virtual bool handleTimeout(Timer* t); virtual bool handleTimeout(Timer* t);
@@ -234,9 +217,7 @@ namespace rfb {
bool isShiftPressed(); bool isShiftPressed();
bool getPerms(bool &read, bool &write, bool &owner) const; bool getPerms(bool &write, bool &owner) const;
bool checkOwnerConn() const;
// Congestion control // Congestion control
void writeRTTPing(); void writeRTTPing();
@@ -249,8 +230,6 @@ namespace rfb {
void writeNoDataUpdate(); void writeNoDataUpdate();
void writeDataUpdate(); void writeDataUpdate();
void writeBinaryClipboard();
void screenLayoutChange(rdr::U16 reason); void screenLayoutChange(rdr::U16 reason);
void setCursor(); void setCursor();
void setCursorPos(); void setCursorPos();
@@ -273,7 +252,6 @@ namespace rfb {
Timer congestionTimer; Timer congestionTimer;
Timer losslessTimer; Timer losslessTimer;
Timer kbdLogTimer; Timer kbdLogTimer;
Timer binclipTimer;
VNCServerST* server; VNCServerST* server;
SimpleUpdateTracker updates; SimpleUpdateTracker updates;
@@ -316,8 +294,6 @@ namespace rfb {
time_t startTime; time_t startTime;
std::vector<CopyPassRect> copypassed; std::vector<CopyPassRect> copypassed;
bool frameTracking;
}; };
} }
#endif #endif

Some files were not shown because too many files have changed in this diff Show More