New upstream version 3.5.99.27

This commit is contained in:
geos_one
2025-08-08 20:00:36 +02:00
commit bc8d10cc33
4267 changed files with 1757978 additions and 0 deletions

25
nxcomp/.gitignore vendored Normal file
View 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
View 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
View File

@@ -0,0 +1 @@
../VERSION

142
nxcomp/configure.ac Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */

View File

@@ -0,0 +1 @@
../../m4/ax_cxx_compile_stdcxx.m4

View File

@@ -0,0 +1 @@
../../m4/ax_cxx_compile_stdcxx_11.m4

1
nxcomp/m4/ax_pthread.m4 Symbolic link
View File

@@ -0,0 +1 @@
../../m4/ax_pthread.m4

1
nxcomp/m4/nx-macros.m4 Symbolic link
View File

@@ -0,0 +1 @@
../../m4/nx-macros.m4

15
nxcomp/nxcomp.pc.in Normal file
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */

View 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);
}

View 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
View 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
View 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 */

View 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
View 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

File diff suppressed because it is too large Load Diff

664
nxcomp/src/Channel.h Normal file
View 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 */

View 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
View 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 */

View 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;
}

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

125
nxcomp/src/ClearArea.cpp Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

434
nxcomp/src/ClientChannel.h Normal file
View 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
View 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
View 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 */

View 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;
}

View 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
View 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
View 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
View 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
View 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 */

View 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);
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */

View 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
View 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 */

View 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;
}

View 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
View 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
View 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 */

View 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
View 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
View 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
View 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 */

View 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
View 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
View 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
View 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 */

View 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
{
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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