mirror of
https://github.com/kasmtech/KasmVNC.git
synced 2024-11-21 15:43:28 +01:00
Initial commit
This commit is contained in:
parent
09a4460ddb
commit
408c005d3e
433
BUILDING.txt
Normal file
433
BUILDING.txt
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
*******************************************************************************
|
||||||
|
** Building KasmVNC
|
||||||
|
*******************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
================================
|
||||||
|
Build Requirements (All Systems)
|
||||||
|
================================
|
||||||
|
|
||||||
|
-- CMake (http://www.cmake.org) v2.8 or later
|
||||||
|
|
||||||
|
-- zlib
|
||||||
|
|
||||||
|
-- If building TLS support:
|
||||||
|
* GnuTLS 3.x
|
||||||
|
* See "Building TLS Support" below.
|
||||||
|
|
||||||
|
-- If building native language support (NLS):
|
||||||
|
* Gnu gettext 0.14.4 or later
|
||||||
|
* See "Building Native Language Support" below.
|
||||||
|
|
||||||
|
-- libjpeg-turbo
|
||||||
|
* "Normal" libjpegv6 is also supported, although it is not
|
||||||
|
recommended as it is much slower.
|
||||||
|
|
||||||
|
-- libwebp
|
||||||
|
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Build Requirements (Unix)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
-- Non-Mac platforms:
|
||||||
|
* X11 development kit
|
||||||
|
|
||||||
|
-- If building Xvnc/libvnc.so:
|
||||||
|
* Xorg server source code, 1.7 or never
|
||||||
|
* All build requirements Xorg imposes (see its documentation)
|
||||||
|
|
||||||
|
============================
|
||||||
|
Build Requirements (Windows)
|
||||||
|
============================
|
||||||
|
|
||||||
|
-- MinGW or MinGW-w64
|
||||||
|
|
||||||
|
-- Inno Setup (needed to build the KasmVNC installer)
|
||||||
|
Inno Setup can be downloaded from http://www.jrsoftware.org/isinfo.php.
|
||||||
|
You also need the Inno Setup Preprocessor, which is available in the
|
||||||
|
Inno Setup QuickStart Pack.
|
||||||
|
|
||||||
|
Add the directory containing iscc.exe (for instance,
|
||||||
|
C:\Program Files\Inno Setup 5) to the system or user PATH environment
|
||||||
|
variable prior to building KasmVNC.
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
Out-of-Tree Builds
|
||||||
|
==================
|
||||||
|
|
||||||
|
Binary objects, libraries, and executables are generated in the same directory
|
||||||
|
from which cmake was executed (the "binary directory"), and this directory need
|
||||||
|
not necessarily be the same as the KasmVNC source directory. You can create
|
||||||
|
multiple independent binary directories, in which different versions of
|
||||||
|
KasmVNC can be built from the same source tree using different compilers or
|
||||||
|
settings. In the sections below, {build_directory} refers to the binary
|
||||||
|
directory, whereas {source_directory} refers to the KasmVNC source directory.
|
||||||
|
For in-tree builds, these directories are the same.
|
||||||
|
|
||||||
|
|
||||||
|
=================
|
||||||
|
Building KasmVNC
|
||||||
|
=================
|
||||||
|
|
||||||
|
|
||||||
|
Building the KasmVNC Server on Modern Unix/Linux Systems
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
Building the KasmVNC Server (Xvnc) is a bit trickier. On newer systems
|
||||||
|
containing Xorg 7.4 or later (such as Fedora), Xvnc is typically built to use
|
||||||
|
the X11 shared libraries provided with the system. The procedure for this is
|
||||||
|
system-specific, since it requires specifying such things as font directories,
|
||||||
|
but the general outline is as follows.
|
||||||
|
|
||||||
|
> cd {build_directory}
|
||||||
|
|
||||||
|
If performing an out-of-tree build:
|
||||||
|
> mkdir unix
|
||||||
|
> cp -R {source_directory}/unix/xserver unix/
|
||||||
|
|
||||||
|
> cp -R {xorg_source}/* unix/xserver/
|
||||||
|
(NOTE: {xorg_source} is the directory containing the Xorg source for the
|
||||||
|
machine on which you are building KasmVNC. The most recent versions of
|
||||||
|
Red Hat/CentOS/Fedora, for instance, provide an RPM called
|
||||||
|
"xorg-x11-server-source", which installs the Xorg source under
|
||||||
|
/usr/share/xorg-x11-server-source.)
|
||||||
|
|
||||||
|
> cd unix/xserver/
|
||||||
|
> patch -p1 < {source_directory}/unix/xserver{version}.patch
|
||||||
|
(where {version} matches the X server version you are building, such as
|
||||||
|
"17" for version 1.7.x.)
|
||||||
|
> autoreconf -fiv
|
||||||
|
|
||||||
|
> ./configure --with-pic --without-dtrace --disable-static --disable-dri \
|
||||||
|
--disable-xinerama --disable-xvfb --disable-xnest --disable-xorg \
|
||||||
|
--disable-dmx --disable-xwin --disable-xephyr --disable-kdrive \
|
||||||
|
--disable-config-dbus --disable-config-hal --disable-config-udev \
|
||||||
|
--disable-dri2 --enable-install-libxf86config --enable-glx \
|
||||||
|
--with-default-font-path="catalogue:/etc/X11/fontpath.d,built-ins" \
|
||||||
|
--with-fontdir=/usr/share/X11/fonts \
|
||||||
|
--with-xkb-path=/usr/share/X11/xkb \
|
||||||
|
--with-xkb-output=/var/lib/xkb \
|
||||||
|
--with-xkb-bin-directory=/usr/bin \
|
||||||
|
--with-serverconfig-path=/usr/lib[64]/xorg \
|
||||||
|
--with-dri-driver-path=/usr/lib[64]/dri \
|
||||||
|
{additional configure options}
|
||||||
|
(NOTE: This is merely an example that works with Red Hat Enterprise/CentOS
|
||||||
|
6 and recent Fedora releases. You should customize it for your particular
|
||||||
|
system. In particular, it will be necessary to customize the font, XKB,
|
||||||
|
and DRI directories.)
|
||||||
|
|
||||||
|
> make KASMVNC_SRCDIR={source_directory}
|
||||||
|
|
||||||
|
|
||||||
|
Building the KasmVNC Server on Legacy Unix/Linux Systems
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
Those using systems with older versions of Xorg must build a "legacy-friendly"
|
||||||
|
version of the KasmVNC Server. This is accomplished by downloading and
|
||||||
|
building the more recent Xorg modules in a local directory and then building
|
||||||
|
Xvnc such that it links against the local build of these libraries, not the X11
|
||||||
|
libraries installed on the system. The "build-xorg" script in the KasmVNC
|
||||||
|
source distribution (located under contrib/xorg/) automates this process.
|
||||||
|
|
||||||
|
The following procedure will build a
|
||||||
|
"legacy-friendly" version of the KasmVNC Server:
|
||||||
|
|
||||||
|
cd {build_directory}
|
||||||
|
sh {source_directory}/contrib/xorg/build-xorg init
|
||||||
|
sh {source_directory}/contrib/xorg/build-xorg build [additional CMake flags]
|
||||||
|
|
||||||
|
build-xorg generates a version of Xvnc that has no external dependencies on the
|
||||||
|
X11 shared libraries or any other distribution-specific shared libraries. This
|
||||||
|
version of Xvnc should be transportable across multiple O/S distributions.
|
||||||
|
build-xorg should work on Red Hat Enterprise 4, its contemporaries, and later
|
||||||
|
systems. It probably will not work on older systems. It has not been tested
|
||||||
|
on non-Linux systems (yet).
|
||||||
|
|
||||||
|
build-xorg can also be used to rebuild just the KasmVNC Server,
|
||||||
|
once the X11 modules and other dependencies have been built for the first time.
|
||||||
|
This is convenient for testing changes that just apply to the KasmVNC source
|
||||||
|
code. To accomplish this, run:
|
||||||
|
|
||||||
|
sh {source_directory}/contrib/xorg/build-xorg rebuild [additional make flags]
|
||||||
|
|
||||||
|
For instance,
|
||||||
|
|
||||||
|
sh {source_directory}/contrib/xorg/build-xorg rebuild clean
|
||||||
|
|
||||||
|
will clean the Xvnc build without destroying any of the
|
||||||
|
build configuration or module dependencies.
|
||||||
|
|
||||||
|
|
||||||
|
Debug Build
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Add "-DCMAKE_BUILD_TYPE=Debug" to the CMake command line.
|
||||||
|
|
||||||
|
|
||||||
|
Portable (semi-static) Build
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
KasmVNC can under favourble circumstances be built in a way that allows
|
||||||
|
the resulting binaries to run on any system without having to also install
|
||||||
|
all the dynamic libraries it depends on. Enable this mode by adding:
|
||||||
|
|
||||||
|
-DBUILD_STATIC=1
|
||||||
|
|
||||||
|
to the CMake command line.
|
||||||
|
|
||||||
|
Note that the method used to achieve this is very fragile and it may be
|
||||||
|
necessary to tweak cmake/StaticBuild.cmake to make things work on your
|
||||||
|
specific system.
|
||||||
|
|
||||||
|
|
||||||
|
======================================
|
||||||
|
Building TLS Support
|
||||||
|
======================================
|
||||||
|
|
||||||
|
TLS requires GnuTLS, which is supplied with most Linux distributions and
|
||||||
|
with MinGW for Windows and can be built from source on OS X and other
|
||||||
|
Unix variants. However, GnuTLS versions > 2.12.x && < 3.3.x should be
|
||||||
|
avoided because of potential incompatibilities during initial handshaking.
|
||||||
|
|
||||||
|
You can override the GNUTLS_LIBRARY and GNUTLS_INCLUDE_DIR CMake variables
|
||||||
|
to specify the locations of libgnutls and any dependencies. For instance,
|
||||||
|
adding
|
||||||
|
|
||||||
|
-DGNUTLS_INCLUDE_DIR=/usr/local/include \
|
||||||
|
-DGNUTLS_LIBRARY=/usr/local/lib/libgnutls.a
|
||||||
|
|
||||||
|
to the CMake command line would link KasmVNC against a static version of
|
||||||
|
libgnutls located under /usr/local.
|
||||||
|
|
||||||
|
|
||||||
|
======================================
|
||||||
|
Building Native Language Support (NLS)
|
||||||
|
======================================
|
||||||
|
|
||||||
|
NLS requires gettext, which is supplied with most Linux distributions and
|
||||||
|
with MinGW for Windows and which can easily be built from source on OS X and
|
||||||
|
other Unix variants.
|
||||||
|
|
||||||
|
You can override the ICONV_LIBRARIES and LIBINTL_LIBRARY CMake variables to
|
||||||
|
specify the locations of libiconv and libintl, respectively. For instance,
|
||||||
|
adding
|
||||||
|
|
||||||
|
-DLIBINTL_LIBRARY=/opt/gettext/lib/libintl.a
|
||||||
|
|
||||||
|
to the CMake command line would link KasmVNC against a static version of
|
||||||
|
libintl located under /opt/gettext. Adding
|
||||||
|
|
||||||
|
-DICONV_INCLUDE_DIR=/mingw/include \
|
||||||
|
-DICONV_LIBRARIES=/mingw/lib/libiconv.a \
|
||||||
|
-DGETTEXT_INCLUDE_DIR=/mingw/include \
|
||||||
|
-DLIBINTL_LIBRARY=/mingw/lib/libintl.a
|
||||||
|
|
||||||
|
to the CMake command line would link KasmVNC against the static versions of
|
||||||
|
libiconv and libintl included in the MinGW Developer Toolkit.
|
||||||
|
|
||||||
|
|
||||||
|
===================
|
||||||
|
Installing KasmVNC
|
||||||
|
===================
|
||||||
|
|
||||||
|
You can use the build system to install KasmVNC into a directory of your
|
||||||
|
choosing. To do this, add:
|
||||||
|
|
||||||
|
-DCMAKE_INSTALL_PREFIX={install_directory}
|
||||||
|
|
||||||
|
to the CMake command line. Then, you can run 'make install' to build and
|
||||||
|
install it.
|
||||||
|
|
||||||
|
If you don't specify CMAKE_INSTALL_PREFIX, then the default is
|
||||||
|
c:\Program Files\KasmVNC on Windows and /usr/local on Unix.
|
||||||
|
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Creating Release Packages
|
||||||
|
=========================
|
||||||
|
|
||||||
|
The following commands can be used to create various types of release packages:
|
||||||
|
|
||||||
|
|
||||||
|
Unix
|
||||||
|
----
|
||||||
|
|
||||||
|
make tarball
|
||||||
|
|
||||||
|
Create a binary tarball containing the utils
|
||||||
|
|
||||||
|
make servertarball
|
||||||
|
|
||||||
|
Create a binary tarball containing both the KasmVNC Server and utils
|
||||||
|
|
||||||
|
make dmg
|
||||||
|
|
||||||
|
Create Macintosh disk image file that contains an application bundle of the
|
||||||
|
utils
|
||||||
|
|
||||||
|
make udmg
|
||||||
|
|
||||||
|
On 64-bit OS X systems, this creates a version of the Macintosh package and
|
||||||
|
disk image which contains universal i386/x86-64 binaries. You should first
|
||||||
|
configure a 32-bit out-of-tree build of KasmVNC, then configure a 64-bit
|
||||||
|
out-of-tree build, then run 'make udmg' from the 64-bit build directory. The
|
||||||
|
build system will look for the 32-bit build under {source_directory}/osxx86
|
||||||
|
by default, but you can override this by setting the OSX_X86_BUILD CMake
|
||||||
|
variable to the directory containing your configured 32-bit build. Either
|
||||||
|
the 64-bit or 32-bit build can be configured to be backward compatible by
|
||||||
|
using the instructions in the "Build Recipes" section.
|
||||||
|
|
||||||
|
|
||||||
|
Windows
|
||||||
|
-------
|
||||||
|
|
||||||
|
make installer
|
||||||
|
|
||||||
|
Create a Windows installer using Inno Setup. The installer package
|
||||||
|
(KasmVNC[64].exe) will be located under {build_directory}.
|
||||||
|
|
||||||
|
|
||||||
|
=============
|
||||||
|
Build Recipes
|
||||||
|
=============
|
||||||
|
|
||||||
|
|
||||||
|
32-bit Build on 64-bit Linux/Unix (including OS X)
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Set the following environment variables before building KasmVNC.
|
||||||
|
|
||||||
|
CFLAGS='-O3 -m32'
|
||||||
|
CXXFLAGS='-O3 -m32'
|
||||||
|
LDFLAGS=-m32
|
||||||
|
|
||||||
|
If you are building the KasmVNC Server on a modern Unix/Linux system, then
|
||||||
|
you will also need to pass the appropriate --host argument when configuring the
|
||||||
|
X server source (for instance, --host=i686-pc-linux-gnu).
|
||||||
|
|
||||||
|
|
||||||
|
64-bit Backward-Compatible Build on 64-bit OS X
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
Add
|
||||||
|
|
||||||
|
-DCMAKE_OSX_SYSROOT=/Developer/SDKs/MacOSX10.5.sdk \
|
||||||
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.5
|
||||||
|
|
||||||
|
to the CMake command line. The OS X 10.5 SDK must be installed.
|
||||||
|
|
||||||
|
|
||||||
|
32-bit Backward-Compatible Build on 64-bit OS X
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
Set the following environment variables:
|
||||||
|
|
||||||
|
CC=gcc-4.0
|
||||||
|
CXX=g++-4.0
|
||||||
|
CFLAGS='-O3 -m32'
|
||||||
|
CXXFLAGS='-O3 -m32'
|
||||||
|
LDFLAGS=-m32
|
||||||
|
|
||||||
|
and add
|
||||||
|
|
||||||
|
-DCMAKE_OSX_SYSROOT=/Developer/SDKs/MacOSX10.4u.sdk \
|
||||||
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.4
|
||||||
|
|
||||||
|
to the CMake command line. The OS X 10.4 SDK must be installed.
|
||||||
|
|
||||||
|
|
||||||
|
64-bit MinGW Build on Cygwin
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
cd {build_directory}
|
||||||
|
CC=/usr/bin/x86_64-w64-mingw32-gcc CXX=/usr/bin/x86_64-w64-mingw32-g++ \
|
||||||
|
RC=/usr/bin/x86_64-w64-mingw32-windres \
|
||||||
|
cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME=Windows \
|
||||||
|
-DCMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar \
|
||||||
|
-DCMAKE_RANLIB=/usr/bin/x86_64-w64-mingw32-ranlib {source_directory}
|
||||||
|
make
|
||||||
|
|
||||||
|
This produces a 64-bit build of KasmVNC that does not depend on cygwin1.dll or
|
||||||
|
other Cygwin DLL's. The mingw64-x86_64-gcc-core and mingw64-x86_64-gcc-g++
|
||||||
|
packages (and their dependencies) must be installed.
|
||||||
|
|
||||||
|
|
||||||
|
32-bit MinGW Build on Cygwin
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
cd {build_directory}
|
||||||
|
CC=/usr/bin/i686-w64-mingw32-gcc CXX=/usr/bin/i686-w64-mingw32-g++ \
|
||||||
|
RC=/usr/bin/i686-w64-mingw32-windres \
|
||||||
|
cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME=Windows \
|
||||||
|
-DDCMAKE_AR=/usr/bin/i686-w64-mingw32-ar \
|
||||||
|
-DCMAKE_RANLIB=/usr/bin/i686-w64-mingw32-ranlib {source_directory}
|
||||||
|
make
|
||||||
|
|
||||||
|
This produces a 32-bit build of KasmVNC that does not depend on cygwin1.dll or
|
||||||
|
other Cygwin DLL's. The mingw64-i686-gcc-core and mingw64-i686-gcc-g++
|
||||||
|
packages (and their dependencies) must be installed.
|
||||||
|
|
||||||
|
|
||||||
|
MinGW-w64 Build on Windows
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
This produces a 64-bit build of KasmVNC using the "native" MinGW-w64 toolchain
|
||||||
|
(which is faster than the Cygwin version):
|
||||||
|
|
||||||
|
cd {build_directory}
|
||||||
|
CC={mingw-w64_binary_path}/x86_64-w64-mingw32-gcc \
|
||||||
|
CXX={mingw-w64_binary_path}/x86_64-w64-mingw32-g++ \
|
||||||
|
RC={mingw-w64_binary_path}/x86_64-w64-mingw32-windres \
|
||||||
|
cmake -G "MSYS Makefiles" \
|
||||||
|
-DCMAKE_AR={mingw-w64_binary_path}/x86_64-w64-mingw32-ar \
|
||||||
|
-DCMAKE_RANLIB={mingw-w64_binary_path}/x86_64-w64-mingw32-ranlib \
|
||||||
|
{source_directory}
|
||||||
|
make
|
||||||
|
|
||||||
|
|
||||||
|
MinGW Build on Linux
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
cd {build_directory}
|
||||||
|
CC={mingw_binary_path}/i386-mingw32-gcc \
|
||||||
|
CXX={mingw_binary_path}/i386-mingw32-g++ \
|
||||||
|
RC={mingw_binary_path}/i386-mingw32-windres \
|
||||||
|
cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME=Windows \
|
||||||
|
-DCMAKE_AR={mingw_binary_path}/i386-mingw32-ar \
|
||||||
|
-DCMAKE_RANLIB={mingw_binary_path}/i386-mingw32-ranlib \
|
||||||
|
{source_directory}
|
||||||
|
make
|
||||||
|
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Distribution-Specific Packaging
|
||||||
|
===============================
|
||||||
|
|
||||||
|
|
||||||
|
RPM Packages for RHEL / CentOS
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
The RPM spec files and patches used to create the nightly builds
|
||||||
|
and releases can be found in the "contrib/rpm/el{5,6}" directories
|
||||||
|
of the KasmVNC subversion trunk. All external source tarballs
|
||||||
|
must be fetched manually and placed into the 'SOURCES' directory
|
||||||
|
under the rpmbuild root. Additionally, the following macros need
|
||||||
|
to be defined:
|
||||||
|
|
||||||
|
EL6:
|
||||||
|
%debug_package %{nil}
|
||||||
|
|
||||||
|
EL5:
|
||||||
|
%dist .el5
|
||||||
|
%_smp_mflags -j3
|
||||||
|
%debug_package %{nil}
|
||||||
|
%__arch_install_post /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot
|
||||||
|
|
||||||
|
|
||||||
|
Debian packages for Ubuntu 12.04LTS
|
||||||
|
-----------------------------------
|
||||||
|
The debian folder used to create the nightly builds and releases
|
||||||
|
can be found in the "contrib/deb/ubuntu-precise" directory of the
|
||||||
|
KasmVNC subversion trunk.
|
242
CMakeLists.txt
Normal file
242
CMakeLists.txt
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
#
|
||||||
|
# Setup
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
if(POLICY CMP0022)
|
||||||
|
cmake_policy(SET CMP0022 OLD)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Internal cmake modules
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
|
||||||
|
|
||||||
|
include(CheckIncludeFiles)
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
include(CheckLibraryExists)
|
||||||
|
include(CheckTypeSize)
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
include(CheckCSourceRuns)
|
||||||
|
|
||||||
|
include(CMakeMacroLibtoolFile)
|
||||||
|
|
||||||
|
project(kasmvnc)
|
||||||
|
set(VERSION 0.9)
|
||||||
|
|
||||||
|
# The RC version must always be four comma-separated numbers
|
||||||
|
set(RCVERSION 0,9,0,0)
|
||||||
|
|
||||||
|
# Installation paths
|
||||||
|
set(BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share")
|
||||||
|
set(MAN_DIR "${DATA_DIR}/man")
|
||||||
|
set(LOCALE_DIR "${DATA_DIR}/locale")
|
||||||
|
set(DOC_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${CMAKE_PROJECT_NAME}-${VERSION}")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(BIN_DIR "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
set(DOC_DIR "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
message(FATAL_ERROR "KasmVNC cannot be built with Visual Studio. Please use MinGW")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT BUILD_TIMESTAMP)
|
||||||
|
set(BUILD_TIMESTAMP "")
|
||||||
|
execute_process(COMMAND "date" "+%Y-%m-%d %H:%M" OUTPUT_VARIABLE BUILD_TIMESTAMP)
|
||||||
|
string(REGEX REPLACE "\n" "" BUILD_TIMESTAMP ${BUILD_TIMESTAMP})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Default to optimised builds instead of debug ones. Our code has no bugs ;)
|
||||||
|
# (CMake makes it fairly easy to toggle this back to Debug if needed)
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
|
message(STATUS "VERSION = ${VERSION}")
|
||||||
|
message(STATUS "BUILD_TIMESTAMP = ${BUILD_TIMESTAMP}")
|
||||||
|
add_definitions(-DBUILD_TIMESTAMP="${BUILD_TIMESTAMP}")
|
||||||
|
|
||||||
|
message(STATUS "WWWDIR = ${DATA_DIR}/kasmvnc/www")
|
||||||
|
add_definitions(-DWWWDIR="${DATA_DIR}/kasmvnc/www")
|
||||||
|
|
||||||
|
# We want to keep our asserts even in release builds so remove NDEBUG
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -UNDEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -UNDEBUG")
|
||||||
|
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -UNDEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -UNDEBUG")
|
||||||
|
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -UNDEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -UNDEBUG")
|
||||||
|
|
||||||
|
# Make sure we get a sane C version
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
|
||||||
|
|
||||||
|
# Enable OpenMP
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
|
||||||
|
|
||||||
|
# Tell the compiler to be stringent
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wformat=2")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wformat=2")
|
||||||
|
# Make sure we catch these issues whilst developing
|
||||||
|
IF(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
option(ENABLE_ASAN "Enable address sanitizer support" OFF)
|
||||||
|
if(ENABLE_ASAN AND NOT WIN32 AND NOT APPLE)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_TSAN "Enable thread sanitizer support" OFF)
|
||||||
|
if(ENABLE_TSAN AND NOT WIN32 AND NOT APPLE AND CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED BUILD_WINVNC)
|
||||||
|
set(BUILD_WINVNC 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Minimum version is Windows Vista/2008 (6.0)
|
||||||
|
if(WIN32)
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||||
|
message(STATUS "64-bit build")
|
||||||
|
else()
|
||||||
|
message(STATUS "32-bit build")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Versions of CMake before 2.8.7 do not properly support resource compilation
|
||||||
|
# with MinGW. Boo!
|
||||||
|
if(MINGW AND "${CMAKE_VERSION}" VERSION_LESS "2.8.7")
|
||||||
|
if(NOT DEFINED RC)
|
||||||
|
set(CMAKE_RC_COMPILER_INIT windres)
|
||||||
|
else()
|
||||||
|
set(CMAKE_RC_COMPILER_INIT ${RC})
|
||||||
|
endif()
|
||||||
|
enable_language(RC)
|
||||||
|
message(STATUS "Resource compiler: ${CMAKE_RC_COMPILER}")
|
||||||
|
set(CMAKE_RC_COMPILE_OBJECT
|
||||||
|
"<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -o <OBJECT> --output-format=coff <SOURCE>")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# MinGW64 has header support but no library support for IActiveDesktop, so we
|
||||||
|
# need to check for both the header and library and use our own implementation
|
||||||
|
# in common/os if either doesn't exist.
|
||||||
|
if(WIN32)
|
||||||
|
check_c_source_compiles("#include <windows.h>\n#include <wininet.h>\n#include <shlobj.h>\nint main(int c, char** v) {IActiveDesktop iad; (void)iad; return 0;}" HAVE_ACTIVE_DESKTOP_H)
|
||||||
|
check_c_source_compiles("#include <windows.h>\n#include <wininet.h>\n#include <shlobj.h>\nint main(int c, char** v) {GUID i = CLSID_ActiveDesktop; (void)i; return 0;}" HAVE_ACTIVE_DESKTOP_L)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# X11 stuff. It's in a if() so that we can say REQUIRED
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
find_package(X11 REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for zlib
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
|
# Check for libjpeg
|
||||||
|
find_package(JPEG REQUIRED)
|
||||||
|
|
||||||
|
# Warn if it doesn't seem to be the accelerated libjpeg that's found
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${JPEG_LIBRARIES})
|
||||||
|
set(CMAKE_REQUIRED_FLAGS -I${JPEG_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(JPEG_TEST_SOURCE "\n
|
||||||
|
#include <stdio.h>\n
|
||||||
|
#include <jpeglib.h>\n
|
||||||
|
int main(void) {\n
|
||||||
|
struct jpeg_compress_struct cinfo;\n
|
||||||
|
struct jpeg_error_mgr jerr;\n
|
||||||
|
cinfo.err=jpeg_std_error(&jerr);\n
|
||||||
|
jpeg_create_compress(&cinfo);\n
|
||||||
|
cinfo.input_components = 3;\n
|
||||||
|
jpeg_set_defaults(&cinfo);\n
|
||||||
|
cinfo.in_color_space = JCS_EXT_RGB;\n
|
||||||
|
jpeg_default_colorspace(&cinfo);\n
|
||||||
|
return 0;\n
|
||||||
|
}")
|
||||||
|
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
check_c_source_compiles("${JPEG_TEST_SOURCE}" FOUND_LIBJPEG_TURBO)
|
||||||
|
else()
|
||||||
|
check_c_source_runs("${JPEG_TEST_SOURCE}" FOUND_LIBJPEG_TURBO)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
set(CMAKE_REQUIRED_DEFINITIONS)
|
||||||
|
|
||||||
|
if(NOT FOUND_LIBJPEG_TURBO)
|
||||||
|
message(STATUS "WARNING: You are not using libjpeg-turbo. Performance will suffer.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(${JPEG_INCLUDE_DIR})
|
||||||
|
|
||||||
|
# Check for GNUTLS library
|
||||||
|
option(ENABLE_GNUTLS "Enable protocol encryption and advanced authentication" ON)
|
||||||
|
if(ENABLE_GNUTLS)
|
||||||
|
find_package(GnuTLS)
|
||||||
|
if (GNUTLS_FOUND)
|
||||||
|
include_directories(${GNUTLS_INCLUDE_DIR})
|
||||||
|
add_definitions("-DHAVE_GNUTLS")
|
||||||
|
add_definitions(${GNUTLS_DEFINITIONS})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for PAM library
|
||||||
|
option(ENABLE_PAM "Enable PAM authentication support" ON)
|
||||||
|
if(ENABLE_PAM)
|
||||||
|
check_include_files(security/pam_appl.h HAVE_PAM_H)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES -lpam)
|
||||||
|
check_function_exists(pam_start HAVE_PAM_START)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
if(HAVE_PAM_H AND HAVE_PAM_START)
|
||||||
|
set(PAM_LIBS pam)
|
||||||
|
else()
|
||||||
|
set(ENABLE_PAM 0)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set(HAVE_PAM ${ENABLE_PAM})
|
||||||
|
|
||||||
|
# Generate config.h and make sure the source finds it
|
||||||
|
configure_file(config.h.in config.h)
|
||||||
|
add_definitions(-DHAVE_CONFIG_H)
|
||||||
|
include_directories(${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
include(cmake/StaticBuild.cmake)
|
||||||
|
|
||||||
|
add_subdirectory(common)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
add_subdirectory(win)
|
||||||
|
else()
|
||||||
|
# No interest in building x related parts on Apple
|
||||||
|
if(NOT APPLE)
|
||||||
|
add_subdirectory(unix)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_NLS)
|
||||||
|
add_subdirectory(po)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(tests)
|
||||||
|
|
||||||
|
|
||||||
|
include(cmake/BuildPackages.cmake)
|
||||||
|
|
||||||
|
# uninstall
|
||||||
|
configure_file("${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||||
|
"cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P cmake_uninstall.cmake)
|
340
LICENCE.TXT
Normal file
340
LICENCE.TXT
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
Appendix: How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) 19yy <name of author>
|
||||||
|
|
||||||
|
This program 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 program 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 program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
194
README.md
Normal file
194
README.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# KasmVNC - Linux Web Remote Desktop
|
||||||
|
|
||||||
|
[![Kasm Technologies](https://kasm-static-content.s3.amazonaws.com/368_kasm_logo_.jpg "Kasm Logo")](https://kasmweb.com)
|
||||||
|
|
||||||
|
[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.
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
# New Features!
|
||||||
|
|
||||||
|
- Webp image compression for better bandwidth usage
|
||||||
|
- Automatic mixing of webp and jpeg based on CPU availability on server
|
||||||
|
- Multi-threaded image encoding for smoother frame rate for servers with more cores
|
||||||
|
- Full screen video detection, goes into configurable video mode for better full screen videoo playback performance.
|
||||||
|
- Dynamic jpeg/webp image coompression quality settings based on screen change rates
|
||||||
|
- Seemless clipboard support
|
||||||
|
- Allow client to set/change most configuration settings
|
||||||
|
- Data Loss Prevention features
|
||||||
|
- Key stroke logging
|
||||||
|
- Clipboard logging
|
||||||
|
- Max clipboard transfer size up and down
|
||||||
|
- Min time between clipboard operations required
|
||||||
|
- Keyboard input rate limit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Future Goals:
|
||||||
|
|
||||||
|
- Support uploads and downloads
|
||||||
|
- Json configuration file
|
||||||
|
- Pre-build Packages for all major Linux distributions
|
||||||
|
- CI pipelines to create releases
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
We are currently developing releasable packages for major operating sytems. The install script available with releases will install dependencies, compile webp, and pull down and install the pre-compiled KasmVNC tarball. Currently, only Ubuntu 18.04 LTS is pre-compiled.
|
||||||
|
|
||||||
|
This installer assumes you already have a desktop environment installed, but have never configured a VNC server.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# download install script from releases
|
||||||
|
sudo ./install.sh
|
||||||
|
|
||||||
|
# change owner of pre-installed cert to your user
|
||||||
|
sudo chown $USER /usr/local/share/kasmvnc/certs/self.pem
|
||||||
|
|
||||||
|
# create required files
|
||||||
|
touch ~/.Xresources
|
||||||
|
# start kasmvnc to generate the required files and then kill it
|
||||||
|
# it will prompt to set the vnc password
|
||||||
|
vncserver :1 -interface 0.0.0.0
|
||||||
|
vncserver -kill :1
|
||||||
|
|
||||||
|
# overwrite the VNC password to nothing. KasmVNC uses HTTPS basic authentication
|
||||||
|
echo '' | vncpasswd -f > $HOME/.vnc/passwd
|
||||||
|
|
||||||
|
# modify vncstartup to launch your environment of choice, in this example LXDE
|
||||||
|
echo '/usr/bin/lxsession -s LXDE &' >> ~/.vnc/xstartup
|
||||||
|
|
||||||
|
# launch KasmVNC
|
||||||
|
vncserver $DISPLAY -depth 24 -geometry 1280x1050 -basicAuth kasm_user:password -websocketPort 8443 -cert /usr/local/share/kasmvnc/certs/self.pem -sslOnly -FrameRate=24 -interface 0.0.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
The options for vncserver in the example above:
|
||||||
|
|
||||||
|
| Argument | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| depth | Color depth, for jpeg/webp should be 24bit |
|
||||||
|
| geometry | Screensize, this will automatically be adjusted when the client connects. |
|
||||||
|
| basicAuth | Username and password seperated by a semi-colon. |
|
||||||
|
| websocketPort | The port to use for the web socket. Use a high port to avoid having to run as root. |
|
||||||
|
| cert | SSL cert to use for HTTPS |
|
||||||
|
| sslOnly | Disable HTTP |
|
||||||
|
| interface | Which interface to bind the web server to. |
|
||||||
|
|
||||||
|
### Development
|
||||||
|
Would you like to contribute to KasmVNC? Please reachout to us at info@kasmweb.com
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Compiling From Source
|
||||||
|
See the builder/README.md. We containerize our build systems to ensure highly repeatable builds.
|
||||||
|
|
||||||
|
License & Legal
|
||||||
|
----
|
||||||
|
Incomplete and generally out of date copyright list::
|
||||||
|
|
||||||
|
Copyright (C) 2020 Kasm Technologies LLC
|
||||||
|
Copyright (C) 1999 AT&T Laboratories Cambridge
|
||||||
|
Copyright (C) 2002-2005 RealVNC Ltd.
|
||||||
|
Copyright (C) 2000-2006 TightVNC Group
|
||||||
|
Copyright (C) 2005-2006 Martin Koegler
|
||||||
|
Copyright (C) 2005-2006 Sun Microsystems, Inc.
|
||||||
|
Copyright (C) 2006 OCCAM Financial Technology
|
||||||
|
Copyright (C) 2000-2008 Constantin Kaplinsky
|
||||||
|
Copyright (C) 2004-2017 Peter Astrand for Cendio AB
|
||||||
|
Copyright (C) 2010 Antoine Martin
|
||||||
|
Copyright (C) 2010 m-privacy GmbH
|
||||||
|
Copyright (C) 2009-2011 D. R. Commander
|
||||||
|
Copyright (C) 2009-2011 Pierre Ossman for Cendio AB
|
||||||
|
Copyright (C) 2004, 2009-2011 Red Hat, Inc.
|
||||||
|
Copyright (C) 2009-2018 TigerVNC Team
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
This software is distributed under the GNU General Public Licence as published
|
||||||
|
by the Free Software Foundation. See the file LICENCE.TXT for the conditions
|
||||||
|
under which this software is made available. KasmVNC also contains code from
|
||||||
|
other sources. See the Acknowledgements section below, and the individual
|
||||||
|
source files, for details of the conditions under which they are made
|
||||||
|
available.
|
||||||
|
|
||||||
|
### Acknoledgements
|
||||||
|
This distribution contains zlib compression software. This is:
|
||||||
|
|
||||||
|
Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
Jean-loup Gailly Mark Adler
|
||||||
|
jloup@gzip.org madler@alumni.caltech.edu
|
||||||
|
|
||||||
|
The data format used by the zlib library is described by RFCs (Request for
|
||||||
|
Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
|
||||||
|
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
|
||||||
|
|
||||||
|
|
||||||
|
This distribution contains public domain DES software by Richard Outerbridge.
|
||||||
|
This is:
|
||||||
|
|
||||||
|
Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
|
||||||
|
(GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
|
||||||
|
|
||||||
|
|
||||||
|
This distribution contains software from the X Window System. This is:
|
||||||
|
|
||||||
|
Copyright 1987, 1988, 1998 The Open Group
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
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
|
||||||
|
OPEN GROUP 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.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of The Open Group shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from The Open Group.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted,
|
||||||
|
provided that the above copyright notice appear in all copies and that
|
||||||
|
both that copyright notice and this permission notice appear in
|
||||||
|
supporting documentation, and that the name of Digital not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||||
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||||||
|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||||
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
SOFTWARE.
|
30
bitbucket-pipelines.yml
Normal file
30
bitbucket-pipelines.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
image: ubuntu:xenial
|
||||||
|
pipelines:
|
||||||
|
default:
|
||||||
|
- step:
|
||||||
|
name: Build and Package
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
script:
|
||||||
|
- export BASE_DIR="$(readlink -f .)"
|
||||||
|
- export RELEASE_VERSION=1.9
|
||||||
|
- export BUILD_FILE="kasmvnc_${RELEASE_VERSION}.${BITBUCKET_COMMIT}.tar.gz"
|
||||||
|
- export S3_BUILD_DIRECTORY="kasmvnc/${BITBUCKET_COMMIT}"
|
||||||
|
- export SANITIZED_BRANCH="$(echo $BITBUCKET_BRANCH | sed 's/\//_/g')"
|
||||||
|
- apt-get update
|
||||||
|
- apt-get install -y git python3 python3-pip python3-boto3 curl
|
||||||
|
- echo $SANITIZED_BRANCH
|
||||||
|
- docker build -t kasmvncbuilder:latest -f builder/dockerfile.build .
|
||||||
|
- docker run -v $BITBUCKET_CLONE_DIR:/build kasmvncbuilder:latest
|
||||||
|
- ls -la $BITBUCKET_CLONE_DIR
|
||||||
|
- ls -la $BITBUCKET_CLONE_DIR/kasmvnc-Linux-x86_64-*.tar.gz
|
||||||
|
- git clone https://bitbucket.org/awslabs/amazon-s3-bitbucket-pipelines-python.git
|
||||||
|
- python3 amazon-s3-bitbucket-pipelines-python/s3_upload.py "${S3_BUCKET}" $BITBUCKET_CLONE_DIR/kasmvnc-Linux-x86_64-*.tar.gz "${S3_BUILD_DIRECTORY}/${BUILD_FILE}"
|
||||||
|
- export S3_URL="https://${S3_BUCKET}.s3.amazonaws.com/${S3_BUILD_DIRECTORY}/${BUILD_FILE}"
|
||||||
|
- export BUILD_STATUS="{\"key\":\"doc\", \"state\":\"SUCCESSFUL\", \"name\":\"${BUILD_FILE}\", \"url\":\"${S3_URL}\"}"
|
||||||
|
- echo ${BITBUCKET_REPO_OWNER}
|
||||||
|
- echo ${BITBUCKET_REPO_SLUG}
|
||||||
|
- echo ${BITBUCKET_COMMIT}
|
||||||
|
- echo ${BB_AUTH_STRING}
|
||||||
|
- echo ${BUILD_STATUS}
|
||||||
|
- curl -H "Content-Type:application/json" -X POST --user "${BB_AUTH_STRING}" -d "${BUILD_STATUS}" "https://api.bitbucket.org/2.0/repositories/${BITBUCKET_REPO_OWNER}/${BITBUCKET_REPO_SLUG}/commit/${BITBUCKET_COMMIT}/statuses/build"
|
22
builder/README.md
Normal file
22
builder/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
REQIUREMENTS
|
||||||
|
Docker CE
|
||||||
|
|
||||||
|
# build the docker image
|
||||||
|
cd /src_code_root
|
||||||
|
sudo docker build -t kasmvncbuilder:18.04 -f builder/dockerfile.build .
|
||||||
|
|
||||||
|
# run the builder
|
||||||
|
sudo docker run -v /tmp:/build kasmvncbuilder:18.04
|
||||||
|
|
||||||
|
# tar will be on /tmp of host
|
||||||
|
cp /tmp/kasmvnc*.tar.gz builder/
|
||||||
|
|
||||||
|
# build test desktop container with new binary installed
|
||||||
|
cd builder
|
||||||
|
sudo docker build -t kasmvnctester:18.04 -f dockerfile.test .
|
||||||
|
|
||||||
|
# run an instance of the new destkop
|
||||||
|
sudo docker run -d -p 80:6901 -p 5901:5901 -e VNCOPTIONS="-detectScrolling -PreferBandwidth -DynamicQualityMin=0" kasmvnctester:latest
|
||||||
|
|
||||||
|
open browser and point to http://IPAddress/vnc_lite.html
|
||||||
|
default password is "vncpassword" or use a VNC client
|
66
builder/build.sh
Executable file
66
builder/build.sh
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
# For build-dep to work, the apt sources need to have the source server
|
||||||
|
#sudo apt-get build-dep xorg-server
|
||||||
|
|
||||||
|
#sudo apt-get install cmake git libjpeg-dev libgnutls-dev
|
||||||
|
|
||||||
|
# Ubuntu applies a million patches, but here we use upstream to simplify matters
|
||||||
|
cd /tmp
|
||||||
|
wget https://www.x.org/archive//individual/xserver/xorg-server-1.18.4.tar.bz2
|
||||||
|
|
||||||
|
#git clone https://kasmweb@bitbucket.org/kasmtech/kasmvnc.git
|
||||||
|
#cd kasmvnc
|
||||||
|
#git checkout dynjpeg
|
||||||
|
cd /src
|
||||||
|
|
||||||
|
# We only want the server, so FLTK and manual tests aren't useful.
|
||||||
|
# Alternatively, install fltk 1.3 and its dev packages.
|
||||||
|
sed -i -e '/find_package(FLTK/s@^@#@' \
|
||||||
|
-e '/add_subdirectory(tests/s@^@#@' \
|
||||||
|
CMakeLists.txt
|
||||||
|
|
||||||
|
cmake .
|
||||||
|
make -j5
|
||||||
|
|
||||||
|
tar -C unix/xserver -xvf /tmp/xorg-server-1.18.4.tar.bz2 --strip-components=1
|
||||||
|
|
||||||
|
cd unix/xserver
|
||||||
|
patch -Np1 -i ../xserver118.patch
|
||||||
|
autoreconf -i
|
||||||
|
# Configuring Xorg is long and has many distro-specific paths.
|
||||||
|
# The distro paths start after prefix and end with the font path,
|
||||||
|
# everything after that is based on BUILDING.txt to remove unneeded
|
||||||
|
# components.
|
||||||
|
./configure --prefix=/opt/kasmweb \
|
||||||
|
--with-xkb-path=/usr/share/X11/xkb \
|
||||||
|
--with-xkb-output=/var/lib/xkb \
|
||||||
|
--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-pic --without-dtrace --disable-static --disable-dri \
|
||||||
|
--disable-xinerama --disable-xvfb --disable-xnest --disable-xorg \
|
||||||
|
--disable-dmx --disable-xwin --disable-xephyr --disable-kdrive \
|
||||||
|
--disable-config-hal --disable-config-udev \
|
||||||
|
--disable-dri2 --enable-glx --disable-xwayland --disable-dri3
|
||||||
|
make -j5
|
||||||
|
|
||||||
|
# modifications for the servertarball
|
||||||
|
cd /src
|
||||||
|
mkdir -p xorg.build/bin
|
||||||
|
cd xorg.build/bin/
|
||||||
|
ln -s /src/unix/xserver/hw/vnc/Xvnc Xvnc
|
||||||
|
cd ..
|
||||||
|
mkdir -p man/man1
|
||||||
|
touch man/man1/Xserver.1
|
||||||
|
touch man/man1/Xvnc.1
|
||||||
|
mkdir lib
|
||||||
|
cd lib
|
||||||
|
ln -s /usr/lib/x86_64-linux-gnu/dri dri
|
||||||
|
cd /src
|
||||||
|
sed $'s#pushd $TMPDIR/inst#CWD=$(pwd)\\\ncd $TMPDIR/inst#' release/maketarball > release/maketarball2
|
||||||
|
sed $'s#popd#cd $CWD#' release/maketarball2 > release/maketarball3
|
||||||
|
mv release/maketarball3 release/maketarball
|
||||||
|
|
||||||
|
make servertarball
|
||||||
|
|
||||||
|
cp kasmvnc*.tar.gz /build/
|
20
builder/build_and_deploy_kasm.sh
Executable file
20
builder/build_and_deploy_kasm.sh
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# this script will build kasmvnc and build a new kasm desktop image
|
||||||
|
# this script assumes you have an instance of kasm already deployed
|
||||||
|
# it will replace the existing kasm desktop image so the next kasm you launch will use the updated image
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "This script must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker build -t kasmvncbuilder:latest -f builder/dockerfile.build .
|
||||||
|
docker run -v /tmp:/build kasmvncbuilder:latest
|
||||||
|
cp /tmp/kasmvnc*.tar.gz builder/
|
||||||
|
cd builder
|
||||||
|
docker build -t kasmweb/desktop-deluxe:develop -f dockerfile.test .
|
||||||
|
docker ps -aq --no-trunc -f status=exited | xargs docker rm
|
||||||
|
docker rmi $(docker images | grep "<none>" | awk "{print $3}")
|
22
builder/dockerfile.16.04.build
Normal file
22
builder/dockerfile.16.04.build
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
FROM ubuntu:16.04
|
||||||
|
|
||||||
|
RUN sed -i 's$# deb-src$deb-src$' /etc/apt/sources.list
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get -y install sudo
|
||||||
|
|
||||||
|
RUN apt-get -y build-dep xorg-server
|
||||||
|
RUN apt-get -y install cmake git libjpeg-dev libgnutls-dev vim wget tightvncserver
|
||||||
|
RUN apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev
|
||||||
|
RUN cd /tmp && wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
|
||||||
|
RUN cd /tmp && tar -xzvf /tmp/libwebp-*
|
||||||
|
RUN cd /tmp/libwebp-1.0.2 && ./configure && make && make install
|
||||||
|
|
||||||
|
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
|
||||||
|
|
||||||
|
COPY . /src
|
||||||
|
RUN chown -R docker:docker /src
|
||||||
|
|
||||||
|
|
||||||
|
USER docker
|
||||||
|
ENTRYPOINT ["/src/builder/build.sh"]
|
29
builder/dockerfile.build
Normal file
29
builder/dockerfile.build
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
FROM ubuntu:18.04
|
||||||
|
|
||||||
|
RUN sed -i 's$# deb-src$deb-src$' /etc/apt/sources.list
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get -y install sudo
|
||||||
|
|
||||||
|
RUN apt-get -y build-dep xorg-server libxfont-dev
|
||||||
|
RUN apt-get -y install cmake git libjpeg-dev libgnutls28-dev vim wget tightvncserver
|
||||||
|
RUN apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev libavcodec-dev libssl-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 -xzvf /tmp/libwebp-*
|
||||||
|
RUN cd /tmp/libwebp-1.0.2 && ./configure && 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 . /src
|
||||||
|
RUN chown -R docker:docker /src
|
||||||
|
|
||||||
|
USER docker
|
||||||
|
ENTRYPOINT ["/src/builder/build.sh"]
|
12
builder/dockerfile.test
Normal file
12
builder/dockerfile.test
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM kasmweb/desktop-deluxe:develop
|
||||||
|
|
||||||
|
ENV VNCOPTIONS "-PreferBandwidth -DynamicQualityMin=3 -DynamicQualityMax=7 -detectScrolling"
|
||||||
|
|
||||||
|
USER root
|
||||||
|
|
||||||
|
COPY kasmvnc-Linux-x86_64-*.tar.gz /tmp/
|
||||||
|
RUN tar -xzvf /tmp/kasmvnc-Linux-x86_64-*.tar.gz --strip 1 -C /
|
||||||
|
|
||||||
|
USER 1000
|
||||||
|
|
||||||
|
CMD ["--tail-log"]
|
79
builder/install/install.sh
Executable file
79
builder/install/install.sh
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
set -e
|
||||||
|
|
||||||
|
OS_ID='unknown'
|
||||||
|
OS_VERSION_ID='unknown'
|
||||||
|
SUPPORTED='false'
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "This script must ran with sudo"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
function install_deps_ubuntu_18(){
|
||||||
|
# install deps and build tools
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install libjpeg-dev libpng-dev libtiff-dev libgif-dev build-essential cmake libxfont-dev
|
||||||
|
|
||||||
|
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
|
||||||
|
sudo dpkg -i libxfont1*.deb
|
||||||
|
rm /tmp/libxfont1*.deb
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_webp(){
|
||||||
|
# build webp
|
||||||
|
wget https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.2.tar.gz
|
||||||
|
tar -xzvf /tmp/libwebp-*
|
||||||
|
cd /tmp/libwebp-1.0.2
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
cd /
|
||||||
|
rm -rf /tmp/libwebp*
|
||||||
|
sudo ldconfig
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_kasmvnc(){
|
||||||
|
# install kasmvnc
|
||||||
|
wget -qO- https://kasmweb-build-artifacts.s3.amazonaws.com/kasmvnc/c0ab0111ae47a39720f26a7dd7ac54a3681540f8/kasmvnc_1.9.c0ab0111ae47a39720f26a7dd7ac54a3681540f8.tar.gz | sudo tar xz --strip 1 -C /
|
||||||
|
#install cert
|
||||||
|
sudo mkdir /usr/local/share/kasmvnc/certs
|
||||||
|
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /usr/local/share/kasmvnc/certs/self.pem -out /usr/local/share/kasmvnc/certs/self.pem -subj "/C=US/ST=VA/L=None/O=None/OU=DoFu/CN=kasm/emailAddress=none@none.none"
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
# Get the OS and version
|
||||||
|
if [ -f /etc/os-release ] ; then
|
||||||
|
OS_ID="$(awk -F= '/^ID=/{print $2}' /etc/os-release)"
|
||||||
|
OS_VERSION_ID="$(awk -F= '/^VERSION_ID/{print $2}' /etc/os-release)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${OS_ID}" == "ubuntu" ] && ( [ "${OS_VERSION_ID}" == '"16.04"' ] || [ "${OS_VERSION_ID}" == '"18.04"' ] || [ "${OS_VERSION_ID}" == '"20.04"' ]) ; then
|
||||||
|
|
||||||
|
if [ "${OS_VERSION_ID}" == '"18.04"' ] ; then
|
||||||
|
SUPPORTED='true'
|
||||||
|
install_deps_ubuntu_18
|
||||||
|
build_webp
|
||||||
|
install_kasmvnc
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${OS_ID}" == "debian" ] && ( [ "${OS_VERSION_ID}" == '"9"' ] || [ "${OS_VERSION_ID}" == '"10"' ] ) ; then
|
||||||
|
#TODO: Add support for debian
|
||||||
|
echo 'Debian is currently not supported'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${OS_ID}" == '"centos"' ] && ( [ "${OS_VERSION_ID}" == '"7"' ] || [ "${OS_VERSION_ID}" == '"8"' ] ) ; then
|
||||||
|
#TODO: Add support for Centos
|
||||||
|
echo 'CentOS is currently not supported'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${SUPPORTED}" == "false" ] ; then
|
||||||
|
echo "Installation Not Supported for this Operating System. You must compile KasmVNC from source."
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Installation is complete"
|
||||||
|
echo "Follow the instructions to complete setup"
|
80
cmake/BuildPackages.cmake
Normal file
80
cmake/BuildPackages.cmake
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# This file is included from the top-level CMakeLists.txt. We just store it
|
||||||
|
# here to avoid cluttering up that file.
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Windows installer (Inno Setup)
|
||||||
|
#
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||||
|
set(INST_NAME ${CMAKE_PROJECT_NAME}64-${VERSION})
|
||||||
|
set(INST_DEFS -DWIN64)
|
||||||
|
else()
|
||||||
|
set(INST_NAME ${CMAKE_PROJECT_NAME}-${VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_WINVNC)
|
||||||
|
set(INST_DEFS ${INST_DEFS} -DBUILD_WINVNC)
|
||||||
|
set(INST_DEPS ${INST_DEPS} winvnc4 wm_hooks vncconfig)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file(release/kasmvnc.iss.in release/kasmvnc.iss)
|
||||||
|
|
||||||
|
add_custom_target(installer
|
||||||
|
iscc -o. ${INST_DEFS} -F${INST_NAME} release/kasmvnc.iss
|
||||||
|
DEPENDS ${INST_DEPS}
|
||||||
|
SOURCES release/kasmvnc.iss)
|
||||||
|
|
||||||
|
endif() # WIN32
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mac DMG
|
||||||
|
#
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
|
||||||
|
set(DEFAULT_OSX_X86_BUILD ${CMAKE_SOURCE_DIR}/osxx86)
|
||||||
|
set(OSX_X86_BUILD ${DEFAULT_OSX_X86_BUILD} CACHE PATH
|
||||||
|
"Directory containing 32-bit OS X build to include in universal binaries (default: ${DEFAULT_OSX_X86_BUILD})")
|
||||||
|
|
||||||
|
configure_file(release/makemacapp.in release/makemacapp)
|
||||||
|
configure_file(release/Info.plist.in release/Info.plist)
|
||||||
|
|
||||||
|
add_custom_target(dmg sh release/makemacapp
|
||||||
|
SOURCES release/makemacapp)
|
||||||
|
|
||||||
|
add_custom_target(udmg sh release/makemacapp universal
|
||||||
|
SOURCES release/makemacapp)
|
||||||
|
|
||||||
|
endif() # APPLE
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Binary tarball
|
||||||
|
#
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
|
||||||
|
configure_file(release/maketarball.in release/maketarball)
|
||||||
|
|
||||||
|
set(TARBALL_DEPENDS vncpasswd vncconfig)
|
||||||
|
|
||||||
|
add_custom_target(tarball sh release/maketarball
|
||||||
|
DEPENDS ${TARBALL_DEPENDS}
|
||||||
|
SOURCES release/maketarball)
|
||||||
|
|
||||||
|
add_custom_target(servertarball sh release/maketarball server
|
||||||
|
DEPENDS ${TARBALL_DEPENDS}
|
||||||
|
SOURCES release/maketarball)
|
||||||
|
|
||||||
|
endif() #UNIX
|
||||||
|
|
||||||
|
#
|
||||||
|
# Common
|
||||||
|
#
|
||||||
|
|
||||||
|
install(FILES ${CMAKE_SOURCE_DIR}/LICENCE.TXT DESTINATION ${DOC_DIR})
|
||||||
|
install(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION ${DOC_DIR})
|
145
cmake/Modules/CMakeMacroLibtoolFile.cmake
Normal file
145
cmake/Modules/CMakeMacroLibtoolFile.cmake
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
macro(libtool_create_control_file _target)
|
||||||
|
get_target_property(_target_type ${_target} TYPE)
|
||||||
|
|
||||||
|
message("-- Creating static libtool control file for target ${_target}")
|
||||||
|
# No support for shared libraries, as KasmVNC only needs libtool config
|
||||||
|
# files for static libraries.
|
||||||
|
if("${_target_type}" MATCHES "^[^STATIC_LIBRARY]$")
|
||||||
|
message(ERROR " - trying to use libtool_create_control_file for non-static library target.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parse the target_LIB_DEPENDS variable to determine which libraries to put
|
||||||
|
# into libtool control file as library dependencies, and handle a few corner
|
||||||
|
# cases.
|
||||||
|
#
|
||||||
|
|
||||||
|
# First we need to split up any internal entries
|
||||||
|
set(target_libs "")
|
||||||
|
foreach(library ${${_target}_LIB_DEPENDS})
|
||||||
|
if("${library}" MATCHES " ")
|
||||||
|
string(REPLACE " " ";" lib_list "${library}")
|
||||||
|
list(APPEND target_libs ${lib_list})
|
||||||
|
else()
|
||||||
|
list(APPEND target_libs "${library}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(STATIC_MODE OFF)
|
||||||
|
|
||||||
|
foreach(library ${target_libs})
|
||||||
|
# Assume all entries are shared libs if platform-specific static library
|
||||||
|
# extension is not matched.
|
||||||
|
if(NOT "${library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")
|
||||||
|
if("${library}" MATCHES ".+\\${CMAKE_SHARED_LIBRARY_SUFFIX}$")
|
||||||
|
# Shared library extension matched, so extract the path and library
|
||||||
|
# name, then add the result to the libtool dependency libs. This
|
||||||
|
# will always be an absolute path, because that's what CMake uses
|
||||||
|
# internally.
|
||||||
|
get_filename_component(_shared_lib ${library} NAME_WE)
|
||||||
|
get_filename_component(_shared_lib_path ${library} PATH)
|
||||||
|
string(REPLACE "lib" "" _shared_lib ${_shared_lib})
|
||||||
|
set(_target_dependency_libs "${_target_dependency_libs} -L${_shared_lib_path} -l${_shared_lib}")
|
||||||
|
else()
|
||||||
|
# No shared library extension matched. Check whether target is a CMake
|
||||||
|
# target.
|
||||||
|
if(TARGET ${library})
|
||||||
|
# Target is a CMake target, so ignore (CMake targets are static
|
||||||
|
# libs in KasmVNC.)
|
||||||
|
elseif(${library} STREQUAL "-Wl,-Bstatic")
|
||||||
|
# All following libraries should be static
|
||||||
|
set(STATIC_MODE ON)
|
||||||
|
elseif(${library} STREQUAL "-Wl,-Bdynamic")
|
||||||
|
# All following libraries should be dynamic
|
||||||
|
set(STATIC_MODE OFF)
|
||||||
|
else()
|
||||||
|
# Normal library, so use find_library() to attempt to locate the
|
||||||
|
# library in a system directory.
|
||||||
|
|
||||||
|
# Need to remove -l prefix
|
||||||
|
if (${library} MATCHES "^\\${CMAKE_LINK_LIBRARY_FLAG}")
|
||||||
|
string(REPLACE ${CMAKE_LINK_LIBRARY_FLAG} "" library ${library})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(STATIC_MODE)
|
||||||
|
set(library ${CMAKE_STATIC_LIBRARY_PREFIX}${library}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_library(FL ${library})
|
||||||
|
if(FL)
|
||||||
|
# Found library. Depending on if it's static or not we might
|
||||||
|
# extract the path and library name, then add the
|
||||||
|
# result to the libtool dependency libs.
|
||||||
|
if(STATIC_MODE)
|
||||||
|
set(_target_dependency_libs "${_target_dependency_libs} ${FL}")
|
||||||
|
else()
|
||||||
|
get_filename_component(_shared_lib ${FL} NAME_WE)
|
||||||
|
get_filename_component(_shared_lib_path ${FL} PATH)
|
||||||
|
string(REPLACE "lib" "" _shared_lib ${_shared_lib})
|
||||||
|
set(_target_dependency_libs "${_target_dependency_libs} -L${_shared_lib_path} -l${_shared_lib}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# No library found, so ignore target.
|
||||||
|
endif()
|
||||||
|
# Need to clear FL to get new results next loop
|
||||||
|
unset(FL CACHE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# Detected a static library. Check whether the library pathname is
|
||||||
|
# absolute and, if not, use find_library() to get the absolute path.
|
||||||
|
get_filename_component(_name ${library} NAME)
|
||||||
|
string(REPLACE "${_name}" "" _path ${library})
|
||||||
|
if(NOT "${_path}" STREQUAL "")
|
||||||
|
# Pathname is absolute, so add it to the libtool library dependencies
|
||||||
|
# as-is.
|
||||||
|
set(_target_dependency_libs "${_target_dependency_libs} ${library}")
|
||||||
|
else()
|
||||||
|
# Pathname is not absolute, so use find_library() to get the absolute
|
||||||
|
# path.
|
||||||
|
find_library(FL ${library})
|
||||||
|
if(FL)
|
||||||
|
# Absolute pathname found. Add it.
|
||||||
|
set(_target_dependency_libs "${_target_dependency_libs} ${FL}")
|
||||||
|
else()
|
||||||
|
# No absolute pathname found. Ignore it.
|
||||||
|
endif()
|
||||||
|
# Need to clear FL to get new results next loop
|
||||||
|
unset(FL CACHE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Write the libtool control file for the static library
|
||||||
|
set(_lname ${CMAKE_STATIC_LIBRARY_PREFIX}${_target})
|
||||||
|
set(_laname ${CMAKE_CURRENT_BINARY_DIR}/${_lname}.la)
|
||||||
|
|
||||||
|
file(WRITE ${_laname} "# ${_lname}.la - a libtool library file\n# Generated by ltmain.sh (GNU libtool) 2.2.6b\n")
|
||||||
|
file(APPEND ${_laname} "dlname=''\n\n")
|
||||||
|
file(APPEND ${_laname} "library_names=''\n\n")
|
||||||
|
file(APPEND ${_laname} "old_library='${_lname}${CMAKE_STATIC_LIBRARY_SUFFIX}'\n\n")
|
||||||
|
file(APPEND ${_laname} "inherited_linker_flags=''\n\n")
|
||||||
|
file(APPEND ${_laname} "dependency_libs=' ${_target_dependency_libs}'\n\n")
|
||||||
|
file(APPEND ${_laname} "weak_library_names=''\n\n")
|
||||||
|
file(APPEND ${_laname} "current=\n")
|
||||||
|
file(APPEND ${_laname} "age=\n")
|
||||||
|
file(APPEND ${_laname} "revision=\n\n")
|
||||||
|
file(APPEND ${_laname} "installed=no\n\n")
|
||||||
|
file(APPEND ${_laname} "shouldnotlink=no\n\n")
|
||||||
|
file(APPEND ${_laname} "dlopen=''\n")
|
||||||
|
file(APPEND ${_laname} "dlpreopen=''\n\n")
|
||||||
|
file(APPEND ${_laname} "libdir='/usr/lib'\n\n")
|
||||||
|
|
||||||
|
# Make sure the timestamp is updated to trigger other make invocations
|
||||||
|
add_custom_command(TARGET ${_target} POST_BUILD COMMAND
|
||||||
|
"${CMAKE_COMMAND}" -E touch "${_laname}")
|
||||||
|
|
||||||
|
|
||||||
|
# Add custom command to symlink the static library so that autotools finds
|
||||||
|
# the library in .libs. These are executed after the specified target build.
|
||||||
|
add_custom_command(TARGET ${_target} POST_BUILD COMMAND
|
||||||
|
"${CMAKE_COMMAND}" -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/.libs")
|
||||||
|
add_custom_command(TARGET ${_target} POST_BUILD COMMAND
|
||||||
|
"${CMAKE_COMMAND}" -E create_symlink ../${_lname}${CMAKE_STATIC_LIBRARY_SUFFIX} "${CMAKE_CURRENT_BINARY_DIR}/.libs/${_lname}${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||||
|
|
||||||
|
endmacro()
|
66
cmake/Modules/FindIconv.cmake
Normal file
66
cmake/Modules/FindIconv.cmake
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# From: http://gitorious.org/gammu/mainline/blobs/master/cmake/FindIconv.cmake
|
||||||
|
|
||||||
|
# - Try to find Iconv
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# ICONV_FOUND - system has Iconv
|
||||||
|
# ICONV_INCLUDE_DIR - the Iconv include directory
|
||||||
|
# ICONV_LIBRARIES - Link these to use Iconv
|
||||||
|
# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const
|
||||||
|
#
|
||||||
|
include(CheckCCompilerFlag)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||||
|
# Already in cache, be silent
|
||||||
|
SET(ICONV_FIND_QUIETLY TRUE)
|
||||||
|
ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||||
|
|
||||||
|
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
|
||||||
|
|
||||||
|
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c)
|
||||||
|
|
||||||
|
IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||||
|
SET(ICONV_FOUND TRUE)
|
||||||
|
ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||||
|
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
|
||||||
|
IF(ICONV_FOUND)
|
||||||
|
check_c_compiler_flag("-Werror" ICONV_HAVE_WERROR)
|
||||||
|
set (CMAKE_C_FLAGS_BACKUP "${CMAKE_C_FLAGS}")
|
||||||
|
if(ICONV_HAVE_WERROR)
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
||||||
|
endif(ICONV_HAVE_WERROR)
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include <iconv.h>
|
||||||
|
int main(){
|
||||||
|
iconv_t conv = 0;
|
||||||
|
const char* in = 0;
|
||||||
|
size_t ilen = 0;
|
||||||
|
char* out = 0;
|
||||||
|
size_t olen = 0;
|
||||||
|
iconv(conv, &in, &ilen, &out, &olen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" ICONV_SECOND_ARGUMENT_IS_CONST )
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_BACKUP}")
|
||||||
|
ENDIF(ICONV_FOUND)
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
|
||||||
|
IF(ICONV_FOUND)
|
||||||
|
IF(NOT ICONV_FIND_QUIETLY)
|
||||||
|
MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
|
||||||
|
ENDIF(NOT ICONV_FIND_QUIETLY)
|
||||||
|
ELSE(ICONV_FOUND)
|
||||||
|
IF(Iconv_FIND_REQUIRED)
|
||||||
|
MESSAGE(FATAL_ERROR "Could not find Iconv")
|
||||||
|
ENDIF(Iconv_FIND_REQUIRED)
|
||||||
|
ENDIF(ICONV_FOUND)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
ICONV_INCLUDE_DIR
|
||||||
|
ICONV_LIBRARIES
|
||||||
|
ICONV_SECOND_ARGUMENT_IS_CONST
|
||||||
|
)
|
142
cmake/StaticBuild.cmake
Normal file
142
cmake/StaticBuild.cmake
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#
|
||||||
|
# Best-effort magic that tries to produce semi-static binaries
|
||||||
|
# (i.e. only depends on "safe" libraries like libc and libX11)
|
||||||
|
#
|
||||||
|
# Note that this often fails as there is no way to automatically
|
||||||
|
# determine the dependencies of the libraries we depend on, and
|
||||||
|
# a lot of details change with each different build environment.
|
||||||
|
#
|
||||||
|
|
||||||
|
option(BUILD_STATIC
|
||||||
|
"Link statically against most libraries, if possible" OFF)
|
||||||
|
|
||||||
|
option(BUILD_STATIC_GCC
|
||||||
|
"Link statically against only libgcc and libstdc++" OFF)
|
||||||
|
|
||||||
|
if(BUILD_STATIC)
|
||||||
|
message(STATUS "Attempting to link static binaries...")
|
||||||
|
|
||||||
|
set(BUILD_STATIC_GCC 1)
|
||||||
|
|
||||||
|
set(JPEG_LIBRARIES "-Wl,-Bstatic -ljpeg -Wl,-Bdynamic")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(ZLIB_LIBRARIES "-Wl,-Bstatic -lz -Wl,-Bdynamic")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# gettext is included in libc on many unix systems
|
||||||
|
if(NOT LIBC_HAS_DGETTEXT)
|
||||||
|
set(GETTEXT_LIBRARIES "-Wl,-Bstatic -lintl -liconv -Wl,-Bdynamic")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(GNUTLS_FOUND)
|
||||||
|
# GnuTLS has historically had different crypto backends
|
||||||
|
FIND_LIBRARY(GCRYPT_LIBRARY NAMES gcrypt libgcrypt
|
||||||
|
HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})
|
||||||
|
FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle
|
||||||
|
HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})
|
||||||
|
FIND_LIBRARY(TASN1_LIBRARY NAMES tasn1 libtasn1
|
||||||
|
HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
set(GNUTLS_LIBRARIES "-Wl,-Bstatic -lgnutls")
|
||||||
|
|
||||||
|
if(TASN1_LIBRARY)
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -ltasn1")
|
||||||
|
endif()
|
||||||
|
if(NETTLE_LIBRARY)
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -lnettle -lhogweed -lgmp")
|
||||||
|
endif()
|
||||||
|
if(GCRYPT_LIBRARY)
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -lgcrypt -lgpg-error")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -Wl,-Bdynamic")
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
# GnuTLS uses various crypto-api stuff
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -lcrypt32")
|
||||||
|
# And sockets
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -lws2_32")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||||
|
# nanosleep() lives here on Solaris
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -lrt")
|
||||||
|
# and socket functions are hidden here
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} -lsocket")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# GnuTLS uses gettext and zlib, so make sure those are always
|
||||||
|
# included and in the proper order
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} ${ZLIB_LIBRARIES}")
|
||||||
|
set(GNUTLS_LIBRARIES "${GNUTLS_LIBRARIES} ${GETTEXT_LIBRARIES}")
|
||||||
|
|
||||||
|
# The last variables might introduce whitespace, which CMake
|
||||||
|
# throws a hissy fit about
|
||||||
|
string(STRIP ${GNUTLS_LIBRARIES} GNUTLS_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(FLTK_FOUND)
|
||||||
|
set(FLTK_LIBRARIES "-Wl,-Bstatic -lfltk_images -lpng -ljpeg -lfltk -Wl,-Bdynamic")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(FLTK_LIBRARIES "${FLTK_LIBRARIES} -lcomctl32")
|
||||||
|
elseif(APPLE)
|
||||||
|
set(FLTK_LIBRARIES "${FLTK_LIBRARIES} -framework Cocoa")
|
||||||
|
else()
|
||||||
|
set(FLTK_LIBRARIES "${FLTK_LIBRARIES} -lm -ldl")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(X11_FOUND AND NOT APPLE)
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||||
|
set(FLTK_LIBRARIES "${FLTK_LIBRARIES} ${X11_Xcursor_LIB} ${X11_Xfixes_LIB} -Wl,-Bstatic -lXft -Wl,-Bdynamic -lfontconfig -lXrender -lXext -R/usr/sfw/lib -L=/usr/sfw/lib -lfreetype -lsocket -lnsl")
|
||||||
|
else()
|
||||||
|
set(FLTK_LIBRARIES "${FLTK_LIBRARIES} -Wl,-Bstatic -lXcursor -lXfixes -lXft -lfontconfig -lexpat -lfreetype -lpng -lbz2 -lXrender -lXext -lXinerama -Wl,-Bdynamic")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(FLTK_LIBRARIES "${FLTK_LIBRARIES} -lX11")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# X11 libraries change constantly on Linux systems so we have to link
|
||||||
|
# them statically, even libXext. libX11 is somewhat stable, although
|
||||||
|
# even it has had an ABI change once or twice.
|
||||||
|
if(X11_FOUND AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||||
|
set(X11_LIBRARIES "-Wl,-Bstatic -lXext -Wl,-Bdynamic -lX11")
|
||||||
|
if(X11_XTest_LIB)
|
||||||
|
set(X11_XTest_LIB "-Wl,-Bstatic -lXtst -Wl,-Bdynamic")
|
||||||
|
endif()
|
||||||
|
if(X11_Xdamage_LIB)
|
||||||
|
set(X11_Xdamage_LIB "-Wl,-Bstatic -lXdamage -Wl,-Bdynamic")
|
||||||
|
endif()
|
||||||
|
if(X11_Xrandr_LIB)
|
||||||
|
set(X11_Xrandr_LIB "-Wl,-Bstatic -lXrandr -lXrender -Wl,-Bdynamic")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_STATIC_GCC)
|
||||||
|
# This ensures that we don't depend on libstdc++ or libgcc_s
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nodefaultlibs")
|
||||||
|
set(STATIC_BASE_LIBRARIES "-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic")
|
||||||
|
if(ENABLE_ASAN AND NOT WIN32 AND NOT APPLE)
|
||||||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -Wl,-Bstatic -lasan -Wl,-Bdynamic -ldl -lm -lpthread")
|
||||||
|
endif()
|
||||||
|
if(ENABLE_TSAN AND NOT WIN32 AND NOT APPLE AND CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||||
|
# libtsan redefines some C++ symbols which then conflict with a
|
||||||
|
# statically linked libstdc++. Work around this by allowing multiple
|
||||||
|
# definitions. The linker will pick the first one (i.e. the one
|
||||||
|
# from libtsan).
|
||||||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -Wl,-z -Wl,muldefs -Wl,-Bstatic -ltsan -Wl,-Bdynamic -ldl -lm")
|
||||||
|
endif()
|
||||||
|
if(WIN32)
|
||||||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -lmingw32 -lgcc_eh -lgcc -lmoldname -lmingwex -lmsvcrt")
|
||||||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -luser32 -lkernel32 -ladvapi32 -lshell32")
|
||||||
|
# mingw has some fun circular dependencies that requires us to link
|
||||||
|
# these things again
|
||||||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -lmingw32 -lgcc_eh -lgcc -lmoldname -lmingwex -lmsvcrt")
|
||||||
|
else()
|
||||||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -lgcc -lgcc_eh -lc")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${STATIC_BASE_LIBRARIES}")
|
||||||
|
endif()
|
24
cmake/cmake_uninstall.cmake.in
Normal file
24
cmake/cmake_uninstall.cmake.in
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# This code is from the CMake FAQ
|
||||||
|
|
||||||
|
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
|
||||||
|
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
|
||||||
|
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||||
|
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||||
|
list(REVERSE files)
|
||||||
|
foreach (file ${files})
|
||||||
|
message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
|
||||||
|
if (EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
execute_process(
|
||||||
|
COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
|
||||||
|
OUTPUT_VARIABLE rm_out
|
||||||
|
RESULT_VARIABLE rm_retval
|
||||||
|
)
|
||||||
|
if(NOT ${rm_retval} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||||
|
endif (NOT ${rm_retval} EQUAL 0)
|
||||||
|
else (EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
|
||||||
|
endif (EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
endforeach(file)
|
15
common/CMakeLists.txt
Normal file
15
common/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
add_subdirectory(os)
|
||||||
|
add_subdirectory(rdr)
|
||||||
|
add_subdirectory(network)
|
||||||
|
add_subdirectory(Xregion)
|
||||||
|
add_subdirectory(rfb)
|
||||||
|
|
||||||
|
# For any convenience libraries that are linked into libvnc.so, we need to
|
||||||
|
# explicitly build their corresponding sources using PIC. WIN32 is excluded
|
||||||
|
# because PIC code does not exist on that platform and MinGW complains if -fPIC
|
||||||
|
# is passed (additionally, libvnc is not used on Windows.)
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
set_target_properties(os rdr network Xregion rfb
|
||||||
|
PROPERTIES COMPILE_FLAGS -fPIC)
|
||||||
|
endif()
|
6
common/Xregion/CMakeLists.txt
Normal file
6
common/Xregion/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
add_library(Xregion STATIC
|
||||||
|
Region.c)
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
libtool_create_control_file(Xregion)
|
||||||
|
endif()
|
1612
common/Xregion/Region.c
Normal file
1612
common/Xregion/Region.c
Normal file
File diff suppressed because it is too large
Load Diff
50
common/Xregion/Xlib.h
Normal file
50
common/Xregion/Xlib.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 1985, 1986, 1987, 1991, 1998 The Open Group
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
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
|
||||||
|
OPEN GROUP 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.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of The Open Group shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from The Open Group.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Xlib.h - Header definition and support file for the C subroutine
|
||||||
|
* interface library (Xlib) to the X Window System Protocol (V11).
|
||||||
|
* Structures and symbols starting with "_" are private to the library.
|
||||||
|
*/
|
||||||
|
#ifndef _X11_XLIB_H_
|
||||||
|
#define _X11_XLIB_H_
|
||||||
|
|
||||||
|
#define NeedFunctionPrototypes 1
|
||||||
|
|
||||||
|
#define Bool int
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short x, y;
|
||||||
|
} XPoint;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short x, y;
|
||||||
|
unsigned short width, height;
|
||||||
|
} XRectangle;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _X11_XLIB_H_ */
|
48
common/Xregion/Xlibint.h
Normal file
48
common/Xregion/Xlibint.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 1984, 1985, 1987, 1989, 1998 The Open Group
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
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 OPEN GROUP 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.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of The Open Group shall
|
||||||
|
not be used in advertising or otherwise to promote the sale, use or
|
||||||
|
other dealings in this Software without prior written authorization
|
||||||
|
from The Open Group.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _X11_XLIBINT_H_
|
||||||
|
#define _X11_XLIBINT_H_ 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Xlibint.h - Header definition and support file for the internal
|
||||||
|
* support routines used by the C subroutine interface
|
||||||
|
* library (Xlib) to the X Window System.
|
||||||
|
*
|
||||||
|
* Warning, there be dragons here....
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define Xfree(ptr) free((ptr))
|
||||||
|
#define Xmalloc(size) malloc((size))
|
||||||
|
#define Xrealloc(ptr, size) realloc((ptr), (size))
|
||||||
|
#define Xcalloc(nelem, elsize) calloc((nelem), (elsize))
|
||||||
|
|
||||||
|
#endif /* _X11_XLIBINT_H_ */
|
190
common/Xregion/Xregion.h
Normal file
190
common/Xregion/Xregion.h
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/************************************************************************
|
||||||
|
|
||||||
|
Copyright 1987, 1998 The Open Group
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
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
|
||||||
|
OPEN GROUP 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.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of The Open Group shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from The Open Group.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
|
||||||
|
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted,
|
||||||
|
provided that the above copyright notice appear in all copies and that
|
||||||
|
both that copyright notice and this permission notice appear in
|
||||||
|
supporting documentation, and that the name of Digital not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||||
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||||||
|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||||
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _X11_XREGION_H_
|
||||||
|
#define _X11_XREGION_H_
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short x1, x2, y1, y2;
|
||||||
|
} Box, BOX, BoxRec, *BoxPtr;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short x, y, width, height;
|
||||||
|
}RECTANGLE, RectangleRec, *RectanglePtr;
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#define MAXSHORT 32767
|
||||||
|
#define MINSHORT -MAXSHORT
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clip region
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct _XRegion {
|
||||||
|
long size;
|
||||||
|
long numRects;
|
||||||
|
BOX *rects;
|
||||||
|
BOX extents;
|
||||||
|
} REGION;
|
||||||
|
|
||||||
|
/* Xutil.h contains the declaration:
|
||||||
|
* typedef struct _XRegion *Region;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 1 if two BOXs overlap.
|
||||||
|
* 0 if two BOXs do not overlap.
|
||||||
|
* Remember, x2 and y2 are not in the region
|
||||||
|
*/
|
||||||
|
#define EXTENTCHECK(r1, r2) \
|
||||||
|
((r1)->x2 > (r2)->x1 && \
|
||||||
|
(r1)->x1 < (r2)->x2 && \
|
||||||
|
(r1)->y2 > (r2)->y1 && \
|
||||||
|
(r1)->y1 < (r2)->y2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update region extents
|
||||||
|
*/
|
||||||
|
#define EXTENTS(r,idRect){\
|
||||||
|
if((r)->x1 < (idRect)->extents.x1)\
|
||||||
|
(idRect)->extents.x1 = (r)->x1;\
|
||||||
|
if((r)->y1 < (idRect)->extents.y1)\
|
||||||
|
(idRect)->extents.y1 = (r)->y1;\
|
||||||
|
if((r)->x2 > (idRect)->extents.x2)\
|
||||||
|
(idRect)->extents.x2 = (r)->x2;\
|
||||||
|
if((r)->y2 > (idRect)->extents.y2)\
|
||||||
|
(idRect)->extents.y2 = (r)->y2;\
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if there is enough memory in the present region.
|
||||||
|
*/
|
||||||
|
#define MEMCHECK(reg, rect, firstrect){\
|
||||||
|
if ((reg)->numRects >= ((reg)->size - 1)){\
|
||||||
|
BoxPtr tmpRect = Xrealloc ((firstrect), \
|
||||||
|
(2 * (sizeof(BOX)) * ((reg)->size))); \
|
||||||
|
if (tmpRect == NULL) \
|
||||||
|
return(0);\
|
||||||
|
(firstrect) = tmpRect; \
|
||||||
|
(reg)->size *= 2;\
|
||||||
|
(rect) = &(firstrect)[(reg)->numRects];\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this routine checks to see if the previous rectangle is the same
|
||||||
|
* or subsumes the new rectangle to add.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\
|
||||||
|
(!(((Reg)->numRects > 0)&&\
|
||||||
|
((R-1)->y1 == (Ry1)) &&\
|
||||||
|
((R-1)->y2 == (Ry2)) &&\
|
||||||
|
((R-1)->x1 <= (Rx1)) &&\
|
||||||
|
((R-1)->x2 >= (Rx2))))
|
||||||
|
|
||||||
|
/* add a rectangle to the given Region */
|
||||||
|
#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\
|
||||||
|
if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\
|
||||||
|
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
|
||||||
|
(r)->x1 = (rx1);\
|
||||||
|
(r)->y1 = (ry1);\
|
||||||
|
(r)->x2 = (rx2);\
|
||||||
|
(r)->y2 = (ry2);\
|
||||||
|
EXTENTS((r), (reg));\
|
||||||
|
(reg)->numRects++;\
|
||||||
|
(r)++;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* add a rectangle to the given Region */
|
||||||
|
#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\
|
||||||
|
if ((rx1 < rx2) && (ry1 < ry2) &&\
|
||||||
|
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
|
||||||
|
(r)->x1 = (rx1);\
|
||||||
|
(r)->y1 = (ry1);\
|
||||||
|
(r)->x2 = (rx2);\
|
||||||
|
(r)->y2 = (ry2);\
|
||||||
|
(reg)->numRects++;\
|
||||||
|
(r)++;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EMPTY_REGION(pReg) pReg->numRects = 0
|
||||||
|
|
||||||
|
#define REGION_NOT_EMPTY(pReg) pReg->numRects
|
||||||
|
|
||||||
|
#define INBOX(r, x, y) \
|
||||||
|
( ( ((r).x2 > x)) && \
|
||||||
|
( ((r).x1 <= x)) && \
|
||||||
|
( ((r).y2 > y)) && \
|
||||||
|
( ((r).y1 <= y)) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* number of points to buffer before sending them off
|
||||||
|
* to scanlines() : Must be an even number
|
||||||
|
*/
|
||||||
|
#define NUMPTSTOBUFFER 200
|
||||||
|
|
||||||
|
/*
|
||||||
|
* used to allocate buffers for points and link
|
||||||
|
* the buffers together
|
||||||
|
*/
|
||||||
|
typedef struct _POINTBLOCK {
|
||||||
|
XPoint pts[NUMPTSTOBUFFER];
|
||||||
|
struct _POINTBLOCK *next;
|
||||||
|
} POINTBLOCK;
|
||||||
|
|
||||||
|
#endif /* _X11_XREGION_H_ */
|
167
common/Xregion/Xutil.h
Normal file
167
common/Xregion/Xutil.h
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
|
||||||
|
Copyright 1987, 1998 The Open Group
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
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
|
||||||
|
OPEN GROUP 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.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of The Open Group shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from The Open Group.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
|
||||||
|
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted,
|
||||||
|
provided that the above copyright notice appear in all copies and that
|
||||||
|
both that copyright notice and this permission notice appear in
|
||||||
|
supporting documentation, and that the name of Digital not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||||
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||||||
|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||||
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
******************************************************************/
|
||||||
|
|
||||||
|
#ifndef _X11_XUTIL_H_
|
||||||
|
#define _X11_XUTIL_H_
|
||||||
|
|
||||||
|
/* You must include <X11/Xlib.h> before including this file */
|
||||||
|
#include "Xlib.h"
|
||||||
|
|
||||||
|
/****** Avoid symbol clash with "real" libX11 ******/
|
||||||
|
#define XClipBox vncXClipBox
|
||||||
|
#define XCreateRegion vncXCreateRegion
|
||||||
|
#define XDestroyRegion vncXDestroyRegion
|
||||||
|
#define XEmptyRegion vncXEmptyRegion
|
||||||
|
#define XEqualRegion vncXEqualRegion
|
||||||
|
#define XIntersectRegion vncXIntersectRegion
|
||||||
|
#define XOffsetRegion vncXOffsetRegion
|
||||||
|
#define XPointInRegion vncXPointInRegion
|
||||||
|
#define XPolygonRegion vncXPolygonRegion
|
||||||
|
#define XRectInRegion vncXRectInRegion
|
||||||
|
#define XShrinkRegion vncXShrinkRegion
|
||||||
|
#define XSubtractRegion vncXSubtractRegion
|
||||||
|
#define XUnionRectWithRegion vncXUnionRectWithRegion
|
||||||
|
#define XUnionRegion vncXUnionRegion
|
||||||
|
#define XXorRegion vncXXorRegion
|
||||||
|
|
||||||
|
/*
|
||||||
|
* opaque reference to Region data type
|
||||||
|
*/
|
||||||
|
typedef struct _XRegion *Region;
|
||||||
|
|
||||||
|
/* Return values from XRectInRegion() */
|
||||||
|
|
||||||
|
#define RectangleOut 0
|
||||||
|
#define RectangleIn 1
|
||||||
|
#define RectanglePart 2
|
||||||
|
|
||||||
|
extern int XClipBox(
|
||||||
|
Region /* r */,
|
||||||
|
XRectangle* /* rect_return */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern Region XCreateRegion(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XDestroyRegion(
|
||||||
|
Region /* r */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XEmptyRegion(
|
||||||
|
Region /* r */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XEqualRegion(
|
||||||
|
Region /* r1 */,
|
||||||
|
Region /* r2 */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XIntersectRegion(
|
||||||
|
Region /* sra */,
|
||||||
|
Region /* srb */,
|
||||||
|
Region /* dr_return */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XOffsetRegion(
|
||||||
|
Region /* r */,
|
||||||
|
int /* dx */,
|
||||||
|
int /* dy */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern Bool XPointInRegion(
|
||||||
|
Region /* r */,
|
||||||
|
int /* x */,
|
||||||
|
int /* y */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern Region XPolygonRegion(
|
||||||
|
XPoint* /* points */,
|
||||||
|
int /* n */,
|
||||||
|
int /* fill_rule */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XRectInRegion(
|
||||||
|
Region /* r */,
|
||||||
|
int /* x */,
|
||||||
|
int /* y */,
|
||||||
|
unsigned int /* width */,
|
||||||
|
unsigned int /* height */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XShrinkRegion(
|
||||||
|
Region /* r */,
|
||||||
|
int /* dx */,
|
||||||
|
int /* dy */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XSubtractRegion(
|
||||||
|
Region /* sra */,
|
||||||
|
Region /* srb */,
|
||||||
|
Region /* dr_return */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XUnionRectWithRegion(
|
||||||
|
XRectangle* /* rectangle */,
|
||||||
|
Region /* src_region */,
|
||||||
|
Region /* dest_region_return */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XUnionRegion(
|
||||||
|
Region /* sra */,
|
||||||
|
Region /* srb */,
|
||||||
|
Region /* dr_return */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int XXorRegion(
|
||||||
|
Region /* sra */,
|
||||||
|
Region /* srb */,
|
||||||
|
Region /* dr_return */
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif /* _X11_XUTIL_H_ */
|
21
common/network/CMakeLists.txt
Normal file
21
common/network/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
include_directories(${CMAKE_SOURCE_DIR}/common)
|
||||||
|
|
||||||
|
set(NETWORK_SOURCES
|
||||||
|
Socket.cxx
|
||||||
|
TcpSocket.cxx
|
||||||
|
websocket.c
|
||||||
|
websockify.c)
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
set(NETWORK_SOURCES ${NETWORK_SOURCES} UnixSocket.cxx)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(network STATIC ${NETWORK_SOURCES})
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(network ws2_32)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
libtool_create_control_file(network)
|
||||||
|
endif()
|
183
common/network/Socket.cxx
Normal file
183
common/network/Socket.cxx
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
//#include <io.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#define errorNumber WSAGetLastError()
|
||||||
|
#else
|
||||||
|
#define errorNumber errno
|
||||||
|
#define closesocket close
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <network/Socket.h>
|
||||||
|
|
||||||
|
using namespace network;
|
||||||
|
|
||||||
|
// -=- Socket initialisation
|
||||||
|
static bool socketsInitialised = false;
|
||||||
|
void network::initSockets() {
|
||||||
|
if (socketsInitialised)
|
||||||
|
return;
|
||||||
|
#ifdef WIN32
|
||||||
|
WORD requiredVersion = MAKEWORD(2,0);
|
||||||
|
WSADATA initResult;
|
||||||
|
|
||||||
|
if (WSAStartup(requiredVersion, &initResult) != 0)
|
||||||
|
throw SocketException("unable to initialise Winsock2", errorNumber);
|
||||||
|
#else
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
socketsInitialised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool network::isSocketListening(int sock)
|
||||||
|
{
|
||||||
|
int listening = 0;
|
||||||
|
socklen_t listening_size = sizeof(listening);
|
||||||
|
if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN,
|
||||||
|
(char *)&listening, &listening_size) < 0)
|
||||||
|
return false;
|
||||||
|
return listening != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket::Socket(int fd)
|
||||||
|
: instream(0), outstream(0),
|
||||||
|
isShutdown_(false), queryConnection(false)
|
||||||
|
{
|
||||||
|
initSockets();
|
||||||
|
setFd(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket::Socket()
|
||||||
|
: instream(0), outstream(0),
|
||||||
|
isShutdown_(false), queryConnection(false)
|
||||||
|
{
|
||||||
|
initSockets();
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket::~Socket()
|
||||||
|
{
|
||||||
|
if (instream && outstream)
|
||||||
|
closesocket(getFd());
|
||||||
|
delete instream;
|
||||||
|
delete outstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if shutdown() is overridden then the override MUST call on to here
|
||||||
|
void Socket::shutdown()
|
||||||
|
{
|
||||||
|
isShutdown_ = true;
|
||||||
|
::shutdown(getFd(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::isShutdown() const
|
||||||
|
{
|
||||||
|
return isShutdown_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was there a "?" in the ConnectionFilter used to accept this Socket?
|
||||||
|
void Socket::setRequiresQuery()
|
||||||
|
{
|
||||||
|
queryConnection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::requiresQuery() const
|
||||||
|
{
|
||||||
|
return queryConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::setFd(int fd)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
// - By default, close the socket on exec()
|
||||||
|
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
instream = new rdr::FdInStream(fd);
|
||||||
|
outstream = new rdr::FdOutStream(fd);
|
||||||
|
isShutdown_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketListener::SocketListener(int fd)
|
||||||
|
: fd(fd), filter(0)
|
||||||
|
{
|
||||||
|
initSockets();
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketListener::SocketListener()
|
||||||
|
: fd(-1), filter(0)
|
||||||
|
{
|
||||||
|
initSockets();
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketListener::~SocketListener()
|
||||||
|
{
|
||||||
|
if (fd != -1)
|
||||||
|
closesocket(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketListener::shutdown()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
closesocket(fd);
|
||||||
|
fd = -1;
|
||||||
|
#else
|
||||||
|
::shutdown(fd, 2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket* SocketListener::accept() {
|
||||||
|
int new_sock = -1;
|
||||||
|
|
||||||
|
// Accept an incoming connection
|
||||||
|
if ((new_sock = ::accept(fd, 0, 0)) < 0)
|
||||||
|
throw SocketException("unable to accept new connection", errorNumber);
|
||||||
|
|
||||||
|
// Create the socket object & check connection is allowed
|
||||||
|
Socket* s = createSocket(new_sock);
|
||||||
|
if (filter && !filter->verifyConnection(s)) {
|
||||||
|
delete s;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketListener::listen(int sock)
|
||||||
|
{
|
||||||
|
// - Set it to be a listening socket
|
||||||
|
if (::listen(sock, 5) < 0) {
|
||||||
|
int e = errorNumber;
|
||||||
|
closesocket(sock);
|
||||||
|
throw SocketException("unable to set socket to listening mode", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = sock;
|
||||||
|
}
|
160
common/network/Socket.h
Normal file
160
common/network/Socket.h
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -=- Socket.h - abstract base-class for any kind of network stream/socket
|
||||||
|
|
||||||
|
#ifndef __NETWORK_SOCKET_H__
|
||||||
|
#define __NETWORK_SOCKET_H__
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <rdr/FdInStream.h>
|
||||||
|
#include <rdr/FdOutStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
namespace network {
|
||||||
|
|
||||||
|
void initSockets();
|
||||||
|
|
||||||
|
bool isSocketListening(int sock);
|
||||||
|
|
||||||
|
class Socket {
|
||||||
|
public:
|
||||||
|
Socket(int fd);
|
||||||
|
virtual ~Socket();
|
||||||
|
|
||||||
|
rdr::FdInStream &inStream() {return *instream;}
|
||||||
|
rdr::FdOutStream &outStream() {return *outstream;}
|
||||||
|
int getFd() {return outstream->getFd();}
|
||||||
|
|
||||||
|
void shutdown();
|
||||||
|
bool isShutdown() const;
|
||||||
|
|
||||||
|
virtual bool cork(bool enable) = 0;
|
||||||
|
|
||||||
|
// information about the remote end of the socket
|
||||||
|
virtual char* getPeerAddress() = 0; // a string e.g. "192.168.0.1"
|
||||||
|
virtual char* getPeerEndpoint() = 0; // <address>::<port>
|
||||||
|
|
||||||
|
// Was there a "?" in the ConnectionFilter used to accept this Socket?
|
||||||
|
void setRequiresQuery();
|
||||||
|
bool requiresQuery() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Socket();
|
||||||
|
|
||||||
|
void setFd(int fd);
|
||||||
|
|
||||||
|
private:
|
||||||
|
rdr::FdInStream* instream;
|
||||||
|
rdr::FdOutStream* outstream;
|
||||||
|
bool isShutdown_;
|
||||||
|
bool queryConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConnectionFilter {
|
||||||
|
public:
|
||||||
|
virtual bool verifyConnection(Socket* s) = 0;
|
||||||
|
virtual ~ConnectionFilter() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SocketListener {
|
||||||
|
public:
|
||||||
|
SocketListener(int fd);
|
||||||
|
virtual ~SocketListener();
|
||||||
|
|
||||||
|
// shutdown() stops the socket from accepting further connections
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
// accept() returns a new Socket object if there is a connection
|
||||||
|
// attempt in progress AND if the connection passes the filter
|
||||||
|
// if one is installed. Otherwise, returns 0.
|
||||||
|
Socket* accept();
|
||||||
|
|
||||||
|
virtual int getMyPort() = 0;
|
||||||
|
|
||||||
|
// setFilter() applies the specified filter to all new connections
|
||||||
|
void setFilter(ConnectionFilter* f) {filter = f;}
|
||||||
|
int getFd() {return fd;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SocketListener();
|
||||||
|
|
||||||
|
void listen(int fd);
|
||||||
|
|
||||||
|
// createSocket() should create a new socket of the correct class
|
||||||
|
// for the given file descriptor
|
||||||
|
virtual Socket* createSocket(int fd) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int fd;
|
||||||
|
ConnectionFilter* filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SocketException : public rdr::SystemException {
|
||||||
|
SocketException(const char* text, int err_) : rdr::SystemException(text, err_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SocketServer {
|
||||||
|
public:
|
||||||
|
virtual ~SocketServer() {}
|
||||||
|
|
||||||
|
// addSocket() tells the server to serve the Socket. The caller
|
||||||
|
// retains ownership of the Socket - the only way for the server
|
||||||
|
// to discard a Socket is by calling shutdown() on it.
|
||||||
|
// outgoing is set to true if the socket was created by connecting out
|
||||||
|
// to another host, or false if the socket was created by accept()ing
|
||||||
|
// an incoming connection.
|
||||||
|
virtual void addSocket(network::Socket* sock, bool outgoing=false) = 0;
|
||||||
|
|
||||||
|
// removeSocket() tells the server to stop serving the Socket. The
|
||||||
|
// caller retains ownership of the Socket - the server must NOT
|
||||||
|
// delete the Socket! This call is used mainly to cause per-Socket
|
||||||
|
// resources to be freed.
|
||||||
|
virtual void removeSocket(network::Socket* sock) = 0;
|
||||||
|
|
||||||
|
// getSockets() gets a list of sockets. This can be used to generate an
|
||||||
|
// fd_set for calling select().
|
||||||
|
virtual void getSockets(std::list<network::Socket*>* sockets) = 0;
|
||||||
|
|
||||||
|
// processSocketReadEvent() tells the server there is a Socket read event.
|
||||||
|
// The implementation can indicate that the Socket is no longer active
|
||||||
|
// by calling shutdown() on it. The caller will then call removeSocket()
|
||||||
|
// soon after processSocketEvent returns, to allow any pre-Socket
|
||||||
|
// resources to be tidied up.
|
||||||
|
virtual void processSocketReadEvent(network::Socket* sock) = 0;
|
||||||
|
|
||||||
|
// processSocketReadEvent() tells the server there is a Socket write event.
|
||||||
|
// This is only necessary if the Socket has been put in non-blocking
|
||||||
|
// mode and needs this callback to flush the buffer.
|
||||||
|
virtual void processSocketWriteEvent(network::Socket* sock) = 0;
|
||||||
|
|
||||||
|
// checkTimeouts() allows the server to check socket timeouts, etc. The
|
||||||
|
// return value is the number of milliseconds to wait before
|
||||||
|
// checkTimeouts() should be called again. If this number is zero then
|
||||||
|
// there is no timeout and checkTimeouts() should be called the next time
|
||||||
|
// an event occurs.
|
||||||
|
virtual int checkTimeouts() = 0;
|
||||||
|
|
||||||
|
virtual bool getDisable() {return false;};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __NETWORK_SOCKET_H__
|
1029
common/network/TcpSocket.cxx
Normal file
1029
common/network/TcpSocket.cxx
Normal file
File diff suppressed because it is too large
Load Diff
158
common/network/TcpSocket.h
Normal file
158
common/network/TcpSocket.h
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -=- TcpSocket.h - base-class for TCP stream sockets.
|
||||||
|
// This header also defines the TcpListener class, used
|
||||||
|
// to listen for incoming socket connections over TCP
|
||||||
|
//
|
||||||
|
// NB: Any file descriptors created by the TcpSocket or
|
||||||
|
// TcpListener classes are close-on-exec if the OS supports
|
||||||
|
// it. TcpSockets initialised with a caller-supplied fd
|
||||||
|
// are NOT set to close-on-exec.
|
||||||
|
|
||||||
|
#ifndef __NETWORK_TCP_SOCKET_H__
|
||||||
|
#define __NETWORK_TCP_SOCKET_H__
|
||||||
|
|
||||||
|
#include <network/Socket.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h> /* for socklen_t */
|
||||||
|
#include <netinet/in.h> /* for struct sockaddr_in */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
/* Tunnelling support. */
|
||||||
|
#define TUNNEL_PORT_OFFSET 5500
|
||||||
|
|
||||||
|
namespace network {
|
||||||
|
|
||||||
|
/* Tunnelling support. */
|
||||||
|
int findFreeTcpPort (void);
|
||||||
|
|
||||||
|
int getSockPort(int sock);
|
||||||
|
|
||||||
|
class TcpSocket : public Socket {
|
||||||
|
public:
|
||||||
|
TcpSocket(int sock);
|
||||||
|
TcpSocket(const char *name, int port);
|
||||||
|
|
||||||
|
virtual char* getPeerAddress();
|
||||||
|
virtual char* getPeerEndpoint();
|
||||||
|
|
||||||
|
virtual bool cork(bool enable);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool enableNagles(bool enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WebSocket : public Socket {
|
||||||
|
public:
|
||||||
|
WebSocket(int sock);
|
||||||
|
|
||||||
|
virtual char* getPeerAddress();
|
||||||
|
virtual char* getPeerEndpoint();
|
||||||
|
|
||||||
|
virtual bool cork(bool enable) { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class TcpListener : public SocketListener {
|
||||||
|
public:
|
||||||
|
TcpListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen);
|
||||||
|
TcpListener(int sock);
|
||||||
|
|
||||||
|
virtual int getMyPort();
|
||||||
|
|
||||||
|
static void getMyAddresses(std::list<char*>* result);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual Socket* createSocket(int fd);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WebsocketListener : public SocketListener {
|
||||||
|
public:
|
||||||
|
WebsocketListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen,
|
||||||
|
bool sslonly, const char *cert, const char *basicauth,
|
||||||
|
const char *httpdir);
|
||||||
|
|
||||||
|
virtual int getMyPort();
|
||||||
|
|
||||||
|
static void getMyAddresses(std::list<char*>* result);
|
||||||
|
|
||||||
|
int internalSocket;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual Socket* createSocket(int fd);
|
||||||
|
};
|
||||||
|
|
||||||
|
void createLocalTcpListeners(std::list<SocketListener*> *listeners,
|
||||||
|
int port);
|
||||||
|
void createWebsocketListeners(std::list<SocketListener*> *listeners,
|
||||||
|
int port,
|
||||||
|
const char *addr,
|
||||||
|
bool sslonly,
|
||||||
|
const char *cert,
|
||||||
|
const char *basicauth,
|
||||||
|
const char *httpdir);
|
||||||
|
void createTcpListeners(std::list<SocketListener*> *listeners,
|
||||||
|
const char *addr,
|
||||||
|
int port);
|
||||||
|
void createTcpListeners(std::list<SocketListener*> *listeners,
|
||||||
|
const struct addrinfo *ai);
|
||||||
|
void createWebsocketListeners(std::list<SocketListener*> *listeners,
|
||||||
|
const struct addrinfo *ai,
|
||||||
|
bool sslonly,
|
||||||
|
const char *cert,
|
||||||
|
const char *basicauth,
|
||||||
|
const char *httpdir);
|
||||||
|
|
||||||
|
typedef struct vnc_sockaddr {
|
||||||
|
union {
|
||||||
|
sockaddr sa;
|
||||||
|
sockaddr_in sin;
|
||||||
|
sockaddr_in6 sin6;
|
||||||
|
} u;
|
||||||
|
} vnc_sockaddr_t;
|
||||||
|
|
||||||
|
class TcpFilter : public ConnectionFilter {
|
||||||
|
public:
|
||||||
|
TcpFilter(const char* filter);
|
||||||
|
virtual ~TcpFilter();
|
||||||
|
|
||||||
|
virtual bool verifyConnection(Socket* s);
|
||||||
|
|
||||||
|
typedef enum {Accept, Reject, Query} Action;
|
||||||
|
struct Pattern {
|
||||||
|
Action action;
|
||||||
|
vnc_sockaddr_t address;
|
||||||
|
unsigned int prefixlen;
|
||||||
|
|
||||||
|
vnc_sockaddr_t mask; // computed from address and prefix
|
||||||
|
};
|
||||||
|
static Pattern parsePattern(const char* s);
|
||||||
|
static char* patternToStr(const Pattern& p);
|
||||||
|
protected:
|
||||||
|
std::list<Pattern> filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __NETWORK_TCP_SOCKET_H__
|
171
common/network/UnixSocket.cxx
Normal file
171
common/network/UnixSocket.cxx
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (c) 2012 University of Oslo. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <network/UnixSocket.h>
|
||||||
|
#include <rfb/LogWriter.h>
|
||||||
|
|
||||||
|
using namespace network;
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
static rfb::LogWriter vlog("UnixSocket");
|
||||||
|
|
||||||
|
// -=- UnixSocket
|
||||||
|
|
||||||
|
UnixSocket::UnixSocket(int sock) : Socket(sock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixSocket::UnixSocket(const char *path)
|
||||||
|
{
|
||||||
|
int sock, err, result;
|
||||||
|
sockaddr_un addr;
|
||||||
|
socklen_t salen;
|
||||||
|
|
||||||
|
if (strlen(path) >= sizeof(addr.sun_path))
|
||||||
|
throw SocketException("socket path is too long", ENAMETOOLONG);
|
||||||
|
|
||||||
|
// - Create a socket
|
||||||
|
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (sock == -1)
|
||||||
|
throw SocketException("unable to create socket", errno);
|
||||||
|
|
||||||
|
// - Attempt to connect
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strcpy(addr.sun_path, path);
|
||||||
|
salen = sizeof(addr);
|
||||||
|
while ((result = connect(sock, (sockaddr *)&addr, salen)) == -1) {
|
||||||
|
err = errno;
|
||||||
|
close(sock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == -1)
|
||||||
|
throw SocketException("unable connect to socket", err);
|
||||||
|
|
||||||
|
setFd(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* UnixSocket::getPeerAddress() {
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
socklen_t salen;
|
||||||
|
|
||||||
|
// AF_UNIX only has a single address (the server side).
|
||||||
|
// Unfortunately we don't know which end we are, so we'll have to
|
||||||
|
// test a bit.
|
||||||
|
|
||||||
|
salen = sizeof(addr);
|
||||||
|
if (getpeername(getFd(), (struct sockaddr *)&addr, &salen) != 0) {
|
||||||
|
vlog.error("unable to get peer name for socket");
|
||||||
|
return rfb::strDup("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (salen > offsetof(struct sockaddr_un, sun_path))
|
||||||
|
return rfb::strDup(addr.sun_path);
|
||||||
|
|
||||||
|
salen = sizeof(addr);
|
||||||
|
if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) != 0) {
|
||||||
|
vlog.error("unable to get local name for socket");
|
||||||
|
return rfb::strDup("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (salen > offsetof(struct sockaddr_un, sun_path))
|
||||||
|
return rfb::strDup(addr.sun_path);
|
||||||
|
|
||||||
|
// socketpair() will create unnamed sockets
|
||||||
|
|
||||||
|
return rfb::strDup("(unnamed UNIX socket)");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* UnixSocket::getPeerEndpoint() {
|
||||||
|
return getPeerAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixSocket::cork(bool enable)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixListener::UnixListener(const char *path, int mode)
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
mode_t saved_umask;
|
||||||
|
int err, result;
|
||||||
|
|
||||||
|
if (strlen(path) >= sizeof(addr.sun_path))
|
||||||
|
throw SocketException("socket path is too long", ENAMETOOLONG);
|
||||||
|
|
||||||
|
// - Create a socket
|
||||||
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||||
|
throw SocketException("unable to create listening socket", errno);
|
||||||
|
|
||||||
|
// - Delete existing socket (ignore result)
|
||||||
|
unlink(path);
|
||||||
|
|
||||||
|
// - Attempt to bind to the requested path
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strcpy(addr.sun_path, path);
|
||||||
|
saved_umask = umask(0777);
|
||||||
|
result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
err = errno;
|
||||||
|
umask(saved_umask);
|
||||||
|
if (result < 0) {
|
||||||
|
close(fd);
|
||||||
|
throw SocketException("unable to bind listening socket", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Set socket mode
|
||||||
|
if (chmod(path, mode) < 0) {
|
||||||
|
err = errno;
|
||||||
|
close(fd);
|
||||||
|
throw SocketException("unable to set socket mode", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixListener::~UnixListener()
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
socklen_t salen = sizeof(addr);
|
||||||
|
|
||||||
|
if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) == 0)
|
||||||
|
unlink(addr.sun_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket* UnixListener::createSocket(int fd) {
|
||||||
|
return new UnixSocket(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int UnixListener::getMyPort() {
|
||||||
|
return 0;
|
||||||
|
}
|
60
common/network/UnixSocket.h
Normal file
60
common/network/UnixSocket.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (c) 2012 University of Oslo. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -=- UnixSocket.h - base-class for UNIX stream sockets.
|
||||||
|
// This header also defines the UnixListener class, used
|
||||||
|
// to listen for incoming socket connections over UNIX
|
||||||
|
//
|
||||||
|
// NB: Any file descriptors created by the UnixSocket or
|
||||||
|
// UnixListener classes are close-on-exec if the OS supports
|
||||||
|
// it. UnixSockets initialised with a caller-supplied fd
|
||||||
|
// are NOT set to close-on-exec.
|
||||||
|
|
||||||
|
#ifndef __NETWORK_UNIX_SOCKET_H__
|
||||||
|
#define __NETWORK_UNIX_SOCKET_H__
|
||||||
|
|
||||||
|
#include <network/Socket.h>
|
||||||
|
|
||||||
|
namespace network {
|
||||||
|
|
||||||
|
class UnixSocket : public Socket {
|
||||||
|
public:
|
||||||
|
UnixSocket(int sock);
|
||||||
|
UnixSocket(const char *name);
|
||||||
|
|
||||||
|
virtual char* getPeerAddress();
|
||||||
|
virtual char* getPeerEndpoint();
|
||||||
|
|
||||||
|
virtual bool cork(bool enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
class UnixListener : public SocketListener {
|
||||||
|
public:
|
||||||
|
UnixListener(const char *listenaddr, int mode);
|
||||||
|
virtual ~UnixListener();
|
||||||
|
|
||||||
|
int getMyPort();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual Socket* createSocket(int fd);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __NETWORK_UNIX_SOCKET_H__
|
1035
common/network/websocket.c
Normal file
1035
common/network/websocket.c
Normal file
File diff suppressed because it is too large
Load Diff
122
common/network/websocket.h
Normal file
122
common/network/websocket.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
#define BUFSIZE 65536
|
||||||
|
#define DBUFSIZE (BUFSIZE * 3) / 4 - 20
|
||||||
|
|
||||||
|
#define SERVER_HANDSHAKE_HIXIE "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\
|
||||||
|
Upgrade: WebSocket\r\n\
|
||||||
|
Connection: Upgrade\r\n\
|
||||||
|
%sWebSocket-Origin: %s\r\n\
|
||||||
|
%sWebSocket-Location: %s://%s%s\r\n\
|
||||||
|
%sWebSocket-Protocol: %s\r\n\
|
||||||
|
\r\n%s"
|
||||||
|
|
||||||
|
#define SERVER_HANDSHAKE_HYBI "HTTP/1.1 101 Switching Protocols\r\n\
|
||||||
|
Upgrade: websocket\r\n\
|
||||||
|
Connection: Upgrade\r\n\
|
||||||
|
Sec-WebSocket-Accept: %s\r\n\
|
||||||
|
Sec-WebSocket-Protocol: %s\r\n\
|
||||||
|
\r\n"
|
||||||
|
|
||||||
|
#define HYBI_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||||
|
|
||||||
|
#define HYBI10_ACCEPTHDRLEN 29
|
||||||
|
|
||||||
|
#define HIXIE_MD5_DIGEST_LENGTH 16
|
||||||
|
|
||||||
|
#define POLICY_RESPONSE "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\n"
|
||||||
|
|
||||||
|
#define OPCODE_TEXT 0x01
|
||||||
|
#define OPCODE_BINARY 0x02
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char path[1024+1];
|
||||||
|
char host[1024+1];
|
||||||
|
char origin[1024+1];
|
||||||
|
char version[1024+1];
|
||||||
|
char connection[1024+1];
|
||||||
|
char protocols[1024+1];
|
||||||
|
char key1[1024+1];
|
||||||
|
char key2[1024+1];
|
||||||
|
char key3[8+1];
|
||||||
|
} headers_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int sockfd;
|
||||||
|
SSL_CTX *ssl_ctx;
|
||||||
|
SSL *ssl;
|
||||||
|
int hixie;
|
||||||
|
int hybi;
|
||||||
|
int opcode;
|
||||||
|
headers_t *headers;
|
||||||
|
char *cin_buf;
|
||||||
|
char *cout_buf;
|
||||||
|
char *tin_buf;
|
||||||
|
char *tout_buf;
|
||||||
|
} ws_ctx_t;
|
||||||
|
|
||||||
|
struct wspass_t {
|
||||||
|
int csock;
|
||||||
|
unsigned id;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int verbose;
|
||||||
|
int listen_sock;
|
||||||
|
unsigned int handler_id;
|
||||||
|
const char *cert;
|
||||||
|
const char *key;
|
||||||
|
const char *basicauth;
|
||||||
|
int ssl_only;
|
||||||
|
const char *httpdir;
|
||||||
|
} settings_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int resolve_host(struct in_addr *sin_addr, const char *hostname);
|
||||||
|
|
||||||
|
ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len);
|
||||||
|
|
||||||
|
ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len);
|
||||||
|
|
||||||
|
/* base64.c declarations */
|
||||||
|
//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);
|
||||||
|
|
||||||
|
extern __thread unsigned wsthread_handler_id;
|
||||||
|
|
||||||
|
#define gen_handler_msg(stream, ...) \
|
||||||
|
if (settings.verbose) { \
|
||||||
|
fprintf(stream, " websocket %d: ", wsthread_handler_id); \
|
||||||
|
fprintf(stream, __VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define wserr(...) \
|
||||||
|
{ \
|
||||||
|
fprintf(stderr, " websocket %d: ", wsthread_handler_id); \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define handler_msg(...) gen_handler_msg(stderr, __VA_ARGS__);
|
||||||
|
#define handler_emsg(...) gen_handler_msg(stderr, __VA_ARGS__);
|
||||||
|
|
||||||
|
void traffic(const char * token);
|
||||||
|
|
||||||
|
int encode_hixie(u_char const *src, size_t srclength,
|
||||||
|
char *target, size_t targsize);
|
||||||
|
int decode_hixie(char *src, size_t srclength,
|
||||||
|
u_char *target, size_t targsize,
|
||||||
|
unsigned int *opcode, unsigned int *left);
|
||||||
|
int encode_hybi(u_char const *src, size_t srclength,
|
||||||
|
char *target, size_t targsize, unsigned int opcode);
|
||||||
|
int decode_hybi(unsigned char *src, size_t srclength,
|
||||||
|
u_char *target, size_t targsize,
|
||||||
|
unsigned int *opcode, unsigned int *left);
|
||||||
|
|
||||||
|
void *start_server(void *unused);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern C
|
||||||
|
#endif
|
361
common/network/websockify.c
Normal file
361
common/network/websockify.c
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
* A WebSocket to TCP socket proxy with support for "wss://" encryption.
|
||||||
|
* Copyright 2010 Joel Martin
|
||||||
|
* Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
|
||||||
|
*
|
||||||
|
* You can make a cert/key with openssl using:
|
||||||
|
* openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
|
||||||
|
* as taken from http://docs.python.org/dev/library/ssl.html#certificates
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "websocket.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
char USAGE[] = "Usage: [options] " \
|
||||||
|
"[source_addr:]source_port target_addr:target_port\n\n" \
|
||||||
|
" --verbose|-v verbose messages and per frame traffic\n" \
|
||||||
|
" --daemon|-D become a daemon (background process)\n" \
|
||||||
|
" --run-once handle a single WebSocket connection and exit\n" \
|
||||||
|
" --cert CERT SSL certificate file\n" \
|
||||||
|
" --key KEY SSL key file (if separate from cert)\n" \
|
||||||
|
" --ssl-only disallow non-encrypted connections";
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int pipe_error;
|
||||||
|
extern settings_t settings;
|
||||||
|
|
||||||
|
static void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
||||||
|
fd_set rlist, wlist, elist;
|
||||||
|
struct timeval tv;
|
||||||
|
int maxfd, client = ws_ctx->sockfd;
|
||||||
|
unsigned int opcode, left, ret;
|
||||||
|
unsigned int tout_start, tout_end, cout_start, cout_end;
|
||||||
|
unsigned int tin_start, tin_end;
|
||||||
|
ssize_t len, bytes;
|
||||||
|
|
||||||
|
tout_start = tout_end = cout_start = cout_end =
|
||||||
|
tin_start = tin_end = 0;
|
||||||
|
maxfd = client > target ? client+1 : target+1;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO(&rlist);
|
||||||
|
FD_ZERO(&wlist);
|
||||||
|
FD_ZERO(&elist);
|
||||||
|
|
||||||
|
FD_SET(client, &elist);
|
||||||
|
FD_SET(target, &elist);
|
||||||
|
|
||||||
|
if (tout_end == tout_start) {
|
||||||
|
// Nothing queued for target, so read from client
|
||||||
|
FD_SET(client, &rlist);
|
||||||
|
} else {
|
||||||
|
// Data queued for target, so write to it
|
||||||
|
FD_SET(target, &wlist);
|
||||||
|
}
|
||||||
|
if (cout_end == cout_start) {
|
||||||
|
// Nothing queued for client, so read from target
|
||||||
|
FD_SET(target, &rlist);
|
||||||
|
} else {
|
||||||
|
// Data queued for client, so write to it
|
||||||
|
FD_SET(client, &wlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = select(maxfd, &rlist, &wlist, &elist, &tv);
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
if (pipe_error) { break; }
|
||||||
|
|
||||||
|
if (FD_ISSET(target, &elist)) {
|
||||||
|
handler_emsg("target exception\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (FD_ISSET(client, &elist)) {
|
||||||
|
handler_emsg("client exception\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
handler_emsg("select(): %s\n", strerror(errno));
|
||||||
|
break;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
//handler_emsg("select timeout\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(target, &wlist)) {
|
||||||
|
len = tout_end-tout_start;
|
||||||
|
bytes = send(target, ws_ctx->tout_buf + tout_start, len, 0);
|
||||||
|
if (pipe_error) { break; }
|
||||||
|
if (bytes < 0) {
|
||||||
|
handler_emsg("target connection error: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tout_start += bytes;
|
||||||
|
if (tout_start >= tout_end) {
|
||||||
|
tout_start = tout_end = 0;
|
||||||
|
traffic(">");
|
||||||
|
} else {
|
||||||
|
traffic(">.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(client, &wlist)) {
|
||||||
|
len = cout_end-cout_start;
|
||||||
|
bytes = ws_send(ws_ctx, ws_ctx->cout_buf + cout_start, len);
|
||||||
|
if (pipe_error) { break; }
|
||||||
|
if (len < 3) {
|
||||||
|
handler_emsg("len: %d, bytes: %d: %d\n",
|
||||||
|
(int) len, (int) bytes,
|
||||||
|
(int) *(ws_ctx->cout_buf + cout_start));
|
||||||
|
}
|
||||||
|
cout_start += bytes;
|
||||||
|
if (cout_start >= cout_end) {
|
||||||
|
cout_start = cout_end = 0;
|
||||||
|
traffic("<");
|
||||||
|
} else {
|
||||||
|
traffic("<.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(target, &rlist)) {
|
||||||
|
bytes = recv(target, ws_ctx->cin_buf, DBUFSIZE , 0);
|
||||||
|
if (pipe_error) { break; }
|
||||||
|
if (bytes <= 0) {
|
||||||
|
handler_emsg("target closed connection\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cout_start = 0;
|
||||||
|
if (ws_ctx->hybi) {
|
||||||
|
cout_end = encode_hybi(ws_ctx->cin_buf, bytes,
|
||||||
|
ws_ctx->cout_buf, BUFSIZE, ws_ctx->opcode);
|
||||||
|
} else {
|
||||||
|
cout_end = encode_hixie(ws_ctx->cin_buf, bytes,
|
||||||
|
ws_ctx->cout_buf, BUFSIZE);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
printf("encoded: ");
|
||||||
|
for (i=0; i< cout_end; i++) {
|
||||||
|
printf("%u,", (unsigned char) *(ws_ctx->cout_buf+i));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
*/
|
||||||
|
if (cout_end < 0) {
|
||||||
|
handler_emsg("encoding error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
traffic("{");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(client, &rlist)) {
|
||||||
|
bytes = ws_recv(ws_ctx, ws_ctx->tin_buf + tin_end, BUFSIZE-1);
|
||||||
|
if (pipe_error) { break; }
|
||||||
|
if (bytes <= 0) {
|
||||||
|
handler_emsg("client closed connection\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tin_end += bytes;
|
||||||
|
/*
|
||||||
|
printf("before decode: ");
|
||||||
|
for (i=0; i< bytes; i++) {
|
||||||
|
printf("%u,", (unsigned char) *(ws_ctx->tin_buf+i));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
*/
|
||||||
|
if (ws_ctx->hybi) {
|
||||||
|
len = decode_hybi(ws_ctx->tin_buf + tin_start,
|
||||||
|
tin_end-tin_start,
|
||||||
|
ws_ctx->tout_buf, BUFSIZE-1,
|
||||||
|
&opcode, &left);
|
||||||
|
} else {
|
||||||
|
len = decode_hixie(ws_ctx->tin_buf + tin_start,
|
||||||
|
tin_end-tin_start,
|
||||||
|
ws_ctx->tout_buf, BUFSIZE-1,
|
||||||
|
&opcode, &left);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcode == 8) {
|
||||||
|
handler_msg("client sent orderly close frame\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("decoded: ");
|
||||||
|
for (i=0; i< len; i++) {
|
||||||
|
printf("%u,", (unsigned char) *(ws_ctx->tout_buf+i));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
*/
|
||||||
|
if (len < 0) {
|
||||||
|
handler_emsg("decoding error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (left) {
|
||||||
|
tin_start = tin_end - left;
|
||||||
|
//printf("partial frame from client");
|
||||||
|
} else {
|
||||||
|
tin_start = 0;
|
||||||
|
tin_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
traffic("}");
|
||||||
|
tout_start = 0;
|
||||||
|
tout_end = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy_handler(ws_ctx_t *ws_ctx) {
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strcpy(addr.sun_path, ".KasmVNCSock");
|
||||||
|
addr.sun_path[0] = '\0';
|
||||||
|
|
||||||
|
int tsock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
handler_msg("connecting to VNC target\n");
|
||||||
|
|
||||||
|
if (connect(tsock, (struct sockaddr *) &addr,
|
||||||
|
sizeof(sa_family_t) + sizeof(".KasmVNCSock")) < 0) {
|
||||||
|
|
||||||
|
handler_emsg("Could not connect to target: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_proxy(ws_ctx, tsock);
|
||||||
|
|
||||||
|
shutdown(tsock, SHUT_RDWR);
|
||||||
|
close(tsock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd, c, option_index = 0;
|
||||||
|
static int ssl_only = 0, daemon = 0, run_once = 0, verbose = 0;
|
||||||
|
char *found;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"verbose", no_argument, &verbose, 'v'},
|
||||||
|
{"ssl-only", no_argument, &ssl_only, 1 },
|
||||||
|
{"daemon", no_argument, &daemon, 'D'},
|
||||||
|
/* ---- */
|
||||||
|
{"run-once", no_argument, 0, 'r'},
|
||||||
|
{"cert", required_argument, 0, 'c'},
|
||||||
|
{"key", required_argument, 0, 'k'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
settings.cert = realpath("self.pem", NULL);
|
||||||
|
if (!settings.cert) {
|
||||||
|
/* Make sure it's always set to something */
|
||||||
|
settings.cert = "self.pem";
|
||||||
|
}
|
||||||
|
settings.key = "";
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
c = getopt_long (argc, argv, "vDrc:k:",
|
||||||
|
long_options, &option_index);
|
||||||
|
|
||||||
|
/* Detect the end */
|
||||||
|
if (c == -1) { break; }
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 0:
|
||||||
|
break; // ignore
|
||||||
|
case 1:
|
||||||
|
break; // ignore
|
||||||
|
case 'v':
|
||||||
|
verbose = 1;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
daemon = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
run_once = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
settings.cert = realpath(optarg, NULL);
|
||||||
|
if (! settings.cert) {
|
||||||
|
usage("No cert file at %s\n", optarg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
settings.key = realpath(optarg, NULL);
|
||||||
|
if (! settings.key) {
|
||||||
|
usage("No key file at %s\n", optarg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.verbose = verbose;
|
||||||
|
settings.ssl_only = ssl_only;
|
||||||
|
settings.daemon = daemon;
|
||||||
|
settings.run_once = run_once;
|
||||||
|
|
||||||
|
if ((argc-optind) != 2) {
|
||||||
|
usage("Invalid number of arguments\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
found = strstr(argv[optind], ":");
|
||||||
|
if (found) {
|
||||||
|
memcpy(settings.listen_host, argv[optind], found-argv[optind]);
|
||||||
|
settings.listen_port = strtol(found+1, NULL, 10);
|
||||||
|
} else {
|
||||||
|
settings.listen_host[0] = '\0';
|
||||||
|
settings.listen_port = strtol(argv[optind], NULL, 10);
|
||||||
|
}
|
||||||
|
optind++;
|
||||||
|
if (settings.listen_port == 0) {
|
||||||
|
usage("Could not parse listen_port\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
found = strstr(argv[optind], ":");
|
||||||
|
if (found) {
|
||||||
|
memcpy(target_host, argv[optind], found-argv[optind]);
|
||||||
|
target_port = strtol(found+1, NULL, 10);
|
||||||
|
} else {
|
||||||
|
usage("Target argument must be host:port\n");
|
||||||
|
}
|
||||||
|
if (target_port == 0) {
|
||||||
|
usage("Could not parse target port\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl_only) {
|
||||||
|
if (access(settings.cert, R_OK) != 0) {
|
||||||
|
usage("SSL only and cert file '%s' not found\n", settings.cert);
|
||||||
|
}
|
||||||
|
} else if (access(settings.cert, R_OK) != 0) {
|
||||||
|
fprintf(stderr, "Warning: '%s' not found\n", settings.cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf(" verbose: %d\n", settings.verbose);
|
||||||
|
//printf(" ssl_only: %d\n", settings.ssl_only);
|
||||||
|
//printf(" daemon: %d\n", settings.daemon);
|
||||||
|
//printf(" run_once: %d\n", settings.run_once);
|
||||||
|
//printf(" cert: %s\n", settings.cert);
|
||||||
|
//printf(" key: %s\n", settings.key);
|
||||||
|
|
||||||
|
settings.handler = proxy_handler;
|
||||||
|
start_server();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
15
common/os/CMakeLists.txt
Normal file
15
common/os/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
include_directories(${CMAKE_SOURCE_DIR}/common)
|
||||||
|
|
||||||
|
add_library(os STATIC
|
||||||
|
Mutex.cxx
|
||||||
|
Thread.cxx
|
||||||
|
w32tiger.c
|
||||||
|
os.cxx)
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
target_link_libraries(os pthread)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
libtool_create_control_file(os)
|
||||||
|
endif()
|
154
common/os/Mutex.cxx
Normal file
154
common/os/Mutex.cxx
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* Copyright 2015 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
#include <os/Mutex.h>
|
||||||
|
|
||||||
|
using namespace os;
|
||||||
|
|
||||||
|
Mutex::Mutex()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
systemMutex = new CRITICAL_SECTION;
|
||||||
|
InitializeCriticalSection((CRITICAL_SECTION*)systemMutex);
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
systemMutex = new pthread_mutex_t;
|
||||||
|
ret = pthread_mutex_init((pthread_mutex_t*)systemMutex, NULL);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to create mutex", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::~Mutex()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
DeleteCriticalSection((CRITICAL_SECTION*)systemMutex);
|
||||||
|
delete (CRITICAL_SECTION*)systemMutex;
|
||||||
|
#else
|
||||||
|
pthread_mutex_destroy((pthread_mutex_t*)systemMutex);
|
||||||
|
delete (pthread_mutex_t*)systemMutex;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::lock()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
EnterCriticalSection((CRITICAL_SECTION*)systemMutex);
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pthread_mutex_lock((pthread_mutex_t*)systemMutex);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to lock mutex", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::unlock()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
LeaveCriticalSection((CRITICAL_SECTION*)systemMutex);
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pthread_mutex_unlock((pthread_mutex_t*)systemMutex);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to unlock mutex", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Condition::Condition(Mutex* mutex)
|
||||||
|
{
|
||||||
|
this->mutex = mutex;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
systemCondition = new CONDITION_VARIABLE;
|
||||||
|
InitializeConditionVariable((CONDITION_VARIABLE*)systemCondition);
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
systemCondition = new pthread_cond_t;
|
||||||
|
ret = pthread_cond_init((pthread_cond_t*)systemCondition, NULL);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to create condition variable", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Condition::~Condition()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
delete (CONDITION_VARIABLE*)systemCondition;
|
||||||
|
#else
|
||||||
|
pthread_cond_destroy((pthread_cond_t*)systemCondition);
|
||||||
|
delete (pthread_cond_t*)systemCondition;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Condition::wait()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
ret = SleepConditionVariableCS((CONDITION_VARIABLE*)systemCondition,
|
||||||
|
(CRITICAL_SECTION*)mutex->systemMutex,
|
||||||
|
INFINITE);
|
||||||
|
if (!ret)
|
||||||
|
throw rdr::SystemException("Failed to wait on condition variable", GetLastError());
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pthread_cond_wait((pthread_cond_t*)systemCondition,
|
||||||
|
(pthread_mutex_t*)mutex->systemMutex);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to wait on condition variable", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Condition::signal()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
WakeConditionVariable((CONDITION_VARIABLE*)systemCondition);
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pthread_cond_signal((pthread_cond_t*)systemCondition);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to signal condition variable", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Condition::broadcast()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
WakeAllConditionVariable((CONDITION_VARIABLE*)systemCondition);
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pthread_cond_broadcast((pthread_cond_t*)systemCondition);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to broadcast condition variable", ret);
|
||||||
|
#endif
|
||||||
|
}
|
64
common/os/Mutex.h
Normal file
64
common/os/Mutex.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* Copyright 2015 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 __OS_MUTEX_H__
|
||||||
|
#define __OS_MUTEX_H__
|
||||||
|
|
||||||
|
namespace os {
|
||||||
|
class Condition;
|
||||||
|
|
||||||
|
class Mutex {
|
||||||
|
public:
|
||||||
|
Mutex();
|
||||||
|
~Mutex();
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
void* systemMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoMutex {
|
||||||
|
public:
|
||||||
|
AutoMutex(Mutex* mutex) { m = mutex; m->lock(); }
|
||||||
|
~AutoMutex() { m->unlock(); }
|
||||||
|
private:
|
||||||
|
Mutex* m;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Condition {
|
||||||
|
public:
|
||||||
|
Condition(Mutex* mutex);
|
||||||
|
~Condition();
|
||||||
|
|
||||||
|
void wait();
|
||||||
|
|
||||||
|
void signal();
|
||||||
|
void broadcast();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mutex* mutex;
|
||||||
|
void* systemCondition;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
165
common/os/Thread.cxx
Normal file
165
common/os/Thread.cxx
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/* Copyright 2015 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
#include <os/Mutex.h>
|
||||||
|
#include <os/Thread.h>
|
||||||
|
|
||||||
|
using namespace os;
|
||||||
|
|
||||||
|
Thread::Thread() : running(false), threadId(NULL)
|
||||||
|
{
|
||||||
|
mutex = new Mutex;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
threadId = new HANDLE;
|
||||||
|
#else
|
||||||
|
threadId = new pthread_t;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread::~Thread()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
delete (HANDLE*)threadId;
|
||||||
|
#else
|
||||||
|
if (isRunning())
|
||||||
|
pthread_cancel(*(pthread_t*)threadId);
|
||||||
|
delete (pthread_t*)threadId;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
delete mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::start()
|
||||||
|
{
|
||||||
|
AutoMutex a(mutex);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
*(HANDLE*)threadId = CreateThread(NULL, 0, startRoutine, this, 0, NULL);
|
||||||
|
if (*(HANDLE*)threadId == NULL)
|
||||||
|
throw rdr::SystemException("Failed to create thread", GetLastError());
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
sigset_t all, old;
|
||||||
|
|
||||||
|
// Creating threads from libraries is a bit evil, so mitigate the
|
||||||
|
// issue by at least avoiding signals on these threads
|
||||||
|
sigfillset(&all);
|
||||||
|
ret = pthread_sigmask(SIG_SETMASK, &all, &old);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to mask signals", ret);
|
||||||
|
|
||||||
|
ret = pthread_create((pthread_t*)threadId, NULL, startRoutine, this);
|
||||||
|
|
||||||
|
pthread_sigmask(SIG_SETMASK, &old, NULL);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to create thread", ret);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::wait()
|
||||||
|
{
|
||||||
|
if (!isRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD ret;
|
||||||
|
|
||||||
|
ret = WaitForSingleObject(*(HANDLE*)threadId, INFINITE);
|
||||||
|
if (ret != WAIT_OBJECT_0)
|
||||||
|
throw rdr::SystemException("Failed to join thread", GetLastError());
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pthread_join(*(pthread_t*)threadId, NULL);
|
||||||
|
if (ret != 0)
|
||||||
|
throw rdr::SystemException("Failed to join thread", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thread::isRunning()
|
||||||
|
{
|
||||||
|
AutoMutex a(mutex);
|
||||||
|
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Thread::getSystemCPUCount()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
SYSTEM_INFO si;
|
||||||
|
size_t count;
|
||||||
|
DWORD mask;
|
||||||
|
|
||||||
|
GetSystemInfo(&si);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (mask = si.dwActiveProcessorMask;mask != 0;mask >>= 1) {
|
||||||
|
if (mask & 0x1)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > si.dwNumberOfProcessors)
|
||||||
|
count = si.dwNumberOfProcessors;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
#else
|
||||||
|
long ret;
|
||||||
|
|
||||||
|
ret = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
long unsigned __stdcall Thread::startRoutine(void* data)
|
||||||
|
#else
|
||||||
|
void* Thread::startRoutine(void* data)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Thread *self;
|
||||||
|
|
||||||
|
self = (Thread*)data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
self->worker();
|
||||||
|
} catch(...) {
|
||||||
|
}
|
||||||
|
|
||||||
|
self->mutex->lock();
|
||||||
|
self->running = false;
|
||||||
|
self->mutex->unlock();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
58
common/os/Thread.h
Normal file
58
common/os/Thread.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* Copyright 2015 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 __OS_THREAD_H__
|
||||||
|
#define __OS_THREAD_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
namespace os {
|
||||||
|
class Mutex;
|
||||||
|
|
||||||
|
class Thread {
|
||||||
|
public:
|
||||||
|
Thread();
|
||||||
|
virtual ~Thread();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void wait();
|
||||||
|
|
||||||
|
bool isRunning();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static size_t getSystemCPUCount();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void worker() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef WIN32
|
||||||
|
static long unsigned __stdcall startRoutine(void* data);
|
||||||
|
#else
|
||||||
|
static void* startRoutine(void* data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mutex *mutex;
|
||||||
|
bool running;
|
||||||
|
|
||||||
|
void *threadId;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
97
common/os/os.cxx
Normal file
97
common/os/os.cxx
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/* Copyright (C) 2010 TightVNC Team. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <os/os.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wininet.h> /* MinGW needs it */
|
||||||
|
#include <shlobj.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int getvnchomedir(char **dirp)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
char *homedir, *dir;
|
||||||
|
size_t len;
|
||||||
|
uid_t uid;
|
||||||
|
struct passwd *passwd;
|
||||||
|
#else
|
||||||
|
TCHAR *dir;
|
||||||
|
BOOL ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert(dirp != NULL && *dirp == NULL);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
homedir = getenv("HOME");
|
||||||
|
if (homedir == NULL) {
|
||||||
|
uid = getuid();
|
||||||
|
passwd = getpwuid(uid);
|
||||||
|
if (passwd == NULL) {
|
||||||
|
/* Do we want emit error msg here? */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
homedir = passwd->pw_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(homedir);
|
||||||
|
dir = new char[len+7];
|
||||||
|
if (dir == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(dir, homedir, len);
|
||||||
|
memcpy(dir + len, "/.vnc/\0", 7);
|
||||||
|
#else
|
||||||
|
dir = new TCHAR[MAX_PATH];
|
||||||
|
if (dir == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, FALSE);
|
||||||
|
if (ret == FALSE) {
|
||||||
|
delete [] dir;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(dir+strlen(dir), (TCHAR *)"\\vnc\\\0", 6);
|
||||||
|
#endif
|
||||||
|
*dirp = dir;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileexists(char *file)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return (GetFileAttributes(file) == INVALID_FILE_ATTRIBUTES) ? -1 : 0;
|
||||||
|
#else
|
||||||
|
return access(file, R_OK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
51
common/os/os.h
Normal file
51
common/os/os.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* Copyright (C) 2010 TightVNC Team. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 OS_OS_H
|
||||||
|
#define OS_OS_H
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <os/w32tiger.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get VNC home directory ($HOME/.vnc or %APPDATA%/vnc/).
|
||||||
|
* If HOME environment variable is set then it is used.
|
||||||
|
* Otherwise home directory is obtained via getpwuid function.
|
||||||
|
*
|
||||||
|
* Note for Windows:
|
||||||
|
* This functions returns array of TCHARs, not array of chars.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 - Success
|
||||||
|
* -1 - Failure
|
||||||
|
*/
|
||||||
|
int getvnchomedir(char **dirp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the file exists
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 - Success
|
||||||
|
* -1 - Failure
|
||||||
|
*/
|
||||||
|
int fileexists(char *file);
|
||||||
|
|
||||||
|
#endif /* OS_OS_H */
|
33
common/os/w32tiger.c
Normal file
33
common/os/w32tiger.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* Copyright (C) 2011 TigerVNC Team. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#define INITGUID
|
||||||
|
#include <basetyps.h>
|
||||||
|
|
||||||
|
#ifndef HAVE_ACTIVE_DESKTOP_L
|
||||||
|
DEFINE_GUID(CLSID_ActiveDesktop,0x75048700L,0xEF1F,0x11D0,0x98,0x88,0x00,0x60,0x97,0xDE,0xAC,0xF9);
|
||||||
|
DEFINE_GUID(IID_IActiveDesktop,0xF490EB00L,0x1240,0x11D1,0x98,0x88,0x00,0x60,0x97,0xDE,0xAC,0xF9);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* WIN32 */
|
187
common/os/w32tiger.h
Normal file
187
common/os/w32tiger.h
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/* Copyright (C) 2011 TigerVNC Team. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 OS_W32TIGER_H
|
||||||
|
#define OS_W32TIGER_H
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wininet.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <shlguid.h>
|
||||||
|
#include <wininet.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Windows has different names for these */
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
|
||||||
|
|
||||||
|
/* MSLLHOOKSTRUCT structure*/
|
||||||
|
#ifndef LLMHF_INJECTED
|
||||||
|
#define LLMHF_INJECTED 0x00000001
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* IActiveDesktop. As of 2011-10-12, MinGW does not define
|
||||||
|
IActiveDesktop in any way (see tracker 2877129), while MinGW64 is
|
||||||
|
broken: has the headers but not the lib symbols. */
|
||||||
|
#ifndef HAVE_ACTIVE_DESKTOP_H
|
||||||
|
extern const GUID CLSID_ActiveDesktop;
|
||||||
|
extern const GUID IID_IActiveDesktop;
|
||||||
|
|
||||||
|
/* IActiveDesktop::AddUrl */
|
||||||
|
#define ADDURL_SILENT 0x0001
|
||||||
|
|
||||||
|
/* IActiveDesktop::AddDesktopItemWithUI */
|
||||||
|
#define DTI_ADDUI_DEFAULT 0x00000000
|
||||||
|
#define DTI_ADDUI_DISPSUBWIZARD 0x00000001
|
||||||
|
#define DTI_ADDUI_POSITIONITEM 0x00000002
|
||||||
|
|
||||||
|
/* IActiveDesktop::ModifyDesktopItem */
|
||||||
|
#define COMP_ELEM_TYPE 0x00000001
|
||||||
|
#define COMP_ELEM_CHECKED 0x00000002
|
||||||
|
#define COMP_ELEM_DIRTY 0x00000004
|
||||||
|
#define COMP_ELEM_NOSCROLL 0x00000008
|
||||||
|
#define COMP_ELEM_POS_LEFT 0x00000010
|
||||||
|
#define COMP_ELEM_POS_TOP 0x00000020
|
||||||
|
#define COMP_ELEM_SIZE_WIDTH 0x00000040
|
||||||
|
#define COMP_ELEM_SIZE_HEIGHT 0x00000080
|
||||||
|
#define COMP_ELEM_POS_ZINDEX 0x00000100
|
||||||
|
#define COMP_ELEM_SOURCE 0x00000200
|
||||||
|
#define COMP_ELEM_FRIENDLYNAME 0x00000400
|
||||||
|
#define COMP_ELEM_SUBSCRIBEDURL 0x00000800
|
||||||
|
#define COMP_ELEM_ORIGINAL_CSI 0x00001000
|
||||||
|
#define COMP_ELEM_RESTORED_CSI 0x00002000
|
||||||
|
#define COMP_ELEM_CURITEMSTATE 0x00004000
|
||||||
|
#define COMP_ELEM_ALL 0x00007FFF /* OR-ed all COMP_ELEM_ */
|
||||||
|
|
||||||
|
/* IActiveDesktop::GetWallpaper */
|
||||||
|
#define AD_GETWP_BMP 0x00000000
|
||||||
|
#define AD_GETWP_IMAGE 0x00000001
|
||||||
|
#define AD_GETWP_LAST_APPLIED 0x00000002
|
||||||
|
|
||||||
|
/* IActiveDesktop::ApplyChanges */
|
||||||
|
#define AD_APPLY_SAVE 0x00000001
|
||||||
|
#define AD_APPLY_HTMLGEN 0x00000002
|
||||||
|
#define AD_APPLY_REFRESH 0x00000004
|
||||||
|
#define AD_APPLY_ALL 0x00000007 /* OR-ed three AD_APPLY_ above */
|
||||||
|
#define AD_APPLY_FORCE 0x00000008
|
||||||
|
#define AD_APPLY_BUFFERED_REFRESH 0x00000010
|
||||||
|
#define AD_APPLY_DYNAMICREFRESH 0x00000020
|
||||||
|
|
||||||
|
/* Structures for IActiveDesktop */
|
||||||
|
typedef struct {
|
||||||
|
DWORD dwSize;
|
||||||
|
int iLeft;
|
||||||
|
int iTop;
|
||||||
|
DWORD dwWidth;
|
||||||
|
DWORD dwHeight;
|
||||||
|
DWORD dwItemState;
|
||||||
|
} COMPSTATEINFO, *LPCOMPSTATEINFO;
|
||||||
|
typedef const COMPSTATEINFO *LPCCOMPSTATEINFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD dwSize;
|
||||||
|
int iLeft;
|
||||||
|
int iTop;
|
||||||
|
DWORD dwWidth;
|
||||||
|
DWORD dwHeight;
|
||||||
|
int izIndex;
|
||||||
|
BOOL fCanResize;
|
||||||
|
BOOL fCanResizeX;
|
||||||
|
BOOL fCanResizeY;
|
||||||
|
int iPreferredLeftPercent;
|
||||||
|
int iPreferredTopPercent;
|
||||||
|
} COMPPOS, *LPCOMPPOS;
|
||||||
|
typedef const COMPPOS *LPCCOMPPOS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD dwSize;
|
||||||
|
DWORD dwID;
|
||||||
|
int iComponentType;
|
||||||
|
BOOL fChecked;
|
||||||
|
BOOL fDirty;
|
||||||
|
BOOL fNoScroll;
|
||||||
|
COMPPOS cpPos;
|
||||||
|
WCHAR wszFriendlyName[MAX_PATH];
|
||||||
|
WCHAR wszSource[INTERNET_MAX_URL_LENGTH];
|
||||||
|
WCHAR wszSubscribedURL[INTERNET_MAX_URL_LENGTH];
|
||||||
|
DWORD dwCurItemState;
|
||||||
|
COMPSTATEINFO csiOriginal;
|
||||||
|
COMPSTATEINFO csiRestored;
|
||||||
|
} COMPONENT, *LPCOMPONENT;
|
||||||
|
typedef const COMPONENT *LPCCOMPONENT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD dwSize;
|
||||||
|
BOOL fEnableComponents;
|
||||||
|
BOOL fActiveDesktop;
|
||||||
|
} COMPONENTSOPT, *LPCOMPONENTSOPT;
|
||||||
|
typedef const COMPONENTSOPT *LPCCOMPONENTSOPT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD dwSize;
|
||||||
|
DWORD dwStyle;
|
||||||
|
} WALLPAPEROPT, *LPWALLPAPEROPT;
|
||||||
|
typedef const WALLPAPEROPT *LPCWALLPAPEROPT;
|
||||||
|
|
||||||
|
/* WALLPAPEROPT styles */
|
||||||
|
#define WPSTYLE_CENTER 0x0
|
||||||
|
#define WPSTYLE_TILE 0x1
|
||||||
|
#define WPSTYLE_STRETCH 0x2
|
||||||
|
#define WPSTYLE_MAX 0x3
|
||||||
|
|
||||||
|
/* Those two are defined in Windows 7 and newer, we don't need them now */
|
||||||
|
#if 0
|
||||||
|
#define WPSTYLE_KEEPASPECT 0x3
|
||||||
|
#define WPSTYLE_CROPTOFIT 0x4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INTERFACE IActiveDesktop
|
||||||
|
DECLARE_INTERFACE_(IActiveDesktop, IUnknown)
|
||||||
|
{
|
||||||
|
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
|
||||||
|
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
||||||
|
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
||||||
|
STDMETHOD(AddDesktopItem)(THIS_ LPCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(AddDesktopItemWithUI)(THIS_ HWND,LPCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(AddUrl)(THIS_ HWND,LPCWSTR,LPCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(ApplyChanges)(THIS_ DWORD) PURE;
|
||||||
|
STDMETHOD(GenerateDesktopItemHtml)(THIS_ LPCWSTR,LPCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetDesktopItem)(THIS_ int,LPCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetDesktopItemByID)(THIS_ DWORD,LPCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetDesktopItemBySource)(THIS_ LPCWSTR,LPCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetDesktopItemCount)(THIS_ LPINT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetDesktopItemOptions)(THIS_ LPCOMPONENTSOPT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetPattern)(THIS_ LPWSTR,UINT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetWallpaper)(THIS_ LPWSTR,UINT,DWORD) PURE;
|
||||||
|
STDMETHOD(GetWallpaperOptions)(THIS_ LPWALLPAPEROPT,DWORD) PURE;
|
||||||
|
STDMETHOD(ModifyDesktopItem)(THIS_ LPCCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(RemoveDesktopItem)(THIS_ LPCCOMPONENT,DWORD) PURE;
|
||||||
|
STDMETHOD(SetDesktopItemOptions)(THIS_ LPCCOMPONENTSOPT,DWORD) PURE;
|
||||||
|
STDMETHOD(SetPattern)(THIS_ LPCWSTR,DWORD) PURE;
|
||||||
|
STDMETHOD(SetWallpaper)(THIS_ LPCWSTR,DWORD) PURE;
|
||||||
|
STDMETHOD(SetWallpaperOptions)(THIS_ LPCWALLPAPEROPT,DWORD) PURE;
|
||||||
|
};
|
||||||
|
#undef INTERFACE
|
||||||
|
#endif /* HAVE_ACTIVE_DESKTOP_H */
|
||||||
|
|
||||||
|
#endif /* WIN32 */
|
||||||
|
#endif /* OS_W32TIGER_H */
|
89
common/os/winerrno.h
Normal file
89
common/os/winerrno.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
/* Generated with:
|
||||||
|
cat /usr/i686-pc-mingw32/sys-root/mingw/include/winerror.h \
|
||||||
|
| awk '/#define WSAE.*WSABASE/{gsub("WSA", ""); print "#undef " $2 "\n#define " $2 " WSA" $2}' \
|
||||||
|
| egrep -v 'EINTR|EBADF|EACCES|EFAULT|EINVAL|EMFILE|_QOS|PROVIDER|PROCTABLE'
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef EWOULDBLOCK
|
||||||
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
|
#undef EINPROGRESS
|
||||||
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
|
#undef EALREADY
|
||||||
|
#define EALREADY WSAEALREADY
|
||||||
|
#undef ENOTSOCK
|
||||||
|
#define ENOTSOCK WSAENOTSOCK
|
||||||
|
#undef EDESTADDRREQ
|
||||||
|
#define EDESTADDRREQ WSAEDESTADDRREQ
|
||||||
|
#undef EMSGSIZE
|
||||||
|
#define EMSGSIZE WSAEMSGSIZE
|
||||||
|
#undef EPROTOTYPE
|
||||||
|
#define EPROTOTYPE WSAEPROTOTYPE
|
||||||
|
#undef ENOPROTOOPT
|
||||||
|
#define ENOPROTOOPT WSAENOPROTOOPT
|
||||||
|
#undef EPROTONOSUPPORT
|
||||||
|
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
|
||||||
|
#undef ESOCKTNOSUPPORT
|
||||||
|
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
|
||||||
|
#undef EOPNOTSUPP
|
||||||
|
#define EOPNOTSUPP WSAEOPNOTSUPP
|
||||||
|
#undef EPFNOSUPPORT
|
||||||
|
#define EPFNOSUPPORT WSAEPFNOSUPPORT
|
||||||
|
#undef EAFNOSUPPORT
|
||||||
|
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||||
|
#undef EADDRINUSE
|
||||||
|
#define EADDRINUSE WSAEADDRINUSE
|
||||||
|
#undef EADDRNOTAVAIL
|
||||||
|
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
|
||||||
|
#undef ENETDOWN
|
||||||
|
#define ENETDOWN WSAENETDOWN
|
||||||
|
#undef ENETUNREACH
|
||||||
|
#define ENETUNREACH WSAENETUNREACH
|
||||||
|
#undef ENETRESET
|
||||||
|
#define ENETRESET WSAENETRESET
|
||||||
|
#undef ECONNABORTED
|
||||||
|
#define ECONNABORTED WSAECONNABORTED
|
||||||
|
#undef ECONNRESET
|
||||||
|
#define ECONNRESET WSAECONNRESET
|
||||||
|
#undef ENOBUFS
|
||||||
|
#define ENOBUFS WSAENOBUFS
|
||||||
|
#undef EISCONN
|
||||||
|
#define EISCONN WSAEISCONN
|
||||||
|
#undef ENOTCONN
|
||||||
|
#define ENOTCONN WSAENOTCONN
|
||||||
|
#undef ESHUTDOWN
|
||||||
|
#define ESHUTDOWN WSAESHUTDOWN
|
||||||
|
#undef ETOOMANYREFS
|
||||||
|
#define ETOOMANYREFS WSAETOOMANYREFS
|
||||||
|
#undef ETIMEDOUT
|
||||||
|
#define ETIMEDOUT WSAETIMEDOUT
|
||||||
|
#undef ECONNREFUSED
|
||||||
|
#define ECONNREFUSED WSAECONNREFUSED
|
||||||
|
#undef ELOOP
|
||||||
|
#define ELOOP WSAELOOP
|
||||||
|
#undef ENAMETOOLONG
|
||||||
|
#define ENAMETOOLONG WSAENAMETOOLONG
|
||||||
|
#undef EHOSTDOWN
|
||||||
|
#define EHOSTDOWN WSAEHOSTDOWN
|
||||||
|
#undef EHOSTUNREACH
|
||||||
|
#define EHOSTUNREACH WSAEHOSTUNREACH
|
||||||
|
#undef ENOTEMPTY
|
||||||
|
#define ENOTEMPTY WSAENOTEMPTY
|
||||||
|
#undef EPROCLIM
|
||||||
|
#define EPROCLIM WSAEPROCLIM
|
||||||
|
#undef EUSERS
|
||||||
|
#define EUSERS WSAEUSERS
|
||||||
|
#undef EDQUOT
|
||||||
|
#define EDQUOT WSAEDQUOT
|
||||||
|
#undef ESTALE
|
||||||
|
#define ESTALE WSAESTALE
|
||||||
|
#undef EREMOTE
|
||||||
|
#define EREMOTE WSAEREMOTE
|
||||||
|
#undef EDISCON
|
||||||
|
#define EDISCON WSAEDISCON
|
||||||
|
#undef ENOMORE
|
||||||
|
#define ENOMORE WSAENOMORE
|
||||||
|
#undef ECANCELLED
|
||||||
|
#define ECANCELLED WSAECANCELLED
|
||||||
|
#undef EREFUSED
|
||||||
|
#define EREFUSED WSAEREFUSED
|
30
common/rdr/CMakeLists.txt
Normal file
30
common/rdr/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
include_directories(${CMAKE_SOURCE_DIR}/common ${ZLIB_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
add_library(rdr STATIC
|
||||||
|
Exception.cxx
|
||||||
|
FdInStream.cxx
|
||||||
|
FdOutStream.cxx
|
||||||
|
FileInStream.cxx
|
||||||
|
HexInStream.cxx
|
||||||
|
HexOutStream.cxx
|
||||||
|
InStream.cxx
|
||||||
|
RandomStream.cxx
|
||||||
|
TLSException.cxx
|
||||||
|
TLSInStream.cxx
|
||||||
|
TLSOutStream.cxx
|
||||||
|
ZlibInStream.cxx
|
||||||
|
ZlibOutStream.cxx)
|
||||||
|
|
||||||
|
set(RDR_LIBRARIES ${ZLIB_LIBRARIES} os)
|
||||||
|
if(GNUTLS_FOUND)
|
||||||
|
set(RDR_LIBRARIES ${RDR_LIBRARIES} ${GNUTLS_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
if(WIN32)
|
||||||
|
set(RDR_LIBRARIES ${RDR_LIBRARIES} ws2_32)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(rdr ${RDR_LIBRARIES})
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
libtool_create_control_file(rdr)
|
||||||
|
endif()
|
99
common/rdr/Exception.cxx
Normal file
99
common/rdr/Exception.cxx
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat Inc.
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
#include <rdr/TLSException.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
Exception::Exception(const char *format, ...) {
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
(void) vsnprintf(str_, len, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemException::SystemException(const char* s, int err_)
|
||||||
|
: Exception("%s", s), err(err_)
|
||||||
|
{
|
||||||
|
strncat(str_, ": ", len-1-strlen(str_));
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Windows error messages are crap, so use unix ones for common errors.
|
||||||
|
const char* msg = 0;
|
||||||
|
switch (err) {
|
||||||
|
case WSAECONNREFUSED: msg = "Connection refused"; break;
|
||||||
|
case WSAETIMEDOUT: msg = "Connection timed out"; break;
|
||||||
|
case WSAECONNRESET: msg = "Connection reset by peer"; break;
|
||||||
|
case WSAECONNABORTED: msg = "Connection aborted"; break;
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
strncat(str_, msg, len-1-strlen(str_));
|
||||||
|
} else {
|
||||||
|
#ifdef UNICODE
|
||||||
|
WCHAR* tmsg = new WCHAR[len-strlen(str_)];
|
||||||
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
0, err, 0, tmsg, len-1-strlen(str_), 0);
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, tmsg, wcslen(tmsg)+1,
|
||||||
|
str_+strlen(str_), len-strlen(str_), 0, 0);
|
||||||
|
delete [] tmsg;
|
||||||
|
#else
|
||||||
|
char* currStr = str_+strlen(str_);
|
||||||
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
0, err, 0, currStr, len-1-strlen(str_), 0);
|
||||||
|
#endif
|
||||||
|
int l = strlen(str_);
|
||||||
|
if ((l >= 2) && (str_[l-2] == '\r') && (str_[l-1] == '\n'))
|
||||||
|
str_[l-2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
strncat(str_, strerror(err), len-1-strlen(str_));
|
||||||
|
#endif
|
||||||
|
strncat(str_, " (", len-1-strlen(str_));
|
||||||
|
char buf[20];
|
||||||
|
#ifdef WIN32
|
||||||
|
if (err < 0)
|
||||||
|
sprintf(buf, "%x", err);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
sprintf(buf,"%d",err);
|
||||||
|
strncat(str_, buf, len-1-strlen(str_));
|
||||||
|
strncat(str_, ")", len-1-strlen(str_));
|
||||||
|
}
|
||||||
|
|
55
common/rdr/Exception.h
Normal file
55
common/rdr/Exception.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat Inc.
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 __RDR_EXCEPTION_H__
|
||||||
|
#define __RDR_EXCEPTION_H__
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define __printf_attr(a, b) __attribute__((__format__ (__printf__, a, b)))
|
||||||
|
#else
|
||||||
|
# define __printf_attr(a, b)
|
||||||
|
#endif // __GNUC__
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
struct Exception {
|
||||||
|
enum { len = 256 };
|
||||||
|
char str_[len];
|
||||||
|
Exception(const char *format = 0, ...) __printf_attr(2, 3);
|
||||||
|
virtual ~Exception() {}
|
||||||
|
virtual const char* str() const { return str_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SystemException : public Exception {
|
||||||
|
int err;
|
||||||
|
SystemException(const char* s, int err_);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimedOut : public Exception {
|
||||||
|
TimedOut() : Exception("Timed out") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EndOfStream : public Exception {
|
||||||
|
EndOfStream() : Exception("End of stream") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
260
common/rdr/FdInStream.cxx
Normal file
260
common/rdr/FdInStream.cxx
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#define close closesocket
|
||||||
|
#undef errno
|
||||||
|
#define errno WSAGetLastError()
|
||||||
|
#include <os/winerrno.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef vncmin
|
||||||
|
#define vncmin(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef vncmax
|
||||||
|
#define vncmax(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Old systems have select() in sys/time.h */
|
||||||
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
|
#include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rdr/FdInStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
enum { DEFAULT_BUF_SIZE = 8192,
|
||||||
|
MIN_BULK_SIZE = 1024 };
|
||||||
|
|
||||||
|
FdInStream::FdInStream(int fd_, int timeoutms_, int bufSize_,
|
||||||
|
bool closeWhenDone_)
|
||||||
|
: fd(fd_), closeWhenDone(closeWhenDone_),
|
||||||
|
timeoutms(timeoutms_), blockCallback(0),
|
||||||
|
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
||||||
|
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
ptr = end = start = new U8[bufSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_,
|
||||||
|
int bufSize_)
|
||||||
|
: fd(fd_), timeoutms(0), blockCallback(blockCallback_),
|
||||||
|
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
||||||
|
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
ptr = end = start = new U8[bufSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
FdInStream::~FdInStream()
|
||||||
|
{
|
||||||
|
delete [] start;
|
||||||
|
if (closeWhenDone) close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FdInStream::setTimeout(int timeoutms_) {
|
||||||
|
timeoutms = timeoutms_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FdInStream::setBlockCallback(FdInStreamBlockCallback* blockCallback_)
|
||||||
|
{
|
||||||
|
blockCallback = blockCallback_;
|
||||||
|
timeoutms = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FdInStream::pos()
|
||||||
|
{
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FdInStream::readBytes(void* data, int length)
|
||||||
|
{
|
||||||
|
if (length < MIN_BULK_SIZE) {
|
||||||
|
InStream::readBytes(data, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
U8* dataPtr = (U8*)data;
|
||||||
|
|
||||||
|
int n = end - ptr;
|
||||||
|
if (n > length) n = length;
|
||||||
|
|
||||||
|
memcpy(dataPtr, ptr, n);
|
||||||
|
dataPtr += n;
|
||||||
|
length -= n;
|
||||||
|
ptr += n;
|
||||||
|
|
||||||
|
while (length > 0) {
|
||||||
|
n = readWithTimeoutOrCallback(dataPtr, length);
|
||||||
|
dataPtr += n;
|
||||||
|
length -= n;
|
||||||
|
offset += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int FdInStream::overrun(int itemSize, int nItems, bool wait)
|
||||||
|
{
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("FdInStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
if (end - ptr != 0)
|
||||||
|
memmove(start, ptr, end - ptr);
|
||||||
|
|
||||||
|
offset += ptr - start;
|
||||||
|
end -= ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
|
||||||
|
int bytes_to_read;
|
||||||
|
while (end < start + itemSize) {
|
||||||
|
bytes_to_read = start + bufSize - end;
|
||||||
|
if (!timing) {
|
||||||
|
// When not timing, we must be careful not to read too much
|
||||||
|
// extra data into the buffer. Otherwise, the line speed
|
||||||
|
// estimation might stay at zero for a long time: All reads
|
||||||
|
// during timing=1 can be satisfied without calling
|
||||||
|
// readWithTimeoutOrCallback. However, reading only 1 or 2 bytes
|
||||||
|
// bytes is ineffecient.
|
||||||
|
bytes_to_read = vncmin(bytes_to_read, vncmax(itemSize*nItems, 8));
|
||||||
|
}
|
||||||
|
int n = readWithTimeoutOrCallback((U8*)end, bytes_to_read, wait);
|
||||||
|
if (n == 0) return 0;
|
||||||
|
end += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// readWithTimeoutOrCallback() reads up to the given length in bytes from the
|
||||||
|
// file descriptor into a buffer. If the wait argument is false, then zero is
|
||||||
|
// returned if no bytes can be read without blocking. Otherwise if a
|
||||||
|
// blockCallback is set, it will be called (repeatedly) instead of blocking.
|
||||||
|
// If alternatively there is a timeout set and that timeout expires, it throws
|
||||||
|
// a TimedOut exception. Otherwise it returns the number of bytes read. It
|
||||||
|
// never attempts to recv() unless select() indicates that the fd is readable -
|
||||||
|
// this means it can be used on an fd which has been set non-blocking. It also
|
||||||
|
// has to cope with the annoying possibility of both select() and recv()
|
||||||
|
// returning EINTR.
|
||||||
|
//
|
||||||
|
|
||||||
|
int FdInStream::readWithTimeoutOrCallback(void* buf, int len, bool wait)
|
||||||
|
{
|
||||||
|
struct timeval before, after;
|
||||||
|
if (timing)
|
||||||
|
gettimeofday(&before, 0);
|
||||||
|
|
||||||
|
int n;
|
||||||
|
while (true) {
|
||||||
|
do {
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timeval* tvp = &tv;
|
||||||
|
|
||||||
|
if (!wait) {
|
||||||
|
tv.tv_sec = tv.tv_usec = 0;
|
||||||
|
} else if (timeoutms != -1) {
|
||||||
|
tv.tv_sec = timeoutms / 1000;
|
||||||
|
tv.tv_usec = (timeoutms % 1000) * 1000;
|
||||||
|
} else {
|
||||||
|
tvp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fd, &fds);
|
||||||
|
n = select(fd+1, &fds, 0, 0, tvp);
|
||||||
|
} while (n < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (n > 0) break;
|
||||||
|
if (n < 0) throw SystemException("select",errno);
|
||||||
|
if (!wait) return 0;
|
||||||
|
if (!blockCallback) throw TimedOut();
|
||||||
|
|
||||||
|
blockCallback->blockCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
n = ::recv(fd, (char*)buf, len, 0);
|
||||||
|
} while (n < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (n < 0) throw SystemException("read",errno);
|
||||||
|
if (n == 0) throw EndOfStream();
|
||||||
|
|
||||||
|
if (timing) {
|
||||||
|
gettimeofday(&after, 0);
|
||||||
|
int newTimeWaited = ((after.tv_sec - before.tv_sec) * 10000 +
|
||||||
|
(after.tv_usec - before.tv_usec) / 100);
|
||||||
|
int newKbits = n * 8 / 1000;
|
||||||
|
|
||||||
|
// limit rate to between 10kbit/s and 40Mbit/s
|
||||||
|
|
||||||
|
if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
|
||||||
|
if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4;
|
||||||
|
|
||||||
|
timeWaitedIn100us += newTimeWaited;
|
||||||
|
timedKbits += newKbits;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FdInStream::startTiming()
|
||||||
|
{
|
||||||
|
timing = true;
|
||||||
|
|
||||||
|
// Carry over up to 1s worth of previous rate for smoothing.
|
||||||
|
|
||||||
|
if (timeWaitedIn100us > 10000) {
|
||||||
|
timedKbits = timedKbits * 10000 / timeWaitedIn100us;
|
||||||
|
timeWaitedIn100us = 10000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FdInStream::stopTiming()
|
||||||
|
{
|
||||||
|
timing = false;
|
||||||
|
if (timeWaitedIn100us < timedKbits/2)
|
||||||
|
timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FdInStream::kbitsPerSecond()
|
||||||
|
{
|
||||||
|
// The following calculation will overflow 32-bit arithmetic if we have
|
||||||
|
// received more than about 50Mbytes (400Mbits) since we started timing, so
|
||||||
|
// it should be OK for a single RFB update.
|
||||||
|
|
||||||
|
return timedKbits * 10000 / timeWaitedIn100us;
|
||||||
|
}
|
78
common/rdr/FdInStream.h
Normal file
78
common/rdr/FdInStream.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// FdInStream streams from a file descriptor.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_FDINSTREAM_H__
|
||||||
|
#define __RDR_FDINSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class FdInStreamBlockCallback {
|
||||||
|
public:
|
||||||
|
virtual void blockCallback() = 0;
|
||||||
|
virtual ~FdInStreamBlockCallback() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FdInStream : public InStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FdInStream(int fd, int timeoutms=-1, int bufSize=0,
|
||||||
|
bool closeWhenDone_=false);
|
||||||
|
FdInStream(int fd, FdInStreamBlockCallback* blockCallback, int bufSize=0);
|
||||||
|
virtual ~FdInStream();
|
||||||
|
|
||||||
|
void setTimeout(int timeoutms);
|
||||||
|
void setBlockCallback(FdInStreamBlockCallback* blockCallback);
|
||||||
|
int getFd() { return fd; }
|
||||||
|
int pos();
|
||||||
|
void readBytes(void* data, int length);
|
||||||
|
|
||||||
|
void startTiming();
|
||||||
|
void stopTiming();
|
||||||
|
unsigned int kbitsPerSecond();
|
||||||
|
unsigned int timeWaited() { return timeWaitedIn100us; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int overrun(int itemSize, int nItems, bool wait);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int readWithTimeoutOrCallback(void* buf, int len, bool wait=true);
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
bool closeWhenDone;
|
||||||
|
int timeoutms;
|
||||||
|
FdInStreamBlockCallback* blockCallback;
|
||||||
|
|
||||||
|
bool timing;
|
||||||
|
unsigned int timeWaitedIn100us;
|
||||||
|
unsigned int timedKbits;
|
||||||
|
|
||||||
|
int bufSize;
|
||||||
|
int offset;
|
||||||
|
U8* start;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
213
common/rdr/FdOutStream.cxx
Normal file
213
common/rdr/FdOutStream.cxx
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2011 Pierre Ossman for Cendio AB
|
||||||
|
* Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#undef errno
|
||||||
|
#define errno WSAGetLastError()
|
||||||
|
#include <os/winerrno.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Old systems have select() in sys/time.h */
|
||||||
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
|
#include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rdr/FdOutStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
#include <rfb/util.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||||
|
|
||||||
|
FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_, int bufSize_)
|
||||||
|
: fd(fd_), blocking(blocking_), timeoutms(timeoutms_),
|
||||||
|
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
ptr = start = sentUpTo = new U8[bufSize];
|
||||||
|
end = start + bufSize;
|
||||||
|
|
||||||
|
gettimeofday(&lastWrite, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
FdOutStream::~FdOutStream()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
blocking = true;
|
||||||
|
flush();
|
||||||
|
} catch (Exception&) {
|
||||||
|
}
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FdOutStream::setTimeout(int timeoutms_) {
|
||||||
|
timeoutms = timeoutms_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FdOutStream::setBlocking(bool blocking_) {
|
||||||
|
blocking = blocking_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FdOutStream::length()
|
||||||
|
{
|
||||||
|
return offset + ptr - sentUpTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FdOutStream::bufferUsage()
|
||||||
|
{
|
||||||
|
return ptr - sentUpTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned FdOutStream::getIdleTime()
|
||||||
|
{
|
||||||
|
return rfb::msSince(&lastWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FdOutStream::flush()
|
||||||
|
{
|
||||||
|
while (sentUpTo < ptr) {
|
||||||
|
int n = writeWithTimeout((const void*) sentUpTo,
|
||||||
|
ptr - sentUpTo,
|
||||||
|
blocking? timeoutms : 0);
|
||||||
|
|
||||||
|
// Timeout?
|
||||||
|
if (n == 0) {
|
||||||
|
// If non-blocking then we're done here
|
||||||
|
if (!blocking)
|
||||||
|
break;
|
||||||
|
|
||||||
|
throw TimedOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
sentUpTo += n;
|
||||||
|
offset += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Managed to flush everything?
|
||||||
|
if (sentUpTo == ptr)
|
||||||
|
ptr = sentUpTo = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int FdOutStream::overrun(int itemSize, int nItems)
|
||||||
|
{
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("FdOutStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
// First try to get rid of the data we have
|
||||||
|
flush();
|
||||||
|
|
||||||
|
// Still not enough space?
|
||||||
|
if (itemSize > end - ptr) {
|
||||||
|
// Can we shuffle things around?
|
||||||
|
// (don't do this if it gains us less than 25%)
|
||||||
|
if ((sentUpTo - start > bufSize / 4) &&
|
||||||
|
(itemSize < bufSize - (ptr - sentUpTo))) {
|
||||||
|
memmove(start, sentUpTo, ptr - sentUpTo);
|
||||||
|
ptr = start + (ptr - sentUpTo);
|
||||||
|
sentUpTo = start;
|
||||||
|
} else {
|
||||||
|
// Have to get rid of more data, so turn off non-blocking
|
||||||
|
// for a bit...
|
||||||
|
bool realBlocking;
|
||||||
|
|
||||||
|
realBlocking = blocking;
|
||||||
|
blocking = true;
|
||||||
|
flush();
|
||||||
|
blocking = realBlocking;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we fit all the items asked for?
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// writeWithTimeout() writes up to the given length in bytes from the given
|
||||||
|
// buffer to the file descriptor. If there is a timeout set and that timeout
|
||||||
|
// expires, it throws a TimedOut exception. Otherwise it returns the number of
|
||||||
|
// bytes written. It never attempts to send() unless select() indicates that
|
||||||
|
// the fd is writable - this means it can be used on an fd which has been set
|
||||||
|
// non-blocking. It also has to cope with the annoying possibility of both
|
||||||
|
// select() and send() returning EINTR.
|
||||||
|
//
|
||||||
|
|
||||||
|
int FdOutStream::writeWithTimeout(const void* data, int length, int timeoutms)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
do {
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timeval* tvp = &tv;
|
||||||
|
|
||||||
|
if (timeoutms != -1) {
|
||||||
|
tv.tv_sec = timeoutms / 1000;
|
||||||
|
tv.tv_usec = (timeoutms % 1000) * 1000;
|
||||||
|
} else {
|
||||||
|
tvp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fd, &fds);
|
||||||
|
n = select(fd+1, 0, &fds, 0, tvp);
|
||||||
|
} while (n < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
throw SystemException("select", errno);
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// select only guarantees that you can write SO_SNDLOWAT without
|
||||||
|
// blocking, which is normally 1. Use MSG_DONTWAIT to avoid
|
||||||
|
// blocking, when possible.
|
||||||
|
#ifndef MSG_DONTWAIT
|
||||||
|
n = ::send(fd, (const char*)data, length, 0);
|
||||||
|
#else
|
||||||
|
n = ::send(fd, (const char*)data, length, MSG_DONTWAIT);
|
||||||
|
#endif
|
||||||
|
} while (n < 0 && (errno == EINTR));
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
throw SystemException("write", errno);
|
||||||
|
|
||||||
|
gettimeofday(&lastWrite, NULL);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
66
common/rdr/FdOutStream.h
Normal file
66
common/rdr/FdOutStream.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2011 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// FdOutStream streams to a file descriptor.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_FDOUTSTREAM_H__
|
||||||
|
#define __RDR_FDOUTSTREAM_H__
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class FdOutStream : public OutStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FdOutStream(int fd, bool blocking=true, int timeoutms=-1, int bufSize=0);
|
||||||
|
virtual ~FdOutStream();
|
||||||
|
|
||||||
|
void setTimeout(int timeoutms);
|
||||||
|
void setBlocking(bool blocking);
|
||||||
|
int getFd() { return fd; }
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
int length();
|
||||||
|
|
||||||
|
int bufferUsage();
|
||||||
|
|
||||||
|
unsigned getIdleTime();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int overrun(int itemSize, int nItems);
|
||||||
|
int writeWithTimeout(const void* data, int length, int timeoutms);
|
||||||
|
int fd;
|
||||||
|
bool blocking;
|
||||||
|
int timeoutms;
|
||||||
|
int bufSize;
|
||||||
|
int offset;
|
||||||
|
U8* start;
|
||||||
|
U8* sentUpTo;
|
||||||
|
struct timeval lastWrite;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
87
common/rdr/FileInStream.cxx
Normal file
87
common/rdr/FileInStream.cxx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (C) 2013 D. R. Commander. All Rights Reserved.
|
||||||
|
* Copyright 2015 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 <errno.h>
|
||||||
|
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
#include <rdr/FileInStream.h>
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
FileInStream::FileInStream(const char *fileName)
|
||||||
|
{
|
||||||
|
file = fopen(fileName, "rb");
|
||||||
|
if (!file)
|
||||||
|
throw SystemException("fopen", errno);
|
||||||
|
ptr = end = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInStream::~FileInStream(void) {
|
||||||
|
if (file) {
|
||||||
|
fclose(file);
|
||||||
|
file = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileInStream::reset(void) {
|
||||||
|
if (!file)
|
||||||
|
throw Exception("File is not open");
|
||||||
|
if (fseek(file, 0, SEEK_SET) != 0)
|
||||||
|
throw SystemException("fseek", errno);
|
||||||
|
ptr = end = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FileInStream::pos()
|
||||||
|
{
|
||||||
|
if (!file)
|
||||||
|
throw Exception("File is not open");
|
||||||
|
|
||||||
|
return ftell(file) + ptr - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FileInStream::overrun(int itemSize, int nItems, bool wait)
|
||||||
|
{
|
||||||
|
if (itemSize > (int)sizeof(b))
|
||||||
|
throw Exception("FileInStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
if (end - ptr != 0)
|
||||||
|
memmove(b, ptr, end - ptr);
|
||||||
|
|
||||||
|
end -= ptr - b;
|
||||||
|
ptr = b;
|
||||||
|
|
||||||
|
|
||||||
|
while (end < b + itemSize) {
|
||||||
|
size_t n = fread((U8 *)end, b + sizeof(b) - end, 1, file);
|
||||||
|
if (n == 0) {
|
||||||
|
if (ferror(file))
|
||||||
|
throw SystemException("fread", errno);
|
||||||
|
if (feof(file))
|
||||||
|
throw EndOfStream();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
end += b + sizeof(b) - end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
50
common/rdr/FileInStream.h
Normal file
50
common/rdr/FileInStream.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* Copyright (C) 2013 D. R. Commander. All Rights Reserved.
|
||||||
|
* Copyright 2015 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 __RDR_FILEINSTREAM_H__
|
||||||
|
#define __RDR_FILEINSTREAM_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class FileInStream : public InStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FileInStream(const char *fileName);
|
||||||
|
~FileInStream(void);
|
||||||
|
|
||||||
|
void reset(void);
|
||||||
|
|
||||||
|
int pos();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int overrun(int itemSize, int nItems, bool wait = true);
|
||||||
|
|
||||||
|
private:
|
||||||
|
U8 b[131072];
|
||||||
|
FILE *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
52
common/rdr/FixedMemOutStream.h
Normal file
52
common/rdr/FixedMemOutStream.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// A FixedMemOutStream writes to a buffer of a fixed length.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_FIXEDMEMOUTSTREAM_H__
|
||||||
|
#define __RDR_FIXEDMEMOUTSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class FixedMemOutStream : public OutStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FixedMemOutStream(void* buf, int len) {
|
||||||
|
ptr = start = (U8*)buf;
|
||||||
|
end = start + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length() { return ptr - start; }
|
||||||
|
void reposition(int pos) { ptr = start + pos; }
|
||||||
|
const void* data() { return (const void*)start; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int overrun(int itemSize, int nItems) { throw EndOfStream(); }
|
||||||
|
U8* start;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
117
common/rdr/HexInStream.cxx
Normal file
117
common/rdr/HexInStream.cxx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <rdr/HexInStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
const int DEFAULT_BUF_LEN = 16384;
|
||||||
|
|
||||||
|
static inline int min(int a, int b) {return a<b ? a : b;}
|
||||||
|
|
||||||
|
HexInStream::HexInStream(InStream& is, int bufSize_)
|
||||||
|
: bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_LEN), offset(0), in_stream(is)
|
||||||
|
{
|
||||||
|
ptr = end = start = new U8[bufSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
HexInStream::~HexInStream() {
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool HexInStream::readHexAndShift(char c, int* v) {
|
||||||
|
c=tolower(c);
|
||||||
|
if ((c >= '0') && (c <= '9'))
|
||||||
|
*v = (*v << 4) + (c - '0');
|
||||||
|
else if ((c >= 'a') && (c <= 'f'))
|
||||||
|
*v = (*v << 4) + (c - 'a' + 10);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HexInStream::hexStrToBin(const char* s, char** data, int* length) {
|
||||||
|
int l=strlen(s);
|
||||||
|
if ((l % 2) == 0) {
|
||||||
|
delete [] *data;
|
||||||
|
*data = 0; *length = 0;
|
||||||
|
if (l == 0)
|
||||||
|
return true;
|
||||||
|
*data = new char[l/2];
|
||||||
|
*length = l/2;
|
||||||
|
for(int i=0;i<l;i+=2) {
|
||||||
|
int byte = 0;
|
||||||
|
if (!readHexAndShift(s[i], &byte) ||
|
||||||
|
!readHexAndShift(s[i+1], &byte))
|
||||||
|
goto decodeError;
|
||||||
|
(*data)[i/2] = byte;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
decodeError:
|
||||||
|
delete [] *data;
|
||||||
|
*data = 0;
|
||||||
|
*length = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int HexInStream::pos() {
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HexInStream::overrun(int itemSize, int nItems, bool wait) {
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("HexInStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
if (end - ptr != 0)
|
||||||
|
memmove(start, ptr, end - ptr);
|
||||||
|
|
||||||
|
end -= ptr - start;
|
||||||
|
offset += ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
|
||||||
|
while (end < ptr + itemSize) {
|
||||||
|
int n = in_stream.check(2, 1, wait);
|
||||||
|
if (n == 0) return 0;
|
||||||
|
const U8* iptr = in_stream.getptr();
|
||||||
|
const U8* eptr = in_stream.getend();
|
||||||
|
int length = min((eptr - iptr)/2, start + bufSize - end);
|
||||||
|
|
||||||
|
U8* optr = (U8*) end;
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
int v = 0;
|
||||||
|
readHexAndShift(iptr[i*2], &v);
|
||||||
|
readHexAndShift(iptr[i*2+1], &v);
|
||||||
|
optr[i] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_stream.setptr(iptr + length*2);
|
||||||
|
end += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
50
common/rdr/HexInStream.h
Normal file
50
common/rdr/HexInStream.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 __RDR_HEX_INSTREAM_H__
|
||||||
|
#define __RDR_HEX_INSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class HexInStream : public InStream {
|
||||||
|
public:
|
||||||
|
|
||||||
|
HexInStream(InStream& is, int bufSize=0);
|
||||||
|
virtual ~HexInStream();
|
||||||
|
|
||||||
|
int pos();
|
||||||
|
|
||||||
|
static bool readHexAndShift(char c, int* v);
|
||||||
|
static bool hexStrToBin(const char* s, char** data, int* length);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int overrun(int itemSize, int nItems, bool wait);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int bufSize;
|
||||||
|
U8* start;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
InStream& in_stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
110
common/rdr/HexOutStream.cxx
Normal file
110
common/rdr/HexOutStream.cxx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <rdr/HexOutStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
const int DEFAULT_BUF_LEN = 16384;
|
||||||
|
|
||||||
|
static inline int min(int a, int b) {return a<b ? a : b;}
|
||||||
|
|
||||||
|
HexOutStream::HexOutStream(OutStream& os, int buflen)
|
||||||
|
: out_stream(os), offset(0), bufSize(buflen ? buflen : DEFAULT_BUF_LEN)
|
||||||
|
{
|
||||||
|
if (bufSize % 2)
|
||||||
|
bufSize--;
|
||||||
|
ptr = start = new U8[bufSize];
|
||||||
|
end = start + bufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
HexOutStream::~HexOutStream() {
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char HexOutStream::intToHex(int i) {
|
||||||
|
if ((i>=0) && (i<=9))
|
||||||
|
return '0'+i;
|
||||||
|
else if ((i>=10) && (i<=15))
|
||||||
|
return 'a'+(i-10);
|
||||||
|
else
|
||||||
|
throw rdr::Exception("intToHex failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* HexOutStream::binToHexStr(const char* data, int length) {
|
||||||
|
char* buffer = new char[length*2+1];
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
buffer[i*2] = intToHex((data[i] >> 4) & 15);
|
||||||
|
buffer[i*2+1] = intToHex((data[i] & 15));
|
||||||
|
if (!buffer[i*2] || !buffer[i*2+1]) {
|
||||||
|
delete [] buffer;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer[length*2] = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HexOutStream::writeBuffer() {
|
||||||
|
U8* pos = start;
|
||||||
|
while (pos != ptr) {
|
||||||
|
out_stream.check(2);
|
||||||
|
U8* optr = out_stream.getptr();
|
||||||
|
U8* oend = out_stream.getend();
|
||||||
|
int length = min(ptr-pos, (oend-optr)/2);
|
||||||
|
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
optr[i*2] = intToHex((pos[i] >> 4) & 0xf);
|
||||||
|
optr[i*2+1] = intToHex(pos[i] & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_stream.setptr(optr + length*2);
|
||||||
|
pos += length;
|
||||||
|
}
|
||||||
|
offset += ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HexOutStream::length()
|
||||||
|
{
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HexOutStream::flush() {
|
||||||
|
writeBuffer();
|
||||||
|
out_stream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
HexOutStream::overrun(int itemSize, int nItems) {
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("HexOutStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
writeBuffer();
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
51
common/rdr/HexOutStream.h
Normal file
51
common/rdr/HexOutStream.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 __RDR_HEX_OUTSTREAM_H__
|
||||||
|
#define __RDR_HEX_OUTSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class HexOutStream : public OutStream {
|
||||||
|
public:
|
||||||
|
|
||||||
|
HexOutStream(OutStream& os, int buflen=0);
|
||||||
|
virtual ~HexOutStream();
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
int length();
|
||||||
|
|
||||||
|
static char intToHex(int i);
|
||||||
|
static char* binToHexStr(const char* data, int length);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeBuffer();
|
||||||
|
int overrun(int itemSize, int nItems);
|
||||||
|
|
||||||
|
OutStream& out_stream;
|
||||||
|
|
||||||
|
U8* start;
|
||||||
|
int offset;
|
||||||
|
int bufSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
35
common/rdr/InStream.cxx
Normal file
35
common/rdr/InStream.cxx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <rdr/InStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
U32 InStream::maxStringLength = 65535;
|
||||||
|
|
||||||
|
char* InStream::readString()
|
||||||
|
{
|
||||||
|
U32 len = readU32();
|
||||||
|
if (len > maxStringLength)
|
||||||
|
throw Exception("InStream max string length exceeded");
|
||||||
|
char* str = new char[len+1];
|
||||||
|
readBytes(str, len);
|
||||||
|
str[len] = 0;
|
||||||
|
return str;
|
||||||
|
}
|
147
common/rdr/InStream.h
Normal file
147
common/rdr/InStream.h
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data
|
||||||
|
// Representation).
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_INSTREAM_H__
|
||||||
|
#define __RDR_INSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/types.h>
|
||||||
|
#include <string.h> // for memcpy
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class InStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~InStream() {}
|
||||||
|
|
||||||
|
// check() ensures there is buffer data for at least one item of size
|
||||||
|
// itemSize bytes. Returns the number of items in the buffer (up to a
|
||||||
|
// maximum of nItems). If wait is false, then instead of blocking to wait
|
||||||
|
// for the bytes, zero is returned if the bytes are not immediately
|
||||||
|
// available.
|
||||||
|
|
||||||
|
inline int check(int itemSize, int nItems=1, bool wait=true)
|
||||||
|
{
|
||||||
|
if (ptr + itemSize * nItems > end) {
|
||||||
|
if (ptr + itemSize > end)
|
||||||
|
return overrun(itemSize, nItems, wait);
|
||||||
|
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
}
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkNoWait() tries to make sure that the given number of bytes can
|
||||||
|
// be read without blocking. It returns true if this is the case, false
|
||||||
|
// otherwise. The length must be "small" (less than the buffer size).
|
||||||
|
|
||||||
|
inline bool checkNoWait(int length) { return check(length, 1, false)!=0; }
|
||||||
|
|
||||||
|
// readU/SN() methods read unsigned and signed N-bit integers.
|
||||||
|
|
||||||
|
inline U8 readU8() { check(1); return *ptr++; }
|
||||||
|
inline U16 readU16() { check(2); int b0 = *ptr++; int b1 = *ptr++;
|
||||||
|
return b0 << 8 | b1; }
|
||||||
|
inline U32 readU32() { check(4); int b0 = *ptr++; int b1 = *ptr++;
|
||||||
|
int b2 = *ptr++; int b3 = *ptr++;
|
||||||
|
return b0 << 24 | b1 << 16 | b2 << 8 | b3; }
|
||||||
|
|
||||||
|
inline S8 readS8() { return (S8) readU8(); }
|
||||||
|
inline S16 readS16() { return (S16)readU16(); }
|
||||||
|
inline S32 readS32() { return (S32)readU32(); }
|
||||||
|
|
||||||
|
// readString() reads a string - a U32 length followed by the data.
|
||||||
|
// Returns a null-terminated string - the caller should delete[] it
|
||||||
|
// afterwards.
|
||||||
|
|
||||||
|
char* readString();
|
||||||
|
|
||||||
|
// maxStringLength protects against allocating a huge buffer. Set it
|
||||||
|
// higher if you need longer strings.
|
||||||
|
|
||||||
|
static U32 maxStringLength;
|
||||||
|
|
||||||
|
inline void skip(int bytes) {
|
||||||
|
while (bytes > 0) {
|
||||||
|
int n = check(1, bytes);
|
||||||
|
ptr += n;
|
||||||
|
bytes -= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readBytes() reads an exact number of bytes.
|
||||||
|
|
||||||
|
void readBytes(void* data, int length) {
|
||||||
|
U8* dataPtr = (U8*)data;
|
||||||
|
U8* dataEnd = dataPtr + length;
|
||||||
|
while (dataPtr < dataEnd) {
|
||||||
|
int n = check(1, dataEnd - dataPtr);
|
||||||
|
memcpy(dataPtr, ptr, n);
|
||||||
|
ptr += n;
|
||||||
|
dataPtr += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readOpaqueN() reads a quantity without byte-swapping.
|
||||||
|
|
||||||
|
inline U8 readOpaque8() { return readU8(); }
|
||||||
|
inline U16 readOpaque16() { check(2); U16 r; ((U8*)&r)[0] = *ptr++;
|
||||||
|
((U8*)&r)[1] = *ptr++; return r; }
|
||||||
|
inline U32 readOpaque32() { check(4); U32 r; ((U8*)&r)[0] = *ptr++;
|
||||||
|
((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
|
||||||
|
((U8*)&r)[3] = *ptr++; return r; }
|
||||||
|
|
||||||
|
// pos() returns the position in the stream.
|
||||||
|
|
||||||
|
virtual int pos() = 0;
|
||||||
|
|
||||||
|
// getptr(), getend() and setptr() are "dirty" methods which allow you to
|
||||||
|
// manipulate the buffer directly. This is useful for a stream which is a
|
||||||
|
// wrapper around an underlying stream.
|
||||||
|
|
||||||
|
inline const U8* getptr() const { return ptr; }
|
||||||
|
inline const U8* getend() const { return end; }
|
||||||
|
inline void setptr(const U8* p) { ptr = p; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// overrun() is implemented by a derived class to cope with buffer overrun.
|
||||||
|
// It ensures there are at least itemSize bytes of buffer data. Returns
|
||||||
|
// the number of items in the buffer (up to a maximum of nItems). itemSize
|
||||||
|
// is supposed to be "small" (a few bytes). If wait is false, then
|
||||||
|
// instead of blocking to wait for the bytes, zero is returned if the bytes
|
||||||
|
// are not immediately available.
|
||||||
|
|
||||||
|
virtual int overrun(int itemSize, int nItems, bool wait=true) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
InStream() {}
|
||||||
|
const U8* ptr;
|
||||||
|
const U8* end;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
63
common/rdr/MemInStream.h
Normal file
63
common/rdr/MemInStream.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// rdr::MemInStream is an InStream which streams from a given memory buffer.
|
||||||
|
// If the deleteWhenDone parameter is true then the buffer will be delete[]d in
|
||||||
|
// the destructor. Note that it is delete[]d as a U8* - strictly speaking this
|
||||||
|
// means it ought to be new[]ed as a U8* as well, but on most platforms this
|
||||||
|
// doesn't matter.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_MEMINSTREAM_H__
|
||||||
|
#define __RDR_MEMINSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class MemInStream : public InStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MemInStream(const void* data, int len, bool deleteWhenDone_=false)
|
||||||
|
: start((const U8*)data), deleteWhenDone(deleteWhenDone_)
|
||||||
|
{
|
||||||
|
ptr = start;
|
||||||
|
end = start + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~MemInStream() {
|
||||||
|
if (deleteWhenDone)
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos() { return ptr - start; }
|
||||||
|
void reposition(int pos) { ptr = start + pos; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int overrun(int itemSize, int nItems, bool wait) { throw EndOfStream(); }
|
||||||
|
const U8* start;
|
||||||
|
bool deleteWhenDone;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
83
common/rdr/MemOutStream.h
Normal file
83
common/rdr/MemOutStream.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// A MemOutStream grows as needed when data is written to it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_MEMOUTSTREAM_H__
|
||||||
|
#define __RDR_MEMOUTSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class MemOutStream : public OutStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MemOutStream(int len=1024) {
|
||||||
|
start = ptr = new U8[len];
|
||||||
|
end = start + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~MemOutStream() {
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeBytes(const void* data, int length) {
|
||||||
|
check(length);
|
||||||
|
memcpy(ptr, data, length);
|
||||||
|
ptr += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length() { return ptr - start; }
|
||||||
|
void clear() { ptr = start; };
|
||||||
|
void clearAndZero() { memset(start, 0, ptr-start); clear(); }
|
||||||
|
void reposition(int pos) { ptr = start + pos; }
|
||||||
|
|
||||||
|
// data() returns a pointer to the buffer.
|
||||||
|
|
||||||
|
const void* data() { return (const void*)start; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// overrun() either doubles the buffer or adds enough space for nItems of
|
||||||
|
// size itemSize bytes.
|
||||||
|
|
||||||
|
int overrun(int itemSize, int nItems) {
|
||||||
|
int len = ptr - start + itemSize * nItems;
|
||||||
|
if (len < (end - start) * 2)
|
||||||
|
len = (end - start) * 2;
|
||||||
|
|
||||||
|
U8* newStart = new U8[len];
|
||||||
|
memcpy(newStart, start, ptr - start);
|
||||||
|
ptr = newStart + (ptr - start);
|
||||||
|
delete [] start;
|
||||||
|
start = newStart;
|
||||||
|
end = newStart + len;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
U8* start;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
158
common/rdr/OutStream.h
Normal file
158
common/rdr/OutStream.h
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// rdr::OutStream marshalls data into a buffer stored in RDR (RFB Data
|
||||||
|
// Representation).
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_OUTSTREAM_H__
|
||||||
|
#define __RDR_OUTSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/types.h>
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <string.h> // for memcpy
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class OutStream {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
OutStream() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~OutStream() {}
|
||||||
|
|
||||||
|
// check() ensures there is buffer space for at least one item of size
|
||||||
|
// itemSize bytes. Returns the number of items which fit (up to a maximum
|
||||||
|
// of nItems).
|
||||||
|
|
||||||
|
inline int check(int itemSize, int nItems=1)
|
||||||
|
{
|
||||||
|
if (ptr + itemSize * nItems > end) {
|
||||||
|
if (ptr + itemSize > end)
|
||||||
|
return overrun(itemSize, nItems);
|
||||||
|
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
}
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeU/SN() methods write unsigned and signed N-bit integers.
|
||||||
|
|
||||||
|
inline void writeU8( U8 u) { check(1); *ptr++ = u; }
|
||||||
|
inline void writeU16(U16 u) { check(2); *ptr++ = u >> 8; *ptr++ = (U8)u; }
|
||||||
|
inline void writeU32(U32 u) { check(4); *ptr++ = u >> 24; *ptr++ = u >> 16;
|
||||||
|
*ptr++ = u >> 8; *ptr++ = u; }
|
||||||
|
|
||||||
|
inline void writeS8( S8 s) { writeU8((U8)s); }
|
||||||
|
inline void writeS16(S16 s) { writeU16((U16)s); }
|
||||||
|
inline void writeS32(S32 s) { writeU32((U32)s); }
|
||||||
|
|
||||||
|
// writeString() writes a string - a U32 length followed by the data. The
|
||||||
|
// given string should be null-terminated (but the terminating null is not
|
||||||
|
// written to the stream).
|
||||||
|
|
||||||
|
inline void writeString(const char* str) {
|
||||||
|
U32 len = strlen(str);
|
||||||
|
writeU32(len);
|
||||||
|
writeBytes(str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void pad(int bytes) {
|
||||||
|
while (bytes-- > 0) writeU8(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void skip(int bytes) {
|
||||||
|
while (bytes > 0) {
|
||||||
|
int n = check(1, bytes);
|
||||||
|
ptr += n;
|
||||||
|
bytes -= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeBytes() writes an exact number of bytes.
|
||||||
|
|
||||||
|
void writeBytes(const void* data, int length) {
|
||||||
|
const U8* dataPtr = (const U8*)data;
|
||||||
|
const U8* dataEnd = dataPtr + length;
|
||||||
|
while (dataPtr < dataEnd) {
|
||||||
|
int n = check(1, dataEnd - dataPtr);
|
||||||
|
memcpy(ptr, dataPtr, n);
|
||||||
|
ptr += n;
|
||||||
|
dataPtr += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copyBytes() efficiently transfers data between streams
|
||||||
|
|
||||||
|
void copyBytes(InStream* is, int length) {
|
||||||
|
while (length > 0) {
|
||||||
|
int n = check(1, length);
|
||||||
|
is->readBytes(ptr, n);
|
||||||
|
ptr += n;
|
||||||
|
length -= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeOpaqueN() writes a quantity without byte-swapping.
|
||||||
|
|
||||||
|
inline void writeOpaque8( U8 u) { writeU8(u); }
|
||||||
|
inline void writeOpaque16(U16 u) { check(2); *ptr++ = ((U8*)&u)[0];
|
||||||
|
*ptr++ = ((U8*)&u)[1]; }
|
||||||
|
inline void writeOpaque32(U32 u) { check(4); *ptr++ = ((U8*)&u)[0];
|
||||||
|
*ptr++ = ((U8*)&u)[1];
|
||||||
|
*ptr++ = ((U8*)&u)[2];
|
||||||
|
*ptr++ = ((U8*)&u)[3]; }
|
||||||
|
|
||||||
|
// length() returns the length of the stream.
|
||||||
|
|
||||||
|
virtual int length() = 0;
|
||||||
|
|
||||||
|
// flush() requests that the stream be flushed.
|
||||||
|
|
||||||
|
virtual void flush() {}
|
||||||
|
|
||||||
|
// getptr(), getend() and setptr() are "dirty" methods which allow you to
|
||||||
|
// manipulate the buffer directly. This is useful for a stream which is a
|
||||||
|
// wrapper around an underlying stream.
|
||||||
|
|
||||||
|
inline U8* getptr() { return ptr; }
|
||||||
|
inline U8* getend() { return end; }
|
||||||
|
inline void setptr(U8* p) { ptr = p; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// overrun() is implemented by a derived class to cope with buffer overrun.
|
||||||
|
// It ensures there are at least itemSize bytes of buffer space. Returns
|
||||||
|
// the number of items which fit (up to a maximum of nItems). itemSize is
|
||||||
|
// supposed to be "small" (a few bytes).
|
||||||
|
|
||||||
|
virtual int overrun(int itemSize, int nItems) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
U8* ptr;
|
||||||
|
U8* end;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
130
common/rdr/RandomStream.cxx
Normal file
130
common/rdr/RandomStream.cxx
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <rdr/RandomStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#else
|
||||||
|
#define getpid() GetCurrentProcessId()
|
||||||
|
#ifndef RFB_HAVE_WINCRYPT
|
||||||
|
#pragma message(" NOTE: Not building WinCrypt-based RandomStream")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
const int DEFAULT_BUF_LEN = 256;
|
||||||
|
|
||||||
|
unsigned int RandomStream::seed;
|
||||||
|
|
||||||
|
RandomStream::RandomStream()
|
||||||
|
: offset(0)
|
||||||
|
{
|
||||||
|
ptr = end = start = new U8[DEFAULT_BUF_LEN];
|
||||||
|
|
||||||
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
|
provider = 0;
|
||||||
|
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) {
|
||||||
|
if (GetLastError() == (DWORD)NTE_BAD_KEYSET) {
|
||||||
|
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
|
||||||
|
fprintf(stderr, "RandomStream: unable to create keyset\n");
|
||||||
|
provider = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "RandomStream: unable to acquire context\n");
|
||||||
|
provider = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!provider) {
|
||||||
|
#else
|
||||||
|
#ifndef WIN32
|
||||||
|
fp = fopen("/dev/urandom", "r");
|
||||||
|
if (!fp)
|
||||||
|
fp = fopen("/dev/random", "r");
|
||||||
|
if (!fp) {
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
fprintf(stderr,"RandomStream: warning: no OS supplied random source - using rand()\n");
|
||||||
|
seed += (unsigned int) time(0) + getpid() + getpid() * 987654 + rand();
|
||||||
|
srand(seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomStream::~RandomStream() {
|
||||||
|
delete [] start;
|
||||||
|
|
||||||
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
|
if (provider)
|
||||||
|
CryptReleaseContext(provider, 0);
|
||||||
|
#endif
|
||||||
|
#ifndef WIN32
|
||||||
|
if (fp) fclose(fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int RandomStream::pos() {
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RandomStream::overrun(int itemSize, int nItems, bool wait) {
|
||||||
|
if (itemSize > DEFAULT_BUF_LEN)
|
||||||
|
throw Exception("RandomStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
if (end - ptr != 0)
|
||||||
|
memmove(start, ptr, end - ptr);
|
||||||
|
|
||||||
|
end -= ptr - start;
|
||||||
|
offset += ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
|
||||||
|
int length = start + DEFAULT_BUF_LEN - end;
|
||||||
|
|
||||||
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
|
if (provider) {
|
||||||
|
if (!CryptGenRandom(provider, length, (U8*)end))
|
||||||
|
throw rdr::SystemException("unable to CryptGenRandom", GetLastError());
|
||||||
|
end += length;
|
||||||
|
} else {
|
||||||
|
#else
|
||||||
|
#ifndef WIN32
|
||||||
|
if (fp) {
|
||||||
|
int n = fread((U8*)end, length, 1, fp);
|
||||||
|
if (n != 1)
|
||||||
|
throw rdr::SystemException("reading /dev/urandom or /dev/random failed",
|
||||||
|
errno);
|
||||||
|
end += length;
|
||||||
|
} else {
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
for (int i=0; i<length; i++)
|
||||||
|
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
63
common/rdr/RandomStream.h
Normal file
63
common/rdr/RandomStream.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 __RDR_RANDOMSTREAM_H__
|
||||||
|
#define __RDR_RANDOMSTREAM_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wincrypt.h>
|
||||||
|
#ifdef WINCRYPT32API
|
||||||
|
#define RFB_HAVE_WINCRYPT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class RandomStream : public InStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
RandomStream();
|
||||||
|
virtual ~RandomStream();
|
||||||
|
|
||||||
|
int pos();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int overrun(int itemSize, int nItems, bool wait);
|
||||||
|
|
||||||
|
private:
|
||||||
|
U8* start;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
static unsigned int seed;
|
||||||
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
|
HCRYPTPROV provider;
|
||||||
|
#endif
|
||||||
|
#ifndef WIN32
|
||||||
|
FILE* fp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
102
common/rdr/SubstitutingInStream.h
Normal file
102
common/rdr/SubstitutingInStream.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 __RDR_SUBSTITUTINGINSTREAM_H__
|
||||||
|
#define __RDR_SUBSTITUTINGINSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class Substitutor {
|
||||||
|
public:
|
||||||
|
virtual char* substitute(const char* varName) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SubstitutingInStream : public InStream {
|
||||||
|
public:
|
||||||
|
SubstitutingInStream(InStream* underlying_, Substitutor* s,
|
||||||
|
int maxVarNameLen_)
|
||||||
|
: underlying(underlying_), dollar(0), substitutor(s), subst(0),
|
||||||
|
maxVarNameLen(maxVarNameLen_)
|
||||||
|
{
|
||||||
|
ptr = end = underlying->getptr();
|
||||||
|
varName = new char[maxVarNameLen+1];
|
||||||
|
}
|
||||||
|
~SubstitutingInStream() {
|
||||||
|
delete underlying;
|
||||||
|
delete [] varName;
|
||||||
|
delete [] subst;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos() { return underlying->pos(); }
|
||||||
|
|
||||||
|
virtual int overrun(int itemSize, int nItems, bool wait=true) {
|
||||||
|
if (itemSize != 1)
|
||||||
|
throw new rdr::Exception("SubstitutingInStream: itemSize must be 1");
|
||||||
|
|
||||||
|
if (subst) {
|
||||||
|
delete [] subst;
|
||||||
|
subst = 0;
|
||||||
|
} else {
|
||||||
|
underlying->setptr(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
underlying->check(1);
|
||||||
|
ptr = underlying->getptr();
|
||||||
|
end = underlying->getend();
|
||||||
|
dollar = (const U8*)memchr(ptr, '$', end-ptr);
|
||||||
|
if (dollar) {
|
||||||
|
if (dollar == ptr) {
|
||||||
|
try {
|
||||||
|
int i = 0;
|
||||||
|
while (i < maxVarNameLen) {
|
||||||
|
varName[i++] = underlying->readS8();
|
||||||
|
varName[i] = 0;
|
||||||
|
subst = substitutor->substitute(varName);
|
||||||
|
if (subst) {
|
||||||
|
ptr = (U8*)subst;
|
||||||
|
end = (U8*)subst + strlen(subst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (EndOfStream&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subst)
|
||||||
|
dollar = (const U8*)memchr(ptr+1, '$', end-ptr-1);
|
||||||
|
}
|
||||||
|
if (!subst && dollar) end = dollar;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
InStream* underlying;
|
||||||
|
const U8* dollar;
|
||||||
|
Substitutor* substitutor;
|
||||||
|
char* varName;
|
||||||
|
char* subst;
|
||||||
|
int maxVarNameLen;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
41
common/rdr/TLSException.cxx
Normal file
41
common/rdr/TLSException.cxx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Red Hat Inc.
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 <rdr/TLSException.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
TLSException::TLSException(const char* s, int err_)
|
||||||
|
: Exception("%s: %s (%d)", s, gnutls_strerror(err_), err_), err(err_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* HAVE_GNUTLS */
|
||||||
|
|
35
common/rdr/TLSException.h
Normal file
35
common/rdr/TLSException.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Red Hat Inc.
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 __RDR_TLSEXCEPTION_H__
|
||||||
|
#define __RDR_TLSEXCEPTION_H__
|
||||||
|
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
struct TLSException : public Exception {
|
||||||
|
int err;
|
||||||
|
TLSException(const char* s, int err_);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
125
common/rdr/TLSInStream.cxx
Normal file
125
common/rdr/TLSInStream.cxx
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 <rdr/Exception.h>
|
||||||
|
#include <rdr/TLSException.h>
|
||||||
|
#include <rdr/TLSInStream.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||||
|
|
||||||
|
ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
|
||||||
|
{
|
||||||
|
TLSInStream* self= (TLSInStream*) str;
|
||||||
|
InStream *in = self->in;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!in->check(1, 1, false)) {
|
||||||
|
gnutls_transport_set_errno(self->session, EAGAIN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in->getend() - in->getptr() < (ptrdiff_t)size)
|
||||||
|
size = in->getend() - in->getptr();
|
||||||
|
|
||||||
|
in->readBytes(data, size);
|
||||||
|
|
||||||
|
} catch (Exception& e) {
|
||||||
|
gnutls_transport_set_errno(self->session, EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
|
||||||
|
: session(_session), in(_in), bufSize(DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
gnutls_transport_ptr_t recv, send;
|
||||||
|
|
||||||
|
ptr = end = start = new U8[bufSize];
|
||||||
|
|
||||||
|
gnutls_transport_set_pull_function(session, pull);
|
||||||
|
gnutls_transport_get_ptr2(session, &recv, &send);
|
||||||
|
gnutls_transport_set_ptr2(session, this, send);
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSInStream::~TLSInStream()
|
||||||
|
{
|
||||||
|
gnutls_transport_set_pull_function(session, NULL);
|
||||||
|
|
||||||
|
delete[] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TLSInStream::pos()
|
||||||
|
{
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TLSInStream::overrun(int itemSize, int nItems, bool wait)
|
||||||
|
{
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("TLSInStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
if (end - ptr != 0)
|
||||||
|
memmove(start, ptr, end - ptr);
|
||||||
|
|
||||||
|
offset += ptr - start;
|
||||||
|
end -= ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
|
||||||
|
while (end < start + itemSize) {
|
||||||
|
int n = readTLS((U8*) end, start + bufSize - end, wait);
|
||||||
|
if (!wait && n == 0)
|
||||||
|
return 0;
|
||||||
|
end += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TLSInStream::readTLS(U8* buf, int len, bool wait)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = in->check(1, 1, wait);
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
n = gnutls_record_recv(session, (void *) buf, len);
|
||||||
|
if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (n < 0) throw TLSException("readTLS", n);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
55
common/rdr/TLSInStream.h
Normal file
55
common/rdr/TLSInStream.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 __RDR_TLSINSTREAM_H__
|
||||||
|
#define __RDR_TLSINSTREAM_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class TLSInStream : public InStream {
|
||||||
|
public:
|
||||||
|
TLSInStream(InStream* in, gnutls_session_t session);
|
||||||
|
virtual ~TLSInStream();
|
||||||
|
|
||||||
|
int pos();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int overrun(int itemSize, int nItems, bool wait);
|
||||||
|
int readTLS(U8* buf, int len, bool wait);
|
||||||
|
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);
|
||||||
|
|
||||||
|
gnutls_session_t session;
|
||||||
|
InStream* in;
|
||||||
|
int bufSize;
|
||||||
|
int offset;
|
||||||
|
U8* start;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
123
common/rdr/TLSOutStream.cxx
Normal file
123
common/rdr/TLSOutStream.cxx
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 <rdr/Exception.h>
|
||||||
|
#include <rdr/TLSException.h>
|
||||||
|
#include <rdr/TLSOutStream.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||||
|
|
||||||
|
ssize_t TLSOutStream::push(gnutls_transport_ptr_t str, const void* data,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
TLSOutStream* self= (TLSOutStream*) str;
|
||||||
|
OutStream *out = self->out;
|
||||||
|
|
||||||
|
try {
|
||||||
|
out->writeBytes(data, size);
|
||||||
|
out->flush();
|
||||||
|
} catch (Exception& e) {
|
||||||
|
gnutls_transport_set_errno(self->session, EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSOutStream::TLSOutStream(OutStream* _out, gnutls_session_t _session)
|
||||||
|
: session(_session), out(_out), bufSize(DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
gnutls_transport_ptr_t recv, send;
|
||||||
|
|
||||||
|
ptr = start = new U8[bufSize];
|
||||||
|
end = start + bufSize;
|
||||||
|
|
||||||
|
gnutls_transport_set_push_function(session, push);
|
||||||
|
gnutls_transport_get_ptr2(session, &recv, &send);
|
||||||
|
gnutls_transport_set_ptr2(session, recv, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSOutStream::~TLSOutStream()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
try {
|
||||||
|
// flush();
|
||||||
|
} catch (Exception&) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
gnutls_transport_set_push_function(session, NULL);
|
||||||
|
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TLSOutStream::length()
|
||||||
|
{
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TLSOutStream::flush()
|
||||||
|
{
|
||||||
|
U8* sentUpTo = start;
|
||||||
|
while (sentUpTo < ptr) {
|
||||||
|
int n = writeTLS(sentUpTo, ptr - sentUpTo);
|
||||||
|
sentUpTo += n;
|
||||||
|
offset += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = start;
|
||||||
|
out->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TLSOutStream::overrun(int itemSize, int nItems)
|
||||||
|
{
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("TLSOutStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
flush();
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TLSOutStream::writeTLS(const U8* data, int length)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = gnutls_record_send(session, data, length);
|
||||||
|
if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
throw TLSException("writeTLS", n);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
57
common/rdr/TLSOutStream.h
Normal file
57
common/rdr/TLSOutStream.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 __RDR_TLSOUTSTREAM_H__
|
||||||
|
#define __RDR_TLSOUTSTREAM_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class TLSOutStream : public OutStream {
|
||||||
|
public:
|
||||||
|
TLSOutStream(OutStream* out, gnutls_session_t session);
|
||||||
|
virtual ~TLSOutStream();
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
int length();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int overrun(int itemSize, int nItems);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int writeTLS(const U8* data, int length);
|
||||||
|
static ssize_t push(gnutls_transport_ptr_t str, const void* data, size_t size);
|
||||||
|
|
||||||
|
gnutls_session_t session;
|
||||||
|
OutStream* out;
|
||||||
|
int bufSize;
|
||||||
|
U8* start;
|
||||||
|
int offset;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
149
common/rdr/ZlibInStream.cxx
Normal file
149
common/rdr/ZlibInStream.cxx
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <assert.h>
|
||||||
|
|
||||||
|
#include <rdr/ZlibInStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||||
|
|
||||||
|
ZlibInStream::ZlibInStream(int bufSize_)
|
||||||
|
: underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0),
|
||||||
|
zs(NULL), bytesIn(0)
|
||||||
|
{
|
||||||
|
ptr = end = start = new U8[bufSize];
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ZlibInStream::~ZlibInStream()
|
||||||
|
{
|
||||||
|
deinit();
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibInStream::setUnderlying(InStream* is, int bytesIn_)
|
||||||
|
{
|
||||||
|
underlying = is;
|
||||||
|
bytesIn = bytesIn_;
|
||||||
|
ptr = end = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZlibInStream::pos()
|
||||||
|
{
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibInStream::removeUnderlying()
|
||||||
|
{
|
||||||
|
ptr = end = start;
|
||||||
|
if (!underlying) return;
|
||||||
|
|
||||||
|
while (bytesIn > 0) {
|
||||||
|
decompress(true);
|
||||||
|
end = start; // throw away any data
|
||||||
|
}
|
||||||
|
underlying = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibInStream::reset()
|
||||||
|
{
|
||||||
|
deinit();
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibInStream::init()
|
||||||
|
{
|
||||||
|
assert(zs == NULL);
|
||||||
|
|
||||||
|
zs = new z_stream;
|
||||||
|
zs->zalloc = Z_NULL;
|
||||||
|
zs->zfree = Z_NULL;
|
||||||
|
zs->opaque = Z_NULL;
|
||||||
|
zs->next_in = Z_NULL;
|
||||||
|
zs->avail_in = 0;
|
||||||
|
if (inflateInit(zs) != Z_OK) {
|
||||||
|
delete zs;
|
||||||
|
zs = NULL;
|
||||||
|
throw Exception("ZlibInStream: inflateInit failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibInStream::deinit()
|
||||||
|
{
|
||||||
|
assert(zs != NULL);
|
||||||
|
removeUnderlying();
|
||||||
|
inflateEnd(zs);
|
||||||
|
delete zs;
|
||||||
|
zs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZlibInStream::overrun(int itemSize, int nItems, bool wait)
|
||||||
|
{
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("ZlibInStream overrun: max itemSize exceeded");
|
||||||
|
if (!underlying)
|
||||||
|
throw Exception("ZlibInStream overrun: no underlying stream");
|
||||||
|
|
||||||
|
if (end - ptr != 0)
|
||||||
|
memmove(start, ptr, end - ptr);
|
||||||
|
|
||||||
|
offset += ptr - start;
|
||||||
|
end -= ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
|
||||||
|
while (end - ptr < itemSize) {
|
||||||
|
if (!decompress(wait))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decompress() calls the decompressor once. Note that this won't necessarily
|
||||||
|
// generate any output data - it may just consume some input data. Returns
|
||||||
|
// false if wait is false and we would block on the underlying stream.
|
||||||
|
|
||||||
|
bool ZlibInStream::decompress(bool wait)
|
||||||
|
{
|
||||||
|
zs->next_out = (U8*)end;
|
||||||
|
zs->avail_out = start + bufSize - end;
|
||||||
|
|
||||||
|
int n = underlying->check(1, 1, wait);
|
||||||
|
if (n == 0) return false;
|
||||||
|
zs->next_in = (U8*)underlying->getptr();
|
||||||
|
zs->avail_in = underlying->getend() - underlying->getptr();
|
||||||
|
if ((int)zs->avail_in > bytesIn)
|
||||||
|
zs->avail_in = bytesIn;
|
||||||
|
|
||||||
|
int rc = inflate(zs, Z_SYNC_FLUSH);
|
||||||
|
if (rc != Z_OK) {
|
||||||
|
throw Exception("ZlibInStream: inflate failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesIn -= zs->next_in - underlying->getptr();
|
||||||
|
end = zs->next_out;
|
||||||
|
underlying->setptr(zs->next_in);
|
||||||
|
return true;
|
||||||
|
}
|
63
common/rdr/ZlibInStream.h
Normal file
63
common/rdr/ZlibInStream.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// ZlibInStream streams from a compressed data stream ("underlying"),
|
||||||
|
// decompressing with zlib on the fly.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_ZLIBINSTREAM_H__
|
||||||
|
#define __RDR_ZLIBINSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
|
||||||
|
struct z_stream_s;
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class ZlibInStream : public InStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ZlibInStream(int bufSize=0);
|
||||||
|
virtual ~ZlibInStream();
|
||||||
|
|
||||||
|
void setUnderlying(InStream* is, int bytesIn);
|
||||||
|
void removeUnderlying();
|
||||||
|
int pos();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void deinit();
|
||||||
|
|
||||||
|
int overrun(int itemSize, int nItems, bool wait);
|
||||||
|
bool decompress(bool wait);
|
||||||
|
|
||||||
|
InStream* underlying;
|
||||||
|
int bufSize;
|
||||||
|
int offset;
|
||||||
|
z_stream_s* zs;
|
||||||
|
int bytesIn;
|
||||||
|
U8* start;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
201
common/rdr/ZlibOutStream.cxx
Normal file
201
common/rdr/ZlibOutStream.cxx
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 <rdr/ZlibOutStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#undef ZLIBOUT_DEBUG
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||||
|
|
||||||
|
ZlibOutStream::ZlibOutStream(OutStream* os, int bufSize_, int compressLevel)
|
||||||
|
: underlying(os), compressionLevel(compressLevel), newLevel(compressLevel),
|
||||||
|
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
zs = new z_stream;
|
||||||
|
zs->zalloc = Z_NULL;
|
||||||
|
zs->zfree = Z_NULL;
|
||||||
|
zs->opaque = Z_NULL;
|
||||||
|
zs->next_in = Z_NULL;
|
||||||
|
zs->avail_in = 0;
|
||||||
|
if (deflateInit(zs, compressLevel) != Z_OK) {
|
||||||
|
delete zs;
|
||||||
|
throw Exception("ZlibOutStream: deflateInit failed");
|
||||||
|
}
|
||||||
|
ptr = start = new U8[bufSize];
|
||||||
|
end = start + bufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZlibOutStream::~ZlibOutStream()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
flush();
|
||||||
|
} catch (Exception&) {
|
||||||
|
}
|
||||||
|
delete [] start;
|
||||||
|
deflateEnd(zs);
|
||||||
|
delete zs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibOutStream::setUnderlying(OutStream* os)
|
||||||
|
{
|
||||||
|
underlying = os;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibOutStream::setCompressionLevel(int level)
|
||||||
|
{
|
||||||
|
if (level < -1 || level > 9)
|
||||||
|
level = -1; // Z_DEFAULT_COMPRESSION
|
||||||
|
|
||||||
|
newLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZlibOutStream::length()
|
||||||
|
{
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibOutStream::flush()
|
||||||
|
{
|
||||||
|
checkCompressionLevel();
|
||||||
|
|
||||||
|
zs->next_in = start;
|
||||||
|
zs->avail_in = ptr - start;
|
||||||
|
|
||||||
|
#ifdef ZLIBOUT_DEBUG
|
||||||
|
fprintf(stderr,"zos flush: avail_in %d\n",zs->avail_in);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Force out everything from the zlib encoder
|
||||||
|
deflate(Z_SYNC_FLUSH);
|
||||||
|
|
||||||
|
offset += ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZlibOutStream::overrun(int itemSize, int nItems)
|
||||||
|
{
|
||||||
|
#ifdef ZLIBOUT_DEBUG
|
||||||
|
fprintf(stderr,"zos overrun\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (itemSize > bufSize)
|
||||||
|
throw Exception("ZlibOutStream overrun: max itemSize exceeded");
|
||||||
|
|
||||||
|
checkCompressionLevel();
|
||||||
|
|
||||||
|
while (end - ptr < itemSize) {
|
||||||
|
zs->next_in = start;
|
||||||
|
zs->avail_in = ptr - start;
|
||||||
|
|
||||||
|
deflate(Z_NO_FLUSH);
|
||||||
|
|
||||||
|
// output buffer not full
|
||||||
|
|
||||||
|
if (zs->avail_in == 0) {
|
||||||
|
offset += ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
} else {
|
||||||
|
// but didn't consume all the data? try shifting what's left to the
|
||||||
|
// start of the buffer.
|
||||||
|
fprintf(stderr,"z out buf not full, but in data not consumed\n");
|
||||||
|
memmove(start, zs->next_in, ptr - zs->next_in);
|
||||||
|
offset += zs->next_in - start;
|
||||||
|
ptr -= zs->next_in - start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSize * nItems > end - ptr)
|
||||||
|
nItems = (end - ptr) / itemSize;
|
||||||
|
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibOutStream::deflate(int flush)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!underlying)
|
||||||
|
throw Exception("ZlibOutStream: underlying OutStream has not been set");
|
||||||
|
|
||||||
|
if ((flush == Z_NO_FLUSH) && (zs->avail_in == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
underlying->check(1);
|
||||||
|
zs->next_out = underlying->getptr();
|
||||||
|
zs->avail_out = underlying->getend() - underlying->getptr();
|
||||||
|
|
||||||
|
#ifdef ZLIBOUT_DEBUG
|
||||||
|
fprintf(stderr,"zos: calling deflate, avail_in %d, avail_out %d\n",
|
||||||
|
zs->avail_in,zs->avail_out);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = ::deflate(zs, flush);
|
||||||
|
if (rc != Z_OK) {
|
||||||
|
// Silly zlib returns an error if you try to flush something twice
|
||||||
|
if ((rc == Z_BUF_ERROR) && (flush != Z_NO_FLUSH))
|
||||||
|
break;
|
||||||
|
|
||||||
|
throw Exception("ZlibOutStream: deflate failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ZLIBOUT_DEBUG
|
||||||
|
fprintf(stderr,"zos: after deflate: %d bytes\n",
|
||||||
|
zs->next_out-underlying->getptr());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
underlying->setptr(zs->next_out);
|
||||||
|
} while (zs->avail_out == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibOutStream::checkCompressionLevel()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (newLevel != compressionLevel) {
|
||||||
|
#ifdef ZLIBOUT_DEBUG
|
||||||
|
fprintf(stderr,"zos change: avail_in %d\n",zs->avail_in);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// zlib is just horribly stupid. It does an implicit flush on
|
||||||
|
// parameter changes, but the flush it does is not one that forces
|
||||||
|
// out all the data. And since you cannot flush things again, we
|
||||||
|
// cannot force out our data after the parameter change. Hence we
|
||||||
|
// need to do a more proper flush here first.
|
||||||
|
deflate(Z_SYNC_FLUSH);
|
||||||
|
|
||||||
|
rc = deflateParams (zs, newLevel, Z_DEFAULT_STRATEGY);
|
||||||
|
if (rc != Z_OK) {
|
||||||
|
// The implicit flush can result in this error, caused by the
|
||||||
|
// explicit flush we did above. It should be safe to ignore though
|
||||||
|
// as the first flush should have left things in a stable state...
|
||||||
|
if (rc != Z_BUF_ERROR)
|
||||||
|
throw Exception("ZlibOutStream: deflateParams failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
compressionLevel = newLevel;
|
||||||
|
}
|
||||||
|
}
|
63
common/rdr/ZlibOutStream.h
Normal file
63
common/rdr/ZlibOutStream.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// ZlibOutStream streams to a compressed data stream (underlying), compressing
|
||||||
|
// with zlib on the fly.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_ZLIBOUTSTREAM_H__
|
||||||
|
#define __RDR_ZLIBOUTSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
struct z_stream_s;
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class ZlibOutStream : public OutStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ZlibOutStream(OutStream* os=0, int bufSize=0, int compressionLevel=-1);
|
||||||
|
virtual ~ZlibOutStream();
|
||||||
|
|
||||||
|
void setUnderlying(OutStream* os);
|
||||||
|
void setCompressionLevel(int level=-1);
|
||||||
|
void flush();
|
||||||
|
int length();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int overrun(int itemSize, int nItems);
|
||||||
|
void deflate(int flush);
|
||||||
|
void checkCompressionLevel();
|
||||||
|
|
||||||
|
OutStream* underlying;
|
||||||
|
int compressionLevel;
|
||||||
|
int newLevel;
|
||||||
|
int bufSize;
|
||||||
|
int offset;
|
||||||
|
z_stream_s* zs;
|
||||||
|
U8* start;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
77
common/rdr/types.h
Normal file
77
common/rdr/types.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 __RDR_TYPES_H__
|
||||||
|
#define __RDR_TYPES_H__
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
typedef unsigned char U8;
|
||||||
|
typedef unsigned short U16;
|
||||||
|
typedef unsigned int U32;
|
||||||
|
typedef unsigned long long U64;
|
||||||
|
typedef signed char S8;
|
||||||
|
typedef signed short S16;
|
||||||
|
typedef signed int S32;
|
||||||
|
|
||||||
|
class U8Array {
|
||||||
|
public:
|
||||||
|
U8Array() : buf(0) {}
|
||||||
|
U8Array(U8* a) : buf(a) {} // note: assumes ownership
|
||||||
|
U8Array(int len) : buf(new U8[len]) {}
|
||||||
|
~U8Array() { delete [] buf; }
|
||||||
|
|
||||||
|
// Get the buffer pointer & clear it (i.e. caller takes ownership)
|
||||||
|
U8* takeBuf() { U8* tmp = buf; buf = 0; return tmp; }
|
||||||
|
|
||||||
|
U8* buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
class U16Array {
|
||||||
|
public:
|
||||||
|
U16Array() : buf(0) {}
|
||||||
|
U16Array(U16* a) : buf(a) {} // note: assumes ownership
|
||||||
|
U16Array(int len) : buf(new U16[len]) {}
|
||||||
|
~U16Array() { delete [] buf; }
|
||||||
|
U16* takeBuf() { U16* tmp = buf; buf = 0; return tmp; }
|
||||||
|
U16* buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
class U32Array {
|
||||||
|
public:
|
||||||
|
U32Array() : buf(0) {}
|
||||||
|
U32Array(U32* a) : buf(a) {} // note: assumes ownership
|
||||||
|
U32Array(int len) : buf(new U32[len]) {}
|
||||||
|
~U32Array() { delete [] buf; }
|
||||||
|
U32* takeBuf() { U32* tmp = buf; buf = 0; return tmp; }
|
||||||
|
U32* buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
class S32Array {
|
||||||
|
public:
|
||||||
|
S32Array() : buf(0) {}
|
||||||
|
S32Array(S32* a) : buf(a) {} // note: assumes ownership
|
||||||
|
S32Array(int len) : buf(new S32[len]) {}
|
||||||
|
~S32Array() { delete [] buf; }
|
||||||
|
S32* takeBuf() { S32* tmp = buf; buf = 0; return tmp; }
|
||||||
|
S32* buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
86
common/rfb/Blacklist.cxx
Normal file
86
common/rfb/Blacklist.cxx
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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/Blacklist.h>
|
||||||
|
#include <rfb/Configuration.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
IntParameter Blacklist::threshold("BlacklistThreshold",
|
||||||
|
"The number of unauthenticated connection attempts allowed from any "
|
||||||
|
"individual host before that host is black-listed",
|
||||||
|
5);
|
||||||
|
IntParameter Blacklist::initialTimeout("BlacklistTimeout",
|
||||||
|
"The initial timeout applied when a host is first black-listed. "
|
||||||
|
"The host cannot re-attempt a connection until the timeout expires.",
|
||||||
|
10);
|
||||||
|
|
||||||
|
|
||||||
|
Blacklist::Blacklist() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Blacklist::~Blacklist() {
|
||||||
|
// Free the map keys
|
||||||
|
BlacklistMap::iterator i;
|
||||||
|
for (i=blm.begin(); i!=blm.end(); i++) {
|
||||||
|
strFree((char*)(*i).first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Blacklist::isBlackmarked(const char* name) {
|
||||||
|
BlacklistMap::iterator i = blm.find(name);
|
||||||
|
if (i == blm.end()) {
|
||||||
|
// Entry is not already black-marked.
|
||||||
|
// Create the entry unmarked, unblocked,
|
||||||
|
// with suitable defaults set.
|
||||||
|
BlacklistInfo bi;
|
||||||
|
bi.marks = 1;
|
||||||
|
bi.blockUntil = 0;
|
||||||
|
bi.blockTimeout = initialTimeout;
|
||||||
|
blm[strDup(name)] = bi;
|
||||||
|
i = blm.find(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry exists - has it reached the threshold yet?
|
||||||
|
if ((*i).second.marks >= threshold) {
|
||||||
|
// Yes - entry is blocked - has the timeout expired?
|
||||||
|
time_t now = time(0);
|
||||||
|
if (now >= (*i).second.blockUntil) {
|
||||||
|
// Timeout has expired. Reset timeout and allow
|
||||||
|
// a re-try.
|
||||||
|
(*i).second.blockUntil = now + (*i).second.blockTimeout;
|
||||||
|
(*i).second.blockTimeout = (*i).second.blockTimeout * 2;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Blocked and timeout still in effect - reject!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We haven't reached the threshold yet.
|
||||||
|
// Increment the black-mark counter but allow
|
||||||
|
// the entry to pass.
|
||||||
|
(*i).second.marks++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blacklist::clearBlackmark(const char* name) {
|
||||||
|
BlacklistMap::iterator i = blm.find(name);
|
||||||
|
if (i != blm.end()) {
|
||||||
|
strFree((char*)(*i).first);
|
||||||
|
blm.erase(i);
|
||||||
|
}
|
||||||
|
}
|
91
common/rfb/Blacklist.h
Normal file
91
common/rfb/Blacklist.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Blacklist.h - Handling of black-listed entities.
|
||||||
|
// Just keeps a table mapping strings to timing information, including
|
||||||
|
// how many times the entry has been black-listed and when to next
|
||||||
|
// put it on probation (e.g. allow a connection in from the host, and
|
||||||
|
// re-blacklist it if that fails).
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RFB_BLACKLIST_H__
|
||||||
|
#define __RFB_BLACKLIST_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <rfb/Configuration.h>
|
||||||
|
#include <rfb/util.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
//
|
||||||
|
// -=- Blacklist handler
|
||||||
|
//
|
||||||
|
// Parameters include a threshold after which to blacklist the named
|
||||||
|
// host, and a timeout after which to re-consider them.
|
||||||
|
//
|
||||||
|
// Threshold means that isBlackmarked can be called that number of times
|
||||||
|
// before it will return true.
|
||||||
|
//
|
||||||
|
// Timeout means that after that many seconds, the next call to isBlackmarked
|
||||||
|
// will return false. At the same time, the timeout is doubled, so that the
|
||||||
|
// next calls will fail, until the timeout expires again or clearBlackmark is
|
||||||
|
// called.
|
||||||
|
//
|
||||||
|
// When clearBlackMark is called, the corresponding entry is completely
|
||||||
|
// removed, causing the next isBlackmarked call to return false.
|
||||||
|
|
||||||
|
// KNOWN BUG: Client can keep making rejected requests, thus increasing
|
||||||
|
// their timeout. If client does this for 30 years, timeout may wrap round
|
||||||
|
// to a very small value again.
|
||||||
|
|
||||||
|
// THIS CLASS IS NOT THREAD-SAFE!
|
||||||
|
|
||||||
|
class Blacklist {
|
||||||
|
public:
|
||||||
|
Blacklist();
|
||||||
|
~Blacklist();
|
||||||
|
|
||||||
|
bool isBlackmarked(const char* name);
|
||||||
|
void clearBlackmark(const char* name);
|
||||||
|
|
||||||
|
static IntParameter threshold;
|
||||||
|
static IntParameter initialTimeout;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct ltStr {
|
||||||
|
bool operator()(const char* s1, const char* s2) const {
|
||||||
|
return strcmp(s1, s2) < 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
struct BlacklistInfo {
|
||||||
|
int marks;
|
||||||
|
time_t blockUntil;
|
||||||
|
unsigned int blockTimeout;
|
||||||
|
};
|
||||||
|
typedef std::map<const char*,BlacklistInfo,ltStr> BlacklistMap;
|
||||||
|
BlacklistMap blm;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
366
common/rfb/CConnection.cxx
Normal file
366
common/rfb/CConnection.cxx
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2011-2017 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 <string.h>
|
||||||
|
|
||||||
|
#include <rfb/Exception.h>
|
||||||
|
#include <rfb/fenceTypes.h>
|
||||||
|
#include <rfb/CMsgReader.h>
|
||||||
|
#include <rfb/CMsgWriter.h>
|
||||||
|
#include <rfb/CSecurity.h>
|
||||||
|
#include <rfb/Security.h>
|
||||||
|
#include <rfb/SecurityClient.h>
|
||||||
|
#include <rfb/CConnection.h>
|
||||||
|
#include <rfb/util.h>
|
||||||
|
|
||||||
|
#include <rfb/LogWriter.h>
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
static LogWriter vlog("CConnection");
|
||||||
|
|
||||||
|
CConnection::CConnection()
|
||||||
|
: csecurity(0), is(0), os(0), reader_(0), writer_(0),
|
||||||
|
shared(false),
|
||||||
|
state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
|
||||||
|
framebuffer(NULL), decoder(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CConnection::~CConnection()
|
||||||
|
{
|
||||||
|
setFramebuffer(NULL);
|
||||||
|
if (csecurity) csecurity->destroy();
|
||||||
|
delete reader_;
|
||||||
|
reader_ = 0;
|
||||||
|
delete writer_;
|
||||||
|
writer_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
|
||||||
|
{
|
||||||
|
is = is_;
|
||||||
|
os = os_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
|
||||||
|
{
|
||||||
|
decoder.flush();
|
||||||
|
|
||||||
|
if ((framebuffer != NULL) && (fb != NULL)) {
|
||||||
|
Rect rect;
|
||||||
|
|
||||||
|
const rdr::U8* data;
|
||||||
|
int stride;
|
||||||
|
|
||||||
|
const rdr::U8 black[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
// Copy still valid area
|
||||||
|
|
||||||
|
rect.setXYWH(0, 0,
|
||||||
|
__rfbmin(fb->width(), framebuffer->width()),
|
||||||
|
__rfbmin(fb->height(), framebuffer->height()));
|
||||||
|
data = framebuffer->getBuffer(framebuffer->getRect(), &stride);
|
||||||
|
fb->imageRect(rect, data, stride);
|
||||||
|
|
||||||
|
// Black out any new areas
|
||||||
|
|
||||||
|
if (fb->width() > framebuffer->width()) {
|
||||||
|
rect.setXYWH(framebuffer->width(), 0,
|
||||||
|
fb->width() - framebuffer->width(),
|
||||||
|
fb->height());
|
||||||
|
fb->fillRect(rect, black);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fb->height() > framebuffer->height()) {
|
||||||
|
rect.setXYWH(0, framebuffer->height(),
|
||||||
|
fb->width(),
|
||||||
|
fb->height() - framebuffer->height());
|
||||||
|
fb->fillRect(rect, black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete framebuffer;
|
||||||
|
framebuffer = fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::initialiseProtocol()
|
||||||
|
{
|
||||||
|
state_ = RFBSTATE_PROTOCOL_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::processMsg()
|
||||||
|
{
|
||||||
|
switch (state_) {
|
||||||
|
|
||||||
|
case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break;
|
||||||
|
case RFBSTATE_SECURITY_TYPES: processSecurityTypesMsg(); break;
|
||||||
|
case RFBSTATE_SECURITY: processSecurityMsg(); break;
|
||||||
|
case RFBSTATE_SECURITY_RESULT: processSecurityResultMsg(); break;
|
||||||
|
case RFBSTATE_INITIALISATION: processInitMsg(); break;
|
||||||
|
case RFBSTATE_NORMAL: reader_->readMsg(); break;
|
||||||
|
case RFBSTATE_UNINITIALISED:
|
||||||
|
throw Exception("CConnection::processMsg: not initialised yet?");
|
||||||
|
default:
|
||||||
|
throw Exception("CConnection::processMsg: invalid state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::processVersionMsg()
|
||||||
|
{
|
||||||
|
vlog.debug("reading protocol version");
|
||||||
|
bool done;
|
||||||
|
if (!cp.readVersion(is, &done)) {
|
||||||
|
state_ = RFBSTATE_INVALID;
|
||||||
|
throw Exception("reading version failed: not an RFB server?");
|
||||||
|
}
|
||||||
|
if (!done) return;
|
||||||
|
|
||||||
|
vlog.info("Server supports RFB protocol version %d.%d",
|
||||||
|
cp.majorVersion, cp.minorVersion);
|
||||||
|
|
||||||
|
// The only official RFB protocol versions are currently 3.3, 3.7 and 3.8
|
||||||
|
if (cp.beforeVersion(3,3)) {
|
||||||
|
vlog.error("Server gave unsupported RFB protocol version %d.%d",
|
||||||
|
cp.majorVersion, cp.minorVersion);
|
||||||
|
state_ = RFBSTATE_INVALID;
|
||||||
|
throw Exception("Server gave unsupported RFB protocol version %d.%d",
|
||||||
|
cp.majorVersion, cp.minorVersion);
|
||||||
|
} else if (useProtocol3_3 || cp.beforeVersion(3,7)) {
|
||||||
|
cp.setVersion(3,3);
|
||||||
|
} else if (cp.afterVersion(3,8)) {
|
||||||
|
cp.setVersion(3,8);
|
||||||
|
}
|
||||||
|
|
||||||
|
cp.writeVersion(os);
|
||||||
|
state_ = RFBSTATE_SECURITY_TYPES;
|
||||||
|
|
||||||
|
vlog.info("Using RFB protocol version %d.%d",
|
||||||
|
cp.majorVersion, cp.minorVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CConnection::processSecurityTypesMsg()
|
||||||
|
{
|
||||||
|
vlog.debug("processing security types message");
|
||||||
|
|
||||||
|
int secType = secTypeInvalid;
|
||||||
|
|
||||||
|
std::list<rdr::U8> secTypes;
|
||||||
|
secTypes = security.GetEnabledSecTypes();
|
||||||
|
|
||||||
|
if (cp.isVersion(3,3)) {
|
||||||
|
|
||||||
|
// legacy 3.3 server may only offer "vnc authentication" or "none"
|
||||||
|
|
||||||
|
secType = is->readU32();
|
||||||
|
if (secType == secTypeInvalid) {
|
||||||
|
throwConnFailedException();
|
||||||
|
|
||||||
|
} else if (secType == secTypeNone || secType == secTypeVncAuth) {
|
||||||
|
std::list<rdr::U8>::iterator i;
|
||||||
|
for (i = secTypes.begin(); i != secTypes.end(); i++)
|
||||||
|
if (*i == secType) {
|
||||||
|
secType = *i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == secTypes.end())
|
||||||
|
secType = secTypeInvalid;
|
||||||
|
} else {
|
||||||
|
vlog.error("Unknown 3.3 security type %d", secType);
|
||||||
|
throw Exception("Unknown 3.3 security type");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// >=3.7 server will offer us a list
|
||||||
|
|
||||||
|
int nServerSecTypes = is->readU8();
|
||||||
|
if (nServerSecTypes == 0)
|
||||||
|
throwConnFailedException();
|
||||||
|
|
||||||
|
std::list<rdr::U8>::iterator j;
|
||||||
|
|
||||||
|
for (int i = 0; i < nServerSecTypes; i++) {
|
||||||
|
rdr::U8 serverSecType = is->readU8();
|
||||||
|
vlog.debug("Server offers security type %s(%d)",
|
||||||
|
secTypeName(serverSecType), serverSecType);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the first type sent by server which matches client's type.
|
||||||
|
* It means server's order specifies priority.
|
||||||
|
*/
|
||||||
|
if (secType == secTypeInvalid) {
|
||||||
|
for (j = secTypes.begin(); j != secTypes.end(); j++)
|
||||||
|
if (*j == serverSecType) {
|
||||||
|
secType = *j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inform the server of our decision
|
||||||
|
if (secType != secTypeInvalid) {
|
||||||
|
os->writeU8(secType);
|
||||||
|
os->flush();
|
||||||
|
vlog.info("Choosing security type %s(%d)",secTypeName(secType),secType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secType == secTypeInvalid) {
|
||||||
|
state_ = RFBSTATE_INVALID;
|
||||||
|
vlog.error("No matching security types");
|
||||||
|
throw Exception("No matching security types");
|
||||||
|
}
|
||||||
|
|
||||||
|
state_ = RFBSTATE_SECURITY;
|
||||||
|
csecurity = security.GetCSecurity(secType);
|
||||||
|
processSecurityMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::processSecurityMsg()
|
||||||
|
{
|
||||||
|
vlog.debug("processing security message");
|
||||||
|
if (csecurity->processMsg(this)) {
|
||||||
|
state_ = RFBSTATE_SECURITY_RESULT;
|
||||||
|
processSecurityResultMsg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::processSecurityResultMsg()
|
||||||
|
{
|
||||||
|
vlog.debug("processing security result message");
|
||||||
|
int result;
|
||||||
|
if (cp.beforeVersion(3,8) && csecurity->getType() == secTypeNone) {
|
||||||
|
result = secResultOK;
|
||||||
|
} else {
|
||||||
|
if (!is->checkNoWait(1)) return;
|
||||||
|
result = is->readU32();
|
||||||
|
}
|
||||||
|
switch (result) {
|
||||||
|
case secResultOK:
|
||||||
|
securityCompleted();
|
||||||
|
return;
|
||||||
|
case secResultFailed:
|
||||||
|
vlog.debug("auth failed");
|
||||||
|
break;
|
||||||
|
case secResultTooMany:
|
||||||
|
vlog.debug("auth failed - too many tries");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw Exception("Unknown security result from server");
|
||||||
|
}
|
||||||
|
state_ = RFBSTATE_INVALID;
|
||||||
|
if (cp.beforeVersion(3,8))
|
||||||
|
throw AuthFailureException();
|
||||||
|
CharArray reason(is->readString());
|
||||||
|
throw AuthFailureException(reason.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::processInitMsg()
|
||||||
|
{
|
||||||
|
vlog.debug("reading server initialisation");
|
||||||
|
reader_->readServerInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::throwConnFailedException()
|
||||||
|
{
|
||||||
|
state_ = RFBSTATE_INVALID;
|
||||||
|
CharArray reason;
|
||||||
|
reason.buf = is->readString();
|
||||||
|
throw ConnFailedException(reason.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::securityCompleted()
|
||||||
|
{
|
||||||
|
state_ = RFBSTATE_INITIALISATION;
|
||||||
|
reader_ = new CMsgReader(this, is);
|
||||||
|
writer_ = new CMsgWriter(&cp, os);
|
||||||
|
vlog.debug("Authentication success!");
|
||||||
|
authSuccess();
|
||||||
|
writer_->writeClientInit(shared);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::setDesktopSize(int w, int h)
|
||||||
|
{
|
||||||
|
decoder.flush();
|
||||||
|
|
||||||
|
CMsgHandler::setDesktopSize(w,h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::setExtendedDesktopSize(unsigned reason,
|
||||||
|
unsigned result,
|
||||||
|
int w, int h,
|
||||||
|
const ScreenSet& layout)
|
||||||
|
{
|
||||||
|
decoder.flush();
|
||||||
|
|
||||||
|
CMsgHandler::setExtendedDesktopSize(reason, result, w, h, layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::readAndDecodeRect(const Rect& r, int encoding,
|
||||||
|
ModifiablePixelBuffer* pb)
|
||||||
|
{
|
||||||
|
decoder.decodeRect(r, encoding, pb);
|
||||||
|
decoder.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::framebufferUpdateStart()
|
||||||
|
{
|
||||||
|
CMsgHandler::framebufferUpdateStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::framebufferUpdateEnd()
|
||||||
|
{
|
||||||
|
decoder.flush();
|
||||||
|
|
||||||
|
CMsgHandler::framebufferUpdateEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::dataRect(const Rect& r, int encoding)
|
||||||
|
{
|
||||||
|
decoder.decodeRect(r, encoding, framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::authSuccess()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::serverInit()
|
||||||
|
{
|
||||||
|
state_ = RFBSTATE_NORMAL;
|
||||||
|
vlog.debug("initialisation done");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
|
||||||
|
{
|
||||||
|
CMsgHandler::fence(flags, len, data);
|
||||||
|
|
||||||
|
if (!(flags & fenceFlagRequest))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We cannot guarantee any synchronisation at this level
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
|
writer()->writeFence(flags, len, data);
|
||||||
|
}
|
195
common/rfb/CConnection.h
Normal file
195
common/rfb/CConnection.h
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2011-2017 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CConnection - class on the client side representing a connection to a
|
||||||
|
// server. A derived class should override methods appropriately.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RFB_CCONNECTION_H__
|
||||||
|
#define __RFB_CCONNECTION_H__
|
||||||
|
|
||||||
|
#include <rfb/CMsgHandler.h>
|
||||||
|
#include <rfb/DecodeManager.h>
|
||||||
|
#include <rfb/SecurityClient.h>
|
||||||
|
#include <rfb/util.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class CMsgReader;
|
||||||
|
class CMsgWriter;
|
||||||
|
class CSecurity;
|
||||||
|
class IdentityVerifier;
|
||||||
|
|
||||||
|
class CConnection : public CMsgHandler {
|
||||||
|
public:
|
||||||
|
|
||||||
|
CConnection();
|
||||||
|
virtual ~CConnection();
|
||||||
|
|
||||||
|
// Methods to initialise the connection
|
||||||
|
|
||||||
|
// setServerName() is used to provide a unique(ish) name for the server to
|
||||||
|
// which we are connected. This might be the result of getPeerEndpoint on
|
||||||
|
// a TcpSocket, for example, or a host specified by DNS name & port.
|
||||||
|
// The serverName is used when verifying the Identity of a host (see RA2).
|
||||||
|
void setServerName(const char* name_) { serverName.replaceBuf(strDup(name_)); }
|
||||||
|
|
||||||
|
// setStreams() sets the streams to be used for the connection. These must
|
||||||
|
// be set before initialiseProtocol() and processMsg() are called. The
|
||||||
|
// CSecurity object may call setStreams() again to provide alternative
|
||||||
|
// streams over which the RFB protocol is sent (i.e. encrypting/decrypting
|
||||||
|
// streams). Ownership of the streams remains with the caller
|
||||||
|
// (i.e. SConnection will not delete them).
|
||||||
|
void setStreams(rdr::InStream* is, rdr::OutStream* os);
|
||||||
|
|
||||||
|
// setShared sets the value of the shared flag which will be sent to the
|
||||||
|
// server upon initialisation.
|
||||||
|
void setShared(bool s) { shared = s; }
|
||||||
|
|
||||||
|
// setProtocol3_3 configures whether or not the CConnection should
|
||||||
|
// only ever support protocol version 3.3
|
||||||
|
void setProtocol3_3(bool s) {useProtocol3_3 = s;}
|
||||||
|
|
||||||
|
// setFramebuffer configures the PixelBuffer that the CConnection
|
||||||
|
// should render all pixel data in to. Note that the CConnection
|
||||||
|
// takes ownership of the PixelBuffer and it must not be deleted by
|
||||||
|
// anyone else. Call setFramebuffer again with NULL or a different
|
||||||
|
// PixelBuffer to delete the previous one.
|
||||||
|
void setFramebuffer(ModifiablePixelBuffer* fb);
|
||||||
|
|
||||||
|
// initialiseProtocol() should be called once the streams and security
|
||||||
|
// types are set. Subsequently, processMsg() should be called whenever
|
||||||
|
// there is data to read on the InStream.
|
||||||
|
void initialiseProtocol();
|
||||||
|
|
||||||
|
// processMsg() should be called whenever there is either:
|
||||||
|
// - data available on the underlying network stream
|
||||||
|
// In this case, processMsg may return without processing an RFB message,
|
||||||
|
// if the available data does not result in an RFB message being ready
|
||||||
|
// to handle. e.g. if data is encrypted.
|
||||||
|
// NB: This makes it safe to call processMsg() in response to select()
|
||||||
|
// - data available on the CConnection's current InStream
|
||||||
|
// In this case, processMsg should always process the available RFB
|
||||||
|
// message before returning.
|
||||||
|
// NB: In either case, you must have called initialiseProtocol() first.
|
||||||
|
void processMsg();
|
||||||
|
|
||||||
|
|
||||||
|
// Methods overridden from CMsgHandler
|
||||||
|
|
||||||
|
// Note: These must be called by any deriving classes
|
||||||
|
|
||||||
|
virtual void setDesktopSize(int w, int h);
|
||||||
|
virtual void setExtendedDesktopSize(unsigned reason, unsigned result,
|
||||||
|
int w, int h,
|
||||||
|
const ScreenSet& layout);
|
||||||
|
|
||||||
|
virtual void readAndDecodeRect(const Rect& r, int encoding,
|
||||||
|
ModifiablePixelBuffer* pb);
|
||||||
|
|
||||||
|
virtual void framebufferUpdateStart();
|
||||||
|
virtual void framebufferUpdateEnd();
|
||||||
|
virtual void dataRect(const Rect& r, int encoding);
|
||||||
|
|
||||||
|
|
||||||
|
// Methods to be overridden in a derived class
|
||||||
|
|
||||||
|
// getIdVerifier() returns the identity verifier associated with the connection.
|
||||||
|
// Ownership of the IdentityVerifier is retained by the CConnection instance.
|
||||||
|
virtual IdentityVerifier* getIdentityVerifier() {return 0;}
|
||||||
|
|
||||||
|
// authSuccess() is called when authentication has succeeded.
|
||||||
|
virtual void authSuccess();
|
||||||
|
|
||||||
|
// serverInit() is called when the ServerInit message is received. The
|
||||||
|
// derived class must call on to CConnection::serverInit().
|
||||||
|
virtual void serverInit();
|
||||||
|
|
||||||
|
|
||||||
|
// Other methods
|
||||||
|
|
||||||
|
CMsgReader* reader() { return reader_; }
|
||||||
|
CMsgWriter* writer() { return writer_; }
|
||||||
|
|
||||||
|
rdr::InStream* getInStream() { return is; }
|
||||||
|
rdr::OutStream* getOutStream() { return os; }
|
||||||
|
|
||||||
|
// Access method used by SSecurity implementations that can verify servers'
|
||||||
|
// Identities, to determine the unique(ish) name of the server.
|
||||||
|
const char* getServerName() const { return serverName.buf; }
|
||||||
|
|
||||||
|
bool isSecure() const { return csecurity ? csecurity->isSecure() : false; }
|
||||||
|
|
||||||
|
enum stateEnum {
|
||||||
|
RFBSTATE_UNINITIALISED,
|
||||||
|
RFBSTATE_PROTOCOL_VERSION,
|
||||||
|
RFBSTATE_SECURITY_TYPES,
|
||||||
|
RFBSTATE_SECURITY,
|
||||||
|
RFBSTATE_SECURITY_RESULT,
|
||||||
|
RFBSTATE_INITIALISATION,
|
||||||
|
RFBSTATE_NORMAL,
|
||||||
|
RFBSTATE_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
stateEnum state() { return state_; }
|
||||||
|
|
||||||
|
CSecurity *csecurity;
|
||||||
|
SecurityClient security;
|
||||||
|
protected:
|
||||||
|
void setState(stateEnum s) { state_ = s; }
|
||||||
|
|
||||||
|
void setReader(CMsgReader *r) { reader_ = r; }
|
||||||
|
void setWriter(CMsgWriter *w) { writer_ = w; }
|
||||||
|
|
||||||
|
ModifiablePixelBuffer* getFramebuffer() { return framebuffer; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This is a default implementation of fences that automatically
|
||||||
|
// responds to requests, stating no support for synchronisation.
|
||||||
|
// When overriding, call CMsgHandler::fence() directly in order to
|
||||||
|
// state correct support for fence flags.
|
||||||
|
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processVersionMsg();
|
||||||
|
void processSecurityTypesMsg();
|
||||||
|
void processSecurityMsg();
|
||||||
|
void processSecurityResultMsg();
|
||||||
|
void processInitMsg();
|
||||||
|
void throwAuthFailureException();
|
||||||
|
void throwConnFailedException();
|
||||||
|
void securityCompleted();
|
||||||
|
|
||||||
|
rdr::InStream* is;
|
||||||
|
rdr::OutStream* os;
|
||||||
|
CMsgReader* reader_;
|
||||||
|
CMsgWriter* writer_;
|
||||||
|
bool deleteStreamsWhenDone;
|
||||||
|
bool shared;
|
||||||
|
stateEnum state_;
|
||||||
|
|
||||||
|
CharArray serverName;
|
||||||
|
|
||||||
|
bool useProtocol3_3;
|
||||||
|
|
||||||
|
ModifiablePixelBuffer* framebuffer;
|
||||||
|
DecodeManager decoder;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
105
common/rfb/CMakeLists.txt
Normal file
105
common/rfb/CMakeLists.txt
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
include_directories(${CMAKE_SOURCE_DIR}/common ${JPEG_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(RFB_SOURCES
|
||||||
|
Blacklist.cxx
|
||||||
|
Congestion.cxx
|
||||||
|
CConnection.cxx
|
||||||
|
CMsgHandler.cxx
|
||||||
|
CMsgReader.cxx
|
||||||
|
CMsgWriter.cxx
|
||||||
|
CSecurityPlain.cxx
|
||||||
|
CSecurityStack.cxx
|
||||||
|
CSecurityVeNCrypt.cxx
|
||||||
|
CSecurityVncAuth.cxx
|
||||||
|
ComparingUpdateTracker.cxx
|
||||||
|
Configuration.cxx
|
||||||
|
ConnParams.cxx
|
||||||
|
CopyRectDecoder.cxx
|
||||||
|
Cursor.cxx
|
||||||
|
DecodeManager.cxx
|
||||||
|
Decoder.cxx
|
||||||
|
d3des.c
|
||||||
|
EncCache.cxx
|
||||||
|
EncodeManager.cxx
|
||||||
|
Encoder.cxx
|
||||||
|
HTTPServer.cxx
|
||||||
|
HextileDecoder.cxx
|
||||||
|
HextileEncoder.cxx
|
||||||
|
JpegCompressor.cxx
|
||||||
|
JpegDecompressor.cxx
|
||||||
|
KeyRemapper.cxx
|
||||||
|
LogWriter.cxx
|
||||||
|
Logger.cxx
|
||||||
|
Logger_file.cxx
|
||||||
|
Logger_stdio.cxx
|
||||||
|
Password.cxx
|
||||||
|
PixelBuffer.cxx
|
||||||
|
PixelFormat.cxx
|
||||||
|
RREEncoder.cxx
|
||||||
|
RREDecoder.cxx
|
||||||
|
RawDecoder.cxx
|
||||||
|
RawEncoder.cxx
|
||||||
|
Region.cxx
|
||||||
|
SConnection.cxx
|
||||||
|
SMsgHandler.cxx
|
||||||
|
SMsgReader.cxx
|
||||||
|
SMsgWriter.cxx
|
||||||
|
ServerCore.cxx
|
||||||
|
Security.cxx
|
||||||
|
SecurityServer.cxx
|
||||||
|
SecurityClient.cxx
|
||||||
|
SSecurityPlain.cxx
|
||||||
|
SSecurityStack.cxx
|
||||||
|
SSecurityVncAuth.cxx
|
||||||
|
SSecurityVeNCrypt.cxx
|
||||||
|
ScaleFilters.cxx
|
||||||
|
Timer.cxx
|
||||||
|
TightDecoder.cxx
|
||||||
|
TightEncoder.cxx
|
||||||
|
TightJPEGEncoder.cxx
|
||||||
|
TightWEBPEncoder.cxx
|
||||||
|
UpdateTracker.cxx
|
||||||
|
VNCSConnectionST.cxx
|
||||||
|
VNCServerST.cxx
|
||||||
|
ZRLEEncoder.cxx
|
||||||
|
ZRLEDecoder.cxx
|
||||||
|
encodings.cxx
|
||||||
|
util.cxx
|
||||||
|
xxhash.c)
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
set(RFB_SOURCES ${RFB_SOURCES} Logger_syslog.cxx)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/win)
|
||||||
|
set(RFB_SOURCES ${RFB_SOURCES} WinPasswdValidator.cxx)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
set(RFB_LIBRARIES ${JPEG_LIBRARIES} os rdr Xregion)
|
||||||
|
|
||||||
|
if(HAVE_PAM)
|
||||||
|
set(RFB_SOURCES ${RFB_SOURCES} UnixPasswordValidator.cxx
|
||||||
|
UnixPasswordValidator.h pam.c pam.h)
|
||||||
|
set(RFB_LIBRARIES ${RFB_LIBRARIES} ${PAM_LIBS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(GNUTLS_FOUND)
|
||||||
|
set(RFB_SOURCES
|
||||||
|
${RFB_SOURCES}
|
||||||
|
CSecurityTLS.cxx
|
||||||
|
SSecurityTLS.cxx
|
||||||
|
)
|
||||||
|
set(RFB_LIBRARIES
|
||||||
|
${RFB_LIBRARIES}
|
||||||
|
${GNUTLS_LIBRARIES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(rfb STATIC ${RFB_SOURCES})
|
||||||
|
|
||||||
|
target_link_libraries(rfb ${RFB_LIBRARIES})
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
libtool_create_control_file(rfb)
|
||||||
|
endif()
|
94
common/rfb/CMsgHandler.cxx
Normal file
94
common/rfb/CMsgHandler.cxx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2009-2011 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 <rfb/Exception.h>
|
||||||
|
#include <rfb/CMsgHandler.h>
|
||||||
|
#include <rfb/screenTypes.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
CMsgHandler::CMsgHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CMsgHandler::~CMsgHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::setDesktopSize(int width, int height)
|
||||||
|
{
|
||||||
|
cp.width = width;
|
||||||
|
cp.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::setExtendedDesktopSize(unsigned reason, unsigned result,
|
||||||
|
int width, int height,
|
||||||
|
const ScreenSet& layout)
|
||||||
|
{
|
||||||
|
cp.supportsSetDesktopSize = true;
|
||||||
|
|
||||||
|
if ((reason == reasonClient) && (result != resultSuccess))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!layout.validate(width, height))
|
||||||
|
fprintf(stderr, "Server sent us an invalid screen layout\n");
|
||||||
|
|
||||||
|
cp.width = width;
|
||||||
|
cp.height = height;
|
||||||
|
cp.screenLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::setPixelFormat(const PixelFormat& pf)
|
||||||
|
{
|
||||||
|
cp.setPF(pf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::setName(const char* name)
|
||||||
|
{
|
||||||
|
cp.setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::fence(rdr::U32 flags, unsigned len, const char data[])
|
||||||
|
{
|
||||||
|
cp.supportsFence = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::endOfContinuousUpdates()
|
||||||
|
{
|
||||||
|
cp.supportsContinuousUpdates = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::supportsQEMUKeyEvent()
|
||||||
|
{
|
||||||
|
cp.supportsQEMUKeyEvent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::framebufferUpdateStart()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::framebufferUpdateEnd()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::setLEDState(unsigned int state)
|
||||||
|
{
|
||||||
|
cp.setLEDState(state);
|
||||||
|
}
|
78
common/rfb/CMsgHandler.h
Normal file
78
common/rfb/CMsgHandler.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2009-2011 Pierre Ossman for Cendio AB
|
||||||
|
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CMsgHandler - class to handle incoming messages on the client side.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RFB_CMSGHANDLER_H__
|
||||||
|
#define __RFB_CMSGHANDLER_H__
|
||||||
|
|
||||||
|
#include <rdr/types.h>
|
||||||
|
#include <rfb/Pixel.h>
|
||||||
|
#include <rfb/ConnParams.h>
|
||||||
|
#include <rfb/Rect.h>
|
||||||
|
#include <rfb/ScreenSet.h>
|
||||||
|
|
||||||
|
namespace rdr { class InStream; }
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class CMsgHandler {
|
||||||
|
public:
|
||||||
|
CMsgHandler();
|
||||||
|
virtual ~CMsgHandler();
|
||||||
|
|
||||||
|
// The following methods are called as corresponding messages are read. A
|
||||||
|
// derived class should override these methods as desired. Note that for
|
||||||
|
// the setDesktopSize(), setExtendedDesktopSize(), setPixelFormat() and
|
||||||
|
// setName() methods, a derived class should call on to CMsgHandler's
|
||||||
|
// methods to set the members of cp appropriately.
|
||||||
|
|
||||||
|
virtual void setDesktopSize(int w, int h);
|
||||||
|
virtual void setExtendedDesktopSize(unsigned reason, unsigned result,
|
||||||
|
int w, int h,
|
||||||
|
const ScreenSet& layout);
|
||||||
|
virtual void setCursor(int width, int height, const Point& hotspot,
|
||||||
|
const rdr::U8* data) = 0;
|
||||||
|
virtual void setPixelFormat(const PixelFormat& pf);
|
||||||
|
virtual void setName(const char* name);
|
||||||
|
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
|
||||||
|
virtual void endOfContinuousUpdates();
|
||||||
|
virtual void supportsQEMUKeyEvent();
|
||||||
|
virtual void serverInit() = 0;
|
||||||
|
|
||||||
|
virtual void readAndDecodeRect(const Rect& r, int encoding,
|
||||||
|
ModifiablePixelBuffer* pb) = 0;
|
||||||
|
|
||||||
|
virtual void framebufferUpdateStart();
|
||||||
|
virtual void framebufferUpdateEnd();
|
||||||
|
virtual void dataRect(const Rect& r, int encoding) = 0;
|
||||||
|
|
||||||
|
virtual void setColourMapEntries(int firstColour, int nColours,
|
||||||
|
rdr::U16* rgbs) = 0;
|
||||||
|
virtual void bell() = 0;
|
||||||
|
virtual void serverCutText(const char* str, rdr::U32 len) = 0;
|
||||||
|
|
||||||
|
virtual void setLEDState(unsigned int state);
|
||||||
|
|
||||||
|
ConnParams cp;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
398
common/rfb/CMsgReader.cxx
Normal file
398
common/rfb/CMsgReader.cxx
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2009-2017 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rfb/msgTypes.h>
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <rfb/Exception.h>
|
||||||
|
#include <rfb/util.h>
|
||||||
|
#include <rfb/CMsgHandler.h>
|
||||||
|
#include <rfb/CMsgReader.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
CMsgReader::CMsgReader(CMsgHandler* handler_, rdr::InStream* is_)
|
||||||
|
: imageBufIdealSize(0), handler(handler_), is(is_),
|
||||||
|
nUpdateRectsLeft(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CMsgReader::~CMsgReader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readServerInit()
|
||||||
|
{
|
||||||
|
int width = is->readU16();
|
||||||
|
int height = is->readU16();
|
||||||
|
handler->setDesktopSize(width, height);
|
||||||
|
PixelFormat pf;
|
||||||
|
pf.read(is);
|
||||||
|
handler->setPixelFormat(pf);
|
||||||
|
CharArray name(is->readString());
|
||||||
|
handler->setName(name.buf);
|
||||||
|
handler->serverInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readMsg()
|
||||||
|
{
|
||||||
|
if (nUpdateRectsLeft == 0) {
|
||||||
|
int type = is->readU8();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case msgTypeSetColourMapEntries:
|
||||||
|
readSetColourMapEntries();
|
||||||
|
break;
|
||||||
|
case msgTypeBell:
|
||||||
|
readBell();
|
||||||
|
break;
|
||||||
|
case msgTypeServerCutText:
|
||||||
|
readServerCutText();
|
||||||
|
break;
|
||||||
|
case msgTypeFramebufferUpdate:
|
||||||
|
readFramebufferUpdate();
|
||||||
|
break;
|
||||||
|
case msgTypeServerFence:
|
||||||
|
readFence();
|
||||||
|
break;
|
||||||
|
case msgTypeEndOfContinuousUpdates:
|
||||||
|
readEndOfContinuousUpdates();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown message type %d\n", type);
|
||||||
|
throw Exception("unknown message type");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int x = is->readU16();
|
||||||
|
int y = is->readU16();
|
||||||
|
int w = is->readU16();
|
||||||
|
int h = is->readU16();
|
||||||
|
int encoding = is->readS32();
|
||||||
|
|
||||||
|
switch (encoding) {
|
||||||
|
case pseudoEncodingLastRect:
|
||||||
|
nUpdateRectsLeft = 1; // this rectangle is the last one
|
||||||
|
break;
|
||||||
|
case pseudoEncodingXCursor:
|
||||||
|
readSetXCursor(w, h, Point(x,y));
|
||||||
|
break;
|
||||||
|
case pseudoEncodingCursor:
|
||||||
|
readSetCursor(w, h, Point(x,y));
|
||||||
|
break;
|
||||||
|
case pseudoEncodingCursorWithAlpha:
|
||||||
|
readSetCursorWithAlpha(w, h, Point(x,y));
|
||||||
|
break;
|
||||||
|
case pseudoEncodingDesktopName:
|
||||||
|
readSetDesktopName(x, y, w, h);
|
||||||
|
break;
|
||||||
|
case pseudoEncodingDesktopSize:
|
||||||
|
handler->setDesktopSize(w, h);
|
||||||
|
break;
|
||||||
|
case pseudoEncodingExtendedDesktopSize:
|
||||||
|
readExtendedDesktopSize(x, y, w, h);
|
||||||
|
break;
|
||||||
|
case pseudoEncodingLEDState:
|
||||||
|
readLEDState();
|
||||||
|
case pseudoEncodingQEMUKeyEvent:
|
||||||
|
handler->supportsQEMUKeyEvent();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
readRect(Rect(x, y, x+w, y+h), encoding);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
nUpdateRectsLeft--;
|
||||||
|
if (nUpdateRectsLeft == 0)
|
||||||
|
handler->framebufferUpdateEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readSetColourMapEntries()
|
||||||
|
{
|
||||||
|
is->skip(1);
|
||||||
|
int firstColour = is->readU16();
|
||||||
|
int nColours = is->readU16();
|
||||||
|
rdr::U16Array rgbs(nColours * 3);
|
||||||
|
for (int i = 0; i < nColours * 3; i++)
|
||||||
|
rgbs.buf[i] = is->readU16();
|
||||||
|
handler->setColourMapEntries(firstColour, nColours, rgbs.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readBell()
|
||||||
|
{
|
||||||
|
handler->bell();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readServerCutText()
|
||||||
|
{
|
||||||
|
is->skip(3);
|
||||||
|
rdr::U32 len = is->readU32();
|
||||||
|
if (len > 256*1024) {
|
||||||
|
is->skip(len);
|
||||||
|
fprintf(stderr,"cut text too long (%d bytes) - ignoring\n",len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CharArray ca(len+1);
|
||||||
|
ca.buf[len] = 0;
|
||||||
|
is->readBytes(ca.buf, len);
|
||||||
|
handler->serverCutText(ca.buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readFence()
|
||||||
|
{
|
||||||
|
rdr::U32 flags;
|
||||||
|
rdr::U8 len;
|
||||||
|
char data[64];
|
||||||
|
|
||||||
|
is->skip(3);
|
||||||
|
|
||||||
|
flags = is->readU32();
|
||||||
|
|
||||||
|
len = is->readU8();
|
||||||
|
if (len > sizeof(data)) {
|
||||||
|
fprintf(stderr, "Ignoring fence with too large payload\n");
|
||||||
|
is->skip(len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
is->readBytes(data, len);
|
||||||
|
|
||||||
|
handler->fence(flags, len, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readEndOfContinuousUpdates()
|
||||||
|
{
|
||||||
|
handler->endOfContinuousUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readFramebufferUpdate()
|
||||||
|
{
|
||||||
|
is->skip(1);
|
||||||
|
nUpdateRectsLeft = is->readU16();
|
||||||
|
handler->framebufferUpdateStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readRect(const Rect& r, int encoding)
|
||||||
|
{
|
||||||
|
if ((r.br.x > handler->cp.width) || (r.br.y > handler->cp.height)) {
|
||||||
|
fprintf(stderr, "Rect too big: %dx%d at %d,%d exceeds %dx%d\n",
|
||||||
|
r.width(), r.height(), r.tl.x, r.tl.y,
|
||||||
|
handler->cp.width, handler->cp.height);
|
||||||
|
throw Exception("Rect too big");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.is_empty())
|
||||||
|
fprintf(stderr, "Warning: zero size rect\n");
|
||||||
|
|
||||||
|
handler->dataRect(r, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
|
||||||
|
{
|
||||||
|
if (width > maxCursorSize || height > maxCursorSize)
|
||||||
|
throw Exception("Too big cursor");
|
||||||
|
|
||||||
|
rdr::U8 buf[width*height*4];
|
||||||
|
|
||||||
|
if (width * height > 0) {
|
||||||
|
rdr::U8 pr, pg, pb;
|
||||||
|
rdr::U8 sr, sg, sb;
|
||||||
|
int data_len = ((width+7)/8) * height;
|
||||||
|
int mask_len = ((width+7)/8) * height;
|
||||||
|
rdr::U8Array data(data_len);
|
||||||
|
rdr::U8Array mask(mask_len);
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
rdr::U8* out;
|
||||||
|
|
||||||
|
pr = is->readU8();
|
||||||
|
pg = is->readU8();
|
||||||
|
pb = is->readU8();
|
||||||
|
|
||||||
|
sr = is->readU8();
|
||||||
|
sg = is->readU8();
|
||||||
|
sb = is->readU8();
|
||||||
|
|
||||||
|
is->readBytes(data.buf, data_len);
|
||||||
|
is->readBytes(mask.buf, mask_len);
|
||||||
|
|
||||||
|
int maskBytesPerRow = (width+7)/8;
|
||||||
|
out = buf;
|
||||||
|
for (y = 0;y < height;y++) {
|
||||||
|
for (x = 0;x < width;x++) {
|
||||||
|
int byte = y * maskBytesPerRow + x / 8;
|
||||||
|
int bit = 7 - x % 8;
|
||||||
|
|
||||||
|
if (data.buf[byte] & (1 << bit)) {
|
||||||
|
out[0] = pr;
|
||||||
|
out[1] = pg;
|
||||||
|
out[2] = pb;
|
||||||
|
} else {
|
||||||
|
out[0] = sr;
|
||||||
|
out[1] = sg;
|
||||||
|
out[2] = sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask.buf[byte] & (1 << bit))
|
||||||
|
out[3] = 255;
|
||||||
|
else
|
||||||
|
out[3] = 0;
|
||||||
|
|
||||||
|
out += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->setCursor(width, height, hotspot, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
|
||||||
|
{
|
||||||
|
if (width > maxCursorSize || height > maxCursorSize)
|
||||||
|
throw Exception("Too big cursor");
|
||||||
|
|
||||||
|
int data_len = width * height * (handler->cp.pf().bpp/8);
|
||||||
|
int mask_len = ((width+7)/8) * height;
|
||||||
|
rdr::U8Array data(data_len);
|
||||||
|
rdr::U8Array mask(mask_len);
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
rdr::U8 buf[width*height*4];
|
||||||
|
rdr::U8* in;
|
||||||
|
rdr::U8* out;
|
||||||
|
|
||||||
|
is->readBytes(data.buf, data_len);
|
||||||
|
is->readBytes(mask.buf, mask_len);
|
||||||
|
|
||||||
|
int maskBytesPerRow = (width+7)/8;
|
||||||
|
in = data.buf;
|
||||||
|
out = buf;
|
||||||
|
for (y = 0;y < height;y++) {
|
||||||
|
for (x = 0;x < width;x++) {
|
||||||
|
int byte = y * maskBytesPerRow + x / 8;
|
||||||
|
int bit = 7 - x % 8;
|
||||||
|
|
||||||
|
handler->cp.pf().rgbFromBuffer(out, in, 1);
|
||||||
|
|
||||||
|
if (mask.buf[byte] & (1 << bit))
|
||||||
|
out[3] = 255;
|
||||||
|
else
|
||||||
|
out[3] = 0;
|
||||||
|
|
||||||
|
in += handler->cp.pf().bpp/8;
|
||||||
|
out += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->setCursor(width, height, hotspot, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hotspot)
|
||||||
|
{
|
||||||
|
if (width > maxCursorSize || height > maxCursorSize)
|
||||||
|
throw Exception("Too big cursor");
|
||||||
|
|
||||||
|
int encoding;
|
||||||
|
|
||||||
|
const PixelFormat rgbaPF(32, 32, false, true, 255, 255, 255, 16, 8, 0);
|
||||||
|
ManagedPixelBuffer pb(rgbaPF, width, height);
|
||||||
|
PixelFormat origPF;
|
||||||
|
|
||||||
|
rdr::U8* buf;
|
||||||
|
int stride;
|
||||||
|
|
||||||
|
encoding = is->readS32();
|
||||||
|
|
||||||
|
origPF = handler->cp.pf();
|
||||||
|
handler->cp.setPF(rgbaPF);
|
||||||
|
handler->readAndDecodeRect(pb.getRect(), encoding, &pb);
|
||||||
|
handler->cp.setPF(origPF);
|
||||||
|
|
||||||
|
// On-wire data has pre-multiplied alpha, but we store it
|
||||||
|
// non-pre-multiplied
|
||||||
|
buf = pb.getBufferRW(pb.getRect(), &stride);
|
||||||
|
assert(stride == width);
|
||||||
|
|
||||||
|
for (int i = 0;i < pb.area();i++) {
|
||||||
|
rdr::U8 alpha;
|
||||||
|
|
||||||
|
alpha = buf[3];
|
||||||
|
if (alpha == 0)
|
||||||
|
alpha = 1; // Avoid division by zero
|
||||||
|
|
||||||
|
buf[0] = (unsigned)buf[0] * 255/alpha;
|
||||||
|
buf[1] = (unsigned)buf[1] * 255/alpha;
|
||||||
|
buf[2] = (unsigned)buf[2] * 255/alpha;
|
||||||
|
|
||||||
|
buf += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
pb.commitBufferRW(pb.getRect());
|
||||||
|
|
||||||
|
handler->setCursor(width, height, hotspot,
|
||||||
|
pb.getBuffer(pb.getRect(), &stride));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readSetDesktopName(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
char* name = is->readString();
|
||||||
|
|
||||||
|
if (x || y || w || h) {
|
||||||
|
fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n");
|
||||||
|
} else {
|
||||||
|
handler->setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
unsigned int screens, i;
|
||||||
|
rdr::U32 id, flags;
|
||||||
|
int sx, sy, sw, sh;
|
||||||
|
ScreenSet layout;
|
||||||
|
|
||||||
|
screens = is->readU8();
|
||||||
|
is->skip(3);
|
||||||
|
|
||||||
|
for (i = 0;i < screens;i++) {
|
||||||
|
id = is->readU32();
|
||||||
|
sx = is->readU16();
|
||||||
|
sy = is->readU16();
|
||||||
|
sw = is->readU16();
|
||||||
|
sh = is->readU16();
|
||||||
|
flags = is->readU32();
|
||||||
|
|
||||||
|
layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->setExtendedDesktopSize(x, y, w, h, layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgReader::readLEDState()
|
||||||
|
{
|
||||||
|
rdr::U8 state;
|
||||||
|
|
||||||
|
state = is->readU8();
|
||||||
|
|
||||||
|
handler->setLEDState(state);
|
||||||
|
}
|
77
common/rfb/CMsgReader.h
Normal file
77
common/rfb/CMsgReader.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2009-2014 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CMsgReader - class for reading RFB messages on the server side
|
||||||
|
// (i.e. messages from client to server).
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RFB_CMSGREADER_H__
|
||||||
|
#define __RFB_CMSGREADER_H__
|
||||||
|
|
||||||
|
#include <rdr/types.h>
|
||||||
|
|
||||||
|
#include <rfb/Rect.h>
|
||||||
|
#include <rfb/encodings.h>
|
||||||
|
|
||||||
|
namespace rdr { class InStream; }
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
class CMsgHandler;
|
||||||
|
struct Rect;
|
||||||
|
|
||||||
|
class CMsgReader {
|
||||||
|
public:
|
||||||
|
CMsgReader(CMsgHandler* handler, rdr::InStream* is);
|
||||||
|
virtual ~CMsgReader();
|
||||||
|
|
||||||
|
void readServerInit();
|
||||||
|
|
||||||
|
// readMsg() reads a message, calling the handler as appropriate.
|
||||||
|
void readMsg();
|
||||||
|
|
||||||
|
rdr::InStream* getInStream() { return is; }
|
||||||
|
|
||||||
|
int imageBufIdealSize;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void readSetColourMapEntries();
|
||||||
|
void readBell();
|
||||||
|
void readServerCutText();
|
||||||
|
void readFence();
|
||||||
|
void readEndOfContinuousUpdates();
|
||||||
|
|
||||||
|
void readFramebufferUpdate();
|
||||||
|
|
||||||
|
void readRect(const Rect& r, int encoding);
|
||||||
|
|
||||||
|
void readSetXCursor(int width, int height, const Point& hotspot);
|
||||||
|
void readSetCursor(int width, int height, const Point& hotspot);
|
||||||
|
void readSetCursorWithAlpha(int width, int height, const Point& hotspot);
|
||||||
|
void readSetDesktopName(int x, int y, int w, int h);
|
||||||
|
void readExtendedDesktopSize(int x, int y, int w, int h);
|
||||||
|
void readLEDState();
|
||||||
|
|
||||||
|
CMsgHandler* handler;
|
||||||
|
rdr::InStream* is;
|
||||||
|
int nUpdateRectsLeft;
|
||||||
|
|
||||||
|
static const int maxCursorSize = 256;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
276
common/rfb/CMsgWriter.cxx
Normal file
276
common/rfb/CMsgWriter.cxx
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2009-2014 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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 <rdr/OutStream.h>
|
||||||
|
#include <rfb/msgTypes.h>
|
||||||
|
#include <rfb/fenceTypes.h>
|
||||||
|
#include <rfb/encodings.h>
|
||||||
|
#include <rfb/qemuTypes.h>
|
||||||
|
#include <rfb/Exception.h>
|
||||||
|
#include <rfb/PixelFormat.h>
|
||||||
|
#include <rfb/Rect.h>
|
||||||
|
#include <rfb/ConnParams.h>
|
||||||
|
#include <rfb/Decoder.h>
|
||||||
|
#include <rfb/CMsgWriter.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
CMsgWriter::CMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
|
||||||
|
: cp(cp_), os(os_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CMsgWriter::~CMsgWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeClientInit(bool shared)
|
||||||
|
{
|
||||||
|
os->writeU8(shared);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
|
||||||
|
{
|
||||||
|
startMsg(msgTypeSetPixelFormat);
|
||||||
|
os->pad(3);
|
||||||
|
pf.write(os);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
|
||||||
|
{
|
||||||
|
startMsg(msgTypeSetEncodings);
|
||||||
|
os->skip(1);
|
||||||
|
os->writeU16(nEncodings);
|
||||||
|
for (int i = 0; i < nEncodings; i++)
|
||||||
|
os->writeU32(encodings[i]);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask for encodings based on which decoders are supported. Assumes higher
|
||||||
|
// encoding numbers are more desirable.
|
||||||
|
|
||||||
|
void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
|
||||||
|
{
|
||||||
|
int nEncodings = 0;
|
||||||
|
rdr::U32 encodings[encodingMax+3];
|
||||||
|
|
||||||
|
if (cp->supportsLocalCursor) {
|
||||||
|
encodings[nEncodings++] = pseudoEncodingCursorWithAlpha;
|
||||||
|
encodings[nEncodings++] = pseudoEncodingCursor;
|
||||||
|
encodings[nEncodings++] = pseudoEncodingXCursor;
|
||||||
|
}
|
||||||
|
if (cp->supportsDesktopResize)
|
||||||
|
encodings[nEncodings++] = pseudoEncodingDesktopSize;
|
||||||
|
if (cp->supportsExtendedDesktopSize)
|
||||||
|
encodings[nEncodings++] = pseudoEncodingExtendedDesktopSize;
|
||||||
|
if (cp->supportsDesktopRename)
|
||||||
|
encodings[nEncodings++] = pseudoEncodingDesktopName;
|
||||||
|
if (cp->supportsLEDState)
|
||||||
|
encodings[nEncodings++] = pseudoEncodingLEDState;
|
||||||
|
|
||||||
|
encodings[nEncodings++] = pseudoEncodingLastRect;
|
||||||
|
encodings[nEncodings++] = pseudoEncodingContinuousUpdates;
|
||||||
|
encodings[nEncodings++] = pseudoEncodingFence;
|
||||||
|
encodings[nEncodings++] = pseudoEncodingQEMUKeyEvent;
|
||||||
|
|
||||||
|
if (Decoder::supported(preferredEncoding)) {
|
||||||
|
encodings[nEncodings++] = preferredEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useCopyRect) {
|
||||||
|
encodings[nEncodings++] = encodingCopyRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prefer encodings in this order:
|
||||||
|
*
|
||||||
|
* Tight, ZRLE, Hextile, *
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((preferredEncoding != encodingTight) &&
|
||||||
|
Decoder::supported(encodingTight))
|
||||||
|
encodings[nEncodings++] = encodingTight;
|
||||||
|
|
||||||
|
if ((preferredEncoding != encodingZRLE) &&
|
||||||
|
Decoder::supported(encodingZRLE))
|
||||||
|
encodings[nEncodings++] = encodingZRLE;
|
||||||
|
|
||||||
|
if ((preferredEncoding != encodingHextile) &&
|
||||||
|
Decoder::supported(encodingHextile))
|
||||||
|
encodings[nEncodings++] = encodingHextile;
|
||||||
|
|
||||||
|
// Remaining encodings
|
||||||
|
for (int i = encodingMax; i >= 0; i--) {
|
||||||
|
switch (i) {
|
||||||
|
case encodingCopyRect:
|
||||||
|
case encodingTight:
|
||||||
|
case encodingZRLE:
|
||||||
|
case encodingHextile:
|
||||||
|
/* These have already been sent earlier */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ((i != preferredEncoding) && Decoder::supported(i))
|
||||||
|
encodings[nEncodings++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp->compressLevel >= 0 && cp->compressLevel <= 9)
|
||||||
|
encodings[nEncodings++] = pseudoEncodingCompressLevel0 + cp->compressLevel;
|
||||||
|
if (cp->qualityLevel >= 0 && cp->qualityLevel <= 9)
|
||||||
|
encodings[nEncodings++] = pseudoEncodingQualityLevel0 + cp->qualityLevel;
|
||||||
|
|
||||||
|
writeSetEncodings(nEncodings, encodings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeSetDesktopSize(int width, int height,
|
||||||
|
const ScreenSet& layout)
|
||||||
|
{
|
||||||
|
if (!cp->supportsSetDesktopSize)
|
||||||
|
throw Exception("Server does not support SetDesktopSize");
|
||||||
|
|
||||||
|
startMsg(msgTypeSetDesktopSize);
|
||||||
|
os->pad(1);
|
||||||
|
|
||||||
|
os->writeU16(width);
|
||||||
|
os->writeU16(height);
|
||||||
|
|
||||||
|
os->writeU8(layout.num_screens());
|
||||||
|
os->pad(1);
|
||||||
|
|
||||||
|
ScreenSet::const_iterator iter;
|
||||||
|
for (iter = layout.begin();iter != layout.end();++iter) {
|
||||||
|
os->writeU32(iter->id);
|
||||||
|
os->writeU16(iter->dimensions.tl.x);
|
||||||
|
os->writeU16(iter->dimensions.tl.y);
|
||||||
|
os->writeU16(iter->dimensions.width());
|
||||||
|
os->writeU16(iter->dimensions.height());
|
||||||
|
os->writeU32(iter->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
|
||||||
|
{
|
||||||
|
startMsg(msgTypeFramebufferUpdateRequest);
|
||||||
|
os->writeU8(incremental);
|
||||||
|
os->writeU16(r.tl.x);
|
||||||
|
os->writeU16(r.tl.y);
|
||||||
|
os->writeU16(r.width());
|
||||||
|
os->writeU16(r.height());
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeEnableContinuousUpdates(bool enable,
|
||||||
|
int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
if (!cp->supportsContinuousUpdates)
|
||||||
|
throw Exception("Server does not support continuous updates");
|
||||||
|
|
||||||
|
startMsg(msgTypeEnableContinuousUpdates);
|
||||||
|
|
||||||
|
os->writeU8(!!enable);
|
||||||
|
|
||||||
|
os->writeU16(x);
|
||||||
|
os->writeU16(y);
|
||||||
|
os->writeU16(w);
|
||||||
|
os->writeU16(h);
|
||||||
|
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
|
||||||
|
{
|
||||||
|
if (!cp->supportsFence)
|
||||||
|
throw Exception("Server does not support fences");
|
||||||
|
if (len > 64)
|
||||||
|
throw Exception("Too large fence payload");
|
||||||
|
if ((flags & ~fenceFlagsSupported) != 0)
|
||||||
|
throw Exception("Unknown fence flags");
|
||||||
|
|
||||||
|
startMsg(msgTypeClientFence);
|
||||||
|
os->pad(3);
|
||||||
|
|
||||||
|
os->writeU32(flags);
|
||||||
|
|
||||||
|
os->writeU8(len);
|
||||||
|
os->writeBytes(data, len);
|
||||||
|
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
|
||||||
|
{
|
||||||
|
if (!cp->supportsQEMUKeyEvent || !keycode) {
|
||||||
|
/* This event isn't meaningful without a valid keysym */
|
||||||
|
if (!keysym)
|
||||||
|
return;
|
||||||
|
|
||||||
|
startMsg(msgTypeKeyEvent);
|
||||||
|
os->writeU8(down);
|
||||||
|
os->pad(2);
|
||||||
|
os->writeU32(keysym);
|
||||||
|
endMsg();
|
||||||
|
} else {
|
||||||
|
startMsg(msgTypeQEMUClientMessage);
|
||||||
|
os->writeU8(qemuExtendedKeyEvent);
|
||||||
|
os->writeU16(down);
|
||||||
|
os->writeU32(keysym);
|
||||||
|
os->writeU32(keycode);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CMsgWriter::writePointerEvent(const Point& pos, int buttonMask)
|
||||||
|
{
|
||||||
|
Point p(pos);
|
||||||
|
if (p.x < 0) p.x = 0;
|
||||||
|
if (p.y < 0) p.y = 0;
|
||||||
|
if (p.x >= cp->width) p.x = cp->width - 1;
|
||||||
|
if (p.y >= cp->height) p.y = cp->height - 1;
|
||||||
|
|
||||||
|
startMsg(msgTypePointerEvent);
|
||||||
|
os->writeU8(buttonMask);
|
||||||
|
os->writeU16(p.x);
|
||||||
|
os->writeU16(p.y);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len)
|
||||||
|
{
|
||||||
|
startMsg(msgTypeClientCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeU32(len);
|
||||||
|
os->writeBytes(str, len);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::startMsg(int type)
|
||||||
|
{
|
||||||
|
os->writeU8(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::endMsg()
|
||||||
|
{
|
||||||
|
os->flush();
|
||||||
|
}
|
67
common/rfb/CMsgWriter.h
Normal file
67
common/rfb/CMsgWriter.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2009-2014 Pierre Ossman for Cendio AB
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CMsgWriter - class for writing RFB messages on the server side.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RFB_CMSGWRITER_H__
|
||||||
|
#define __RFB_CMSGWRITER_H__
|
||||||
|
|
||||||
|
#include <rdr/types.h>
|
||||||
|
|
||||||
|
namespace rdr { class OutStream; }
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class PixelFormat;
|
||||||
|
class ConnParams;
|
||||||
|
struct ScreenSet;
|
||||||
|
struct Point;
|
||||||
|
struct Rect;
|
||||||
|
|
||||||
|
class CMsgWriter {
|
||||||
|
public:
|
||||||
|
CMsgWriter(ConnParams* cp, rdr::OutStream* os);
|
||||||
|
virtual ~CMsgWriter();
|
||||||
|
|
||||||
|
void writeClientInit(bool shared);
|
||||||
|
|
||||||
|
void writeSetPixelFormat(const PixelFormat& pf);
|
||||||
|
void writeSetEncodings(int nEncodings, rdr::U32* encodings);
|
||||||
|
void writeSetEncodings(int preferredEncoding, bool useCopyRect);
|
||||||
|
void writeSetDesktopSize(int width, int height, const ScreenSet& layout);
|
||||||
|
|
||||||
|
void writeFramebufferUpdateRequest(const Rect& r,bool incremental);
|
||||||
|
void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h);
|
||||||
|
|
||||||
|
void writeFence(rdr::U32 flags, unsigned len, const char data[]);
|
||||||
|
|
||||||
|
void writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
|
||||||
|
void writePointerEvent(const Point& pos, int buttonMask);
|
||||||
|
void writeClientCutText(const char* str, rdr::U32 len);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void startMsg(int type);
|
||||||
|
void endMsg();
|
||||||
|
|
||||||
|
ConnParams* cp;
|
||||||
|
rdr::OutStream* os;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
61
common/rfb/CSecurity.h
Normal file
61
common/rfb/CSecurity.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CSecurity - class on the client side for handling security handshaking. A
|
||||||
|
// derived class for a particular security type overrides the processMsg()
|
||||||
|
// method.
|
||||||
|
|
||||||
|
// processMsg() is called first when the security type has been decided on, and
|
||||||
|
// will keep being called whenever there is data to read from the server. It
|
||||||
|
// should return false when it needs more data, or true when the security
|
||||||
|
// handshaking is over and we are now waiting for the SecurityResult message
|
||||||
|
// from the server. In the event of failure a suitable exception should be
|
||||||
|
// thrown.
|
||||||
|
//
|
||||||
|
// Note that the first time processMsg() is called, there is no guarantee that
|
||||||
|
// there is any data to read from the CConnection's InStream, but subsequent
|
||||||
|
// calls guarantee there is at least one byte which can be read without
|
||||||
|
// blocking.
|
||||||
|
//
|
||||||
|
// description is a string describing the level of encryption applied to the
|
||||||
|
// session, or null if no encryption will be used.
|
||||||
|
|
||||||
|
#ifndef __RFB_CSECURITY_H__
|
||||||
|
#define __RFB_CSECURITY_H__
|
||||||
|
|
||||||
|
#include <rfb/UserPasswdGetter.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
class CConnection;
|
||||||
|
class CSecurity {
|
||||||
|
public:
|
||||||
|
virtual ~CSecurity() {}
|
||||||
|
virtual bool processMsg(CConnection* cc)=0;
|
||||||
|
virtual void destroy() { delete this; }
|
||||||
|
virtual int getType() const = 0;
|
||||||
|
virtual const char* description() const = 0;
|
||||||
|
virtual bool isSecure() const { return false; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use variable directly instead of dumb get/set methods.
|
||||||
|
* It MUST be set by viewer.
|
||||||
|
*/
|
||||||
|
static UserPasswdGetter *upg;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
37
common/rfb/CSecurityNone.h
Normal file
37
common/rfb/CSecurityNone.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CSecurityNone.h
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __CSECURITYNONE_H__
|
||||||
|
#define __CSECURITYNONE_H__
|
||||||
|
|
||||||
|
#include <rfb/Security.h>
|
||||||
|
#include <rfb/CSecurity.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class CSecurityNone : public CSecurity {
|
||||||
|
public:
|
||||||
|
virtual bool processMsg(CConnection* cc) { return true; }
|
||||||
|
virtual int getType() const {return secTypeNone;}
|
||||||
|
virtual const char* description() const {return "No Encryption";}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
45
common/rfb/CSecurityPlain.cxx
Normal file
45
common/rfb/CSecurityPlain.cxx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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/CConnection.h>
|
||||||
|
#include <rfb/CSecurityPlain.h>
|
||||||
|
#include <rfb/UserPasswdGetter.h>
|
||||||
|
#include <rfb/util.h>
|
||||||
|
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
bool CSecurityPlain::processMsg(CConnection* cc)
|
||||||
|
{
|
||||||
|
rdr::OutStream* os = cc->getOutStream();
|
||||||
|
|
||||||
|
CharArray username;
|
||||||
|
CharArray password;
|
||||||
|
|
||||||
|
(CSecurity::upg)->getUserPasswd(cc->isSecure(), &username.buf, &password.buf);
|
||||||
|
|
||||||
|
// Return the response to the server
|
||||||
|
os->writeU32(strlen(username.buf));
|
||||||
|
os->writeU32(strlen(password.buf));
|
||||||
|
os->writeBytes(username.buf,strlen(username.buf));
|
||||||
|
os->writeBytes(password.buf,strlen(password.buf));
|
||||||
|
os->flush();
|
||||||
|
return true;
|
||||||
|
}
|
35
common/rfb/CSecurityPlain.h
Normal file
35
common/rfb/CSecurityPlain.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 __RFB_CSECURITYPLAIN_H__
|
||||||
|
#define __RFB_CSECURITYPLAIN_H__
|
||||||
|
|
||||||
|
#include <rfb/CSecurity.h>
|
||||||
|
#include <rfb/Security.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class CSecurityPlain : public CSecurity {
|
||||||
|
public:
|
||||||
|
CSecurityPlain() {}
|
||||||
|
virtual bool processMsg(CConnection* cc);
|
||||||
|
virtual int getType() const { return secTypePlain; }
|
||||||
|
virtual const char* description() const { return "ask for username and password"; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
74
common/rfb/CSecurityStack.cxx
Normal file
74
common/rfb/CSecurityStack.cxx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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/CSecurityStack.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
CSecurityStack::CSecurityStack(int Type, const char*Name, CSecurity* s0,
|
||||||
|
CSecurity* s1)
|
||||||
|
:name(Name),type(Type)
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
state0 = s0;
|
||||||
|
state1 = s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSecurityStack::~CSecurityStack()
|
||||||
|
{
|
||||||
|
if (state0)
|
||||||
|
delete state0;
|
||||||
|
if (state1)
|
||||||
|
delete state1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSecurityStack::processMsg(CConnection* cc)
|
||||||
|
{
|
||||||
|
bool res=true;
|
||||||
|
if (state == 0) {
|
||||||
|
if (state0)
|
||||||
|
res = state0->processMsg(cc);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == 1) {
|
||||||
|
if(state1)
|
||||||
|
res = state1->processMsg(cc);
|
||||||
|
|
||||||
|
if(!res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSecurityStack::isSecure() const
|
||||||
|
{
|
||||||
|
if (state0 && state0->isSecure())
|
||||||
|
return true;
|
||||||
|
if (state == 1 && state1 && state1->isSecure())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
44
common/rfb/CSecurityStack.h
Normal file
44
common/rfb/CSecurityStack.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2006 OCCAM Financial Technology
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 __RFB_CSECURITYSTACK_H__
|
||||||
|
#define __RFB_CSECURITYSTACK_H__
|
||||||
|
|
||||||
|
#include <rfb/CSecurity.h>
|
||||||
|
#include <rfb/Security.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class CSecurityStack : public CSecurity {
|
||||||
|
public:
|
||||||
|
CSecurityStack(int Type, const char *Name, CSecurity* s0 = 0, CSecurity* s1 = 0);
|
||||||
|
~CSecurityStack();
|
||||||
|
virtual bool processMsg(CConnection* cc);
|
||||||
|
virtual int getType() const {return type;};
|
||||||
|
virtual const char* description() const {return name;}
|
||||||
|
virtual bool isSecure() const;
|
||||||
|
protected:
|
||||||
|
int state;
|
||||||
|
CSecurity* state0;
|
||||||
|
CSecurity* state1;
|
||||||
|
const char* name;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
445
common/rfb/CSecurityTLS.cxx
Normal file
445
common/rfb/CSecurityTLS.cxx
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Red Hat Inc.
|
||||||
|
* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
* Copyright (C) 2010 m-privacy GmbH
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#ifndef HAVE_GNUTLS
|
||||||
|
#error "This header should not be compiled without HAVE_GNUTLS defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rfb/CSecurityTLS.h>
|
||||||
|
#include <rfb/SSecurityVeNCrypt.h>
|
||||||
|
#include <rfb/CConnection.h>
|
||||||
|
#include <rfb/LogWriter.h>
|
||||||
|
#include <rfb/Exception.h>
|
||||||
|
#include <rfb/UserMsgBox.h>
|
||||||
|
#include <rdr/TLSInStream.h>
|
||||||
|
#include <rdr/TLSOutStream.h>
|
||||||
|
#include <os/os.h>
|
||||||
|
|
||||||
|
#include <gnutls/x509.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNUTLS 2.6.5 and older didn't have some variables defined so don't use them.
|
||||||
|
* GNUTLS 1.X.X defined LIBGNUTLS_VERSION_NUMBER so treat it as "old" gnutls as
|
||||||
|
* well
|
||||||
|
*/
|
||||||
|
#if (defined(GNUTLS_VERSION_NUMBER) && GNUTLS_VERSION_NUMBER < 0x020606) || \
|
||||||
|
defined(LIBGNUTLS_VERSION_NUMBER)
|
||||||
|
#define WITHOUT_X509_TIMES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Ancient GNUTLS... */
|
||||||
|
#if !defined(GNUTLS_VERSION_NUMBER) && !defined(LIBGNUTLS_VERSION_NUMBER)
|
||||||
|
#define WITHOUT_X509_TIMES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
StringParameter CSecurityTLS::X509CA("X509CA", "X509 CA certificate", "", ConfViewer);
|
||||||
|
StringParameter CSecurityTLS::X509CRL("X509CRL", "X509 CRL file", "", ConfViewer);
|
||||||
|
|
||||||
|
static LogWriter vlog("TLS");
|
||||||
|
|
||||||
|
CSecurityTLS::CSecurityTLS(bool _anon) : session(0), anon_cred(0),
|
||||||
|
anon(_anon), fis(0), fos(0)
|
||||||
|
{
|
||||||
|
cafile = X509CA.getData();
|
||||||
|
crlfile = X509CRL.getData();
|
||||||
|
|
||||||
|
if (gnutls_global_init() != GNUTLS_E_SUCCESS)
|
||||||
|
throw AuthFailureException("gnutls_global_init failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSecurityTLS::setDefaults()
|
||||||
|
{
|
||||||
|
char* homeDir = NULL;
|
||||||
|
|
||||||
|
if (getvnchomedir(&homeDir) == -1) {
|
||||||
|
vlog.error("Could not obtain VNC home directory path");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(homeDir) + 1;
|
||||||
|
CharArray caDefault(len + 11);
|
||||||
|
CharArray crlDefault(len + 12);
|
||||||
|
sprintf(caDefault.buf, "%sx509_ca.pem", homeDir);
|
||||||
|
sprintf(crlDefault.buf, "%s509_crl.pem", homeDir);
|
||||||
|
delete [] homeDir;
|
||||||
|
|
||||||
|
if (!fileexists(caDefault.buf))
|
||||||
|
X509CA.setDefaultStr(strdup(caDefault.buf));
|
||||||
|
if (!fileexists(crlDefault.buf))
|
||||||
|
X509CRL.setDefaultStr(strdup(crlDefault.buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSecurityTLS::shutdown(bool needbye)
|
||||||
|
{
|
||||||
|
if (session && needbye)
|
||||||
|
if (gnutls_bye(session, GNUTLS_SHUT_RDWR) != GNUTLS_E_SUCCESS)
|
||||||
|
vlog.error("gnutls_bye failed");
|
||||||
|
|
||||||
|
if (anon_cred) {
|
||||||
|
gnutls_anon_free_client_credentials(anon_cred);
|
||||||
|
anon_cred = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert_cred) {
|
||||||
|
gnutls_certificate_free_credentials(cert_cred);
|
||||||
|
cert_cred = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
gnutls_deinit(session);
|
||||||
|
session = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSecurityTLS::~CSecurityTLS()
|
||||||
|
{
|
||||||
|
shutdown(true);
|
||||||
|
|
||||||
|
if (fis)
|
||||||
|
delete fis;
|
||||||
|
if (fos)
|
||||||
|
delete fos;
|
||||||
|
|
||||||
|
delete[] cafile;
|
||||||
|
delete[] crlfile;
|
||||||
|
|
||||||
|
gnutls_global_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSecurityTLS::processMsg(CConnection* cc)
|
||||||
|
{
|
||||||
|
rdr::InStream* is = cc->getInStream();
|
||||||
|
rdr::OutStream* os = cc->getOutStream();
|
||||||
|
client = cc;
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
if (!is->checkNoWait(1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (is->readU8() == 0) {
|
||||||
|
rdr::U32 result = is->readU32();
|
||||||
|
CharArray reason;
|
||||||
|
if (result == secResultFailed || result == secResultTooMany)
|
||||||
|
reason.buf = is->readString();
|
||||||
|
else
|
||||||
|
reason.buf = strDup("protocol error");
|
||||||
|
throw AuthFailureException(reason.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gnutls_init(&session, GNUTLS_CLIENT) != GNUTLS_E_SUCCESS)
|
||||||
|
throw AuthFailureException("gnutls_init failed");
|
||||||
|
|
||||||
|
if (gnutls_set_default_priority(session) != GNUTLS_E_SUCCESS)
|
||||||
|
throw AuthFailureException("gnutls_set_default_priority failed");
|
||||||
|
|
||||||
|
setParam();
|
||||||
|
}
|
||||||
|
|
||||||
|
rdr::TLSInStream *tlsis = new rdr::TLSInStream(is, session);
|
||||||
|
rdr::TLSOutStream *tlsos = new rdr::TLSOutStream(os, session);
|
||||||
|
|
||||||
|
int err;
|
||||||
|
err = gnutls_handshake(session);
|
||||||
|
if (err != GNUTLS_E_SUCCESS) {
|
||||||
|
delete tlsis;
|
||||||
|
delete tlsos;
|
||||||
|
|
||||||
|
if (!gnutls_error_is_fatal(err))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vlog.error("TLS Handshake failed: %s\n", gnutls_strerror (err));
|
||||||
|
shutdown(false);
|
||||||
|
throw AuthFailureException("TLS Handshake failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSession();
|
||||||
|
|
||||||
|
cc->setStreams(fis = tlsis, fos = tlsos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSecurityTLS::setParam()
|
||||||
|
{
|
||||||
|
static const char kx_anon_priority[] = ":+ANON-ECDH:+ANON-DH";
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
char *prio;
|
||||||
|
const char *err;
|
||||||
|
|
||||||
|
prio = (char*)malloc(strlen(Security::GnuTLSPriority) +
|
||||||
|
strlen(kx_anon_priority) + 1);
|
||||||
|
if (prio == NULL)
|
||||||
|
throw AuthFailureException("Not enough memory for GnuTLS priority string");
|
||||||
|
|
||||||
|
strcpy(prio, Security::GnuTLSPriority);
|
||||||
|
if (anon)
|
||||||
|
strcat(prio, kx_anon_priority);
|
||||||
|
|
||||||
|
ret = gnutls_priority_set_direct(session, prio, &err);
|
||||||
|
|
||||||
|
free(prio);
|
||||||
|
|
||||||
|
if (ret != GNUTLS_E_SUCCESS) {
|
||||||
|
if (ret == GNUTLS_E_INVALID_REQUEST)
|
||||||
|
vlog.error("GnuTLS priority syntax error at: %s", err);
|
||||||
|
throw AuthFailureException("gnutls_set_priority_direct failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anon) {
|
||||||
|
if (gnutls_anon_allocate_client_credentials(&anon_cred) != GNUTLS_E_SUCCESS)
|
||||||
|
throw AuthFailureException("gnutls_anon_allocate_client_credentials failed");
|
||||||
|
|
||||||
|
if (gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred) != GNUTLS_E_SUCCESS)
|
||||||
|
throw AuthFailureException("gnutls_credentials_set failed");
|
||||||
|
|
||||||
|
vlog.debug("Anonymous session has been set");
|
||||||
|
} else {
|
||||||
|
if (gnutls_certificate_allocate_credentials(&cert_cred) != GNUTLS_E_SUCCESS)
|
||||||
|
throw AuthFailureException("gnutls_certificate_allocate_credentials failed");
|
||||||
|
|
||||||
|
if (*cafile && gnutls_certificate_set_x509_trust_file(cert_cred,cafile,GNUTLS_X509_FMT_PEM) < 0)
|
||||||
|
throw AuthFailureException("load of CA cert failed");
|
||||||
|
|
||||||
|
/* Load previously saved certs */
|
||||||
|
char *homeDir = NULL;
|
||||||
|
int err;
|
||||||
|
if (getvnchomedir(&homeDir) == -1)
|
||||||
|
vlog.error("Could not obtain VNC home directory path");
|
||||||
|
else {
|
||||||
|
CharArray caSave(strlen(homeDir) + 19 + 1);
|
||||||
|
sprintf(caSave.buf, "%sx509_savedcerts.pem", homeDir);
|
||||||
|
delete [] homeDir;
|
||||||
|
|
||||||
|
err = gnutls_certificate_set_x509_trust_file(cert_cred, caSave.buf,
|
||||||
|
GNUTLS_X509_FMT_PEM);
|
||||||
|
if (err < 0)
|
||||||
|
vlog.debug("Failed to load saved server certificates from %s", caSave.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*crlfile && gnutls_certificate_set_x509_crl_file(cert_cred,crlfile,GNUTLS_X509_FMT_PEM) < 0)
|
||||||
|
throw AuthFailureException("load of CRL failed");
|
||||||
|
|
||||||
|
if (gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred) != GNUTLS_E_SUCCESS)
|
||||||
|
throw AuthFailureException("gnutls_credentials_set failed");
|
||||||
|
|
||||||
|
if (gnutls_server_name_set(session, GNUTLS_NAME_DNS,
|
||||||
|
client->getServerName(),
|
||||||
|
strlen(client->getServerName())) != GNUTLS_E_SUCCESS)
|
||||||
|
vlog.error("Failed to configure the server name for TLS handshake");
|
||||||
|
|
||||||
|
vlog.debug("X509 session has been set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSecurityTLS::checkSession()
|
||||||
|
{
|
||||||
|
const unsigned allowed_errors = GNUTLS_CERT_INVALID |
|
||||||
|
GNUTLS_CERT_SIGNER_NOT_FOUND |
|
||||||
|
GNUTLS_CERT_SIGNER_NOT_CA;
|
||||||
|
unsigned int status;
|
||||||
|
const gnutls_datum_t *cert_list;
|
||||||
|
unsigned int cert_list_size = 0;
|
||||||
|
int err;
|
||||||
|
gnutls_datum_t info;
|
||||||
|
|
||||||
|
if (anon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
|
||||||
|
throw AuthFailureException("unsupported certificate type");
|
||||||
|
|
||||||
|
err = gnutls_certificate_verify_peers2(session, &status);
|
||||||
|
if (err != 0) {
|
||||||
|
vlog.error("server certificate verification failed: %s", gnutls_strerror(err));
|
||||||
|
throw AuthFailureException("server certificate verification failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & GNUTLS_CERT_REVOKED)
|
||||||
|
throw AuthFailureException("server certificate has been revoked");
|
||||||
|
|
||||||
|
#ifndef WITHOUT_X509_TIMES
|
||||||
|
if (status & GNUTLS_CERT_NOT_ACTIVATED)
|
||||||
|
throw AuthFailureException("server certificate has not been activated");
|
||||||
|
|
||||||
|
if (status & GNUTLS_CERT_EXPIRED) {
|
||||||
|
vlog.debug("server certificate has expired");
|
||||||
|
if (!msg->showMsgBox(UserMsgBox::M_YESNO, "certificate has expired",
|
||||||
|
"The certificate of the server has expired, "
|
||||||
|
"do you want to continue?"))
|
||||||
|
throw AuthFailureException("server certificate has expired");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Process other errors later */
|
||||||
|
|
||||||
|
cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
|
||||||
|
if (!cert_list_size)
|
||||||
|
throw AuthFailureException("empty certificate chain");
|
||||||
|
|
||||||
|
/* Process only server's certificate, not issuer's certificate */
|
||||||
|
gnutls_x509_crt_t crt;
|
||||||
|
gnutls_x509_crt_init(&crt);
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_import(crt, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
|
||||||
|
throw AuthFailureException("decoding of certificate failed");
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) {
|
||||||
|
char buf[255];
|
||||||
|
vlog.debug("hostname mismatch");
|
||||||
|
snprintf(buf, sizeof(buf), "Hostname (%s) does not match any certificate, "
|
||||||
|
"do you want to continue?", client->getServerName());
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
if (!msg->showMsgBox(UserMsgBox::M_YESNO, "hostname mismatch", buf))
|
||||||
|
throw AuthFailureException("hostname mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
/* Everything is fine (hostname + verification) */
|
||||||
|
gnutls_x509_crt_deinit(crt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & GNUTLS_CERT_INVALID)
|
||||||
|
vlog.debug("server certificate invalid");
|
||||||
|
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
|
||||||
|
vlog.debug("server cert signer not found");
|
||||||
|
if (status & GNUTLS_CERT_SIGNER_NOT_CA)
|
||||||
|
vlog.debug("server cert signer not CA");
|
||||||
|
|
||||||
|
if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
|
||||||
|
throw AuthFailureException("The server certificate uses an insecure algorithm");
|
||||||
|
|
||||||
|
if ((status & (~allowed_errors)) != 0) {
|
||||||
|
/* No other errors are allowed */
|
||||||
|
vlog.debug("GNUTLS status of certificate verification: %u", status);
|
||||||
|
throw AuthFailureException("Invalid status of server certificate verification");
|
||||||
|
}
|
||||||
|
|
||||||
|
vlog.debug("Saved server certificates don't match");
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info)) {
|
||||||
|
/*
|
||||||
|
* GNUTLS doesn't correctly export gnutls_free symbol which is
|
||||||
|
* a function pointer. Linking with Visual Studio 2008 Express will
|
||||||
|
* fail when you call gnutls_free().
|
||||||
|
*/
|
||||||
|
#if WIN32
|
||||||
|
free(info.data);
|
||||||
|
#else
|
||||||
|
gnutls_free(info.data);
|
||||||
|
#endif
|
||||||
|
throw AuthFailureException("Could not find certificate to display");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t out_size = 0;
|
||||||
|
char *out_buf = NULL;
|
||||||
|
char *certinfo = NULL;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
vlog.debug("certificate issuer unknown");
|
||||||
|
|
||||||
|
len = snprintf(NULL, 0, "This certificate has been signed by an unknown "
|
||||||
|
"authority:\n\n%s\n\nDo you want to save it and "
|
||||||
|
"continue?\n ", info.data);
|
||||||
|
if (len < 0)
|
||||||
|
AuthFailureException("certificate decoding error");
|
||||||
|
|
||||||
|
vlog.debug("%s", info.data);
|
||||||
|
|
||||||
|
certinfo = new char[len];
|
||||||
|
if (certinfo == NULL)
|
||||||
|
throw AuthFailureException("Out of memory");
|
||||||
|
|
||||||
|
snprintf(certinfo, len, "This certificate has been signed by an unknown "
|
||||||
|
"authority:\n\n%s\n\nDo you want to save it and "
|
||||||
|
"continue? ", info.data);
|
||||||
|
|
||||||
|
for (int i = 0; i < len - 1; i++)
|
||||||
|
if (certinfo[i] == ',' && certinfo[i + 1] == ' ')
|
||||||
|
certinfo[i] = '\n';
|
||||||
|
|
||||||
|
if (!msg->showMsgBox(UserMsgBox::M_YESNO, "certificate issuer unknown",
|
||||||
|
certinfo)) {
|
||||||
|
delete [] certinfo;
|
||||||
|
throw AuthFailureException("certificate issuer unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] certinfo;
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, NULL, &out_size)
|
||||||
|
== GNUTLS_E_SHORT_MEMORY_BUFFER)
|
||||||
|
AuthFailureException("Out of memory");
|
||||||
|
|
||||||
|
// Save cert
|
||||||
|
out_buf = new char[out_size];
|
||||||
|
if (out_buf == NULL)
|
||||||
|
AuthFailureException("Out of memory");
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, out_buf, &out_size) < 0)
|
||||||
|
AuthFailureException("certificate issuer unknown, and certificate "
|
||||||
|
"export failed");
|
||||||
|
|
||||||
|
char *homeDir = NULL;
|
||||||
|
if (getvnchomedir(&homeDir) == -1)
|
||||||
|
vlog.error("Could not obtain VNC home directory path");
|
||||||
|
else {
|
||||||
|
FILE *f;
|
||||||
|
CharArray caSave(strlen(homeDir) + 1 + 19);
|
||||||
|
sprintf(caSave.buf, "%sx509_savedcerts.pem", homeDir);
|
||||||
|
delete [] homeDir;
|
||||||
|
f = fopen(caSave.buf, "a+");
|
||||||
|
if (!f)
|
||||||
|
msg->showMsgBox(UserMsgBox::M_OK, "certificate save failed",
|
||||||
|
"Could not save the certificate");
|
||||||
|
else {
|
||||||
|
fprintf(f, "%s\n", out_buf);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] out_buf;
|
||||||
|
|
||||||
|
gnutls_x509_crt_deinit(crt);
|
||||||
|
/*
|
||||||
|
* GNUTLS doesn't correctly export gnutls_free symbol which is
|
||||||
|
* a function pointer. Linking with Visual Studio 2008 Express will
|
||||||
|
* fail when you call gnutls_free().
|
||||||
|
*/
|
||||||
|
#if WIN32
|
||||||
|
free(info.data);
|
||||||
|
#else
|
||||||
|
gnutls_free(info.data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
77
common/rfb/CSecurityTLS.h
Normal file
77
common/rfb/CSecurityTLS.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Red Hat Inc.
|
||||||
|
* Copyright (C) 2005 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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 __C_SECURITY_TLS_H__
|
||||||
|
#define __C_SECURITY_TLS_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_GNUTLS
|
||||||
|
#error "This header should not be compiled without HAVE_GNUTLS defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rfb/CSecurity.h>
|
||||||
|
#include <rfb/SSecurityVeNCrypt.h>
|
||||||
|
#include <rfb/Security.h>
|
||||||
|
#include <rfb/UserMsgBox.h>
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
class UserMsgBox;
|
||||||
|
class CSecurityTLS : public CSecurity {
|
||||||
|
public:
|
||||||
|
CSecurityTLS(bool _anon);
|
||||||
|
virtual ~CSecurityTLS();
|
||||||
|
virtual bool processMsg(CConnection* cc);
|
||||||
|
virtual int getType() const { return anon ? secTypeTLSNone : secTypeX509None; }
|
||||||
|
virtual const char* description() const
|
||||||
|
{ return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; }
|
||||||
|
virtual bool isSecure() const { return !anon; }
|
||||||
|
static void setDefaults();
|
||||||
|
|
||||||
|
static StringParameter X509CA;
|
||||||
|
static StringParameter X509CRL;
|
||||||
|
static UserMsgBox *msg;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void shutdown(bool needbye);
|
||||||
|
void freeResources();
|
||||||
|
void setParam();
|
||||||
|
void checkSession();
|
||||||
|
CConnection *client;
|
||||||
|
|
||||||
|
private:
|
||||||
|
gnutls_session_t session;
|
||||||
|
gnutls_anon_client_credentials_t anon_cred;
|
||||||
|
gnutls_certificate_credentials_t cert_cred;
|
||||||
|
bool anon;
|
||||||
|
|
||||||
|
char *cafile, *crlfile;
|
||||||
|
rdr::InStream* fis;
|
||||||
|
rdr::OutStream* fos;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
206
common/rfb/CSecurityVeNCrypt.cxx
Normal file
206
common/rfb/CSecurityVeNCrypt.cxx
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006 OCCAM Financial Technology
|
||||||
|
* Copyright (C) 2005-2006 Martin Koegler
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CSecurityVeNCrypt
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <rfb/Exception.h>
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
#include <rfb/CConnection.h>
|
||||||
|
#include <rfb/CSecurityVeNCrypt.h>
|
||||||
|
#include <rfb/LogWriter.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
using namespace rdr;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static LogWriter vlog("CVeNCrypt");
|
||||||
|
|
||||||
|
CSecurityVeNCrypt::CSecurityVeNCrypt(SecurityClient* sec) : csecurity(NULL), security(sec)
|
||||||
|
{
|
||||||
|
haveRecvdMajorVersion = false;
|
||||||
|
haveRecvdMinorVersion = false;
|
||||||
|
haveSentVersion = false;
|
||||||
|
haveAgreedVersion = false;
|
||||||
|
haveListOfTypes = false;
|
||||||
|
haveNumberOfTypes = false;
|
||||||
|
haveChosenType = false;
|
||||||
|
majorVersion = 0;
|
||||||
|
minorVersion = 0;
|
||||||
|
chosenType = secTypeVeNCrypt;
|
||||||
|
nAvailableTypes = 0;
|
||||||
|
availableTypes = NULL;
|
||||||
|
iAvailableType = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSecurityVeNCrypt::~CSecurityVeNCrypt()
|
||||||
|
{
|
||||||
|
if (availableTypes)
|
||||||
|
delete[] availableTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSecurityVeNCrypt::processMsg(CConnection* cc)
|
||||||
|
{
|
||||||
|
InStream* is = cc->getInStream();
|
||||||
|
OutStream* os = cc->getOutStream();
|
||||||
|
|
||||||
|
/* get major, minor versions, send what we can support (or 0.0 for can't support it) */
|
||||||
|
if (!haveRecvdMajorVersion) {
|
||||||
|
majorVersion = is->readU8();
|
||||||
|
haveRecvdMajorVersion = true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveRecvdMinorVersion) {
|
||||||
|
minorVersion = is->readU8();
|
||||||
|
haveRecvdMinorVersion = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* major version in upper 8 bits and minor version in lower 8 bits */
|
||||||
|
U16 Version = (((U16) majorVersion) << 8) | ((U16) minorVersion);
|
||||||
|
|
||||||
|
if (!haveSentVersion) {
|
||||||
|
/* Currently we don't support former VeNCrypt 0.1 */
|
||||||
|
if (Version >= 0x0002) {
|
||||||
|
majorVersion = 0;
|
||||||
|
minorVersion = 2;
|
||||||
|
os->writeU8(majorVersion);
|
||||||
|
os->writeU8(minorVersion);
|
||||||
|
os->flush();
|
||||||
|
} else {
|
||||||
|
/* Send 0.0 to indicate no support */
|
||||||
|
majorVersion = 0;
|
||||||
|
minorVersion = 0;
|
||||||
|
os->writeU8(0);
|
||||||
|
os->writeU8(0);
|
||||||
|
os->flush();
|
||||||
|
throw AuthFailureException("The server reported an unsupported VeNCrypt version");
|
||||||
|
}
|
||||||
|
|
||||||
|
haveSentVersion = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the server is OK */
|
||||||
|
if (!haveAgreedVersion) {
|
||||||
|
if (is->readU8())
|
||||||
|
throw AuthFailureException("The server reported it could not support the "
|
||||||
|
"VeNCrypt version");
|
||||||
|
|
||||||
|
haveAgreedVersion = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a number of types */
|
||||||
|
if (!haveNumberOfTypes) {
|
||||||
|
nAvailableTypes = is->readU8();
|
||||||
|
iAvailableType = 0;
|
||||||
|
|
||||||
|
if (!nAvailableTypes)
|
||||||
|
throw AuthFailureException("The server reported no VeNCrypt sub-types");
|
||||||
|
|
||||||
|
availableTypes = new rdr::U32[nAvailableTypes];
|
||||||
|
haveNumberOfTypes = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nAvailableTypes) {
|
||||||
|
/* read in the types possible */
|
||||||
|
if (!haveListOfTypes) {
|
||||||
|
if (is->checkNoWait(4)) {
|
||||||
|
availableTypes[iAvailableType++] = is->readU32();
|
||||||
|
haveListOfTypes = (iAvailableType >= nAvailableTypes);
|
||||||
|
vlog.debug("Server offers security type %s (%d)",
|
||||||
|
secTypeName(availableTypes[iAvailableType - 1]),
|
||||||
|
availableTypes[iAvailableType - 1]);
|
||||||
|
|
||||||
|
if (!haveListOfTypes)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make a choice and send it to the server, meanwhile set up the stack */
|
||||||
|
if (!haveChosenType) {
|
||||||
|
chosenType = secTypeInvalid;
|
||||||
|
U8 i;
|
||||||
|
list<U32>::iterator j;
|
||||||
|
list<U32> secTypes;
|
||||||
|
|
||||||
|
secTypes = security->GetEnabledExtSecTypes();
|
||||||
|
|
||||||
|
/* Honor server's security type order */
|
||||||
|
for (i = 0; i < nAvailableTypes; i++) {
|
||||||
|
for (j = secTypes.begin(); j != secTypes.end(); j++) {
|
||||||
|
if (*j == availableTypes[i]) {
|
||||||
|
chosenType = *j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chosenType != secTypeInvalid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vlog.info("Choosing security type %s (%d)", secTypeName(chosenType),
|
||||||
|
chosenType);
|
||||||
|
|
||||||
|
/* Set up the stack according to the chosen type: */
|
||||||
|
if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)
|
||||||
|
throw AuthFailureException("No valid VeNCrypt sub-type");
|
||||||
|
|
||||||
|
csecurity = security->GetCSecurity(chosenType);
|
||||||
|
|
||||||
|
/* send chosen type to server */
|
||||||
|
os->writeU32(chosenType);
|
||||||
|
os->flush();
|
||||||
|
|
||||||
|
haveChosenType = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Server told us that there are 0 types it can support - this should not
|
||||||
|
* happen, since if the server supports 0 sub-types, it doesn't support
|
||||||
|
* this security type
|
||||||
|
*/
|
||||||
|
throw AuthFailureException("The server reported 0 VeNCrypt sub-types");
|
||||||
|
}
|
||||||
|
|
||||||
|
return csecurity->processMsg(cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* CSecurityVeNCrypt::description() const
|
||||||
|
{
|
||||||
|
if (csecurity)
|
||||||
|
return csecurity->description();
|
||||||
|
return "VeNCrypt";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSecurityVeNCrypt::isSecure() const
|
||||||
|
{
|
||||||
|
if (csecurity && csecurity->isSecure())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
61
common/rfb/CSecurityVeNCrypt.h
Normal file
61
common/rfb/CSecurityVeNCrypt.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2006 Martin Koegler
|
||||||
|
* Copyright (C) 2006 OCCAM Financial Technology
|
||||||
|
* Copyright (C) 2010 TigerVNC Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CSecurityVeNCrypt
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __CSECURITYVENCRYPT_H__
|
||||||
|
#define __CSECURITYVENCRYPT_H__
|
||||||
|
|
||||||
|
#include <rfb/CSecurity.h>
|
||||||
|
#include <rfb/SecurityClient.h>
|
||||||
|
#include <rdr/types.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class CSecurityVeNCrypt : public CSecurity {
|
||||||
|
public:
|
||||||
|
|
||||||
|
CSecurityVeNCrypt(SecurityClient* sec);
|
||||||
|
~CSecurityVeNCrypt();
|
||||||
|
virtual bool processMsg(CConnection* cc);// { return true; }
|
||||||
|
int getType() const {return chosenType;}
|
||||||
|
virtual const char* description() const;
|
||||||
|
virtual bool isSecure() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CSecurity *csecurity;
|
||||||
|
SecurityClient *security;
|
||||||
|
bool haveRecvdMajorVersion;
|
||||||
|
bool haveRecvdMinorVersion;
|
||||||
|
bool haveSentVersion;
|
||||||
|
bool haveAgreedVersion;
|
||||||
|
bool haveListOfTypes;
|
||||||
|
bool haveNumberOfTypes;
|
||||||
|
bool haveChosenType;
|
||||||
|
rdr::U8 majorVersion, minorVersion;
|
||||||
|
rdr::U32 chosenType;
|
||||||
|
rdr::U8 nAvailableTypes;
|
||||||
|
rdr::U32 *availableTypes;
|
||||||
|
rdr::U8 iAvailableType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
67
common/rfb/CSecurityVncAuth.cxx
Normal file
67
common/rfb/CSecurityVncAuth.cxx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// CSecurityVncAuth
|
||||||
|
//
|
||||||
|
// XXX not thread-safe, because d3des isn't - do we need to worry about this?
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rfb/CConnection.h>
|
||||||
|
#include <rfb/Password.h>
|
||||||
|
#include <rfb/CSecurityVncAuth.h>
|
||||||
|
#include <rfb/util.h>
|
||||||
|
#include <rfb/Security.h>
|
||||||
|
extern "C" {
|
||||||
|
#include <rfb/d3des.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
static const int vncAuthChallengeSize = 16;
|
||||||
|
|
||||||
|
bool CSecurityVncAuth::processMsg(CConnection* cc)
|
||||||
|
{
|
||||||
|
rdr::InStream* is = cc->getInStream();
|
||||||
|
rdr::OutStream* os = cc->getOutStream();
|
||||||
|
|
||||||
|
// Read the challenge & obtain the user's password
|
||||||
|
rdr::U8 challenge[vncAuthChallengeSize];
|
||||||
|
is->readBytes(challenge, vncAuthChallengeSize);
|
||||||
|
PlainPasswd passwd;
|
||||||
|
(CSecurity::upg)->getUserPasswd(cc->isSecure(), 0, &passwd.buf);
|
||||||
|
|
||||||
|
// Calculate the correct response
|
||||||
|
rdr::U8 key[8];
|
||||||
|
int pwdLen = strlen(passwd.buf);
|
||||||
|
for (int i=0; i<8; i++)
|
||||||
|
key[i] = i<pwdLen ? passwd.buf[i] : 0;
|
||||||
|
deskey(key, EN0);
|
||||||
|
for (int j = 0; j < vncAuthChallengeSize; j += 8)
|
||||||
|
des(challenge+j, challenge+j);
|
||||||
|
|
||||||
|
// Return the response to the server
|
||||||
|
os->writeBytes(challenge, vncAuthChallengeSize);
|
||||||
|
os->flush();
|
||||||
|
return true;
|
||||||
|
}
|
35
common/rfb/CSecurityVncAuth.h
Normal file
35
common/rfb/CSecurityVncAuth.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 __RFB_CSECURITYVNCAUTH_H__
|
||||||
|
#define __RFB_CSECURITYVNCAUTH_H__
|
||||||
|
|
||||||
|
#include <rfb/CSecurity.h>
|
||||||
|
#include <rfb/Security.h>
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
class CSecurityVncAuth : public CSecurity {
|
||||||
|
public:
|
||||||
|
CSecurityVncAuth(void) {}
|
||||||
|
virtual ~CSecurityVncAuth() {}
|
||||||
|
virtual bool processMsg(CConnection* cc);
|
||||||
|
virtual int getType() const {return secTypeVncAuth;};
|
||||||
|
virtual const char* description() const {return "No Encryption";}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user