New upstream version 3.5.99.27
This commit is contained in:
25
nxcomp/.gitignore
vendored
Normal file
25
nxcomp/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
compile
|
||||
config.guess
|
||||
config.sub
|
||||
depcomp
|
||||
install-sh
|
||||
ltmain.sh
|
||||
missing
|
||||
config.h
|
||||
config.h.in
|
||||
libtool
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
nxcomp.pc
|
||||
src/Makefile
|
||||
src/Makefile.in
|
||||
test/.deps/
|
||||
test/Makefile
|
||||
test/Makefile.in
|
||||
test/logging_test
|
||||
23
nxcomp/Makefile.am
Normal file
23
nxcomp/Makefile.am
Normal file
@@ -0,0 +1,23 @@
|
||||
SUBDIRS = src test
|
||||
|
||||
pkgconfig_DATA = nxcomp.pc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
$(srcdir)/autom4te.cache/* \
|
||||
$(srcdir)/build-aux/* \
|
||||
$(srcdir)/Makefile.in \
|
||||
$(srcdir)/src/Makefile.in \
|
||||
$(srcdir)/aclocal.m4 \
|
||||
$(srcdir)/config.h.in \
|
||||
$(srcdir)/config.h.in~ \
|
||||
$(srcdir)/configure \
|
||||
$(srcdir)/m4/libtool.m4 \
|
||||
$(srcdir)/m4/lt~obsolete.m4 \
|
||||
$(srcdir)/m4/ltoptions.m4 \
|
||||
$(srcdir)/m4/ltsugar.m4 \
|
||||
$(srcdir)/m4/ltversion.m4 \
|
||||
$(NULL)
|
||||
|
||||
DISTCLEANFILES=$(MAINTAINERCLEANFILES)
|
||||
1
nxcomp/VERSION
Symbolic link
1
nxcomp/VERSION
Symbolic link
@@ -0,0 +1 @@
|
||||
../VERSION
|
||||
142
nxcomp/configure.ac
Normal file
142
nxcomp/configure.ac
Normal file
@@ -0,0 +1,142 @@
|
||||
# ***************************************************************************
|
||||
# *** configure.ac for nxcomp ***
|
||||
# ***************************************************************************
|
||||
|
||||
m4_define([nxcomp_version], m4_esyscmd([tr -d '\n' < VERSION]))
|
||||
|
||||
# Initialize Autoconf
|
||||
AC_PREREQ(2.60)
|
||||
|
||||
AC_INIT([libXcomp], [nxcomp_version], [https://github.com/ArcticaProject/nx-libs/issues])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_PROG_CXX
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign no-dist-gzip dist-bzip2])
|
||||
|
||||
# Initialize libtool
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
# enable this to add the variable to the Makefiles
|
||||
#AC_ARG_VAR(NX_VERSION_CUSTOM, [custom version string])
|
||||
|
||||
if test "x$NX_VERSION_CUSTOM" != x; then
|
||||
AC_DEFINE_UNQUOTED([NX_VERSION_CUSTOM], ["${NX_VERSION_CUSTOM}"], [user provided custom version string])
|
||||
fi
|
||||
|
||||
COMP_VERSION=nxcomp_version
|
||||
AC_SUBST([COMP_VERSION])
|
||||
|
||||
LT_COMP_VERSION=["$(printf '%s\n' "${COMP_VERSION}" | awk -F '.' '/^[0-9]+\.[0-9]+\.[0-9]+.*$/ { print $1 ":" $2 ":" $3; }')"]
|
||||
AC_SUBST([LT_COMP_VERSION])
|
||||
|
||||
# Silence warning: ar: 'u' modifier ignored since 'D' is the default
|
||||
AC_SUBST(AR_FLAGS, [cr])
|
||||
|
||||
# Upstream's pkg.m4 (since 0.27) offers this now, but define our own
|
||||
# compatible version in case the local version of pkgconfig isn't new enough.
|
||||
# https://bugs.freedesktop.org/show_bug.cgi?id=48743
|
||||
m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR],
|
||||
[AC_ARG_WITH([pkgconfigdir],
|
||||
[AS_HELP_STRING([--with-pkgconfigdir],
|
||||
[install directory for nxcomp.pc pkg-config file])],
|
||||
[],[with_pkgconfigdir='$(libdir)/pkgconfig'])
|
||||
AC_SUBST([pkgconfigdir], [${with_pkgconfigdir}])])
|
||||
|
||||
PKG_CHECK_MODULES([JPEG], [libjpeg], [], [LIBJPEG_FALLBACK_CHECK])
|
||||
PKG_CHECK_MODULES([PNG], [libpng])
|
||||
PKG_CHECK_MODULES([Z], [zlib], [], [ZLIB_FALLBACK_CHECK])
|
||||
|
||||
AC_LANG([C++])
|
||||
NX_COMPILER_BRAND
|
||||
NX_DEFAULT_OPTIONS
|
||||
|
||||
NX_BUILD_ON_CYGWIN32
|
||||
NX_BUILD_ON_AMD64
|
||||
NX_BUILD_ON_DARWIN
|
||||
NX_BUILD_ON_SUN
|
||||
NX_BUILD_ON_FreeBSD
|
||||
|
||||
# Build PIC libraries.
|
||||
|
||||
if test "$CYGWIN32" != yes -a "$DARWIN" != yes; then
|
||||
CXXFLAGS="$CXXFLAGS -fPIC"
|
||||
CFLAGS="$CFLAGS -fPIC"
|
||||
fi
|
||||
|
||||
# On FreeBSD search libraries and includes under /usr/local.
|
||||
|
||||
if test "$FreeBSD" = yes; then
|
||||
LIBS="$LIBS -L/usr/local/lib"
|
||||
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
|
||||
fi
|
||||
|
||||
AX_PTHREAD([], AC_MSG_ERROR([no POSIX threads support detected]))
|
||||
|
||||
# If in_addr_t is not defined use unsigned int.
|
||||
AC_CHECK_TYPES([in_addr_t], [], [], [[#include <netinet/in.h>]])
|
||||
|
||||
AC_ARG_ENABLE([cxx11],
|
||||
[AS_HELP_STRING([--enable-cxx11],
|
||||
[enable optional features requiring C++11 support (disabled by default)])],
|
||||
[AS_IF([test x$enableval = xyes],
|
||||
[AX_CXX_COMPILE_STDCXX_11([], [mandatory])])])
|
||||
|
||||
# Check if std::put_time is available.
|
||||
AC_MSG_CHECKING([if std::put_time is available])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
]],
|
||||
[[
|
||||
std::time_t t = std::time(NULL);
|
||||
std::tm tm = *std::localtime(&t);
|
||||
(void) std::put_time(&tm, "%c");
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_STD_PUT_TIME, [1],
|
||||
[Use std::put_time to format times, must be made available by the compiler if turned on.])],
|
||||
[AC_MSG_RESULT([no])])
|
||||
|
||||
# Check if ::ctime_s is available.
|
||||
AC_MSG_CHECKING([if ::ctime_s is available])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
#include <ctime>
|
||||
]],
|
||||
[[
|
||||
time_t res = time(NULL);
|
||||
char str[26] = { };
|
||||
::ctime_s(str, sizeof(str), &res);
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_CTIME_S, [1],
|
||||
[Use ::ctime_s to format times, must be made available by the compiler if turned on.])],
|
||||
[AC_MSG_RESULT([no])])
|
||||
|
||||
AC_ARG_ENABLE([debug],
|
||||
[AS_HELP_STRING([--enable-debug],
|
||||
[enable to get info session log output (disabled by default)])],
|
||||
[AS_IF([test x$enableval = xyes],
|
||||
[AC_DEFINE(INFO, 1, [Define this to get info session log output.])
|
||||
info_messages=yes])])
|
||||
|
||||
AC_ARG_ENABLE([valgrind],
|
||||
[AS_HELP_STRING([--enable-valgrind],
|
||||
[enable for extra valgrind hacks (disabled by default)])],
|
||||
[AS_IF([test x$enableval = xyes],
|
||||
[AC_DEFINE(VALGRIND, 1, [Define this for extra valgrind hacks.])
|
||||
valgrind_hacks=yes])])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
test/Makefile
|
||||
nxcomp.pc
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
91
nxcomp/include/MD5.h
Normal file
91
nxcomp/include/MD5.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#ifndef md5_INCLUDED
|
||||
# define md5_INCLUDED
|
||||
|
||||
/*
|
||||
* This package supports both compile-time and run-time determination of CPU
|
||||
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
* defined as non-zero, the code will be compiled to run only on big-endian
|
||||
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
* run on either big- or little-endian CPUs, but will run slightly less
|
||||
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
||||
typedef unsigned int md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct md5_state_s {
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
} md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
void md5_init(md5_state_t *pms);
|
||||
|
||||
/* Append a string to the message. */
|
||||
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
|
||||
|
||||
/* Finish the message and return the digest. */
|
||||
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* md5_INCLUDED */
|
||||
474
nxcomp/include/NX.h
Normal file
474
nxcomp/include/NX.h
Normal file
@@ -0,0 +1,474 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NX_H
|
||||
#define NX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#define NX_FD_ANY -1
|
||||
|
||||
#define NX_MODE_ANY -1
|
||||
#define NX_MODE_CLIENT 1
|
||||
#define NX_MODE_SERVER 2
|
||||
|
||||
#define NX_DISPLAY_ANY NULL
|
||||
|
||||
#define NX_SIGNAL_ANY -1
|
||||
#define NX_SIGNAL_ENABLE 1
|
||||
#define NX_SIGNAL_DISABLE 2
|
||||
#define NX_SIGNAL_RAISE 3
|
||||
#define NX_SIGNAL_FORWARD 4
|
||||
|
||||
#define NX_POLICY_IMMEDIATE 1
|
||||
#define NX_POLICY_DEFERRED 2
|
||||
|
||||
#define NX_ALERT_REMOTE 0
|
||||
#define NX_ALERT_LOCAL 1
|
||||
|
||||
#define NX_HANDLER_FLUSH 0
|
||||
#define NX_HANDLER_STATISTICS 1
|
||||
|
||||
#define NX_STATISTICS_PARTIAL 0
|
||||
#define NX_STATISTICS_TOTAL 1
|
||||
|
||||
#define NX_CHANNEL_X11 0
|
||||
#define NX_CHANNEL_CUPS 1
|
||||
#define NX_CHANNEL_SMB 2
|
||||
#define NX_CHANNEL_MEDIA 3
|
||||
#define NX_CHANNEL_HTTP 4
|
||||
#define NX_CHANNEL_FONT 5
|
||||
#define NX_CHANNEL_SLAVE 6
|
||||
|
||||
#define NX_FILE_SESSION 0
|
||||
#define NX_FILE_ERRORS 1
|
||||
#define NX_FILE_OPTIONS 2
|
||||
#define NX_FILE_STATS 3
|
||||
|
||||
/*
|
||||
* The following are the new interfaces to the NX transport. The
|
||||
* NX proxy software is now intended to be run as a library of a
|
||||
* higher level communication manager (nxssh, nxhttp, nxrtp, etc,
|
||||
* not only nxproxy). This is a work-in-progress, so expect these
|
||||
* interfaces to change in future. At the present moment, as an
|
||||
* example, there is no provision for creating and managing mul-
|
||||
* tiple proxy connections.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Attach a NX transport to the provided descriptor. This should be
|
||||
* done after having created a pair of connected sockets.
|
||||
*/
|
||||
|
||||
extern int NXTransCreate(int fd, int mode, const char *options);
|
||||
|
||||
/*
|
||||
* Tell the proxy to use the second descriptor as its own end of
|
||||
* the internal connection to the NX agent. The NX agent will use
|
||||
* the first descriptor. Setting an agent connection will have the
|
||||
* effect of disabling further X client connections and, if it is
|
||||
* possible, will trigger the use of the memory-to-memory transport.
|
||||
*/
|
||||
|
||||
extern int NXTransAgent(int fd[2]);
|
||||
|
||||
/*
|
||||
* Prepare the file sets and the timeout for a later execution of
|
||||
* the select(). The masks and the timeout must persist across all
|
||||
* the calls, so if you don't need any of the values, it is requi-
|
||||
* red that you create empty masks and a default timeout. To save
|
||||
* a check at each run, all the functions below assume that valid
|
||||
* pointers are passed.
|
||||
*/
|
||||
|
||||
extern int NXTransPrepare(int *maxfds, fd_set *readfds,
|
||||
fd_set *writefds, struct timeval *timeout);
|
||||
|
||||
/*
|
||||
* Call select() to find out the descriptors in the sets having
|
||||
* pending data.
|
||||
*/
|
||||
|
||||
extern int NXTransSelect(int *result, int *error, int *maxfds, fd_set *readfds,
|
||||
fd_set *writefds, struct timeval *timeout);
|
||||
|
||||
/*
|
||||
* Perform the required I/O on all the NX descriptors having pen-
|
||||
* ding data. This can include reading and writing to the NX chan-
|
||||
* nels, encoding and decoding the proxy data or managing any of
|
||||
* the other NX resources.
|
||||
*/
|
||||
|
||||
extern int NXTransExecute(int *result, int *error, int *maxfds, fd_set *readfds,
|
||||
fd_set *writefds, struct timeval *timeout);
|
||||
|
||||
/*
|
||||
* Run an empty loop, giving to the NX transport a chance to check
|
||||
* its descriptors.
|
||||
*/
|
||||
|
||||
extern int NXTransContinue(struct timeval *timeout);
|
||||
|
||||
/*
|
||||
* Perform I/O on the given descriptors. If memory-to-memory trans-
|
||||
* port has been activated and the descriptor is recognized as a
|
||||
* valid agent connection, then the functions will read and write
|
||||
* the data directly to the proxy buffer, otherwise the correspond-
|
||||
* ing network operation will be performed.
|
||||
*/
|
||||
|
||||
extern int NXTransRead(int fd, char *data, int size);
|
||||
extern int NXTransWrite(int fd, char *data, int size);
|
||||
extern int NXTransReadable(int fd, int *readable);
|
||||
|
||||
extern int NXTransReadVector(int fd, struct iovec *iovdata, int iovsize);
|
||||
extern int NXTransWriteVector(int fd, struct iovec *iovdata, int iovsize);
|
||||
|
||||
extern int NXTransClose(int fd);
|
||||
|
||||
/*
|
||||
* Return true if the NX transport is running. The fd parameter can
|
||||
* be either the local descriptor attached to the NX transport or
|
||||
* NX_FD_ANY.
|
||||
*/
|
||||
|
||||
extern int NXTransRunning(int fd);
|
||||
|
||||
/*
|
||||
* Close down the NX transport and free all the allocated resources.
|
||||
* The fd parameter can be either the local descriptor or NX_FD_ANY.
|
||||
* This must be explicitly called by the agent before the proxy can
|
||||
* start the tear down procedure.
|
||||
*/
|
||||
|
||||
extern int NXTransDestroy(int fd);
|
||||
|
||||
/*
|
||||
* Tell to the proxy how to handle the standard POSIX signals. For
|
||||
* example, given the SIGINT signal, the caller can specify any of
|
||||
* the following actions:
|
||||
*
|
||||
* NX_SIGNAL_ENABLE: A signal handler will have to be installed by
|
||||
* the library, so that it can be intercepted by
|
||||
* the proxy.
|
||||
*
|
||||
* NX_SIGNAL_DISABLE: The signal will be handled by the caller and,
|
||||
* eventually, forwarded to the proxy by calling
|
||||
* NXTransSignal() explicitly.
|
||||
*
|
||||
* NX_SIGNAL_RAISE: The signal must be handled now, as if it had
|
||||
* been delivered by the operating system. This
|
||||
* function can be called by the agent with the
|
||||
* purpose of propagating a signal to the proxy.
|
||||
*
|
||||
* NX_SIGNAL_FORWARD: A signal handler will have to be installed by
|
||||
* the library but the library will have to call
|
||||
* the original signal handler when the signal
|
||||
* is received.
|
||||
*
|
||||
* As a rule of thumb, agents should let the proxy handle SIGUSR1
|
||||
* and SIGUSR2, used for producing the NX protocol statistics, and
|
||||
* SIGHUP, used for disconnecting the NX transport.
|
||||
*
|
||||
* The following signals are blocked by default upon creation of the
|
||||
* NX transport:
|
||||
*
|
||||
* SIGCHLD These signals should be always put under the control
|
||||
* SIGUSR1 of the proxy. If agents are intercepting them, agents
|
||||
* SIGUSR2 should later call NXTransSignal(..., NX_SIGNAL_RAISE)
|
||||
* SIGHUP to forward the signal to the proxy. As an alternative
|
||||
* they can specify a NX_SIGNAL_FORWARD action, so they,
|
||||
* in turn, can be notified about the signal. This can
|
||||
* be especially useful for SIGCHLD.
|
||||
*
|
||||
* SIGINT These signals should be intercepted by agents. Agents
|
||||
* SIGTERM should ensure that NXTransDestroy() is called before
|
||||
* exiting, to give the proxy a chance to shut down the
|
||||
* NX transport.
|
||||
*
|
||||
* SIGPIPE This signal is blocked by the proxy, but not used to
|
||||
* implement any functionality. It can be handled by the
|
||||
* NX agent without affecting the proxy.
|
||||
*
|
||||
* SIGALRM This is now used by the proxy and agents should not
|
||||
* redefine it. Agents can use the signal to implement
|
||||
* their own timers but should not interleave calls to
|
||||
* the NX transport and should restore the old handler
|
||||
* when the timeout is raised.
|
||||
*
|
||||
* SIGVTALRM These signals are not used but may be used in future
|
||||
* SIGWINCH versions of the library.
|
||||
* SIGIO
|
||||
* SIGTSTP
|
||||
* SIGTTIN
|
||||
* SIGTTOU
|
||||
*
|
||||
* By calling NXTransSignal(..., NX_SIGNAL_DISABLE) nxcomp will res-
|
||||
* tore the signal handler that was saved at the time the proxy hand-
|
||||
* ler was installed. This means that you should call the function
|
||||
* just after the XOpenDisplay() or any other function used to init-
|
||||
* ialize the NX transport.
|
||||
*/
|
||||
|
||||
extern int NXTransSignal(int signal, int action);
|
||||
|
||||
/*
|
||||
* Return a value between 0 and 9 indicating the congestion level
|
||||
* based on the tokens still available. A value of 9 means that
|
||||
* the link is congested and no further data can be sent.
|
||||
*/
|
||||
|
||||
extern int NXTransCongestion(int fd);
|
||||
|
||||
/*
|
||||
* Let the application to be notified by the proxy when an event oc-
|
||||
* curs. The parameter, as set at the time the handler is installed,
|
||||
* is passed each time to the callback function. The parameter is
|
||||
* presumably the display pointer, given that at the present moment
|
||||
* the NX transport doesn't have access to the display structure and
|
||||
* so wouldn't be able to determine the display to pass to the call-
|
||||
* back function.
|
||||
*
|
||||
* NX_HANDLER_FLUSH: The handler function is called when some
|
||||
* more data has been written to the proxy
|
||||
* link.
|
||||
*
|
||||
* The data is the number of bytes written.
|
||||
*
|
||||
* NX_HANDLER_STATISTICS: This handler is called to let the agent
|
||||
* include arbitrary data in the transport
|
||||
* statistics. The parameter, in this case,
|
||||
* is a pointer to a pointer to a null term-
|
||||
* inated string. The pointer is set at the
|
||||
* time the handler is registered. The point-
|
||||
* ed string will have to be filled by the
|
||||
* agent with its statistics data.
|
||||
*
|
||||
* The data can be NX_STATISTICS_PARTIAL or NX_STATISTICS_TOTAL. The
|
||||
* agent can refer to the value by using the NXStatisticsPartial and
|
||||
* NXStatisticsTotal constants defined in NXvars.h.
|
||||
*
|
||||
* Note that these interfaces are used by Xlib and nxcompext. Agents
|
||||
* should never call these interfaces directly, but use the nxcompext
|
||||
* wrapper.
|
||||
*/
|
||||
|
||||
extern int NXTransHandler(int fd, int type, void (*handler)(void *parameter,
|
||||
int reason), void *parameter);
|
||||
|
||||
/*
|
||||
* Set the policy to be used by the NX transport to write data to the
|
||||
* proxy link:
|
||||
*
|
||||
* NX_POLICY_IMMEDIATE: When set to immediate, the proxy will try to
|
||||
* write the data just after having encoded it.
|
||||
*
|
||||
* NX_POLICY_DEFERRED: When policy is set to deferred, data will be
|
||||
* accumulated in a buffer and written to the
|
||||
* remote proxy when NXTransFlush() is called by
|
||||
* the agent.
|
||||
*/
|
||||
|
||||
extern int NXTransPolicy(int fd, int type);
|
||||
|
||||
/*
|
||||
* Query the number of bytes that have been accumulated for a deferred
|
||||
* flush.
|
||||
*/
|
||||
|
||||
extern int NXTransFlushable(int fd);
|
||||
|
||||
/*
|
||||
* Tell to the NX transport to write all the accumulated data to the
|
||||
* remote proxy.
|
||||
*/
|
||||
|
||||
extern int NXTransFlush(int fd);
|
||||
|
||||
/*
|
||||
* Create a new channel of the given type. It returns 1 on success,
|
||||
* 0 if the NX transport is not running, or -1 in the case of error.
|
||||
* On success, the descriptor provided by the caller can be later
|
||||
* used for the subsequent I/O. The type parameter not only tells to
|
||||
* the proxy the remote port where the channel has to be connected,
|
||||
* but also gives a hint about the type of data that will be carried
|
||||
* by the channel, so that the proxy can try to optimize the traffic
|
||||
* on the proxy link.
|
||||
*
|
||||
* NX_CHANNEL_X: The channel will carry X traffic and it
|
||||
* will be connected to the remote X display.
|
||||
*
|
||||
* NX_CHANNEL_CUPS: The channel will carry CUPS/IPP protocol.
|
||||
*
|
||||
* NX_CHANNEL_SMB: The channel will carry SMB/CIFS protocol.
|
||||
*
|
||||
* NX_CHANNEL_MEDIA: The channel will transport audio or other
|
||||
* multimedia data.
|
||||
*
|
||||
* NX_CHANNEL_HTTP: The channel will carry HTTP protocol.
|
||||
*
|
||||
* NX_CHANNEL_FONT: The channel will forward a X font server
|
||||
* connection.
|
||||
*
|
||||
* NX_CHANNEL_SLAVE: The channel will forward data to a remote slave
|
||||
* command (see NX_SLAVE_CMD environment variable)
|
||||
*
|
||||
* Only a proxy running at the NX server/X client side will be able
|
||||
* to create a X, CUPS, SMB, MEDIA and HTTP channel. A proxy running
|
||||
* at the NX client/X server side can create font server connections.
|
||||
* The channel creation will also fail if the remote end has not been
|
||||
* set up to forward the connection.
|
||||
*
|
||||
* To create a new channel the agent will have to set up a socketpair
|
||||
* and pass to the proxy one of the socket descriptors.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #include <sys/types.h>
|
||||
* #include <sys/socket.h>
|
||||
*
|
||||
* int fds[2];
|
||||
*
|
||||
* if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0)
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* //
|
||||
* // Use fds[0] locally and let the
|
||||
* // proxy use fds[1].
|
||||
* //
|
||||
*
|
||||
* if (NXTransChannel(NX_FD_ANY, fds[1], NX_CHANNEL_X) <= 0)
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* //
|
||||
* // The agent can now use fds[0] in
|
||||
* // read(), write() and select()
|
||||
* // system calls.
|
||||
* //
|
||||
*
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Note that all the I/O on the descriptor should be non-blocking, to
|
||||
* give a chance to the NX transport to run in the background and handle
|
||||
* the data that will be fed to the agent's side of the socketpair. This
|
||||
* will happen automatically, as long as the agent uses the XSelect()
|
||||
* version of the select() function (as it is normal whenever performing
|
||||
* Xlib I/O). In all the other cases, like presumably in the agent's main
|
||||
* loop, the agent will have to loop through NXTransPrepare(), NXTrans-
|
||||
* Select() and NXTransExecute() functions explicitly, adding to the sets
|
||||
* the descriptors that are awaited by the agent. Please check the imple-
|
||||
* mentation of _XSelect() in nx-X11/lib/X11/XlibInt.c for an example.
|
||||
*/
|
||||
|
||||
extern int NXTransChannel(int fd, int channelfd, int type);
|
||||
|
||||
/*
|
||||
* Return the name of the files used by the proxy for the current session.
|
||||
*
|
||||
* The type parameter can be:
|
||||
*
|
||||
* NX_FILE_SESSION: Usually the file 'session' in the user's session
|
||||
* directory.
|
||||
*
|
||||
* NX_FILE_ERRORS: The file used for the diagnostic output. Usually
|
||||
* the file 'errors' in the session directory.
|
||||
*
|
||||
* NX_FILE_OPTIONS: The file containing the NX options, if any.
|
||||
*
|
||||
* NX_FILE_STATS: The file used for the statistics output.
|
||||
*
|
||||
* The returned string is allocated in static memory. The caller should
|
||||
* copy the string upon returning from the function, without freeing the
|
||||
* pointer.
|
||||
*/
|
||||
|
||||
extern const char *NXTransFile(int type);
|
||||
|
||||
/*
|
||||
* Return the time in milliseconds elapsed since the last call to this
|
||||
* same function.
|
||||
*/
|
||||
|
||||
extern long NXTransTime(void);
|
||||
|
||||
/*
|
||||
* Other interfaces to the internal transport functions.
|
||||
*/
|
||||
|
||||
extern int NXTransProxy(int fd, int mode, const char *display);
|
||||
|
||||
extern int NXTransClient(const char *display);
|
||||
|
||||
extern int NXTransDialog(const char *caption, const char *message,
|
||||
const char *window, const char *type, int local,
|
||||
const char *display);
|
||||
|
||||
extern int NXTransAlert(int code, int local);
|
||||
|
||||
extern int NXTransWatchdog(int timeout);
|
||||
|
||||
extern int NXTransKeeper(int caches, int images, const char *root);
|
||||
|
||||
extern void NXTransExit(int code) __attribute__((noreturn));
|
||||
|
||||
extern int NXTransParseCommandLine(int argc, const char **argv);
|
||||
extern int NXTransParseEnvironment(const char *env, int force);
|
||||
|
||||
extern void NXTransCleanup(void) __attribute__((noreturn));
|
||||
|
||||
/*
|
||||
* Cleans up the global and local state
|
||||
* (the same way as NXTransCleanup does)
|
||||
* but does not exit the process
|
||||
* Needed for IOS platform
|
||||
*/
|
||||
extern void NXTransCleanupForReconnect(void);
|
||||
|
||||
extern const char* NXVersion(void);
|
||||
extern int NXMajorVersion(void);
|
||||
extern int NXMinorVersion(void);
|
||||
extern int NXPatchVersion(void);
|
||||
extern int NXMaintenancePatchVersion(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NX_H */
|
||||
276
nxcomp/include/NXalert.h
Normal file
276
nxcomp/include/NXalert.h
Normal file
@@ -0,0 +1,276 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NXalert_H
|
||||
#define NXalert_H
|
||||
|
||||
#define ALERT_CAPTION_PREFIX "NX - "
|
||||
|
||||
#define INTERNAL_ERROR_ALERT 1
|
||||
#define INTERNAL_ERROR_ALERT_TYPE "error"
|
||||
#define INTERNAL_ERROR_ALERT_STRING \
|
||||
"\
|
||||
An unrecoverable internal error was detected.\n\
|
||||
Press OK to terminate the current session.\n\
|
||||
"
|
||||
|
||||
#define CLOSE_DEAD_X_CONNECTION_CLIENT_ALERT 2
|
||||
#define CLOSE_DEAD_X_CONNECTION_CLIENT_ALERT_TYPE "yesno"
|
||||
#define CLOSE_DEAD_X_CONNECTION_CLIENT_ALERT_STRING \
|
||||
"\
|
||||
One of the applications currently in use is not responding.\n\
|
||||
Do you want to terminate the current session?\n\
|
||||
"
|
||||
|
||||
#define CLOSE_DEAD_X_CONNECTION_SERVER_ALERT 3
|
||||
#define CLOSE_DEAD_X_CONNECTION_SERVER_ALERT_TYPE "yesno"
|
||||
#define CLOSE_DEAD_X_CONNECTION_SERVER_ALERT_STRING \
|
||||
"\
|
||||
One of the applications did not behave correctly and caused\n\
|
||||
the X server to stop responding in a timely fashion. Do you\n\
|
||||
want to terminate the current session?\n\
|
||||
"
|
||||
|
||||
#define CLOSE_DEAD_PROXY_CONNECTION_CLIENT_ALERT 4
|
||||
#define CLOSE_DEAD_PROXY_CONNECTION_CLIENT_ALERT_TYPE NULL
|
||||
#define CLOSE_DEAD_PROXY_CONNECTION_CLIENT_ALERT_STRING NULL
|
||||
|
||||
#define CLOSE_DEAD_PROXY_CONNECTION_SERVER_ALERT 5
|
||||
#define CLOSE_DEAD_PROXY_CONNECTION_SERVER_ALERT_TYPE "yesno"
|
||||
#define CLOSE_DEAD_PROXY_CONNECTION_SERVER_ALERT_STRING \
|
||||
"\
|
||||
No response received from the remote server.\n\
|
||||
Do you want to terminate the current session?\n\
|
||||
"
|
||||
|
||||
#define RESTART_DEAD_PROXY_CONNECTION_CLIENT_ALERT 6
|
||||
#define RESTART_DEAD_PROXY_CONNECTION_CLIENT_ALERT_TYPE NULL
|
||||
#define RESTART_DEAD_PROXY_CONNECTION_CLIENT_ALERT_STRING NULL
|
||||
|
||||
#define RESTART_DEAD_PROXY_CONNECTION_SERVER_ALERT 7
|
||||
#define RESTART_DEAD_PROXY_CONNECTION_SERVER_ALERT_TYPE "yesno"
|
||||
#define RESTART_DEAD_PROXY_CONNECTION_SERVER_ALERT_STRING \
|
||||
"\
|
||||
Connection with remote server was shut down. NX will try\n\
|
||||
to establish a new server connection. Session could have\n\
|
||||
been left in a unusable state. Do you want to terminate\n\
|
||||
the session?\n\
|
||||
"
|
||||
|
||||
#define CLOSE_UNRESPONSIVE_X_SERVER_ALERT 8
|
||||
#define CLOSE_UNRESPONSIVE_X_SERVER_ALERT_TYPE "panic"
|
||||
#define CLOSE_UNRESPONSIVE_X_SERVER_ALERT_STRING \
|
||||
"\
|
||||
You pressed the key sequence CTRL+ALT+SHIFT+ESC.\n\
|
||||
This is probably because your X server has become\n\
|
||||
unresponsive. Session will be terminated in 30\n\
|
||||
seconds unless you abort the procedure by pressing\n\
|
||||
the Cancel button.\n\
|
||||
"
|
||||
|
||||
#define WRONG_PROXY_VERSION_ALERT 9
|
||||
#define WRONG_PROXY_VERSION_ALERT_TYPE "ok"
|
||||
#define WRONG_PROXY_VERSION_ALERT_STRING \
|
||||
"\
|
||||
Local NX libraries version " VERSION " do not match the NX\n\
|
||||
version of the remote server. Please check the error\n\
|
||||
log on the server to find out which client version you\n\
|
||||
need to install to be able to access this server.\n\
|
||||
"
|
||||
|
||||
#define FAILED_PROXY_CONNECTION_CLIENT_ALERT 10
|
||||
#define FAILED_PROXY_CONNECTION_CLIENT_ALERT_TYPE NULL
|
||||
#define FAILED_PROXY_CONNECTION_CLIENT_ALERT_STRING NULL
|
||||
|
||||
#define FAILED_PROXY_CONNECTION_SERVER_ALERT 11
|
||||
#define FAILED_PROXY_CONNECTION_SERVER_ALERT_TYPE "yesno"
|
||||
#define FAILED_PROXY_CONNECTION_SERVER_ALERT_STRING \
|
||||
"\
|
||||
Could not yet establish the connection to the remote\n\
|
||||
proxy. Do you want to terminate the current session?\n\
|
||||
"
|
||||
|
||||
#define MISSING_PROXY_CACHE_ALERT 12
|
||||
#define MISSING_PROXY_CACHE_ALERT_TYPE "ok"
|
||||
#define MISSING_PROXY_CACHE_ALERT_STRING \
|
||||
"\
|
||||
NX was unable to negotiate a cache for this session.\n\
|
||||
This may happen if this is the first time you run a\n\
|
||||
session on this server or if cache was corrupted or\n\
|
||||
produced by an incompatible NX version.\n\
|
||||
"
|
||||
|
||||
#define ABORT_PROXY_CONNECTION_ALERT 13
|
||||
#define ABORT_PROXY_CONNECTION_ALERT_TYPE "ok"
|
||||
#define ABORT_PROXY_CONNECTION_ALERT_STRING \
|
||||
"\
|
||||
The connection with the remote server was shut down.\n\
|
||||
Please check the state of your network connection.\n\
|
||||
"
|
||||
|
||||
/*
|
||||
* The one below is a special alert, used to close
|
||||
* a previous alert that is running on the given
|
||||
* side. This can be used to get rid of a message
|
||||
* that has ceased to hold true.
|
||||
*/
|
||||
|
||||
#define DISPLACE_MESSAGE_ALERT 14
|
||||
#define DISPLACE_MESSAGE_ALERT_TYPE NULL
|
||||
#define DISPLACE_MESSAGE_ALERT_STRING NULL
|
||||
|
||||
/*
|
||||
* These are the other alert messages that were
|
||||
* added in the 1.5.0 release. The first is never
|
||||
* shown and is intended just for testing.
|
||||
*/
|
||||
|
||||
#define GREETING_MESSAGE_ALERT 15
|
||||
#define GREETING_MESSAGE_ALERT_TYPE "ok"
|
||||
#define GREETING_MESSAGE_ALERT_STRING \
|
||||
"\
|
||||
Welcome to NX from the NoMachine team. We really\n\
|
||||
hope you will enjoy this wonderful software as much\n\
|
||||
as we had fun making it ;-).\n\
|
||||
"
|
||||
|
||||
/*
|
||||
* These alerts are intended to notify the user
|
||||
* of the reason why the agent failed to resume
|
||||
* the session.
|
||||
*/
|
||||
|
||||
#define START_RESUME_SESSION_ALERT 16
|
||||
#define START_RESUME_SESSION_ALERT_TYPE "ok"
|
||||
#define START_RESUME_SESSION_ALERT_STRING \
|
||||
"\
|
||||
You appear to run your NX session across a slow network\n\
|
||||
connection. Resuming the session may require some time.\n\
|
||||
Please wait.\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_DISPLAY_ALERT 17
|
||||
#define FAILED_RESUME_DISPLAY_ALERT_TYPE "error"
|
||||
#define FAILED_RESUME_DISPLAY_ALERT_STRING \
|
||||
"\
|
||||
Failed to open the display. Can't resume the NX\n\
|
||||
session on this display.\n\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_DISPLAY_BROKEN_ALERT 18
|
||||
#define FAILED_RESUME_DISPLAY_BROKEN_TYPE "error"
|
||||
#define FAILED_RESUME_DISPLAY_BROKEN_STRING \
|
||||
"\
|
||||
The display connection was broken while trying to\n\
|
||||
resume the session. Please, check your network\n\
|
||||
connection and try again.\n\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_VISUALS_ALERT 19
|
||||
#define FAILED_RESUME_VISUALS_ALERT_TYPE "error"
|
||||
#define FAILED_RESUME_VISUALS_ALERT_STRING \
|
||||
"\
|
||||
Failed to restore all the required visuals.\n\
|
||||
Can't resume the NX session on this display.\n\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_COLORMAPS_ALERT 20
|
||||
#define FAILED_RESUME_COLORMAPS_ALERT_TYPE "error"
|
||||
#define FAILED_RESUME_COLORMAPS_ALERT_STRING \
|
||||
"\
|
||||
The number of available colormaps is different\n\
|
||||
on the new display. Can't resume the NX session\n\
|
||||
on this display.\n\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_PIXMAPS_ALERT 21
|
||||
#define FAILED_RESUME_PIXMAPS_ALERT_TYPE "error"
|
||||
#define FAILED_RESUME_PIXMAPS_ALERT_STRING \
|
||||
"\
|
||||
Failed to restore all the required pixmap formats.\n\
|
||||
Can't resume the NX session on this display.\n\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_DEPTHS_ALERT 22
|
||||
#define FAILED_RESUME_DEPTHS_ALERT_TYPE "error"
|
||||
#define FAILED_RESUME_DEPTHS_ALERT_STRING \
|
||||
"\
|
||||
Failed to restore all the required screen depths.\n\
|
||||
Can't resume the NX session on this display.\n\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_RENDER_ALERT 23
|
||||
#define FAILED_RESUME_RENDER_ALERT_TYPE "error"
|
||||
#define FAILED_RESUME_RENDER_ALERT_STRING \
|
||||
"\
|
||||
The render extension is missing or an incompatible\n\
|
||||
version was detected on your X server. Can't resume\n\
|
||||
the NX session on this display.\n\
|
||||
"
|
||||
|
||||
#define FAILED_RESUME_FONTS_ALERT 24
|
||||
#define FAILED_RESUME_FONTS_ALERT_TYPE "error"
|
||||
#define FAILED_RESUME_FONTS_ALERT_STRING \
|
||||
"\
|
||||
One or more of the fonts that are in use by the\n\
|
||||
session are missing. Can't resume the NX session\n\
|
||||
on this display.\n\
|
||||
"
|
||||
|
||||
#define ABORT_PROXY_NEGOTIATION_ALERT 62
|
||||
#define ABORT_PROXY_NEGOTIATION_ALERT_TYPE "ok"
|
||||
#define ABORT_PROXY_NEGOTIATION_ALERT_STRING \
|
||||
"\
|
||||
The remote proxy closed the connection while negotiating\n\
|
||||
the session. This may be due to the wrong authentication\n\
|
||||
credentials passed to the server.\n\
|
||||
"
|
||||
|
||||
#define ABORT_PROXY_SHUTDOWN_ALERT 64
|
||||
#define ABORT_PROXY_SHUTDOWN_ALERT_TYPE "ok"
|
||||
#define ABORT_PROXY_SHUTDOWN_ALERT_STRING \
|
||||
"\
|
||||
No response received from the remote proxy while\n\
|
||||
waiting for the session shutdown.\n\
|
||||
"
|
||||
|
||||
#define FAILED_XDMCP_CONNECTION_ALERT 65
|
||||
#define FAILED_XDMCP_CONNECTION_ALERT_TYPE "ok"
|
||||
#define FAILED_XDMCP_CONNECTION_ALERT_STRING \
|
||||
"\
|
||||
The XDM host that was contacted by the NX server doesn't\n\
|
||||
seem to be able to start the session. Please check your\n\
|
||||
server configuration.\n\
|
||||
"
|
||||
|
||||
/*
|
||||
* Used to handle the backward compatibility.
|
||||
* Update the numbers if you add a new alert.
|
||||
*/
|
||||
|
||||
#define LAST_PROTO_STEP_6_ALERT 63
|
||||
#define LAST_PROTO_STEP_7_ALERT 65
|
||||
|
||||
#endif /* NXalert_H */
|
||||
141
nxcomp/include/NXpack.h
Normal file
141
nxcomp/include/NXpack.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NXpack_H
|
||||
#define NXpack_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MASK_METHOD_LIMIT 10
|
||||
|
||||
#define NO_MASK 0
|
||||
|
||||
#define MASK_8_COLORS 1
|
||||
#define MASK_64_COLORS 2
|
||||
#define MASK_256_COLORS 3
|
||||
#define MASK_512_COLORS 4
|
||||
#define MASK_4K_COLORS 5
|
||||
#define MASK_32K_COLORS 6
|
||||
#define MASK_64K_COLORS 7
|
||||
#define MASK_256K_COLORS 8
|
||||
#define MASK_2M_COLORS 9
|
||||
#define MASK_16M_COLORS 10
|
||||
|
||||
#define PACK_METHOD_LIMIT 128
|
||||
|
||||
#define NO_PACK 0
|
||||
|
||||
#define PACK_MASKED_8_COLORS 1
|
||||
#define PACK_MASKED_64_COLORS 2
|
||||
#define PACK_MASKED_256_COLORS 3
|
||||
#define PACK_MASKED_512_COLORS 4
|
||||
#define PACK_MASKED_4K_COLORS 5
|
||||
#define PACK_MASKED_32K_COLORS 6
|
||||
#define PACK_MASKED_64K_COLORS 7
|
||||
#define PACK_MASKED_256K_COLORS 8
|
||||
#define PACK_MASKED_2M_COLORS 9
|
||||
#define PACK_MASKED_16M_COLORS 10
|
||||
|
||||
#define PACK_RAW_8_BITS 3
|
||||
#define PACK_RAW_16_BITS 7
|
||||
#define PACK_RAW_24_BITS 10
|
||||
|
||||
#define PACK_COLORMAP_256_COLORS 11
|
||||
|
||||
#define PACK_JPEG_8_COLORS 26
|
||||
#define PACK_JPEG_64_COLORS 27
|
||||
#define PACK_JPEG_256_COLORS 28
|
||||
#define PACK_JPEG_512_COLORS 29
|
||||
#define PACK_JPEG_4K_COLORS 30
|
||||
#define PACK_JPEG_32K_COLORS 31
|
||||
#define PACK_JPEG_64K_COLORS 32
|
||||
#define PACK_JPEG_256K_COLORS 33
|
||||
#define PACK_JPEG_2M_COLORS 34
|
||||
#define PACK_JPEG_16M_COLORS 35
|
||||
|
||||
#define PACK_PNG_8_COLORS 37
|
||||
#define PACK_PNG_64_COLORS 38
|
||||
#define PACK_PNG_256_COLORS 39
|
||||
#define PACK_PNG_512_COLORS 40
|
||||
#define PACK_PNG_4K_COLORS 41
|
||||
#define PACK_PNG_32K_COLORS 42
|
||||
#define PACK_PNG_64K_COLORS 43
|
||||
#define PACK_PNG_256K_COLORS 44
|
||||
#define PACK_PNG_2M_COLORS 45
|
||||
#define PACK_PNG_16M_COLORS 46
|
||||
|
||||
#define PACK_RGB_16M_COLORS 63
|
||||
#define PACK_RLE_16M_COLORS 64
|
||||
|
||||
#define PACK_ALPHA 65
|
||||
#define PACK_COLORMAP 66
|
||||
|
||||
#define PACK_BITMAP_16M_COLORS 67
|
||||
|
||||
/*
|
||||
* Not really pack methods. These values
|
||||
* allow dynamic selection of the pack
|
||||
* method by the agent.
|
||||
*/
|
||||
|
||||
#define PACK_NONE 0
|
||||
#define PACK_LOSSY 253
|
||||
#define PACK_LOSSLESS 254
|
||||
#define PACK_ADAPTIVE 255
|
||||
|
||||
/*
|
||||
* Reduce the number of colors in the
|
||||
* image by applying a mask.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int color_mask;
|
||||
unsigned int correction_mask;
|
||||
unsigned int white_threshold;
|
||||
unsigned int black_threshold;
|
||||
|
||||
} ColorMask;
|
||||
|
||||
extern const ColorMask Mask8TrueColor;
|
||||
extern const ColorMask Mask64TrueColor;
|
||||
extern const ColorMask Mask512TrueColor;
|
||||
extern const ColorMask Mask4KTrueColor;
|
||||
extern const ColorMask Mask32KTrueColor;
|
||||
extern const ColorMask Mask256KTrueColor;
|
||||
extern const ColorMask Mask2MTrueColor;
|
||||
extern const ColorMask Mask16MTrueColor;
|
||||
|
||||
const ColorMask *MethodColorMask(unsigned int method);
|
||||
|
||||
int MethodBitsPerPixel(unsigned int method);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NXpack_H */
|
||||
447
nxcomp/include/NXproto.h
Normal file
447
nxcomp/include/NXproto.h
Normal file
@@ -0,0 +1,447 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NXproto_H
|
||||
#define NXproto_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xmd.h>
|
||||
#include <X11/Xproto.h>
|
||||
|
||||
/*
|
||||
* Force the size to match the wire protocol.
|
||||
*/
|
||||
|
||||
#define Drawable CARD32
|
||||
#define GContext CARD32
|
||||
|
||||
#define sz_xNXGetControlParametersReq 4
|
||||
#define sz_xNXGetCleanupParametersReq 4
|
||||
#define sz_xNXGetImageParametersReq 4
|
||||
#define sz_xNXGetUnpackParametersReq 8
|
||||
#define sz_xNXGetShmemParametersReq 16
|
||||
#define sz_xNXGetFontParametersReq 4
|
||||
#define sz_xNXSetExposeParametersReq 8
|
||||
#define sz_xNXSetCacheParametersReq 8
|
||||
#define sz_xNXStartSplitReq 8
|
||||
#define sz_xNXEndSplitReq 4
|
||||
#define sz_xNXCommitSplitReq 12
|
||||
#define sz_xNXSetUnpackGeometryReq 24
|
||||
#define sz_xNXSetUnpackColormapReq 16
|
||||
#define sz_xNXSetUnpackAlphaReq 16
|
||||
#define sz_xNXPutPackedImageReq 40
|
||||
#define sz_xNXFreeUnpackReq 4
|
||||
#define sz_xNXFinishSplitReq 4
|
||||
#define sz_xNXAbortSplitReq 4
|
||||
#define sz_xNXFreeSplitReq 4
|
||||
|
||||
#define sz_xGetControlParametersReply 32
|
||||
#define sz_xGetCleanupParametersReply 32
|
||||
#define sz_xGetImageParametersReply 32
|
||||
#define sz_xGetUnpackParametersReply 32
|
||||
#define sz_xGetShmemParametersReply 32
|
||||
|
||||
#define LINK_TYPE_LIMIT 5
|
||||
|
||||
#define LINK_TYPE_NONE 0
|
||||
#define LINK_TYPE_MODEM 1
|
||||
#define LINK_TYPE_ISDN 2
|
||||
#define LINK_TYPE_ADSL 3
|
||||
#define LINK_TYPE_WAN 4
|
||||
#define LINK_TYPE_LAN 5
|
||||
|
||||
/*
|
||||
* NX Replies.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following reply has 4 new boolean
|
||||
* fields in the last protocol version.
|
||||
*/
|
||||
|
||||
typedef struct _NXGetControlParametersReply {
|
||||
BYTE type; /* Is X_Reply. */
|
||||
CARD8 linkType;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32; /* Is 0. */
|
||||
CARD8 localMajor;
|
||||
CARD8 localMinor;
|
||||
CARD8 localPatch;
|
||||
CARD8 remoteMajor;
|
||||
CARD8 remoteMinor;
|
||||
CARD8 remotePatch;
|
||||
CARD16 splitTimeout B16;
|
||||
CARD16 motionTimeout B16;
|
||||
CARD8 splitMode;
|
||||
CARD8 pad1;
|
||||
CARD32 splitSize B32;
|
||||
CARD8 packMethod;
|
||||
CARD8 packQuality;
|
||||
CARD8 dataLevel;
|
||||
CARD8 streamLevel;
|
||||
CARD8 deltaLevel;
|
||||
CARD8 loadCache;
|
||||
CARD8 saveCache;
|
||||
CARD8 startupCache;
|
||||
} xNXGetControlParametersReply;
|
||||
|
||||
typedef struct _NXGetCleanupParametersReply {
|
||||
BYTE type; /* Is X_Reply. */
|
||||
BYTE pad;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32; /* Is 0. */
|
||||
BOOL cleanGet;
|
||||
BOOL cleanAlloc;
|
||||
BOOL cleanFlush;
|
||||
BOOL cleanSend;
|
||||
BOOL cleanImages;
|
||||
BYTE pad1, pad2, pad3;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
CARD32 pad7 B32;
|
||||
} xNXGetCleanupParametersReply;
|
||||
|
||||
typedef struct _NXGetImageParametersReply {
|
||||
BYTE type; /* Is X_Reply. */
|
||||
BYTE pad;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32; /* Is 0. */
|
||||
BOOL imageSplit;
|
||||
BOOL imageMask;
|
||||
BOOL imageFrame;
|
||||
CARD8 imageMaskMethod;
|
||||
CARD8 imageSplitMethod;
|
||||
BYTE pad1, pad2, pad3;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
CARD32 pad7 B32;
|
||||
} xNXGetImageParametersReply;
|
||||
|
||||
/*
|
||||
* Data is made of PACK_METHOD_LIMIT values of
|
||||
* type BOOL telling which unpack capabilities
|
||||
* are implemented in proxy.
|
||||
*/
|
||||
|
||||
typedef struct _NXGetUnpackParametersReply {
|
||||
BYTE type; /* Is X_Reply. */
|
||||
BYTE pad;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32; /* Is PACK_METHOD_LIMIT / 4 from NXpack.h. */
|
||||
CARD8 entries; /* Is PACK_METHOD_LIMIT. */
|
||||
BYTE pad1, pad2, pad3;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
CARD32 pad7 B32;
|
||||
CARD32 pad8 B32;
|
||||
} xNXGetUnpackParametersReply;
|
||||
|
||||
typedef struct _NXGetShmemParametersReply {
|
||||
BYTE type; /* Is X_Reply. */
|
||||
CARD8 stage; /* As in the corresponding request. */
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32; /* Is 0. */
|
||||
BOOL clientEnabled; /* SHM on path agent to proxy. */
|
||||
BOOL serverEnabled; /* SHM on path proxy to X server. */
|
||||
BYTE pad1, pad2; /* Previous values can be checked */
|
||||
CARD32 clientSize B32; /* at end of stage 2. */
|
||||
CARD32 serverSize B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
} xNXGetShmemParametersReply;
|
||||
|
||||
typedef struct _NXGetFontParametersReply {
|
||||
BYTE type; /* Is X_Reply. */
|
||||
BYTE pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32; /* Is length of path string + 1 / 4. */
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
CARD32 pad7 B32;
|
||||
} xNXGetFontParametersReply;
|
||||
|
||||
/*
|
||||
* NX Requests.
|
||||
*/
|
||||
|
||||
typedef struct _NXGetControlParametersReq {
|
||||
CARD8 reqType;
|
||||
BYTE pad;
|
||||
CARD16 length B16;
|
||||
} xNXGetControlParametersReq;
|
||||
|
||||
typedef struct _NXGetCleanupParametersReq {
|
||||
CARD8 reqType;
|
||||
BYTE pad;
|
||||
CARD16 length B16;
|
||||
} xNXGetCleanupParametersReq;
|
||||
|
||||
typedef struct _NXGetImageParametersReq {
|
||||
CARD8 reqType;
|
||||
BYTE pad;
|
||||
CARD16 length B16;
|
||||
} xNXGetImageParametersReq;
|
||||
|
||||
typedef struct _NXGetUnpackParametersReq {
|
||||
CARD8 reqType;
|
||||
BYTE pad;
|
||||
CARD16 length B16;
|
||||
CARD8 entries;
|
||||
BYTE pad1, pad2, pad3;
|
||||
} xNXGetUnpackParametersReq;
|
||||
|
||||
typedef struct _NXGetShmemParametersReq {
|
||||
CARD8 reqType;
|
||||
CARD8 stage; /* It is between 0 and 2. */
|
||||
CARD16 length B16;
|
||||
BOOL enableClient; /* X client side support is */
|
||||
BOOL enableServer; /* not implemented yet. */
|
||||
BYTE pad1, pad2;
|
||||
CARD32 clientSegment; /* XID identifying the shared */
|
||||
CARD32 serverSegment; /* memory segments. */
|
||||
} xNXGetShmemParametersReq;
|
||||
|
||||
typedef struct _NXGetFontParametersReq {
|
||||
CARD8 reqType;
|
||||
CARD8 pad;
|
||||
CARD16 length B16;
|
||||
} xNXGetFontParametersReq;
|
||||
|
||||
/*
|
||||
* The available split modes.
|
||||
*/
|
||||
|
||||
#define NXSplitModeDefault 0
|
||||
#define NXSplitModeAsync 1
|
||||
#define NXSplitModeSync 2
|
||||
|
||||
typedef struct _NXStartSplitReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
CARD8 mode;
|
||||
BYTE pad1, pad2, pad3;
|
||||
} xNXStartSplitReq;
|
||||
|
||||
typedef struct _NXEndSplitReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
} xNXEndSplitReq;
|
||||
|
||||
typedef struct _NXCommitSplitReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
CARD8 propagate;
|
||||
CARD8 request;
|
||||
BYTE pad1, pad2;
|
||||
CARD32 position B32;
|
||||
} xNXCommitSplitReq;
|
||||
|
||||
typedef struct _NXFinishSplitReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
} xNXFinishSplitReq;
|
||||
|
||||
typedef struct _NXAbortSplitReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
} xNXAbortSplitReq;
|
||||
|
||||
typedef struct _NXFreeSplitReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
} xNXFreeSplitReq;
|
||||
|
||||
typedef struct _NXSetExposeParametersReq {
|
||||
CARD8 reqType;
|
||||
BYTE pad;
|
||||
CARD16 length B16;
|
||||
BOOL expose;
|
||||
BOOL graphicsExpose;
|
||||
BOOL noExpose;
|
||||
BYTE pad1;
|
||||
} xNXSetExposeParametersReq;
|
||||
|
||||
typedef struct _NXSetCacheParametersReq {
|
||||
CARD8 reqType;
|
||||
BYTE pad;
|
||||
CARD16 length B16;
|
||||
BOOL enableCache;
|
||||
BOOL enableSplit;
|
||||
BOOL enableSave;
|
||||
BOOL enableLoad;
|
||||
} xNXSetCacheParametersReq;
|
||||
|
||||
typedef struct _NXSetUnpackGeometryReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
CARD8 depth1Bpp;
|
||||
CARD8 depth4Bpp;
|
||||
CARD8 depth8Bpp;
|
||||
CARD8 depth16Bpp;
|
||||
CARD8 depth24Bpp;
|
||||
CARD8 depth32Bpp;
|
||||
BYTE pad1, pad2;
|
||||
CARD32 redMask B32;
|
||||
CARD32 greenMask B32;
|
||||
CARD32 blueMask B32;
|
||||
} xNXSetUnpackGeometryReq;
|
||||
|
||||
typedef struct _NXSetUnpackColormapReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
CARD8 method;
|
||||
BYTE pad1, pad2, pad3;
|
||||
CARD32 srcLength B32;
|
||||
CARD32 dstLength B32;
|
||||
} xNXSetUnpackColormapReq;
|
||||
|
||||
typedef struct _NXSetUnpackAlphaReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
CARD8 method;
|
||||
BYTE pad1, pad2, pad3;
|
||||
CARD32 srcLength B32;
|
||||
CARD32 dstLength B32;
|
||||
} xNXSetUnpackAlphaReq;
|
||||
|
||||
typedef struct _NXPutPackedImageReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
Drawable drawable B32;
|
||||
GContext gc B32;
|
||||
CARD8 method;
|
||||
CARD8 format;
|
||||
CARD8 srcDepth;
|
||||
CARD8 dstDepth;
|
||||
CARD32 srcLength B32;
|
||||
CARD32 dstLength B32;
|
||||
INT16 srcX B16, srcY B16;
|
||||
CARD16 srcWidth B16, srcHeight B16;
|
||||
INT16 dstX B16, dstY B16;
|
||||
CARD16 dstWidth B16, dstHeight B16;
|
||||
} xNXPutPackedImageReq;
|
||||
|
||||
typedef struct _NXFreeUnpackReq {
|
||||
CARD8 reqType;
|
||||
CARD8 resource;
|
||||
CARD16 length B16;
|
||||
} xNXFreeUnpackReq;
|
||||
|
||||
/*
|
||||
* The X_NXSplitData and X_NXSplitEvent opcodes
|
||||
* are used internally and are ignored if coming
|
||||
* from the agent.
|
||||
*/
|
||||
|
||||
#define X_NXInternalGenericData 0
|
||||
#define X_NXInternalGenericReply 1
|
||||
#define X_NXInternalGenericRequest 255
|
||||
|
||||
#define X_NXInternalShapeExtension 128
|
||||
#define X_NXInternalRenderExtension 129
|
||||
|
||||
#define X_NXFirstOpcode 230
|
||||
#define X_NXLastOpcode 252
|
||||
|
||||
#define X_NXGetControlParameters 230
|
||||
#define X_NXGetCleanupParameters 231
|
||||
#define X_NXGetImageParameters 232
|
||||
#define X_NXGetUnpackParameters 233
|
||||
#define X_NXStartSplit 234
|
||||
#define X_NXEndSplit 235
|
||||
#define X_NXSplitData 236
|
||||
#define X_NXCommitSplit 237
|
||||
#define X_NXSetExposeParameters 240
|
||||
#define X_NXSetUnpackGeometry 241
|
||||
#define X_NXSetUnpackColormap 242
|
||||
#define X_NXPutPackedImage 243
|
||||
#define X_NXSplitEvent 244
|
||||
#define X_NXGetShmemParameters 245
|
||||
#define X_NXSetUnpackAlpha 246
|
||||
#define X_NXFreeUnpack 247
|
||||
#define X_NXFinishSplit 248
|
||||
#define X_NXAbortSplit 249
|
||||
#define X_NXFreeSplit 250
|
||||
#define X_NXGetFontParameters 251
|
||||
#define X_NXSetCacheParameters 252
|
||||
|
||||
/*
|
||||
* The following events are received by the agent
|
||||
* in the form of a ClientMessage with the value
|
||||
* 0 in fields atom and window. The format is
|
||||
* always 32. Event specific data starts at byte
|
||||
* offset 12.
|
||||
*
|
||||
* These events are sent by the NX transport to
|
||||
* notify the agent about the result of a split
|
||||
* operation.
|
||||
*/
|
||||
|
||||
#define NXNoSplitNotify 1
|
||||
#define NXStartSplitNotify 2
|
||||
#define NXCommitSplitNotify 3
|
||||
#define NXEndSplitNotify 4
|
||||
#define NXEmptySplitNotify 5
|
||||
|
||||
/*
|
||||
* Notifications of collect events. These events
|
||||
* don't come from the NX transport but are put
|
||||
* back in client's event queue by NXlib.
|
||||
*/
|
||||
|
||||
#define NXCollectImageNotify 8
|
||||
#define NXCollectPropertyNotify 9
|
||||
#define NXCollectGrabPointerNotify 10
|
||||
#define NXCollectInputFocusNotify 11
|
||||
|
||||
#undef Drawable
|
||||
#undef GContext
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NXproto_H */
|
||||
201
nxcomp/include/NXvars.h
Normal file
201
nxcomp/include/NXvars.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NXvars_H
|
||||
#define NXvars_H
|
||||
|
||||
/*
|
||||
* This can be included by the proxy or another
|
||||
* layer that doesn't use Xlib.
|
||||
*/
|
||||
|
||||
#if !defined(_XLIB_H_) && !defined(_XKBSRV_H_)
|
||||
|
||||
#define NeedFunctionPrototypes 1
|
||||
|
||||
#define Display void
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Display flush policies.
|
||||
*/
|
||||
|
||||
#define NXPolicyImmediate 1
|
||||
#define NXPolicyDeferred 2
|
||||
|
||||
/*
|
||||
* Type of flush.
|
||||
*/
|
||||
|
||||
#define NXFlushBuffer 0
|
||||
#define NXFlushLink 1
|
||||
|
||||
/*
|
||||
* Type of statistics.
|
||||
*/
|
||||
|
||||
#define NXStatisticsPartial 0
|
||||
#define NXStatisticsTotal 1
|
||||
|
||||
/*
|
||||
* Reason why the display is blocking.
|
||||
*/
|
||||
|
||||
#define NXBlockRead 1
|
||||
#define NXBlockWrite 2
|
||||
|
||||
/*
|
||||
* Set if the client is interested in ignoring
|
||||
* the display error and continue with the exe-
|
||||
* cution of the program. By default the usual
|
||||
* Xlib behaviour is gotten, and the library
|
||||
* will call an exit().
|
||||
*/
|
||||
|
||||
extern int _NXHandleDisplayError;
|
||||
|
||||
/*
|
||||
* The function below is called whenever Xlib is
|
||||
* going to perform an I/O operation. The funct-
|
||||
* ion can be redefined to include additional
|
||||
* checks aimed at detecting if the display needs
|
||||
* to be closed, for example because of an event
|
||||
* or a signal mandating the end of the session.
|
||||
* In this way the client program can regain the
|
||||
* control before Xlib blocks waiting for input
|
||||
* from the network.
|
||||
*/
|
||||
|
||||
typedef int (*NXDisplayErrorPredicate)(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* display */,
|
||||
int /* reason */
|
||||
#endif
|
||||
);
|
||||
|
||||
extern NXDisplayErrorPredicate _NXDisplayErrorFunction;
|
||||
|
||||
/*
|
||||
* This is called when Xlib is going to block
|
||||
* waiting for the display to become readable or
|
||||
* writable. The client can use the hook to run
|
||||
* any arbitrary operation that may require some
|
||||
* time to complete. The user should not try to
|
||||
* read or write to the display inside the call-
|
||||
* back routine.
|
||||
*/
|
||||
|
||||
typedef void (*NXDisplayBlockHandler)(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* display */,
|
||||
int /* reason */
|
||||
#endif
|
||||
);
|
||||
|
||||
extern NXDisplayBlockHandler _NXDisplayBlockFunction;
|
||||
|
||||
/*
|
||||
* Used to notify the program when more data
|
||||
* is written to the socket.
|
||||
*/
|
||||
|
||||
typedef void (*NXDisplayWriteHandler)(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* display */,
|
||||
int /* length */
|
||||
#endif
|
||||
);
|
||||
|
||||
extern NXDisplayWriteHandler _NXDisplayWriteFunction;
|
||||
|
||||
/*
|
||||
* This callback is used to notify the agent
|
||||
* that the proxy link has been flushed.
|
||||
*/
|
||||
|
||||
typedef void (*NXDisplayFlushHandler)(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* display */,
|
||||
int /* length */
|
||||
#endif
|
||||
);
|
||||
|
||||
extern NXDisplayFlushHandler _NXDisplayFlushFunction;
|
||||
|
||||
/*
|
||||
* Used by the NX transport to get an arbitrary
|
||||
* string to add to its protocol statistics.
|
||||
*/
|
||||
|
||||
typedef void (*NXDisplayStatisticsHandler)(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* display */,
|
||||
char* /* buffer */,
|
||||
int /* size */
|
||||
#endif
|
||||
);
|
||||
|
||||
extern NXDisplayStatisticsHandler _NXDisplayStatisticsFunction;
|
||||
|
||||
/*
|
||||
* Let users redefine the function printing an
|
||||
* error message in the case of a out-of-order
|
||||
* sequence number.
|
||||
*/
|
||||
|
||||
typedef void (*NXLostSequenceHandler)(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* display */,
|
||||
unsigned long /* newseq */,
|
||||
unsigned long /* lastseq */,
|
||||
unsigned int /* type */
|
||||
#endif
|
||||
);
|
||||
|
||||
extern NXLostSequenceHandler _NXLostSequenceFunction;
|
||||
|
||||
/*
|
||||
* Let the X server run the children processes
|
||||
* (as for example the keyboard initialization
|
||||
* utilities) by using the native system libra-
|
||||
* ries, instead of the libraries shipped with
|
||||
* the NX environment. If set, the Popen() in
|
||||
* the X server will remove the LD_LIBRARY_PATH
|
||||
* setting from the environment before calling
|
||||
* the execl() function in the child process.
|
||||
*/
|
||||
|
||||
extern int _NXUnsetLibraryPath;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NXvars_H */
|
||||
1
nxcomp/m4/ax_cxx_compile_stdcxx.m4
Symbolic link
1
nxcomp/m4/ax_cxx_compile_stdcxx.m4
Symbolic link
@@ -0,0 +1 @@
|
||||
../../m4/ax_cxx_compile_stdcxx.m4
|
||||
1
nxcomp/m4/ax_cxx_compile_stdcxx_11.m4
Symbolic link
1
nxcomp/m4/ax_cxx_compile_stdcxx_11.m4
Symbolic link
@@ -0,0 +1 @@
|
||||
../../m4/ax_cxx_compile_stdcxx_11.m4
|
||||
1
nxcomp/m4/ax_pthread.m4
Symbolic link
1
nxcomp/m4/ax_pthread.m4
Symbolic link
@@ -0,0 +1 @@
|
||||
../../m4/ax_pthread.m4
|
||||
1
nxcomp/m4/nx-macros.m4
Symbolic link
1
nxcomp/m4/nx-macros.m4
Symbolic link
@@ -0,0 +1 @@
|
||||
../../m4/nx-macros.m4
|
||||
15
nxcomp/nxcomp.pc.in
Normal file
15
nxcomp/nxcomp.pc.in
Normal file
@@ -0,0 +1,15 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: nxcomp
|
||||
Description: NX Compression Library
|
||||
Version: @COMP_VERSION@
|
||||
#libjepg does not provide a pkgconfig-file, zlib does not provide it for older versions
|
||||
#Requires: libjpeg zlib
|
||||
Requires: libpng
|
||||
Requires.private: x11
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lXcomp
|
||||
|
||||
51
nxcomp/src/ActionCache.cpp
Normal file
51
nxcomp/src/ActionCache.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Control.h"
|
||||
|
||||
#include "ActionCache.h"
|
||||
|
||||
ActionCache::ActionCache()
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
base_[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
slot_ = 0;
|
||||
last_ = 0;
|
||||
}
|
||||
|
||||
ActionCache::~ActionCache()
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
delete base_[i];
|
||||
}
|
||||
}
|
||||
49
nxcomp/src/ActionCache.h
Normal file
49
nxcomp/src/ActionCache.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ActionCache_H
|
||||
#define ActionCache_H
|
||||
|
||||
#include "IntCache.h"
|
||||
|
||||
class ActionCache
|
||||
{
|
||||
friend class EncodeBuffer;
|
||||
friend class DecodeBuffer;
|
||||
|
||||
public:
|
||||
|
||||
ActionCache();
|
||||
~ActionCache();
|
||||
|
||||
private:
|
||||
|
||||
IntCache *base_[256];
|
||||
|
||||
unsigned int slot_;
|
||||
unsigned short last_;
|
||||
};
|
||||
|
||||
#endif /* ActionCache_H */
|
||||
84
nxcomp/src/Agent.cpp
Normal file
84
nxcomp/src/Agent.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Agent.h"
|
||||
#include "Proxy.h"
|
||||
|
||||
extern Proxy *proxy;
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
Agent::Agent(int fd[2])
|
||||
{
|
||||
remoteFd_ = fd[0];
|
||||
localFd_ = fd[1];
|
||||
|
||||
transport_ = new AgentTransport(localFd_);
|
||||
|
||||
if (transport_ == NULL)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Agent: PANIC! Can't create the memory-to-memory transport "
|
||||
<< "for FD#" << localFd_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Can't create the memory-to-memory transport "
|
||||
<< "for FD#" << localFd_ << ".\n";
|
||||
|
||||
HandleCleanup();
|
||||
}
|
||||
|
||||
FD_ZERO(&saveRead_);
|
||||
FD_ZERO(&saveWrite_);
|
||||
|
||||
canRead_ = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "Agent: Created agent object at " << this
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
Agent::~Agent()
|
||||
{
|
||||
delete transport_;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "Agent: Deleted agent object at " << this
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
263
nxcomp/src/Agent.h
Normal file
263
nxcomp/src/Agent.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef Agent_H
|
||||
#define Agent_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Transport.h"
|
||||
#include "Proxy.h"
|
||||
|
||||
extern Proxy *proxy;
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
class Agent
|
||||
{
|
||||
public:
|
||||
|
||||
//
|
||||
// Must be created by passing the fake descriptor that
|
||||
// will be used for simulating socket communication
|
||||
// between the agent and the proxy. I/O will take place
|
||||
// by copying data to the agent's read and write buf-
|
||||
// fers.
|
||||
//
|
||||
|
||||
Agent(int fd[2]);
|
||||
|
||||
~Agent();
|
||||
|
||||
AgentTransport *getTransport() const
|
||||
{
|
||||
return transport_;
|
||||
}
|
||||
|
||||
void saveReadMask(fd_set *readSet)
|
||||
{
|
||||
saveRead_ = *readSet;
|
||||
}
|
||||
|
||||
void saveWriteMask(fd_set *writeSet)
|
||||
{
|
||||
saveWrite_ = *writeSet;
|
||||
}
|
||||
|
||||
void clearReadMask(fd_set *readSet)
|
||||
{
|
||||
FD_CLR(remoteFd_, readSet);
|
||||
FD_CLR(localFd_, readSet);
|
||||
}
|
||||
|
||||
void clearWriteMask(fd_set *writeSet)
|
||||
{
|
||||
FD_CLR(remoteFd_, writeSet);
|
||||
FD_CLR(localFd_, writeSet);
|
||||
}
|
||||
|
||||
void setLocalRead(fd_set *readSet, int *result)
|
||||
{
|
||||
(*result)++;
|
||||
|
||||
FD_SET(localFd_, readSet);
|
||||
}
|
||||
|
||||
void setRemoteRead(fd_set *readSet, int *result)
|
||||
{
|
||||
(*result)++;
|
||||
|
||||
FD_SET(remoteFd_, readSet);
|
||||
}
|
||||
|
||||
void setRemoteWrite(fd_set *writeSet, int *result)
|
||||
{
|
||||
(*result)++;
|
||||
|
||||
FD_SET(remoteFd_, writeSet);
|
||||
}
|
||||
|
||||
fd_set *getSavedReadMask()
|
||||
{
|
||||
return &saveRead_;
|
||||
}
|
||||
|
||||
fd_set *getSavedWriteMask()
|
||||
{
|
||||
return &saveWrite_;
|
||||
}
|
||||
|
||||
int getRemoteFd() const
|
||||
{
|
||||
return remoteFd_;
|
||||
}
|
||||
|
||||
int getLocalFd() const
|
||||
{
|
||||
return localFd_;
|
||||
}
|
||||
|
||||
int getProxyFd() const
|
||||
{
|
||||
return proxy -> getFd();
|
||||
}
|
||||
|
||||
int isValid() const
|
||||
{
|
||||
return (transport_ != NULL);
|
||||
}
|
||||
|
||||
int localReadable()
|
||||
{
|
||||
return (transport_ -> readable() != 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Check if we can process more data from
|
||||
// the agent descriptor and cache the result
|
||||
// to avoid multiple calls. This must be
|
||||
// always called before querying the other
|
||||
// functions.
|
||||
//
|
||||
|
||||
void saveChannelState()
|
||||
{
|
||||
canRead_ = (proxy != NULL ? proxy -> canRead(localFd_) : 0);
|
||||
}
|
||||
|
||||
int remoteCanRead(const fd_set * const readSet)
|
||||
{
|
||||
// OS X 10.5 requires the second argument to be non-const, so copy readSet.
|
||||
// It's safe though, as FD_ISSET does not operate on it.
|
||||
fd_set readWorkSet = *readSet;
|
||||
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "Agent: remoteCanRead() is " <<
|
||||
(FD_ISSET(remoteFd_, &readWorkSet) && transport_ -> dequeuable() != 0)
|
||||
<< " with FD_ISSET() " << (int) FD_ISSET(remoteFd_, &readWorkSet)
|
||||
<< " and dequeuable " << transport_ -> dequeuable()
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return (FD_ISSET(remoteFd_, &readWorkSet) &&
|
||||
transport_ -> dequeuable() != 0);
|
||||
}
|
||||
|
||||
int remoteCanWrite(const fd_set * const writeSet)
|
||||
{
|
||||
// OS X 10.5 requires the second argument to be non-const, so copy writeSet.
|
||||
// It's safe though, as FD_ISSET does not operate on it.
|
||||
fd_set writeWorkSet = *writeSet;
|
||||
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "Agent: remoteCanWrite() is " <<
|
||||
(FD_ISSET(remoteFd_, &writeWorkSet) && transport_ ->
|
||||
queuable() != 0 && canRead_ == 1) << " with FD_ISSET() "
|
||||
<< (int) FD_ISSET(remoteFd_, &writeWorkSet) << " queueable "
|
||||
<< transport_ -> queuable() << " channel can read "
|
||||
<< canRead_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return (FD_ISSET(remoteFd_, &writeWorkSet) &&
|
||||
transport_ -> queuable() != 0 &&
|
||||
canRead_ == 1);
|
||||
}
|
||||
|
||||
int localCanRead()
|
||||
{
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "Agent: localCanRead() is " <<
|
||||
(transport_ -> readable() != 0 && canRead_ == 1)
|
||||
<< " with readable " << transport_ -> readable()
|
||||
<< " channel can read " << canRead_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return (transport_ -> readable() != 0 &&
|
||||
canRead_ == 1);
|
||||
}
|
||||
|
||||
int proxyCanRead()
|
||||
{
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "Agent: proxyCanRead() is " << proxy -> canRead()
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return (proxy -> canRead());
|
||||
}
|
||||
|
||||
int proxyCanRead(const fd_set * const readSet)
|
||||
{
|
||||
// OS X 10.5 requires the second argument to be non-const, so copy readSet.
|
||||
// It's safe though, as FD_ISSET does not operate on it.
|
||||
fd_set readWorkSet = *readSet;
|
||||
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "Agent: proxyCanRead() is "
|
||||
<< ((int) FD_ISSET(proxy -> getFd(), &readWorkSet))
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return (FD_ISSET(proxy -> getFd(), &readWorkSet));
|
||||
}
|
||||
|
||||
int enqueueData(const char *data, const int size) const
|
||||
{
|
||||
return transport_ -> enqueue(data, size);
|
||||
}
|
||||
|
||||
int dequeueData(char *data, int size) const
|
||||
{
|
||||
return transport_ -> dequeue(data, size);
|
||||
}
|
||||
|
||||
int dequeuableData() const
|
||||
{
|
||||
return transport_ -> dequeuable();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int remoteFd_;
|
||||
int localFd_;
|
||||
|
||||
fd_set saveRead_;
|
||||
fd_set saveWrite_;
|
||||
|
||||
int canRead_;
|
||||
|
||||
AgentTransport *transport_;
|
||||
};
|
||||
|
||||
#endif /* Agent_H */
|
||||
138
nxcomp/src/Alpha.cpp
Normal file
138
nxcomp/src/Alpha.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Unpack.h"
|
||||
#include "Alpha.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
int UnpackAlpha(unsigned char method, unsigned char *src_data, int src_size,
|
||||
unsigned char *dst_data, int dst_size)
|
||||
{
|
||||
if (*src_data == 0)
|
||||
{
|
||||
if (dst_size != src_size - 1)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackAlpha: PANIC! Invalid destination size "
|
||||
<< dst_size << " with source " << src_size
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackAlpha: Expanding " << src_size - 1
|
||||
<< " bytes of plain alpha data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
memcpy(dst_data, src_data + 1, src_size - 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int check_size = dst_size;
|
||||
|
||||
int result = ZDecompress(&unpackStream, dst_data, &check_size,
|
||||
src_data + 1, src_size - 1);
|
||||
|
||||
if (result != Z_OK)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "UnpackAlpha: PANIC! Failure decompressing alpha data. "
|
||||
<< "Error is '" << zError(result) << "'.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decompressing alpha data. "
|
||||
<< "Error is '" << zError(result) << "'.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if (check_size != (unsigned int) dst_size)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "UnpackAlpha: PANIC! Size mismatch in alpha data. "
|
||||
<< "Resulting size is " << check_size << " with "
|
||||
<< "expected size " << dst_size << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Size mismatch in alpha data. "
|
||||
<< "Resulting size is " << check_size << " with "
|
||||
<< "expected size " << dst_size << ".\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackAlpha: Decompressed " << src_size - 1
|
||||
<< " bytes to " << dst_size << " bytes of alpha data.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UnpackAlpha(T_alpha *alpha, unsigned char *dst_data,
|
||||
int dst_size, int big_endian)
|
||||
{
|
||||
unsigned int count = dst_size >> 2;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
int shift;
|
||||
|
||||
if (count != alpha -> entries)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "UnpackAlpha: WARNING! Not applying the alpha with "
|
||||
<< count << " elements needed and " << alpha -> entries
|
||||
<< " available.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
shift = (big_endian == 1 ? 0 : 3);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
*(dst_data + shift) = *(alpha -> data + i);
|
||||
|
||||
dst_data += 4;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
35
nxcomp/src/Alpha.h
Normal file
35
nxcomp/src/Alpha.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef Alpha_H
|
||||
#define Alpha_H
|
||||
|
||||
int UnpackAlpha(unsigned char method, unsigned char *src_data, int src_size,
|
||||
unsigned char *dst_data, int dst_size);
|
||||
|
||||
int UnpackAlpha(T_alpha *alpha, unsigned char *dst_data,
|
||||
int dst_size, int big_endian);
|
||||
|
||||
#endif /* Aplha_H */
|
||||
685
nxcomp/src/Auth.cpp
Normal file
685
nxcomp/src/Auth.cpp
Normal file
@@ -0,0 +1,685 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Auth.h"
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Control.h"
|
||||
#include "Timestamp.h"
|
||||
#include "Pipe.h"
|
||||
|
||||
#define DEFAULT_STRING_LIMIT 512
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Store the provided cookie as our 'fake' cookie, then
|
||||
// read the 'real' cookie from the current X authority
|
||||
// file.
|
||||
//
|
||||
|
||||
Auth::Auth(char *display, char *cookie)
|
||||
{
|
||||
display_ = NULL;
|
||||
|
||||
file_ = NULL;
|
||||
|
||||
last_ = nullTimestamp();
|
||||
|
||||
fakeCookie_ = NULL;
|
||||
realCookie_ = NULL;
|
||||
|
||||
fakeData_ = NULL;
|
||||
realData_ = NULL;
|
||||
|
||||
dataSize_ = 0;
|
||||
|
||||
generatedCookie_ = 0;
|
||||
|
||||
if (display == NULL || *display == '\0' || cookie == NULL ||
|
||||
*cookie == '\0' || strlen(cookie) != 32)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Can't create the X authorization data "
|
||||
<< "with cookie '" << cookie << "' and display '"
|
||||
<< display << "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Can't create the X authorization data "
|
||||
<< "with cookie '" << cookie << "' and display '"
|
||||
<< display << "'.\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Creating X authorization data with cookie '"
|
||||
<< cookie << "' and display '" << display << "'.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Get a local copy of all parameters.
|
||||
//
|
||||
|
||||
display_ = new char[strlen(display) + 1];
|
||||
file_ = new char[DEFAULT_STRING_LIMIT];
|
||||
|
||||
fakeCookie_ = new char[strlen(cookie) + 1];
|
||||
realCookie_ = new char[DEFAULT_STRING_LIMIT];
|
||||
|
||||
if (display_ == NULL || file_ == NULL ||
|
||||
fakeCookie_ == NULL || realCookie_ == NULL)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Cannot allocate memory for the X "
|
||||
<< "authorization data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Cannot allocate memory for the X "
|
||||
<< "authorization data.\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(display_, display);
|
||||
|
||||
*file_ = '\0';
|
||||
|
||||
strcpy(fakeCookie_, cookie);
|
||||
|
||||
*realCookie_ = '\0';
|
||||
|
||||
//
|
||||
// Get the real cookie from the authorization file.
|
||||
//
|
||||
|
||||
updateCookie();
|
||||
}
|
||||
|
||||
Auth::~Auth()
|
||||
{
|
||||
delete [] display_;
|
||||
delete [] file_;
|
||||
|
||||
delete [] fakeCookie_;
|
||||
delete [] realCookie_;
|
||||
|
||||
delete [] fakeData_;
|
||||
delete [] realData_;
|
||||
}
|
||||
|
||||
//
|
||||
// At the present moment the cookie is read only once,
|
||||
// at the time the instance is initialized. If the auth
|
||||
// file changes along the life of the session, the old
|
||||
// cookie will be used. This works with X servers beca-
|
||||
// use of an undocumented "feature". See nx-X11.
|
||||
//
|
||||
|
||||
int Auth::updateCookie()
|
||||
{
|
||||
if (isTimestamp(last_) == 0)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Reading the X authorization file "
|
||||
<< "with last update at " << strMsTimestamp(last_)
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (getCookie() == 1 && validateCookie() == 1)
|
||||
{
|
||||
//
|
||||
// It should rather be the modification time
|
||||
// the auth file, so we can read it again if
|
||||
// the file is changed.
|
||||
//
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Setting last X authorization file "
|
||||
<< "update at " << strMsTimestamp() << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
last_ = getTimestamp();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Cannot read the cookie from the X "
|
||||
<< "authorization file.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Cannot read the cookie from the X "
|
||||
<< "authorization file.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: WARNING! Skipping check on the X "
|
||||
<< "authorization file.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Auth::getCookie()
|
||||
{
|
||||
//
|
||||
// Check the name of the auth file that we are going to use.
|
||||
// It can be either the value of the XAUTHORITY environment
|
||||
// or the default .Xauthority file in the user's home.
|
||||
//
|
||||
|
||||
char *environment;
|
||||
|
||||
environment = getenv("XAUTHORITY");
|
||||
|
||||
if (environment != NULL && *environment != '\0')
|
||||
{
|
||||
snprintf(file_, DEFAULT_STRING_LIMIT, "%s", environment);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(file_, DEFAULT_STRING_LIMIT, "%s/.Xauthority",
|
||||
control -> HomePath);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Using X authorization file '" << file_
|
||||
<< "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Use the nxauth command on Windows and the Mac, xauth
|
||||
// on all the other platforms. On Windows we assume that
|
||||
// the nxauth command is located under bin in the client
|
||||
// installation directory. On Mac OS X we assume that the
|
||||
// command is located directly in the client installation
|
||||
// directory, to make bundle shipping easier. On all the
|
||||
// other platforms we use the default xauth command that
|
||||
// is in our path.
|
||||
//
|
||||
|
||||
char command[DEFAULT_STRING_LIMIT];
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__CYGWIN32__)
|
||||
|
||||
snprintf(command, DEFAULT_STRING_LIMIT,
|
||||
"%s/bin/nxauth", control -> SystemPath);
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
snprintf(command, DEFAULT_STRING_LIMIT,
|
||||
"%s/nxauth", control -> SystemPath);
|
||||
|
||||
#else
|
||||
|
||||
strcpy(command, "xauth");
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Using X auth command '" << command
|
||||
<< "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// The SSH code forces using the unix:n port when passing localhost:n.
|
||||
// This is probably because localhost:n can fail to return a valid
|
||||
// entry on machines where the hostname for localhost doesn't match
|
||||
// exactly the 'localhost' string. For example, on a freshly installed
|
||||
// Fedora Core 3 I get a 'localhost.localdomain/unix:0' entry. Query-
|
||||
// ing 'xauth list localhost:0' results in an empty result, while the
|
||||
// query 'xauth list unix:0' works as expected. Note anyway that if
|
||||
// the cookie for the TCP connection on 'localhost' is set to a dif-
|
||||
// ferent cookie than the one for the Unix connections, both SSH and
|
||||
// NX will match the wrong cookie and session will fail.
|
||||
//
|
||||
|
||||
char line[DEFAULT_STRING_LIMIT];
|
||||
FILE *data = NULL;
|
||||
int result = -1;
|
||||
|
||||
if (strncmp(display_, "localhost:", 10) == 0)
|
||||
{
|
||||
snprintf(line, DEFAULT_STRING_LIMIT, "unix:%s", display_ + 10);
|
||||
}
|
||||
else if ((0 == strncasecmp(display_, "/tmp/launch", 11)) || (0 == strncasecmp(display_, "/private/tmp/com.apple.launchd", 30)))
|
||||
{
|
||||
/*
|
||||
* Launchd socket support, mostly for OS X, but maybe also other BSD derivates.
|
||||
*/
|
||||
const char *separator = strrchr(display_, ':');
|
||||
|
||||
if ((NULL == separator) || (!isdigit(*(separator + 1))))
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Unable to find separating colon character '"
|
||||
<< "in launchd socket path '" << display_
|
||||
<< "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
goto AuthGetCookieResult;
|
||||
}
|
||||
|
||||
snprintf(line, DEFAULT_STRING_LIMIT, "unix:%s", separator + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(line, DEFAULT_STRING_LIMIT, "%.200s", display_);
|
||||
}
|
||||
|
||||
const char *parameters[256];
|
||||
|
||||
parameters[0] = command;
|
||||
parameters[1] = command;
|
||||
parameters[2] = "-f";
|
||||
parameters[3] = file_;
|
||||
parameters[4] = "list";
|
||||
parameters[5] = line;
|
||||
parameters[6] = NULL;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Executing command ";
|
||||
|
||||
for (int i = 0; i < 256 && parameters[i] != NULL; i++)
|
||||
{
|
||||
*logofs << "[" << parameters[i] << "]";
|
||||
}
|
||||
|
||||
*logofs << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Use the popen() function to read the result
|
||||
// of the command. We would better use our own
|
||||
// implementation.
|
||||
//
|
||||
|
||||
data = Popen((char *const *) parameters, "r");
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Failed to execute the X auth command.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failed to execute the X auth command.\n";
|
||||
|
||||
goto AuthGetCookieResult;
|
||||
}
|
||||
|
||||
if (fgets(line, DEFAULT_STRING_LIMIT, data) == NULL)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "Auth: WARNING! Failed to read data from the X "
|
||||
<< "auth command.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
#ifdef TEST
|
||||
cerr << "Warning" << ": Failed to read data from the X "
|
||||
<< "auth command.\n";
|
||||
#endif
|
||||
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: WARNING! Generating a fake cookie for "
|
||||
<< "X authentication.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
#ifdef TEST
|
||||
cerr << "Warning" << ": Generating a fake cookie for "
|
||||
<< "X authentication.\n";
|
||||
#endif
|
||||
|
||||
generateCookie(realCookie_);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Checking cookie in string '" << line
|
||||
<< "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Skip the hostname in the authority entry
|
||||
// just in case it includes some white spaces.
|
||||
//
|
||||
|
||||
char *cookie = NULL;
|
||||
|
||||
cookie = index(line, ':');
|
||||
|
||||
if (cookie == NULL)
|
||||
{
|
||||
cookie = line;
|
||||
}
|
||||
|
||||
if (sscanf(cookie, "%*s %*s %511s", realCookie_) != 1)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Failed to identify the cookie "
|
||||
<< "in string '" << line << "'.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failed to identify the cookie "
|
||||
<< "in string '" << line << "'.\n";
|
||||
|
||||
goto AuthGetCookieResult;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Got cookie '" << realCookie_
|
||||
<< "' from file '" << file_ << "'.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
result = 1;
|
||||
|
||||
AuthGetCookieResult:
|
||||
|
||||
if (data != NULL)
|
||||
{
|
||||
Pclose(data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int Auth::validateCookie()
|
||||
{
|
||||
unsigned int length = strlen(realCookie_);
|
||||
|
||||
if (length > DEFAULT_STRING_LIMIT / 2 - 1 ||
|
||||
strlen(fakeCookie_) != length)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Size mismatch between cookies '"
|
||||
<< realCookie_ << "' and '" << fakeCookie_ << "'.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Size mismatch between cookies '"
|
||||
<< realCookie_ << "' and '" << fakeCookie_ << "'.\n";
|
||||
|
||||
goto AuthValidateCookieError;
|
||||
}
|
||||
|
||||
//
|
||||
// The length of the resulting data will be
|
||||
// half the size of the Hex cookie.
|
||||
//
|
||||
|
||||
length = length / 2;
|
||||
|
||||
fakeData_ = new char[length];
|
||||
realData_ = new char[length];
|
||||
|
||||
if (fakeData_ == NULL || realData_ == NULL)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Cannot allocate memory for the binary X "
|
||||
<< "authorization data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Cannot allocate memory for the binary X "
|
||||
<< "authorization data.\n";
|
||||
|
||||
goto AuthValidateCookieError;
|
||||
}
|
||||
|
||||
//
|
||||
// Translate the real cookie from Hex data
|
||||
// to its binary representation.
|
||||
//
|
||||
|
||||
unsigned int value;
|
||||
|
||||
for (unsigned int i = 0; i < length; i++)
|
||||
{
|
||||
if (sscanf(realCookie_ + 2 * i, "%2x", &value) != 1)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Bad X authorization data in real "
|
||||
<< "cookie '" << realCookie_ << "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Bad X authorization data in real cookie '"
|
||||
<< realCookie_ << "'.\n";
|
||||
|
||||
goto AuthValidateCookieError;
|
||||
}
|
||||
|
||||
realData_[i] = value;
|
||||
|
||||
if (sscanf(fakeCookie_ + 2 * i, "%2x", &value) != 1)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Bad X authorization data in fake "
|
||||
<< "cookie '" << fakeCookie_ << "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Bad X authorization data in fake cookie '"
|
||||
<< fakeCookie_ << "'.\n";
|
||||
|
||||
goto AuthValidateCookieError;
|
||||
}
|
||||
|
||||
fakeData_[i] = value;
|
||||
}
|
||||
|
||||
dataSize_ = length;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Validated real cookie '"
|
||||
<< realCookie_ << "' and fake cookie '" << fakeCookie_
|
||||
<< "' with data with size " << dataSize_ << ".\n"
|
||||
<< logofs_flush;
|
||||
|
||||
*logofs << "Auth: Ready to accept incoming connections.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
AuthValidateCookieError:
|
||||
|
||||
delete [] fakeData_;
|
||||
delete [] realData_;
|
||||
|
||||
fakeData_ = NULL;
|
||||
realData_ = NULL;
|
||||
|
||||
dataSize_ = 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Auth::checkCookie(unsigned char *buffer)
|
||||
{
|
||||
if (isValid() != 1)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Auth: PANIC! Attempt to check the X cookie with "
|
||||
<< "invalid authorization data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Attempt to check the X cookie with "
|
||||
<< "invalid authorization data.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *protoName = "MIT-MAGIC-COOKIE-1";
|
||||
int protoSize = strlen(protoName);
|
||||
|
||||
int matchedProtoSize;
|
||||
int matchedDataSize;
|
||||
|
||||
if (buffer[0] == 0x42)
|
||||
{
|
||||
//
|
||||
// Byte order is MSB first.
|
||||
//
|
||||
|
||||
matchedProtoSize = 256 * buffer[6] + buffer[7];
|
||||
matchedDataSize = 256 * buffer[8] + buffer[9];
|
||||
}
|
||||
else if (buffer[0] == 0x6c)
|
||||
{
|
||||
//
|
||||
// Byte order is LSB first.
|
||||
//
|
||||
|
||||
matchedProtoSize = buffer[6] + 256 * buffer[7];
|
||||
matchedDataSize = buffer[8] + 256 * buffer[9];
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "Auth: WARNING! Bad X connection data in the buffer.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Warning" << ": Bad X connection data in the buffer.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if both the authentication protocol
|
||||
// and the fake cookie match our data.
|
||||
//
|
||||
|
||||
int protoOffset = 12;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Received a protocol size of "
|
||||
<< matchedProtoSize << " bytes.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
if (matchedProtoSize != protoSize ||
|
||||
memcmp(buffer + protoOffset, protoName, protoSize) != 0)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "Auth: WARNING! Protocol mismatch or no X "
|
||||
<< "authentication data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Warning" << ": Protocol mismatch or no X "
|
||||
<< "authentication data.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dataOffset = protoOffset + ((matchedProtoSize + 3) & ~3);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Received a data size of "
|
||||
<< matchedDataSize << " bytes.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
if (matchedDataSize != dataSize_ ||
|
||||
memcmp(buffer + dataOffset, fakeData_, dataSize_) != 0)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "Auth: WARNING! Cookie mismatch in the X "
|
||||
<< "authentication data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Warning" << ": Cookie mismatch in the X "
|
||||
<< "authentication data.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Everything is OK. Replace the fake data.
|
||||
//
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Replacing fake X authentication data "
|
||||
<< "with the real data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
memcpy(buffer + dataOffset, realData_, dataSize_);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Auth::generateCookie(char *cookie)
|
||||
{
|
||||
//
|
||||
// Code is from the SSH implementation, except that
|
||||
// we use a much weaker random number generator.
|
||||
// This is not critical, anyway, as this is just a
|
||||
// fake cookie. The X server doesn't have a cookie
|
||||
// for the display, so it will ignore the value we
|
||||
// feed to it.
|
||||
//
|
||||
|
||||
T_timestamp timer = getTimestamp();
|
||||
|
||||
srand((unsigned int) timer.tv_usec);
|
||||
|
||||
unsigned int data = rand();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (i % 4 == 0)
|
||||
{
|
||||
data = rand();
|
||||
}
|
||||
|
||||
snprintf(cookie + 2 * i, 3, "%02x", data & 0xff);
|
||||
|
||||
data >>= 8;
|
||||
}
|
||||
|
||||
generatedCookie_ = 1;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Auth: Generated X cookie string '"
|
||||
<< cookie << "'.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
127
nxcomp/src/Auth.h
Normal file
127
nxcomp/src/Auth.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef Auth_H
|
||||
#define Auth_H
|
||||
|
||||
#include "Timestamp.h"
|
||||
|
||||
//
|
||||
// Handle the forwarding of authorization credentials
|
||||
// to the X server by replacing the fake cookie with
|
||||
// the real cookie as it is read from the auth file.
|
||||
// At the moment only the MIT-MAGIC-COOKIE-1 cookies
|
||||
// are recognized. The implementation is based on the
|
||||
// corresponding code found in the SSH client.
|
||||
//
|
||||
|
||||
class Auth
|
||||
{
|
||||
public:
|
||||
|
||||
//
|
||||
// Must be created by passing the fake cookie that
|
||||
// will be forwarded by the remote end and with the
|
||||
// real X display that is going to be used for the
|
||||
// session.
|
||||
//
|
||||
|
||||
Auth(char *display, char *cookie);
|
||||
|
||||
~Auth();
|
||||
|
||||
int isValid()
|
||||
{
|
||||
return (isTimestamp(last_) == 1 && fakeCookie_ != NULL &&
|
||||
*fakeCookie_ != '\0' && realCookie_ != NULL &&
|
||||
*realCookie_ != '\0' && fakeData_ != NULL &&
|
||||
realData_ != NULL && dataSize_ != 0);
|
||||
}
|
||||
|
||||
int isFake() const
|
||||
{
|
||||
return generatedCookie_;
|
||||
}
|
||||
|
||||
//
|
||||
// Method called in the channel class to find if the
|
||||
// provided cookie matches the fake one. If the data
|
||||
// matches, the fake cookie is replaced with the real
|
||||
// one.
|
||||
//
|
||||
|
||||
int checkCookie(unsigned char *buffer);
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
// Update the real cookie for the display. If called
|
||||
// a further time, check if the auth file is changed
|
||||
// and get the new cookie.
|
||||
//
|
||||
|
||||
int updateCookie();
|
||||
|
||||
//
|
||||
// Find out which authorization file is to be used
|
||||
// and query the cookie for the current display.
|
||||
//
|
||||
|
||||
int getCookie();
|
||||
|
||||
//
|
||||
// Extract the binary data from the cookies so that
|
||||
// data can be directly compared at the time it is
|
||||
// taken from the X request.
|
||||
//
|
||||
|
||||
int validateCookie();
|
||||
|
||||
//
|
||||
// Generate a fake random cookie and copy it to the
|
||||
// provided string.
|
||||
//
|
||||
|
||||
void generateCookie(char *cookie);
|
||||
|
||||
private:
|
||||
|
||||
char *display_;
|
||||
char *file_;
|
||||
|
||||
T_timestamp last_;
|
||||
|
||||
char *fakeCookie_;
|
||||
char *realCookie_;
|
||||
|
||||
char *fakeData_;
|
||||
char *realData_;
|
||||
|
||||
int dataSize_;
|
||||
|
||||
int generatedCookie_;
|
||||
};
|
||||
|
||||
#endif /* Auth_H */
|
||||
118
nxcomp/src/Bitmap.cpp
Normal file
118
nxcomp/src/Bitmap.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Bitmap.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
int UnpackBitmap(T_geometry *geometry, unsigned char method, unsigned char *src_data,
|
||||
int src_size, int dst_bpp, int dst_width, int dst_height,
|
||||
unsigned char *dst_data, int dst_size)
|
||||
{
|
||||
if (dst_bpp != 32)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackBitmap: Nothing to do with "
|
||||
<< "image of " << dst_bpp << " bits per plane "
|
||||
<< "and size " << src_size << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
if (src_size != dst_size)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "UnpackBitmap: PANIC! Size mismatch with "
|
||||
<< src_size << " bytes in the source and "
|
||||
<< dst_size << " in the destination.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dst_data, src_data, src_size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (src_size != dst_width * dst_height * 3 ||
|
||||
dst_size != dst_width * dst_height * 4)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "UnpackBitmap: PANIC! Size mismatch with "
|
||||
<< src_size << " bytes in the source and "
|
||||
<< dst_size << " in the destination.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert the 4th byte in the bitmap.
|
||||
*/
|
||||
|
||||
unsigned char *next_src = src_data;
|
||||
unsigned char *next_dst = dst_data;
|
||||
|
||||
if (geometry -> image_byte_order == LSBFirst)
|
||||
{
|
||||
while (next_src < src_data + src_size)
|
||||
{
|
||||
*next_dst++ = *next_src++;
|
||||
*next_dst++ = *next_src++;
|
||||
*next_dst++ = *next_src++;
|
||||
|
||||
next_dst++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (next_src < src_data + src_size)
|
||||
{
|
||||
next_dst++;
|
||||
|
||||
*next_dst++ = *next_src++;
|
||||
*next_dst++ = *next_src++;
|
||||
*next_dst++ = *next_src++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackBitmap: Unpacked " << src_size
|
||||
<< " bytes to a buffer of " << dst_size
|
||||
<< " with " << dst_bpp << " bits per plane.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
36
nxcomp/src/Bitmap.h
Normal file
36
nxcomp/src/Bitmap.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef Bitmap_H
|
||||
#define Bitmap_H
|
||||
|
||||
#include "Unpack.h"
|
||||
|
||||
int UnpackBitmap(T_geometry *geometry, unsigned char method,
|
||||
unsigned char *src_data, int src_size, int dst_bpp,
|
||||
int dst_width, int dst_height, unsigned char *dst_data,
|
||||
int dst_size);
|
||||
|
||||
#endif /* Bitmap_H */
|
||||
81
nxcomp/src/BlockCache.cpp
Normal file
81
nxcomp/src/BlockCache.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "BlockCache.h"
|
||||
|
||||
|
||||
int BlockCache::compare(unsigned int size, const unsigned char *data,
|
||||
int overwrite)
|
||||
{
|
||||
int match = 0;
|
||||
if (size == size_)
|
||||
{
|
||||
match = 1;
|
||||
for (unsigned int i = 0; i < size_; i++)
|
||||
if (data[i] != buffer_[i])
|
||||
{
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match && overwrite)
|
||||
set(size, data);
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
void BlockCache::set(unsigned int size, const unsigned char *data)
|
||||
{
|
||||
if (size_ < size)
|
||||
{
|
||||
delete[]buffer_;
|
||||
buffer_ = new unsigned char[size];
|
||||
}
|
||||
size_ = size;
|
||||
memcpy(buffer_, data, size);
|
||||
checksum_ = checksum(size, data);
|
||||
}
|
||||
|
||||
|
||||
unsigned int BlockCache::checksum(unsigned int size, const unsigned char *data)
|
||||
{
|
||||
unsigned int sum = 0;
|
||||
unsigned int shift = 0;
|
||||
const unsigned char *next = data;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
unsigned int value = (unsigned int) *next++;
|
||||
sum += (value << shift);
|
||||
shift++;
|
||||
if (shift == 8)
|
||||
shift = 0;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
67
nxcomp/src/BlockCache.h
Normal file
67
nxcomp/src/BlockCache.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef BlockCache_H
|
||||
#define BlockCache_H
|
||||
|
||||
|
||||
// Cache to hold an arbitrary-length block of bytes
|
||||
|
||||
class BlockCache
|
||||
{
|
||||
public:
|
||||
BlockCache():buffer_(0), size_(0), checksum_(0)
|
||||
{
|
||||
}
|
||||
~BlockCache()
|
||||
{
|
||||
delete[]buffer_;
|
||||
}
|
||||
int compare(unsigned int size, const unsigned char *data,
|
||||
int overwrite = 1);
|
||||
void set(unsigned int size, const unsigned char *data);
|
||||
|
||||
unsigned int getLength() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
unsigned int getChecksum() const
|
||||
{
|
||||
return checksum_;
|
||||
}
|
||||
const unsigned char *getData() const
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
static unsigned int checksum(unsigned int size, const unsigned char *data);
|
||||
|
||||
private:
|
||||
unsigned char *buffer_;
|
||||
unsigned int size_;
|
||||
unsigned int checksum_;
|
||||
};
|
||||
|
||||
#endif /* BlockCache_H */
|
||||
147
nxcomp/src/BlockCacheSet.cpp
Normal file
147
nxcomp/src/BlockCacheSet.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Misc.h"
|
||||
#include "BlockCacheSet.h"
|
||||
|
||||
|
||||
BlockCacheSet::BlockCacheSet(unsigned int numCaches):
|
||||
caches_(new BlockCache *[numCaches]), size_(numCaches),
|
||||
length_(0)
|
||||
{
|
||||
for (unsigned int i = 0; i < numCaches; i++)
|
||||
caches_[i] = new BlockCache();
|
||||
}
|
||||
|
||||
|
||||
BlockCacheSet::~BlockCacheSet()
|
||||
{
|
||||
//
|
||||
// TODO: There is still a strange segfault occurring
|
||||
// at random time under Cygwin, when proxy is being
|
||||
// shutdown. Problem appeared just after upgrading
|
||||
// to the latest version of the Cygwin DLL. A stack
|
||||
// trace, obtained at the last minute, reveals that
|
||||
// failure happens in this destructor.
|
||||
//
|
||||
|
||||
#if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
|
||||
|
||||
for (unsigned int i = 0; i < size_; i++)
|
||||
delete caches_[i];
|
||||
delete[]caches_;
|
||||
|
||||
#endif /* if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BlockCacheSet::lookup(unsigned int dataLength, const unsigned char *data,
|
||||
unsigned int &index)
|
||||
{
|
||||
unsigned int checksum = BlockCache::checksum(dataLength, data);
|
||||
for (unsigned int i = 0; i < length_; i++)
|
||||
if ((caches_[i]->getChecksum() == checksum) &&
|
||||
(caches_[i]->compare(dataLength, data, 0)))
|
||||
{
|
||||
// match
|
||||
index = i;
|
||||
if (i)
|
||||
{
|
||||
BlockCache *save = caches_[i];
|
||||
unsigned int target = (i >> 1);
|
||||
do
|
||||
{
|
||||
caches_[i] = caches_[i - 1];
|
||||
i--;
|
||||
}
|
||||
while (i > target);
|
||||
caches_[target] = save;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
// no match
|
||||
unsigned int insertionPoint = (length_ >> 1);
|
||||
unsigned int start;
|
||||
if (length_ >= size_)
|
||||
start = size_ - 1;
|
||||
else
|
||||
{
|
||||
start = length_;
|
||||
length_++;
|
||||
}
|
||||
BlockCache *save = caches_[start];
|
||||
for (unsigned int k = start; k > insertionPoint; k--)
|
||||
caches_[k] = caches_[k - 1];
|
||||
caches_[insertionPoint] = save;
|
||||
save->set(dataLength, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BlockCacheSet::get(unsigned index, unsigned int &size,
|
||||
const unsigned char *&data)
|
||||
{
|
||||
size = caches_[index]->getLength();
|
||||
data = caches_[index]->getData();
|
||||
if (index)
|
||||
{
|
||||
BlockCache *save = caches_[index];
|
||||
unsigned int target = (index >> 1);
|
||||
do
|
||||
{
|
||||
caches_[index] = caches_[index - 1];
|
||||
index--;
|
||||
}
|
||||
while (index > target);
|
||||
caches_[target] = save;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BlockCacheSet::set(unsigned int dataLength, const unsigned char *data)
|
||||
{
|
||||
unsigned int insertionPoint = (length_ >> 1);
|
||||
unsigned int start;
|
||||
if (length_ >= size_)
|
||||
start = size_ - 1;
|
||||
else
|
||||
{
|
||||
start = length_;
|
||||
length_++;
|
||||
}
|
||||
BlockCache *save = caches_[start];
|
||||
for (unsigned int k = start; k > insertionPoint; k--)
|
||||
caches_[k] = caches_[k - 1];
|
||||
caches_[insertionPoint] = save;
|
||||
save->set(dataLength, data);
|
||||
}
|
||||
49
nxcomp/src/BlockCacheSet.h
Normal file
49
nxcomp/src/BlockCacheSet.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef BlockCacheSet_H
|
||||
#define BlockCacheSet_H
|
||||
|
||||
#include "BlockCache.h"
|
||||
|
||||
|
||||
class BlockCacheSet
|
||||
{
|
||||
public:
|
||||
BlockCacheSet(unsigned int numCaches);
|
||||
~BlockCacheSet();
|
||||
|
||||
int lookup(unsigned int size, const unsigned char *data,
|
||||
unsigned int &index);
|
||||
void get(unsigned int index, unsigned int &size, const unsigned char *&data);
|
||||
void set(unsigned int size, const unsigned char *data);
|
||||
|
||||
private:
|
||||
BlockCache ** caches_;
|
||||
unsigned int size_;
|
||||
unsigned int length_;
|
||||
};
|
||||
|
||||
#endif /* BlockCacheSet_H */
|
||||
184
nxcomp/src/ChangeGC.cpp
Normal file
184
nxcomp/src/ChangeGC.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ChangeGC.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int ChangeGCStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ChangeGCMessage *changeGC = (ChangeGCMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
changeGC -> gcontext = GetULONG(buffer + 4, bigEndian);
|
||||
changeGC -> value_mask = GetULONG(buffer + 8, bigEndian);
|
||||
|
||||
//
|
||||
// Clear the unused bytes carried in the
|
||||
// payload to increase the effectiveness
|
||||
// of the caching algorithm.
|
||||
//
|
||||
|
||||
if ((int) size > dataOffset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Removing unused bytes from the "
|
||||
<< "data payload.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
changeGC -> value_mask &= (1 << 23) - 1;
|
||||
|
||||
unsigned int mask = 0x1;
|
||||
unsigned char *source = (unsigned char *) buffer + CHANGEGC_DATA_OFFSET;
|
||||
unsigned long value = 0;
|
||||
|
||||
for (unsigned int i = 0; i < 23; i++)
|
||||
{
|
||||
if (changeGC -> value_mask & mask)
|
||||
{
|
||||
value = GetULONG(source, bigEndian);
|
||||
|
||||
value &= (0xffffffff >> (32 - CREATEGC_FIELD_WIDTH[i]));
|
||||
|
||||
PutULONG(value, source, bigEndian);
|
||||
|
||||
source += 4;
|
||||
}
|
||||
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at "
|
||||
<< this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ChangeGCStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ChangeGCMessage *changeGC = (ChangeGCMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
PutULONG(changeGC -> gcontext, buffer + 4, bigEndian);
|
||||
PutULONG(changeGC -> value_mask, buffer + 8, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at "
|
||||
<< this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ChangeGCStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
ChangeGCMessage *changeGC = (ChangeGCMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity gcontext " << changeGC -> gcontext
|
||||
<< ", mask " << changeGC -> value_mask << ", size "
|
||||
<< changeGC -> size_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ChangeGCStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
/*
|
||||
md5_append(md5_state_, buffer + 4, 8);
|
||||
*/
|
||||
md5_append(md5_state_, buffer + 8, 4);
|
||||
}
|
||||
|
||||
void ChangeGCStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ChangeGCMessage *changeGC = (ChangeGCMessage *) message;
|
||||
ChangeGCMessage *cachedChangeGC = (ChangeGCMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << changeGC -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(changeGC -> gcontext, clientCache -> gcCache);
|
||||
|
||||
cachedChangeGC -> gcontext = changeGC -> gcontext;
|
||||
}
|
||||
|
||||
void ChangeGCStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ChangeGCMessage *changeGC = (ChangeGCMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> gcCache);
|
||||
|
||||
changeGC -> gcontext = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << changeGC -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
185
nxcomp/src/ChangeGC.h
Normal file
185
nxcomp/src/ChangeGC.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ChangeGC_H
|
||||
#define ChangeGC_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define CHANGEGC_ENABLE_CACHE 1
|
||||
#define CHANGEGC_ENABLE_DATA 0
|
||||
#define CHANGEGC_ENABLE_SPLIT 0
|
||||
#define CHANGEGC_ENABLE_COMPRESS 0
|
||||
|
||||
#define CHANGEGC_DATA_LIMIT 144
|
||||
#define CHANGEGC_DATA_OFFSET 12
|
||||
|
||||
#define CHANGEGC_CACHE_SLOTS 3000
|
||||
#define CHANGEGC_CACHE_THRESHOLD 3
|
||||
#define CHANGEGC_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class ChangeGCMessage : public Message
|
||||
{
|
||||
friend class ChangeGCStore;
|
||||
|
||||
public:
|
||||
|
||||
ChangeGCMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~ChangeGCMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned int gcontext;
|
||||
unsigned int value_mask;
|
||||
};
|
||||
|
||||
class ChangeGCStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
ChangeGCStore() : MessageStore()
|
||||
{
|
||||
enableCache = CHANGEGC_ENABLE_CACHE;
|
||||
enableData = CHANGEGC_ENABLE_DATA;
|
||||
enableSplit = CHANGEGC_ENABLE_SPLIT;
|
||||
enableCompress = CHANGEGC_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = CHANGEGC_DATA_LIMIT;
|
||||
dataOffset = CHANGEGC_DATA_OFFSET;
|
||||
|
||||
cacheSlots = CHANGEGC_CACHE_SLOTS;
|
||||
cacheThreshold = CHANGEGC_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = CHANGEGC_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~ChangeGCStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "ChangeGC";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_ChangeGC;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(ChangeGCMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new ChangeGCMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new ChangeGCMessage((const ChangeGCMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (ChangeGCMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
};
|
||||
|
||||
#endif /* ChangeGC_H */
|
||||
191
nxcomp/src/ChangeProperty.cpp
Normal file
191
nxcomp/src/ChangeProperty.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ChangeProperty.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int ChangePropertyStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ChangePropertyMessage *changeProperty = (ChangePropertyMessage *) message;
|
||||
|
||||
changeProperty -> mode = *(buffer + 1);
|
||||
changeProperty -> format = *(buffer + 16);
|
||||
|
||||
changeProperty -> window = GetULONG(buffer + 4, bigEndian);
|
||||
changeProperty -> property = GetULONG(buffer + 8, bigEndian);
|
||||
changeProperty -> type = GetULONG(buffer + 12, bigEndian);
|
||||
changeProperty -> length = GetULONG(buffer + 20, bigEndian);
|
||||
|
||||
//
|
||||
// Cleanup the padding bytes.
|
||||
//
|
||||
|
||||
unsigned int uiFormat;
|
||||
unsigned int uiLengthInBytes;
|
||||
|
||||
if ((int) size > CHANGEPROPERTY_DATA_OFFSET)
|
||||
{
|
||||
uiFormat = *(buffer + 16);
|
||||
|
||||
uiLengthInBytes = changeProperty -> length;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": length " << uiLengthInBytes
|
||||
<< ", format " << uiFormat << ", size "
|
||||
<< size << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (uiFormat == 16)
|
||||
{
|
||||
uiLengthInBytes <<= 1;
|
||||
}
|
||||
else if (uiFormat == 32)
|
||||
{
|
||||
uiLengthInBytes <<= 2;
|
||||
}
|
||||
|
||||
unsigned char *end = ((unsigned char *) buffer) + size;
|
||||
unsigned char *pad = ((unsigned char *) buffer) + CHANGEPROPERTY_DATA_OFFSET + uiLengthInBytes;
|
||||
|
||||
CleanData((unsigned char *) pad, end - pad);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at "
|
||||
<< message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ChangePropertyStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ChangePropertyMessage *changeProperty = (ChangePropertyMessage *) message;
|
||||
|
||||
*(buffer + 1) = changeProperty -> mode;
|
||||
*(buffer + 16) = changeProperty -> format;
|
||||
|
||||
PutULONG(changeProperty -> window, buffer + 4, bigEndian);
|
||||
PutULONG(changeProperty -> property, buffer + 8, bigEndian);
|
||||
PutULONG(changeProperty -> type, buffer + 12, bigEndian);
|
||||
PutULONG(changeProperty -> length, buffer + 20, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at "
|
||||
<< this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ChangePropertyStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
ChangePropertyMessage *changeProperty = (ChangePropertyMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity mode " << (unsigned int) changeProperty -> mode << ", format "
|
||||
<< (unsigned int) changeProperty -> format << ", window " << changeProperty -> window
|
||||
<< ", property " << changeProperty -> property << ", type " << changeProperty -> type
|
||||
<< ", length " << changeProperty -> length << ", size " << changeProperty -> size_
|
||||
<< ".\n" << logofs_flush;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ChangePropertyStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
md5_append(md5_state_, buffer + 16, 1);
|
||||
|
||||
md5_append(md5_state_, buffer + 8, 4);
|
||||
md5_append(md5_state_, buffer + 12, 4);
|
||||
md5_append(md5_state_, buffer + 20, 4);
|
||||
}
|
||||
|
||||
void ChangePropertyStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ChangePropertyMessage *changeProperty = (ChangePropertyMessage *) message;
|
||||
ChangePropertyMessage *cachedChangeProperty = (ChangePropertyMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << changeProperty -> window
|
||||
<< " as window field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(changeProperty -> window, clientCache -> windowCache);
|
||||
|
||||
cachedChangeProperty -> window = changeProperty -> window;
|
||||
}
|
||||
|
||||
void ChangePropertyStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ChangePropertyMessage *changeProperty = (ChangePropertyMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> windowCache);
|
||||
|
||||
changeProperty -> window = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << changeProperty -> window
|
||||
<< " as window field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
189
nxcomp/src/ChangeProperty.h
Normal file
189
nxcomp/src/ChangeProperty.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ChangeProperty_H
|
||||
#define ChangeProperty_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define CHANGEPROPERTY_ENABLE_CACHE 1
|
||||
#define CHANGEPROPERTY_ENABLE_DATA 0
|
||||
#define CHANGEPROPERTY_ENABLE_SPLIT 0
|
||||
#define CHANGEPROPERTY_ENABLE_COMPRESS 0
|
||||
|
||||
#define CHANGEPROPERTY_DATA_LIMIT 28688
|
||||
#define CHANGEPROPERTY_DATA_OFFSET 24
|
||||
|
||||
#define CHANGEPROPERTY_CACHE_SLOTS 2000
|
||||
#define CHANGEPROPERTY_CACHE_THRESHOLD 2
|
||||
#define CHANGEPROPERTY_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class ChangePropertyMessage : public Message
|
||||
{
|
||||
friend class ChangePropertyStore;
|
||||
|
||||
public:
|
||||
|
||||
ChangePropertyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~ChangePropertyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char mode;
|
||||
unsigned char format;
|
||||
unsigned int window;
|
||||
unsigned int property;
|
||||
unsigned int type;
|
||||
unsigned int length;
|
||||
};
|
||||
|
||||
class ChangePropertyStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
ChangePropertyStore() : MessageStore()
|
||||
{
|
||||
enableCache = CHANGEPROPERTY_ENABLE_CACHE;
|
||||
enableData = CHANGEPROPERTY_ENABLE_DATA;
|
||||
enableSplit = CHANGEPROPERTY_ENABLE_SPLIT;
|
||||
enableCompress = CHANGEPROPERTY_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = CHANGEPROPERTY_DATA_LIMIT;
|
||||
dataOffset = CHANGEPROPERTY_DATA_OFFSET;
|
||||
|
||||
cacheSlots = CHANGEPROPERTY_CACHE_SLOTS;
|
||||
cacheThreshold = CHANGEPROPERTY_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = CHANGEPROPERTY_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~ChangePropertyStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "ChangeProperty";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_ChangeProperty;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(ChangePropertyMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new ChangePropertyMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new ChangePropertyMessage((const ChangePropertyMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (ChangePropertyMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* ChangeProperty_H */
|
||||
2039
nxcomp/src/Channel.cpp
Normal file
2039
nxcomp/src/Channel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
664
nxcomp/src/Channel.h
Normal file
664
nxcomp/src/Channel.h
Normal file
@@ -0,0 +1,664 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef Channel_H
|
||||
#define Channel_H
|
||||
|
||||
#include "Transport.h"
|
||||
|
||||
#include "WriteBuffer.h"
|
||||
|
||||
#include "OpcodeStore.h"
|
||||
|
||||
#include "ClientStore.h"
|
||||
#include "ServerStore.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
#include "ServerCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Forward declaration of referenced classes.
|
||||
//
|
||||
|
||||
class List;
|
||||
|
||||
class StaticCompressor;
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Define this to log a line when a channel
|
||||
// is created or destroyed.
|
||||
//
|
||||
|
||||
#undef REFERENCES
|
||||
|
||||
//
|
||||
// Type of traffic carried by channel.
|
||||
//
|
||||
|
||||
typedef enum
|
||||
{
|
||||
channel_none = -1,
|
||||
channel_x11,
|
||||
channel_cups,
|
||||
channel_smb,
|
||||
channel_media,
|
||||
channel_http,
|
||||
channel_font,
|
||||
channel_slave,
|
||||
channel_last_tag
|
||||
|
||||
} T_channel_type;
|
||||
|
||||
//
|
||||
// Type of notification event to be sent
|
||||
// by proxy to the X channel.
|
||||
//
|
||||
|
||||
typedef enum
|
||||
{
|
||||
notify_no_split,
|
||||
notify_start_split,
|
||||
notify_commit_split,
|
||||
notify_end_split,
|
||||
notify_empty_split,
|
||||
|
||||
} T_notification_type;
|
||||
|
||||
class Channel
|
||||
{
|
||||
public:
|
||||
|
||||
//
|
||||
// Maximum number of X connections supported.
|
||||
//
|
||||
|
||||
static const int CONNECTIONS_LIMIT = 256;
|
||||
|
||||
Channel(Transport *transport, StaticCompressor *compressor);
|
||||
|
||||
virtual ~Channel();
|
||||
|
||||
//
|
||||
// Read any X message available on the X
|
||||
// connection and encode it to the encode
|
||||
// buffer.
|
||||
//
|
||||
|
||||
virtual int handleRead(EncodeBuffer &encodeBuffer, const unsigned char *message,
|
||||
unsigned int length) = 0;
|
||||
|
||||
//
|
||||
// Decode any X message encoded in the
|
||||
// proxy message and write it to the X
|
||||
// connection.
|
||||
//
|
||||
|
||||
virtual int handleWrite(const unsigned char *message, unsigned int length) = 0;
|
||||
|
||||
//
|
||||
// Other methods to be implemented in
|
||||
// client, server and generic channel
|
||||
// classes.
|
||||
//
|
||||
|
||||
virtual int handleSplit(EncodeBuffer &encodeBuffer, MessageStore *store,
|
||||
T_store_action action, int position, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size) = 0;
|
||||
|
||||
virtual int handleSplit(DecodeBuffer &decodeBuffer, MessageStore *store,
|
||||
T_store_action action, int position, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size) = 0;
|
||||
|
||||
virtual int handleSplit(EncodeBuffer &encodeBuffer) = 0;
|
||||
|
||||
virtual int handleSplit(DecodeBuffer &decodeBuffer) = 0;
|
||||
|
||||
virtual int handleSplitEvent(EncodeBuffer &encodeBuffer, Split *split) = 0;
|
||||
|
||||
virtual int handleSplitEvent(DecodeBuffer &decodeBuffer) = 0;
|
||||
|
||||
virtual int handleMotion(EncodeBuffer &encodeBuffer) = 0;
|
||||
|
||||
virtual int handleCompletion(EncodeBuffer &encodeBuffer) = 0;
|
||||
|
||||
virtual int handleConfiguration() = 0;
|
||||
|
||||
virtual int handleFinish() = 0;
|
||||
|
||||
//
|
||||
// Interleave reads of the available
|
||||
// events while writing data to the
|
||||
// channel socket.
|
||||
//
|
||||
|
||||
virtual int handleAsyncEvents() = 0;
|
||||
|
||||
//
|
||||
// Handle the channel tear down.
|
||||
//
|
||||
|
||||
int handleClosing()
|
||||
{
|
||||
closing_ = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int handleDrop()
|
||||
{
|
||||
drop_ = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to read more data from the socket. In
|
||||
// the meanwhile flush any enqueued data if
|
||||
// the channel is blocked. Return as soon as
|
||||
// more data has been read or the timeout has
|
||||
// been exceeded.
|
||||
//
|
||||
|
||||
int handleWait(int timeout);
|
||||
|
||||
//
|
||||
// Drain the output buffer while handling the
|
||||
// data that may become readable.
|
||||
//
|
||||
|
||||
int handleDrain(int timeout, int limit);
|
||||
|
||||
//
|
||||
// Flush any remaining data in the transport
|
||||
// buffer.
|
||||
//
|
||||
|
||||
int handleFlush();
|
||||
|
||||
//
|
||||
// Called when the loop has replaced or
|
||||
// closed a previous alert.
|
||||
//
|
||||
|
||||
void handleResetAlert();
|
||||
|
||||
//
|
||||
// Initialize all the static members.
|
||||
//
|
||||
|
||||
static int setReferences();
|
||||
|
||||
//
|
||||
// Set pointer to object mapping opcodes
|
||||
// of NX specific messages.
|
||||
//
|
||||
|
||||
int setOpcodes(OpcodeStore *opcodeStore);
|
||||
|
||||
//
|
||||
// Update pointers to message stores in
|
||||
// channels.
|
||||
//
|
||||
|
||||
int setStores(ClientStore *clientStore, ServerStore *serverStore);
|
||||
|
||||
//
|
||||
// The same for channels caches.
|
||||
//
|
||||
|
||||
int setCaches(ClientCache *clientCache, ServerCache *serverCache);
|
||||
|
||||
//
|
||||
// Set the port used for tunneling of the
|
||||
// font server connections.
|
||||
//
|
||||
|
||||
void setPorts(int fontPort)
|
||||
{
|
||||
fontPort_ = fontPort;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if there are pending split
|
||||
// to send to the remote side.
|
||||
//
|
||||
|
||||
virtual int needSplit() const = 0;
|
||||
|
||||
//
|
||||
// Check if there are motion events
|
||||
// to flush.
|
||||
//
|
||||
|
||||
virtual int needMotion() const = 0;
|
||||
|
||||
//
|
||||
// Return the type of traffic carried
|
||||
// by this channel.
|
||||
//
|
||||
|
||||
virtual T_channel_type getType() const = 0;
|
||||
|
||||
//
|
||||
// Check if the channel has been marked
|
||||
// as closing down.
|
||||
//
|
||||
|
||||
int getFinish() const
|
||||
{
|
||||
return finish_;
|
||||
}
|
||||
|
||||
int getClosing()
|
||||
{
|
||||
return closing_;
|
||||
}
|
||||
|
||||
int getDrop()
|
||||
{
|
||||
return drop_;
|
||||
}
|
||||
|
||||
int getCongestion()
|
||||
{
|
||||
return congestion_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
int handleFlush(T_flush type)
|
||||
{
|
||||
//
|
||||
// We could write the data immediately if there
|
||||
// is already something queued to the low level
|
||||
// TCP buffers.
|
||||
//
|
||||
// if (... || transport_ -> queued() > 0)
|
||||
// {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
|
||||
if (writeBuffer_.getScratchLength() > 0 ||
|
||||
(type == flush_if_any && writeBuffer_.getLength() > 0) ||
|
||||
writeBuffer_.getLength() >= (unsigned int)
|
||||
control -> TransportFlushBufferSize)
|
||||
{
|
||||
return handleFlush(type, writeBuffer_.getLength(),
|
||||
writeBuffer_.getScratchLength());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Actually flush the data to the
|
||||
// channel descriptor.
|
||||
//
|
||||
|
||||
int handleFlush(T_flush type, int bufferLength, int scratchLength);
|
||||
|
||||
//
|
||||
// Handle the congestion changes.
|
||||
//
|
||||
|
||||
int handleCongestion();
|
||||
|
||||
//
|
||||
// Encode and decode X messages.
|
||||
//
|
||||
|
||||
int handleEncode(EncodeBuffer &encodeBuffer, ChannelCache *channelCache,
|
||||
MessageStore *store, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
int handleDecode(DecodeBuffer &decodeBuffer, ChannelCache *channelCache,
|
||||
MessageStore *store, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size);
|
||||
|
||||
//
|
||||
// Encode the message based on its
|
||||
// message store.
|
||||
//
|
||||
|
||||
int handleEncodeCached(EncodeBuffer &encodeBuffer, ChannelCache *channelCache,
|
||||
MessageStore *store, const unsigned char *buffer,
|
||||
const unsigned int size);
|
||||
|
||||
int handleDecodeCached(DecodeBuffer &decodeBuffer, ChannelCache *channelCache,
|
||||
MessageStore *store, unsigned char *&buffer,
|
||||
unsigned int &size);
|
||||
|
||||
int handleEncodeIdentity(EncodeBuffer &encodeBuffer, ChannelCache *channelCache,
|
||||
MessageStore *store, const unsigned char *buffer,
|
||||
const unsigned int size, int _bigEndian)
|
||||
{
|
||||
return (store -> encodeIdentity(encodeBuffer, buffer, size,
|
||||
_bigEndian, channelCache));
|
||||
}
|
||||
|
||||
int handleDecodeIdentity(DecodeBuffer &decodeBuffer, ChannelCache *channelCache,
|
||||
MessageStore *store, unsigned char *&buffer,
|
||||
unsigned int &size, int _bigEndian,
|
||||
WriteBuffer *writeBuffer)
|
||||
{
|
||||
return (store -> decodeIdentity(decodeBuffer, buffer, size, _bigEndian,
|
||||
writeBuffer, channelCache));
|
||||
}
|
||||
|
||||
//
|
||||
// Other utility functions used by
|
||||
// the encoding and decoding methods.
|
||||
//
|
||||
|
||||
void handleCopy(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned int offset, const unsigned char *buffer,
|
||||
const unsigned int size)
|
||||
{
|
||||
if (size > offset)
|
||||
{
|
||||
encodeBuffer.encodeMemory(buffer + offset, size - offset);
|
||||
}
|
||||
}
|
||||
|
||||
void handleCopy(DecodeBuffer &decodeBuffer, const unsigned char opcode,
|
||||
const unsigned int offset, unsigned char *buffer,
|
||||
const unsigned int size)
|
||||
{
|
||||
if (size > offset)
|
||||
{
|
||||
memcpy(buffer + offset, decodeBuffer.decodeMemory(size - offset), size - offset);
|
||||
}
|
||||
}
|
||||
|
||||
void handleUpdate(MessageStore *store, const unsigned int dataSize,
|
||||
const unsigned int compressedDataSize)
|
||||
{
|
||||
if (store -> lastAction == IS_ADDED)
|
||||
{
|
||||
handleUpdateAdded(store, dataSize, compressedDataSize);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSave(MessageStore *store, unsigned char *buffer, unsigned int size,
|
||||
const unsigned char *compressedData = NULL,
|
||||
const unsigned int compressedDataSize = 0)
|
||||
{
|
||||
if (store -> lastAction == IS_ADDED)
|
||||
{
|
||||
handleSaveAdded(store, 0, buffer, size, compressedData, compressedDataSize);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSaveSplit(MessageStore *store, unsigned char *buffer,
|
||||
unsigned int size)
|
||||
{
|
||||
if (store -> lastAction == IS_ADDED)
|
||||
{
|
||||
return handleSaveAdded(store, 1, buffer, size, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void handleUpdateAdded(MessageStore *store, const unsigned int dataSize,
|
||||
const unsigned int compressedDataSize);
|
||||
|
||||
void handleSaveAdded(MessageStore *store, int split, unsigned char *buffer,
|
||||
unsigned int size, const unsigned char *compressedData,
|
||||
const unsigned int compressedDataSize);
|
||||
|
||||
//
|
||||
// Compress the data part of a message
|
||||
// using ZLIB or another compressor
|
||||
// and send it over the network.
|
||||
//
|
||||
|
||||
int handleCompress(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned int offset, const unsigned char *buffer,
|
||||
const unsigned int size, unsigned char *&compressedData,
|
||||
unsigned int &compressedDataSize);
|
||||
|
||||
int handleDecompress(DecodeBuffer &decodeBuffer, const unsigned char opcode,
|
||||
const unsigned int offset, unsigned char *buffer,
|
||||
const unsigned int size, const unsigned char *&compressedData,
|
||||
unsigned int &compressedDataSize);
|
||||
|
||||
//
|
||||
// Send an X_NoOperation to the X server.
|
||||
// The second version also removes any
|
||||
// previous data in the write buffer.
|
||||
//
|
||||
|
||||
int handleNullRequest(unsigned char &opcode, unsigned char *&buffer,
|
||||
unsigned int &size);
|
||||
|
||||
int handleCleanAndNullRequest(unsigned char &opcode, unsigned char *&buffer,
|
||||
unsigned int &size);
|
||||
|
||||
//
|
||||
// X11 channels are considered to be in
|
||||
// congestion state when there was a
|
||||
// blocking write and, since then, the
|
||||
// local end didn't consume all the data.
|
||||
//
|
||||
|
||||
virtual int isCongested()
|
||||
{
|
||||
return (transport_ -> getType() !=
|
||||
transport_agent && transport_ -> length() >
|
||||
control -> TransportFlushBufferSize);
|
||||
}
|
||||
|
||||
virtual int isReliable()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Determine how to handle allocation
|
||||
// of new messages in the message
|
||||
// stores.
|
||||
//
|
||||
|
||||
int mustCleanStore(MessageStore *store)
|
||||
{
|
||||
return (store -> getRemoteTotalStorageSize() > control ->
|
||||
RemoteTotalStorageSize || store -> getLocalTotalStorageSize() >
|
||||
control -> LocalTotalStorageSize || (store -> getRemoteStorageSize() >
|
||||
(control -> RemoteTotalStorageSize / 100 * store ->
|
||||
cacheThreshold)) || (store -> getLocalStorageSize() >
|
||||
(control -> LocalTotalStorageSize / 100 * store ->
|
||||
cacheThreshold)));
|
||||
}
|
||||
|
||||
int canCleanStore(MessageStore *store)
|
||||
{
|
||||
return ((store -> getSize() > 0 && (store -> getRemoteStorageSize() >
|
||||
(control -> RemoteTotalStorageSize / 100 * store ->
|
||||
cacheLowerThreshold))) || (store -> getLocalStorageSize() >
|
||||
(control -> LocalTotalStorageSize / 100 * store ->
|
||||
cacheLowerThreshold)));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
// Set up the split stores.
|
||||
//
|
||||
|
||||
void handleSplitStoreError(int resource) __attribute__((noreturn));
|
||||
|
||||
void handleSplitStoreAlloc(List *list, int resource);
|
||||
void handleSplitStoreRemove(List *list, int resource);
|
||||
|
||||
Split *handleSplitCommitRemove(int request, int resource, int position);
|
||||
|
||||
void validateSize(const char *name, int input, int output,
|
||||
int offset, int size)
|
||||
{
|
||||
if (size < offset || size > control -> MaximumMessageSize ||
|
||||
size != (int) RoundUp4(input) + offset ||
|
||||
output > control -> MaximumMessageSize)
|
||||
{
|
||||
*logofs << "Channel: PANIC! Invalid size " << size
|
||||
<< " for " << name << " output with data "
|
||||
<< input << "/" << output << "/" << offset
|
||||
<< "/" << size << ".\n" << logofs_flush;
|
||||
|
||||
cerr << "Error" << ": Invalid size " << size
|
||||
<< " for " << name << " output.\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Is the X client big endian?
|
||||
//
|
||||
|
||||
int bigEndian() const
|
||||
{
|
||||
return bigEndian_;
|
||||
}
|
||||
|
||||
int bigEndian_;
|
||||
|
||||
//
|
||||
// Other X server's features
|
||||
// saved at session startup.
|
||||
//
|
||||
|
||||
unsigned int imageByteOrder_;
|
||||
unsigned int bitmapBitOrder_;
|
||||
unsigned int scanlineUnit_;
|
||||
unsigned int scanlinePad_;
|
||||
|
||||
int firstRequest_;
|
||||
int firstReply_;
|
||||
|
||||
//
|
||||
// Use this class for IO operations.
|
||||
//
|
||||
|
||||
Transport *transport_;
|
||||
|
||||
//
|
||||
// The static compressor is created by the
|
||||
// proxy and shared among channels.
|
||||
//
|
||||
|
||||
StaticCompressor *compressor_;
|
||||
|
||||
//
|
||||
// Map NX operations to opcodes. Propagated
|
||||
// by proxy to all channels on the same X
|
||||
// server.
|
||||
//
|
||||
|
||||
OpcodeStore *opcodeStore_;
|
||||
|
||||
//
|
||||
// Also stores are shared between channels.
|
||||
//
|
||||
|
||||
ClientStore *clientStore_;
|
||||
ServerStore *serverStore_;
|
||||
|
||||
//
|
||||
// Caches are specific for each channel.
|
||||
//
|
||||
|
||||
ClientCache *clientCache_;
|
||||
ServerCache *serverCache_;
|
||||
|
||||
//
|
||||
// Data going to X connection.
|
||||
//
|
||||
|
||||
WriteBuffer writeBuffer_;
|
||||
|
||||
//
|
||||
// Other data members.
|
||||
//
|
||||
|
||||
int fd_;
|
||||
|
||||
int finish_;
|
||||
int closing_;
|
||||
int drop_;
|
||||
int congestion_;
|
||||
int priority_;
|
||||
|
||||
int alert_;
|
||||
|
||||
//
|
||||
// It will be set to the descriptor of the
|
||||
// first X channel that is successfully con-
|
||||
// nected and will print an info message on
|
||||
// standard error.
|
||||
//
|
||||
|
||||
static int firstClient_;
|
||||
|
||||
//
|
||||
// Port used for font server connections.
|
||||
//
|
||||
|
||||
static int fontPort_;
|
||||
|
||||
//
|
||||
// Track which cache operations have been
|
||||
// enabled by the agent.
|
||||
//
|
||||
|
||||
int enableCache_;
|
||||
int enableSplit_;
|
||||
int enableSave_;
|
||||
int enableLoad_;
|
||||
|
||||
//
|
||||
// Keep track of object creation and
|
||||
// deletion.
|
||||
//
|
||||
|
||||
#ifdef REFERENCES
|
||||
|
||||
static int references_;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* Channel_H */
|
||||
68
nxcomp/src/ChannelCache.cpp
Normal file
68
nxcomp/src/ChannelCache.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ChannelCache.h"
|
||||
|
||||
const unsigned int CONFIGUREWINDOW_FIELD_WIDTH[7] =
|
||||
{
|
||||
16, // x
|
||||
16, // y
|
||||
16, // width
|
||||
16, // height
|
||||
16, // border width
|
||||
29, // sibling window
|
||||
3 // stack mode
|
||||
};
|
||||
|
||||
const unsigned int CREATEGC_FIELD_WIDTH[23] =
|
||||
{
|
||||
4, // function
|
||||
32, // plane mask
|
||||
32, // foreground
|
||||
32, // background
|
||||
16, // line width
|
||||
2, // line style
|
||||
2, // cap style
|
||||
2, // join style
|
||||
2, // fill style
|
||||
1, // fill rule
|
||||
29, // tile
|
||||
29, // stipple
|
||||
16, // tile/stipple x origin
|
||||
16, // tile/stipple y origin
|
||||
29, // font
|
||||
1, // subwindow mode
|
||||
1, // graphics exposures
|
||||
16, // clip x origin
|
||||
16, // clip y origin
|
||||
29, // clip mask
|
||||
16, // card offset
|
||||
8, // dashes
|
||||
1 // arc mode
|
||||
};
|
||||
61
nxcomp/src/ChannelCache.h
Normal file
61
nxcomp/src/ChannelCache.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ChannelCache_H
|
||||
#define ChannelCache_H
|
||||
|
||||
//
|
||||
// Sizes of optional fields for ConfigureWindow
|
||||
// request.
|
||||
//
|
||||
|
||||
extern const unsigned int CONFIGUREWINDOW_FIELD_WIDTH[7];
|
||||
|
||||
//
|
||||
// Sizes of optional fields for CreateGC request.
|
||||
//
|
||||
|
||||
extern const unsigned int CREATEGC_FIELD_WIDTH[23];
|
||||
|
||||
//
|
||||
// This is just needed to provide a pointer
|
||||
// to the base cache class in encoding and
|
||||
// decoding procedures of message stores.
|
||||
//
|
||||
|
||||
class ChannelCache
|
||||
{
|
||||
public:
|
||||
|
||||
ChannelCache()
|
||||
{
|
||||
}
|
||||
|
||||
~ChannelCache()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ChannelCache_H */
|
||||
375
nxcomp/src/ChannelEndPoint.cpp
Normal file
375
nxcomp/src/ChannelEndPoint.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "ChannelEndPoint.h"
|
||||
|
||||
#include "NXalert.h"
|
||||
|
||||
#include "Misc.h"
|
||||
|
||||
ChannelEndPoint::ChannelEndPoint(const char *spec)
|
||||
: defaultTCPPort_(0), defaultTCPInterface_(0),
|
||||
defaultUnixPath_(NULL), spec_(NULL) {
|
||||
setSpec(spec);
|
||||
}
|
||||
|
||||
ChannelEndPoint::~ChannelEndPoint()
|
||||
{
|
||||
char *unixPath = NULL;
|
||||
|
||||
if (getUnixPath(&unixPath))
|
||||
{
|
||||
struct stat st;
|
||||
lstat(unixPath, &st);
|
||||
if(S_ISSOCK(st.st_mode))
|
||||
unlink(unixPath);
|
||||
}
|
||||
SAFE_FREE(unixPath);
|
||||
SAFE_FREE(defaultUnixPath_);
|
||||
SAFE_FREE(spec_);
|
||||
}
|
||||
|
||||
void
|
||||
ChannelEndPoint::setSpec(const char *spec) {
|
||||
SAFE_FREE(spec_);
|
||||
|
||||
if (spec && strlen(spec))
|
||||
{
|
||||
spec_ = strdup(spec);
|
||||
isUnix_ = getUnixPath();
|
||||
isTCP_ = getTCPHostAndPort();
|
||||
}
|
||||
else
|
||||
{
|
||||
spec_ = NULL;
|
||||
isUnix_ = false;
|
||||
isTCP_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ChannelEndPoint::setSpec(long port) {
|
||||
if (port >= 0) {
|
||||
char tmp[20];
|
||||
sprintf(tmp, "%ld", port);
|
||||
setSpec(tmp);
|
||||
}
|
||||
else {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ChannelEndPoint::setSpec(const char *hostName, long port) {
|
||||
int length;
|
||||
|
||||
isUnix_ = false;
|
||||
isTCP_ = false;
|
||||
|
||||
SAFE_FREE(spec_);
|
||||
|
||||
if (hostName && strlen(hostName) && port >= 1)
|
||||
{
|
||||
length = snprintf(NULL, 0, "tcp:%s:%ld", hostName, port);
|
||||
spec_ = static_cast<char *>(calloc(length + 1, sizeof(char)));
|
||||
snprintf(spec_, length+1, "tcp:%s:%ld", hostName, port);
|
||||
isTCP_ = true;
|
||||
}
|
||||
else setSpec(static_cast<char*>(NULL));
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::getSpec(char **socketUri) const {
|
||||
|
||||
if (socketUri)
|
||||
{
|
||||
*socketUri = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char *unixPath = NULL;
|
||||
char *hostName = NULL;
|
||||
long port = -1;
|
||||
|
||||
int length = -1;
|
||||
|
||||
if (getUnixPath(&unixPath))
|
||||
{
|
||||
length = snprintf(NULL, 0, "unix:%s", unixPath);
|
||||
}
|
||||
else if (getTCPHostAndPort(&hostName, &port))
|
||||
{
|
||||
length = snprintf(NULL, 0, "tcp:%s:%ld", hostName, port);
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
char *newSocketUri = static_cast<char *>(calloc(length + 1, sizeof(char)));
|
||||
|
||||
if (newSocketUri)
|
||||
{
|
||||
if (isUnixSocket())
|
||||
snprintf(newSocketUri, length+1, "unix:%s", unixPath);
|
||||
else
|
||||
snprintf(newSocketUri, length+1, "tcp:%s:%ld", hostName, port);
|
||||
|
||||
*socketUri = strdup(newSocketUri);
|
||||
|
||||
SAFE_FREE(newSocketUri);
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_FREE(unixPath);
|
||||
SAFE_FREE(hostName);
|
||||
|
||||
if (NULL != *socketUri)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ChannelEndPoint::setDefaultTCPPort(long port) {
|
||||
defaultTCPPort_ = port;
|
||||
isTCP_ = getTCPHostAndPort();
|
||||
}
|
||||
|
||||
void
|
||||
ChannelEndPoint::setDefaultTCPInterface(int publicInterface) {
|
||||
defaultTCPInterface_ = publicInterface;
|
||||
}
|
||||
|
||||
void
|
||||
ChannelEndPoint::setDefaultUnixPath(char *path) {
|
||||
SAFE_FREE(defaultUnixPath_);
|
||||
|
||||
if (path && strlen(path))
|
||||
defaultUnixPath_ = strdup(path);
|
||||
|
||||
isUnix_ = getUnixPath();
|
||||
}
|
||||
|
||||
void
|
||||
ChannelEndPoint::disable() {
|
||||
setSpec("0");
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::getPort(long *port) const {
|
||||
if (port) *port = 0;
|
||||
long p = -1;
|
||||
if (spec_) {
|
||||
char *end;
|
||||
p = strtol(spec_, &end, 10);
|
||||
if ((end == spec_) || (*end != '\0'))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (port) *port = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::getUnixPath(char **unixPath) const {
|
||||
|
||||
if (unixPath)
|
||||
*unixPath = NULL;
|
||||
|
||||
long p;
|
||||
char *path = NULL;
|
||||
|
||||
if (getPort(&p)) {
|
||||
if (p != 1) return false;
|
||||
}
|
||||
else if (spec_ && (strncmp("unix:", spec_, 5) == 0)) {
|
||||
path = spec_ + 5;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (!path || (*path == '\0')) {
|
||||
path = defaultUnixPath_;
|
||||
if (!path)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only return value wanted
|
||||
if ( unixPath )
|
||||
*unixPath = strdup(path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::isUnixSocket() const {
|
||||
return isUnix_;
|
||||
}
|
||||
|
||||
// FIXME!!!
|
||||
static const char *
|
||||
getComputerName() {
|
||||
//
|
||||
// Strangely enough, under some Windows OSes SMB
|
||||
// service doesn't bind to localhost. Fall back
|
||||
// to localhost if can't find computer name in
|
||||
// the environment. In future we should try to
|
||||
// bind to localhost and then try the other IPs.
|
||||
//
|
||||
|
||||
const char *hostname = NULL;
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__CYGWIN32__)
|
||||
|
||||
hostname = getenv("COMPUTERNAME");
|
||||
|
||||
#endif
|
||||
|
||||
if (hostname == NULL)
|
||||
{
|
||||
hostname = "localhost";
|
||||
}
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::getTCPHostAndPort(char **host, long *port) const {
|
||||
long p;
|
||||
char *h = NULL;
|
||||
ssize_t h_len;
|
||||
|
||||
if (host)
|
||||
*host = NULL;
|
||||
if (port)
|
||||
*port = 0;
|
||||
|
||||
if (getPort(&p)) {
|
||||
h_len = 0;
|
||||
}
|
||||
else if (spec_ && (strncmp("tcp:", spec_, 4) == 0)) {
|
||||
h = spec_ + 4;
|
||||
char *colon = strrchr(h, ':');
|
||||
if (colon) {
|
||||
char *end;
|
||||
h_len = colon++ - h;
|
||||
p = strtol(colon, &end, 10);
|
||||
if ((end == colon) || (*end != '\0'))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
h_len = strlen(h);
|
||||
p = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (p == 1) p = defaultTCPPort_;
|
||||
if (p < 1) return false;
|
||||
|
||||
if (port)
|
||||
*port = p;
|
||||
|
||||
if (host)
|
||||
*host = ( h_len
|
||||
? strndup(h, h_len)
|
||||
: strdup(defaultTCPInterface_ ? getComputerName() : "localhost"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::isTCPSocket() const {
|
||||
return isTCP_;
|
||||
}
|
||||
|
||||
long ChannelEndPoint::getTCPPort() const {
|
||||
long port;
|
||||
if (getTCPHostAndPort(NULL, &port)) return port;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::enabled() const {
|
||||
return (isUnixSocket() || isTCPSocket());
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::configured() const {
|
||||
return ( spec_ && ( strcmp(spec_, "0") != 0) );
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelEndPoint::validateSpec() {
|
||||
isTCP_ = getTCPHostAndPort();
|
||||
isUnix_ = getUnixPath();
|
||||
return ( getPort() || isUnix_ || isTCP_ );
|
||||
}
|
||||
|
||||
ChannelEndPoint &ChannelEndPoint::operator=(const ChannelEndPoint &other) {
|
||||
char *old;
|
||||
defaultTCPPort_ = other.defaultTCPPort_;
|
||||
defaultTCPInterface_ = other.defaultTCPInterface_;
|
||||
old = defaultUnixPath_;
|
||||
defaultUnixPath_ = (other.defaultUnixPath_ ? strdup(other.defaultUnixPath_) : NULL);
|
||||
SAFE_FREE(old);
|
||||
old = spec_;
|
||||
spec_ = (other.spec_ ? strdup(other.spec_) : NULL);
|
||||
SAFE_FREE(old);
|
||||
isUnix_ = getUnixPath();
|
||||
isTCP_ = getTCPHostAndPort();
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ChannelEndPoint& endPoint) {
|
||||
if (endPoint.enabled()) {
|
||||
char* endPointSpec = NULL;
|
||||
if (endPoint.getSpec(&endPointSpec))
|
||||
{
|
||||
os << endPointSpec;
|
||||
SAFE_FREE(endPointSpec);
|
||||
}
|
||||
else
|
||||
os << "(invalid)";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "(disabled)";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
72
nxcomp/src/ChannelEndPoint.h
Normal file
72
nxcomp/src/ChannelEndPoint.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ChannelEndPoint_H
|
||||
#define ChannelEndPoint_H
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/un.h>
|
||||
|
||||
class ChannelEndPoint
|
||||
{
|
||||
private:
|
||||
long defaultTCPPort_;
|
||||
int defaultTCPInterface_; // 0=localhost, otherwise IP of public interface.
|
||||
char *defaultUnixPath_;
|
||||
char *spec_;
|
||||
bool isUnix_;
|
||||
bool isTCP_;
|
||||
|
||||
bool getPort(long *port = NULL) const;
|
||||
|
||||
public:
|
||||
ChannelEndPoint(const char *spec = NULL);
|
||||
~ChannelEndPoint();
|
||||
ChannelEndPoint &operator=(const ChannelEndPoint &other);
|
||||
|
||||
bool configured() const;
|
||||
bool enabled() const;
|
||||
bool disabled() { return !enabled(); }
|
||||
void disable();
|
||||
void setSpec(const char *spec);
|
||||
void setSpec(long port);
|
||||
void setSpec(const char *hostName, long port);
|
||||
bool getSpec(char **socketUri) const;
|
||||
void setDefaultTCPPort(long port);
|
||||
void setDefaultTCPInterface(int publicInterface);
|
||||
void setDefaultUnixPath(char *path);
|
||||
|
||||
bool getUnixPath(char **path = NULL) const;
|
||||
bool isUnixSocket() const;
|
||||
bool getTCPHostAndPort(char **hostname = NULL, long *port = NULL) const;
|
||||
long getTCPPort() const;
|
||||
bool isTCPSocket() const;
|
||||
|
||||
bool validateSpec();
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ChannelEndPoint& endPoint);
|
||||
|
||||
#endif
|
||||
54
nxcomp/src/ChannelStore.h
Normal file
54
nxcomp/src/ChannelStore.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ChannelStore_H
|
||||
#define ChannelStore_H
|
||||
|
||||
//
|
||||
// One message store for each opcode.
|
||||
//
|
||||
|
||||
#define CHANNEL_STORE_OPCODE_LIMIT 256
|
||||
|
||||
//
|
||||
// One split store for each resource.
|
||||
//
|
||||
|
||||
#define CHANNEL_STORE_RESOURCE_LIMIT 256
|
||||
|
||||
class ChannelStore
|
||||
{
|
||||
public:
|
||||
|
||||
ChannelStore()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ChannelStore()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ChannelStore_H */
|
||||
73
nxcomp/src/CharCache.cpp
Normal file
73
nxcomp/src/CharCache.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "CharCache.h"
|
||||
|
||||
int CharCache::lookup(unsigned char value, unsigned int &index)
|
||||
{
|
||||
for (unsigned int i = 0; i < length_; i++)
|
||||
if (value == buffer_[i])
|
||||
{
|
||||
index = i;
|
||||
if (i)
|
||||
{
|
||||
unsigned int target = (i >> 1);
|
||||
do
|
||||
{
|
||||
buffer_[i] = buffer_[i - 1];
|
||||
i--;
|
||||
}
|
||||
while (i > target);
|
||||
buffer_[target] = value;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
insert(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CharCache::insert(unsigned char value)
|
||||
{
|
||||
unsigned int insertionPoint = 0;
|
||||
if (2 >= length_)
|
||||
insertionPoint = length_;
|
||||
else
|
||||
insertionPoint = 2;
|
||||
unsigned int start;
|
||||
if (length_ >= 7)
|
||||
start = 7 - 1;
|
||||
else
|
||||
{
|
||||
start = length_;
|
||||
length_++;
|
||||
}
|
||||
for (unsigned int k = start; k > insertionPoint; k--)
|
||||
buffer_[k] = buffer_[k - 1];
|
||||
buffer_[insertionPoint] = value;
|
||||
}
|
||||
91
nxcomp/src/CharCache.h
Normal file
91
nxcomp/src/CharCache.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CharCache_H
|
||||
#define CharCache_H
|
||||
|
||||
//
|
||||
// CharCache is a counterpart of IntCache that is
|
||||
// optimized for use in compressing text composed
|
||||
// of 8-bit characters.
|
||||
//
|
||||
|
||||
class CharCache
|
||||
{
|
||||
public:
|
||||
|
||||
CharCache() : length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
~CharCache()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int getSize() const
|
||||
{
|
||||
return (unsigned int) length_;
|
||||
}
|
||||
|
||||
int lookup(unsigned char value, unsigned int &index);
|
||||
|
||||
//
|
||||
// This can be inlined as it is only
|
||||
// called by decodeCachedValue().
|
||||
//
|
||||
|
||||
unsigned int get(unsigned int index)
|
||||
{
|
||||
unsigned char result = buffer_[index];
|
||||
|
||||
if (index != 0)
|
||||
{
|
||||
unsigned int i = index;
|
||||
unsigned int target = (i >> 1);
|
||||
|
||||
do
|
||||
{
|
||||
buffer_[i] = buffer_[i - 1];
|
||||
|
||||
i--;
|
||||
}
|
||||
while (i > target);
|
||||
|
||||
buffer_[target] = result;
|
||||
}
|
||||
|
||||
return (unsigned int) result;
|
||||
}
|
||||
|
||||
void insert(unsigned char value);
|
||||
|
||||
private:
|
||||
|
||||
unsigned char length_;
|
||||
|
||||
unsigned char buffer_[7];
|
||||
};
|
||||
|
||||
#endif /* CharCache_H */
|
||||
1087
nxcomp/src/Children.cpp
Normal file
1087
nxcomp/src/Children.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
nxcomp/src/ClearArea.cpp
Normal file
125
nxcomp/src/ClearArea.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ClearArea.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int ClearAreaStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ClearAreaMessage *clearArea = (ClearAreaMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
clearArea -> exposures = *(buffer + 1);
|
||||
|
||||
clearArea -> window = GetULONG(buffer + 4, bigEndian);
|
||||
|
||||
clearArea -> x = GetUINT(buffer + 8, bigEndian);
|
||||
clearArea -> y = GetUINT(buffer + 10, bigEndian);
|
||||
clearArea -> width = GetUINT(buffer + 12, bigEndian);
|
||||
clearArea -> height = GetUINT(buffer + 14, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClearAreaStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ClearAreaMessage *clearArea = (ClearAreaMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
*(buffer + 1) = clearArea -> exposures;
|
||||
|
||||
PutULONG(clearArea -> window, buffer + 4, bigEndian);
|
||||
|
||||
PutUINT(clearArea -> x, buffer + 8, bigEndian);
|
||||
PutUINT(clearArea -> y, buffer + 10, bigEndian);
|
||||
PutUINT(clearArea -> width, buffer + 12, bigEndian);
|
||||
PutUINT(clearArea -> height, buffer + 14, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ClearAreaStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
ClearAreaMessage *clearArea = (ClearAreaMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity exposures " << (unsigned int) clearArea -> exposures
|
||||
<< ", window " << clearArea -> window << ", x " << clearArea -> x
|
||||
<< ", y " << clearArea -> y << ", width " << clearArea -> width
|
||||
<< ", height " << clearArea -> height << ", size " << clearArea -> size_
|
||||
<< ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClearAreaStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
md5_append(md5_state_, buffer + 4, 4);
|
||||
md5_append(md5_state_, buffer + 8, 2);
|
||||
md5_append(md5_state_, buffer + 10, 2);
|
||||
md5_append(md5_state_, buffer + 12, 2);
|
||||
md5_append(md5_state_, buffer + 14, 2);
|
||||
}
|
||||
182
nxcomp/src/ClearArea.h
Normal file
182
nxcomp/src/ClearArea.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ClearArea_H
|
||||
#define ClearArea_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define CLEARAREA_ENABLE_CACHE 1
|
||||
#define CLEARAREA_ENABLE_DATA 0
|
||||
#define CLEARAREA_ENABLE_SPLIT 0
|
||||
#define CLEARAREA_ENABLE_COMPRESS 0
|
||||
|
||||
#define CLEARAREA_DATA_LIMIT 0
|
||||
#define CLEARAREA_DATA_OFFSET 16
|
||||
|
||||
#define CLEARAREA_CACHE_SLOTS 3000
|
||||
#define CLEARAREA_CACHE_THRESHOLD 5
|
||||
#define CLEARAREA_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class ClearAreaMessage : public Message
|
||||
{
|
||||
friend class ClearAreaStore;
|
||||
|
||||
public:
|
||||
|
||||
ClearAreaMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~ClearAreaMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char exposures;
|
||||
unsigned int window;
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
};
|
||||
|
||||
class ClearAreaStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
ClearAreaStore() : MessageStore()
|
||||
{
|
||||
enableCache = CLEARAREA_ENABLE_CACHE;
|
||||
enableData = CLEARAREA_ENABLE_DATA;
|
||||
enableSplit = CLEARAREA_ENABLE_SPLIT;
|
||||
enableCompress = CLEARAREA_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = CLEARAREA_DATA_LIMIT;
|
||||
dataOffset = CLEARAREA_DATA_OFFSET;
|
||||
|
||||
cacheSlots = CLEARAREA_CACHE_SLOTS;
|
||||
cacheThreshold = CLEARAREA_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = CLEARAREA_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~ClearAreaStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "ClearArea";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_ClearArea;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(ClearAreaMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new ClearAreaMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new ClearAreaMessage((const ClearAreaMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (ClearAreaMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* ClearArea_H */
|
||||
392
nxcomp/src/ClientCache.cpp
Normal file
392
nxcomp/src/ClientCache.cpp
Normal file
@@ -0,0 +1,392 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
ClientCache::ClientCache() :
|
||||
|
||||
freeGCCache(16), freeDrawableCache(16), freeWindowCache(16),
|
||||
|
||||
cursorCache(16), colormapCache(16), visualCache(16), lastFont(0),
|
||||
|
||||
changePropertyPropertyCache(16), changePropertyTypeCache(16),
|
||||
changePropertyData32Cache(16),
|
||||
|
||||
configureWindowBitmaskCache(4),
|
||||
|
||||
convertSelectionRequestorCache(16),
|
||||
convertSelectionLastTimestamp(0),
|
||||
|
||||
copyPlaneBitPlaneCache(8),
|
||||
|
||||
createGCBitmaskCache(8),
|
||||
|
||||
createPixmapIdCache(16), createPixmapLastId(0),
|
||||
createPixmapXCache(8), createPixmapYCache(8),
|
||||
|
||||
createWindowBitmaskCache(8),
|
||||
|
||||
fillPolyNumPointsCache(8), fillPolyIndex(0),
|
||||
|
||||
getSelectionOwnerSelectionCache(8),
|
||||
|
||||
grabButtonEventMaskCache(8), grabButtonConfineCache(8),
|
||||
grabButtonModifierCache(8),
|
||||
|
||||
grabKeyboardLastTimestamp(0),
|
||||
|
||||
imageTextLengthCache(8),
|
||||
imageTextLastX(0), imageTextLastY(0),
|
||||
imageTextCacheX(8), imageTextCacheY(8),
|
||||
|
||||
polySegmentCacheX(8), polySegmentCacheY(8), polySegmentCacheIndex(0),
|
||||
|
||||
polyTextLastX(0), polyTextLastY(0), polyTextCacheX(8),
|
||||
polyTextCacheY(8), polyTextFontCache(8),
|
||||
|
||||
putImageWidthCache(8), putImageHeightCache(8), putImageLastX(0),
|
||||
putImageLastY(0), putImageXCache(8), putImageYCache(8),
|
||||
|
||||
getImagePlaneMaskCache(8),
|
||||
|
||||
queryColorsLastPixel(0),
|
||||
|
||||
setClipRectanglesXCache(8), setClipRectanglesYCache(8),
|
||||
|
||||
setDashesLengthCache(8), setDashesOffsetCache(8),
|
||||
|
||||
setSelectionOwnerCache(8), setSelectionOwnerTimestampCache(8),
|
||||
|
||||
translateCoordsSrcCache(8), translateCoordsDstCache(8),
|
||||
translateCoordsXCache(8), translateCoordsYCache(8),
|
||||
|
||||
sendEventMaskCache(16), sendEventLastSequence(0),
|
||||
sendEventIntDataCache(16),
|
||||
|
||||
putPackedImageSrcLengthCache(16), putPackedImageDstLengthCache(16),
|
||||
|
||||
//
|
||||
// RenderExtension requests.
|
||||
//
|
||||
|
||||
renderFreePictureCache(16),
|
||||
|
||||
renderGlyphSetCache(16),
|
||||
renderFreeGlyphSetCache(16),
|
||||
|
||||
renderIdCache(8),
|
||||
|
||||
renderLengthCache(16), renderFormatCache(16),
|
||||
renderValueMaskCache(8), renderNumGlyphsCache(8),
|
||||
|
||||
renderXCache(16), renderYCache(16),
|
||||
renderLastX(0), renderLastY(0),
|
||||
|
||||
renderWidthCache(16), renderHeightCache(16),
|
||||
|
||||
renderLastId(0),
|
||||
|
||||
renderGlyphXCache(16), renderGlyphYCache(16),
|
||||
renderGlyphX(0), renderGlyphY(0),
|
||||
|
||||
renderLastCompositeGlyphsData(0),
|
||||
|
||||
setCacheParametersCache(8),
|
||||
|
||||
lastIdCache(16), lastId(0)
|
||||
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
allocColorRGBCache[i] = new IntCache(8);
|
||||
|
||||
convertSelectionAtomCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
clearAreaGeomCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
configureWindowAttrCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
copyAreaGeomCache[i] = new IntCache(8);
|
||||
copyPlaneGeomCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 23; i++)
|
||||
{
|
||||
if (CREATEGC_FIELD_WIDTH[i] > 16)
|
||||
{
|
||||
createGCAttrCache[i] = new IntCache(16);
|
||||
}
|
||||
else
|
||||
{
|
||||
createGCAttrCache[i] = new IntCache(CREATEGC_FIELD_WIDTH[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
createWindowGeomCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
createWindowAttrCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
fillPolyXRelCache[i] = new IntCache(8);
|
||||
fillPolyXAbsCache[i] = new IntCache(8);
|
||||
fillPolyYRelCache[i] = new IntCache(8);
|
||||
fillPolyYAbsCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
fillPolyRecentX[i] = 0;
|
||||
fillPolyRecentY[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
polyFillRectangleCacheX[i] = new IntCache(8);
|
||||
polyFillRectangleCacheY[i] = new IntCache(8);
|
||||
polyFillRectangleCacheWidth[i] = new IntCache(8);
|
||||
polyFillRectangleCacheHeight[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
polyLineCacheX[i] = new IntCache(8);
|
||||
polyLineCacheY[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
polyPointCacheX[i] = new IntCache(8);
|
||||
polyPointCacheY[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
polyRectangleGeomCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
polySegmentLastX[i] = 0;
|
||||
polySegmentLastY[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
setClipRectanglesGeomCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
polyFillArcCacheX[i] = new IntCache(8);
|
||||
polyFillArcCacheY[i] = new IntCache(8);
|
||||
polyFillArcCacheWidth[i] = new IntCache(8);
|
||||
polyFillArcCacheHeight[i] = new IntCache(8);
|
||||
polyFillArcCacheAngle1[i] = new IntCache(8);
|
||||
polyFillArcCacheAngle2[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
polyArcCacheX[i] = new IntCache(8);
|
||||
polyArcCacheY[i] = new IntCache(8);
|
||||
polyArcCacheWidth[i] = new IntCache(8);
|
||||
polyArcCacheHeight[i] = new IntCache(8);
|
||||
polyArcCacheAngle1[i] = new IntCache(8);
|
||||
polyArcCacheAngle2[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
shapeDataCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
genericRequestDataCache[i] = new IntCache(8);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
renderDataCache[i] = new IntCache(16);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
renderCompositeGlyphsDataCache[i] = new IntCache(16);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
renderCompositeDataCache[i] = new IntCache(16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ClientCache::~ClientCache()
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
delete allocColorRGBCache[i];
|
||||
delete convertSelectionAtomCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
delete clearAreaGeomCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
delete configureWindowAttrCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
delete copyAreaGeomCache[i];
|
||||
delete copyPlaneGeomCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 23; i++)
|
||||
{
|
||||
delete createGCAttrCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
delete createWindowGeomCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
delete createWindowAttrCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
delete fillPolyXRelCache[i];
|
||||
delete fillPolyXAbsCache[i];
|
||||
delete fillPolyYRelCache[i];
|
||||
delete fillPolyYAbsCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
delete polyFillRectangleCacheX[i];
|
||||
delete polyFillRectangleCacheY[i];
|
||||
delete polyFillRectangleCacheWidth[i];
|
||||
delete polyFillRectangleCacheHeight[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
delete polyLineCacheX[i];
|
||||
delete polyLineCacheY[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
delete polyPointCacheX[i];
|
||||
delete polyPointCacheY[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
delete polyRectangleGeomCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
delete setClipRectanglesGeomCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
delete polyFillArcCacheX[i];
|
||||
delete polyFillArcCacheY[i];
|
||||
delete polyFillArcCacheWidth[i];
|
||||
delete polyFillArcCacheHeight[i];
|
||||
delete polyFillArcCacheAngle1[i];
|
||||
delete polyFillArcCacheAngle2[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
delete polyArcCacheX[i];
|
||||
delete polyArcCacheY[i];
|
||||
delete polyArcCacheWidth[i];
|
||||
delete polyArcCacheHeight[i];
|
||||
delete polyArcCacheAngle1[i];
|
||||
delete polyArcCacheAngle2[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
delete shapeDataCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
delete genericRequestDataCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
delete renderDataCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
delete renderCompositeGlyphsDataCache[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
delete renderCompositeDataCache[i];
|
||||
}
|
||||
}
|
||||
417
nxcomp/src/ClientCache.h
Normal file
417
nxcomp/src/ClientCache.h
Normal file
@@ -0,0 +1,417 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ClientCache_H
|
||||
#define ClientCache_H
|
||||
|
||||
#include "Misc.h"
|
||||
|
||||
#include "IntCache.h"
|
||||
#include "CharCache.h"
|
||||
#include "OpcodeCache.h"
|
||||
#include "XidCache.h"
|
||||
#include "FreeCache.h"
|
||||
|
||||
#include "ChannelCache.h"
|
||||
|
||||
class ClientCache : public ChannelCache
|
||||
{
|
||||
public:
|
||||
|
||||
ClientCache();
|
||||
|
||||
~ClientCache();
|
||||
|
||||
//
|
||||
// Opcode prediction caches.
|
||||
//
|
||||
|
||||
OpcodeCache opcodeCache;
|
||||
|
||||
//
|
||||
// GC and drawables caches.
|
||||
//
|
||||
|
||||
XidCache gcCache;
|
||||
FreeCache freeGCCache;
|
||||
|
||||
XidCache drawableCache;
|
||||
FreeCache freeDrawableCache;
|
||||
|
||||
XidCache windowCache;
|
||||
FreeCache freeWindowCache;
|
||||
|
||||
//
|
||||
// General-purpose caches.
|
||||
//
|
||||
|
||||
IntCache cursorCache;
|
||||
IntCache colormapCache;
|
||||
IntCache visualCache;
|
||||
CharCache depthCache;
|
||||
CharCache resourceCache;
|
||||
CharCache methodCache;
|
||||
|
||||
unsigned int lastFont;
|
||||
|
||||
//
|
||||
// AllocColor request.
|
||||
//
|
||||
|
||||
IntCache *allocColorRGBCache[3];
|
||||
|
||||
//
|
||||
// ChangeProperty request.
|
||||
//
|
||||
|
||||
CharCache changePropertyFormatCache;
|
||||
IntCache changePropertyPropertyCache;
|
||||
IntCache changePropertyTypeCache;
|
||||
IntCache changePropertyData32Cache;
|
||||
|
||||
//
|
||||
// ClearArea request.
|
||||
//
|
||||
|
||||
IntCache *clearAreaGeomCache[4];
|
||||
|
||||
//
|
||||
// ConfigureWindow request.
|
||||
//
|
||||
|
||||
IntCache configureWindowBitmaskCache;
|
||||
IntCache *configureWindowAttrCache[7];
|
||||
|
||||
//
|
||||
// ConvertSelection request.
|
||||
//
|
||||
|
||||
IntCache convertSelectionRequestorCache;
|
||||
IntCache* convertSelectionAtomCache[3];
|
||||
unsigned int convertSelectionLastTimestamp;
|
||||
|
||||
//
|
||||
// CopyArea request.
|
||||
//
|
||||
|
||||
IntCache *copyAreaGeomCache[6];
|
||||
|
||||
//
|
||||
// CopyPlane request.
|
||||
//
|
||||
|
||||
IntCache *copyPlaneGeomCache[6];
|
||||
IntCache copyPlaneBitPlaneCache;
|
||||
|
||||
//
|
||||
// CreateGC request.
|
||||
//
|
||||
|
||||
IntCache createGCBitmaskCache;
|
||||
IntCache *createGCAttrCache[23];
|
||||
|
||||
//
|
||||
// CreatePixmap request.
|
||||
//
|
||||
|
||||
IntCache createPixmapIdCache;
|
||||
unsigned int createPixmapLastId;
|
||||
IntCache createPixmapXCache;
|
||||
IntCache createPixmapYCache;
|
||||
|
||||
//
|
||||
// CreateWindow request.
|
||||
//
|
||||
|
||||
IntCache *createWindowGeomCache[6];
|
||||
IntCache createWindowBitmaskCache;
|
||||
IntCache *createWindowAttrCache[15];
|
||||
|
||||
//
|
||||
// FillPoly request.
|
||||
//
|
||||
|
||||
IntCache fillPolyNumPointsCache;
|
||||
IntCache *fillPolyXRelCache[10];
|
||||
IntCache *fillPolyXAbsCache[10];
|
||||
IntCache *fillPolyYRelCache[10];
|
||||
IntCache *fillPolyYAbsCache[10];
|
||||
unsigned int fillPolyRecentX[8];
|
||||
unsigned int fillPolyRecentY[8];
|
||||
unsigned int fillPolyIndex;
|
||||
|
||||
//
|
||||
// GetSelectionOwner request.
|
||||
//
|
||||
|
||||
IntCache getSelectionOwnerSelectionCache;
|
||||
|
||||
//
|
||||
// GrabButton request (also used for GrabPointer).
|
||||
//
|
||||
|
||||
IntCache grabButtonEventMaskCache;
|
||||
IntCache grabButtonConfineCache;
|
||||
CharCache grabButtonButtonCache;
|
||||
IntCache grabButtonModifierCache;
|
||||
|
||||
//
|
||||
// GrabKeyboard request.
|
||||
//
|
||||
|
||||
unsigned int grabKeyboardLastTimestamp;
|
||||
|
||||
//
|
||||
// ImageText8/16 request.
|
||||
//
|
||||
|
||||
IntCache imageTextLengthCache;
|
||||
unsigned int imageTextLastX;
|
||||
unsigned int imageTextLastY;
|
||||
IntCache imageTextCacheX;
|
||||
IntCache imageTextCacheY;
|
||||
|
||||
//
|
||||
// PolyFillRectangle request.
|
||||
//
|
||||
|
||||
IntCache *polyFillRectangleCacheX[4];
|
||||
IntCache *polyFillRectangleCacheY[4];
|
||||
IntCache *polyFillRectangleCacheWidth[4];
|
||||
IntCache *polyFillRectangleCacheHeight[4];
|
||||
|
||||
//
|
||||
// PolyLine request.
|
||||
//
|
||||
|
||||
IntCache *polyLineCacheX[2];
|
||||
IntCache *polyLineCacheY[2];
|
||||
|
||||
//
|
||||
// PolyPoint request.
|
||||
//
|
||||
|
||||
IntCache *polyPointCacheX[2];
|
||||
IntCache *polyPointCacheY[2];
|
||||
|
||||
//
|
||||
// PolyRectangle request.
|
||||
//
|
||||
|
||||
IntCache *polyRectangleGeomCache[4];
|
||||
|
||||
//
|
||||
// PolySegment request.
|
||||
//
|
||||
|
||||
IntCache polySegmentCacheX;
|
||||
IntCache polySegmentCacheY;
|
||||
unsigned int polySegmentLastX[2];
|
||||
unsigned int polySegmentLastY[2];
|
||||
unsigned int polySegmentCacheIndex;
|
||||
|
||||
//
|
||||
// PolyText8/16 request.
|
||||
//
|
||||
|
||||
unsigned int polyTextLastX;
|
||||
unsigned int polyTextLastY;
|
||||
IntCache polyTextCacheX;
|
||||
IntCache polyTextCacheY;
|
||||
IntCache polyTextFontCache;
|
||||
CharCache polyTextDeltaCache;
|
||||
|
||||
//
|
||||
// PutImage request.
|
||||
//
|
||||
|
||||
IntCache putImageWidthCache;
|
||||
IntCache putImageHeightCache;
|
||||
unsigned int putImageLastX;
|
||||
unsigned int putImageLastY;
|
||||
IntCache putImageXCache;
|
||||
IntCache putImageYCache;
|
||||
CharCache putImageLeftPadCache;
|
||||
|
||||
//
|
||||
// GetImage request.
|
||||
//
|
||||
|
||||
IntCache getImagePlaneMaskCache;
|
||||
|
||||
//
|
||||
// QueryColors request.
|
||||
//
|
||||
|
||||
unsigned int queryColorsLastPixel;
|
||||
|
||||
//
|
||||
// SetClipRectangles request.
|
||||
//
|
||||
|
||||
IntCache setClipRectanglesXCache;
|
||||
IntCache setClipRectanglesYCache;
|
||||
IntCache *setClipRectanglesGeomCache[4];
|
||||
|
||||
//
|
||||
// SetDashes request.
|
||||
//
|
||||
|
||||
IntCache setDashesLengthCache;
|
||||
IntCache setDashesOffsetCache;
|
||||
CharCache setDashesDashCache_[2];
|
||||
|
||||
//
|
||||
// SetSelectionOwner request.
|
||||
//
|
||||
|
||||
IntCache setSelectionOwnerCache;
|
||||
IntCache setSelectionOwnerTimestampCache;
|
||||
|
||||
//
|
||||
// TranslateCoords request.
|
||||
//
|
||||
|
||||
IntCache translateCoordsSrcCache;
|
||||
IntCache translateCoordsDstCache;
|
||||
IntCache translateCoordsXCache;
|
||||
IntCache translateCoordsYCache;
|
||||
|
||||
//
|
||||
// SendEvent request.
|
||||
//
|
||||
|
||||
IntCache sendEventMaskCache;
|
||||
CharCache sendEventCodeCache;
|
||||
CharCache sendEventByteDataCache;
|
||||
unsigned int sendEventLastSequence;
|
||||
IntCache sendEventIntDataCache;
|
||||
CharCache sendEventEventCache;
|
||||
|
||||
//
|
||||
// PolyFillArc request.
|
||||
//
|
||||
|
||||
IntCache *polyFillArcCacheX[2];
|
||||
IntCache *polyFillArcCacheY[2];
|
||||
IntCache *polyFillArcCacheWidth[2];
|
||||
IntCache *polyFillArcCacheHeight[2];
|
||||
IntCache *polyFillArcCacheAngle1[2];
|
||||
IntCache *polyFillArcCacheAngle2[2];
|
||||
|
||||
//
|
||||
// PolyArc request.
|
||||
//
|
||||
|
||||
IntCache *polyArcCacheX[2];
|
||||
IntCache *polyArcCacheY[2];
|
||||
IntCache *polyArcCacheWidth[2];
|
||||
IntCache *polyArcCacheHeight[2];
|
||||
IntCache *polyArcCacheAngle1[2];
|
||||
IntCache *polyArcCacheAngle2[2];
|
||||
|
||||
//
|
||||
// PutPackedImage request.
|
||||
//
|
||||
|
||||
IntCache putPackedImageSrcLengthCache;
|
||||
IntCache putPackedImageDstLengthCache;
|
||||
|
||||
//
|
||||
// Shape extension requests.
|
||||
//
|
||||
|
||||
CharCache shapeOpcodeCache;
|
||||
IntCache *shapeDataCache[8];
|
||||
|
||||
//
|
||||
// Generic requests.
|
||||
//
|
||||
|
||||
CharCache genericRequestOpcodeCache;
|
||||
IntCache *genericRequestDataCache[8];
|
||||
|
||||
//
|
||||
// Render extension requests.
|
||||
//
|
||||
|
||||
OpcodeCache renderOpcodeCache;
|
||||
|
||||
CharCache renderOpCache;
|
||||
|
||||
XidCache renderSrcPictureCache;
|
||||
XidCache renderMaskPictureCache;
|
||||
XidCache renderDstPictureCache;
|
||||
FreeCache renderFreePictureCache;
|
||||
|
||||
IntCache renderGlyphSetCache;
|
||||
FreeCache renderFreeGlyphSetCache;
|
||||
|
||||
IntCache renderIdCache;
|
||||
IntCache renderLengthCache;
|
||||
IntCache renderFormatCache;
|
||||
IntCache renderValueMaskCache;
|
||||
IntCache renderNumGlyphsCache;
|
||||
|
||||
IntCache renderXCache;
|
||||
IntCache renderYCache;
|
||||
|
||||
unsigned int renderLastX;
|
||||
unsigned int renderLastY;
|
||||
|
||||
IntCache renderWidthCache;
|
||||
IntCache renderHeightCache;
|
||||
|
||||
unsigned int renderLastId;
|
||||
|
||||
IntCache *renderDataCache[16];
|
||||
|
||||
IntCache renderGlyphXCache;
|
||||
IntCache renderGlyphYCache;
|
||||
|
||||
unsigned int renderGlyphX;
|
||||
unsigned int renderGlyphY;
|
||||
|
||||
IntCache *renderCompositeGlyphsDataCache[16];
|
||||
unsigned int renderLastCompositeGlyphsData;
|
||||
|
||||
IntCache *renderCompositeDataCache[3];
|
||||
|
||||
//
|
||||
// SetCacheParameters request.
|
||||
//
|
||||
|
||||
IntCache setCacheParametersCache;
|
||||
|
||||
//
|
||||
// Encode new XID values based
|
||||
// on the last value encoded.
|
||||
//
|
||||
|
||||
IntCache lastIdCache;
|
||||
unsigned int lastId;
|
||||
};
|
||||
|
||||
#endif /* ClientCache_H */
|
||||
7881
nxcomp/src/ClientChannel.cpp
Normal file
7881
nxcomp/src/ClientChannel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
434
nxcomp/src/ClientChannel.h
Normal file
434
nxcomp/src/ClientChannel.h
Normal file
@@ -0,0 +1,434 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ClientChannel_H
|
||||
#define ClientChannel_H
|
||||
|
||||
#include "List.h"
|
||||
#include "Channel.h"
|
||||
|
||||
#include "SequenceQueue.h"
|
||||
|
||||
#include "ClientReadBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// If defined, the client channel will
|
||||
// have the chance of suppressing more
|
||||
// opcodes for test purposes.
|
||||
//
|
||||
|
||||
#undef LAME
|
||||
|
||||
//
|
||||
// Define this to log a line when a
|
||||
// channel is created or destroyed.
|
||||
//
|
||||
|
||||
#undef REFERENCES
|
||||
|
||||
//
|
||||
// This class implements the X client
|
||||
// side compression of the protocol.
|
||||
//
|
||||
|
||||
class ClientChannel : public Channel
|
||||
{
|
||||
public:
|
||||
|
||||
ClientChannel(Transport *transport, StaticCompressor *compressor);
|
||||
|
||||
virtual ~ClientChannel();
|
||||
|
||||
virtual int handleRead(EncodeBuffer &encodeBuffer, const unsigned char *message,
|
||||
unsigned int length);
|
||||
|
||||
virtual int handleWrite(const unsigned char *message, unsigned int length);
|
||||
|
||||
virtual int handleSplit(EncodeBuffer &encodeBuffer, MessageStore *store,
|
||||
T_store_action action, int position, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
virtual int handleSplit(DecodeBuffer &decodeBuffer, MessageStore *store,
|
||||
T_store_action action, int position, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleSplit(EncodeBuffer &encodeBuffer);
|
||||
|
||||
virtual int handleSplit(DecodeBuffer &decodeBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleSplitEvent(EncodeBuffer &encodeBuffer, Split *split);
|
||||
|
||||
virtual int handleSplitEvent(DecodeBuffer &decodeBuffer);
|
||||
|
||||
virtual int handleMotion(EncodeBuffer &encodeBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleCompletion(EncodeBuffer &encodeBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleConfiguration();
|
||||
|
||||
virtual int handleFinish();
|
||||
|
||||
virtual int handleAsyncEvents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int needSplit() const
|
||||
{
|
||||
#if defined(TEST) || defined(SPLIT)
|
||||
*logofs << "needSplit: SPLIT! Returning pending split "
|
||||
<< "flag " << splitState_.pending << " with "
|
||||
<< clientStore_ -> getSplitTotalSize()
|
||||
<< " splits in the split stores.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return splitState_.pending;
|
||||
}
|
||||
|
||||
virtual int needMotion() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual T_channel_type getType() const
|
||||
{
|
||||
return channel_x11;
|
||||
}
|
||||
|
||||
int setBigEndian(int flag);
|
||||
|
||||
//
|
||||
// Initialize the static members.
|
||||
//
|
||||
|
||||
static int setReferences();
|
||||
|
||||
private:
|
||||
|
||||
int handleFastReadRequest(EncodeBuffer &encodeBuffer, const unsigned char &opcode,
|
||||
const unsigned char *&buffer, const unsigned int &size);
|
||||
|
||||
int handleFastWriteReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size);
|
||||
|
||||
int handleFastWriteEvent(DecodeBuffer &decodeBuffer, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size);
|
||||
|
||||
//
|
||||
// Intercept the request before the opcode
|
||||
// is encoded.
|
||||
//
|
||||
|
||||
int handleTaintRequest(unsigned char &opcode, const unsigned char *&buffer,
|
||||
unsigned int &size)
|
||||
{
|
||||
if (control -> TaintReplies > 0 &&
|
||||
opcode == X_GetInputFocus)
|
||||
{
|
||||
return handleTaintSyncRequest(opcode, buffer, size);
|
||||
}
|
||||
|
||||
#ifdef LAME
|
||||
|
||||
return handleTaintLameRequest(opcode, buffer, size);
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handleTaintLameRequest(unsigned char &opcode, const unsigned char *&buffer,
|
||||
unsigned int &size);
|
||||
|
||||
int handleTaintSyncRequest(unsigned char &opcode, const unsigned char *&buffer,
|
||||
unsigned int &size);
|
||||
|
||||
int handleTaintSyncError(unsigned char opcode);
|
||||
|
||||
//
|
||||
// How to handle sequence counter
|
||||
// in notification event.
|
||||
//
|
||||
|
||||
enum T_sequence_mode
|
||||
{
|
||||
sequence_immediate,
|
||||
sequence_deferred
|
||||
};
|
||||
|
||||
//
|
||||
// Send split notifications to the
|
||||
// agent.
|
||||
//
|
||||
|
||||
int handleRestart(T_sequence_mode mode, int resource);
|
||||
|
||||
int handleNotify(T_notification_type type, T_sequence_mode mode,
|
||||
int resource, int request, int position);
|
||||
|
||||
//
|
||||
// Other utility functions used in
|
||||
// handling of the image streaming.
|
||||
//
|
||||
|
||||
int mustSplitMessage(int resource)
|
||||
{
|
||||
return (clientStore_ -> getSplitStore(resource) ->
|
||||
getSize() != 0);
|
||||
}
|
||||
|
||||
int canSplitMessage(T_split_mode mode, unsigned int size)
|
||||
{
|
||||
return ((int) size >= control -> SplitDataThreshold &&
|
||||
(clientStore_ -> getSplitTotalStorageSize() < control ->
|
||||
SplitTotalStorageSize && clientStore_ ->
|
||||
getSplitTotalSize() < control -> SplitTotalSize));
|
||||
}
|
||||
|
||||
int canSendSplit(Split *split)
|
||||
{
|
||||
return (split -> getMode() != split_sync ||
|
||||
split -> getState() == split_missed ||
|
||||
split -> getState() == split_loaded);
|
||||
}
|
||||
|
||||
int handleSplitSend(EncodeBuffer &encodeBuffer, int resource,
|
||||
int &total, int &bytes);
|
||||
|
||||
Split *handleSplitFind(T_checksum checksum, int resource);
|
||||
|
||||
int handleSplitChecksum(EncodeBuffer &encodeBuffer, T_checksum checksum);
|
||||
|
||||
void handleSplitPending(int resource)
|
||||
{
|
||||
if (splitState_.pending == 0)
|
||||
{
|
||||
if (clientStore_ -> getSplitStore(resource) != NULL &&
|
||||
clientStore_ -> getSplitStore(resource) ->
|
||||
getFirstSplit() != NULL)
|
||||
{
|
||||
splitState_.pending = canSendSplit(clientStore_ ->
|
||||
getSplitStore(resource) -> getFirstSplit());
|
||||
|
||||
#if defined(TEST) || defined(SPLIT)
|
||||
*logofs << "handleSplitPending: SPLIT! Set the pending "
|
||||
<< "split flag to " << splitState_.pending
|
||||
<< " with " << clientStore_ -> getSplitTotalSize()
|
||||
<< " splits in the split stores.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Scan all the split stores to find
|
||||
// if there is any split to send.
|
||||
//
|
||||
|
||||
void handleSplitPending();
|
||||
|
||||
//
|
||||
// Handle the MIT-SHM initialization
|
||||
// messages exchanged with the remote
|
||||
// proxy.
|
||||
//
|
||||
|
||||
int handleShmemRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
int handleShmemReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size);
|
||||
|
||||
//
|
||||
// Query the port used to tunnel
|
||||
// the font server connections.
|
||||
//
|
||||
|
||||
int handleFontRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
int handleFontReply(DecodeBuffer &decodeBuffer, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size);
|
||||
|
||||
//
|
||||
// Let the agent set the cache
|
||||
// policy for image requests.
|
||||
//
|
||||
|
||||
int handleCacheRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
//
|
||||
// Encode the start and end split
|
||||
// requests.
|
||||
//
|
||||
|
||||
int handleStartSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
int handleEndSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
//
|
||||
// Empty a split store and send the
|
||||
// restart event.
|
||||
//
|
||||
|
||||
int handleAbortSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
//
|
||||
// Force the proxy to finalize all
|
||||
// the pending split operations and
|
||||
// restart a resource.
|
||||
//
|
||||
|
||||
int handleFinishSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
//
|
||||
// Tell the remote peer to send the
|
||||
// split requests to the X server.
|
||||
//
|
||||
|
||||
int handleCommitSplitRequest(EncodeBuffer &encodeBuffer, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size);
|
||||
|
||||
//
|
||||
// Other utilities.
|
||||
//
|
||||
|
||||
void handleDecodeCharInfo(DecodeBuffer &, unsigned char *);
|
||||
|
||||
//
|
||||
// Own read buffer. It is able to identify
|
||||
// full messages read from the X descriptor.
|
||||
//
|
||||
|
||||
ClientReadBuffer readBuffer_;
|
||||
|
||||
//
|
||||
// Sequence number of last request coming
|
||||
// from the X client or the X server.
|
||||
//
|
||||
|
||||
unsigned int clientSequence_;
|
||||
unsigned int serverSequence_;
|
||||
|
||||
//
|
||||
// Last sequence number known by client. It can
|
||||
// be the real sequence generated by server or
|
||||
// the one of the last auto-generated event.
|
||||
//
|
||||
|
||||
unsigned int lastSequence_;
|
||||
|
||||
//
|
||||
// Used to identify replies based on sequence
|
||||
// number of original request.
|
||||
//
|
||||
|
||||
SequenceQueue sequenceQueue_;
|
||||
|
||||
//
|
||||
// This is used to test the synchronous flush
|
||||
// in the proxy.
|
||||
//
|
||||
|
||||
int lastRequest_;
|
||||
|
||||
//
|
||||
// Current resource id selected as target and
|
||||
// other information related to the image split.
|
||||
// The pending and abort flags are set when we
|
||||
// want the proxy to give us a chance to send
|
||||
// more split data. We also save the position
|
||||
// of the last commit operation performed by
|
||||
// channel so we can differentially encode the
|
||||
// position of next message to commit.
|
||||
//
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int resource;
|
||||
int pending;
|
||||
int commit;
|
||||
T_split_mode mode;
|
||||
|
||||
} T_split_state;
|
||||
|
||||
T_split_state splitState_;
|
||||
|
||||
//
|
||||
// List of agent resources.
|
||||
//
|
||||
|
||||
List splitResources_;
|
||||
|
||||
//
|
||||
// How many sync requests we
|
||||
// have tainted so far.
|
||||
//
|
||||
|
||||
int taintCounter_;
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Keep track of object
|
||||
// creation and deletion.
|
||||
//
|
||||
|
||||
#ifdef REFERENCES
|
||||
|
||||
static int references_;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* ClientChannel_H */
|
||||
553
nxcomp/src/ClientProxy.cpp
Normal file
553
nxcomp/src/ClientProxy.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Socket.h"
|
||||
#include "Agent.h"
|
||||
|
||||
#include "ClientProxy.h"
|
||||
|
||||
#include "ClientChannel.h"
|
||||
#include "GenericChannel.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Log the operations related to sending
|
||||
// and receiving the control tokens.
|
||||
//
|
||||
|
||||
#undef TOKEN
|
||||
|
||||
ClientProxy::ClientProxy(int proxyFd) : Proxy(proxyFd)
|
||||
{
|
||||
fontServerPort_ = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "ClientProxy: Created new object at " << this
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
ClientProxy::~ClientProxy()
|
||||
{
|
||||
delete [] fontServerPort_;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "ClientProxy: Deleted object at " << this
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClientProxy::handleDisplayConfiguration(const char *xServerDisplay, int xServerAddrFamily,
|
||||
sockaddr * xServerAddr, unsigned int xServerAddrLength)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << "ClientProxy: No display configuration to set.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClientProxy::handlePortConfiguration(ChannelEndPoint &cupsServerPort,
|
||||
ChannelEndPoint &smbServerPort,
|
||||
ChannelEndPoint &mediaServerPort,
|
||||
ChannelEndPoint &httpServerPort,
|
||||
const char *fontServerPort)
|
||||
{
|
||||
delete [] fontServerPort_;
|
||||
|
||||
fontServerPort_ = new char[strlen(fontServerPort) + 1];
|
||||
|
||||
strcpy(fontServerPort_, fontServerPort);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "ClientProxy: Set port configuration to font '"
|
||||
<< fontServerPort_ << "'.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ClientProxy::handleNewConnection(T_channel_type type, int clientFd)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case channel_x11:
|
||||
{
|
||||
return handleNewXConnection(clientFd);
|
||||
}
|
||||
case channel_cups:
|
||||
{
|
||||
return handleNewGenericConnection(clientFd, channel_cups, "CUPS");
|
||||
}
|
||||
case channel_smb:
|
||||
{
|
||||
return handleNewGenericConnection(clientFd, channel_smb, "SMB");
|
||||
}
|
||||
case channel_media:
|
||||
{
|
||||
return handleNewGenericConnection(clientFd, channel_media, "media");
|
||||
}
|
||||
case channel_http:
|
||||
{
|
||||
return handleNewGenericConnection(clientFd, channel_http, "HTTP");
|
||||
}
|
||||
case channel_slave:
|
||||
{
|
||||
return handleNewSlaveConnection(clientFd);
|
||||
}
|
||||
default:
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Unsupported channel with type '"
|
||||
<< getTypeName(type) << "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Unsupported channel with type '"
|
||||
<< getTypeName(type) << "'.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ClientProxy::handleNewConnectionFromProxy(T_channel_type type, int channelId)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case channel_font:
|
||||
{
|
||||
int port = atoi(fontServerPort_);
|
||||
|
||||
if (port > 0)
|
||||
{
|
||||
//
|
||||
// Connect on the TCP port number.
|
||||
//
|
||||
|
||||
return handleNewGenericConnectionFromProxyTCP(channelId, channel_font, "localhost",
|
||||
port, "font");
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Connect to the Unix path.
|
||||
//
|
||||
|
||||
return handleNewGenericConnectionFromProxyUnix(channelId, channel_font,
|
||||
fontServerPort_, "font");
|
||||
}
|
||||
}
|
||||
case channel_slave:
|
||||
{
|
||||
return handleNewSlaveConnectionFromProxy(channelId);
|
||||
}
|
||||
default:
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Unsupported channel with type '"
|
||||
<< getTypeName(type) << "'.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Unsupported channel with type '"
|
||||
<< getTypeName(type) << "'.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ClientProxy::handleNewAgentConnection(Agent *agent)
|
||||
{
|
||||
int clientFd = agent -> getLocalFd();
|
||||
|
||||
int channelId = allocateChannelMap(clientFd);
|
||||
|
||||
if (channelId == -1)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Maximum number of available "
|
||||
<< "channels exceeded.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Maximum number of available "
|
||||
<< "channels exceeded.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
transports_[channelId] = agent -> getTransport();
|
||||
|
||||
agent_ = channelId;
|
||||
|
||||
return handleNewXConnection(clientFd);
|
||||
}
|
||||
|
||||
int ClientProxy::handleNewXConnection(int clientFd)
|
||||
{
|
||||
int channelId = getChannel(clientFd);
|
||||
|
||||
//
|
||||
// Check if the channel has been
|
||||
// already mapped.
|
||||
//
|
||||
|
||||
if (channelId == -1)
|
||||
{
|
||||
channelId = allocateChannelMap(clientFd);
|
||||
|
||||
if (channelId == -1)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Maximum number of available "
|
||||
<< "channels exceeded.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Maximum number of available "
|
||||
<< "channels exceeded.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "ClientProxy: X client descriptor FD#" << clientFd
|
||||
<< " mapped to channel ID#" << channelId << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Turn queuing off for path proxy-to-X-client.
|
||||
//
|
||||
|
||||
if (control -> OptionClientNoDelay == 1)
|
||||
{
|
||||
SetNoDelay(clientFd, control -> OptionClientNoDelay);
|
||||
}
|
||||
|
||||
//
|
||||
// If requested, set the size of the TCP send
|
||||
// and receive buffers.
|
||||
//
|
||||
|
||||
if (control -> OptionClientSendBuffer != -1)
|
||||
{
|
||||
SetSendBuffer(clientFd, control -> OptionClientSendBuffer);
|
||||
}
|
||||
|
||||
if (control -> OptionClientReceiveBuffer != -1)
|
||||
{
|
||||
SetReceiveBuffer(clientFd, control -> OptionClientReceiveBuffer);
|
||||
}
|
||||
|
||||
if (allocateTransport(clientFd, channelId) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Starting from protocol level 3 client and server
|
||||
// caches are created in proxy and shared between all
|
||||
// channels. If remote proxy has older protocol level
|
||||
// pointers are NULL and channels must create their
|
||||
// own instances.
|
||||
//
|
||||
|
||||
channels_[channelId] = new ClientChannel(transports_[channelId], compressor_);
|
||||
|
||||
if (channels_[channelId] == NULL)
|
||||
{
|
||||
deallocateTransport(channelId);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
increaseChannels(channelId);
|
||||
|
||||
//
|
||||
// Propagate channel stores and caches to the new
|
||||
// channel.
|
||||
//
|
||||
|
||||
channels_[channelId] -> setOpcodes(opcodeStore_);
|
||||
|
||||
channels_[channelId] -> setStores(clientStore_, serverStore_);
|
||||
|
||||
channels_[channelId] -> setCaches(clientCache_, serverCache_);
|
||||
|
||||
int port = atoi(fontServerPort_);
|
||||
|
||||
if (port > 0 || *fontServerPort_ != '\0')
|
||||
{
|
||||
channels_[channelId] -> setPorts(1);
|
||||
}
|
||||
|
||||
if (handleControl(code_new_x_connection, channelId) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Let channel configure itself according
|
||||
// to control parameters.
|
||||
//
|
||||
|
||||
channels_[channelId] -> handleConfiguration();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientProxy::handleNewXConnectionFromProxy(int channelId)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Can't create a new X channel "
|
||||
<< "with ID#" << channelId << " at this side.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Can't create a new X channel "
|
||||
<< "with ID#" << channelId << " at this side.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ClientProxy::handleLoad(T_load_type type)
|
||||
{
|
||||
int channelCount = getChannels(channel_x11);
|
||||
|
||||
if ((channelCount == 0 && type == load_if_first) ||
|
||||
(channelCount > 0 && type == load_if_any))
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "ClientProxy: Going to load content of client store.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
int result = handleLoadStores();
|
||||
|
||||
if (result == 1)
|
||||
{
|
||||
if (handleControl(code_load_request) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
priority_ = 1;
|
||||
}
|
||||
else if (result < 0)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "ClientProxy: WARNING! Failed to load content "
|
||||
<< "of persistent cache.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Don't abort the proxy connection in the case
|
||||
// of a corrupted cache. By not sending the load
|
||||
// message to the remote peer, both sides will
|
||||
// start encoding messages using empty stores.
|
||||
// This behaviour is compatible with old proxy
|
||||
// versions.
|
||||
//
|
||||
|
||||
if (channelCount == 0 && type == load_if_first)
|
||||
{
|
||||
if (handleResetStores() < 0)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Failed to reset message stores.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Can't load the stores with "
|
||||
<< channelCount << " remaining channels.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientProxy::handleSave()
|
||||
{
|
||||
//
|
||||
// If no more X channels are remaining
|
||||
// then save content of message stores.
|
||||
//
|
||||
|
||||
int channelCount = getChannels(channel_x11);
|
||||
|
||||
if (channelCount == 0)
|
||||
{
|
||||
int result = handleSaveStores();
|
||||
|
||||
if (result == 1)
|
||||
{
|
||||
if (handleControl(code_save_request) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
priority_ = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (result < 0)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Failed to save stores "
|
||||
<< "to persistent cache.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Can't save the stores with "
|
||||
<< channelCount << " remaining channels.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientProxy::handleAsyncEvents()
|
||||
{
|
||||
if (canRead() == 1)
|
||||
{
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "Proxy: WARNING! Reading while writing "
|
||||
<< "with data available on the proxy link.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
if (handleRead() < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ClientProxy::handleLoadFromProxy()
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Invalid load control message "
|
||||
<< "received in proxy.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Invalid load control message "
|
||||
<< "received in proxy.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ClientProxy::handleSaveFromProxy()
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientProxy: PANIC! Invalid save control message "
|
||||
<< "received in proxy.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Invalid save control message "
|
||||
<< "received in proxy.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ClientProxy::handleSaveAllStores(ostream *cachefs, md5_state_t *md5StateStream,
|
||||
md5_state_t *md5StateClient) const
|
||||
{
|
||||
if (clientStore_ -> saveRequestStores(cachefs, md5StateStream, md5StateClient,
|
||||
use_checksum, discard_data) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (serverStore_ -> saveReplyStores(cachefs, md5StateStream, md5StateClient,
|
||||
discard_checksum, use_data) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (serverStore_ -> saveEventStores(cachefs, md5StateStream, md5StateClient,
|
||||
discard_checksum, use_data) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientProxy::handleLoadAllStores(istream *cachefs, md5_state_t *md5StateStream) const
|
||||
{
|
||||
if (clientStore_ -> loadRequestStores(cachefs, md5StateStream,
|
||||
use_checksum, discard_data) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (serverStore_ -> loadReplyStores(cachefs, md5StateStream,
|
||||
discard_checksum, use_data) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (serverStore_ -> loadEventStores(cachefs, md5StateStream,
|
||||
discard_checksum, use_data) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
113
nxcomp/src/ClientProxy.h
Normal file
113
nxcomp/src/ClientProxy.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ClientProxy_H
|
||||
#define ClientProxy_H
|
||||
|
||||
#include "Proxy.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
class ClientProxy : public Proxy
|
||||
{
|
||||
public:
|
||||
|
||||
ClientProxy(int proxyFD);
|
||||
|
||||
virtual ~ClientProxy();
|
||||
|
||||
virtual void handleDisplayConfiguration(const char *xServerDisplay, int xServerAddrFamily,
|
||||
sockaddr *xServerAddr, unsigned int xServerAddrLength);
|
||||
|
||||
virtual void handlePortConfiguration(ChannelEndPoint &cupsServerPort,
|
||||
ChannelEndPoint &smbServerPort,
|
||||
ChannelEndPoint &mediaServerPort,
|
||||
ChannelEndPoint &httpServerPort,
|
||||
const char *fontServerPort);
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
// Create a new channel.
|
||||
//
|
||||
|
||||
virtual int handleNewConnection(T_channel_type type, int clientFd);
|
||||
|
||||
virtual int handleNewConnectionFromProxy(T_channel_type type, int channelId);
|
||||
|
||||
virtual int handleNewAgentConnection(Agent *agent);
|
||||
|
||||
virtual int handleNewXConnection(int clientFd);
|
||||
|
||||
virtual int handleNewXConnectionFromProxy(int channelId);
|
||||
|
||||
//
|
||||
// Implement persistence according
|
||||
// to our proxy mode.
|
||||
//
|
||||
|
||||
virtual int handleLoad(T_load_type type);
|
||||
virtual int handleSave();
|
||||
|
||||
virtual int handleAsyncEvents();
|
||||
|
||||
virtual int handleLoadFromProxy();
|
||||
virtual int handleSaveFromProxy();
|
||||
|
||||
virtual int handleSaveAllStores(ostream *cachefs, md5_state_t *md5StateStream,
|
||||
md5_state_t *md5StateClient) const;
|
||||
|
||||
virtual int handleLoadAllStores(istream *cachefs, md5_state_t *md5StateStream) const;
|
||||
|
||||
//
|
||||
// Utility function used to realize
|
||||
// a new connection.
|
||||
//
|
||||
|
||||
protected:
|
||||
|
||||
virtual int checkLocalChannelMap(int channelId)
|
||||
{
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
return ((channelId & control -> ChannelMask) != 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Ports where to forward extended services'
|
||||
// TCP connections.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
char *fontServerPort_;
|
||||
};
|
||||
|
||||
|
||||
#endif /* ClientProxy_H */
|
||||
178
nxcomp/src/ClientReadBuffer.cpp
Normal file
178
nxcomp/src/ClientReadBuffer.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ClientReadBuffer.h"
|
||||
|
||||
#include "ClientChannel.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
unsigned int ClientReadBuffer::suggestedLength(unsigned int pendingLength)
|
||||
{
|
||||
//
|
||||
// Even if the pending data is not
|
||||
// enough to make a complete message,
|
||||
// resize the buffer to accommodate
|
||||
// it all.
|
||||
//
|
||||
|
||||
unsigned int readLength = pendingLength;
|
||||
|
||||
if (pendingLength < remaining_)
|
||||
{
|
||||
readLength = remaining_;
|
||||
}
|
||||
|
||||
return readLength;
|
||||
}
|
||||
|
||||
int ClientReadBuffer::locateMessage(const unsigned char *start,
|
||||
const unsigned char *end,
|
||||
unsigned int &controlLength,
|
||||
unsigned int &dataLength,
|
||||
unsigned int &trailerLength)
|
||||
{
|
||||
unsigned int size = end - start;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "ClientReadBuffer: Locating message for FD#"
|
||||
<< transport_ -> fd() << " with " << size
|
||||
<< " bytes.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (firstMessage_)
|
||||
{
|
||||
if (size < 12)
|
||||
{
|
||||
remaining_ = 12 - size;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "ClientReadBuffer: No message was located "
|
||||
<< "with remaining " << remaining_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*start == 0x42)
|
||||
{
|
||||
bigEndian_ = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bigEndian_ = 0;
|
||||
}
|
||||
|
||||
channel_ -> setBigEndian(bigEndian_);
|
||||
|
||||
dataLength = 12 + RoundUp4(GetUINT(start + 6, bigEndian_)) +
|
||||
RoundUp4(GetUINT(start + 8, bigEndian_));
|
||||
|
||||
//
|
||||
// Send the data immediately if this is unlikely
|
||||
// to be a X connection attempt.
|
||||
//
|
||||
|
||||
if (dataLength > 4096)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "ClientReadBuffer: WARNING! Flushing suspicious X "
|
||||
<< "connection with first request of " << dataLength
|
||||
<< " bytes.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
dataLength = size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size < 4)
|
||||
{
|
||||
remaining_ = 4 - size;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "ClientReadBuffer: No message was located "
|
||||
<< "with remaining " << remaining_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
dataLength = (GetUINT(start + 2, bigEndian_) << 2);
|
||||
|
||||
if (dataLength < 4)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "ClientReadBuffer: WARNING! Assuming length 4 "
|
||||
<< "for suspicious message of length " << dataLength
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
dataLength = 4;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "ClientReadBuffer: Length of the next message is "
|
||||
<< dataLength << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (size < dataLength)
|
||||
{
|
||||
remaining_ = dataLength - size;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "ClientReadBuffer: No message was located "
|
||||
<< "with remaining " << remaining_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
firstMessage_ = 0;
|
||||
|
||||
controlLength = 0;
|
||||
trailerLength = 0;
|
||||
|
||||
remaining_ = 0;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "ClientReadBuffer: Located message with "
|
||||
<< "remaining " << remaining_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
65
nxcomp/src/ClientReadBuffer.h
Normal file
65
nxcomp/src/ClientReadBuffer.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ClientReadBuffer_H
|
||||
#define ClientReadBuffer_H
|
||||
|
||||
#include "Control.h"
|
||||
#include "ReadBuffer.h"
|
||||
|
||||
class ClientChannel;
|
||||
|
||||
class ClientReadBuffer : public ReadBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
ClientReadBuffer(Transport *transport, ClientChannel *channel)
|
||||
|
||||
: ReadBuffer(transport), firstMessage_(1), channel_(channel)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ClientReadBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual unsigned int suggestedLength(unsigned int pendingLength);
|
||||
|
||||
virtual int locateMessage(const unsigned char *start,
|
||||
const unsigned char *end,
|
||||
unsigned int &controlLength,
|
||||
unsigned int &dataLength,
|
||||
unsigned int &trailerLength);
|
||||
|
||||
int bigEndian_;
|
||||
|
||||
int firstMessage_;
|
||||
|
||||
ClientChannel *channel_;
|
||||
};
|
||||
|
||||
#endif /* ClientReadBuffer_H */
|
||||
226
nxcomp/src/ClientStore.cpp
Normal file
226
nxcomp/src/ClientStore.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ClientStore.h"
|
||||
|
||||
//
|
||||
// Cached request classes.
|
||||
//
|
||||
|
||||
#include "ChangeProperty.h"
|
||||
#include "SendEvent.h"
|
||||
#include "CreateGC.h"
|
||||
#include "ChangeGC.h"
|
||||
#include "CreatePixmap.h"
|
||||
#include "SetClipRectangles.h"
|
||||
#include "CopyArea.h"
|
||||
#include "PolyLine.h"
|
||||
#include "PolySegment.h"
|
||||
#include "PolyFillRectangle.h"
|
||||
#include "PutImage.h"
|
||||
#include "TranslateCoords.h"
|
||||
#include "GetImage.h"
|
||||
#include "ClearArea.h"
|
||||
#include "ConfigureWindow.h"
|
||||
#include "ShapeExtension.h"
|
||||
#include "RenderExtension.h"
|
||||
#include "PolyText8.h"
|
||||
#include "PolyText16.h"
|
||||
#include "ImageText8.h"
|
||||
#include "ImageText16.h"
|
||||
#include "PolyPoint.h"
|
||||
#include "PolyFillArc.h"
|
||||
#include "PolyArc.h"
|
||||
#include "FillPoly.h"
|
||||
#include "InternAtom.h"
|
||||
#include "GetProperty.h"
|
||||
#include "SetUnpackGeometry.h"
|
||||
#include "SetUnpackColormap.h"
|
||||
#include "SetUnpackAlpha.h"
|
||||
#include "PutPackedImage.h"
|
||||
#include "GenericRequest.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define WARNING
|
||||
#define PANIC
|
||||
#undef TEST
|
||||
|
||||
ClientStore::ClientStore(StaticCompressor *compressor)
|
||||
|
||||
: compressor_(compressor)
|
||||
{
|
||||
if (logofs == NULL)
|
||||
{
|
||||
logofs = &cout;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CHANNEL_STORE_OPCODE_LIMIT; i++)
|
||||
{
|
||||
requests_[i] = NULL;
|
||||
}
|
||||
|
||||
requests_[X_ChangeProperty] = new ChangePropertyStore();
|
||||
requests_[X_SendEvent] = new SendEventStore();
|
||||
requests_[X_CreateGC] = new CreateGCStore();
|
||||
requests_[X_SetClipRectangles] = new SetClipRectanglesStore();
|
||||
requests_[X_CopyArea] = new CopyAreaStore();
|
||||
requests_[X_PolyLine] = new PolyLineStore();
|
||||
requests_[X_PolySegment] = new PolySegmentStore();
|
||||
requests_[X_PolyFillRectangle] = new PolyFillRectangleStore();
|
||||
requests_[X_PutImage] = new PutImageStore(compressor);
|
||||
requests_[X_TranslateCoords] = new TranslateCoordsStore();
|
||||
requests_[X_GetImage] = new GetImageStore();
|
||||
requests_[X_ClearArea] = new ClearAreaStore();
|
||||
requests_[X_ConfigureWindow] = new ConfigureWindowStore();
|
||||
requests_[X_PolyText8] = new PolyText8Store();
|
||||
requests_[X_PolyText16] = new PolyText16Store();
|
||||
requests_[X_ImageText8] = new ImageText8Store();
|
||||
requests_[X_ImageText16] = new ImageText16Store();
|
||||
requests_[X_PolyPoint] = new PolyPointStore();
|
||||
requests_[X_PolyFillArc] = new PolyFillArcStore();
|
||||
requests_[X_PolyArc] = new PolyArcStore();
|
||||
requests_[X_FillPoly] = new FillPolyStore();
|
||||
requests_[X_InternAtom] = new InternAtomStore();
|
||||
requests_[X_GetProperty] = new GetPropertyStore();
|
||||
|
||||
requests_[X_NXInternalShapeExtension] = new ShapeExtensionStore(compressor);
|
||||
requests_[X_NXInternalGenericRequest] = new GenericRequestStore(compressor);
|
||||
requests_[X_NXInternalRenderExtension] = new RenderExtensionStore(compressor);
|
||||
requests_[X_NXSetUnpackGeometry] = new SetUnpackGeometryStore(compressor);
|
||||
requests_[X_NXPutPackedImage] = new PutPackedImageStore(compressor);
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
requests_[X_ChangeGC] = new ChangeGCStore();
|
||||
requests_[X_CreatePixmap] = new CreatePixmapStore();
|
||||
requests_[X_NXSetUnpackColormap] = new SetUnpackColormapStore(compressor);
|
||||
requests_[X_NXSetUnpackAlpha] = new SetUnpackAlphaStore(compressor);
|
||||
|
||||
for (int i = 0; i < CHANNEL_STORE_RESOURCE_LIMIT; i++)
|
||||
{
|
||||
splits_[i] = NULL;
|
||||
}
|
||||
|
||||
commits_ = new CommitStore(compressor);
|
||||
}
|
||||
|
||||
ClientStore::~ClientStore()
|
||||
{
|
||||
if (logofs == NULL)
|
||||
{
|
||||
logofs = &cout;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CHANNEL_STORE_OPCODE_LIMIT; i++)
|
||||
{
|
||||
delete requests_[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < CHANNEL_STORE_RESOURCE_LIMIT; i++)
|
||||
{
|
||||
delete splits_[i];
|
||||
}
|
||||
|
||||
delete commits_;
|
||||
}
|
||||
|
||||
int ClientStore::saveRequestStores(ostream *cachefs, md5_state_t *md5StateStream,
|
||||
md5_state_t *md5StateClient, T_checksum_action checksumAction,
|
||||
T_data_action dataAction) const
|
||||
{
|
||||
for (int i = 0; i < CHANNEL_STORE_OPCODE_LIMIT; i++)
|
||||
{
|
||||
if (requests_[i] != NULL &&
|
||||
requests_[i] -> saveStore(cachefs, md5StateStream, md5StateClient,
|
||||
checksumAction, dataAction,
|
||||
storeBigEndian()) < 0)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "ClientStore: WARNING! Error saving request store "
|
||||
<< "for OPCODE#" << (unsigned int) i << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Warning" << ": Error saving request store "
|
||||
<< "for opcode '" << (unsigned int) i << "'.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientStore::loadRequestStores(istream *cachefs, md5_state_t *md5StateStream,
|
||||
T_checksum_action checksumAction, T_data_action dataAction) const
|
||||
{
|
||||
for (int i = 0; i < CHANNEL_STORE_OPCODE_LIMIT; i++)
|
||||
{
|
||||
if (requests_[i] != NULL &&
|
||||
requests_[i] -> loadStore(cachefs, md5StateStream,
|
||||
checksumAction, dataAction,
|
||||
storeBigEndian()) < 0)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "ClientStore: WARNING! Error loading request store "
|
||||
<< "for OPCODE#" << (unsigned int) i << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ClientStore::dumpSplitStores() const
|
||||
{
|
||||
for (int i = 0; i < CHANNEL_STORE_RESOURCE_LIMIT; i++)
|
||||
{
|
||||
if (splits_[i] != NULL)
|
||||
{
|
||||
splits_[i] -> dump();
|
||||
}
|
||||
}
|
||||
|
||||
if ((getSplitTotalSize() != 0 && getSplitTotalStorageSize() == 0) ||
|
||||
(getSplitTotalSize() == 0 && getSplitTotalStorageSize() != 0))
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "ClientStore: PANIC! Inconsistency detected "
|
||||
<< "while handling the split stores.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
HandleCleanup();
|
||||
}
|
||||
}
|
||||
143
nxcomp/src/ClientStore.h
Normal file
143
nxcomp/src/ClientStore.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ClientStore_H
|
||||
#define ClientStore_H
|
||||
|
||||
#include "Message.h"
|
||||
#include "Split.h"
|
||||
|
||||
#include "ChannelStore.h"
|
||||
|
||||
class StaticCompressor;
|
||||
|
||||
class ClientStore : public ChannelStore
|
||||
{
|
||||
public:
|
||||
|
||||
ClientStore(StaticCompressor *compressor);
|
||||
|
||||
virtual ~ClientStore();
|
||||
|
||||
//
|
||||
// Get the store based on the index.
|
||||
//
|
||||
|
||||
MessageStore *getRequestStore(unsigned char opcode) const
|
||||
{
|
||||
return requests_[opcode];
|
||||
}
|
||||
|
||||
SplitStore *getSplitStore(int resource) const
|
||||
{
|
||||
return splits_[resource];
|
||||
}
|
||||
|
||||
int getSplitTotalSize() const
|
||||
{
|
||||
return SplitStore::getTotalSize();
|
||||
}
|
||||
|
||||
int getSplitTotalStorageSize() const
|
||||
{
|
||||
return SplitStore::getTotalStorageSize();
|
||||
}
|
||||
|
||||
CommitStore *getCommitStore() const
|
||||
{
|
||||
return commits_;
|
||||
}
|
||||
|
||||
int getCommitSize() const
|
||||
{
|
||||
return commits_ -> getSize();
|
||||
}
|
||||
|
||||
void dumpSplitStore(int resource) const
|
||||
{
|
||||
splits_[resource] -> dump();
|
||||
}
|
||||
|
||||
void dumpCommitStore() const
|
||||
{
|
||||
commits_ -> dump();
|
||||
}
|
||||
|
||||
void dumpSplitStores() const;
|
||||
|
||||
SplitStore *createSplitStore(int resource)
|
||||
{
|
||||
splits_[resource] = new SplitStore(compressor_, commits_, resource);
|
||||
|
||||
return splits_[resource];
|
||||
}
|
||||
|
||||
void destroySplitStore(int resource)
|
||||
{
|
||||
delete splits_[resource];
|
||||
|
||||
splits_[resource] = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Actually save the message store
|
||||
// to disk according to proxy mode.
|
||||
//
|
||||
|
||||
int saveRequestStores(ostream *cachefs, md5_state_t *md5StateStream,
|
||||
md5_state_t *md5StateClient, T_checksum_action checksumAction,
|
||||
T_data_action dataAction) const;
|
||||
|
||||
int loadRequestStores(istream *cachefs, md5_state_t *md5StateStream,
|
||||
T_checksum_action checksumAction, T_data_action dataAction) const;
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// A client store contains requests.
|
||||
//
|
||||
|
||||
MessageStore *requests_[CHANNEL_STORE_OPCODE_LIMIT];
|
||||
|
||||
//
|
||||
// Client messages being split.
|
||||
//
|
||||
|
||||
SplitStore *splits_[CHANNEL_STORE_RESOURCE_LIMIT];
|
||||
|
||||
//
|
||||
// Messages having been recomposed.
|
||||
//
|
||||
|
||||
CommitStore *commits_;
|
||||
|
||||
//
|
||||
// Passed forward to the other stores.
|
||||
//
|
||||
|
||||
StaticCompressor *compressor_;
|
||||
};
|
||||
|
||||
#endif /* ClientStore_H */
|
||||
106
nxcomp/src/Colormap.cpp
Normal file
106
nxcomp/src/Colormap.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Unpack.h"
|
||||
#include "Colormap.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
int UnpackColormap(unsigned char method, unsigned char *src_data, int src_size,
|
||||
unsigned char *dst_data, int dst_size)
|
||||
{
|
||||
if (*src_data == 0)
|
||||
{
|
||||
if (dst_size != src_size - 1)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackColormap: PANIC! Invalid destination size "
|
||||
<< dst_size << " with source " << src_size
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackColormap: Expanding " << src_size - 1
|
||||
<< " bytes of plain colormap data.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
memcpy(dst_data, src_data + 1, src_size - 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int check_size = dst_size;
|
||||
|
||||
int result = ZDecompress(&unpackStream, dst_data, &check_size,
|
||||
src_data + 1, src_size - 1);
|
||||
|
||||
if (result != Z_OK)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "UnpackColormap: PANIC! Failure decompressing colormap data. "
|
||||
<< "Error is '" << zError(result) << "'.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decompressing colormap data. "
|
||||
<< "Error is '" << zError(result) << "'.\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if (check_size != (unsigned int) dst_size)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "UnpackColormap: PANIC! Size mismatch in colormap data. "
|
||||
<< "Resulting size is " << check_size << " with "
|
||||
<< "expected size " << dst_size << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Size mismatch in colormap data. "
|
||||
<< "Resulting size is " << check_size << " with "
|
||||
<< "expected size " << dst_size << ".\n";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "UnpackColormap: Decompressed " << src_size - 1
|
||||
<< " bytes to " << dst_size << " bytes of colormap data.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
32
nxcomp/src/Colormap.h
Normal file
32
nxcomp/src/Colormap.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef Colormap_H
|
||||
#define Colormap_H
|
||||
|
||||
int UnpackColormap(unsigned char method, unsigned char *src_data, int src_size,
|
||||
unsigned char *dst_data, int dst_size);
|
||||
|
||||
#endif /* Colormap_H */
|
||||
142
nxcomp/src/ConfigureWindow.cpp
Normal file
142
nxcomp/src/ConfigureWindow.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ConfigureWindow.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int ConfigureWindowStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ConfigureWindowMessage *configureWindow = (ConfigureWindowMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
configureWindow -> window = GetULONG(buffer + 4, bigEndian);
|
||||
|
||||
configureWindow -> value_mask = GetUINT(buffer + 8, bigEndian);
|
||||
|
||||
//
|
||||
// To increase effectiveness of the caching algorithm
|
||||
// we remove the unused bytes carried in the data part.
|
||||
//
|
||||
|
||||
if ((int) size > dataOffset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Removing unused bytes from the data payload.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
configureWindow -> value_mask &= (1 << 7) - 1;
|
||||
|
||||
unsigned int mask = 0x1;
|
||||
unsigned char *source = (unsigned char *) buffer + CONFIGUREWINDOW_DATA_OFFSET;
|
||||
unsigned long value = 0;
|
||||
|
||||
for (unsigned int i = 0; i < 7; i++)
|
||||
{
|
||||
if (configureWindow -> value_mask & mask)
|
||||
{
|
||||
value = GetULONG(source, bigEndian);
|
||||
|
||||
value &= (1 << CONFIGUREWINDOW_FIELD_WIDTH[i]) - 1;
|
||||
|
||||
PutULONG(value, source, bigEndian);
|
||||
|
||||
source += 4;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ConfigureWindowStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ConfigureWindowMessage *configureWindow = (ConfigureWindowMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
PutULONG(configureWindow -> window, buffer + 4, bigEndian);
|
||||
|
||||
PutUINT(configureWindow -> value_mask, buffer + 8, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ConfigureWindowStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
ConfigureWindowMessage *configureWindow = (ConfigureWindowMessage *) message;
|
||||
|
||||
*logofs << "ConfigureWindow: window " << configureWindow -> window
|
||||
<< ", value_mask " << configureWindow -> value_mask
|
||||
<< ", size " << configureWindow -> size_ << ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConfigureWindowStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 4, 4);
|
||||
md5_append(md5_state_, buffer + 8, 2);
|
||||
}
|
||||
178
nxcomp/src/ConfigureWindow.h
Normal file
178
nxcomp/src/ConfigureWindow.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ConfigureWindow_H
|
||||
#define ConfigureWindow_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define CONFIGUREWINDOW_ENABLE_CACHE 1
|
||||
#define CONFIGUREWINDOW_ENABLE_DATA 0
|
||||
#define CONFIGUREWINDOW_ENABLE_SPLIT 0
|
||||
#define CONFIGUREWINDOW_ENABLE_COMPRESS 0
|
||||
|
||||
#define CONFIGUREWINDOW_DATA_LIMIT 32
|
||||
#define CONFIGUREWINDOW_DATA_OFFSET 12
|
||||
|
||||
#define CONFIGUREWINDOW_CACHE_SLOTS 3000
|
||||
#define CONFIGUREWINDOW_CACHE_THRESHOLD 5
|
||||
#define CONFIGUREWINDOW_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class ConfigureWindowMessage : public Message
|
||||
{
|
||||
friend class ConfigureWindowStore;
|
||||
|
||||
public:
|
||||
|
||||
ConfigureWindowMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~ConfigureWindowMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned int window;
|
||||
unsigned short value_mask;
|
||||
};
|
||||
|
||||
class ConfigureWindowStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
ConfigureWindowStore() : MessageStore()
|
||||
{
|
||||
enableCache = CONFIGUREWINDOW_ENABLE_CACHE;
|
||||
enableData = CONFIGUREWINDOW_ENABLE_DATA;
|
||||
enableSplit = CONFIGUREWINDOW_ENABLE_SPLIT;
|
||||
enableCompress = CONFIGUREWINDOW_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = CONFIGUREWINDOW_DATA_LIMIT;
|
||||
dataOffset = CONFIGUREWINDOW_DATA_OFFSET;
|
||||
|
||||
cacheSlots = CONFIGUREWINDOW_CACHE_SLOTS;
|
||||
cacheThreshold = CONFIGUREWINDOW_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = CONFIGUREWINDOW_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~ConfigureWindowStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "ConfigureWindow";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_ConfigureWindow;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(ConfigureWindowMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new ConfigureWindowMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new ConfigureWindowMessage((const ConfigureWindowMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (ConfigureWindowMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* ConfigureWindow_H */
|
||||
822
nxcomp/src/Control.cpp
Normal file
822
nxcomp/src/Control.cpp
Normal file
@@ -0,0 +1,822 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "NX.h"
|
||||
#include "NXpack.h"
|
||||
|
||||
#include "Control.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Flush immediately on prioritized messages.
|
||||
//
|
||||
|
||||
#define FLUSH_PRIORITY 0
|
||||
|
||||
//
|
||||
// Maximum number of bytes sent for each token.
|
||||
//
|
||||
|
||||
#define TOKEN_SIZE 1536
|
||||
|
||||
//
|
||||
// Maximum number of tokens that can be spent
|
||||
// by the client proxy before having to block
|
||||
// waiting for a token reply.
|
||||
//
|
||||
|
||||
#define TOKEN_LIMIT 24
|
||||
|
||||
//
|
||||
// By default assume the proxy is running as a
|
||||
// standalone program.
|
||||
//
|
||||
|
||||
#define LINK_ENCRYPTED 0
|
||||
|
||||
//
|
||||
// Maximum number of pids the proxy will record
|
||||
// and kill at shutdown.
|
||||
//
|
||||
|
||||
#define KILL_LIMIT 16
|
||||
|
||||
//
|
||||
// Allocate on the NX client side channels whose
|
||||
// ids are a multiple of 8 (starting from 0). All
|
||||
// the other ids can be used to allocate channels
|
||||
// at the NX server side (X client side).
|
||||
//
|
||||
|
||||
#define CHANNEL_MASK 0x07
|
||||
|
||||
//
|
||||
// Kill session if control parameters cannot be
|
||||
// negotiated before this timeout.
|
||||
//
|
||||
|
||||
#define INIT_TIMEOUT 60000
|
||||
|
||||
//
|
||||
// Enter the congestion state if the remote does
|
||||
// not reply to a ping within the given amount
|
||||
// of time.
|
||||
//
|
||||
|
||||
#define PING_TIMEOUT 5000
|
||||
|
||||
//
|
||||
// Only send one motion event any N milliseconds.
|
||||
//
|
||||
|
||||
#define MOTION_TIMEOUT 0
|
||||
|
||||
|
||||
//
|
||||
// Force an update of the congestion counter if
|
||||
// the proxy is idle for this time.
|
||||
//
|
||||
|
||||
#define IDLE_TIMEOUT 50
|
||||
|
||||
//
|
||||
// Close X connection if can't write before this
|
||||
// timeout.
|
||||
//
|
||||
|
||||
#define CHANNEL_TIMEOUT 10000
|
||||
|
||||
//
|
||||
// Warn user (or close proxy connection) if don't
|
||||
// receive any data before this timeout.
|
||||
//
|
||||
|
||||
#define PROXY_TIMEOUT 120000
|
||||
|
||||
//
|
||||
// How many milliseconds to wait for the shared
|
||||
// memory completion event to become available.
|
||||
//
|
||||
|
||||
#define SHMEM_TIMEOUT 200
|
||||
//
|
||||
// Before closing down the proxy, wait for the
|
||||
// given amount of milliseconds to let all the
|
||||
// running applications to close down their
|
||||
// connections.
|
||||
//
|
||||
// A null timeout will cause the proxy to wait
|
||||
// indefinitely, until the watchdog process is
|
||||
// killed. This is usually the way the proxy is
|
||||
// started by the NX server. If on the other
|
||||
// hand a timeout is given and there no channel
|
||||
// is remaining, the proxy will be closed down
|
||||
// using a small timeout, presently of 500 ms.
|
||||
//
|
||||
|
||||
#define CLEANUP_TIMEOUT 3000
|
||||
|
||||
//
|
||||
// Wait this amount of milliseconds after any
|
||||
// iteration of the house-keeping process.
|
||||
//
|
||||
|
||||
#define KEEPER_TIMEOUT 60000
|
||||
|
||||
//
|
||||
// In case of timeout, select can return control
|
||||
// to program earlier or later of this amount of
|
||||
// ms. Consider this when calculating if timeout
|
||||
// is elapsed.
|
||||
//
|
||||
|
||||
#define LATENCY_TIMEOUT 1
|
||||
|
||||
//
|
||||
// Control memory allocation in transport
|
||||
// and other classes.
|
||||
//
|
||||
|
||||
#define TRANSPORT_X_BUFFER_SIZE 131072
|
||||
#define TRANSPORT_PROXY_BUFFER_SIZE 65536
|
||||
#define TRANSPORT_GENERIC_BUFFER_SIZE 16384
|
||||
|
||||
#define TRANSPORT_X_BUFFER_THRESHOLD 262144
|
||||
#define TRANSPORT_PROXY_BUFFER_THRESHOLD 131072
|
||||
#define TRANSPORT_GENERIC_BUFFER_THRESHOLD 32768
|
||||
|
||||
//
|
||||
// Never allow buffers to exceed this limit.
|
||||
//
|
||||
|
||||
#define TRANSPORT_MAXIMUM_BUFFER_SIZE 393216
|
||||
|
||||
//
|
||||
// Immediately flush the accumulated data to
|
||||
// the X server if the write buffer exceeds
|
||||
// this size.
|
||||
//
|
||||
|
||||
#define TRANSPORT_FLUSH_BUFFER_SIZE 16384
|
||||
|
||||
//
|
||||
// Defaults used for socket options.
|
||||
//
|
||||
|
||||
#define OPTION_PROXY_KEEP_ALIVE 0
|
||||
#define OPTION_PROXY_LOW_DELAY 1
|
||||
#define OPTION_PROXY_CLIENT_NO_DELAY 1
|
||||
#define OPTION_PROXY_SERVER_NO_DELAY 1
|
||||
#define OPTION_CLIENT_NO_DELAY 1
|
||||
#define OPTION_SERVER_NO_DELAY 1
|
||||
|
||||
#define OPTION_PROXY_RECEIVE_BUFFER -1
|
||||
#define OPTION_CLIENT_RECEIVE_BUFFER -1
|
||||
#define OPTION_SERVER_RECEIVE_BUFFER -1
|
||||
|
||||
#define OPTION_PROXY_SEND_BUFFER -1
|
||||
#define OPTION_CLIENT_SEND_BUFFER -1
|
||||
#define OPTION_SERVER_SEND_BUFFER -1
|
||||
|
||||
#define OPTION_PROXY_RETRY_CONNECT 30
|
||||
#define OPTION_PROXY_RETRY_ACCEPT 3
|
||||
#define OPTION_SERVER_RETRY_CONNECT 3
|
||||
|
||||
//
|
||||
// Defaults used for cache persistence.
|
||||
//
|
||||
|
||||
#define PERSISTENT_CACHE_THRESHOLD 102400
|
||||
|
||||
#define PERSISTENT_CACHE_ENABLE_LOAD 1
|
||||
#define PERSISTENT_CACHE_ENABLE_SAVE 1
|
||||
|
||||
#define PERSISTENT_CACHE_CHECK_ON_SHUTDOWN 0
|
||||
|
||||
#define PERSISTENT_CACHE_LOAD_PACKED 1
|
||||
#define PERSISTENT_CACHE_LOAD_RENDER 1
|
||||
|
||||
#define PERSISTENT_CACHE_DISK_LIMIT 33554432
|
||||
|
||||
//
|
||||
// Defaults used for image cache.
|
||||
//
|
||||
|
||||
#define IMAGE_CACHE_ENABLE_LOAD 0
|
||||
#define IMAGE_CACHE_ENABLE_SAVE 0
|
||||
|
||||
#define IMAGE_CACHE_DISK_LIMIT 33554432
|
||||
|
||||
//
|
||||
// Suggested defaults for read length parameters
|
||||
// used by read buffer classes.
|
||||
//
|
||||
|
||||
#define CLIENT_INITIAL_READ_SIZE 8192
|
||||
#define CLIENT_MAXIMUM_BUFFER_SIZE 262144
|
||||
|
||||
#define SERVER_INITIAL_READ_SIZE 8192
|
||||
#define SERVER_MAXIMUM_BUFFER_SIZE 65536
|
||||
|
||||
#define PROXY_INITIAL_READ_SIZE 65536
|
||||
#define PROXY_MAXIMUM_BUFFER_SIZE 262144 + 1024
|
||||
|
||||
#define GENERIC_INITIAL_READ_SIZE 8192
|
||||
#define GENERIC_MAXIMUM_BUFFER_SIZE 8192
|
||||
|
||||
//
|
||||
// Calculate bitrate in given time frames.
|
||||
// Values are in milliseconds.
|
||||
//
|
||||
|
||||
#define SHORT_BITRATE_TIME_FRAME 5000
|
||||
#define LONG_BITRATE_TIME_FRAME 30000
|
||||
|
||||
//
|
||||
// Bandwidth control. A value of 0 means no
|
||||
// limit. Values are stored internally in
|
||||
// bytes per second.
|
||||
//
|
||||
|
||||
#define CLIENT_BITRATE_LIMIT 0
|
||||
#define SERVER_BITRATE_LIMIT 0
|
||||
|
||||
//
|
||||
// Default values for cache control. We limit
|
||||
// the maximum size of a request to 262144 but
|
||||
// we need to consider the replies, whose size
|
||||
// may be up to 4MB.
|
||||
//
|
||||
|
||||
#define MINIMUM_MESSAGE_SIZE 4
|
||||
#define MAXIMUM_MESSAGE_SIZE 4194304
|
||||
#define MAXIMUM_REQUEST_SIZE 262144
|
||||
|
||||
#define CLIENT_TOTAL_STORAGE_SIZE 8388608
|
||||
#define SERVER_TOTAL_STORAGE_SIZE 8388608
|
||||
|
||||
#define STORE_TIME_LIMIT 3600
|
||||
|
||||
#define STORE_HITS_LOAD_BONUS 10
|
||||
#define STORE_HITS_ADD_BONUS 20
|
||||
#define STORE_HITS_LIMIT 100
|
||||
|
||||
#define STORE_HITS_TOUCH 1
|
||||
#define STORE_HITS_UNTOUCH 2
|
||||
|
||||
//
|
||||
// Default parameters for message splitting.
|
||||
//
|
||||
|
||||
#define SPLIT_MODE 1
|
||||
#define SPLIT_TIMEOUT 50
|
||||
#define SPLIT_TOTAL_SIZE 128
|
||||
#define SPLIT_TOTAL_STORAGE_SIZE 1048576
|
||||
#define SPLIT_DATA_THRESHOLD 65536
|
||||
#define SPLIT_DATA_PACKET_LIMIT 24576
|
||||
|
||||
//
|
||||
// Agent related parameters.
|
||||
//
|
||||
|
||||
#define PACK_METHOD 63
|
||||
#define PACK_QUALITY 9
|
||||
#define HIDE_RENDER 0
|
||||
#define TAINT_REPLIES 1
|
||||
#define TAINT_THRESHOLD 8
|
||||
|
||||
//
|
||||
// In current version only X server support is
|
||||
// implemented. Note that use of shared memory
|
||||
// is negotiated according to options provided
|
||||
// by the user.
|
||||
//
|
||||
|
||||
#define SHMEM_CLIENT 0
|
||||
#define SHMEM_SERVER 1
|
||||
|
||||
//
|
||||
// Default size of shared memory segments used
|
||||
// in MIT-SHM support.
|
||||
//
|
||||
|
||||
#define SHMEM_CLIENT_SIZE 0
|
||||
#define SHMEM_SERVER_SIZE 2097152
|
||||
|
||||
//
|
||||
// What do we do at the end of session? If this
|
||||
// flag is set, we launch a new client letting
|
||||
// the user run a new NX session.
|
||||
//
|
||||
|
||||
#define ENABLE_RESTART_ON_SHUTDOWN 0
|
||||
|
||||
//
|
||||
// Do we produce a core dump on fatal errors?
|
||||
//
|
||||
|
||||
#define ENABLE_CORE_DUMP_ON_ABORT 0
|
||||
|
||||
//
|
||||
// Reopen the log file if it exceeds this size.
|
||||
//
|
||||
|
||||
#define FILE_SIZE_LIMIT 60000000
|
||||
|
||||
//
|
||||
// Check periodically if we need to truncate the
|
||||
// log file. By default check every minute.
|
||||
//
|
||||
|
||||
#define FILE_SIZE_CHECK_TIMEOUT 60000
|
||||
|
||||
//
|
||||
// Protocol version compatibility values
|
||||
//
|
||||
|
||||
const int Control::NX_MIN_PROTO_STEP = 10;
|
||||
const int Control::NX_MAX_PROTO_STEP = 10;
|
||||
const char* const Control::NXPROXY_COMPATIBILITY_VERSION = "3.5.0";
|
||||
|
||||
//
|
||||
// Set defaults for control. They should be what
|
||||
// you get in case of 'local' connection.
|
||||
//
|
||||
|
||||
Control::Control()
|
||||
{
|
||||
ProxyMode = proxy_undefined;
|
||||
ProxyStage = stage_undefined;
|
||||
SessionMode = session_undefined;
|
||||
FlushPolicy = policy_undefined;
|
||||
LinkMode = link_undefined;
|
||||
|
||||
LinkEncrypted = LINK_ENCRYPTED;
|
||||
FlushPriority = FLUSH_PRIORITY;
|
||||
|
||||
TokenSize = TOKEN_SIZE;
|
||||
TokenLimit = TOKEN_LIMIT;
|
||||
|
||||
ChannelMask = CHANNEL_MASK;
|
||||
|
||||
InitTimeout = INIT_TIMEOUT;
|
||||
PingTimeout = PING_TIMEOUT;
|
||||
MotionTimeout = MOTION_TIMEOUT;
|
||||
IdleTimeout = IDLE_TIMEOUT;
|
||||
|
||||
ChannelTimeout = CHANNEL_TIMEOUT;
|
||||
ProxyTimeout = PROXY_TIMEOUT;
|
||||
ShmemTimeout = SHMEM_TIMEOUT;
|
||||
|
||||
CleanupTimeout = CLEANUP_TIMEOUT;
|
||||
KeeperTimeout = KEEPER_TIMEOUT;
|
||||
LatencyTimeout = LATENCY_TIMEOUT;
|
||||
|
||||
FileSizeLimit = FILE_SIZE_LIMIT;
|
||||
FileSizeCheckTimeout = FILE_SIZE_CHECK_TIMEOUT;
|
||||
|
||||
EnableRestartOnShutdown = ENABLE_RESTART_ON_SHUTDOWN;
|
||||
|
||||
KillDaemonOnShutdownLimit = KILL_LIMIT;
|
||||
|
||||
KillDaemonOnShutdown = new int[KillDaemonOnShutdownLimit];
|
||||
|
||||
for (int i = 0; i < KILL_LIMIT; i++)
|
||||
{
|
||||
KillDaemonOnShutdown[i] = -1;
|
||||
}
|
||||
|
||||
KillDaemonOnShutdownNumber = 0;
|
||||
|
||||
EnableCoreDumpOnAbort = ENABLE_CORE_DUMP_ON_ABORT;
|
||||
|
||||
//
|
||||
// Collect statistics by default.
|
||||
//
|
||||
|
||||
EnableStatistics = 1;
|
||||
|
||||
//
|
||||
// Memory restrictions if any.
|
||||
//
|
||||
|
||||
LocalMemoryLevel = -1;
|
||||
|
||||
//
|
||||
// Compression must be negotiated between proxies.
|
||||
//
|
||||
|
||||
LocalDeltaCompression = -1;
|
||||
RemoteDeltaCompression = -1;
|
||||
|
||||
LocalDataCompression = -1;
|
||||
LocalStreamCompression = -1;
|
||||
|
||||
RemoteDataCompression = -1;
|
||||
RemoteStreamCompression = -1;
|
||||
|
||||
LocalDataCompressionLevel = -1;
|
||||
LocalDataCompressionThreshold = -1;
|
||||
LocalStreamCompressionLevel = -1;
|
||||
|
||||
RemoteDataCompressionLevel = -1;
|
||||
RemoteStreamCompressionLevel = -1;
|
||||
|
||||
//
|
||||
// Transport buffers' allocation parameters.
|
||||
//
|
||||
|
||||
TransportXBufferSize = TRANSPORT_X_BUFFER_SIZE;
|
||||
TransportProxyBufferSize = TRANSPORT_PROXY_BUFFER_SIZE;
|
||||
TransportGenericBufferSize = TRANSPORT_GENERIC_BUFFER_SIZE;
|
||||
|
||||
TransportXBufferThreshold = TRANSPORT_X_BUFFER_THRESHOLD;
|
||||
TransportProxyBufferThreshold = TRANSPORT_PROXY_BUFFER_THRESHOLD;
|
||||
TransportGenericBufferThreshold = TRANSPORT_GENERIC_BUFFER_THRESHOLD;
|
||||
|
||||
TransportMaximumBufferSize = TRANSPORT_MAXIMUM_BUFFER_SIZE;
|
||||
|
||||
//
|
||||
// Flush the write buffer if it exceeds
|
||||
// this size.
|
||||
//
|
||||
|
||||
TransportFlushBufferSize = TRANSPORT_FLUSH_BUFFER_SIZE;
|
||||
|
||||
//
|
||||
// Socket options.
|
||||
//
|
||||
|
||||
OptionProxyKeepAlive = OPTION_PROXY_KEEP_ALIVE;
|
||||
OptionProxyLowDelay = OPTION_PROXY_LOW_DELAY;
|
||||
OptionProxyClientNoDelay = OPTION_PROXY_CLIENT_NO_DELAY;
|
||||
OptionProxyServerNoDelay = OPTION_PROXY_SERVER_NO_DELAY;
|
||||
OptionClientNoDelay = OPTION_CLIENT_NO_DELAY;
|
||||
OptionServerNoDelay = OPTION_SERVER_NO_DELAY;
|
||||
|
||||
OptionProxyReceiveBuffer = OPTION_PROXY_RECEIVE_BUFFER;
|
||||
OptionClientReceiveBuffer = OPTION_CLIENT_RECEIVE_BUFFER;
|
||||
OptionServerReceiveBuffer = OPTION_SERVER_RECEIVE_BUFFER;
|
||||
|
||||
OptionProxySendBuffer = OPTION_PROXY_SEND_BUFFER;
|
||||
OptionClientSendBuffer = OPTION_CLIENT_SEND_BUFFER;
|
||||
OptionServerSendBuffer = OPTION_SERVER_SEND_BUFFER;
|
||||
|
||||
OptionProxyRetryAccept = OPTION_PROXY_RETRY_ACCEPT;
|
||||
OptionProxyRetryConnect = OPTION_PROXY_RETRY_CONNECT;
|
||||
OptionServerRetryConnect = OPTION_SERVER_RETRY_CONNECT;
|
||||
|
||||
//
|
||||
// Base NX directories.
|
||||
//
|
||||
|
||||
HomePath = NULL;
|
||||
RootPath = NULL;
|
||||
SystemPath = NULL;
|
||||
TempPath = NULL;
|
||||
ClientPath = NULL;
|
||||
|
||||
//
|
||||
// Set defaults for handling persistent cache.
|
||||
//
|
||||
|
||||
PersistentCachePath = NULL;
|
||||
PersistentCacheName = NULL;
|
||||
|
||||
PersistentCacheThreshold = PERSISTENT_CACHE_THRESHOLD;
|
||||
|
||||
PersistentCacheEnableLoad = PERSISTENT_CACHE_ENABLE_LOAD;
|
||||
PersistentCacheEnableSave = PERSISTENT_CACHE_ENABLE_SAVE;
|
||||
|
||||
PersistentCacheCheckOnShutdown = PERSISTENT_CACHE_CHECK_ON_SHUTDOWN;
|
||||
|
||||
PersistentCacheLoadPacked = PERSISTENT_CACHE_LOAD_PACKED;
|
||||
PersistentCacheLoadRender = PERSISTENT_CACHE_LOAD_RENDER;
|
||||
|
||||
PersistentCacheDiskLimit = PERSISTENT_CACHE_DISK_LIMIT;
|
||||
|
||||
//
|
||||
// Set defaults for image cache.
|
||||
//
|
||||
|
||||
ImageCachePath = NULL;
|
||||
|
||||
ImageCacheEnableLoad = IMAGE_CACHE_ENABLE_LOAD;
|
||||
ImageCacheEnableSave = IMAGE_CACHE_ENABLE_SAVE;
|
||||
|
||||
ImageCacheDiskLimit = IMAGE_CACHE_DISK_LIMIT;
|
||||
|
||||
//
|
||||
// Set defaults for the read buffers.
|
||||
//
|
||||
|
||||
ClientInitialReadSize = CLIENT_INITIAL_READ_SIZE;
|
||||
ClientMaximumBufferSize = CLIENT_MAXIMUM_BUFFER_SIZE;
|
||||
|
||||
ServerInitialReadSize = SERVER_INITIAL_READ_SIZE;
|
||||
ServerMaximumBufferSize = SERVER_MAXIMUM_BUFFER_SIZE;
|
||||
|
||||
ProxyInitialReadSize = PROXY_INITIAL_READ_SIZE;
|
||||
ProxyMaximumBufferSize = PROXY_MAXIMUM_BUFFER_SIZE;
|
||||
|
||||
GenericInitialReadSize = GENERIC_INITIAL_READ_SIZE;
|
||||
GenericMaximumBufferSize = GENERIC_MAXIMUM_BUFFER_SIZE;
|
||||
|
||||
ShortBitrateTimeFrame = SHORT_BITRATE_TIME_FRAME;
|
||||
LongBitrateTimeFrame = LONG_BITRATE_TIME_FRAME;
|
||||
|
||||
//
|
||||
// Bandwidth control.
|
||||
//
|
||||
|
||||
LocalBitrateLimit = -1;
|
||||
|
||||
ClientBitrateLimit = CLIENT_BITRATE_LIMIT;
|
||||
ServerBitrateLimit = SERVER_BITRATE_LIMIT;
|
||||
|
||||
//
|
||||
// Default parameters for message handling.
|
||||
//
|
||||
|
||||
ClientTotalStorageSize = CLIENT_TOTAL_STORAGE_SIZE;
|
||||
ServerTotalStorageSize = SERVER_TOTAL_STORAGE_SIZE;
|
||||
|
||||
LocalTotalStorageSize = -1;
|
||||
RemoteTotalStorageSize = -1;
|
||||
|
||||
StoreTimeLimit = STORE_TIME_LIMIT;
|
||||
|
||||
StoreHitsLoadBonus = STORE_HITS_LOAD_BONUS;
|
||||
StoreHitsAddBonus = STORE_HITS_ADD_BONUS;
|
||||
StoreHitsLimit = STORE_HITS_LIMIT;
|
||||
|
||||
StoreHitsTouch = STORE_HITS_TOUCH;
|
||||
StoreHitsUntouch = STORE_HITS_UNTOUCH;
|
||||
|
||||
MinimumMessageSize = MINIMUM_MESSAGE_SIZE;
|
||||
MaximumMessageSize = MAXIMUM_MESSAGE_SIZE;
|
||||
MaximumRequestSize = MAXIMUM_REQUEST_SIZE;
|
||||
|
||||
SplitMode = SPLIT_MODE;
|
||||
SplitTimeout = SPLIT_TIMEOUT;
|
||||
SplitTotalSize = SPLIT_TOTAL_SIZE;
|
||||
SplitTotalStorageSize = SPLIT_TOTAL_STORAGE_SIZE;
|
||||
SplitDataThreshold = SPLIT_DATA_THRESHOLD;
|
||||
SplitDataPacketLimit = SPLIT_DATA_PACKET_LIMIT;
|
||||
|
||||
PackMethod = PACK_METHOD;
|
||||
PackQuality = PACK_QUALITY;
|
||||
HideRender = HIDE_RENDER;
|
||||
TaintReplies = TAINT_REPLIES;
|
||||
TaintThreshold = TAINT_THRESHOLD;
|
||||
|
||||
ShmemClient = SHMEM_CLIENT;
|
||||
ShmemServer = SHMEM_SERVER;
|
||||
|
||||
ShmemClientSize = SHMEM_CLIENT_SIZE;
|
||||
ShmemServerSize = SHMEM_SERVER_SIZE;
|
||||
|
||||
//
|
||||
// Get local version number from compile time
|
||||
// settings. Version of remote proxy will be
|
||||
// checked at connection time.
|
||||
//
|
||||
|
||||
RemoteVersionMajor = -1;
|
||||
RemoteVersionMinor = -1;
|
||||
RemoteVersionPatch = -1;
|
||||
RemoteVersionMaintenancePatch = -1;
|
||||
|
||||
CompatVersionMajor = -1;
|
||||
CompatVersionMinor = -1;
|
||||
CompatVersionPatch = -1;
|
||||
CompatVersionMaintenancePatch = -1;
|
||||
|
||||
LocalVersionMajor = NXMajorVersion();
|
||||
LocalVersionMinor = NXMinorVersion();
|
||||
LocalVersionPatch = NXPatchVersion();
|
||||
LocalVersionMaintenancePatch = NXMaintenancePatchVersion();
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "Control: Major version is " << LocalVersionMajor
|
||||
<< " minor is " << LocalVersionMinor << " patch is "
|
||||
<< LocalVersionPatch << " Maintenance version is "
|
||||
<< LocalVersionMaintenancePatch << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Initialize local implemented methods later
|
||||
// and negotiate remote methods at connection
|
||||
// time.
|
||||
//
|
||||
|
||||
LocalUnpackMethods = NULL;
|
||||
RemoteUnpackMethods = NULL;
|
||||
|
||||
//
|
||||
// Set to 1 those methods which are implemented.
|
||||
//
|
||||
|
||||
setLocalUnpackMethods();
|
||||
|
||||
//
|
||||
// Set the protocol version at the
|
||||
// time the session is negotiated.
|
||||
//
|
||||
|
||||
protoStep_ = 0;
|
||||
}
|
||||
|
||||
Control::~Control()
|
||||
{
|
||||
if (KillDaemonOnShutdown != NULL)
|
||||
{
|
||||
delete [] KillDaemonOnShutdown;
|
||||
}
|
||||
|
||||
if (HomePath != NULL)
|
||||
{
|
||||
delete [] HomePath;
|
||||
}
|
||||
|
||||
if (RootPath != NULL)
|
||||
{
|
||||
delete [] RootPath;
|
||||
}
|
||||
|
||||
if (SystemPath != NULL)
|
||||
{
|
||||
delete [] SystemPath;
|
||||
}
|
||||
|
||||
if (TempPath != NULL)
|
||||
{
|
||||
delete [] TempPath;
|
||||
}
|
||||
|
||||
if (ClientPath != NULL)
|
||||
{
|
||||
delete [] ClientPath;
|
||||
}
|
||||
|
||||
if (PersistentCachePath != NULL)
|
||||
{
|
||||
delete [] PersistentCachePath;
|
||||
}
|
||||
|
||||
if (PersistentCacheName != NULL)
|
||||
{
|
||||
delete [] PersistentCacheName;
|
||||
}
|
||||
|
||||
if (LocalUnpackMethods != NULL)
|
||||
{
|
||||
delete [] LocalUnpackMethods;
|
||||
}
|
||||
|
||||
if (RemoteUnpackMethods != NULL)
|
||||
{
|
||||
delete [] RemoteUnpackMethods;
|
||||
}
|
||||
|
||||
if (ImageCachePath != NULL)
|
||||
{
|
||||
delete [] ImageCachePath;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Set the protocol step based on the
|
||||
// remote version.
|
||||
//
|
||||
|
||||
void Control::setProtoStep(int step)
|
||||
{
|
||||
if (isValidProtoStep(step))
|
||||
{
|
||||
protoStep_ = step;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Control: PANIC! Invalid protocol step "
|
||||
<< "with value " << step << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
HandleCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
int Control::getProtoStep()
|
||||
{
|
||||
if (isValidProtoStep(protoStep_))
|
||||
{
|
||||
return protoStep_;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "Control: PANIC! Can't identify the "
|
||||
<< "protocol step.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
HandleCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Set here the pack/unpack methods that are
|
||||
// implemented by this NX proxy.
|
||||
//
|
||||
|
||||
void Control::setLocalUnpackMethods()
|
||||
{
|
||||
LocalUnpackMethods = new unsigned char[PACK_METHOD_LIMIT];
|
||||
RemoteUnpackMethods = new unsigned char[PACK_METHOD_LIMIT];
|
||||
|
||||
for (int i = 0; i < PACK_METHOD_LIMIT; i++)
|
||||
{
|
||||
LocalUnpackMethods[i] = 0;
|
||||
RemoteUnpackMethods[i] = 0;
|
||||
}
|
||||
|
||||
LocalUnpackMethods[NO_PACK] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_MASKED_8_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_64_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_256_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_512_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_4K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_32K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_64K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_256K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_2M_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_MASKED_16M_COLORS] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_RAW_8_BITS] = 1;
|
||||
LocalUnpackMethods[PACK_RAW_16_BITS] = 1;
|
||||
LocalUnpackMethods[PACK_RAW_24_BITS] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_COLORMAP_256_COLORS] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_JPEG_8_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_64_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_256_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_512_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_4K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_32K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_64K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_256K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_2M_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_JPEG_16M_COLORS] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_PNG_8_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_64_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_256_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_512_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_4K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_32K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_64K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_256K_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_2M_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_PNG_16M_COLORS] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_RGB_16M_COLORS] = 1;
|
||||
LocalUnpackMethods[PACK_RLE_16M_COLORS] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_ALPHA] = 1;
|
||||
LocalUnpackMethods[PACK_COLORMAP] = 1;
|
||||
|
||||
LocalUnpackMethods[PACK_BITMAP_16M_COLORS] = 1;
|
||||
}
|
||||
764
nxcomp/src/Control.h
Normal file
764
nxcomp/src/Control.h
Normal file
@@ -0,0 +1,764 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef Control_H
|
||||
#define Control_H
|
||||
|
||||
#include "NXpack.h"
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Types.h"
|
||||
#include "Timestamp.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// This is the mode proxy is running.
|
||||
//
|
||||
|
||||
typedef enum
|
||||
{
|
||||
proxy_undefined = -1,
|
||||
proxy_client,
|
||||
proxy_server,
|
||||
proxy_last_tag
|
||||
}
|
||||
T_proxy_mode;
|
||||
|
||||
//
|
||||
// Handle advances in the connection
|
||||
// procedure.
|
||||
//
|
||||
|
||||
typedef enum
|
||||
{
|
||||
stage_undefined,
|
||||
stage_initializing,
|
||||
stage_connecting,
|
||||
stage_connected,
|
||||
stage_waiting_forwarder_version,
|
||||
stage_waiting_forwarder_options,
|
||||
stage_sending_forwarder_options,
|
||||
stage_waiting_proxy_version,
|
||||
stage_waiting_proxy_options,
|
||||
stage_sending_proxy_options,
|
||||
stage_waiting_proxy_caches,
|
||||
stage_sending_proxy_caches,
|
||||
stage_operational,
|
||||
stage_terminating,
|
||||
stage_terminated
|
||||
}
|
||||
T_proxy_stage;
|
||||
|
||||
//
|
||||
// Hint about whether or not the proxy is
|
||||
// connected to a NX agen.
|
||||
//
|
||||
|
||||
typedef enum
|
||||
{
|
||||
session_undefined = -1,
|
||||
session_agent,
|
||||
session_shadow,
|
||||
session_proxy,
|
||||
session_last_tag
|
||||
}
|
||||
T_session_mode;
|
||||
|
||||
//
|
||||
// Set how data will be written to the peer
|
||||
// socket.
|
||||
//
|
||||
|
||||
typedef enum
|
||||
{
|
||||
policy_undefined = -1,
|
||||
policy_immediate,
|
||||
policy_deferred
|
||||
}
|
||||
T_flush_policy;
|
||||
|
||||
//
|
||||
// Link mode, after negotiation, will be set to
|
||||
// any of the values defined in the NXproto.h.
|
||||
//
|
||||
|
||||
#define link_undefined -1;
|
||||
|
||||
//
|
||||
// This class collects functioning parameters,
|
||||
// to be configurable at run-time. They are for
|
||||
// the most part regarding timeouts, transport
|
||||
// and message stores handling.
|
||||
//
|
||||
|
||||
class Control
|
||||
{
|
||||
public:
|
||||
|
||||
//
|
||||
// Does proxy run in client mode or server mode?
|
||||
// As soon as we'll have gone through parsing of
|
||||
// the command line options the current mode will
|
||||
// be propagated to the control class.
|
||||
//
|
||||
|
||||
T_proxy_mode ProxyMode;
|
||||
|
||||
//
|
||||
// Goes from initializing to operational.
|
||||
//
|
||||
|
||||
T_proxy_stage ProxyStage;
|
||||
|
||||
//
|
||||
// Hint about type of session currently running.
|
||||
//
|
||||
|
||||
T_session_mode SessionMode;
|
||||
|
||||
//
|
||||
// Either immediate or deferred flushes.
|
||||
//
|
||||
|
||||
T_flush_policy FlushPolicy;
|
||||
|
||||
//
|
||||
// If set, the channels will try to flush the
|
||||
// encoded data whenever there is a prioritized
|
||||
// message. Depending on the flush policy, this
|
||||
// may determine an immediate flush or an event
|
||||
// being generated telling to the agent that it
|
||||
// should flush the proxy link.
|
||||
//
|
||||
|
||||
int FlushPriority;
|
||||
|
||||
//
|
||||
// Id corresponding to link speed negotiated
|
||||
// between proxies.
|
||||
//
|
||||
|
||||
int LinkMode;
|
||||
|
||||
//
|
||||
// Set if the proxy is connected to a program
|
||||
// providing the encryption of the point to
|
||||
// point communication.
|
||||
//
|
||||
|
||||
int LinkEncrypted;
|
||||
|
||||
//
|
||||
// Maximum number of bytes sent for each token.
|
||||
//
|
||||
|
||||
int TokenSize;
|
||||
|
||||
//
|
||||
// Maximum number of tokens that can be spent
|
||||
// by the client proxy before having to block
|
||||
// waiting for a reply.
|
||||
//
|
||||
|
||||
int TokenLimit;
|
||||
|
||||
//
|
||||
// Bitmask used to determine the distribution
|
||||
// of channel ids between the client and server
|
||||
// proxies.
|
||||
//
|
||||
|
||||
int ChannelMask;
|
||||
|
||||
//
|
||||
// Kill session if control parameters cannot
|
||||
// be negotiated before this timeout.
|
||||
//
|
||||
|
||||
int InitTimeout;
|
||||
|
||||
//
|
||||
// Enter the congestion state if the remote does
|
||||
// not reply to the ping within the given amount
|
||||
// of time.
|
||||
//
|
||||
|
||||
int PingTimeout;
|
||||
|
||||
//
|
||||
// Enqueue motion notify events in server channel.
|
||||
//
|
||||
|
||||
int MotionTimeout;
|
||||
|
||||
//
|
||||
// Force an update of the congestion counter if
|
||||
// the proxy is idle for this time.
|
||||
//
|
||||
|
||||
int IdleTimeout;
|
||||
|
||||
//
|
||||
// Close the connection if can't write before
|
||||
// this timeout.
|
||||
//
|
||||
|
||||
int ChannelTimeout;
|
||||
|
||||
//
|
||||
// Close connection if can't write before
|
||||
// this timeout.
|
||||
//
|
||||
|
||||
int ProxyTimeout;
|
||||
|
||||
//
|
||||
// How many milliseconds to wait for the shared
|
||||
// memory completion event to become available.
|
||||
//
|
||||
|
||||
int ShmemTimeout;
|
||||
|
||||
//
|
||||
// Wait for applications to complete at the time
|
||||
// proxy is shut down.
|
||||
//
|
||||
|
||||
int CleanupTimeout;
|
||||
|
||||
//
|
||||
// Wait this amount of milliseconds before any
|
||||
// iteration of the house-keeping process.
|
||||
//
|
||||
|
||||
int KeeperTimeout;
|
||||
|
||||
//
|
||||
// Adjust timeout calculations.
|
||||
//
|
||||
|
||||
int LatencyTimeout;
|
||||
|
||||
//
|
||||
// Maximum allowed size of log files.
|
||||
//
|
||||
|
||||
int FileSizeLimit;
|
||||
int FileSizeCheckTimeout;
|
||||
|
||||
//
|
||||
// What do we do at the end of session? If
|
||||
// this flag is set we launch a new client
|
||||
// letting the user run a new NX session.
|
||||
//
|
||||
|
||||
int EnableRestartOnShutdown;
|
||||
|
||||
//
|
||||
// The client can request the proxy to kill
|
||||
// a number of processes before exiting.
|
||||
//
|
||||
|
||||
int *KillDaemonOnShutdown;
|
||||
int KillDaemonOnShutdownNumber;
|
||||
int KillDaemonOnShutdownLimit;
|
||||
|
||||
//
|
||||
// Do we generate a core dump and exit in
|
||||
// case of program errors?
|
||||
//
|
||||
|
||||
int EnableCoreDumpOnAbort;
|
||||
|
||||
//
|
||||
// Is statistic output enabled?
|
||||
//
|
||||
|
||||
int EnableStatistics;
|
||||
|
||||
//
|
||||
// Version number of local and remote proxy.
|
||||
//
|
||||
|
||||
/*
|
||||
* LocalVersionMaintenancePatch, RemoteVersionMaintenancePatch
|
||||
* CompatVersionMaintenancePatch
|
||||
*
|
||||
* currently not used, for future compatibility checks
|
||||
*/
|
||||
int LocalVersionMajor;
|
||||
int LocalVersionMinor;
|
||||
int LocalVersionPatch;
|
||||
int LocalVersionMaintenancePatch;
|
||||
|
||||
int RemoteVersionMajor;
|
||||
int RemoteVersionMinor;
|
||||
int RemoteVersionPatch;
|
||||
int RemoteVersionMaintenancePatch;
|
||||
|
||||
int CompatVersionMajor;
|
||||
int CompatVersionMinor;
|
||||
int CompatVersionPatch;
|
||||
int CompatVersionMaintenancePatch;
|
||||
|
||||
//
|
||||
// Compatibility version for the proxy
|
||||
//
|
||||
|
||||
static const char* const NXPROXY_COMPATIBILITY_VERSION;
|
||||
|
||||
//
|
||||
// Which unpack methods are implemented in proxy?
|
||||
//
|
||||
|
||||
unsigned char *LocalUnpackMethods;
|
||||
unsigned char *RemoteUnpackMethods;
|
||||
|
||||
//
|
||||
// Memory restriction imposed by user.
|
||||
//
|
||||
|
||||
int LocalMemoryLevel;
|
||||
|
||||
//
|
||||
// Use or not differential compression
|
||||
// and caching of X protocol messages.
|
||||
//
|
||||
|
||||
int LocalDeltaCompression;
|
||||
int RemoteDeltaCompression;
|
||||
|
||||
//
|
||||
// Compression of images and replies.
|
||||
//
|
||||
|
||||
int LocalDataCompression;
|
||||
int LocalDataCompressionLevel;
|
||||
|
||||
int RemoteDataCompression;
|
||||
int RemoteDataCompressionLevel;
|
||||
|
||||
//
|
||||
// Minimum packet size to be compressed.
|
||||
//
|
||||
|
||||
int LocalDataCompressionThreshold;
|
||||
|
||||
//
|
||||
// Compress or not data flowing through the proxy
|
||||
// link. Level should be one of the ZLIB level as
|
||||
// Z_DEFAULT_COMPRESSION or Z_BEST_COMPRESSION.
|
||||
//
|
||||
|
||||
int LocalStreamCompression;
|
||||
int LocalStreamCompressionLevel;
|
||||
|
||||
int RemoteStreamCompression;
|
||||
int RemoteStreamCompressionLevel;
|
||||
|
||||
//
|
||||
// Size of read operations in read buffer classes.
|
||||
//
|
||||
|
||||
int ClientInitialReadSize;
|
||||
int ClientMaximumBufferSize;
|
||||
|
||||
int ServerInitialReadSize;
|
||||
int ServerMaximumBufferSize;
|
||||
|
||||
int ProxyInitialReadSize;
|
||||
int ProxyMaximumBufferSize;
|
||||
|
||||
int GenericInitialReadSize;
|
||||
int GenericMaximumBufferSize;
|
||||
|
||||
//
|
||||
// Set initial size and resize policy of
|
||||
// transport buffers. If maximum size is
|
||||
// exceeded, print a warning.
|
||||
//
|
||||
|
||||
int TransportXBufferSize;
|
||||
int TransportProxyBufferSize;
|
||||
int TransportGenericBufferSize;
|
||||
|
||||
int TransportXBufferThreshold;
|
||||
int TransportProxyBufferThreshold;
|
||||
int TransportGenericBufferThreshold;
|
||||
|
||||
int TransportMaximumBufferSize;
|
||||
|
||||
//
|
||||
// Flush the data produced for the channel
|
||||
// connection if it exceeds this size.
|
||||
//
|
||||
|
||||
int TransportFlushBufferSize;
|
||||
|
||||
//
|
||||
// Socket options.
|
||||
//
|
||||
|
||||
int OptionProxyKeepAlive;
|
||||
int OptionProxyLowDelay;
|
||||
int OptionProxyClientNoDelay;
|
||||
int OptionProxyServerNoDelay;
|
||||
int OptionClientNoDelay;
|
||||
int OptionServerNoDelay;
|
||||
|
||||
int OptionProxyReceiveBuffer;
|
||||
int OptionClientReceiveBuffer;
|
||||
int OptionServerReceiveBuffer;
|
||||
|
||||
int OptionProxySendBuffer;
|
||||
int OptionClientSendBuffer;
|
||||
int OptionServerSendBuffer;
|
||||
|
||||
int OptionProxyRetryAccept;
|
||||
int OptionProxyRetryConnect;
|
||||
int OptionServerRetryConnect;
|
||||
|
||||
//
|
||||
// Calculate current bitrate on proxy link
|
||||
// using these observation periods. Value
|
||||
// is in milliseconds.
|
||||
//
|
||||
|
||||
int ShortBitrateTimeFrame;
|
||||
int LongBitrateTimeFrame;
|
||||
|
||||
//
|
||||
// Limit the bandwidth usage of the proxy
|
||||
// link.
|
||||
//
|
||||
|
||||
int LocalBitrateLimit;
|
||||
|
||||
int ClientBitrateLimit;
|
||||
int ServerBitrateLimit;
|
||||
|
||||
//
|
||||
// This is the limit imposed by user on
|
||||
// total cache size.
|
||||
//
|
||||
|
||||
int ClientTotalStorageSize;
|
||||
int ServerTotalStorageSize;
|
||||
|
||||
int LocalTotalStorageSize;
|
||||
int RemoteTotalStorageSize;
|
||||
|
||||
//
|
||||
// Discard messages in store older than
|
||||
// this amount of seconds.
|
||||
//
|
||||
|
||||
int StoreTimeLimit;
|
||||
|
||||
//
|
||||
// Any new message in store starts with
|
||||
// this amount of hits.
|
||||
//
|
||||
|
||||
int StoreHitsAddBonus;
|
||||
|
||||
//
|
||||
// Unless it is loaded from persistent
|
||||
// cache.
|
||||
//
|
||||
|
||||
int StoreHitsLoadBonus;
|
||||
|
||||
//
|
||||
// Stop increasing hits at this threshold.
|
||||
//
|
||||
|
||||
int StoreHitsLimit;
|
||||
|
||||
//
|
||||
// Give a special weight to messages put or
|
||||
// taken from cache during startup time.
|
||||
//
|
||||
|
||||
int StoreHitsStartup;
|
||||
|
||||
//
|
||||
// Weight of touch and untoch operations.
|
||||
//
|
||||
|
||||
int StoreHitsTouch;
|
||||
int StoreHitsUntouch;
|
||||
|
||||
//
|
||||
// Directives on size of messages to cache.
|
||||
//
|
||||
|
||||
int MinimumMessageSize;
|
||||
int MaximumMessageSize;
|
||||
|
||||
//
|
||||
// Maximum size of a single X request.
|
||||
//
|
||||
|
||||
int MaximumRequestSize;
|
||||
|
||||
//
|
||||
// Currently selected streaming mode.
|
||||
//
|
||||
|
||||
int SplitMode;
|
||||
|
||||
//
|
||||
// Send new split data any given amount of
|
||||
// milliseconds.
|
||||
//
|
||||
|
||||
int SplitTimeout;
|
||||
|
||||
//
|
||||
// Maximum number of distinct messages and
|
||||
// maximum size in bytes of the temporary
|
||||
// storage.
|
||||
//
|
||||
|
||||
int SplitTotalSize;
|
||||
int SplitTotalStorageSize;
|
||||
|
||||
//
|
||||
// Don't split messages smaller that this
|
||||
// threshold and send no more than the
|
||||
// given amount of bytes in a single data
|
||||
// shot when streaming the split messages.
|
||||
//
|
||||
|
||||
int SplitDataThreshold;
|
||||
int SplitDataPacketLimit;
|
||||
|
||||
//
|
||||
// Agent related parameters. These values apply
|
||||
// to the agent which, at startup, must query
|
||||
// the user's settings.
|
||||
//
|
||||
|
||||
int PackMethod;
|
||||
int PackQuality;
|
||||
int HideRender;
|
||||
int TaintReplies;
|
||||
int TaintThreshold;
|
||||
|
||||
//
|
||||
// Do we allow shared memory image support in
|
||||
// client and or server?
|
||||
//
|
||||
|
||||
int ShmemClient;
|
||||
int ShmemServer;
|
||||
|
||||
//
|
||||
// Default size of shared memory segments used
|
||||
// in MIT-SHM support.
|
||||
//
|
||||
|
||||
int ShmemClientSize;
|
||||
int ShmemServerSize;
|
||||
|
||||
//
|
||||
// The user's home directory.
|
||||
//
|
||||
|
||||
char *HomePath;
|
||||
|
||||
//
|
||||
// The ".nx" directory, usually in
|
||||
// the user's home.
|
||||
//
|
||||
|
||||
char *RootPath;
|
||||
|
||||
//
|
||||
// Usually the /usr/NX" directory.
|
||||
//
|
||||
|
||||
char *SystemPath;
|
||||
|
||||
//
|
||||
// Usually the "/tmp" directory.
|
||||
//
|
||||
|
||||
char *TempPath;
|
||||
|
||||
//
|
||||
// The complete path to the client.
|
||||
//
|
||||
|
||||
char *ClientPath;
|
||||
|
||||
//
|
||||
// String containing path of cache
|
||||
// file selected for load or save.
|
||||
//
|
||||
|
||||
char *PersistentCachePath;
|
||||
|
||||
//
|
||||
// Name of selected cache file.
|
||||
//
|
||||
|
||||
char *PersistentCacheName;
|
||||
|
||||
//
|
||||
// Minimum size of cache in memory
|
||||
// to proceed to its storage on disk.
|
||||
//
|
||||
|
||||
int PersistentCacheThreshold;
|
||||
|
||||
//
|
||||
// Is persistent cache enabled?
|
||||
//
|
||||
|
||||
int PersistentCacheEnableLoad;
|
||||
int PersistentCacheEnableSave;
|
||||
|
||||
//
|
||||
// This is used just for test because
|
||||
// it requires that client and server
|
||||
// reside on the same machine.
|
||||
//
|
||||
|
||||
int PersistentCacheCheckOnShutdown;
|
||||
|
||||
//
|
||||
// Load packed image and render extension
|
||||
// message stores. This currently depends
|
||||
// on the type of session.
|
||||
//
|
||||
|
||||
int PersistentCacheLoadPacked;
|
||||
int PersistentCacheLoadRender;
|
||||
|
||||
//
|
||||
// Maximum disk consumption of message
|
||||
// caches on disk.
|
||||
//
|
||||
|
||||
int PersistentCacheDiskLimit;
|
||||
|
||||
//
|
||||
// String containing the base path
|
||||
// of image cache files.
|
||||
//
|
||||
|
||||
char *ImageCachePath;
|
||||
|
||||
//
|
||||
// Is image cache enabled?
|
||||
//
|
||||
|
||||
int ImageCacheEnableLoad;
|
||||
int ImageCacheEnableSave;
|
||||
|
||||
//
|
||||
// Maximum disk consumption of image
|
||||
// caches on disk.
|
||||
//
|
||||
|
||||
int ImageCacheDiskLimit;
|
||||
|
||||
//
|
||||
// Only constructor, destructor
|
||||
// and a few utility functions.
|
||||
//
|
||||
|
||||
Control();
|
||||
|
||||
~Control();
|
||||
|
||||
//
|
||||
// Should not leverage control to find channel
|
||||
// stores' size limits. As most of values in
|
||||
// control, this info must be moved elsewhere.
|
||||
//
|
||||
|
||||
int getUpperStorageSize() const
|
||||
{
|
||||
return (ClientTotalStorageSize >
|
||||
ServerTotalStorageSize ?
|
||||
ClientTotalStorageSize :
|
||||
ServerTotalStorageSize);
|
||||
}
|
||||
|
||||
int getLowerStorageSize() const
|
||||
{
|
||||
return (ClientTotalStorageSize <
|
||||
ServerTotalStorageSize ?
|
||||
ClientTotalStorageSize :
|
||||
ServerTotalStorageSize);
|
||||
}
|
||||
|
||||
void setProtoStep(int step);
|
||||
|
||||
int getProtoStep();
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Look in Control.cpp.
|
||||
//
|
||||
|
||||
void setLocalUnpackMethods();
|
||||
|
||||
//
|
||||
// Manage the encoding according
|
||||
// to the protocol version.
|
||||
//
|
||||
|
||||
int protoStep_;
|
||||
|
||||
//
|
||||
// Min and max values allowed for protocol step
|
||||
// depending on protocol version compatibility
|
||||
//
|
||||
|
||||
static const int NX_MIN_PROTO_STEP;
|
||||
static const int NX_MAX_PROTO_STEP;
|
||||
|
||||
//
|
||||
// Check the validity of protocol step
|
||||
//
|
||||
|
||||
bool isValidProtoStep(int step)
|
||||
{
|
||||
return ((step >= NX_MIN_PROTO_STEP) && (step <= NX_MAX_PROTO_STEP));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* Control_H */
|
||||
199
nxcomp/src/CopyArea.cpp
Normal file
199
nxcomp/src/CopyArea.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "CopyArea.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
int CopyAreaStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
CopyAreaMessage *copyArea = (CopyAreaMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
copyArea -> src_drawable = GetULONG(buffer + 4, bigEndian);
|
||||
copyArea -> dst_drawable = GetULONG(buffer + 8, bigEndian);
|
||||
copyArea -> gcontext = GetULONG(buffer + 12, bigEndian);
|
||||
|
||||
copyArea -> src_x = GetUINT(buffer + 16, bigEndian);
|
||||
copyArea -> src_y = GetUINT(buffer + 18, bigEndian);
|
||||
copyArea -> dst_x = GetUINT(buffer + 20, bigEndian);
|
||||
copyArea -> dst_y = GetUINT(buffer + 22, bigEndian);
|
||||
|
||||
copyArea -> width = GetUINT(buffer + 24, bigEndian);
|
||||
copyArea -> height = GetUINT(buffer + 26, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CopyAreaStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
CopyAreaMessage *copyArea = (CopyAreaMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
PutULONG(copyArea -> src_drawable, buffer + 4, bigEndian);
|
||||
PutULONG(copyArea -> dst_drawable, buffer + 8, bigEndian);
|
||||
PutULONG(copyArea -> gcontext, buffer + 12, bigEndian);
|
||||
|
||||
PutUINT(copyArea -> src_x, buffer + 16, bigEndian);
|
||||
PutUINT(copyArea -> src_y, buffer + 18, bigEndian);
|
||||
PutUINT(copyArea -> dst_x, buffer + 20, bigEndian);
|
||||
PutUINT(copyArea -> dst_y, buffer + 22, bigEndian);
|
||||
|
||||
PutUINT(copyArea -> width, buffer + 24, bigEndian);
|
||||
PutUINT(copyArea -> height, buffer + 26, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CopyAreaStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
CopyAreaMessage *copyArea = (CopyAreaMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity src_drawable " << copyArea -> src_drawable
|
||||
<< ", dst_drawable " << copyArea -> dst_drawable << ", gcontext " << copyArea -> gcontext
|
||||
<< ", src_x " << copyArea -> src_x << ", src_y " << copyArea -> src_y
|
||||
<< ", dst_x " << copyArea -> dst_x << ", dst_y " << copyArea -> dst_y
|
||||
<< ", width " << copyArea -> width << ", height " << copyArea -> height
|
||||
<< ", size " << copyArea -> size_ << ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void CopyAreaStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 16, 12);
|
||||
}
|
||||
|
||||
void CopyAreaStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
CopyAreaMessage *copyArea = (CopyAreaMessage *) message;
|
||||
CopyAreaMessage *cachedCopyArea = (CopyAreaMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << copyArea -> src_drawable
|
||||
<< " as " << "src_drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(copyArea -> src_drawable, clientCache -> drawableCache);
|
||||
|
||||
cachedCopyArea -> src_drawable = copyArea -> src_drawable;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << copyArea -> dst_drawable
|
||||
<< " as " << "dst_drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(copyArea -> dst_drawable, clientCache -> drawableCache);
|
||||
|
||||
cachedCopyArea -> dst_drawable = copyArea -> dst_drawable;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << copyArea -> gcontext
|
||||
<< " as " << "gcontext" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(copyArea -> gcontext, clientCache -> gcCache);
|
||||
|
||||
cachedCopyArea -> gcontext = copyArea -> gcontext;
|
||||
}
|
||||
|
||||
void CopyAreaStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
CopyAreaMessage *copyArea = (CopyAreaMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> drawableCache);
|
||||
|
||||
copyArea -> src_drawable = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << copyArea -> src_drawable
|
||||
<< " as " << "src_drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> drawableCache);
|
||||
|
||||
copyArea -> dst_drawable = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << copyArea -> dst_drawable
|
||||
<< " as " << "dst_drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> gcCache);
|
||||
|
||||
copyArea -> gcontext = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << copyArea -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
192
nxcomp/src/CopyArea.h
Normal file
192
nxcomp/src/CopyArea.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CopyArea_H
|
||||
#define CopyArea_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define COPYAREA_ENABLE_CACHE 1
|
||||
#define COPYAREA_ENABLE_DATA 0
|
||||
#define COPYAREA_ENABLE_SPLIT 0
|
||||
#define COPYAREA_ENABLE_COMPRESS 0
|
||||
|
||||
#define COPYAREA_DATA_LIMIT 0
|
||||
#define COPYAREA_DATA_OFFSET 28
|
||||
|
||||
#define COPYAREA_CACHE_SLOTS 3000
|
||||
#define COPYAREA_CACHE_THRESHOLD 5
|
||||
#define COPYAREA_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class CopyAreaMessage : public Message
|
||||
{
|
||||
friend class CopyAreaStore;
|
||||
|
||||
public:
|
||||
|
||||
CopyAreaMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~CopyAreaMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned int src_drawable;
|
||||
unsigned int dst_drawable;
|
||||
unsigned int gcontext;
|
||||
unsigned short src_x;
|
||||
unsigned short src_y;
|
||||
unsigned short dst_x;
|
||||
unsigned short dst_y;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
};
|
||||
|
||||
class CopyAreaStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
CopyAreaStore() : MessageStore()
|
||||
{
|
||||
enableCache = COPYAREA_ENABLE_CACHE;
|
||||
enableData = COPYAREA_ENABLE_DATA;
|
||||
enableSplit = COPYAREA_ENABLE_SPLIT;
|
||||
enableCompress = COPYAREA_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = COPYAREA_DATA_LIMIT;
|
||||
dataOffset = COPYAREA_DATA_OFFSET;
|
||||
|
||||
cacheSlots = COPYAREA_CACHE_SLOTS;
|
||||
cacheThreshold = COPYAREA_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = COPYAREA_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~CopyAreaStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "CopyArea";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_CopyArea;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(CopyAreaMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new CopyAreaMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new CopyAreaMessage((const CopyAreaMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (CopyAreaMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* CopyArea_H */
|
||||
194
nxcomp/src/CreateGC.cpp
Normal file
194
nxcomp/src/CreateGC.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "CreateGC.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int CreateGCStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
CreateGCMessage *createGC = (CreateGCMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
createGC -> gcontext = GetULONG(buffer + 4, bigEndian);
|
||||
createGC -> drawable = GetULONG(buffer + 8, bigEndian);
|
||||
createGC -> value_mask = GetULONG(buffer + 12, bigEndian);
|
||||
|
||||
//
|
||||
// Clear the unused bytes carried in the
|
||||
// payload to increase the effectiveness
|
||||
// of the caching algorithm.
|
||||
//
|
||||
|
||||
if ((int) size > dataOffset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Removing unused bytes from the "
|
||||
<< "data payload.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
createGC -> value_mask &= (1 << 23) - 1;
|
||||
|
||||
unsigned int mask = 0x1;
|
||||
unsigned char *source = (unsigned char *) buffer + CREATEGC_DATA_OFFSET;
|
||||
unsigned long value = 0;
|
||||
|
||||
for (unsigned int i = 0; i < 23; i++)
|
||||
{
|
||||
if (createGC -> value_mask & mask)
|
||||
{
|
||||
value = GetULONG(source, bigEndian);
|
||||
|
||||
value &= (0xffffffff >> (32 - CREATEGC_FIELD_WIDTH[i]));
|
||||
|
||||
PutULONG(value, source, bigEndian);
|
||||
|
||||
source += 4;
|
||||
}
|
||||
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at "
|
||||
<< this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CreateGCStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
CreateGCMessage *createGC = (CreateGCMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
PutULONG(createGC -> gcontext, buffer + 4, bigEndian);
|
||||
PutULONG(createGC -> drawable, buffer + 8, bigEndian);
|
||||
PutULONG(createGC -> value_mask, buffer + 12, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at "
|
||||
<< this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CreateGCStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
CreateGCMessage *createGC = (CreateGCMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity gcontext " << createGC -> gcontext << ", drawable "
|
||||
<< createGC -> drawable << ", value_mask " << createGC -> value_mask
|
||||
<< ", size " << createGC -> size_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CreateGCStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
//
|
||||
// This didn't include the drawable
|
||||
// in previous versions.
|
||||
//
|
||||
|
||||
md5_append(md5_state_, buffer + 8, 8);
|
||||
}
|
||||
|
||||
void CreateGCStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
CreateGCMessage *createGC = (CreateGCMessage *) message;
|
||||
CreateGCMessage *cachedCreateGC = (CreateGCMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << createGC -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeNewXidValue(createGC -> gcontext, clientCache -> lastId,
|
||||
clientCache -> lastIdCache, clientCache -> gcCache,
|
||||
clientCache -> freeGCCache);
|
||||
|
||||
cachedCreateGC -> gcontext = createGC -> gcontext;
|
||||
}
|
||||
|
||||
void CreateGCStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
CreateGCMessage *createGC = (CreateGCMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
decodeBuffer.decodeNewXidValue(value, clientCache -> lastId,
|
||||
clientCache -> lastIdCache, clientCache -> gcCache,
|
||||
clientCache -> freeGCCache);
|
||||
|
||||
createGC -> gcontext = value;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded value " << createGC -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
186
nxcomp/src/CreateGC.h
Normal file
186
nxcomp/src/CreateGC.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CreateGC_H
|
||||
#define CreateGC_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define CREATEGC_ENABLE_CACHE 1
|
||||
#define CREATEGC_ENABLE_DATA 0
|
||||
#define CREATEGC_ENABLE_SPLIT 0
|
||||
#define CREATEGC_ENABLE_COMPRESS 0
|
||||
|
||||
#define CREATEGC_DATA_LIMIT 144
|
||||
#define CREATEGC_DATA_OFFSET 16
|
||||
|
||||
#define CREATEGC_CACHE_SLOTS 2000
|
||||
#define CREATEGC_CACHE_THRESHOLD 2
|
||||
#define CREATEGC_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class CreateGCMessage : public Message
|
||||
{
|
||||
friend class CreateGCStore;
|
||||
|
||||
public:
|
||||
|
||||
CreateGCMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~CreateGCMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned int gcontext;
|
||||
unsigned int drawable;
|
||||
unsigned int value_mask;
|
||||
};
|
||||
|
||||
class CreateGCStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
CreateGCStore() : MessageStore()
|
||||
{
|
||||
enableCache = CREATEGC_ENABLE_CACHE;
|
||||
enableData = CREATEGC_ENABLE_DATA;
|
||||
enableSplit = CREATEGC_ENABLE_SPLIT;
|
||||
enableCompress = CREATEGC_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = CREATEGC_DATA_LIMIT;
|
||||
dataOffset = CREATEGC_DATA_OFFSET;
|
||||
|
||||
cacheSlots = CREATEGC_CACHE_SLOTS;
|
||||
cacheThreshold = CREATEGC_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = CREATEGC_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~CreateGCStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "CreateGC";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_CreateGC;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(CreateGCMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new CreateGCMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new CreateGCMessage((const CreateGCMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (CreateGCMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* CreateGC_H */
|
||||
280
nxcomp/src/CreatePixmap.cpp
Normal file
280
nxcomp/src/CreatePixmap.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "CreatePixmap.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
#include "WriteBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
CreatePixmapStore::CreatePixmapStore()
|
||||
|
||||
: MessageStore()
|
||||
{
|
||||
enableCache = CREATEPIXMAP_ENABLE_CACHE;
|
||||
enableData = CREATEPIXMAP_ENABLE_DATA;
|
||||
enableSplit = CREATEPIXMAP_ENABLE_SPLIT;
|
||||
enableCompress = CREATEPIXMAP_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = CREATEPIXMAP_DATA_LIMIT;
|
||||
dataOffset = CREATEPIXMAP_DATA_OFFSET;
|
||||
|
||||
cacheSlots = CREATEPIXMAP_CACHE_SLOTS;
|
||||
cacheThreshold = CREATEPIXMAP_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = CREATEPIXMAP_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
CreatePixmapStore::~CreatePixmapStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int CreatePixmapStore::encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
encodeBuffer.encodeCachedValue(*(buffer + 1), 8,
|
||||
clientCache -> depthCache);
|
||||
|
||||
encodeBuffer.encodeNewXidValue(GetULONG(buffer + 4, bigEndian),
|
||||
clientCache -> lastId, clientCache -> lastIdCache,
|
||||
clientCache -> drawableCache,
|
||||
clientCache -> freeDrawableCache);
|
||||
|
||||
encodeBuffer.encodeXidValue(GetULONG(buffer + 8, bigEndian),
|
||||
clientCache -> windowCache);
|
||||
|
||||
encodeBuffer.encodeCachedValue(GetUINT(buffer + 12, bigEndian), 16,
|
||||
clientCache -> createPixmapXCache, 8);
|
||||
|
||||
encodeBuffer.encodeCachedValue(GetUINT(buffer + 14, bigEndian), 16,
|
||||
clientCache -> createPixmapYCache, 8);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoded message. Size is "
|
||||
<< size << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CreatePixmapStore::decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned char cValue;
|
||||
unsigned int value;
|
||||
|
||||
size = 16;
|
||||
|
||||
buffer = writeBuffer -> addMessage(size);
|
||||
|
||||
decodeBuffer.decodeCachedValue(cValue, 8,
|
||||
clientCache -> depthCache);
|
||||
|
||||
*(buffer + 1) = cValue;
|
||||
|
||||
decodeBuffer.decodeNewXidValue(value,
|
||||
clientCache -> lastId, clientCache -> lastIdCache,
|
||||
clientCache -> drawableCache,
|
||||
clientCache -> freeDrawableCache);
|
||||
|
||||
PutULONG(value, buffer + 4, bigEndian);
|
||||
|
||||
decodeBuffer.decodeXidValue(value,
|
||||
clientCache -> windowCache);
|
||||
|
||||
PutULONG(value, buffer + 8, bigEndian);
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
clientCache -> createPixmapXCache, 8);
|
||||
|
||||
PutUINT(value, buffer + 12, bigEndian);
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
clientCache -> createPixmapYCache, 8);
|
||||
|
||||
PutUINT(value, buffer + 14, bigEndian);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded message. Size is "
|
||||
<< size << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CreatePixmapStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
CreatePixmapMessage *createPixmap = (CreatePixmapMessage *) message;
|
||||
|
||||
createPixmap -> depth = *(buffer + 1);
|
||||
|
||||
createPixmap -> id = GetULONG(buffer + 4, bigEndian);
|
||||
createPixmap -> drawable = GetULONG(buffer + 8, bigEndian);
|
||||
|
||||
createPixmap -> width = GetUINT(buffer + 12, bigEndian);
|
||||
createPixmap -> height = GetUINT(buffer + 14, bigEndian);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Parsed identity. Size is "
|
||||
<< createPixmap -> size_ << " identity is "
|
||||
<< createPixmap -> i_size_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CreatePixmapStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
CreatePixmapMessage *createPixmap = (CreatePixmapMessage *) message;
|
||||
|
||||
*(buffer + 1) = createPixmap -> depth;
|
||||
|
||||
PutULONG(createPixmap -> id, buffer + 4, bigEndian);
|
||||
PutULONG(createPixmap -> drawable, buffer + 8, bigEndian);
|
||||
|
||||
PutUINT(createPixmap -> width, buffer + 12, bigEndian);
|
||||
PutUINT(createPixmap -> height, buffer + 14, bigEndian);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Unparsed identity. Size is "
|
||||
<< createPixmap -> size_ << " identity is "
|
||||
<< createPixmap -> i_size_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CreatePixmapStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
#ifdef WARNING
|
||||
*logofs << name() << ": WARNING! Dump of identity not implemented.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void CreatePixmapStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
md5_append(md5_state_, buffer + 8, 8);
|
||||
}
|
||||
|
||||
void CreatePixmapStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
CreatePixmapMessage *createPixmap = (CreatePixmapMessage *) message;
|
||||
CreatePixmapMessage *cachedCreatePixmap = (CreatePixmapMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
encodeBuffer.encodeNewXidValue(createPixmap -> id,
|
||||
clientCache -> lastId, clientCache -> lastIdCache,
|
||||
clientCache -> drawableCache,
|
||||
clientCache -> freeDrawableCache);
|
||||
|
||||
cachedCreatePixmap -> id = createPixmap -> id;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoded update. Size is "
|
||||
<< createPixmap -> size_ << " identity is "
|
||||
<< createPixmap -> i_size_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CreatePixmapStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
CreatePixmapMessage *createPixmap = (CreatePixmapMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
decodeBuffer.decodeNewXidValue(createPixmap -> id,
|
||||
clientCache -> lastId, clientCache -> lastIdCache,
|
||||
clientCache -> drawableCache,
|
||||
clientCache -> freeDrawableCache);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded update. Size is "
|
||||
<< createPixmap -> size_ << " identity is "
|
||||
<< createPixmap -> i_size_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
162
nxcomp/src/CreatePixmap.h
Normal file
162
nxcomp/src/CreatePixmap.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CreatePixmap_H
|
||||
#define CreatePixmap_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define CREATEPIXMAP_ENABLE_CACHE 1
|
||||
#define CREATEPIXMAP_ENABLE_DATA 0
|
||||
#define CREATEPIXMAP_ENABLE_SPLIT 0
|
||||
#define CREATEPIXMAP_ENABLE_COMPRESS 0
|
||||
|
||||
#define CREATEPIXMAP_DATA_LIMIT 16
|
||||
#define CREATEPIXMAP_DATA_OFFSET 16
|
||||
|
||||
#define CREATEPIXMAP_CACHE_SLOTS 1000
|
||||
#define CREATEPIXMAP_CACHE_THRESHOLD 2
|
||||
#define CREATEPIXMAP_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class CreatePixmapMessage : public Message
|
||||
{
|
||||
friend class CreatePixmapStore;
|
||||
|
||||
public:
|
||||
|
||||
CreatePixmapMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~CreatePixmapMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char depth;
|
||||
|
||||
unsigned int id;
|
||||
unsigned int drawable;
|
||||
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
};
|
||||
|
||||
class CreatePixmapStore : public MessageStore
|
||||
{
|
||||
public:
|
||||
|
||||
CreatePixmapStore();
|
||||
|
||||
virtual ~CreatePixmapStore();
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "CreatePixmap";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_CreatePixmap;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(CreatePixmapMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
protected:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new CreatePixmapMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new CreatePixmapMessage((const CreatePixmapMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (CreatePixmapMessage *) message;
|
||||
}
|
||||
|
||||
virtual int encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* CreatePixmap_H */
|
||||
639
nxcomp/src/DecodeBuffer.cpp
Normal file
639
nxcomp/src/DecodeBuffer.cpp
Normal file
@@ -0,0 +1,639 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Control.h"
|
||||
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
DecodeBuffer::DecodeBuffer(const unsigned char *data, unsigned int length)
|
||||
|
||||
: buffer_(data), end_(buffer_ + length), nextSrc_(buffer_), srcMask_(0x80)
|
||||
{
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
end_ = buffer_ + length - DECODE_BUFFER_POSTFIX_SIZE;
|
||||
}
|
||||
|
||||
int DecodeBuffer::decodeValue(unsigned int &value, unsigned int numBits,
|
||||
unsigned int blockSize, int endOkay)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "DecodeBuffer: Decoding " << numBits
|
||||
<< " bits value with block " << blockSize
|
||||
<< " and " << (nextSrc_ - buffer_)
|
||||
<< " bytes in buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned int result = 0;
|
||||
unsigned int destMask = 0x1;
|
||||
unsigned int bitsRead = 0;
|
||||
|
||||
if (blockSize == 0)
|
||||
blockSize = numBits;
|
||||
|
||||
unsigned char nextSrcChar = *nextSrc_;
|
||||
unsigned int numBlocks = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if (numBlocks == 4)
|
||||
{
|
||||
blockSize = numBits;
|
||||
}
|
||||
|
||||
unsigned int bitsToRead = (blockSize > numBits - bitsRead ?
|
||||
numBits - bitsRead : blockSize);
|
||||
unsigned int count = 0;
|
||||
unsigned char lastBit;
|
||||
|
||||
do
|
||||
{
|
||||
if (nextSrc_ >= end_)
|
||||
{
|
||||
if (!endOkay)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [A] "
|
||||
<< "in decodeValue() nextSrc_ = " << (nextSrc_ - buffer_)
|
||||
<< " end_ = " << (end_ - buffer_) << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Label "context" is just used to identify
|
||||
// the routine which detected the problem in
|
||||
// present source file.
|
||||
//
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [A].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [B] "
|
||||
<< "in decodeValue() nextSrc_ = " << (nextSrc_ - buffer_)
|
||||
<< " end_ = " << (end_ - buffer_) << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [B].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
lastBit = (nextSrcChar & srcMask_);
|
||||
|
||||
if (lastBit)
|
||||
result |= destMask;
|
||||
|
||||
srcMask_ >>= 1;
|
||||
|
||||
if (srcMask_ == 0)
|
||||
{
|
||||
srcMask_ = 0x80;
|
||||
nextSrc_++;
|
||||
nextSrcChar = *nextSrc_;
|
||||
}
|
||||
|
||||
destMask <<= 1;
|
||||
}
|
||||
while (bitsToRead > ++count);
|
||||
|
||||
bitsRead += bitsToRead;
|
||||
|
||||
if (bitsRead < numBits)
|
||||
{
|
||||
if (nextSrc_ >= end_)
|
||||
{
|
||||
if (!endOkay)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [C] "
|
||||
<< "in decodeValue() nextSrc_ = " << (nextSrc_ - buffer_)
|
||||
<< " end_ = " << (end_ - buffer_) << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [C].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [D] "
|
||||
<< "in decodeValue() nextSrc_ = " << (nextSrc_ - buffer_)
|
||||
<< " end_ = " << (end_ - buffer_) << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [D].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
unsigned char moreData = (nextSrcChar & srcMask_);
|
||||
|
||||
srcMask_ >>= 1;
|
||||
|
||||
if (srcMask_ == 0)
|
||||
{
|
||||
srcMask_ = 0x80;
|
||||
nextSrc_++;
|
||||
nextSrcChar = *nextSrc_;
|
||||
}
|
||||
|
||||
if (!moreData)
|
||||
{
|
||||
if (lastBit)
|
||||
{
|
||||
do
|
||||
{
|
||||
result |= destMask;
|
||||
destMask <<= 1;
|
||||
}
|
||||
while (numBits > ++bitsRead);
|
||||
}
|
||||
else
|
||||
bitsRead = numBits;
|
||||
}
|
||||
}
|
||||
|
||||
blockSize >>= 1;
|
||||
|
||||
if (blockSize < 2)
|
||||
blockSize = 2;
|
||||
|
||||
numBlocks++;
|
||||
}
|
||||
while (numBits > bitsRead);
|
||||
|
||||
value = result;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DecodeBuffer::decodeCachedValue(unsigned int &value, unsigned int numBits,
|
||||
IntCache &cache, unsigned int blockSize,
|
||||
int endOkay)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "DecodeBuffer: Decoding " << numBits
|
||||
<< " bits cached value with block " << blockSize
|
||||
<< " and " << (nextSrc_ - buffer_)
|
||||
<< " bytes in buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (nextSrc_ >= end_)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [E] "
|
||||
<< "in decodeValue() nextSrc_ = " << (nextSrc_ - buffer_)
|
||||
<< " end_ = " << (end_ - buffer_) << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [E].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
unsigned int index = 0;
|
||||
unsigned char nextSrcChar = *nextSrc_;
|
||||
|
||||
while (!(nextSrcChar & srcMask_))
|
||||
{
|
||||
index++;
|
||||
srcMask_ >>= 1;
|
||||
if (srcMask_ == 0)
|
||||
{
|
||||
srcMask_ = 0x80;
|
||||
nextSrc_++;
|
||||
if (nextSrc_ >= end_)
|
||||
{
|
||||
if (!endOkay)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [F] "
|
||||
<< "in decodeCachedValue() nextSrc_ = "
|
||||
<< (nextSrc_ - buffer_) << " end_ = "
|
||||
<< (end_ - buffer_) << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [F].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [G] "
|
||||
<< "in decodeValue() nextSrc_ = " << (nextSrc_ - buffer_)
|
||||
<< " end_ = " << (end_ - buffer_) << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [G].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
nextSrcChar = *nextSrc_;
|
||||
}
|
||||
}
|
||||
|
||||
srcMask_ >>= 1;
|
||||
|
||||
if (srcMask_ == 0)
|
||||
{
|
||||
srcMask_ = 0x80;
|
||||
nextSrc_++;
|
||||
}
|
||||
|
||||
if (index == 2)
|
||||
{
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
blockSize = cache.getBlockSize(blockSize);
|
||||
|
||||
if (decodeValue(value, numBits, blockSize, endOkay))
|
||||
{
|
||||
cache.insert(value, IntMask[numBits]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [H] "
|
||||
<< "in decodeCacheValue() with no value found.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [H].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index > 2)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
||||
if (index > cache.getSize())
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [I] "
|
||||
<< "in decodeCachedValue() index = " << index
|
||||
<< " cache size = " << cache.getSize() << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [I].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
value = cache.get(index);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int DecodeBuffer::decodeCachedValue(unsigned char &value, unsigned int numBits,
|
||||
CharCache &cache, unsigned int blockSize,
|
||||
int endOkay)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "DecodeBuffer: Decoding " << numBits
|
||||
<< " bits char cached value with block " << blockSize
|
||||
<< " and " << nextSrc_ - buffer_ << " bytes read out of "
|
||||
<< end_ - buffer_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (nextSrc_ >= end_)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "DecodeBuffer: End of buffer reached in context [J] with "
|
||||
<< nextSrc_ - buffer_ << " bytes read out of "
|
||||
<< end_ - buffer_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int index = 0;
|
||||
unsigned char nextSrcChar = *nextSrc_;
|
||||
|
||||
while (!(nextSrcChar & srcMask_))
|
||||
{
|
||||
index++;
|
||||
srcMask_ >>= 1;
|
||||
|
||||
if (srcMask_ == 0)
|
||||
{
|
||||
srcMask_ = 0x80;
|
||||
nextSrc_++;
|
||||
|
||||
if (nextSrc_ >= end_)
|
||||
{
|
||||
if (!endOkay)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [K] "
|
||||
<< "in decodeCachedValue() nextSrc_ "
|
||||
<< (nextSrc_ - buffer_) << " end_ " << (end_ - buffer_)
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [K].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "DecodeBuffer: End of buffer reached in context [L] with "
|
||||
<< nextSrc_ - buffer_ << " bytes read out of "
|
||||
<< end_ - buffer_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
nextSrcChar = *nextSrc_;
|
||||
}
|
||||
}
|
||||
|
||||
srcMask_ >>= 1;
|
||||
|
||||
if (srcMask_ == 0)
|
||||
{
|
||||
srcMask_ = 0x80;
|
||||
nextSrc_++;
|
||||
}
|
||||
|
||||
if (index == 2)
|
||||
{
|
||||
unsigned int temp;
|
||||
|
||||
if (decodeValue(temp, numBits, blockSize, endOkay))
|
||||
{
|
||||
value = (unsigned char) temp;
|
||||
|
||||
cache.insert(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [M] "
|
||||
<< "in decodeValue() with index = 2.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [M].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index > 2)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
||||
if (index > cache.getSize())
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [N] "
|
||||
<< "in decodeCachedValue() " << "index = " << index
|
||||
<< " cache size = " << cache.getSize() << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [N].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
value = cache.get(index);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Simply returns a pointer to the correct spot in
|
||||
// the internal buffer. If the caller needs this
|
||||
// data to last beyond the lifetime of the internal
|
||||
// buffer, it must copy the data in its own memory.
|
||||
//
|
||||
|
||||
const unsigned char *DecodeBuffer::decodeMemory(unsigned int numBytes)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "DecodeBuffer: Decoding " << numBytes
|
||||
<< " bytes of memory with " << (nextSrc_ - buffer_)
|
||||
<< " bytes in buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
const unsigned char *result;
|
||||
|
||||
//
|
||||
// Force ourselves to a byte boundary.
|
||||
// Is up to application to ensure data
|
||||
// is word aligned when needed.
|
||||
//
|
||||
|
||||
if (srcMask_ != 0x80)
|
||||
{
|
||||
srcMask_ = 0x80;
|
||||
nextSrc_++;
|
||||
}
|
||||
|
||||
result = nextSrc_;
|
||||
|
||||
if (numBytes > DECODE_BUFFER_OVERFLOW_SIZE)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Can't decode a buffer of "
|
||||
<< numBytes << " bytes with limit set to "
|
||||
<< DECODE_BUFFER_OVERFLOW_SIZE << ".\n"
|
||||
<< logofs_flush;
|
||||
|
||||
*logofs << "DecodeBuffer: PANIC! Assuming failure decoding "
|
||||
<< "data in context [O].\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Should never decode buffer of size "
|
||||
<< "greater than " << DECODE_BUFFER_OVERFLOW_SIZE
|
||||
<< " bytes.\n";
|
||||
|
||||
cerr << "Error" << ": Assuming failure decoding data in "
|
||||
<< "context [O].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
else if (end_ - nextSrc_ < (int) numBytes)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "DecodeBuffer: PANIC! Assertion failed. Error [P] "
|
||||
<< "in decodeMemory() " << "with length " << numBytes
|
||||
<< " and " << (end_ - nextSrc_)
|
||||
<< " bytes remaining.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Failure decoding data in context [P].\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
nextSrc_ += numBytes;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DecodeBuffer::decodeActionValue(unsigned char &value, unsigned short &position,
|
||||
ActionCache &cache)
|
||||
{
|
||||
unsigned int t;
|
||||
|
||||
decodeCachedValue(t, 15, *(cache.base_[cache.slot_]));
|
||||
|
||||
cache.last_ += t;
|
||||
cache.last_ &= 0x7fff;
|
||||
|
||||
value = cache.last_ >> 13;
|
||||
|
||||
position = cache.last_ & 0x1fff;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "DecodeBuffer: Decoded value "
|
||||
<< (unsigned) value << " and position "
|
||||
<< position << " with base " << cache.slot_
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "DecodeBuffer: Action block prediction is "
|
||||
<< (*(cache.base_[cache.slot_])).getBlockSize(15)
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cache.slot_ = (cache.last_ & 0xff);
|
||||
}
|
||||
|
||||
void DecodeBuffer::decodeNewXidValue(unsigned int &value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, IntCache &cache,
|
||||
FreeCache &freeCache)
|
||||
{
|
||||
decodeCachedValue(value, 29, lastIdCache);
|
||||
|
||||
lastId += (value + 1);
|
||||
lastId &= 0x1fffffff;
|
||||
|
||||
value = lastId;
|
||||
|
||||
cache.push(value, 0x1fffffff);
|
||||
|
||||
freeCache.push(value, 0x1fffffff);
|
||||
}
|
||||
|
||||
void DecodeBuffer::decodeNewXidValue(unsigned int &value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, XidCache &cache,
|
||||
FreeCache &freeCache)
|
||||
{
|
||||
decodeCachedValue(value, 29, lastIdCache);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "DecodeBuffer: Decoded new Xid difference "
|
||||
<< value << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
lastId += (value + 1);
|
||||
lastId &= 0x1fffffff;
|
||||
|
||||
value = lastId;
|
||||
|
||||
unsigned int t = (value - cache.last_);
|
||||
|
||||
cache.last_ = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "DecodeBuffer: Decoded new Xid " << value
|
||||
<< " with base " << cache.slot_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cache.slot_ = (value & 0xff);
|
||||
|
||||
cache.base_[cache.slot_] -> push(t, 0x1fffffff);
|
||||
|
||||
freeCache.push(value, 0x1fffffff);
|
||||
}
|
||||
|
||||
void DecodeBuffer::decodeXidValue(unsigned int &value, XidCache &cache)
|
||||
{
|
||||
unsigned int t;
|
||||
|
||||
decodeCachedValue(t, 29, *(cache.base_[cache.slot_]));
|
||||
|
||||
cache.last_ += t;
|
||||
cache.last_ &= 0x1fffffff;
|
||||
|
||||
value = cache.last_;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "DecodeBuffer: Decoded Xid " << value
|
||||
<< " with base " << cache.slot_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cache.slot_ = (value & 0xff);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "DecodeBuffer: Xid block prediction is "
|
||||
<< (*(cache.base_[cache.slot_])).getBlockSize(29)
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DecodeBuffer::decodeFreeXidValue(unsigned int &value, FreeCache &cache)
|
||||
{
|
||||
decodeCachedValue(value, 29, cache);
|
||||
}
|
||||
|
||||
138
nxcomp/src/DecodeBuffer.h
Normal file
138
nxcomp/src/DecodeBuffer.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef DecodeBuffer_H
|
||||
#define DecodeBuffer_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "IntCache.h"
|
||||
#include "CharCache.h"
|
||||
#include "XidCache.h"
|
||||
#include "FreeCache.h"
|
||||
#include "OpcodeCache.h"
|
||||
#include "ActionCache.h"
|
||||
|
||||
#define DECODE_BUFFER_OVERFLOW_SIZE 4194304
|
||||
|
||||
#define DECODE_BUFFER_POSTFIX_SIZE 1
|
||||
|
||||
class DecodeBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
DecodeBuffer(const unsigned char *data, unsigned int length);
|
||||
|
||||
~DecodeBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
int decodeValue(unsigned int &value, unsigned int numBits,
|
||||
unsigned int blockSize = 0, int endOkay = 0);
|
||||
|
||||
int decodeCachedValue(unsigned int &value, unsigned int numBits,
|
||||
IntCache &cache, unsigned int blockSize = 0,
|
||||
int endOkay = 0);
|
||||
|
||||
int decodeCachedValue(unsigned char &value, unsigned int numBits,
|
||||
CharCache &cache, unsigned int blockSize = 0,
|
||||
int endOkay = 0);
|
||||
|
||||
void decodeDiffCachedValue(unsigned int &value, unsigned int &previous,
|
||||
unsigned int numBits, IntCache &cache,
|
||||
unsigned int blockSize = 0)
|
||||
{
|
||||
decodeCachedValue(value, numBits, cache, blockSize);
|
||||
|
||||
previous += (value + 1);
|
||||
previous &= (0xffffffff >> (32 - numBits));
|
||||
|
||||
value = previous;
|
||||
}
|
||||
|
||||
void decodeBoolValue(unsigned int &value)
|
||||
{
|
||||
decodeValue(value, 1);
|
||||
}
|
||||
|
||||
int decodeOpcodeValue(unsigned char &value, OpcodeCache &cache, int endOkay = 0)
|
||||
{
|
||||
int result = decodeCachedValue(value, 8, cache.base_[cache.slot_], 8, endOkay);
|
||||
|
||||
if (result == 1)
|
||||
{
|
||||
cache.slot_ = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void decodeActionValue(unsigned char &value, unsigned short &position,
|
||||
ActionCache &cache);
|
||||
|
||||
void decodeNewXidValue(unsigned int &value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, IntCache &cache,
|
||||
FreeCache &freeCache);
|
||||
|
||||
void decodeNewXidValue(unsigned int &value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, XidCache &cache,
|
||||
FreeCache &freeCache);
|
||||
|
||||
void decodeXidValue(unsigned int &value, XidCache &cache);
|
||||
|
||||
void decodeFreeXidValue(unsigned int &value, FreeCache &cache);
|
||||
|
||||
void decodeTextData(unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
decodeMemory(buffer, numBytes);
|
||||
}
|
||||
|
||||
void decodeIntData(unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
decodeMemory(buffer, numBytes);
|
||||
}
|
||||
|
||||
void decodeLongData(unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
decodeMemory(buffer, numBytes);
|
||||
}
|
||||
|
||||
const unsigned char *decodeMemory(unsigned int numBytes);
|
||||
|
||||
void decodeMemory(unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
memcpy(buffer, decodeMemory(numBytes), numBytes);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const unsigned char *buffer_;
|
||||
const unsigned char *end_;
|
||||
const unsigned char *nextSrc_;
|
||||
|
||||
unsigned char srcMask_;
|
||||
};
|
||||
|
||||
#endif /* DecodeBuffer_H */
|
||||
638
nxcomp/src/EncodeBuffer.cpp
Normal file
638
nxcomp/src/EncodeBuffer.cpp
Normal file
@@ -0,0 +1,638 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Misc.h"
|
||||
#include "Control.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
#define ADVANCE_DEST \
|
||||
\
|
||||
if (destShift_ == 0) \
|
||||
{ \
|
||||
destShift_ = 7; nextDest_++; *nextDest_ = 0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
destShift_--; \
|
||||
}
|
||||
|
||||
EncodeBuffer::EncodeBuffer()
|
||||
{
|
||||
size_ = ENCODE_BUFFER_DEFAULT_SIZE;
|
||||
|
||||
buffer_ = new unsigned char[size_ + ENCODE_BUFFER_PREFIX_SIZE +
|
||||
ENCODE_BUFFER_POSTFIX_SIZE] + ENCODE_BUFFER_PREFIX_SIZE;
|
||||
end_ = buffer_ + size_;
|
||||
|
||||
nextDest_ = buffer_;
|
||||
*nextDest_ = 0;
|
||||
destShift_ = 7;
|
||||
|
||||
lastBits_ = 0;
|
||||
|
||||
initialSize_ = ENCODE_BUFFER_DEFAULT_SIZE;
|
||||
thresholdSize_ = ENCODE_BUFFER_DEFAULT_SIZE << 1;
|
||||
maximumSize_ = ENCODE_BUFFER_DEFAULT_SIZE << 4;
|
||||
|
||||
#ifdef VALGRIND
|
||||
|
||||
memset(buffer_, '\0', size_);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
EncodeBuffer::~EncodeBuffer()
|
||||
{
|
||||
delete [] (buffer_ - ENCODE_BUFFER_PREFIX_SIZE);
|
||||
}
|
||||
|
||||
void EncodeBuffer::setSize(unsigned int initialSize, unsigned int thresholdSize,
|
||||
unsigned int maximumSize)
|
||||
{
|
||||
initialSize_ = initialSize;
|
||||
thresholdSize_ = thresholdSize;
|
||||
maximumSize_ = maximumSize;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "EncodeBuffer: Set buffer sizes to "
|
||||
<< initialSize_ << "/" << thresholdSize_
|
||||
<< "/" << maximumSize_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void EncodeBuffer::fullReset()
|
||||
{
|
||||
if (size_ > initialSize_)
|
||||
{
|
||||
delete [] (buffer_ - ENCODE_BUFFER_PREFIX_SIZE);
|
||||
|
||||
size_ = initialSize_;
|
||||
|
||||
buffer_ = new unsigned char[size_ + ENCODE_BUFFER_PREFIX_SIZE +
|
||||
ENCODE_BUFFER_POSTFIX_SIZE];
|
||||
|
||||
#ifdef VALGRIND
|
||||
|
||||
memset(buffer_, '\0', size_ + ENCODE_BUFFER_PREFIX_SIZE + ENCODE_BUFFER_POSTFIX_SIZE);
|
||||
|
||||
#endif
|
||||
|
||||
buffer_ += ENCODE_BUFFER_PREFIX_SIZE;
|
||||
}
|
||||
|
||||
end_ = buffer_ + size_;
|
||||
|
||||
nextDest_ = buffer_;
|
||||
*nextDest_ = 0;
|
||||
destShift_ = 7;
|
||||
|
||||
lastBits_ = 0;
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeValue(unsigned int value, unsigned int numBits,
|
||||
unsigned int blockSize)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoding " << numBits
|
||||
<< " bits value with block " << blockSize
|
||||
<< " and " << (nextDest_ - buffer_)
|
||||
<< " bytes in buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
value &= IntMask[numBits];
|
||||
|
||||
unsigned int srcMask = 0x1;
|
||||
unsigned int bitsWritten = 0;
|
||||
|
||||
if (blockSize == 0)
|
||||
blockSize = numBits;
|
||||
|
||||
if (end_ - nextDest_ < 8)
|
||||
{
|
||||
growBuffer();
|
||||
}
|
||||
|
||||
unsigned int numBlocks = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if (numBlocks == 4)
|
||||
blockSize = numBits;
|
||||
|
||||
unsigned int bitsToWrite = (blockSize > numBits - bitsWritten ?
|
||||
numBits - bitsWritten : blockSize);
|
||||
unsigned int count = 0;
|
||||
unsigned int lastBit;
|
||||
|
||||
do
|
||||
{
|
||||
lastBit = (value & srcMask);
|
||||
if (lastBit)
|
||||
*nextDest_ |= (1 << destShift_);
|
||||
ADVANCE_DEST;
|
||||
srcMask <<= 1;
|
||||
}
|
||||
while (bitsToWrite > ++count);
|
||||
|
||||
bitsWritten += bitsToWrite;
|
||||
|
||||
if (bitsWritten < numBits)
|
||||
{
|
||||
unsigned int tmpMask = srcMask;
|
||||
unsigned int i = bitsWritten;
|
||||
|
||||
if (lastBit)
|
||||
{
|
||||
do
|
||||
{
|
||||
unsigned int nextBit = (value & tmpMask);
|
||||
|
||||
if (!nextBit)
|
||||
break;
|
||||
|
||||
tmpMask <<= 1;
|
||||
}
|
||||
while (numBits > ++i);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
unsigned int nextBit = (value & tmpMask);
|
||||
|
||||
if (nextBit)
|
||||
break;
|
||||
|
||||
tmpMask <<= 1;
|
||||
}
|
||||
while (numBits > ++i);
|
||||
}
|
||||
|
||||
if (i < numBits)
|
||||
*nextDest_ |= (1 << destShift_);
|
||||
else
|
||||
bitsWritten = numBits;
|
||||
|
||||
ADVANCE_DEST;
|
||||
}
|
||||
blockSize >>= 1;
|
||||
|
||||
if (blockSize < 2)
|
||||
blockSize = 2;
|
||||
|
||||
numBlocks++;
|
||||
}
|
||||
while (numBits > bitsWritten);
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeCachedValue(unsigned int value, unsigned int numBits,
|
||||
IntCache &cache, unsigned int blockSize)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoding " << numBits
|
||||
<< " bits cached value with block " << blockSize
|
||||
<< " and " << (nextDest_ - buffer_)
|
||||
<< " bytes in buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
value &= IntMask[numBits];
|
||||
|
||||
if (end_ - nextDest_ < 8)
|
||||
{
|
||||
growBuffer();
|
||||
}
|
||||
|
||||
blockSize = cache.getBlockSize(blockSize);
|
||||
|
||||
unsigned int index;
|
||||
unsigned int sameDiff;
|
||||
|
||||
#ifdef DUMP
|
||||
|
||||
diffBits();
|
||||
|
||||
#endif
|
||||
|
||||
if (cache.lookup(value, index, IntMask[numBits], sameDiff))
|
||||
{
|
||||
if (index > 1)
|
||||
index++;
|
||||
|
||||
while (destShift_ < index)
|
||||
{
|
||||
index -= destShift_;
|
||||
index--;
|
||||
destShift_ = 7;
|
||||
nextDest_++;
|
||||
*nextDest_ = 0;
|
||||
}
|
||||
|
||||
destShift_ -= index;
|
||||
*nextDest_ |= (1 << destShift_);
|
||||
ADVANCE_DEST;
|
||||
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoded cached int using "
|
||||
<< diffBits() << " bits out of " << numBits
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ADVANCE_DEST;
|
||||
ADVANCE_DEST;
|
||||
*nextDest_ |= (1 << destShift_);
|
||||
ADVANCE_DEST;
|
||||
|
||||
//
|
||||
// The attempt is very seldom successful.
|
||||
// Avoid to encode the additional bool.
|
||||
//
|
||||
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoded missed int using "
|
||||
<< diffBits() << " bits out of " << numBits
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeValue(value, numBits, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeCachedValue(unsigned char value, unsigned int numBits,
|
||||
CharCache &cache, unsigned int blockSize)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoding " << numBits
|
||||
<< " bits char cached value with block " << blockSize
|
||||
<< " and " << (nextDest_ - buffer_)
|
||||
<< " bytes in buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
value &= IntMask[numBits];
|
||||
|
||||
if (end_ - nextDest_ < 8)
|
||||
{
|
||||
growBuffer();
|
||||
}
|
||||
|
||||
unsigned int index;
|
||||
|
||||
#ifdef DUMP
|
||||
|
||||
diffBits();
|
||||
|
||||
#endif
|
||||
|
||||
if (cache.lookup(value, index))
|
||||
{
|
||||
if (index > 1)
|
||||
index++;
|
||||
|
||||
while (destShift_ < index)
|
||||
{
|
||||
index -= destShift_;
|
||||
index--;
|
||||
destShift_ = 7;
|
||||
nextDest_++;
|
||||
*nextDest_ = 0;
|
||||
}
|
||||
|
||||
destShift_ -= index;
|
||||
*nextDest_ |= (1 << destShift_);
|
||||
ADVANCE_DEST;
|
||||
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoded cached char using "
|
||||
<< diffBits() << " bits out of " << numBits
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ADVANCE_DEST;
|
||||
ADVANCE_DEST;
|
||||
*nextDest_ |= (1 << destShift_);
|
||||
ADVANCE_DEST;
|
||||
|
||||
encodeValue(value, numBits, blockSize);
|
||||
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoded missed char using "
|
||||
<< diffBits() << " bits out of " << numBits
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeMemory(const unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
#ifdef DUMP
|
||||
*logofs << "EncodeBuffer: Encoding " << numBytes
|
||||
<< " bytes of memory with " << (nextDest_ - buffer_)
|
||||
<< " bytes in buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (numBytes > ENCODE_BUFFER_OVERFLOW_SIZE)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "EncodeBuffer: PANIC! Should never encode buffer "
|
||||
<< "of size greater than " << ENCODE_BUFFER_OVERFLOW_SIZE
|
||||
<< " bytes.\n" << logofs_flush;
|
||||
|
||||
*logofs << "EncodeBuffer: PANIC! Assuming failure encoding data "
|
||||
<< "in context [A].\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Label "context" is just used to identify
|
||||
// the routine which detected the problem in
|
||||
// present source file.
|
||||
//
|
||||
|
||||
cerr << "Error" << ": Should never encode buffer of size "
|
||||
<< "greater than " << ENCODE_BUFFER_OVERFLOW_SIZE
|
||||
<< " bytes.\n";
|
||||
|
||||
cerr << "Error" << ": Assuming failure encoding data "
|
||||
<< "in context [A].\n" ;
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
alignBuffer();
|
||||
|
||||
if (end_ - nextDest_ < (int) numBytes)
|
||||
{
|
||||
growBuffer(numBytes);
|
||||
}
|
||||
|
||||
memcpy(nextDest_, buffer, numBytes);
|
||||
|
||||
nextDest_ += numBytes;
|
||||
|
||||
if (nextDest_ == end_)
|
||||
{
|
||||
growBuffer();
|
||||
}
|
||||
else if (nextDest_ > end_)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "EncodeBuffer: PANIC! Assertion failed. Error [B] "
|
||||
<< "in encodeMemory() nextDest_ " << (nextDest_ - buffer)
|
||||
<< " end_ " << (end_ - buffer) << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Label "context" is just used to identify
|
||||
// the routine which detected the problem in
|
||||
// present source file.
|
||||
//
|
||||
|
||||
cerr << "Error" << ": Failure encoding raw data "
|
||||
<< "in context [B].\n" ;
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
*nextDest_ = 0;
|
||||
}
|
||||
|
||||
unsigned int EncodeBuffer::getLength() const
|
||||
{
|
||||
unsigned int length = nextDest_ - buffer_;
|
||||
|
||||
if (destShift_ != 7)
|
||||
{
|
||||
length++;
|
||||
}
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
if (length > 0)
|
||||
{
|
||||
return length + ENCODE_BUFFER_POSTFIX_SIZE;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned int EncodeBuffer::diffBits()
|
||||
{
|
||||
unsigned int bits = ((nextDest_ - buffer_) << 3);
|
||||
|
||||
bits += (7 - destShift_);
|
||||
|
||||
unsigned int diff = bits - lastBits_;
|
||||
|
||||
lastBits_ = bits;
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
void EncodeBuffer::growBuffer(unsigned int numBytes)
|
||||
{
|
||||
if (numBytes == 0)
|
||||
{
|
||||
numBytes = initialSize_;
|
||||
}
|
||||
|
||||
unsigned int bytesInBuffer = nextDest_ - buffer_;
|
||||
|
||||
unsigned int newSize = thresholdSize_;
|
||||
|
||||
while (newSize < bytesInBuffer + numBytes)
|
||||
{
|
||||
newSize <<= 1;
|
||||
|
||||
if (newSize > maximumSize_)
|
||||
{
|
||||
newSize = bytesInBuffer + numBytes + initialSize_;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *newBuffer;
|
||||
|
||||
newBuffer = new unsigned char[newSize + ENCODE_BUFFER_PREFIX_SIZE +
|
||||
ENCODE_BUFFER_POSTFIX_SIZE] + ENCODE_BUFFER_PREFIX_SIZE;
|
||||
|
||||
if (newBuffer == NULL)
|
||||
{
|
||||
#ifdef PANIC
|
||||
*logofs << "EncodeBuffer: PANIC! Error in context [C] "
|
||||
<< "growing buffer to accommodate " << numBytes
|
||||
<< " bytes .\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cerr << "Error" << ": Error in context [C] "
|
||||
<< "growing encode buffer to accommodate "
|
||||
<< numBytes << " bytes.\n";
|
||||
|
||||
HandleAbort();
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
if (newSize >= maximumSize_)
|
||||
{
|
||||
*logofs << "EncodeBuffer: WARNING! Buffer grown to reach "
|
||||
<< "size of " << newSize << " bytes.\n"
|
||||
<< logofs_flush;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Prefix should not contain any valid data.
|
||||
// It is proxy that will fill it with control
|
||||
// messages and data length at the time a new
|
||||
// frame is written to socket.
|
||||
//
|
||||
|
||||
memcpy(newBuffer, buffer_, bytesInBuffer + 1);
|
||||
|
||||
newBuffer[bytesInBuffer + 1] = 0;
|
||||
|
||||
delete [] (buffer_ - ENCODE_BUFFER_PREFIX_SIZE);
|
||||
|
||||
buffer_ = newBuffer;
|
||||
size_ = newSize;
|
||||
end_ = buffer_ + size_;
|
||||
|
||||
nextDest_ = buffer_ + bytesInBuffer;
|
||||
}
|
||||
|
||||
void EncodeBuffer::alignBuffer()
|
||||
{
|
||||
if (destShift_ != 7)
|
||||
{
|
||||
destShift_ = 7;
|
||||
nextDest_++;
|
||||
|
||||
if (nextDest_ >= end_)
|
||||
{
|
||||
growBuffer();
|
||||
}
|
||||
|
||||
*nextDest_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeActionValue(unsigned char value, unsigned short position,
|
||||
ActionCache &cache)
|
||||
{
|
||||
unsigned int v = (value << 13) | position;
|
||||
|
||||
unsigned int t = (v - cache.last_);
|
||||
|
||||
encodeCachedValue(t, 15, *(cache.base_[cache.slot_]));
|
||||
|
||||
cache.last_ = v;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "EncodeBuffer: Encoded value "
|
||||
<< (unsigned) value << " and position "
|
||||
<< position << " with base " << cache.slot_
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
cache.slot_ = (cache.last_ & 0xff);
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeNewXidValue(unsigned int value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, IntCache &cache,
|
||||
FreeCache &freeCache)
|
||||
{
|
||||
encodeCachedValue((value - 1) - lastId, 29, lastIdCache);
|
||||
|
||||
lastId = value;
|
||||
|
||||
cache.push(value, 0x1fffffff);
|
||||
|
||||
freeCache.push(value, 0x1fffffff);
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeNewXidValue(unsigned int value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, XidCache &cache,
|
||||
FreeCache &freeCache)
|
||||
{
|
||||
encodeCachedValue((value - 1) - lastId, 29, lastIdCache);
|
||||
|
||||
lastId = value;
|
||||
|
||||
unsigned int t = (value - cache.last_);
|
||||
|
||||
cache.last_ = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "EncodeBuffer: Encoded new Xid " << value
|
||||
<< " with base " << cache.slot_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cache.slot_ = (value & 0xff);
|
||||
|
||||
cache.base_[cache.slot_] -> push(t, 0x1fffffff);
|
||||
|
||||
freeCache.push(value, IntMask[29]);
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeXidValue(unsigned int value, XidCache &cache)
|
||||
{
|
||||
unsigned int t = (value - cache.last_);
|
||||
|
||||
encodeCachedValue(t, 29, *(cache.base_[cache.slot_]));
|
||||
|
||||
cache.last_ = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "EncodeBuffer: Encoded Xid " << value
|
||||
<< " with base " << cache.slot_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
cache.slot_ = (value & 0xff);
|
||||
}
|
||||
|
||||
void EncodeBuffer::encodeFreeXidValue(unsigned int value, FreeCache &cache)
|
||||
{
|
||||
encodeCachedValue(value, 29, cache);
|
||||
}
|
||||
183
nxcomp/src/EncodeBuffer.h
Normal file
183
nxcomp/src/EncodeBuffer.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef EncodeBuffer_H
|
||||
#define EncodeBuffer_H
|
||||
|
||||
#include "IntCache.h"
|
||||
#include "CharCache.h"
|
||||
#include "XidCache.h"
|
||||
#include "FreeCache.h"
|
||||
#include "OpcodeCache.h"
|
||||
#include "ActionCache.h"
|
||||
|
||||
#define ENCODE_BUFFER_DEFAULT_SIZE 16384
|
||||
|
||||
//
|
||||
// This should match the maximum size of
|
||||
// a single message added to write buffer
|
||||
// (see WriteBuffer.h).
|
||||
//
|
||||
|
||||
#define ENCODE_BUFFER_OVERFLOW_SIZE 4194304
|
||||
|
||||
//
|
||||
// Adjust for the control messages and the
|
||||
// frame length added by the proxy.
|
||||
//
|
||||
|
||||
#define ENCODE_BUFFER_PREFIX_SIZE 64
|
||||
|
||||
//
|
||||
// The encode routines may write one byte
|
||||
// past the nominal end of the encode buffer.
|
||||
// This additional byte is included in the
|
||||
// payload. This is actually a harmless bug.
|
||||
//
|
||||
|
||||
#define ENCODE_BUFFER_POSTFIX_SIZE 1
|
||||
|
||||
class EncodeBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
EncodeBuffer();
|
||||
|
||||
~EncodeBuffer();
|
||||
|
||||
void setSize(unsigned int initialSize, unsigned int thresholdSize,
|
||||
unsigned int maximumSize);
|
||||
|
||||
void encodeValue(unsigned int value, unsigned int numBits,
|
||||
unsigned int blockSize = 0);
|
||||
|
||||
void encodeCachedValue(unsigned int value, unsigned int numBits,
|
||||
IntCache &cache, unsigned int blockSize = 0);
|
||||
|
||||
void encodeCachedValue(unsigned char value, unsigned int numBits,
|
||||
CharCache &cache, unsigned int blockSize = 0);
|
||||
|
||||
void encodeDiffCachedValue(const unsigned int value, unsigned int &previous,
|
||||
unsigned int numBits, IntCache &cache,
|
||||
unsigned int blockSize = 0)
|
||||
{
|
||||
encodeCachedValue((value - 1) - previous, numBits, cache, blockSize);
|
||||
|
||||
previous = value;
|
||||
}
|
||||
|
||||
void encodeBoolValue(unsigned int value)
|
||||
{
|
||||
encodeValue(value, 1);
|
||||
}
|
||||
|
||||
void encodeOpcodeValue(unsigned char value, OpcodeCache &cache)
|
||||
{
|
||||
encodeCachedValue(value, 8, cache.base_[cache.slot_], 8);
|
||||
|
||||
cache.slot_ = value;
|
||||
}
|
||||
|
||||
void encodeActionValue(unsigned char value, ActionCache &cache)
|
||||
{
|
||||
unsigned short position = 0;
|
||||
|
||||
encodeActionValue(value, position, cache);
|
||||
}
|
||||
|
||||
void encodeActionValue(unsigned char value, unsigned short position,
|
||||
ActionCache &cache);
|
||||
|
||||
void encodeNewXidValue(unsigned int value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, IntCache &cache,
|
||||
FreeCache &freeCache);
|
||||
|
||||
void encodeNewXidValue(unsigned int value, unsigned int &lastId,
|
||||
IntCache &lastIdCache, XidCache &cache,
|
||||
FreeCache &freeCache);
|
||||
|
||||
void encodeXidValue(unsigned int value, XidCache &cache);
|
||||
|
||||
void encodeFreeXidValue(unsigned int value, FreeCache &cache);
|
||||
|
||||
void encodeTextData(const unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
encodeMemory(buffer, numBytes);
|
||||
}
|
||||
|
||||
void encodeIntData(const unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
encodeMemory(buffer, numBytes);
|
||||
}
|
||||
|
||||
void encodeLongData(const unsigned char *buffer, unsigned int numBytes)
|
||||
{
|
||||
encodeMemory(buffer, numBytes);
|
||||
}
|
||||
|
||||
void encodeMemory(const unsigned char *buffer, unsigned int numBytes);
|
||||
|
||||
unsigned char *getData()
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
unsigned int getLength() const;
|
||||
|
||||
unsigned int getBits() const
|
||||
{
|
||||
return ((nextDest_ - buffer_) << 3) + (7 - destShift_);
|
||||
}
|
||||
|
||||
unsigned int diffBits();
|
||||
|
||||
void fullReset();
|
||||
|
||||
private:
|
||||
|
||||
void growBuffer(unsigned int numBytes = 0);
|
||||
|
||||
void alignBuffer();
|
||||
|
||||
unsigned int size_;
|
||||
unsigned char *buffer_;
|
||||
|
||||
//
|
||||
// This points to the first byte
|
||||
// just beyond end of the buffer.
|
||||
//
|
||||
|
||||
const unsigned char *end_;
|
||||
|
||||
unsigned char *nextDest_;
|
||||
unsigned int destShift_;
|
||||
unsigned int lastBits_;
|
||||
|
||||
unsigned int initialSize_;
|
||||
unsigned int thresholdSize_;
|
||||
unsigned int maximumSize_;
|
||||
};
|
||||
|
||||
#endif /* EncodeBuffer_H */
|
||||
239
nxcomp/src/FillPoly.cpp
Normal file
239
nxcomp/src/FillPoly.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "FillPoly.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int FillPolyStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
FillPolyMessage *fillPoly = (FillPolyMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
fillPoly -> drawable = GetULONG(buffer + 4, bigEndian);
|
||||
fillPoly -> gcontext = GetULONG(buffer + 8, bigEndian);
|
||||
|
||||
fillPoly -> shape = *(buffer + 12);
|
||||
fillPoly -> mode = *(buffer + 13);
|
||||
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
if (size >= (unsigned int) dataOffset)
|
||||
{
|
||||
fillPoly -> x_origin = GetUINT(buffer + 16, bigEndian);
|
||||
fillPoly -> y_origin = GetUINT(buffer + 18, bigEndian);
|
||||
}
|
||||
else
|
||||
{
|
||||
fillPoly -> x_origin = 0;
|
||||
fillPoly -> y_origin = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FillPolyStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
FillPolyMessage *fillPoly = (FillPolyMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
PutULONG(fillPoly -> drawable, buffer + 4, bigEndian);
|
||||
PutULONG(fillPoly -> gcontext, buffer + 8, bigEndian);
|
||||
|
||||
*(buffer + 12) = fillPoly -> shape;
|
||||
*(buffer + 13) = fillPoly -> mode;
|
||||
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
if (size >= (unsigned int) dataOffset)
|
||||
{
|
||||
PutUINT(fillPoly -> x_origin, buffer + 16, bigEndian);
|
||||
PutUINT(fillPoly -> y_origin, buffer + 18, bigEndian);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FillPolyStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
FillPolyMessage *fillPoly = (FillPolyMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity drawable " << fillPoly -> drawable
|
||||
<< ", gcontext " << fillPoly -> gcontext << ", shape "
|
||||
<< fillPoly -> shape << ", mode " << fillPoly -> mode
|
||||
<< fillPoly -> size_ << ", x_origin " << fillPoly -> x_origin
|
||||
<< ", y_origin " << fillPoly -> y_origin << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FillPolyStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
//
|
||||
// Fields shape, mode.
|
||||
//
|
||||
|
||||
md5_append(md5_state_, buffer + 12, 2);
|
||||
}
|
||||
|
||||
void FillPolyStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
FillPolyMessage *fillPoly = (FillPolyMessage *) message;
|
||||
FillPolyMessage *cachedFillPoly = (FillPolyMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << fillPoly -> drawable
|
||||
<< " as drawable field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(fillPoly -> drawable, clientCache -> drawableCache);
|
||||
|
||||
cachedFillPoly -> drawable = fillPoly -> drawable;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << fillPoly -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(fillPoly -> gcontext, clientCache -> gcCache);
|
||||
|
||||
cachedFillPoly -> gcontext = fillPoly -> gcontext;
|
||||
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
if (fillPoly -> size_ >= dataOffset)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << fillPoly -> x_origin
|
||||
<< " as x_origin field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue(fillPoly -> x_origin, 16,
|
||||
*clientCache -> fillPolyXAbsCache[0], 8);
|
||||
|
||||
cachedFillPoly -> x_origin = fillPoly -> x_origin;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << fillPoly -> y_origin
|
||||
<< " as y_origin field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue(fillPoly -> y_origin, 16,
|
||||
*clientCache -> fillPolyYAbsCache[0], 8);
|
||||
|
||||
cachedFillPoly -> y_origin = fillPoly -> y_origin;
|
||||
}
|
||||
}
|
||||
|
||||
void FillPolyStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
FillPolyMessage *fillPoly = (FillPolyMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
decodeBuffer.decodeXidValue(fillPoly -> drawable, clientCache -> drawableCache);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded value " << fillPoly -> drawable
|
||||
<< " as drawable field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeXidValue(fillPoly -> gcontext, clientCache -> gcCache);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded value " << fillPoly -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
if (fillPoly -> size_ >= dataOffset)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
*clientCache -> fillPolyXAbsCache[0], 8);
|
||||
|
||||
fillPoly -> x_origin = value;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded value " << fillPoly -> x_origin
|
||||
<< " as x_origin field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
*clientCache -> fillPolyYAbsCache[0], 8);
|
||||
|
||||
fillPoly -> y_origin = value;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded value " << fillPoly -> y_origin
|
||||
<< " as y_origin field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
200
nxcomp/src/FillPoly.h
Normal file
200
nxcomp/src/FillPoly.h
Normal file
@@ -0,0 +1,200 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FillPoly_H
|
||||
#define FillPoly_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define FILLPOLY_ENABLE_CACHE 1
|
||||
#define FILLPOLY_ENABLE_DATA 0
|
||||
#define FILLPOLY_ENABLE_SPLIT 0
|
||||
#define FILLPOLY_ENABLE_COMPRESS 0
|
||||
|
||||
#define FILLPOLY_DATA_LIMIT 512
|
||||
|
||||
#define FILLPOLY_CACHE_SLOTS 2000
|
||||
#define FILLPOLY_CACHE_THRESHOLD 3
|
||||
#define FILLPOLY_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
#define FILLPOLY_DATA_OFFSET_IF_PROTO_STEP_8 20
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class FillPolyMessage : public Message
|
||||
{
|
||||
friend class FillPolyStore;
|
||||
|
||||
public:
|
||||
|
||||
FillPolyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~FillPolyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char shape;
|
||||
unsigned char mode;
|
||||
unsigned int drawable;
|
||||
unsigned int gcontext;
|
||||
|
||||
unsigned short x_origin;
|
||||
unsigned short y_origin;
|
||||
};
|
||||
|
||||
class FillPolyStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
FillPolyStore() : MessageStore()
|
||||
{
|
||||
enableCache = FILLPOLY_ENABLE_CACHE;
|
||||
enableData = FILLPOLY_ENABLE_DATA;
|
||||
enableSplit = FILLPOLY_ENABLE_SPLIT;
|
||||
enableCompress = FILLPOLY_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = FILLPOLY_DATA_LIMIT;
|
||||
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
dataOffset = FILLPOLY_DATA_OFFSET_IF_PROTO_STEP_8;
|
||||
|
||||
cacheSlots = FILLPOLY_CACHE_SLOTS;
|
||||
cacheThreshold = FILLPOLY_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = FILLPOLY_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~FillPolyStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "FillPoly";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_FillPoly;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(FillPolyMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new FillPolyMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new FillPolyMessage((const FillPolyMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (FillPolyMessage *) message;
|
||||
}
|
||||
|
||||
virtual int identitySize(const unsigned char *buffer, unsigned int size)
|
||||
{
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
return (size >= FILLPOLY_DATA_OFFSET_IF_PROTO_STEP_8 ?
|
||||
FILLPOLY_DATA_OFFSET_IF_PROTO_STEP_8 : size);
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* FillPoly_H */
|
||||
110
nxcomp/src/Fork.cpp
Normal file
110
nxcomp/src/Fork.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Fork.h"
|
||||
#include "Misc.h"
|
||||
#include "Timestamp.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Only on Cygwin, retry n times waiting a
|
||||
// given amount of milliseconds after each
|
||||
// attempt.
|
||||
//
|
||||
|
||||
#define RETRY_LIMIT 30
|
||||
#define RETRY_TIMEOUT 1000
|
||||
|
||||
int Fork()
|
||||
{
|
||||
#if defined(__CYGWIN__) || defined(__CYGWIN32__)
|
||||
|
||||
int limit = RETRY_LIMIT;
|
||||
int timeout = RETRY_TIMEOUT;
|
||||
|
||||
#else
|
||||
|
||||
int limit = 1;
|
||||
int timeout = 0;
|
||||
|
||||
#endif
|
||||
|
||||
int pid = 0;
|
||||
|
||||
for (int i = 0; i < limit; i++)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "Fork: Trying at " << strMsTimestamp()
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// It could optionally try again only if the
|
||||
// error code is 11, 'Resource temporarily
|
||||
// unavailable'.
|
||||
//
|
||||
|
||||
if ((pid = fork()) >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (i < limit - 1)
|
||||
{
|
||||
#ifdef WARNING
|
||||
*logofs << "Fork: WARNING! Function fork failed. "
|
||||
<< "Error is " << EGET() << " '" << ESTR()
|
||||
<< "'. Retrying...\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
usleep(timeout * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
if (pid <= 0)
|
||||
{
|
||||
*logofs << "Fork: Returning at " << strMsTimestamp()
|
||||
<< ".\n" << logofs_flush;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return pid;
|
||||
}
|
||||
31
nxcomp/src/Fork.h
Normal file
31
nxcomp/src/Fork.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
//
|
||||
// Try again if the fork() fails, as it can happen
|
||||
// often on Cygwin.
|
||||
//
|
||||
|
||||
extern int Fork();
|
||||
42
nxcomp/src/FreeCache.h
Normal file
42
nxcomp/src/FreeCache.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FreeCache_H
|
||||
#define FreeCache_H
|
||||
|
||||
#include "IntCache.h"
|
||||
|
||||
class FreeCache : public IntCache
|
||||
{
|
||||
public:
|
||||
|
||||
FreeCache(unsigned int size)
|
||||
|
||||
: IntCache(size)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FreeCache_H */
|
||||
495
nxcomp/src/GenericChannel.cpp
Normal file
495
nxcomp/src/GenericChannel.cpp
Normal file
@@ -0,0 +1,495 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "GenericChannel.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
#include "StaticCompressor.h"
|
||||
|
||||
#include "Statistics.h"
|
||||
#include "Proxy.h"
|
||||
|
||||
extern Proxy *proxy;
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Log the important tracepoints related
|
||||
// to writing packets to the peer proxy.
|
||||
//
|
||||
|
||||
#undef FLUSH
|
||||
|
||||
//
|
||||
// Define this to log when a channel
|
||||
// is created or destroyed.
|
||||
//
|
||||
|
||||
#undef REFERENCES
|
||||
|
||||
//
|
||||
// Here are the static members.
|
||||
//
|
||||
|
||||
#ifdef REFERENCES
|
||||
|
||||
int GenericChannel::references_ = 0;
|
||||
|
||||
#endif
|
||||
|
||||
GenericChannel::GenericChannel(Transport *transport, StaticCompressor *compressor)
|
||||
|
||||
: Channel(transport, compressor), readBuffer_(transport_, this)
|
||||
{
|
||||
#ifdef REFERENCES
|
||||
*logofs << "GenericChannel: Created new object at "
|
||||
<< this << " for FD#" << fd_ << " out of "
|
||||
<< ++references_ << " allocated channels.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
GenericChannel::~GenericChannel()
|
||||
{
|
||||
#ifdef REFERENCES
|
||||
*logofs << "GenericChannel: Deleted object at "
|
||||
<< this << " for FD#" << fd_ << " out of "
|
||||
<< --references_ << " allocated channels.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Beginning of handleRead().
|
||||
//
|
||||
|
||||
int GenericChannel::handleRead(EncodeBuffer &encodeBuffer, const unsigned char *message,
|
||||
unsigned int length)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "handleRead: Called for FD#" << fd_
|
||||
<< " with " << encodeBuffer.getLength()
|
||||
<< " bytes already encoded.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Pointer to located message and
|
||||
// its size in bytes.
|
||||
//
|
||||
|
||||
const unsigned char *inputMessage;
|
||||
unsigned int inputLength;
|
||||
|
||||
//
|
||||
// Tag message as generic data in compression
|
||||
// routine. Opcode is not actually transferred
|
||||
// over the network.
|
||||
//
|
||||
|
||||
unsigned char inputOpcode = X_NXInternalGenericData;
|
||||
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "handleRead: Trying to read from FD#"
|
||||
<< fd_ << " at " << strMsTimestamp() << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
int result = readBuffer_.readMessage();
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << "handleRead: Read result on FD#" << fd_
|
||||
<< " is " << result << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
//
|
||||
// Let the proxy close the channel.
|
||||
//
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if (result == 0)
|
||||
{
|
||||
#if defined(TEST) || defined(INFO)
|
||||
|
||||
*logofs << "handleRead: PANIC! No data read from FD#"
|
||||
<< fd_ << " while encoding messages.\n"
|
||||
<< logofs_flush;
|
||||
|
||||
HandleCleanup();
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(TEST) || defined(INFO) || defined(FLUSH)
|
||||
*logofs << "handleRead: Encoding messages for FD#" << fd_
|
||||
<< " with " << readBuffer_.getLength() << " bytes "
|
||||
<< "in the buffer.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Divide the available data in multiple
|
||||
// messages and encode them one by one.
|
||||
//
|
||||
|
||||
if (proxy -> handleAsyncSwitch(fd_) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((inputMessage = readBuffer_.getMessage(inputLength)) != NULL)
|
||||
{
|
||||
encodeBuffer.encodeValue(inputLength, 32, 14);
|
||||
|
||||
if (isCompressed() == 1)
|
||||
{
|
||||
unsigned int compressedDataSize = 0;
|
||||
unsigned char *compressedData = NULL;
|
||||
|
||||
if (handleCompress(encodeBuffer, inputOpcode, 0,
|
||||
inputMessage, inputLength, compressedData,
|
||||
compressedDataSize) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
encodeBuffer.encodeMemory(inputMessage, inputLength);
|
||||
}
|
||||
|
||||
int bits = encodeBuffer.diffBits();
|
||||
|
||||
#if defined(TEST) || defined(OPCODES)
|
||||
*logofs << "handleRead: Handled generic data for FD#" << fd_
|
||||
<< ". " << inputLength << " bytes in, " << bits << " bits ("
|
||||
<< ((float) bits) / 8 << " bytes) out.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
addProtocolBits(inputLength << 3, bits);
|
||||
|
||||
if (isPrioritized() == 1)
|
||||
{
|
||||
priority_++;
|
||||
}
|
||||
|
||||
} // End of while ((inputMessage = readBuffer_.getMessage(inputLength)) != NULL) ...
|
||||
|
||||
//
|
||||
// All data has been read from the read buffer.
|
||||
// We still need to mark the end of the encode
|
||||
// buffer just before sending the frame. This
|
||||
// allows us to accommodate multiple reads in
|
||||
// a single frame.
|
||||
//
|
||||
|
||||
if (priority_ > 0)
|
||||
{
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "handleRead: WARNING! Requesting flush "
|
||||
<< "because of " << priority_ << " prioritized "
|
||||
<< "messages for FD#" << fd_ << ".\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
if (proxy -> handleAsyncPriority() < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Reset the priority flag.
|
||||
//
|
||||
|
||||
priority_ = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Flush if we produced enough data.
|
||||
//
|
||||
|
||||
if (proxy -> canAsyncFlush() == 1)
|
||||
{
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "handleRead: WARNING! Requesting flush "
|
||||
<< "because of enough data or timeout on the "
|
||||
<< "proxy link.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (proxy -> handleAsyncFlush() < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TEST) || defined(INFO)
|
||||
|
||||
if (transport_ -> pending() != 0 ||
|
||||
readBuffer_.checkMessage() != 0)
|
||||
{
|
||||
*logofs << "handleRead: PANIC! Buffer for X descriptor FD#"
|
||||
<< fd_ << " has " << transport_ -> pending()
|
||||
<< " bytes to read.\n" << logofs_flush;
|
||||
|
||||
HandleCleanup();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Reset the read buffer.
|
||||
//
|
||||
|
||||
readBuffer_.fullReset();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// End of handleRead().
|
||||
//
|
||||
|
||||
//
|
||||
// Beginning of handleWrite().
|
||||
//
|
||||
|
||||
int GenericChannel::handleWrite(const unsigned char *message, unsigned int length)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "handleWrite: Called for FD#" << fd_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Create the buffer from which to
|
||||
// decode messages.
|
||||
//
|
||||
|
||||
DecodeBuffer decodeBuffer(message, length);
|
||||
|
||||
#if defined(TEST) || defined(INFO) || defined(FLUSH)
|
||||
*logofs << "handleWrite: Decoding messages for FD#" << fd_
|
||||
<< " with " << length << " bytes in the buffer.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned char *outputMessage;
|
||||
unsigned int outputLength;
|
||||
|
||||
//
|
||||
// Tag message as generic data
|
||||
// in decompression.
|
||||
//
|
||||
|
||||
unsigned char outputOpcode = X_NXInternalGenericData;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
decodeBuffer.decodeValue(outputLength, 32, 14);
|
||||
|
||||
if (outputLength == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (isCompressed() == 1)
|
||||
{
|
||||
if (writeBuffer_.getAvailable() < outputLength ||
|
||||
(int) outputLength >= control -> TransportFlushBufferSize)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << "handleWrite: Using scratch buffer for "
|
||||
<< "generic data with size " << outputLength << " and "
|
||||
<< writeBuffer_.getLength() << " bytes in buffer.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
outputMessage = writeBuffer_.addScratchMessage(outputLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputMessage = writeBuffer_.addMessage(outputLength);
|
||||
}
|
||||
|
||||
const unsigned char *compressedData = NULL;
|
||||
unsigned int compressedDataSize = 0;
|
||||
|
||||
int decompressed = handleDecompress(decodeBuffer, outputOpcode, 0,
|
||||
outputMessage, outputLength, compressedData,
|
||||
compressedDataSize);
|
||||
if (decompressed < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << "handleWrite: Using scratch buffer for "
|
||||
<< "generic data with size " << outputLength << " and "
|
||||
<< writeBuffer_.getLength() << " bytes in buffer.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
writeBuffer_.addScratchMessage((unsigned char *)
|
||||
decodeBuffer.decodeMemory(outputLength), outputLength);
|
||||
}
|
||||
|
||||
#if defined(TEST) || defined(OPCODES)
|
||||
*logofs << "handleWrite: Handled generic data for FD#" << fd_
|
||||
<< ". " << outputLength << " bytes out.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
handleFlush(flush_if_needed);
|
||||
}
|
||||
|
||||
//
|
||||
// Write any remaining data to socket.
|
||||
//
|
||||
|
||||
if (handleFlush(flush_if_any) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// End of handleWrite().
|
||||
//
|
||||
|
||||
//
|
||||
// Other members.
|
||||
//
|
||||
|
||||
int GenericChannel::handleCompletion(EncodeBuffer &encodeBuffer)
|
||||
{
|
||||
//
|
||||
// Add the bits telling to the remote
|
||||
// that all data in the frame has been
|
||||
// encoded.
|
||||
//
|
||||
|
||||
if (encodeBuffer.getLength() > 0)
|
||||
{
|
||||
#if defined(TEST) || defined(INFO)
|
||||
*logofs << "handleCompletion: Writing completion bits with "
|
||||
<< encodeBuffer.getLength() << " bytes encoded "
|
||||
<< "for FD#" << fd_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeValue(0, 32, 14);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#if defined(TEST) || defined(INFO)
|
||||
else
|
||||
{
|
||||
*logofs << "handleCompletion: PANIC! No completion to write "
|
||||
<< "for FD#" << fd_ << ".\n" << logofs_flush;
|
||||
|
||||
HandleCleanup();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GenericChannel::handleConfiguration()
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "GenericChannel: Setting new buffer parameters.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
readBuffer_.setSize(control -> GenericInitialReadSize,
|
||||
control -> GenericMaximumBufferSize);
|
||||
|
||||
writeBuffer_.setSize(control -> TransportGenericBufferSize,
|
||||
control -> TransportGenericBufferThreshold,
|
||||
control -> TransportMaximumBufferSize);
|
||||
|
||||
transport_ -> setSize(control -> TransportGenericBufferSize,
|
||||
control -> TransportGenericBufferThreshold,
|
||||
control -> TransportMaximumBufferSize);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericChannel::handleFinish()
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "GenericChannel: Finishing channel for FD#"
|
||||
<< fd_ << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
congestion_ = 0;
|
||||
priority_ = 0;
|
||||
|
||||
finish_ = 1;
|
||||
|
||||
transport_ -> fullReset();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericChannel::setReferences()
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << "GenericChannel: Initializing the static "
|
||||
<< "members for the generic channels.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
#ifdef REFERENCES
|
||||
|
||||
references_ = 0;
|
||||
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
440
nxcomp/src/GenericChannel.h
Normal file
440
nxcomp/src/GenericChannel.h
Normal file
@@ -0,0 +1,440 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GenericChannel_H
|
||||
#define GenericChannel_H
|
||||
|
||||
#include "Channel.h"
|
||||
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "GenericReadBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
//
|
||||
// Define this to log a line when a channel
|
||||
// is created or destroyed.
|
||||
//
|
||||
|
||||
#undef REFERENCES
|
||||
|
||||
//
|
||||
// This class implements the client
|
||||
// side compression of X protocol.
|
||||
//
|
||||
|
||||
class GenericChannel : public Channel
|
||||
{
|
||||
public:
|
||||
|
||||
GenericChannel(Transport *transport, StaticCompressor *compressor);
|
||||
|
||||
virtual ~GenericChannel();
|
||||
|
||||
virtual int handleRead(EncodeBuffer &encodeBuffer, const unsigned char *message,
|
||||
unsigned int length);
|
||||
|
||||
virtual int handleWrite(const unsigned char *message, unsigned int length);
|
||||
|
||||
|
||||
virtual int handleSplit(EncodeBuffer &encodeBuffer, MessageStore *store,
|
||||
T_store_action action, int position, const unsigned char opcode,
|
||||
const unsigned char *buffer, const unsigned int size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleSplit(DecodeBuffer &decodeBuffer, MessageStore *store,
|
||||
T_store_action action, int position, unsigned char &opcode,
|
||||
unsigned char *&buffer, unsigned int &size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
virtual int handleSplit(EncodeBuffer &encodeBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleSplit(DecodeBuffer &decodeBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleSplitEvent(EncodeBuffer &encodeBuffer, Split *split)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleSplitEvent(DecodeBuffer &decodeBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleMotion(EncodeBuffer &encodeBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int handleCompletion(EncodeBuffer &encodeBuffer);
|
||||
|
||||
virtual int handleConfiguration();
|
||||
|
||||
virtual int handleFinish();
|
||||
|
||||
virtual int handleAsyncEvents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int needSplit() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int needMotion() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual T_channel_type getType() const = 0;
|
||||
|
||||
//
|
||||
// Initialize the static members.
|
||||
//
|
||||
|
||||
static int setReferences();
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
// Generic channels are considered to be
|
||||
// in congestion state as soon as the
|
||||
// socket is blocked for write.
|
||||
//
|
||||
|
||||
virtual int isCongested()
|
||||
{
|
||||
return (transport_ -> blocked() == 1);
|
||||
}
|
||||
|
||||
virtual int isReliable()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Model generic channels' encoding and
|
||||
// decoding policy.
|
||||
//
|
||||
|
||||
virtual int isCompressed() = 0;
|
||||
|
||||
//
|
||||
// Return true if the channel contains
|
||||
// time sensitive data.
|
||||
//
|
||||
|
||||
virtual int isPrioritized() = 0;
|
||||
|
||||
//
|
||||
// Record the protocol bits for the
|
||||
// specific service.
|
||||
//
|
||||
|
||||
virtual void addProtocolBits(unsigned int bitsIn, unsigned int bitsOut) = 0;
|
||||
|
||||
//
|
||||
// Channel's own read buffer.
|
||||
//
|
||||
|
||||
GenericReadBuffer readBuffer_;
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Keep track of object's creation
|
||||
// and deletion.
|
||||
//
|
||||
|
||||
#ifdef REFERENCES
|
||||
|
||||
static int references_;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
class CupsChannel : public GenericChannel
|
||||
{
|
||||
public:
|
||||
|
||||
CupsChannel(Transport *transport, StaticCompressor *compressor)
|
||||
|
||||
: GenericChannel(transport, compressor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CupsChannel()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual T_channel_type getType() const
|
||||
{
|
||||
return channel_cups;
|
||||
}
|
||||
|
||||
virtual int isCompressed()
|
||||
{
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int isPrioritized()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void addProtocolBits(unsigned int bitsIn,
|
||||
unsigned int bitsOut)
|
||||
{
|
||||
statistics -> addCupsBits(bitsIn, bitsOut);
|
||||
}
|
||||
};
|
||||
|
||||
class SmbChannel : public GenericChannel
|
||||
{
|
||||
public:
|
||||
|
||||
SmbChannel(Transport *transport, StaticCompressor *compressor)
|
||||
|
||||
: GenericChannel(transport, compressor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SmbChannel()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual T_channel_type getType() const
|
||||
{
|
||||
return channel_smb;
|
||||
}
|
||||
|
||||
virtual int isCompressed()
|
||||
{
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int isPrioritized()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void addProtocolBits(unsigned int bitsIn,
|
||||
unsigned int bitsOut)
|
||||
{
|
||||
statistics -> addSmbBits(bitsIn, bitsOut);
|
||||
}
|
||||
};
|
||||
|
||||
class MediaChannel : public GenericChannel
|
||||
{
|
||||
public:
|
||||
|
||||
MediaChannel(Transport *transport, StaticCompressor *compressor)
|
||||
|
||||
: GenericChannel(transport, compressor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~MediaChannel()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual T_channel_type getType() const
|
||||
{
|
||||
return channel_media;
|
||||
}
|
||||
|
||||
//
|
||||
// Don't try to compress the media data.
|
||||
//
|
||||
|
||||
virtual int isCompressed()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Reduce the latency of media channels
|
||||
// by setting them as prioritized, even
|
||||
// if this will take away bandwidth from
|
||||
// the X channels.
|
||||
//
|
||||
|
||||
virtual int isPrioritized()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void addProtocolBits(unsigned int bitsIn,
|
||||
unsigned int bitsOut)
|
||||
{
|
||||
statistics -> addMediaBits(bitsIn, bitsOut);
|
||||
}
|
||||
};
|
||||
|
||||
class HttpChannel : public GenericChannel
|
||||
{
|
||||
public:
|
||||
|
||||
HttpChannel(Transport *transport, StaticCompressor *compressor)
|
||||
|
||||
: GenericChannel(transport, compressor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~HttpChannel()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual T_channel_type getType() const
|
||||
{
|
||||
return channel_http;
|
||||
}
|
||||
|
||||
virtual int isCompressed()
|
||||
{
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int isPrioritized()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void addProtocolBits(unsigned int bitsIn,
|
||||
unsigned int bitsOut)
|
||||
{
|
||||
statistics -> addHttpBits(bitsIn, bitsOut);
|
||||
}
|
||||
};
|
||||
|
||||
class FontChannel : public GenericChannel
|
||||
{
|
||||
public:
|
||||
|
||||
FontChannel(Transport *transport, StaticCompressor *compressor)
|
||||
|
||||
: GenericChannel(transport, compressor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~FontChannel()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual T_channel_type getType() const
|
||||
{
|
||||
return channel_font;
|
||||
}
|
||||
|
||||
virtual int isCompressed()
|
||||
{
|
||||
// Since ProtoStep8 (#issue 108)
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int isPrioritized()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void addProtocolBits(unsigned int bitsIn,
|
||||
unsigned int bitsOut)
|
||||
{
|
||||
statistics -> addFontBits(bitsIn, bitsOut);
|
||||
}
|
||||
};
|
||||
|
||||
class SlaveChannel : public GenericChannel
|
||||
{
|
||||
public:
|
||||
|
||||
SlaveChannel(Transport *transport, StaticCompressor *compressor)
|
||||
|
||||
: GenericChannel(transport, compressor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SlaveChannel()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual T_channel_type getType() const
|
||||
{
|
||||
return channel_slave;
|
||||
}
|
||||
|
||||
virtual int isCompressed()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int isPrioritized()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void addProtocolBits(unsigned int bitsIn,
|
||||
unsigned int bitsOut)
|
||||
{
|
||||
statistics -> addSlaveBits(bitsIn, bitsOut);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* GenericChannel_H */
|
||||
82
nxcomp/src/GenericReadBuffer.cpp
Normal file
82
nxcomp/src/GenericReadBuffer.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GenericReadBuffer.h"
|
||||
|
||||
#include "GenericChannel.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
|
||||
unsigned int GenericReadBuffer::suggestedLength(unsigned int pendingLength)
|
||||
{
|
||||
//
|
||||
// Always read the initial read size.
|
||||
//
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GenericReadBuffer::locateMessage(const unsigned char *start,
|
||||
const unsigned char *end,
|
||||
unsigned int &controlLength,
|
||||
unsigned int &dataLength,
|
||||
unsigned int &trailerLength)
|
||||
{
|
||||
//
|
||||
// We don't care about the endianness
|
||||
// in generic channels.
|
||||
//
|
||||
|
||||
unsigned int size = end - start;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << "GenericReadBuffer: Locating message for FD#"
|
||||
<< transport_ -> fd() << " with " << size
|
||||
<< " bytes.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
remaining_ = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
dataLength = size;
|
||||
|
||||
controlLength = 0;
|
||||
trailerLength = 0;
|
||||
|
||||
remaining_ = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
61
nxcomp/src/GenericReadBuffer.h
Normal file
61
nxcomp/src/GenericReadBuffer.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GenericReadBuffer_H
|
||||
#define GenericReadBuffer_H
|
||||
|
||||
#include "ReadBuffer.h"
|
||||
#include "Control.h"
|
||||
|
||||
class GenericChannel;
|
||||
|
||||
class GenericReadBuffer : public ReadBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
GenericReadBuffer(Transport *transport, GenericChannel *channel)
|
||||
|
||||
: ReadBuffer(transport), channel_(channel)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~GenericReadBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual unsigned int suggestedLength(unsigned int pendingLength);
|
||||
|
||||
virtual int locateMessage(const unsigned char *start,
|
||||
const unsigned char *end,
|
||||
unsigned int &controlLength,
|
||||
unsigned int &dataLength,
|
||||
unsigned int &trailerLength);
|
||||
|
||||
GenericChannel *channel_;
|
||||
};
|
||||
|
||||
#endif /* GenericReadBuffer_H */
|
||||
302
nxcomp/src/GenericReply.cpp
Normal file
302
nxcomp/src/GenericReply.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GenericReply.h"
|
||||
|
||||
#include "ServerCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
#include "WriteBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
GenericReplyStore::GenericReplyStore(StaticCompressor *compressor)
|
||||
|
||||
: MessageStore(compressor)
|
||||
{
|
||||
enableCache = GENERICREPLY_ENABLE_CACHE;
|
||||
enableData = GENERICREPLY_ENABLE_DATA;
|
||||
enableSplit = GENERICREPLY_ENABLE_SPLIT;
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
enableCompress = GENERICREPLY_ENABLE_COMPRESS_IF_PROTO_STEP_7;
|
||||
|
||||
dataLimit = GENERICREPLY_DATA_LIMIT;
|
||||
dataOffset = GENERICREPLY_DATA_OFFSET;
|
||||
|
||||
cacheSlots = GENERICREPLY_CACHE_SLOTS;
|
||||
cacheThreshold = GENERICREPLY_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = GENERICREPLY_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
GenericReplyStore::~GenericReplyStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int GenericReplyStore::encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Encoding full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeValue(GetULONG(buffer + 4, bigEndian), 32, 15);
|
||||
|
||||
encodeBuffer.encodeCachedValue(*(buffer + 1), 8,
|
||||
serverCache -> genericReplyCharCache);
|
||||
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
{
|
||||
encodeBuffer.encodeCachedValue(GetULONG(buffer + i * 4 + 8, bigEndian), 32,
|
||||
*serverCache -> genericReplyIntCache[i]);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Encoded full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericReplyStore::decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoding full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeValue(size, 32, 15);
|
||||
|
||||
size = 32 + (size << 2);
|
||||
|
||||
buffer = writeBuffer -> addMessage(size);
|
||||
|
||||
decodeBuffer.decodeCachedValue(*(buffer + 1), 8,
|
||||
serverCache -> genericReplyCharCache);
|
||||
|
||||
unsigned int value;
|
||||
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
{
|
||||
decodeBuffer.decodeCachedValue(value, 32,
|
||||
*serverCache -> genericReplyIntCache[i]);
|
||||
|
||||
PutULONG(value, buffer + i * 4 + 8, bigEndian);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericReplyStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GenericReplyMessage *genericReply = (GenericReplyMessage *) message;
|
||||
|
||||
genericReply -> byte_data = *(buffer + 1);
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
genericReply -> short_data[i] = GetUINT(buffer + i * 2 + 8, bigEndian);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at "
|
||||
<< message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericReplyStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GenericReplyMessage *genericReply = (GenericReplyMessage *) message;
|
||||
|
||||
*(buffer + 1) = genericReply -> byte_data;
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
PutUINT(genericReply -> short_data[i], buffer + i * 2 + 8, bigEndian);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at "
|
||||
<< message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GenericReplyStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
GenericReplyMessage *genericReply = (GenericReplyMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity byte_data "
|
||||
<< (unsigned) genericReply -> byte_data;
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
*logofs << ", short_data[" << i << "]"
|
||||
<< (unsigned) genericReply -> short_data[i];
|
||||
}
|
||||
|
||||
*logofs << ", size " << genericReply -> size_ << ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void GenericReplyStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
}
|
||||
|
||||
void GenericReplyStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
//
|
||||
// Encode the variant part.
|
||||
//
|
||||
|
||||
GenericReplyMessage *genericReply = (GenericReplyMessage *) message;
|
||||
GenericReplyMessage *cachedGenericReply = (GenericReplyMessage *) cachedMessage;
|
||||
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value "
|
||||
<< (unsigned int) genericReply -> byte_data
|
||||
<< " as byte_data field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue(genericReply -> byte_data, 8,
|
||||
serverCache -> genericReplyCharCache);
|
||||
|
||||
cachedGenericReply -> byte_data = genericReply -> byte_data;
|
||||
|
||||
for (unsigned int i = 0; i < 12; i++)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << genericReply -> short_data[i]
|
||||
<< " as short_data[" << i << "] field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue(genericReply -> short_data[i], 16,
|
||||
*serverCache -> genericReplyIntCache[i]);
|
||||
|
||||
cachedGenericReply -> short_data[i] = genericReply -> short_data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void GenericReplyStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
//
|
||||
// Decode the variant part.
|
||||
//
|
||||
|
||||
GenericReplyMessage *genericReply = (GenericReplyMessage *) message;
|
||||
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
decodeBuffer.decodeCachedValue(genericReply -> byte_data, 8,
|
||||
serverCache -> genericReplyCharCache);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded value "
|
||||
<< (unsigned int) genericReply -> byte_data
|
||||
<< " as byte_data field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned int value;
|
||||
|
||||
for (unsigned int i = 0; i < 12; i++)
|
||||
{
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
*serverCache -> genericReplyIntCache[i]);
|
||||
|
||||
genericReply -> short_data[i] = (unsigned short) value;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Decoded value " << genericReply -> short_data[i]
|
||||
<< " as short_data[" << i << "] field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
160
nxcomp/src/GenericReply.h
Normal file
160
nxcomp/src/GenericReply.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GenericReply_H
|
||||
#define GenericReply_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define GENERICREPLY_ENABLE_CACHE 1
|
||||
#define GENERICREPLY_ENABLE_DATA 1
|
||||
#define GENERICREPLY_ENABLE_SPLIT 0
|
||||
|
||||
#define GENERICREPLY_DATA_LIMIT 1048576 - 32
|
||||
#define GENERICREPLY_DATA_OFFSET 32
|
||||
|
||||
#define GENERICREPLY_CACHE_SLOTS 400
|
||||
#define GENERICREPLY_CACHE_THRESHOLD 5
|
||||
#define GENERICREPLY_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
#define GENERICREPLY_ENABLE_COMPRESS_IF_PROTO_STEP_7 0
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class GenericReplyMessage : public Message
|
||||
{
|
||||
friend class GenericReplyStore;
|
||||
|
||||
public:
|
||||
|
||||
GenericReplyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~GenericReplyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute the
|
||||
// 'identity' part of the message. Starting
|
||||
// from protocol level 3 we use short data
|
||||
// to increase cache efficiency.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char byte_data;
|
||||
unsigned short short_data[12];
|
||||
};
|
||||
|
||||
class GenericReplyStore : public MessageStore
|
||||
{
|
||||
public:
|
||||
|
||||
GenericReplyStore(StaticCompressor *compressor);
|
||||
|
||||
virtual ~GenericReplyStore();
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "GenericReply";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_NXInternalGenericReply;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(GenericReplyMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
protected:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new GenericReplyMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new GenericReplyMessage((const GenericReplyMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (GenericReplyMessage *) message;
|
||||
}
|
||||
|
||||
virtual int encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* GenericReply_H */
|
||||
334
nxcomp/src/GenericRequest.cpp
Normal file
334
nxcomp/src/GenericRequest.cpp
Normal file
@@ -0,0 +1,334 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GenericRequest.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
#include "WriteBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
GenericRequestStore::GenericRequestStore(StaticCompressor *compressor)
|
||||
|
||||
: MessageStore(compressor)
|
||||
{
|
||||
enableCache = GENERICREQUEST_ENABLE_CACHE;
|
||||
enableData = GENERICREQUEST_ENABLE_DATA;
|
||||
enableSplit = GENERICREQUEST_ENABLE_SPLIT;
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
enableCompress = GENERICREQUEST_ENABLE_COMPRESS_IF_PROTO_STEP_7;
|
||||
|
||||
dataLimit = GENERICREQUEST_DATA_LIMIT;
|
||||
dataOffset = GENERICREQUEST_DATA_OFFSET;
|
||||
|
||||
cacheSlots = GENERICREQUEST_CACHE_SLOTS;
|
||||
cacheThreshold = GENERICREQUEST_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = GENERICREQUEST_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
GenericRequestStore::~GenericRequestStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int GenericRequestStore::encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Encoding full message identity.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeValue(size >> 2, 16, 10);
|
||||
|
||||
encodeBuffer.encodeCachedValue(*(buffer + 1), 8,
|
||||
clientCache -> genericRequestOpcodeCache);
|
||||
|
||||
for (unsigned int i = 0; i < 8 && (i * 2 + 4) < size; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Encoding data[" << i << "] "
|
||||
<< "at position " << i * 2 + 4 << " with value "
|
||||
<< GetUINT(buffer + (i * 2) + 4, bigEndian)
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue(GetUINT(buffer + (i * 2) + 4, bigEndian), 16,
|
||||
*clientCache -> genericRequestDataCache[i]);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Encoded full message identity.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericRequestStore::decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoding full message identity.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeValue(size, 16, 10);
|
||||
|
||||
size <<= 2;
|
||||
|
||||
buffer = writeBuffer -> addMessage(size);
|
||||
|
||||
decodeBuffer.decodeCachedValue(*(buffer + 1), 8,
|
||||
clientCache -> genericRequestOpcodeCache);
|
||||
|
||||
unsigned int value;
|
||||
|
||||
for (unsigned int i = 0; i < 8 && (i * 2 + 4) < size; i++)
|
||||
{
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
*clientCache -> genericRequestDataCache[i]);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoding data[" << i << "] "
|
||||
<< "at position " << i * 2 + 4 << " with value "
|
||||
<< value << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
PutUINT(value, buffer + 4 + (i * 2), bigEndian);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded full message identity.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericRequestStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GenericRequestMessage *genericRequest = (GenericRequestMessage *) message;
|
||||
|
||||
genericRequest -> opcode = *(buffer + 1);
|
||||
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
{
|
||||
if ((i * 2 + 4) < size)
|
||||
{
|
||||
genericRequest -> data[i] = GetUINT(buffer + i * 2 + 4, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed data[" << i << "] "
|
||||
<< "with value " << genericRequest -> data[i]
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
genericRequest -> data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at "
|
||||
<< this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GenericRequestStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GenericRequestMessage *genericRequest = (GenericRequestMessage *) message;
|
||||
|
||||
*(buffer + 1) = genericRequest -> opcode;
|
||||
|
||||
for (unsigned int i = 0; i < 8 && (i * 2 + 4) < size; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed data[" << i << "] "
|
||||
<< "with value " << genericRequest -> data[i]
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
PutUINT(genericRequest -> data[i], buffer + i * 2 + 4, bigEndian);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at "
|
||||
<< this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GenericRequestStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
GenericRequestMessage *genericRequest = (GenericRequestMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity opcode " << (unsigned) genericRequest -> opcode;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
*logofs << ", data[" << i << "] " << genericRequest -> data[i];
|
||||
}
|
||||
|
||||
*logofs << ", size " << genericRequest -> size_ << ".\n" << logofs_flush;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void GenericRequestStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
//
|
||||
// As data offset can be beyond the real end of
|
||||
// the message, we need to include the message's
|
||||
// size or we will match any message whose size
|
||||
// is less or equal to the data offset.
|
||||
//
|
||||
|
||||
md5_append(md5_state_, buffer + 2, 2);
|
||||
}
|
||||
|
||||
void GenericRequestStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
//
|
||||
// Encode the variant part.
|
||||
//
|
||||
|
||||
GenericRequestMessage *genericRequest = (GenericRequestMessage *) message;
|
||||
GenericRequestMessage *cachedGenericRequest = (GenericRequestMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Updating value "
|
||||
<< (unsigned) genericRequest -> opcode
|
||||
<< " as opcode field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue((unsigned int) genericRequest -> opcode, 8,
|
||||
clientCache -> genericRequestOpcodeCache);
|
||||
|
||||
cachedGenericRequest -> opcode = genericRequest -> opcode;
|
||||
|
||||
for (int i = 0; i < 8 && (i * 2 + 4) < genericRequest -> size_; i++)
|
||||
{
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Updating data[" << i << "] "
|
||||
<< "with value " << genericRequest -> data[i]
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue((unsigned int) genericRequest -> data[i], 16,
|
||||
*clientCache -> genericRequestDataCache[i]);
|
||||
|
||||
cachedGenericRequest -> data[i] = genericRequest -> data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void GenericRequestStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
GenericRequestMessage *genericRequest = (GenericRequestMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
decodeBuffer.decodeCachedValue(genericRequest -> opcode, 8,
|
||||
clientCache -> genericRequestOpcodeCache);
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Updated value "
|
||||
<< (unsigned) genericRequest -> opcode
|
||||
<< " as opcode field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned int value;
|
||||
|
||||
for (int i = 0; i < 8 && (i * 2 + 4) < genericRequest -> size_; i++)
|
||||
{
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
*clientCache -> genericRequestDataCache[i]);
|
||||
|
||||
genericRequest -> data[i] = (unsigned short) value;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Updated data[" << i << "] "
|
||||
<< "with value " << genericRequest -> data[i]
|
||||
<< ".\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
160
nxcomp/src/GenericRequest.h
Normal file
160
nxcomp/src/GenericRequest.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GenericRequest_H
|
||||
#define GenericRequest_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define GENERICREQUEST_ENABLE_CACHE 1
|
||||
#define GENERICREQUEST_ENABLE_DATA 1
|
||||
#define GENERICREQUEST_ENABLE_SPLIT 0
|
||||
|
||||
#define GENERICREQUEST_DATA_LIMIT 262144 - 20
|
||||
#define GENERICREQUEST_DATA_OFFSET 20
|
||||
|
||||
#define GENERICREQUEST_CACHE_SLOTS 400
|
||||
#define GENERICREQUEST_CACHE_THRESHOLD 5
|
||||
#define GENERICREQUEST_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
#define GENERICREQUEST_ENABLE_COMPRESS_IF_PROTO_STEP_7 0
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class GenericRequestMessage : public Message
|
||||
{
|
||||
friend class GenericRequestStore;
|
||||
|
||||
public:
|
||||
|
||||
GenericRequestMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~GenericRequestMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Note that we consider for this message a data offset
|
||||
// of 4 (or 20 starting from protocol 3). Bytes from 9
|
||||
// to 20, if present, are taken as part of identity and
|
||||
// encoded through an array of int caches.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char opcode;
|
||||
unsigned short data[8];
|
||||
};
|
||||
|
||||
class GenericRequestStore : public MessageStore
|
||||
{
|
||||
public:
|
||||
|
||||
GenericRequestStore(StaticCompressor *compressor);
|
||||
|
||||
virtual ~GenericRequestStore();
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "GenericRequest";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_NXInternalGenericRequest;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(GenericRequestMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new GenericRequestMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new GenericRequestMessage((const GenericRequestMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (GenericRequestMessage *) message;
|
||||
}
|
||||
|
||||
virtual int encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* GenericRequest_H */
|
||||
177
nxcomp/src/GetImage.cpp
Normal file
177
nxcomp/src/GetImage.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GetImage.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int GetImageStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GetImageMessage *getImage = (GetImageMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
getImage -> format = *(buffer + 1);
|
||||
|
||||
#ifdef TEST
|
||||
if (getImage -> format != 1 && getImage -> format != 2)
|
||||
{
|
||||
*logofs << name() << ": WARNING! Dirty value " << getImage -> format
|
||||
<< " for field format.\n" << logofs_flush;
|
||||
}
|
||||
#endif
|
||||
|
||||
getImage -> drawable = GetULONG(buffer + 4, bigEndian);
|
||||
|
||||
getImage -> x = GetUINT(buffer + 8, bigEndian);
|
||||
getImage -> y = GetUINT(buffer + 10, bigEndian);
|
||||
getImage -> width = GetUINT(buffer + 12, bigEndian);
|
||||
getImage -> height = GetUINT(buffer + 14, bigEndian);
|
||||
|
||||
getImage -> plane_mask = GetULONG(buffer + 16, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetImageStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GetImageMessage *getImage = (GetImageMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
*(buffer + 1) = getImage -> format;
|
||||
|
||||
PutULONG(getImage -> drawable, buffer + 4, bigEndian);
|
||||
|
||||
PutUINT(getImage -> x, buffer + 8, bigEndian);
|
||||
PutUINT(getImage -> y, buffer + 10, bigEndian);
|
||||
PutUINT(getImage -> width, buffer + 12, bigEndian);
|
||||
PutUINT(getImage -> height, buffer + 14, bigEndian);
|
||||
|
||||
PutULONG(getImage -> plane_mask, buffer + 16, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GetImageStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
GetImageMessage *getImage = (GetImageMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity format " << (unsigned) getImage -> format
|
||||
<< ", drawable " << getImage -> drawable << ", x " << getImage -> x
|
||||
<< ", y " << getImage -> y << ", width " << getImage -> width
|
||||
<< ", height " << getImage -> height << ", plane_mask "
|
||||
<< getImage -> plane_mask << ", size " << getImage -> size_
|
||||
<< ".\n" << logofs_flush;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetImageStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
md5_append(md5_state_, buffer + 8, 2);
|
||||
md5_append(md5_state_, buffer + 10, 2);
|
||||
md5_append(md5_state_, buffer + 12, 2);
|
||||
md5_append(md5_state_, buffer + 14, 2);
|
||||
md5_append(md5_state_, buffer + 16, 4);
|
||||
}
|
||||
|
||||
void GetImageStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
GetImageMessage *getImage = (GetImageMessage *) message;
|
||||
GetImageMessage *cachedGetImage = (GetImageMessage *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << getImage -> drawable
|
||||
<< " as drawable field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(getImage -> drawable, clientCache -> drawableCache);
|
||||
|
||||
cachedGetImage -> drawable = getImage -> drawable;
|
||||
}
|
||||
|
||||
void GetImageStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
GetImageMessage *getImage = (GetImageMessage *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> drawableCache);
|
||||
|
||||
getImage -> drawable = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << getImage -> drawable
|
||||
<< " as drawable field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
190
nxcomp/src/GetImage.h
Normal file
190
nxcomp/src/GetImage.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GetImage_H
|
||||
#define GetImage_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define GETIMAGE_ENABLE_CACHE 1
|
||||
#define GETIMAGE_ENABLE_DATA 0
|
||||
#define GETIMAGE_ENABLE_SPLIT 0
|
||||
#define GETIMAGE_ENABLE_COMPRESS 0
|
||||
|
||||
#define GETIMAGE_DATA_LIMIT 0
|
||||
#define GETIMAGE_DATA_OFFSET 20
|
||||
|
||||
#define GETIMAGE_CACHE_SLOTS 200
|
||||
#define GETIMAGE_CACHE_THRESHOLD 1
|
||||
#define GETIMAGE_CACHE_LOWER_THRESHOLD 0
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class GetImageMessage : public Message
|
||||
{
|
||||
friend class GetImageStore;
|
||||
|
||||
public:
|
||||
|
||||
GetImageMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~GetImageMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char format;
|
||||
unsigned int drawable;
|
||||
unsigned short int x;
|
||||
unsigned short int y;
|
||||
unsigned short int width;
|
||||
unsigned short int height;
|
||||
unsigned int plane_mask;
|
||||
};
|
||||
|
||||
class GetImageStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
GetImageStore() : MessageStore()
|
||||
{
|
||||
enableCache = GETIMAGE_ENABLE_CACHE;
|
||||
enableData = GETIMAGE_ENABLE_DATA;
|
||||
enableSplit = GETIMAGE_ENABLE_SPLIT;
|
||||
enableCompress = GETIMAGE_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = GETIMAGE_DATA_LIMIT;
|
||||
dataOffset = GETIMAGE_DATA_OFFSET;
|
||||
|
||||
cacheSlots = GETIMAGE_CACHE_SLOTS;
|
||||
cacheThreshold = GETIMAGE_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = GETIMAGE_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~GetImageStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "GetImage";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_GetImage;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(GetImageMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new GetImageMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new GetImageMessage((const GetImageMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (GetImageMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* GetImage_H */
|
||||
194
nxcomp/src/GetImageReply.cpp
Normal file
194
nxcomp/src/GetImageReply.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GetImageReply.h"
|
||||
|
||||
#include "ServerCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
GetImageReplyStore::GetImageReplyStore(StaticCompressor *compressor)
|
||||
|
||||
: MessageStore(compressor)
|
||||
{
|
||||
enableCache = GETIMAGEREPLY_ENABLE_CACHE;
|
||||
enableData = GETIMAGEREPLY_ENABLE_DATA;
|
||||
enableSplit = GETIMAGEREPLY_ENABLE_SPLIT;
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
enableCompress = GETIMAGEREPLY_ENABLE_COMPRESS_IF_PROTO_STEP_7;
|
||||
|
||||
dataLimit = GETIMAGEREPLY_DATA_LIMIT;
|
||||
dataOffset = GETIMAGEREPLY_DATA_OFFSET;
|
||||
|
||||
cacheSlots = GETIMAGEREPLY_CACHE_SLOTS;
|
||||
cacheThreshold = GETIMAGEREPLY_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = GETIMAGEREPLY_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
GetImageReplyStore::~GetImageReplyStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int GetImageReplyStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GetImageReplyMessage *getImageReply = (GetImageReplyMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
getImageReply -> depth = *(buffer + 1);
|
||||
|
||||
getImageReply -> visual = GetULONG(buffer + 8, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at "
|
||||
<< message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetImageReplyStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GetImageReplyMessage *getImageReply = (GetImageReplyMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
*(buffer + 1) = getImageReply -> depth;
|
||||
|
||||
PutULONG(getImageReply -> visual, buffer + 8, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at "
|
||||
<< message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GetImageReplyStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
GetImageReplyMessage *getImageReply = (GetImageReplyMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity depth " << (unsigned) getImageReply -> depth
|
||||
<< ", visual " << getImageReply -> visual << ", size "
|
||||
<< getImageReply -> size_ << ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetImageReplyStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
//
|
||||
// Field depth.
|
||||
//
|
||||
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
}
|
||||
|
||||
void GetImageReplyStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
//
|
||||
// Encode the variant part.
|
||||
//
|
||||
|
||||
GetImageReplyMessage *getImageReply = (GetImageReplyMessage *) message;
|
||||
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << getImageReply -> visual
|
||||
<< " as visual field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeCachedValue(getImageReply -> visual, 29,
|
||||
serverCache -> visualCache);
|
||||
}
|
||||
|
||||
void GetImageReplyStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
//
|
||||
// Decode the variant part.
|
||||
//
|
||||
|
||||
GetImageReplyMessage *getImageReply = (GetImageReplyMessage *) message;
|
||||
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
decodeBuffer.decodeCachedValue(getImageReply -> visual, 29,
|
||||
serverCache -> visualCache);
|
||||
}
|
||||
150
nxcomp/src/GetImageReply.h
Normal file
150
nxcomp/src/GetImageReply.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GetImageReply_H
|
||||
#define GetImageReply_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define GETIMAGEREPLY_ENABLE_CACHE 1
|
||||
#define GETIMAGEREPLY_ENABLE_DATA 1
|
||||
#define GETIMAGEREPLY_ENABLE_SPLIT 0
|
||||
|
||||
#define GETIMAGEREPLY_DATA_LIMIT 1048576 - 32
|
||||
#define GETIMAGEREPLY_DATA_OFFSET 32
|
||||
|
||||
#define GETIMAGEREPLY_CACHE_SLOTS 1000
|
||||
#define GETIMAGEREPLY_CACHE_THRESHOLD 20
|
||||
#define GETIMAGEREPLY_CACHE_LOWER_THRESHOLD 2
|
||||
|
||||
#define GETIMAGEREPLY_ENABLE_COMPRESS_IF_PROTO_STEP_7 0
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class GetImageReplyMessage : public Message
|
||||
{
|
||||
friend class GetImageReplyStore;
|
||||
|
||||
public:
|
||||
|
||||
GetImageReplyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~GetImageReplyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char depth;
|
||||
unsigned int visual;
|
||||
};
|
||||
|
||||
class GetImageReplyStore : public MessageStore
|
||||
{
|
||||
public:
|
||||
|
||||
GetImageReplyStore(StaticCompressor *compressor);
|
||||
|
||||
virtual ~GetImageReplyStore();
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "GetImageReply";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_GetImage;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(GetImageReplyMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
protected:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new GetImageReplyMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new GetImageReplyMessage((const GetImageReplyMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (GetImageReplyMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* GetImageReply_H */
|
||||
119
nxcomp/src/GetProperty.cpp
Normal file
119
nxcomp/src/GetProperty.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GetProperty.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int GetPropertyStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GetPropertyMessage *getProperty = (GetPropertyMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
getProperty -> property_delete = *(buffer + 1);
|
||||
|
||||
getProperty -> window = GetULONG(buffer + 4, bigEndian);
|
||||
getProperty -> property = GetULONG(buffer + 8, bigEndian);
|
||||
getProperty -> type = GetULONG(buffer + 12, bigEndian);
|
||||
getProperty -> long_offset = GetULONG(buffer + 16, bigEndian);
|
||||
getProperty -> long_length = GetULONG(buffer + 20, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at " << message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetPropertyStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
|
||||
GetPropertyMessage *getProperty = (GetPropertyMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
*(buffer + 1) = getProperty -> property_delete;
|
||||
|
||||
PutULONG(getProperty -> window, buffer + 4, bigEndian);
|
||||
PutULONG(getProperty -> property, buffer + 8, bigEndian);
|
||||
PutULONG(getProperty -> type, buffer + 12, bigEndian);
|
||||
PutULONG(getProperty -> long_offset, buffer + 16, bigEndian);
|
||||
PutULONG(getProperty -> long_length, buffer + 20, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GetPropertyStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
GetPropertyMessage *getProperty = (GetPropertyMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity property_delete " << (unsigned int) getProperty -> property_delete
|
||||
<< ", window " << getProperty -> window << ", property " << getProperty -> property
|
||||
<< ", type " << getProperty -> type << ", long-offset " << getProperty -> long_offset
|
||||
<< ", long-length " << getProperty -> long_length << ".\n" << logofs_flush;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetPropertyStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
md5_append(md5_state_, buffer + 4, 20);
|
||||
}
|
||||
183
nxcomp/src/GetProperty.h
Normal file
183
nxcomp/src/GetProperty.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GetProperty_H
|
||||
#define GetProperty_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define GETPROPERTY_ENABLE_CACHE 1
|
||||
#define GETPROPERTY_ENABLE_DATA 0
|
||||
#define GETPROPERTY_ENABLE_SPLIT 0
|
||||
#define GETPROPERTY_ENABLE_COMPRESS 0
|
||||
|
||||
#define GETPROPERTY_DATA_LIMIT 0
|
||||
#define GETPROPERTY_DATA_OFFSET 24
|
||||
|
||||
#define GETPROPERTY_CACHE_SLOTS 2000
|
||||
#define GETPROPERTY_CACHE_THRESHOLD 2
|
||||
#define GETPROPERTY_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class GetPropertyMessage : public Message
|
||||
{
|
||||
friend class GetPropertyStore;
|
||||
|
||||
public:
|
||||
|
||||
GetPropertyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~GetPropertyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char property_delete;
|
||||
unsigned long window;
|
||||
unsigned long property;
|
||||
unsigned long type;
|
||||
unsigned long long_offset;
|
||||
unsigned long long_length;
|
||||
};
|
||||
|
||||
class GetPropertyStore : public MessageStore
|
||||
{
|
||||
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
GetPropertyStore() : MessageStore()
|
||||
{
|
||||
enableCache = GETPROPERTY_ENABLE_CACHE;
|
||||
enableData = GETPROPERTY_ENABLE_DATA;
|
||||
enableSplit = GETPROPERTY_ENABLE_SPLIT;
|
||||
enableCompress = GETPROPERTY_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = GETPROPERTY_DATA_LIMIT;
|
||||
dataOffset = GETPROPERTY_DATA_OFFSET;
|
||||
|
||||
cacheSlots = GETPROPERTY_CACHE_SLOTS;
|
||||
cacheThreshold = GETPROPERTY_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = GETPROPERTY_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~GetPropertyStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "GetProperty";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_GetProperty;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(GetPropertyMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
protected:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new GetPropertyMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new GetPropertyMessage((const GetPropertyMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (GetPropertyMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* GetProperty_H */
|
||||
304
nxcomp/src/GetPropertyReply.cpp
Normal file
304
nxcomp/src/GetPropertyReply.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GetPropertyReply.h"
|
||||
|
||||
#include "ServerCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
#include "WriteBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
GetPropertyReplyStore::GetPropertyReplyStore(StaticCompressor *compressor)
|
||||
|
||||
: MessageStore(compressor)
|
||||
{
|
||||
enableCache = GETPROPERTYREPLY_ENABLE_CACHE;
|
||||
enableData = GETPROPERTYREPLY_ENABLE_DATA;
|
||||
enableSplit = GETPROPERTYREPLY_ENABLE_SPLIT;
|
||||
|
||||
// Since ProtoStep7 (#issue 108)
|
||||
enableCompress = GETPROPERTYREPLY_ENABLE_COMPRESS_IF_PROTO_STEP_7;
|
||||
|
||||
dataLimit = GETPROPERTYREPLY_DATA_LIMIT;
|
||||
dataOffset = GETPROPERTYREPLY_DATA_OFFSET;
|
||||
|
||||
cacheSlots = GETPROPERTYREPLY_CACHE_SLOTS;
|
||||
cacheThreshold = GETPROPERTYREPLY_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = GETPROPERTYREPLY_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
GetPropertyReplyStore::~GetPropertyReplyStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int GetPropertyReplyStore::encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Encoding full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned char format = (unsigned int) *(buffer + 1);
|
||||
|
||||
encodeBuffer.encodeCachedValue(format, 8,
|
||||
serverCache -> getPropertyFormatCache);
|
||||
|
||||
unsigned int numBytes = GetULONG(buffer + 16, bigEndian);
|
||||
|
||||
encodeBuffer.encodeValue(numBytes, 32, 9);
|
||||
|
||||
if (format == 16)
|
||||
{
|
||||
numBytes <<= 1;
|
||||
}
|
||||
else if (format == 32)
|
||||
{
|
||||
numBytes <<= 2;
|
||||
}
|
||||
|
||||
encodeBuffer.encodeCachedValue(GetULONG(buffer + 8, bigEndian), 29,
|
||||
serverCache -> getPropertyTypeCache, 9);
|
||||
|
||||
encodeBuffer.encodeValue(GetULONG(buffer + 12, bigEndian), 32, 9);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Encoded full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetPropertyReplyStore::decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ServerCache *serverCache = (ServerCache *) channelCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoding full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned char format;
|
||||
|
||||
decodeBuffer.decodeCachedValue(format, 8,
|
||||
serverCache -> getPropertyFormatCache);
|
||||
|
||||
unsigned int length;
|
||||
|
||||
decodeBuffer.decodeValue(length, 32, 9);
|
||||
|
||||
unsigned int numBytes = length;
|
||||
|
||||
if (format == 16)
|
||||
{
|
||||
numBytes <<= 1;
|
||||
}
|
||||
else if (format == 32)
|
||||
{
|
||||
numBytes <<= 2;
|
||||
}
|
||||
|
||||
size = 32 + RoundUp4(numBytes);
|
||||
|
||||
buffer = writeBuffer -> addMessage(size);
|
||||
|
||||
*(buffer + 1) = format;
|
||||
|
||||
PutULONG(length, buffer + 16, bigEndian);
|
||||
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 29,
|
||||
serverCache -> getPropertyTypeCache, 9);
|
||||
|
||||
PutULONG(value, buffer + 8, bigEndian);
|
||||
|
||||
decodeBuffer.decodeValue(value, 32, 9);
|
||||
|
||||
PutULONG(value, buffer + 12, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded full message identity.\n"
|
||||
<< logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetPropertyReplyStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GetPropertyReplyMessage *getPropertyReply = (GetPropertyReplyMessage *) message;
|
||||
|
||||
getPropertyReply -> format = *(buffer + 1);
|
||||
|
||||
getPropertyReply -> type = GetULONG(buffer + 8, bigEndian);
|
||||
getPropertyReply -> after = GetULONG(buffer + 12, bigEndian);
|
||||
getPropertyReply -> items = GetULONG(buffer + 16, bigEndian);
|
||||
|
||||
//
|
||||
// Cleanup the padding bytes.
|
||||
//
|
||||
|
||||
unsigned int uiLengthInBytes;
|
||||
unsigned int uiFormat;
|
||||
|
||||
if ((int) size > GETPROPERTYREPLY_DATA_OFFSET)
|
||||
{
|
||||
uiLengthInBytes = getPropertyReply -> items;
|
||||
|
||||
uiFormat = *(buffer + 1);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": length " << uiLengthInBytes
|
||||
<< ", format " << uiFormat << ", size "
|
||||
<< size << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
if (uiFormat == 16)
|
||||
{
|
||||
uiLengthInBytes <<= 1;
|
||||
}
|
||||
else if (uiFormat == 32)
|
||||
{
|
||||
uiLengthInBytes <<= 2;
|
||||
}
|
||||
|
||||
unsigned char *end = ((unsigned char *) buffer) + size;
|
||||
unsigned char *pad = ((unsigned char *) buffer) + GETPROPERTYREPLY_DATA_OFFSET + uiLengthInBytes;
|
||||
|
||||
CleanData((unsigned char *) pad, end - pad);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at "
|
||||
<< message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetPropertyReplyStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
GetPropertyReplyMessage *getPropertyReply = (GetPropertyReplyMessage *) message;
|
||||
|
||||
*(buffer + 1) = getPropertyReply -> format;
|
||||
|
||||
PutULONG(getPropertyReply -> type, buffer + 8, bigEndian);
|
||||
PutULONG(getPropertyReply -> after, buffer + 12, bigEndian);
|
||||
PutULONG(getPropertyReply -> items, buffer + 16, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at "
|
||||
<< message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GetPropertyReplyStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
GetPropertyReplyMessage *getPropertyReply = (GetPropertyReplyMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity format "
|
||||
<< (unsigned) getPropertyReply -> format << ", type "
|
||||
<< getPropertyReply -> type << ", after " << getPropertyReply -> after
|
||||
<< ", items " << getPropertyReply -> items << ", size "
|
||||
<< getPropertyReply -> size_ << ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetPropertyReplyStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
//
|
||||
// Fields format, type, after, items.
|
||||
//
|
||||
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
md5_append(md5_state_, buffer + 8, 12);
|
||||
}
|
||||
|
||||
void GetPropertyReplyStore::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
}
|
||||
|
||||
void GetPropertyReplyStore::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
}
|
||||
160
nxcomp/src/GetPropertyReply.h
Normal file
160
nxcomp/src/GetPropertyReply.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GetPropertyReply_H
|
||||
#define GetPropertyReply_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define GETPROPERTYREPLY_ENABLE_CACHE 1
|
||||
#define GETPROPERTYREPLY_ENABLE_DATA 1
|
||||
#define GETPROPERTYREPLY_ENABLE_SPLIT 0
|
||||
|
||||
#define GETPROPERTYREPLY_DATA_LIMIT 1048576 - 32
|
||||
#define GETPROPERTYREPLY_DATA_OFFSET 32
|
||||
|
||||
#define GETPROPERTYREPLY_CACHE_SLOTS 400
|
||||
#define GETPROPERTYREPLY_CACHE_THRESHOLD 5
|
||||
#define GETPROPERTYREPLY_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
#define GETPROPERTYREPLY_ENABLE_COMPRESS_IF_PROTO_STEP_7 0
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class GetPropertyReplyMessage : public Message
|
||||
{
|
||||
friend class GetPropertyReplyStore;
|
||||
|
||||
public:
|
||||
|
||||
GetPropertyReplyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~GetPropertyReplyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char format;
|
||||
unsigned int type;
|
||||
unsigned int after;
|
||||
unsigned int items;
|
||||
};
|
||||
|
||||
class GetPropertyReplyStore : public MessageStore
|
||||
{
|
||||
public:
|
||||
|
||||
GetPropertyReplyStore(StaticCompressor *compressor);
|
||||
|
||||
virtual ~GetPropertyReplyStore();
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "GetPropertyReply";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_GetProperty;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(GetPropertyReplyMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
protected:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new GetPropertyReplyMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new GetPropertyReplyMessage((const GetPropertyReplyMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (GetPropertyReplyMessage *) message;
|
||||
}
|
||||
|
||||
virtual int encodeIdentity(EncodeBuffer &encodeBuffer, const unsigned char *buffer,
|
||||
const unsigned int size, int bigEndian,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int decodeIdentity(DecodeBuffer &decodeBuffer, unsigned char *&buffer,
|
||||
unsigned int &size, int bigEndian, WriteBuffer *writeBuffer,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* GetPropertyReply_H */
|
||||
231
nxcomp/src/ImageText16.cpp
Normal file
231
nxcomp/src/ImageText16.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ImageText16.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int ImageText16Store::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ImageText16Message *imageText16 = (ImageText16Message *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
imageText16 -> len = *(buffer + 1);
|
||||
|
||||
imageText16 -> drawable = GetULONG(buffer + 4, bigEndian);
|
||||
imageText16 -> gcontext = GetULONG(buffer + 8, bigEndian);
|
||||
|
||||
imageText16 -> x = GetUINT(buffer + 12, bigEndian);
|
||||
imageText16 -> y = GetUINT(buffer + 14, bigEndian);
|
||||
|
||||
if ((int) size > dataOffset)
|
||||
{
|
||||
int pad = (size - dataOffset) - (imageText16 -> len * 2);
|
||||
|
||||
if (pad > 0)
|
||||
{
|
||||
CleanData((unsigned char *) buffer + size - pad, pad);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ImageText16Store::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ImageText16Message *imageText16 = (ImageText16Message *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
*(buffer + 1) = imageText16 -> len;
|
||||
|
||||
PutULONG(imageText16 -> drawable, buffer + 4, bigEndian);
|
||||
PutULONG(imageText16 -> gcontext, buffer + 8, bigEndian);
|
||||
|
||||
PutUINT(imageText16 -> x, buffer + 12, bigEndian);
|
||||
PutUINT(imageText16 -> y, buffer + 14, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ImageText16Store::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
ImageText16Message *imageText16 = (ImageText16Message *) message;
|
||||
|
||||
*logofs << name() << ": Identity len " << (unsigned int) imageText16 -> len
|
||||
<< " drawable " << imageText16 -> drawable << ", gcontext "
|
||||
<< imageText16 -> gcontext << ", x " << imageText16 -> x << ", y "
|
||||
<< imageText16 -> y << ", size " << imageText16 -> size_ << ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ImageText16Store::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
}
|
||||
|
||||
void ImageText16Store::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ImageText16Message *imageText16 = (ImageText16Message *) message;
|
||||
ImageText16Message *cachedImageText16 = (ImageText16Message *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText16 -> drawable
|
||||
<< " as " << "drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(imageText16 -> drawable, clientCache -> drawableCache);
|
||||
|
||||
cachedImageText16 -> drawable = imageText16 -> drawable;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText16 -> gcontext
|
||||
<< " as " << "gcontext" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(imageText16 -> gcontext, clientCache -> gcCache);
|
||||
|
||||
cachedImageText16 -> gcontext = imageText16 -> gcontext;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText16 -> x
|
||||
<< " as " << "x" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned short int diff_x = imageText16 -> x - cachedImageText16 -> x;
|
||||
|
||||
encodeBuffer.encodeCachedValue(diff_x, 16,
|
||||
clientCache -> imageTextCacheX);
|
||||
|
||||
cachedImageText16 -> x = imageText16 -> x;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText16 -> y
|
||||
<< " as " << "y" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned short int diff_y = imageText16 -> y - cachedImageText16 -> y;
|
||||
|
||||
encodeBuffer.encodeCachedValue(diff_y, 16,
|
||||
clientCache -> imageTextCacheY);
|
||||
|
||||
cachedImageText16 -> y = imageText16 -> y;
|
||||
}
|
||||
|
||||
void ImageText16Store::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ImageText16Message *imageText16 = (ImageText16Message *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> drawableCache);
|
||||
|
||||
imageText16 -> drawable = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText16 -> drawable
|
||||
<< " as " << "drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> gcCache);
|
||||
|
||||
imageText16 -> gcontext = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText16 -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
clientCache -> imageTextCacheX);
|
||||
|
||||
imageText16 -> x += value;
|
||||
imageText16 -> x &= 0xffff;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText16 -> x
|
||||
<< " as x field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
clientCache -> imageTextCacheY);
|
||||
|
||||
imageText16 -> y += value;
|
||||
imageText16 -> y &= 0xffff;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText16 -> y
|
||||
<< " as y field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
190
nxcomp/src/ImageText16.h
Normal file
190
nxcomp/src/ImageText16.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ImageText16_H
|
||||
#define ImageText16_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define IMAGETEXT16_ENABLE_CACHE 1
|
||||
#define IMAGETEXT16_ENABLE_DATA 0
|
||||
#define IMAGETEXT16_ENABLE_SPLIT 0
|
||||
#define IMAGETEXT16_ENABLE_COMPRESS 0
|
||||
|
||||
#define IMAGETEXT16_DATA_LIMIT 512
|
||||
#define IMAGETEXT16_DATA_OFFSET 16
|
||||
|
||||
#define IMAGETEXT16_CACHE_SLOTS 3000
|
||||
#define IMAGETEXT16_CACHE_THRESHOLD 5
|
||||
#define IMAGETEXT16_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class ImageText16Message : public Message
|
||||
{
|
||||
friend class ImageText16Store;
|
||||
|
||||
public:
|
||||
|
||||
ImageText16Message()
|
||||
{
|
||||
}
|
||||
|
||||
~ImageText16Message()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char len;
|
||||
|
||||
unsigned int drawable;
|
||||
unsigned int gcontext;
|
||||
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
};
|
||||
|
||||
class ImageText16Store : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
ImageText16Store() : MessageStore()
|
||||
{
|
||||
enableCache = IMAGETEXT16_ENABLE_CACHE;
|
||||
enableData = IMAGETEXT16_ENABLE_DATA;
|
||||
enableSplit = IMAGETEXT16_ENABLE_SPLIT;
|
||||
enableCompress = IMAGETEXT16_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = IMAGETEXT16_DATA_LIMIT;
|
||||
dataOffset = IMAGETEXT16_DATA_OFFSET;
|
||||
|
||||
cacheSlots = IMAGETEXT16_CACHE_SLOTS;
|
||||
cacheThreshold = IMAGETEXT16_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = IMAGETEXT16_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~ImageText16Store()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "ImageText16";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_ImageText16;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(ImageText16Message);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new ImageText16Message();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new ImageText16Message((const ImageText16Message &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (ImageText16Message *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* ImageText16_H */
|
||||
231
nxcomp/src/ImageText8.cpp
Normal file
231
nxcomp/src/ImageText8.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ImageText8.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int ImageText8Store::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ImageText8Message *imageText8 = (ImageText8Message *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
imageText8 -> len = *(buffer + 1);
|
||||
|
||||
imageText8 -> drawable = GetULONG(buffer + 4, bigEndian);
|
||||
imageText8 -> gcontext = GetULONG(buffer + 8, bigEndian);
|
||||
|
||||
imageText8 -> x = GetUINT(buffer + 12, bigEndian);
|
||||
imageText8 -> y = GetUINT(buffer + 14, bigEndian);
|
||||
|
||||
if ((int) size > dataOffset)
|
||||
{
|
||||
int pad = (size - dataOffset) - imageText8 -> len;
|
||||
|
||||
if (pad > 0)
|
||||
{
|
||||
CleanData((unsigned char *) buffer + size - pad, pad);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ImageText8Store::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
ImageText8Message *imageText8 = (ImageText8Message *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
*(buffer + 1) = imageText8 -> len;
|
||||
|
||||
PutULONG(imageText8 -> drawable, buffer + 4, bigEndian);
|
||||
PutULONG(imageText8 -> gcontext, buffer + 8, bigEndian);
|
||||
|
||||
PutUINT(imageText8 -> x, buffer + 12, bigEndian);
|
||||
PutUINT(imageText8 -> y, buffer + 14, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ImageText8Store::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
ImageText8Message *imageText8 = (ImageText8Message *) message;
|
||||
|
||||
*logofs << name() << ": Identity len " << (unsigned int) imageText8 -> len
|
||||
<< " drawable " << imageText8 -> drawable << ", gcontext "
|
||||
<< imageText8 -> gcontext << ", x " << imageText8 -> x << ", y "
|
||||
<< imageText8 -> y << ", size " << imageText8 -> size_ << ".\n";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ImageText8Store::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
}
|
||||
|
||||
void ImageText8Store::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ImageText8Message *imageText8 = (ImageText8Message *) message;
|
||||
ImageText8Message *cachedImageText8 = (ImageText8Message *) cachedMessage;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText8 -> drawable
|
||||
<< " as " << "drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(imageText8 -> drawable, clientCache -> drawableCache);
|
||||
|
||||
cachedImageText8 -> drawable = imageText8 -> drawable;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText8 -> gcontext
|
||||
<< " as " << "gcontext" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
encodeBuffer.encodeXidValue(imageText8 -> gcontext, clientCache -> gcCache);
|
||||
|
||||
cachedImageText8 -> gcontext = imageText8 -> gcontext;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText8 -> x
|
||||
<< " as " << "x" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned short int diff_x = imageText8 -> x - cachedImageText8 -> x;
|
||||
|
||||
encodeBuffer.encodeCachedValue(diff_x, 16,
|
||||
clientCache -> imageTextCacheX);
|
||||
|
||||
cachedImageText8 -> x = imageText8 -> x;
|
||||
|
||||
#ifdef TEST
|
||||
*logofs << name() << ": Encoding value " << imageText8 -> y
|
||||
<< " as " << "y" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
unsigned short int diff_y = imageText8 -> y - cachedImageText8 -> y;
|
||||
|
||||
encodeBuffer.encodeCachedValue(diff_y, 16,
|
||||
clientCache -> imageTextCacheY);
|
||||
|
||||
cachedImageText8 -> y = imageText8 -> y;
|
||||
}
|
||||
|
||||
void ImageText8Store::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const
|
||||
{
|
||||
ImageText8Message *imageText8 = (ImageText8Message *) message;
|
||||
|
||||
ClientCache *clientCache = (ClientCache *) channelCache;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> drawableCache);
|
||||
|
||||
imageText8 -> drawable = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText8 -> drawable
|
||||
<< " as " << "drawable" << " field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeXidValue(value, clientCache -> gcCache);
|
||||
|
||||
imageText8 -> gcontext = value;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText8 -> gcontext
|
||||
<< " as gcontext field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
clientCache -> imageTextCacheX);
|
||||
|
||||
imageText8 -> x += value;
|
||||
imageText8 -> x &= 0xffff;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText8 -> x
|
||||
<< " as x field.\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
decodeBuffer.decodeCachedValue(value, 16,
|
||||
clientCache -> imageTextCacheY);
|
||||
|
||||
imageText8 -> y += value;
|
||||
imageText8 -> y &= 0xffff;
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Decoded value " << imageText8 -> y
|
||||
<< " as y field.\n" << logofs_flush;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
190
nxcomp/src/ImageText8.h
Normal file
190
nxcomp/src/ImageText8.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ImageText8_H
|
||||
#define ImageText8_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define IMAGETEXT8_ENABLE_CACHE 1
|
||||
#define IMAGETEXT8_ENABLE_DATA 0
|
||||
#define IMAGETEXT8_ENABLE_SPLIT 0
|
||||
#define IMAGETEXT8_ENABLE_COMPRESS 0
|
||||
|
||||
#define IMAGETEXT8_DATA_LIMIT 256
|
||||
#define IMAGETEXT8_DATA_OFFSET 16
|
||||
|
||||
#define IMAGETEXT8_CACHE_SLOTS 3000
|
||||
#define IMAGETEXT8_CACHE_THRESHOLD 5
|
||||
#define IMAGETEXT8_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class ImageText8Message : public Message
|
||||
{
|
||||
friend class ImageText8Store;
|
||||
|
||||
public:
|
||||
|
||||
ImageText8Message()
|
||||
{
|
||||
}
|
||||
|
||||
~ImageText8Message()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char len;
|
||||
|
||||
unsigned int drawable;
|
||||
unsigned int gcontext;
|
||||
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
};
|
||||
|
||||
class ImageText8Store : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
ImageText8Store() : MessageStore()
|
||||
{
|
||||
enableCache = IMAGETEXT8_ENABLE_CACHE;
|
||||
enableData = IMAGETEXT8_ENABLE_DATA;
|
||||
enableSplit = IMAGETEXT8_ENABLE_SPLIT;
|
||||
enableCompress = IMAGETEXT8_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = IMAGETEXT8_DATA_LIMIT;
|
||||
dataOffset = IMAGETEXT8_DATA_OFFSET;
|
||||
|
||||
cacheSlots = IMAGETEXT8_CACHE_SLOTS;
|
||||
cacheThreshold = IMAGETEXT8_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = IMAGETEXT8_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~ImageText8Store()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "ImageText8";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_ImageText8;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(ImageText8Message);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new ImageText8Message();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new ImageText8Message((const ImageText8Message &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (ImageText8Message *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
|
||||
const Message *cachedMessage,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
|
||||
ChannelCache *channelCache) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* ImageText8_H */
|
||||
230
nxcomp/src/IntCache.cpp
Normal file
230
nxcomp/src/IntCache.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Misc.h"
|
||||
#include "IntCache.h"
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
IntCache::IntCache(unsigned int size)
|
||||
|
||||
: size_(size), length_(0), buffer_(new unsigned int[size]),
|
||||
lastDiff_(0), lastValueInserted_(0), predictedBlockSize_(0)
|
||||
{
|
||||
}
|
||||
|
||||
int IntCache::lookup(unsigned int &value, unsigned int &index,
|
||||
unsigned int mask, unsigned int &sameDiff)
|
||||
{
|
||||
for (unsigned int i = 0; i < length_; i++)
|
||||
{
|
||||
if (value == buffer_[i])
|
||||
{
|
||||
index = i;
|
||||
if (i)
|
||||
{
|
||||
unsigned int target = (i >> 1);
|
||||
do
|
||||
{
|
||||
buffer_[i] = buffer_[i - 1];
|
||||
i--;
|
||||
}
|
||||
while (i > target);
|
||||
buffer_[target] = value;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
unsigned int insertionPoint;
|
||||
if (2 >= length_)
|
||||
insertionPoint = length_;
|
||||
else
|
||||
insertionPoint = 2;
|
||||
unsigned int start;
|
||||
if (length_ >= size_)
|
||||
start = size_ - 1;
|
||||
else
|
||||
{
|
||||
start = length_;
|
||||
length_++;
|
||||
}
|
||||
for (unsigned int k = start; k > insertionPoint; k--)
|
||||
buffer_[k] = buffer_[k - 1];
|
||||
buffer_[insertionPoint] = value;
|
||||
unsigned int diff = value - lastValueInserted_;
|
||||
|
||||
lastValueInserted_ = (value & mask);
|
||||
value = (diff & mask);
|
||||
sameDiff = (value == lastDiff_);
|
||||
if (!sameDiff)
|
||||
{
|
||||
lastDiff_ = value;
|
||||
|
||||
unsigned int lastChangeIndex = 0;
|
||||
unsigned int lastBitIsOne = (lastDiff_ & 0x1);
|
||||
unsigned int j = 1;
|
||||
for (unsigned int nextMask = 0x2; nextMask & mask; nextMask <<= 1)
|
||||
{
|
||||
unsigned int nextBitIsOne = (lastDiff_ & nextMask);
|
||||
if (nextBitIsOne)
|
||||
{
|
||||
if (!lastBitIsOne)
|
||||
{
|
||||
lastChangeIndex = j;
|
||||
lastBitIsOne = nextBitIsOne;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastBitIsOne)
|
||||
{
|
||||
lastChangeIndex = j;
|
||||
lastBitIsOne = nextBitIsOne;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
predictedBlockSize_ = lastChangeIndex + 1;
|
||||
if (predictedBlockSize_ < 2)
|
||||
predictedBlockSize_ = 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IntCache::insert(unsigned int &value, unsigned int mask)
|
||||
{
|
||||
unsigned int insertionPoint;
|
||||
if (2 >= length_)
|
||||
insertionPoint = length_;
|
||||
else
|
||||
insertionPoint = 2;
|
||||
unsigned int start;
|
||||
if (length_ >= size_)
|
||||
start = size_ - 1;
|
||||
else
|
||||
{
|
||||
start = length_;
|
||||
length_++;
|
||||
}
|
||||
for (unsigned int k = start; k > insertionPoint; k--)
|
||||
buffer_[k] = buffer_[k - 1];
|
||||
if (lastDiff_ != value)
|
||||
{
|
||||
lastDiff_ = value;
|
||||
unsigned int lastChangeIndex = 0;
|
||||
unsigned int lastBitIsOne = (lastDiff_ & 0x1);
|
||||
unsigned int j = 1;
|
||||
for (unsigned int nextMask = 0x2; nextMask & mask; nextMask <<= 1)
|
||||
{
|
||||
unsigned int nextBitIsOne = (lastDiff_ & nextMask);
|
||||
if (nextBitIsOne)
|
||||
{
|
||||
if (!lastBitIsOne)
|
||||
{
|
||||
lastChangeIndex = j;
|
||||
lastBitIsOne = nextBitIsOne;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastBitIsOne)
|
||||
{
|
||||
lastChangeIndex = j;
|
||||
lastBitIsOne = nextBitIsOne;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
predictedBlockSize_ = lastChangeIndex + 1;
|
||||
if (predictedBlockSize_ < 2)
|
||||
predictedBlockSize_ = 2;
|
||||
}
|
||||
lastValueInserted_ += value;
|
||||
lastValueInserted_ &= mask;
|
||||
buffer_[insertionPoint] = lastValueInserted_;
|
||||
value = lastValueInserted_;
|
||||
}
|
||||
|
||||
void IntCache::push(unsigned int &value, unsigned int mask)
|
||||
{
|
||||
//
|
||||
// Using a memmove() appears to be slower.
|
||||
//
|
||||
// memmove((char *) &buffer_[1], (char *) &buffer_[0],
|
||||
// sizeof(unsigned int) * (size_ - 1));
|
||||
//
|
||||
// if (length_ < size_)
|
||||
// {
|
||||
// length_++;
|
||||
// }
|
||||
//
|
||||
|
||||
unsigned int start;
|
||||
|
||||
if (length_ >= size_)
|
||||
{
|
||||
start = size_ - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = length_;
|
||||
|
||||
length_++;
|
||||
}
|
||||
|
||||
for (unsigned int k = start; k > 0; k--)
|
||||
{
|
||||
buffer_[k] = buffer_[k - 1];
|
||||
}
|
||||
|
||||
value &= mask;
|
||||
|
||||
buffer_[0] = value;
|
||||
}
|
||||
|
||||
void IntCache::dump()
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
*logofs << "IntCache: Dumping content of cache at "
|
||||
<< (void *) this << ":\n" << logofs_flush;
|
||||
|
||||
for (unsigned int i = 0; i < length_; i++)
|
||||
{
|
||||
*logofs << "IntCache: [" << i << "][" << buffer_[i] << "]\n";
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
119
nxcomp/src/IntCache.h
Normal file
119
nxcomp/src/IntCache.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef IntCache_H
|
||||
#define IntCache_H
|
||||
|
||||
class IntCache
|
||||
{
|
||||
public:
|
||||
|
||||
IntCache(unsigned int size);
|
||||
|
||||
~IntCache()
|
||||
{
|
||||
delete [] buffer_;
|
||||
}
|
||||
|
||||
unsigned int getSize() const
|
||||
{
|
||||
return length_;
|
||||
}
|
||||
|
||||
int lookup(unsigned int &value, unsigned int &index,
|
||||
unsigned int mask, unsigned int &sameDiff);
|
||||
|
||||
//
|
||||
// This can be inlined as it is only
|
||||
// called by decodeCachedValue().
|
||||
//
|
||||
|
||||
unsigned int get(unsigned int index)
|
||||
{
|
||||
unsigned int result = buffer_[index];
|
||||
|
||||
if (index != 0)
|
||||
{
|
||||
//
|
||||
// Using a memmove() appears to be slower.
|
||||
//
|
||||
// unsigned int target = index >> 1;
|
||||
//
|
||||
// memmove((char *) &buffer_[target + 1], (char *) &buffer_[target],
|
||||
// sizeof(unsigned int) * (index - target));
|
||||
//
|
||||
// buffer_[target] = result;
|
||||
//
|
||||
|
||||
unsigned int i = index;
|
||||
|
||||
unsigned int target = (i >> 1);
|
||||
|
||||
do
|
||||
{
|
||||
buffer_[i] = buffer_[i - 1];
|
||||
|
||||
i--;
|
||||
}
|
||||
while (i > target);
|
||||
|
||||
buffer_[target] = result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void insert(unsigned int &value, unsigned int mask);
|
||||
|
||||
void push(unsigned int &value, unsigned int mask);
|
||||
|
||||
void dump();
|
||||
|
||||
unsigned int getLastDiff(unsigned int mask) const
|
||||
{
|
||||
return lastDiff_;
|
||||
}
|
||||
|
||||
unsigned int getBlockSize(unsigned int bits) const
|
||||
{
|
||||
if (bits > 0)
|
||||
{
|
||||
return (predictedBlockSize_ < bits ? predictedBlockSize_ : bits);
|
||||
}
|
||||
|
||||
return predictedBlockSize_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
unsigned int size_;
|
||||
unsigned int length_;
|
||||
unsigned int *buffer_;
|
||||
unsigned int lastDiff_;
|
||||
unsigned int lastValueInserted_;
|
||||
unsigned int predictedBlockSize_;
|
||||
};
|
||||
|
||||
#endif /* IntCache_H */
|
||||
131
nxcomp/src/InternAtom.cpp
Normal file
131
nxcomp/src/InternAtom.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "InternAtom.h"
|
||||
|
||||
#include "ClientCache.h"
|
||||
|
||||
#include "EncodeBuffer.h"
|
||||
#include "DecodeBuffer.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Here are the methods to handle messages' content.
|
||||
//
|
||||
|
||||
int InternAtomStore::parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
InternAtomMessage *internAtom = (InternAtomMessage *) message;
|
||||
|
||||
//
|
||||
// Here is the fingerprint.
|
||||
//
|
||||
|
||||
internAtom -> only_if_exists = *(buffer + 1);
|
||||
internAtom -> name_length = GetUINT(buffer + 4, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Parsed identity for message at " << message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Clean up padding bytes.
|
||||
//
|
||||
|
||||
if ((int) size > dataOffset)
|
||||
{
|
||||
unsigned char *end = ((unsigned char *) buffer) + size;
|
||||
|
||||
for (unsigned char *pad = ((unsigned char *) buffer) + 8 +
|
||||
internAtom -> name_length; pad < end; pad++)
|
||||
{
|
||||
*pad = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int InternAtomStore::unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
InternAtomMessage *internAtom = (InternAtomMessage *) message;
|
||||
|
||||
//
|
||||
// Fill all the message's fields.
|
||||
//
|
||||
|
||||
*(buffer + 1) = internAtom -> only_if_exists;
|
||||
|
||||
PutUINT(internAtom -> name_length, buffer + 4, bigEndian);
|
||||
|
||||
#ifdef DEBUG
|
||||
*logofs << name() << ": Unparsed identity for message at " << message << ".\n" << logofs_flush;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InternAtomStore::dumpIdentity(const Message *message) const
|
||||
{
|
||||
#ifdef DUMP
|
||||
|
||||
InternAtomMessage *internAtom = (InternAtomMessage *) message;
|
||||
|
||||
*logofs << name() << ": Identity only_if_exists "
|
||||
<< (unsigned int) internAtom -> only_if_exists
|
||||
<< ", name_length " << internAtom -> name_length
|
||||
<< ", name '";
|
||||
|
||||
for (int i = 0; i < internAtom -> name_length; i++)
|
||||
{
|
||||
*logofs << internAtom -> data_[i];
|
||||
}
|
||||
|
||||
*logofs << "'.\n" << logofs_flush;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void InternAtomStore::identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const
|
||||
{
|
||||
md5_append(md5_state_, buffer + 1, 1);
|
||||
md5_append(md5_state_, buffer + 4, 2);
|
||||
}
|
||||
178
nxcomp/src/InternAtom.h
Normal file
178
nxcomp/src/InternAtom.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
||||
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
||||
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
||||
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
||||
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
||||
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
||||
/* */
|
||||
/* NXCOMP, NX protocol compression and NX extensions to this software */
|
||||
/* are copyright of the aforementioned persons and companies. */
|
||||
/* */
|
||||
/* Redistribution and use of the present software is allowed according */
|
||||
/* to terms specified in the file LICENSE.nxcomp which comes in the */
|
||||
/* source distribution. */
|
||||
/* */
|
||||
/* All rights reserved. */
|
||||
/* */
|
||||
/* NOTE: This software has received contributions from various other */
|
||||
/* contributors, only the core maintainers and supporters are listed as */
|
||||
/* copyright holders. Please contact us, if you feel you should be listed */
|
||||
/* as copyright holder, as well. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef InternAtom_H
|
||||
#define InternAtom_H
|
||||
|
||||
#include "Message.h"
|
||||
|
||||
//
|
||||
// Set the verbosity level.
|
||||
//
|
||||
|
||||
#define PANIC
|
||||
#define WARNING
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#undef DUMP
|
||||
|
||||
//
|
||||
// Set default values.
|
||||
//
|
||||
|
||||
#define INTERNATOM_ENABLE_CACHE 1
|
||||
#define INTERNATOM_ENABLE_DATA 0
|
||||
#define INTERNATOM_ENABLE_SPLIT 0
|
||||
#define INTERNATOM_ENABLE_COMPRESS 0
|
||||
|
||||
#define INTERNATOM_DATA_LIMIT 80
|
||||
#define INTERNATOM_DATA_OFFSET 8
|
||||
|
||||
#define INTERNATOM_CACHE_SLOTS 2000
|
||||
#define INTERNATOM_CACHE_THRESHOLD 2
|
||||
#define INTERNATOM_CACHE_LOWER_THRESHOLD 1
|
||||
|
||||
//
|
||||
// The message class.
|
||||
//
|
||||
|
||||
class InternAtomMessage : public Message
|
||||
{
|
||||
friend class InternAtomStore;
|
||||
|
||||
public:
|
||||
|
||||
InternAtomMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~InternAtomMessage()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Put here the fields which constitute
|
||||
// the 'identity' part of the message.
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
unsigned char only_if_exists;
|
||||
unsigned short name_length;
|
||||
};
|
||||
|
||||
class InternAtomStore : public MessageStore
|
||||
{
|
||||
//
|
||||
// Constructors and destructors.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
InternAtomStore() : MessageStore()
|
||||
{
|
||||
enableCache = INTERNATOM_ENABLE_CACHE;
|
||||
enableData = INTERNATOM_ENABLE_DATA;
|
||||
enableSplit = INTERNATOM_ENABLE_SPLIT;
|
||||
enableCompress = INTERNATOM_ENABLE_COMPRESS;
|
||||
|
||||
dataLimit = INTERNATOM_DATA_LIMIT;
|
||||
dataOffset = INTERNATOM_DATA_OFFSET;
|
||||
|
||||
cacheSlots = INTERNATOM_CACHE_SLOTS;
|
||||
cacheThreshold = INTERNATOM_CACHE_THRESHOLD;
|
||||
cacheLowerThreshold = INTERNATOM_CACHE_LOWER_THRESHOLD;
|
||||
|
||||
messages_ -> resize(cacheSlots);
|
||||
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
*i = NULL;
|
||||
}
|
||||
|
||||
temporary_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~InternAtomStore()
|
||||
{
|
||||
for (T_messages::iterator i = messages_ -> begin();
|
||||
i < messages_ -> end(); i++)
|
||||
{
|
||||
destroy(*i);
|
||||
}
|
||||
|
||||
destroy(temporary_);
|
||||
}
|
||||
|
||||
virtual const char *name() const
|
||||
{
|
||||
return "InternAtom";
|
||||
}
|
||||
|
||||
virtual unsigned char opcode() const
|
||||
{
|
||||
return X_InternAtom;
|
||||
}
|
||||
|
||||
virtual unsigned int storage() const
|
||||
{
|
||||
return sizeof(InternAtomMessage);
|
||||
}
|
||||
|
||||
//
|
||||
// Message handling methods.
|
||||
//
|
||||
|
||||
protected:
|
||||
|
||||
virtual Message *create() const
|
||||
{
|
||||
return new InternAtomMessage();
|
||||
}
|
||||
|
||||
virtual Message *create(const Message &message) const
|
||||
{
|
||||
return new InternAtomMessage((const InternAtomMessage &) message);
|
||||
}
|
||||
|
||||
virtual void destroy(Message *message) const
|
||||
{
|
||||
delete (InternAtomMessage *) message;
|
||||
}
|
||||
|
||||
virtual int parseIdentity(Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual int unparseIdentity(const Message *message, unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void identityChecksum(const Message *message, const unsigned char *buffer,
|
||||
unsigned int size, int bigEndian) const;
|
||||
|
||||
virtual void dumpIdentity(const Message *message) const;
|
||||
};
|
||||
|
||||
#endif /* InternAtom_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user