Merge branch 'devel' into v0.9
This commit is contained in:
commit
d868b05273
@ -4,13 +4,13 @@ FreeBSD_task:
|
||||
SSL: libressl
|
||||
matrix:
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-1
|
||||
image_family: freebsd-12-2
|
||||
prepare_script:
|
||||
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm
|
||||
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check
|
||||
- git submodule update --init --recursive
|
||||
configure_script:
|
||||
- ./bootstrap
|
||||
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman
|
||||
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman --enable-fuse
|
||||
build_script:
|
||||
- make -j $(sysctl -n hw.ncpu || echo 4)
|
||||
install_script:
|
||||
|
||||
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
|
||||
|
||||
# Minimal 64-bit arch builds
|
||||
- CC: gcc
|
||||
feature_set: min
|
||||
@ -38,19 +38,19 @@ jobs:
|
||||
arch: amd64
|
||||
os: ubuntu-latest
|
||||
DISTCHECK: true
|
||||
|
||||
|
||||
- CC: g++
|
||||
feature_set: max
|
||||
arch: amd64
|
||||
os: ubuntu-latest
|
||||
DISTCHECK: true
|
||||
|
||||
|
||||
- CC: clang
|
||||
feature_set: max
|
||||
arch: amd64
|
||||
os: ubuntu-latest
|
||||
DISTCHECK: true
|
||||
|
||||
|
||||
# Maximal debug 64-bit arch builds
|
||||
- CC: gcc
|
||||
feature_set: max
|
||||
@ -58,7 +58,7 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
name_extra: and DEBUG
|
||||
CONF_FLAGS_EXTRA: "--enable-xrdpdebug"
|
||||
|
||||
|
||||
# Maximal 32-bit arch builds
|
||||
- CC: gcc
|
||||
feature_set: max
|
||||
@ -82,12 +82,12 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: ${{ matrix.CC }}
|
||||
|
||||
# HACK (2020-11-16): github actions dosen't support YAML anchors/aliases to
|
||||
# avoid repeating long config values. So instead the config values are defined
|
||||
# as environment variables using a naming convention with fields that come from
|
||||
# the job config. These environment variables are then referenced as regualr
|
||||
# environment variables via the naming convention in the "define env" step to
|
||||
|
||||
# HACK (2020-11-16): github actions dosen't support YAML anchors/aliases to
|
||||
# avoid repeating long config values. So instead the config values are defined
|
||||
# as environment variables using a naming convention with fields that come from
|
||||
# the job config. These environment variables are then referenced as regualr
|
||||
# environment variables via the naming convention in the "define env" step to
|
||||
# define the stardard environment variable used in the rest of the steps.
|
||||
CONF_FLAGS_amd64_min: "--disable-ipv6 --disable-jpeg --disable-fuse --disable-mp3lame
|
||||
--disable-fdkaac --disable-opus --disable-rfxcodec --disable-painter
|
||||
@ -98,13 +98,13 @@ jobs:
|
||||
CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
|
||||
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
|
||||
--disable-pixman --host=i686-linux"
|
||||
|
||||
|
||||
PKG_CONFIG_PATH_i386: "/usr/lib/i386-linux-gnu/pkgconfig"
|
||||
CFLAGS_i386: "-m32"
|
||||
LDFLAGS_i386: "-m32"
|
||||
steps:
|
||||
- name: Define feature and arch dependent environment variables
|
||||
# Note: any "variable=value" written to the $GITHUB_ENV file will be
|
||||
# Note: any "variable=value" written to the $GITHUB_ENV file will be
|
||||
# defined as an environment variable for all future steps in this job
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
|
||||
run: |
|
||||
@ -119,17 +119,21 @@ jobs:
|
||||
- run: make
|
||||
- if: ${{ matrix.DISTCHECK }}
|
||||
run: make distcheck
|
||||
|
||||
|
||||
cppcheck:
|
||||
name: cppcheck
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CC: gcc
|
||||
# This is required to use a version of cppcheck other than that
|
||||
# suplied with the operating system
|
||||
CPPCHECK_VER: 2.1
|
||||
# supplied with the operating system
|
||||
CPPCHECK_VER: 2.4
|
||||
CPPCHECK_REPO: https://github.com/danmar/cppcheck.git
|
||||
steps:
|
||||
# This is currently the only way to get a version into
|
||||
# the cache tag name - see https://github.com/actions/cache/issues/543
|
||||
- run: |
|
||||
echo "OS_VERSION=`lsb_release -sr`" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v2
|
||||
- name: Cache cppcheck
|
||||
uses: actions/cache@v2
|
||||
@ -137,9 +141,8 @@ jobs:
|
||||
cache-name: cache-cppcheck
|
||||
with:
|
||||
path: ~/cppcheck.local
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.CPPCHECK_VER }}
|
||||
key: ${{ runner.os }}-${{ env.OS_VERSION }}-build-${{ env.cache-name }}-${{ env.CPPCHECK_VER }}
|
||||
- run: sudo scripts/install_cppcheck_dependencies_with_apt.sh
|
||||
- run: ./bootstrap
|
||||
- run: scripts/install_cppcheck.sh $CPPCHECK_REPO $CPPCHECK_VER
|
||||
- run: scripts/run_cppcheck.sh -v $CPPCHECK_VER
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@ -22,6 +22,7 @@ keygen/xrdp-keygen
|
||||
.libs
|
||||
libtool
|
||||
*.lo
|
||||
*.log
|
||||
ltmain.sh
|
||||
Makefile
|
||||
Makefile.in
|
||||
@ -41,6 +42,12 @@ sesman/xrdp-sesman
|
||||
sesman/sesman.ini
|
||||
*.so
|
||||
stamp-h1
|
||||
tap-driver.sh
|
||||
test-driver
|
||||
tests/common/test_common
|
||||
tests/memtest/memtest
|
||||
tools/devel/tcp_proxy/tcp_proxy
|
||||
*.trs
|
||||
xrdp/xrdp
|
||||
xrdp/xrdp.ini
|
||||
xrdp_configure_options.h
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--without-systemdsystemunitdir \
|
||||
--enable-strict-locations
|
||||
--enable-strict-locations \
|
||||
--enable-tests
|
||||
|
||||
EXTRA_DIST = \
|
||||
COPYING \
|
||||
@ -20,7 +21,6 @@ EXTRA_DIST = \
|
||||
m4 \
|
||||
postinstall-pak \
|
||||
tcutils \
|
||||
tests \
|
||||
vrplayer
|
||||
|
||||
if XRDP_NEUTRINORDP
|
||||
@ -64,7 +64,9 @@ SUBDIRS = \
|
||||
genkeymap \
|
||||
xrdpapi \
|
||||
pkgconfig \
|
||||
$(XRDPVRDIR)
|
||||
$(XRDPVRDIR) \
|
||||
tests \
|
||||
tools
|
||||
|
||||
distclean-local:
|
||||
-rm -f xrdp_configure_options.h
|
||||
|
||||
57
README.md
57
README.md
@ -1,4 +1,4 @@
|
||||
[](https://travis-ci.org/neutrinolabs/xrdp)
|
||||
[](https://github.com/neutrinolabs/xrdp/actions)
|
||||
[](https://gitter.im/neutrinolabs/xrdp-questions)
|
||||

|
||||
|
||||
@ -9,9 +9,15 @@
|
||||
## Overview
|
||||
|
||||
**xrdp** provides a graphical login to remote machines using Microsoft
|
||||
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of
|
||||
RDP clients: FreeRDP, rdesktop, NeutrinoRDP and Microsoft Remote Desktop
|
||||
Client (for Windows, Mac OS, iOS and Android).
|
||||
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of RDP clients:
|
||||
* FreeRDP
|
||||
* rdesktop
|
||||
* KRDC
|
||||
* NeutrinoRDP
|
||||
* Windows MSTSC (Microsoft Terminal Services Client, aka `mstsc.exe`)
|
||||
* Microsoft Remote Desktop (found on Microsoft Store, which is distinct from MSTSC)
|
||||
|
||||
Many of these work on some or all of Windows, Mac OS, iOS, and/or Android.
|
||||
|
||||
RDP transport is encrypted using TLS by default.
|
||||
|
||||
@ -24,13 +30,24 @@ RDP transport is encrypted using TLS by default.
|
||||
* Connect to a Linux desktop using RDP from anywhere (requires
|
||||
[xorgxrdp](https://github.com/neutrinolabs/xorgxrdp) Xorg module)
|
||||
* Reconnect to an existing session
|
||||
* Session resizing
|
||||
* Session resizing (both on-connect and on-the-fly)
|
||||
* RDP/VNC proxy (connect to another RDP/VNC server via xrdp)
|
||||
|
||||
### Access to Remote Resources
|
||||
* two-way clipboard transfer (text, bitmap, file)
|
||||
* audio redirection ([requires to build additional modules](https://github.com/neutrinolabs/xrdp/wiki/How-to-set-up-audio-redirection))
|
||||
* drive redirection (mount local client drives on remote machine)
|
||||
* Two-way clipboard transfer (text, bitmap, file)
|
||||
* Audio redirection ([requires to build additional modules](https://github.com/neutrinolabs/xrdp/wiki/How-to-set-up-audio-redirection))
|
||||
* Microphone redirection ([requires to build additional modules](https://github.com/neutrinolabs/xrdp/wiki/How-to-set-up-audio-redirection))
|
||||
* Drive redirection (mount local client drives on remote machine)
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
**xrdp** primarily targets GNU/Linux operating system. x86 (including x86-64)
|
||||
and ARM processors are most mature architecture to run xrdp on.
|
||||
See also [Platform Support Tier](https://github.com/neutrinolabs/xrdp/wiki/Platform-Support-Tier).
|
||||
|
||||
Some components such as xorgxrdp and RemoteFX codec have special optimization
|
||||
for x86 using SIMD instructions. So running xrdp on x86 processors will get
|
||||
fully accelerated experience.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@ -65,20 +82,6 @@ yum install xrdp
|
||||
`yum` is being replaced with `dnf`, so you may need to use `dnf` instead
|
||||
of `yum` in the above commands.
|
||||
|
||||
## Environment
|
||||
|
||||
**xrdp** primarily targets to GNU/Linux. Tested on x86, x86_64, SPARC and
|
||||
PowerPC.
|
||||
|
||||
xorgxrdp and RemoteFX Codec have special optimization for x86 and x86_64 using
|
||||
SIMD instructions.
|
||||
|
||||
FreeBSD is not a primary target of xrdp. It is working on FreeBSD except
|
||||
for the drive redirection feature.
|
||||
|
||||
Other operating systems such as macOS are not supported so far, but we
|
||||
welcome your contributions.
|
||||
|
||||
## Compiling
|
||||
|
||||
See also https://github.com/neutrinolabs/xrdp/wiki#building-from-sources
|
||||
@ -132,9 +135,17 @@ xrdp
|
||||
├── mc ·········· media center module
|
||||
├── neutrinordp · RDP client module for proxying RDP connections using NeutrinoRDP
|
||||
├── pkgconfig ··· pkg-config configuration
|
||||
├── sesman ······ session manager for xrdp
|
||||
├── scripts ····· build scripts
|
||||
├┬─ sesman ······ session manager for xrdp
|
||||
|├── chansrv ···· channel server for xrdp
|
||||
|├── libscp ····· authorization library
|
||||
|└── tools ······ session management tools for sys admins
|
||||
├── tcutils ····· QT based utility program for thin clients
|
||||
├── tests ······· tests for the code
|
||||
├┬─ tools ······· tools
|
||||
|└┬─ devel ······ development tools
|
||||
| ├── gtcp_proxy GTK app that forwards TCP connections to a remote host
|
||||
| └── tcp_proxy · CLI app that forwards TCP connections to a remote host
|
||||
├── vnc ········· VNC client module for xrdp
|
||||
├── vrplayer ···· QT player redirecting video/audio to clients over xrdpvr channel
|
||||
├── xrdp ········ main server code
|
||||
|
||||
@ -14,6 +14,7 @@ include_HEADERS = \
|
||||
ms-rdpegdi.h \
|
||||
ms-rdpele.h \
|
||||
ms-rdperp.h \
|
||||
ms-rdpedisp.h \
|
||||
ms-smb2.h \
|
||||
xrdp_client_info.h \
|
||||
xrdp_constants.h \
|
||||
@ -32,7 +33,10 @@ if XRDP_DEBUG
|
||||
AM_CPPFLAGS += -DXRDP_DEBUG
|
||||
endif
|
||||
|
||||
AM_CFLAGS = $(OPENSSL_CFLAGS)
|
||||
# -no-suppress is an automake-specific flag which is needed
|
||||
# to prevent us missing compiler errors in some circumstances
|
||||
# (see https://github.com/neutrinolabs/xrdp/pull/1843 )
|
||||
AM_CFLAGS = -no-suppress $(OPENSSL_CFLAGS)
|
||||
|
||||
module_LTLIBRARIES = \
|
||||
libcommon.la
|
||||
|
||||
@ -64,7 +64,8 @@ typedef int bool_t;
|
||||
|
||||
#if !(defined(L_ENDIAN) || defined(B_ENDIAN))
|
||||
#if defined(__sparc__) || \
|
||||
defined(__hppa__) || \
|
||||
defined(__s390__) || defined (__s390x__) || \
|
||||
defined(__hppa__) || defined (__m68k__) || \
|
||||
(defined(__PPC__) && defined(__BIG_ENDIAN__)) || \
|
||||
(defined(__ppc__) && defined(__BIG_ENDIAN__))
|
||||
#define B_ENDIAN
|
||||
@ -77,14 +78,16 @@ typedef int bool_t;
|
||||
/* check if we need to align data */
|
||||
#if !(defined(NEED_ALIGN) || defined(NO_NEED_ALIGN))
|
||||
#if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \
|
||||
defined(__AIX__) || defined(__mips__) || \
|
||||
defined(__ia64__) || defined(__arm__) || \
|
||||
defined(__AIX__) || defined(__m68k__) || defined(__mips__) || \
|
||||
defined(__ia64__) || defined(__arm__) || defined(__sh__) || \
|
||||
(defined(__PPC__) && defined(__BIG_ENDIAN__)) || \
|
||||
(defined(__ppc__) && defined(__BIG_ENDIAN__))
|
||||
#define NEED_ALIGN
|
||||
#elif defined(__x86__) || defined(__x86_64__) || \
|
||||
defined(__AMD64__) || defined(_M_IX86) || defined (_M_AMD64) || \
|
||||
defined(__i386__) || defined(__aarch64__) || \
|
||||
defined(__PPC__) || defined(__LITTLE_ENDIAN__) || \
|
||||
defined(__s390__) || defined (__s390x__) || \
|
||||
defined(__riscv)
|
||||
#define NO_NEED_ALIGN
|
||||
#else
|
||||
@ -142,7 +145,7 @@ typedef int tsock;
|
||||
/* format string verification */
|
||||
#if defined(HAVE_FUNC_ATTRIBUTE_FORMAT)
|
||||
#define printflike(arg_format, arg_first_check) \
|
||||
__attribute__((__format__(__printf__, arg_format, arg_first_check)))
|
||||
__attribute__((__format__(__printf__, arg_format, arg_first_check)))
|
||||
#else
|
||||
#define printflike(arg_format, arg_first_check)
|
||||
#endif
|
||||
@ -151,8 +154,8 @@ typedef int tsock;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
tintptr mod_init(void);
|
||||
int mod_exit(tintptr);
|
||||
tintptr mod_init(void);
|
||||
int mod_exit(tintptr);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -67,7 +67,7 @@ base64_decode(char *dst, const char *src, size_t len)
|
||||
bio = BIO_new_mem_buf(b64str, len);
|
||||
bio = BIO_push(b64, bio);
|
||||
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
|
||||
decoded_bytes = BIO_read(bio , dst, len);
|
||||
decoded_bytes = BIO_read(bio, dst, len);
|
||||
BIO_free_all(bio);
|
||||
|
||||
/* if input is corrupt, return empty string */
|
||||
|
||||
@ -21,14 +21,6 @@
|
||||
#ifndef DEFINES_H
|
||||
#define DEFINES_H
|
||||
|
||||
/* check for debug */
|
||||
#ifdef XRDP_DEBUG
|
||||
#define DEBUG(args) g_writeln args;
|
||||
#define LIB_DEBUG(_mod, _text) _mod->server_msg(_mod, _text, 1);
|
||||
#else
|
||||
#define DEBUG(args)
|
||||
#define LIB_DEBUG(_mod, _text)
|
||||
#endif
|
||||
/* other macros */
|
||||
#undef MIN
|
||||
#define MIN(x1, x2) ((x1) < (x2) ? (x1) : (x2))
|
||||
@ -44,25 +36,25 @@
|
||||
|
||||
/* graphics macros */
|
||||
#define MAKERECT(r, x, y, cx, cy) \
|
||||
{ (r).left = x; (r).top = y; (r).right = (x) + (cx); (r).bottom = (y) + (cy); }
|
||||
{ (r).left = x; (r).top = y; (r).right = (x) + (cx); (r).bottom = (y) + (cy); }
|
||||
#define ISRECTEMPTY(r) (((r).right <= (r).left) || ((r).bottom <= (r).top))
|
||||
#define RECTOFFSET(r, dx, dy) \
|
||||
{ (r).left += dx; (r).top += dy; (r).right += dx; (r).bottom += dy; }
|
||||
{ (r).left += dx; (r).top += dy; (r).right += dx; (r).bottom += dy; }
|
||||
#define GETPIXEL8(d, x, y, w) (*(((unsigned char*)d) + ((y) * (w) + (x))))
|
||||
#define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x))))
|
||||
#define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x))))
|
||||
#define SETPIXEL8(d, x, y, w, v) \
|
||||
(*(((unsigned char*)d) + ((y) * (w) + (x))) = (v))
|
||||
(*(((unsigned char*)d) + ((y) * (w) + (x))) = (v))
|
||||
#define SETPIXEL16(d, x, y, w, v) \
|
||||
(*(((unsigned short*)d) + ((y) * (w) + (x))) = (v))
|
||||
(*(((unsigned short*)d) + ((y) * (w) + (x))) = (v))
|
||||
#define SETPIXEL32(d, x, y, w, v) \
|
||||
(*(((unsigned int*)d) + ((y) * (w) + (x))) = (v))
|
||||
(*(((unsigned int*)d) + ((y) * (w) + (x))) = (v))
|
||||
#define COLOR8(r, g, b) \
|
||||
( \
|
||||
(((r) >> 5) << 0) | \
|
||||
(((g) >> 5) << 3) | \
|
||||
(((b) >> 6) << 6) \
|
||||
)
|
||||
( \
|
||||
(((r) >> 5) << 0) | \
|
||||
(((g) >> 5) << 3) | \
|
||||
(((b) >> 6) << 6) \
|
||||
)
|
||||
#define COLOR15(r, g, b) ((((r) >> 3) << 10) | (((g) >> 3) << 5) | ((b) >> 3))
|
||||
#define COLOR16(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
|
||||
#define COLOR24RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b))
|
||||
@ -71,43 +63,43 @@
|
||||
#define HGREEN(c) ((c & 0x00ff00) >> 8)
|
||||
#define HBLUE(c) ((c & 0x0000ff))
|
||||
#define HCOLOR(bpp,c) \
|
||||
( \
|
||||
(bpp==8?COLOR8(HRED(c),HGREEN(c),HBLUE(c)): \
|
||||
(bpp==15?COLOR15(HRED(c),HGREEN(c),HBLUE(c)): \
|
||||
(bpp==16?COLOR16(HRED(c),HGREEN(c),HBLUE(c)): \
|
||||
(bpp>=24?COLOR24BGR(HRED(c),HGREEN(c),HBLUE(c)):c) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
( \
|
||||
(bpp==8?COLOR8(HRED(c),HGREEN(c),HBLUE(c)): \
|
||||
(bpp==15?COLOR15(HRED(c),HGREEN(c),HBLUE(c)): \
|
||||
(bpp==16?COLOR16(HRED(c),HGREEN(c),HBLUE(c)): \
|
||||
(bpp>=24?COLOR24BGR(HRED(c),HGREEN(c),HBLUE(c)):c) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
#define SPLITCOLOR15(r, g, b, c) \
|
||||
{ \
|
||||
r = (((c) >> 7) & 0xf8) | (((c) >> 12) & 0x7); \
|
||||
g = (((c) >> 2) & 0xf8) | (((c) >> 8) & 0x7); \
|
||||
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
|
||||
}
|
||||
{ \
|
||||
r = (((c) >> 7) & 0xf8) | (((c) >> 12) & 0x7); \
|
||||
g = (((c) >> 2) & 0xf8) | (((c) >> 8) & 0x7); \
|
||||
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
|
||||
}
|
||||
#define SPLITCOLOR16(r, g, b, c) \
|
||||
{ \
|
||||
r = (((c) >> 8) & 0xf8) | (((c) >> 13) & 0x7); \
|
||||
g = (((c) >> 3) & 0xfc) | (((c) >> 9) & 0x3); \
|
||||
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
|
||||
}
|
||||
{ \
|
||||
r = (((c) >> 8) & 0xf8) | (((c) >> 13) & 0x7); \
|
||||
g = (((c) >> 3) & 0xfc) | (((c) >> 9) & 0x3); \
|
||||
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
|
||||
}
|
||||
#define SPLITCOLOR32(r, g, b, c) \
|
||||
{ \
|
||||
r = ((c) >> 16) & 0xff; \
|
||||
g = ((c) >> 8) & 0xff; \
|
||||
b = (c) & 0xff; \
|
||||
}
|
||||
{ \
|
||||
r = ((c) >> 16) & 0xff; \
|
||||
g = ((c) >> 8) & 0xff; \
|
||||
b = (c) & 0xff; \
|
||||
}
|
||||
/* font macros */
|
||||
#define FONT_DATASIZE(f) \
|
||||
((((f)->height * (((f)->width + 7) / 8)) + 3) & ~3);
|
||||
((((f)->height * (((f)->width + 7) / 8)) + 3) & ~3);
|
||||
/* use crc for bitmap cache lookups */
|
||||
#define USE_CRC
|
||||
|
||||
#define XR_RGB2BGR(a_ulColor) \
|
||||
(a_ulColor & 0xFF000000) | \
|
||||
((a_ulColor & 0x00FF0000) >> 16) | \
|
||||
(a_ulColor & 0x0000FF00) | \
|
||||
((a_ulColor & 0x000000FF) << 16)
|
||||
(a_ulColor & 0xFF000000) | \
|
||||
((a_ulColor & 0x00FF0000) >> 16) | \
|
||||
(a_ulColor & 0x0000FF00) | \
|
||||
((a_ulColor & 0x000000FF) << 16)
|
||||
|
||||
#endif
|
||||
|
||||
@ -47,20 +47,24 @@ fifo_delete(FIFO *self)
|
||||
USER_DATA *udp;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->head)
|
||||
{
|
||||
/* FIFO is empty */
|
||||
g_free(self);
|
||||
return;
|
||||
}
|
||||
if (!self->head)
|
||||
{
|
||||
/* FIFO is empty */
|
||||
g_free(self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->head == self->tail)
|
||||
{
|
||||
/* only one item in FIFO */
|
||||
if (self->auto_free)
|
||||
{
|
||||
g_free(self->head->item);
|
||||
}
|
||||
|
||||
g_free(self->head);
|
||||
g_free(self);
|
||||
@ -73,7 +77,9 @@ fifo_delete(FIFO *self)
|
||||
udp = self->head;
|
||||
|
||||
if (self->auto_free)
|
||||
{
|
||||
g_free(udp->item);
|
||||
}
|
||||
|
||||
self->head = udp->next;
|
||||
g_free(udp);
|
||||
@ -97,10 +103,14 @@ fifo_add_item(FIFO *self, void *item)
|
||||
USER_DATA *udp;
|
||||
|
||||
if (!self || !item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((udp = (USER_DATA *) g_malloc(sizeof(USER_DATA), 0)) == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
udp->item = item;
|
||||
udp->next = 0;
|
||||
@ -135,7 +145,9 @@ fifo_remove_item(FIFO *self)
|
||||
USER_DATA *udp;
|
||||
|
||||
if (!self || !self->head)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->head == self->tail)
|
||||
{
|
||||
@ -167,7 +179,9 @@ int
|
||||
fifo_is_empty(FIFO *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (self->head == 0);
|
||||
}
|
||||
|
||||
@ -38,10 +38,10 @@ typedef struct fifo
|
||||
int auto_free;
|
||||
} FIFO;
|
||||
|
||||
FIFO * fifo_create(void);
|
||||
FIFO *fifo_create(void);
|
||||
void fifo_delete(FIFO *self);
|
||||
int fifo_add_item(FIFO *self, void *item);
|
||||
void * fifo_remove_item(FIFO *self);
|
||||
void *fifo_remove_item(FIFO *self);
|
||||
int fifo_is_empty(FIFO *self);
|
||||
|
||||
#endif
|
||||
|
||||
@ -24,14 +24,14 @@
|
||||
#include "arch.h"
|
||||
|
||||
int
|
||||
file_read_sections(int fd, struct list* names);
|
||||
file_read_sections(int fd, struct list *names);
|
||||
int
|
||||
file_by_name_read_sections(const char* file_name, struct list* names);
|
||||
file_by_name_read_sections(const char *file_name, struct list *names);
|
||||
int
|
||||
file_read_section(int fd, const char* section,
|
||||
struct list* names, struct list* values);
|
||||
file_read_section(int fd, const char *section,
|
||||
struct list *names, struct list *values);
|
||||
int
|
||||
file_by_name_read_section(const char* file_name, const char* section,
|
||||
struct list* names, struct list* values);
|
||||
file_by_name_read_section(const char *file_name, const char *section,
|
||||
struct list *names, struct list *values);
|
||||
|
||||
#endif
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct list *
|
||||
@ -221,11 +222,11 @@ list_dump_items(struct list *self)
|
||||
|
||||
if (self->count == 0)
|
||||
{
|
||||
g_writeln("List is empty");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "List is empty");
|
||||
}
|
||||
|
||||
for (index = 0; index < self->count; index++)
|
||||
{
|
||||
g_writeln("%d: %p", index, (void *) list_get_item(self, index));
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "%d: %p", index, (void *) list_get_item(self, index));
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,32 +26,32 @@
|
||||
/* list */
|
||||
struct list
|
||||
{
|
||||
tintptr* items;
|
||||
tintptr *items;
|
||||
int count;
|
||||
int alloc_size;
|
||||
int grow_by;
|
||||
int auto_free;
|
||||
};
|
||||
|
||||
struct list*
|
||||
struct list *
|
||||
list_create(void);
|
||||
void
|
||||
list_delete(struct list* self);
|
||||
list_delete(struct list *self);
|
||||
void
|
||||
list_add_item(struct list* self, tintptr item);
|
||||
list_add_item(struct list *self, tintptr item);
|
||||
tintptr
|
||||
list_get_item(const struct list *self, int index);
|
||||
void
|
||||
list_clear(struct list* self);
|
||||
list_clear(struct list *self);
|
||||
int
|
||||
list_index_of(struct list* self, tintptr item);
|
||||
list_index_of(struct list *self, tintptr item);
|
||||
void
|
||||
list_remove_item(struct list* self, int index);
|
||||
list_remove_item(struct list *self, int index);
|
||||
void
|
||||
list_insert_item(struct list* self, int index, tintptr item);
|
||||
list_insert_item(struct list *self, int index, tintptr item);
|
||||
void
|
||||
list_append_list_strdup(struct list* self, struct list* dest, int start_index);
|
||||
list_append_list_strdup(struct list *self, struct list *dest, int start_index);
|
||||
void
|
||||
list_dump_items(struct list* self);
|
||||
list_dump_items(struct list *self);
|
||||
|
||||
#endif
|
||||
|
||||
@ -52,7 +52,7 @@ list16_delete(struct list16 *self)
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
list16_init(struct list16* self)
|
||||
list16_init(struct list16 *self)
|
||||
{
|
||||
g_memset(self, 0, sizeof(struct list16));
|
||||
self->max_count = 4;
|
||||
@ -61,7 +61,7 @@ list16_init(struct list16* self)
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
list16_deinit(struct list16* self)
|
||||
list16_deinit(struct list16 *self)
|
||||
{
|
||||
if (self->items != self->mitems)
|
||||
{
|
||||
|
||||
@ -26,31 +26,31 @@
|
||||
/* list */
|
||||
struct list16
|
||||
{
|
||||
tui16* items;
|
||||
int count;
|
||||
int max_count;
|
||||
tui16 mitems[4];
|
||||
tui16 *items;
|
||||
int count;
|
||||
int max_count;
|
||||
tui16 mitems[4];
|
||||
};
|
||||
|
||||
struct list16*
|
||||
struct list16 *
|
||||
list16_create(void);
|
||||
void
|
||||
list16_delete(struct list16* self);
|
||||
list16_delete(struct list16 *self);
|
||||
void
|
||||
list16_init(struct list16* self);
|
||||
list16_init(struct list16 *self);
|
||||
void
|
||||
list16_deinit(struct list16* self);
|
||||
list16_deinit(struct list16 *self);
|
||||
void
|
||||
list16_add_item(struct list16* self, tui16 item);
|
||||
list16_add_item(struct list16 *self, tui16 item);
|
||||
tui16
|
||||
list16_get_item(struct list16* self, int index);
|
||||
list16_get_item(struct list16 *self, int index);
|
||||
void
|
||||
list16_clear(struct list16* self);
|
||||
list16_clear(struct list16 *self);
|
||||
int
|
||||
list16_index_of(struct list16* self, tui16 item);
|
||||
list16_index_of(struct list16 *self, tui16 item);
|
||||
void
|
||||
list16_remove_item(struct list16* self, int index);
|
||||
list16_remove_item(struct list16 *self, int index);
|
||||
void
|
||||
list16_insert_item(struct list16* self, int index, tui16 item);
|
||||
list16_insert_item(struct list16 *self, int index, tui16 item);
|
||||
|
||||
#endif
|
||||
|
||||
159
common/log.c
159
common/log.c
@ -304,7 +304,7 @@ internal_config_read_logging(int file,
|
||||
lc->console_level = LOG_LEVEL_INFO;
|
||||
lc->enable_syslog = 0;
|
||||
lc->syslog_level = LOG_LEVEL_INFO;
|
||||
lc->dump_on_start = 1;
|
||||
lc->dump_on_start = 0;
|
||||
lc->enable_pid = 0;
|
||||
|
||||
g_snprintf(section_name, 511, "%s%s", section_prefix, SESMAN_CFG_LOGGING);
|
||||
@ -616,7 +616,6 @@ log_config_init_for_console(enum logLevels lvl, const char *override_name)
|
||||
{
|
||||
config->console_level = lvl;
|
||||
}
|
||||
config->dump_on_start = 0; /* Don't need dump for console only */
|
||||
}
|
||||
return config;
|
||||
}
|
||||
@ -721,7 +720,8 @@ log_start_from_param(const struct log_config *src_log_config)
|
||||
* @return 0 on success
|
||||
*/
|
||||
enum logReturns
|
||||
log_start(const char *iniFile, const char *applicationName)
|
||||
log_start(const char *iniFile, const char *applicationName,
|
||||
bool_t dump_on_start)
|
||||
{
|
||||
enum logReturns ret = LOG_GENERAL_ERROR;
|
||||
struct log_config *config;
|
||||
@ -730,6 +730,7 @@ log_start(const char *iniFile, const char *applicationName)
|
||||
|
||||
if (config != NULL)
|
||||
{
|
||||
config->dump_on_start = dump_on_start;
|
||||
ret = log_start_from_param(config);
|
||||
log_config_free(config);
|
||||
|
||||
@ -763,7 +764,18 @@ log_end(void)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* produce a hex dump */
|
||||
/* log a hex dump */
|
||||
enum logReturns
|
||||
log_hexdump(const enum logLevels log_level,
|
||||
const char *message,
|
||||
const char *src,
|
||||
int len)
|
||||
{
|
||||
return log_hexdump_with_location("", "", 0, log_level, message, src, len);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* log a hex dump */
|
||||
enum logReturns
|
||||
log_hexdump_with_location(const char *function_name,
|
||||
const char *file_name,
|
||||
@ -773,38 +785,11 @@ log_hexdump_with_location(const char *function_name,
|
||||
const char *src,
|
||||
int len)
|
||||
{
|
||||
unsigned char *line;
|
||||
int i;
|
||||
int dump_number_lines;
|
||||
int dump_line_length;
|
||||
int dump_length;
|
||||
int dump_offset;
|
||||
int thisline;
|
||||
int offset;
|
||||
char *dump_buffer;
|
||||
enum logReturns rv;
|
||||
enum logReturns rv = LOG_STARTUP_OK;
|
||||
enum logLevels override_log_level;
|
||||
bool_t override_destination_level = 0;
|
||||
|
||||
/* Start the dump on a new line so that the first line of the dump is
|
||||
aligned to the first column instead of to after the log message
|
||||
preamble (eg. time, log level, ...)
|
||||
*/
|
||||
#define HEX_DUMP_SOURCE_BYTES_PER_LINE (16)
|
||||
#ifdef _WIN32
|
||||
#define HEX_DUMP_HEADER ("%s Hex Dump:\r\n")
|
||||
#define HEX_DUMP_NEWLINE_SIZE (2)
|
||||
#else
|
||||
#ifdef _MACOS
|
||||
#define HEX_DUMP_HEADER ("%s Hex Dump:\r")
|
||||
#define HEX_DUMP_NEWLINE_SIZE (1)
|
||||
#else
|
||||
#define HEX_DUMP_HEADER ("%s Hex Dump:\n")
|
||||
#define HEX_DUMP_NEWLINE_SIZE (1)
|
||||
#endif
|
||||
#endif
|
||||
#define HEX_DUMP_HEADER_SIZE (sizeof(HEX_DUMP_HEADER) - 1)
|
||||
|
||||
override_destination_level = internal_log_location_overrides_level(
|
||||
function_name,
|
||||
file_name,
|
||||
@ -814,107 +799,37 @@ log_hexdump_with_location(const char *function_name,
|
||||
return LOG_STARTUP_OK;
|
||||
}
|
||||
|
||||
dump_line_length = (4 + 3 /* = 4 offset + 3 space */
|
||||
+ ((2 + 1) * HEX_DUMP_SOURCE_BYTES_PER_LINE) /* + (2 hex char + 1 space) per source byte */
|
||||
+ 2 /* + 2 space */
|
||||
+ HEX_DUMP_SOURCE_BYTES_PER_LINE
|
||||
+ HEX_DUMP_NEWLINE_SIZE);
|
||||
|
||||
dump_number_lines = (len / HEX_DUMP_SOURCE_BYTES_PER_LINE) + 1; /* +1 to round up */
|
||||
dump_length = (dump_number_lines *dump_line_length /* hex dump lines */
|
||||
+ HEX_DUMP_HEADER_SIZE
|
||||
+ 1); /* terminating NULL */
|
||||
dump_buffer = (char *)g_malloc(dump_length, 1);
|
||||
if (dump_buffer == NULL)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
||||
"Failed to allocate buffer for hex dump of size %d",
|
||||
dump_length);
|
||||
return LOG_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
line = (unsigned char *)src;
|
||||
offset = 0;
|
||||
|
||||
g_memcpy(dump_buffer, HEX_DUMP_HEADER, HEX_DUMP_HEADER_SIZE);
|
||||
dump_offset = HEX_DUMP_HEADER_SIZE;
|
||||
|
||||
while (offset < len)
|
||||
{
|
||||
g_sprintf(dump_buffer + dump_offset, "%04x ", offset);
|
||||
dump_offset += 7;
|
||||
thisline = len - offset;
|
||||
|
||||
if (thisline > HEX_DUMP_SOURCE_BYTES_PER_LINE)
|
||||
{
|
||||
thisline = HEX_DUMP_SOURCE_BYTES_PER_LINE;
|
||||
}
|
||||
|
||||
for (i = 0; i < thisline; i++)
|
||||
{
|
||||
g_sprintf(dump_buffer + dump_offset, "%02x ", line[i]);
|
||||
dump_offset += 3;
|
||||
}
|
||||
|
||||
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
|
||||
{
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
}
|
||||
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
|
||||
for (i = 0; i < thisline; i++)
|
||||
{
|
||||
dump_buffer[dump_offset++] = (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.';
|
||||
}
|
||||
|
||||
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
|
||||
{
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
}
|
||||
|
||||
/* Start the dump on a new line so that the first line of the dump is
|
||||
aligned to the first column instead of to after the log message
|
||||
preamble (eg. time, log level, ...)
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
dump_buffer[dump_offset++] = '\r';
|
||||
dump_buffer[dump_offset++] = '\n';
|
||||
#define HEX_DUMP_HEADER ("Hex Dump:\r\n")
|
||||
#else
|
||||
#ifdef _MACOS
|
||||
dump_buffer[dump_offset++] = '\r';
|
||||
#define HEX_DUMP_HEADER ("Hex Dump:\r")
|
||||
#else
|
||||
dump_buffer[dump_offset++] = '\n';
|
||||
#define HEX_DUMP_HEADER ("Hex Dump:\n")
|
||||
#endif
|
||||
#endif
|
||||
offset += thisline;
|
||||
line += thisline;
|
||||
|
||||
dump_buffer = g_bytes_to_hexdump(src, len);
|
||||
|
||||
if ((dump_offset - HEX_DUMP_HEADER_SIZE) % dump_line_length != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"BUG: dump_offset (%d) at the end of a line is not a "
|
||||
"multiple of the line length (%d)",
|
||||
dump_offset, dump_line_length);
|
||||
}
|
||||
|
||||
}
|
||||
if (dump_offset > dump_length)
|
||||
if (dump_buffer != NULL)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"BUG: dump_offset (%d) is larger than the dump_buffer length (%d)",
|
||||
dump_offset, dump_length);
|
||||
if (g_strlen(file_name) > 0)
|
||||
{
|
||||
rv = log_message_with_location(function_name, file_name, line_number,
|
||||
log_level, "%s %s%s",
|
||||
message, HEX_DUMP_HEADER, dump_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = log_message(log_level, "%s %s%s",
|
||||
message, HEX_DUMP_HEADER, dump_buffer);
|
||||
}
|
||||
g_free(dump_buffer);
|
||||
return LOG_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* replace the last new line with the end of the string since log_message
|
||||
will add a new line */
|
||||
dump_buffer[dump_offset - HEX_DUMP_NEWLINE_SIZE] = '\0';
|
||||
|
||||
rv = log_message_with_location(function_name, file_name, line_number,
|
||||
log_level, dump_buffer, message);
|
||||
g_free(dump_buffer);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
46
common/log.h
46
common/log.h
@ -22,6 +22,7 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include "arch.h"
|
||||
#include "defines.h"
|
||||
#include "list.h"
|
||||
|
||||
/* logging buffer size */
|
||||
@ -95,7 +96,7 @@ enum logReturns
|
||||
* @param ... the arguments for the printf format c-string
|
||||
*/
|
||||
#define LOG_DEVEL(log_level, args...) \
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args);
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
|
||||
|
||||
/**
|
||||
* @brief Logging macro for messages that are for a systeam administrator to
|
||||
@ -109,7 +110,7 @@ enum logReturns
|
||||
* @param ... the arguments for the printf format c-string
|
||||
*/
|
||||
#define LOG(log_level, args...) \
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args);
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
|
||||
|
||||
/**
|
||||
* @brief Logging macro for logging the contents of a byte array using a hex
|
||||
@ -124,12 +125,31 @@ enum logReturns
|
||||
* @param length, the length of the byte array to log
|
||||
*/
|
||||
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) \
|
||||
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length);
|
||||
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
|
||||
|
||||
/**
|
||||
* @brief Logging macro for logging the contents of a byte array using a hex
|
||||
* dump format.
|
||||
*
|
||||
* @param log_level, the log level
|
||||
* @param message, a message prefix for the hex dump. Note: no printf like
|
||||
* formatting is done to this message.
|
||||
* @param buffer, a pointer to the byte array to log as a hex dump
|
||||
* @param length, the length of the byte array to log
|
||||
*/
|
||||
#define LOG_HEXDUMP(log_level, message, buffer, length) \
|
||||
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
|
||||
|
||||
#else
|
||||
#define LOG_DEVEL(log_level, args...)
|
||||
#define LOG(log_level, args...) log_message(log_level, args);
|
||||
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length)
|
||||
#define LOG(log_level, args...) log_message(log_level, args)
|
||||
#define LOG_HEXDUMP(log_level, message, buffer, length) \
|
||||
log_hexdump(log_level, message, buffer, length)
|
||||
|
||||
/* Since log_message() returns a value ensure that the elided versions of
|
||||
* LOG_DEVEL and LOG_DEVEL_HEXDUMP also "fake" returning the success value
|
||||
*/
|
||||
#define LOG_DEVEL(log_level, args...) UNUSED_VAR(LOG_STARTUP_OK)
|
||||
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) UNUSED_VAR(LOG_STARTUP_OK)
|
||||
|
||||
#endif
|
||||
|
||||
@ -263,11 +283,15 @@ internal_log_location_overrides_level(const char *function_name,
|
||||
* This function initialize the log facilities according to the configuration
|
||||
* file, that is described by the in parameter.
|
||||
* @param iniFile
|
||||
* @param applicationName, the name that is used in the log for the running application
|
||||
* @param applicationName the name that is used in the log for the running
|
||||
* application
|
||||
* @param dump_on_start Whether to dump the config on stdout before
|
||||
* logging is started
|
||||
* @return LOG_STARTUP_OK on success
|
||||
*/
|
||||
enum logReturns
|
||||
log_start(const char *iniFile, const char *applicationName);
|
||||
log_start(const char *iniFile, const char *applicationName,
|
||||
bool_t dump_on_start);
|
||||
|
||||
/**
|
||||
* An alternative log_start where the caller gives the params directly.
|
||||
@ -336,6 +360,12 @@ log_end(void);
|
||||
enum logReturns
|
||||
log_message(const enum logLevels lvl, const char *msg, ...) printflike(2, 3);
|
||||
|
||||
enum logReturns
|
||||
log_hexdump(const enum logLevels log_level,
|
||||
const char *msg,
|
||||
const char *p,
|
||||
int len);
|
||||
|
||||
/**
|
||||
* the log function that all files use to log an event,
|
||||
* with the function name and file line.
|
||||
|
||||
@ -78,7 +78,12 @@
|
||||
/* This isn't explicitly named in MS-RDPBCGR */
|
||||
#define CHANNEL_NAME_LEN 7
|
||||
|
||||
/* Oprions field */
|
||||
/* 2.2.1.3.6 Client Monitor Data - */
|
||||
/* monitorCount (4 bytes): A 32-bit, unsigned integer. The number of display */
|
||||
/* monitor definitions in the monitorDefArray field (the maximum allowed is 16). */
|
||||
#define CLIENT_MONITOR_DATA_MAXIMUM_MONITORS 16
|
||||
|
||||
/* Options field */
|
||||
/* NOTE: XR_ prefixed to avoid conflict with FreeRDP */
|
||||
#define XR_CHANNEL_OPTION_INITIALIZED 0x80000000
|
||||
#define XR_CHANNEL_OPTION_ENCRYPT_RDP 0x40000000
|
||||
@ -282,16 +287,16 @@
|
||||
#define TS_NEG_SCRBLT_INDEX 0x02
|
||||
#define TS_NEG_MEMBLT_INDEX 0x03
|
||||
#define TS_NEG_MEM3BLT_INDEX 0x04
|
||||
/* 0x05 */
|
||||
/* 0x06 */
|
||||
/* 0x05 */
|
||||
/* 0x06 */
|
||||
#define TS_NEG_DRAWNINEGRID_INDEX 0x07
|
||||
#define TS_NEG_LINETO_INDEX 0x08
|
||||
#define TS_NEG_MULTI_DRAWNINEGRID_INDEX 0x09
|
||||
/* 0x0A */
|
||||
/* 0x0A */
|
||||
#define TS_NEG_SAVEBITMAP_INDEX 0x0B
|
||||
/* 0x0C */
|
||||
/* 0x0D */
|
||||
/* 0x0E */
|
||||
/* 0x0C */
|
||||
/* 0x0D */
|
||||
/* 0x0E */
|
||||
#define TS_NEG_MULTIDSTBLT_INDEX 0x0F
|
||||
#define TS_NEG_MULTIPATBLT_INDEX 0x10
|
||||
#define TS_NEG_MULTISCRBLT_INDEX 0x11
|
||||
@ -300,15 +305,15 @@
|
||||
#define TS_NEG_POLYGON_SC_INDEX 0x14
|
||||
#define TS_NEG_POLYGON_CB_INDEX 0x15
|
||||
#define TS_NEG_POLYLINE_INDEX 0x16
|
||||
/* 0x17 */
|
||||
/* 0x17 */
|
||||
#define TS_NEG_FAST_GLYPH_INDEX 0x18
|
||||
#define TS_NEG_ELLIPSE_SC_INDEX 0x19
|
||||
#define TS_NEG_ELLIPSE_CB_INDEX 0x1A
|
||||
#define TS_NEG_INDEX_INDEX 0x1B
|
||||
/* 0x1C */
|
||||
/* 0x1D */
|
||||
/* 0x1E */
|
||||
/* 0x1F */
|
||||
/* 0x1C */
|
||||
/* 0x1D */
|
||||
/* 0x1E */
|
||||
/* 0x1F */
|
||||
|
||||
/* Input Capability Set: inputFlags (2.2.7.1.6) */
|
||||
#define INPUT_FLAG_SCANCODES 0x0001
|
||||
@ -340,27 +345,27 @@
|
||||
|
||||
/* CODEC_GUID_NSCODEC CA8D1BB9-000F-154F-589FAE2D1A87E2D6 */
|
||||
#define XR_CODEC_GUID_NSCODEC \
|
||||
"\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6"
|
||||
"\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6"
|
||||
|
||||
/* CODEC_GUID_REMOTEFX 76772F12-BD72-4463-AFB3B73C9C6F7886 */
|
||||
#define XR_CODEC_GUID_REMOTEFX \
|
||||
"\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86"
|
||||
"\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86"
|
||||
|
||||
/* CODEC_GUID_IMAGE_REMOTEFX 2744CCD4-9D8A-4E74-803C-0ECBEEA19C54 */
|
||||
#define XR_CODEC_GUID_IMAGE_REMOTEFX \
|
||||
"\xD4\xCC\x44\x27\x8A\x9D\x74\x4E\x80\x3C\x0E\xCB\xEE\xA1\x9C\x54"
|
||||
"\xD4\xCC\x44\x27\x8A\x9D\x74\x4E\x80\x3C\x0E\xCB\xEE\xA1\x9C\x54"
|
||||
|
||||
/* MFVideoFormat_H264 0x34363248-0000-0010-800000AA00389B71 */
|
||||
#define XR_CODEC_GUID_H264 \
|
||||
"\x48\x32\x36\x34\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
|
||||
"\x48\x32\x36\x34\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
|
||||
|
||||
/* CODEC_GUID_JPEG 1BAF4CE6-9EED-430C-869ACB8B37B66237 */
|
||||
#define XR_CODEC_GUID_JPEG \
|
||||
"\xE6\x4C\xAF\x1B\xED\x9E\x0C\x43\x86\x9A\xCB\x8B\x37\xB6\x62\x37"
|
||||
"\xE6\x4C\xAF\x1B\xED\x9E\x0C\x43\x86\x9A\xCB\x8B\x37\xB6\x62\x37"
|
||||
|
||||
/* CODEC_GUID_PNG 0E0C858D-28E0-45DB-ADAA0F83E57CC560 */
|
||||
#define XR_CODEC_GUID_PNG \
|
||||
"\x8D\x85\x0C\x0E\xE0\x28\xDB\x45\xAD\xAA\x0F\x83\xE5\x7C\xC5\x60"
|
||||
"\x8D\x85\x0C\x0E\xE0\x28\xDB\x45\xAD\xAA\x0F\x83\xE5\x7C\xC5\x60"
|
||||
|
||||
/* PDU Types (2.2.8.1.1.1.1) */
|
||||
#define PDUTYPE_DEMANDACTIVEPDU 0x1
|
||||
@ -369,6 +374,15 @@
|
||||
#define PDUTYPE_DATAPDU 0x7
|
||||
#define PDUTYPE_SERVER_REDIR_PKT 0xA
|
||||
|
||||
#define PDUTYPE_TO_STR(pdu_type) \
|
||||
((pdu_type) == PDUTYPE_DEMANDACTIVEPDU ? "PDUTYPE_DEMANDACTIVEPDU" : \
|
||||
(pdu_type) == PDUTYPE_CONFIRMACTIVEPDU ? "PDUTYPE_CONFIRMACTIVEPDU" : \
|
||||
(pdu_type) == PDUTYPE_DEACTIVATEALLPDU ? "PDUTYPE_DEACTIVATEALLPDU" : \
|
||||
(pdu_type) == PDUTYPE_DATAPDU ? "PDUTYPE_DATAPDU" : \
|
||||
(pdu_type) == PDUTYPE_SERVER_REDIR_PKT ? "PDUTYPE_SERVER_REDIR_PKT" : \
|
||||
"unknown" \
|
||||
)
|
||||
|
||||
/* Share Data Header: pduType2 (2.2.8.1.1.1.2) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP_DATA_PDU_UPDATE 2 /* PDUTYPE2_UPDATE */
|
||||
@ -378,6 +392,9 @@
|
||||
#define RDP_DATA_PDU_SYNCHRONISE 31
|
||||
#define PDUTYPE2_REFRESH_RECT 33
|
||||
#define RDP_DATA_PDU_PLAY_SOUND 34
|
||||
#define PDUTYPE2_SUPPRESS_OUTPUT 35
|
||||
#define PDUTYPE2_SHUTDOWN_REQUEST 36
|
||||
#define PDUTYPE2_SHUTDOWN_DENIED 37
|
||||
#define RDP_DATA_PDU_LOGON 38
|
||||
#define RDP_DATA_PDU_FONT2 39
|
||||
#define RDP_DATA_PDU_DISCONNECT 47
|
||||
@ -405,7 +422,7 @@
|
||||
|
||||
/* Keyboard Event: keyboardFlags (2.2.8.1.1.3.1.1.1) */
|
||||
/* TODO: to be renamed */
|
||||
#define KBD_FLAG_RIGHT 0x0001
|
||||
#define KBD_FLAG_RIGHT 0x0001
|
||||
#define KBD_FLAG_EXT 0x0100 /* KBDFLAGS_EXTENDED */
|
||||
#define KBD_FLAG_QUIET 0x1000
|
||||
#define KBD_FLAG_DOWN 0x4000
|
||||
@ -457,6 +474,14 @@
|
||||
#define RDP_UPDATE_PALETTE 2
|
||||
#define RDP_UPDATE_SYNCHRONIZE 3
|
||||
|
||||
#define GRAPHICS_UPDATE_TYPE_TO_STR(type) \
|
||||
((type) == RDP_UPDATE_ORDERS ? "RDP_UPDATE_ORDERS" : \
|
||||
(type) == RDP_UPDATE_BITMAP ? "RDP_UPDATE_BITMAP" : \
|
||||
(type) == RDP_UPDATE_PALETTE ? "RDP_UPDATE_PALETTE" : \
|
||||
(type) == RDP_UPDATE_SYNCHRONIZE ? "RDP_UPDATE_SYNCHRONIZE" : \
|
||||
"unknown" \
|
||||
)
|
||||
|
||||
/* Server Pointer Update PDU: messageType (2.2.9.1.1.4) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP_POINTER_SYSTEM 1 /* TS_PTRMSGTYPE_SYSTEM */
|
||||
|
||||
29
common/ms-rdpedisp.h
Normal file
29
common/ms-rdpedisp.h
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* MS-RDPEDISP : Definitions from [MS-RDPEDISP]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* References to MS-RDPEDISP are currently correct for v20201030 of that
|
||||
* document
|
||||
*/
|
||||
|
||||
#if !defined(MS_RDPEDISP_H)
|
||||
#define MS_RDPEDISP_H
|
||||
|
||||
/* Display Control Messages: Display Virtual Channel Extension (2.2.2) */
|
||||
#define DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002
|
||||
#define DISPLAYCONTROL_PDU_TYPE_CAPS 0x00000005
|
||||
|
||||
#endif /* MS_RDPEDISP_H */
|
||||
@ -121,9 +121,9 @@ g_mk_socket_path(const char *app_name)
|
||||
/* if failed, still check if it got created by someone else */
|
||||
if (!g_directory_exist(XRDP_SOCKET_PATH))
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR,
|
||||
"g_mk_socket_path: g_create_path(%s) failed",
|
||||
XRDP_SOCKET_PATH);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"g_mk_socket_path: g_create_path(%s) failed",
|
||||
XRDP_SOCKET_PATH);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -269,7 +269,7 @@ g_write(const char *format, ...)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* produce a hex dump */
|
||||
/* print a hex dump to stdout*/
|
||||
void
|
||||
g_hexdump(const char *p, int len)
|
||||
{
|
||||
@ -360,13 +360,13 @@ g_tcp_set_no_delay(int sck)
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("Error setting tcp_nodelay");
|
||||
LOG(LOG_LEVEL_ERROR, "Error setting tcp_nodelay");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("Error getting tcp_nodelay");
|
||||
LOG(LOG_LEVEL_ERROR, "Error getting tcp_nodelay");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -399,13 +399,13 @@ g_tcp_set_keepalive(int sck)
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("Error setting tcp_keepalive");
|
||||
LOG(LOG_LEVEL_ERROR, "Error setting tcp_keepalive");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("Error getting tcp_keepalive");
|
||||
LOG(LOG_LEVEL_ERROR, "Error getting tcp_keepalive");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -428,12 +428,12 @@ g_tcp_socket(void)
|
||||
switch (errno)
|
||||
{
|
||||
case EAFNOSUPPORT: /* if IPv6 not supported, retry IPv4 */
|
||||
log_message(LOG_LEVEL_INFO, "IPv6 not supported, falling back to IPv4");
|
||||
LOG(LOG_LEVEL_INFO, "IPv6 not supported, falling back to IPv4");
|
||||
rv = (int)socket(AF_INET, SOCK_STREAM, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -442,12 +442,12 @@ g_tcp_socket(void)
|
||||
#endif
|
||||
if (rv < 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
|
||||
return -1;
|
||||
}
|
||||
#if defined(XRDP_ENABLE_IPV6)
|
||||
option_len = sizeof(option_value);
|
||||
if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&option_value,
|
||||
if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&option_value,
|
||||
&option_len) == 0)
|
||||
{
|
||||
if (option_value != 0)
|
||||
@ -458,10 +458,10 @@ g_tcp_socket(void)
|
||||
option_value = 0;
|
||||
#endif
|
||||
option_len = sizeof(option_value);
|
||||
if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&option_value,
|
||||
option_len) < 0)
|
||||
if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&option_value,
|
||||
option_len) < 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -475,9 +475,9 @@ g_tcp_socket(void)
|
||||
option_value = 1;
|
||||
option_len = sizeof(option_value);
|
||||
if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
|
||||
option_len) < 0)
|
||||
option_len) < 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -492,9 +492,9 @@ g_tcp_socket(void)
|
||||
option_value = 1024 * 32;
|
||||
option_len = sizeof(option_value);
|
||||
if (setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
|
||||
option_len) < 0)
|
||||
option_len) < 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -638,9 +638,9 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid)
|
||||
|
||||
if (getsockopt(sck, SOL_SOCKET, LOCAL_PEERCRED, &xucred, &xucred_length))
|
||||
{
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
if (pid !=0)
|
||||
if (pid != 0)
|
||||
{
|
||||
*pid = 0; /* can't get pid in FreeBSD, OS X */
|
||||
}
|
||||
@ -648,7 +648,8 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid)
|
||||
{
|
||||
*uid = xucred.cr_uid;
|
||||
}
|
||||
if (gid != 0) {
|
||||
if (gid != 0)
|
||||
{
|
||||
*gid = xucred.cr_gid;
|
||||
}
|
||||
return 0;
|
||||
@ -738,8 +739,8 @@ g_sck_close(int sck)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_LEVEL_WARNING, "getsockname() failed on socket %d: %s",
|
||||
sck, g_get_strerror());
|
||||
LOG(LOG_LEVEL_WARNING, "getsockname() failed on socket %d: %s",
|
||||
sck, g_get_strerror());
|
||||
|
||||
if (errno == EBADF || errno == ENOTSOCK)
|
||||
{
|
||||
@ -751,12 +752,12 @@ g_sck_close(int sck)
|
||||
|
||||
if (close(sck) == 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_DEBUG, "Closed socket %d (%s)", sck, sockname);
|
||||
LOG(LOG_LEVEL_DEBUG, "Closed socket %d (%s)", sck, sockname);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_LEVEL_WARNING, "Cannot close socket %d (%s): %s", sck,
|
||||
sockname, g_get_strerror());
|
||||
LOG(LOG_LEVEL_WARNING, "Cannot close socket %d (%s): %s", sck,
|
||||
sockname, g_get_strerror());
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -777,7 +778,7 @@ connect_loopback(int sck, const char *port)
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_addr = in6addr_loopback; // IPv6 ::1
|
||||
sa.sin6_port = htons((tui16)atoi(port));
|
||||
res = connect(sck, (struct sockaddr*)&sa, sizeof(sa));
|
||||
res = connect(sck, (struct sockaddr *)&sa, sizeof(sa));
|
||||
if (res == -1 && errno == EINPROGRESS)
|
||||
{
|
||||
return -1;
|
||||
@ -792,7 +793,7 @@ connect_loopback(int sck, const char *port)
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // IPv4 127.0.0.1
|
||||
s.sin_port = htons((tui16)atoi(port));
|
||||
res = connect(sck, (struct sockaddr*)&s, sizeof(s));
|
||||
res = connect(sck, (struct sockaddr *)&s, sizeof(s));
|
||||
if (res == -1 && errno == EINPROGRESS)
|
||||
{
|
||||
return -1;
|
||||
@ -807,7 +808,7 @@ connect_loopback(int sck, const char *port)
|
||||
sa.sin6_family = AF_INET6;
|
||||
inet_pton(AF_INET6, "::FFFF:127.0.0.1", &sa.sin6_addr);
|
||||
sa.sin6_port = htons((tui16)atoi(port));
|
||||
res = connect(sck, (struct sockaddr*)&sa, sizeof(sa));
|
||||
res = connect(sck, (struct sockaddr *)&sa, sizeof(sa));
|
||||
if (res == -1 && errno == EINPROGRESS)
|
||||
{
|
||||
return -1;
|
||||
@ -850,8 +851,8 @@ g_tcp_connect(int sck, const char *address, const char *port)
|
||||
}
|
||||
if (res != 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_connect(%d, %s, %s): getaddrinfo() failed: %s",
|
||||
sck, address, port, gai_strerror(res));
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_connect(%d, %s, %s): getaddrinfo() failed: %s",
|
||||
sck, address, port, gai_strerror(res));
|
||||
}
|
||||
if (res > -1)
|
||||
{
|
||||
@ -879,10 +880,10 @@ g_tcp_connect(int sck, const char *address, const char *port)
|
||||
}
|
||||
#else
|
||||
int
|
||||
g_tcp_connect(int sck, const char* address, const char* port)
|
||||
g_tcp_connect(int sck, const char *address, const char *port)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
struct hostent* h;
|
||||
struct hostent *h;
|
||||
int res;
|
||||
|
||||
g_memset(&s, 0, sizeof(struct sockaddr_in));
|
||||
@ -900,13 +901,13 @@ g_tcp_connect(int sck, const char* address, const char* port)
|
||||
{
|
||||
if ((*(h->h_addr_list)) != 0)
|
||||
{
|
||||
s.sin_addr.s_addr = *((int*)(*(h->h_addr_list)));
|
||||
s.sin_addr.s_addr = *((int *)(*(h->h_addr_list)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res = connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
|
||||
res = connect(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_in));
|
||||
|
||||
/* Mac OSX connect() returns -1 for already established connections */
|
||||
if (res == -1 && errno == EISCONN)
|
||||
@ -951,7 +952,7 @@ g_sck_set_non_blocking(int sck)
|
||||
i = i | O_NONBLOCK;
|
||||
if (fcntl(sck, F_SETFL, i) < 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "g_sck_set_non_blocking: fcntl() failed");
|
||||
LOG(LOG_LEVEL_ERROR, "g_sck_set_non_blocking: fcntl() failed");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
@ -972,7 +973,7 @@ g_tcp_bind(int sck, const char *port)
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_addr = in6addr_any; // IPv6 ::
|
||||
sa.sin6_port = htons((tui16)atoi(port));
|
||||
if (bind(sck, (struct sockaddr*)&sa, sizeof(sa)) == 0)
|
||||
if (bind(sck, (struct sockaddr *)&sa, sizeof(sa)) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -983,19 +984,19 @@ g_tcp_bind(int sck, const char *port)
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_addr.s_addr = htonl(INADDR_ANY); // IPv4 0.0.0.0
|
||||
s.sin_port = htons((tui16)atoi(port));
|
||||
if (bind(sck, (struct sockaddr*)&s, sizeof(s)) == 0)
|
||||
if (bind(sck, (struct sockaddr *)&s, sizeof(s)) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_bind(%d, %s) failed "
|
||||
"bind IPv6 (errno=%d) and IPv4 (errno=%d).",
|
||||
sck, port, errno6, errno);
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_bind(%d, %s) failed "
|
||||
"bind IPv6 (errno=%d) and IPv4 (errno=%d).",
|
||||
sck, port, errno6, errno);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
int
|
||||
g_tcp_bind(int sck, const char* port)
|
||||
g_tcp_bind(int sck, const char *port)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
|
||||
@ -1003,7 +1004,7 @@ g_tcp_bind(int sck, const char* port)
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons((tui16)atoi(port));
|
||||
s.sin_addr.s_addr = INADDR_ANY;
|
||||
return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
|
||||
return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1078,7 +1079,7 @@ bind_loopback(int sck, const char *port)
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_addr = in6addr_loopback; // IPv6 ::1
|
||||
sa.sin6_port = htons((tui16)atoi(port));
|
||||
if (bind(sck, (struct sockaddr*)&sa, sizeof(sa)) == 0)
|
||||
if (bind(sck, (struct sockaddr *)&sa, sizeof(sa)) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -1089,7 +1090,7 @@ bind_loopback(int sck, const char *port)
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // IPv4 127.0.0.1
|
||||
s.sin_port = htons((tui16)atoi(port));
|
||||
if (bind(sck, (struct sockaddr*)&s, sizeof(s)) == 0)
|
||||
if (bind(sck, (struct sockaddr *)&s, sizeof(s)) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -1100,14 +1101,14 @@ bind_loopback(int sck, const char *port)
|
||||
sa.sin6_family = AF_INET6;
|
||||
inet_pton(AF_INET6, "::FFFF:127.0.0.1", &sa.sin6_addr);
|
||||
sa.sin6_port = htons((tui16)atoi(port));
|
||||
if (bind(sck, (struct sockaddr*)&sa, sizeof(sa)) == 0)
|
||||
if (bind(sck, (struct sockaddr *)&sa, sizeof(sa)) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_message(LOG_LEVEL_ERROR, "bind_loopback(%d, %s) failed; "
|
||||
"IPv6 ::1 (errno=%d), IPv4 127.0.0.1 (errno=%d) and IPv6 ::FFFF:127.0.0.1 (errno=%d).",
|
||||
sck, port, errno6, errno4, errno);
|
||||
LOG(LOG_LEVEL_ERROR, "bind_loopback(%d, %s) failed; "
|
||||
"IPv6 ::1 (errno=%d), IPv4 127.0.0.1 (errno=%d) and IPv6 ::FFFF:127.0.0.1 (errno=%d).",
|
||||
sck, port, errno6, errno4, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1142,7 +1143,7 @@ getaddrinfo_bind(int sck, const char *port, const char *address)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "getaddrinfo error: %s", gai_strerror(error));
|
||||
LOG(LOG_LEVEL_ERROR, "getaddrinfo error: %s", gai_strerror(error));
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
@ -1159,16 +1160,16 @@ g_tcp_bind_address(int sck, const char *port, const char *address)
|
||||
int res;
|
||||
|
||||
if ((address == 0) ||
|
||||
(address[0] == 0) ||
|
||||
(g_strcmp(address, "0.0.0.0") == 0) ||
|
||||
(g_strcmp(address, "::") == 0))
|
||||
(address[0] == 0) ||
|
||||
(g_strcmp(address, "0.0.0.0") == 0) ||
|
||||
(g_strcmp(address, "::") == 0))
|
||||
{
|
||||
return g_tcp_bind(sck, port);
|
||||
}
|
||||
|
||||
if ((g_strcmp(address, "127.0.0.1") == 0) ||
|
||||
(g_strcmp(address, "::1") == 0) ||
|
||||
(g_strcmp(address, "localhost") == 0))
|
||||
(g_strcmp(address, "::1") == 0) ||
|
||||
(g_strcmp(address, "localhost") == 0))
|
||||
{
|
||||
return bind_loopback(sck, port);
|
||||
}
|
||||
@ -1183,7 +1184,7 @@ g_tcp_bind_address(int sck, const char *port, const char *address)
|
||||
struct in_addr a;
|
||||
if ((inet_aton(address, &a) == 1) && (strlen(address) <= 15))
|
||||
{
|
||||
char sz[7+15+1];
|
||||
char sz[7 + 15 + 1];
|
||||
sprintf(sz, "::FFFF:%s", address);
|
||||
res = getaddrinfo_bind(sck, port, sz);
|
||||
if (res == 0)
|
||||
@ -1192,15 +1193,15 @@ g_tcp_bind_address(int sck, const char *port, const char *address)
|
||||
}
|
||||
}
|
||||
|
||||
log_message(LOG_LEVEL_ERROR, "g_tcp_bind_address(%d, %s, %s) Failed!",
|
||||
sck, port, address);
|
||||
LOG(LOG_LEVEL_ERROR, "g_tcp_bind_address(%d, %s, %s) Failed!",
|
||||
sck, port, address);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int
|
||||
g_tcp_bind_address(int sck, const char* port, const char* address)
|
||||
g_tcp_bind_address(int sck, const char *port, const char *address)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
|
||||
@ -1212,7 +1213,7 @@ g_tcp_bind_address(int sck, const char* port, const char* address)
|
||||
{
|
||||
return -1; /* bad address */
|
||||
}
|
||||
return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
|
||||
return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1246,7 +1247,7 @@ g_tcp_accept(int sck)
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
switch(sock_info.sock_addr.sa_family)
|
||||
switch (sock_info.sock_addr.sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
@ -1255,7 +1256,7 @@ g_tcp_accept(int sck)
|
||||
g_snprintf(msg, sizeof(msg), "A connection received from %s port %d",
|
||||
inet_ntoa(sock_addr_in->sin_addr),
|
||||
ntohs(sock_addr_in->sin_port));
|
||||
log_message(LOG_LEVEL_INFO, "%s", msg);
|
||||
LOG(LOG_LEVEL_INFO, "%s", msg);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1271,7 +1272,7 @@ g_tcp_accept(int sck)
|
||||
&sock_addr_in6->sin6_addr, addr, sizeof(addr));
|
||||
g_snprintf(msg, sizeof(msg), "A connection received from %s port %d",
|
||||
addr, ntohs(sock_addr_in6->sin6_port));
|
||||
log_message(LOG_LEVEL_INFO, "%s", msg);
|
||||
LOG(LOG_LEVEL_INFO, "%s", msg);
|
||||
|
||||
break;
|
||||
|
||||
@ -1310,7 +1311,7 @@ g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
switch(sock_info.sock_addr.sa_family)
|
||||
switch (sock_info.sock_addr.sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
@ -1380,7 +1381,7 @@ g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
|
||||
}
|
||||
|
||||
|
||||
log_message(LOG_LEVEL_INFO, "Socket %d: %s", ret, msg);
|
||||
LOG(LOG_LEVEL_INFO, "Socket %d: %s", ret, msg);
|
||||
|
||||
}
|
||||
|
||||
@ -1419,7 +1420,7 @@ g_write_ip_address(int rcv_sck, char *ip_address, int bytes)
|
||||
|
||||
if (getpeername(rcv_sck, (struct sockaddr *)&sock_info, &sock_len) == 0)
|
||||
{
|
||||
switch(sock_info.sock_addr.sa_family)
|
||||
switch (sock_info.sock_addr.sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
@ -1806,7 +1807,7 @@ g_set_wait_obj(tintptr obj)
|
||||
{
|
||||
error = errno;
|
||||
if ((error == EAGAIN) || (error == EWOULDBLOCK) ||
|
||||
(error == EINPROGRESS) || (error == EINTR))
|
||||
(error == EINPROGRESS) || (error == EINTR))
|
||||
{
|
||||
/* ok */
|
||||
}
|
||||
@ -1857,7 +1858,7 @@ g_reset_wait_obj(tintptr obj)
|
||||
{
|
||||
error = errno;
|
||||
if ((error == EAGAIN) || (error == EWOULDBLOCK) ||
|
||||
(error == EINPROGRESS) || (error == EINTR))
|
||||
(error == EINPROGRESS) || (error == EINTR))
|
||||
{
|
||||
/* ok */
|
||||
}
|
||||
@ -2008,7 +2009,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount,
|
||||
}
|
||||
else if (rcount > 0)
|
||||
{
|
||||
g_writeln("Programming error read_objs is null");
|
||||
LOG(LOG_LEVEL_ERROR, "Programming error read_objs is null");
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
@ -2031,7 +2032,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount,
|
||||
}
|
||||
else if (wcount > 0)
|
||||
{
|
||||
g_writeln("Programming error write_objs is null");
|
||||
LOG(LOG_LEVEL_ERROR, "Programming error write_objs is null");
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
@ -2590,16 +2591,41 @@ g_get_errno(void)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32 */
|
||||
|
||||
#define ARGS_STR_LEN 1024
|
||||
|
||||
int
|
||||
g_execvp(const char *p1, char *args[])
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return 0;
|
||||
#else
|
||||
|
||||
int rv;
|
||||
char args_str[ARGS_STR_LEN];
|
||||
int args_len;
|
||||
|
||||
args_len = 0;
|
||||
while (args[args_len] != NULL)
|
||||
{
|
||||
args_len++;
|
||||
}
|
||||
|
||||
g_strnjoin(args_str, ARGS_STR_LEN, " ", (const char **) args, args_len);
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"Calling exec (excutable: %s, arguments: %s)",
|
||||
p1, args_str);
|
||||
|
||||
g_rm_temp_dir();
|
||||
rv = execvp(p1, args);
|
||||
|
||||
/* should not get here */
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error calling exec (excutable: %s, arguments: %s) "
|
||||
"returned errno: %d, description: %s",
|
||||
p1, args_str, g_get_errno(), g_get_strerror());
|
||||
|
||||
g_mk_socket_path(0);
|
||||
return rv;
|
||||
#endif
|
||||
@ -2614,9 +2640,24 @@ g_execlp3(const char *a1, const char *a2, const char *a3)
|
||||
return 0;
|
||||
#else
|
||||
int rv;
|
||||
const char *args[] = {a2, a3, NULL};
|
||||
char args_str[ARGS_STR_LEN];
|
||||
|
||||
g_strnjoin(args_str, ARGS_STR_LEN, " ", args, 2);
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"Calling exec (excutable: %s, arguments: %s)",
|
||||
a1, args_str);
|
||||
|
||||
g_rm_temp_dir();
|
||||
rv = execlp(a1, a2, a3, (void *)0);
|
||||
|
||||
/* should not get here */
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error calling exec (excutable: %s, arguments: %s) "
|
||||
"returned errno: %d, description: %s",
|
||||
a1, args_str, g_get_errno(), g_get_strerror());
|
||||
|
||||
g_mk_socket_path(0);
|
||||
return rv;
|
||||
#endif
|
||||
@ -2715,6 +2756,12 @@ g_fork(void)
|
||||
{
|
||||
g_mk_socket_path(0);
|
||||
}
|
||||
else if (rv == -1) /* error */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Process fork failed with errno: %d, description: %s",
|
||||
g_get_errno(), g_get_strerror());
|
||||
}
|
||||
|
||||
return rv;
|
||||
#endif
|
||||
@ -2875,6 +2922,51 @@ g_waitpid(int pid)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32
|
||||
returns exit status code of child process with pid */
|
||||
struct exit_status
|
||||
g_waitpid_status(int pid)
|
||||
{
|
||||
struct exit_status exit_status;
|
||||
|
||||
#if defined(_WIN32)
|
||||
exit_status.exit_code = -1;
|
||||
exit_status.signal_no = 0;
|
||||
return exit_status;
|
||||
#else
|
||||
int rv;
|
||||
int status;
|
||||
|
||||
exit_status.exit_code = -1;
|
||||
exit_status.signal_no = 0;
|
||||
|
||||
if (pid > 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "waiting for pid %d to exit", pid);
|
||||
rv = waitpid(pid, &status, 0);
|
||||
|
||||
if (rv != -1)
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
{
|
||||
exit_status.exit_code = WEXITSTATUS(status);
|
||||
}
|
||||
if (WIFSIGNALED(status))
|
||||
{
|
||||
exit_status.signal_no = WTERMSIG(status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "wait for pid %d returned unknown result", pid);
|
||||
}
|
||||
}
|
||||
|
||||
return exit_status;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32 */
|
||||
void
|
||||
@ -3135,11 +3227,11 @@ struct dib_hdr
|
||||
int vres;
|
||||
unsigned int ncolors;
|
||||
unsigned int nimpcolors;
|
||||
};
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
g_save_to_bmp(const char *filename, char *data, int stride_bytes,
|
||||
int width, int height, int depth, int bits_per_pixel)
|
||||
{
|
||||
struct bmp_magic bm;
|
||||
@ -3152,8 +3244,8 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
int pixel;
|
||||
int extra;
|
||||
int file_stride_bytes;
|
||||
char* line;
|
||||
char* line_ptr;
|
||||
char *line;
|
||||
char *line_ptr;
|
||||
|
||||
if ((depth == 24) && (bits_per_pixel == 32))
|
||||
{
|
||||
@ -3163,7 +3255,9 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("g_save_to_bpp: unimp");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"g_save_to_bpp: unimplemented for: depth %d, bits_per_pixel %d",
|
||||
depth, bits_per_pixel);
|
||||
return 1;
|
||||
}
|
||||
bm.magic[0] = 'B';
|
||||
@ -3196,23 +3290,23 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (fd == -1)
|
||||
{
|
||||
g_writeln("g_save_to_bpp: open error");
|
||||
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: open error");
|
||||
return 1;
|
||||
}
|
||||
bytes = write(fd, &bm, sizeof(bm));
|
||||
if (bytes != sizeof(bm))
|
||||
{
|
||||
g_writeln("g_save_to_bpp: write error");
|
||||
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
|
||||
}
|
||||
bytes = write(fd, &bh, sizeof(bh));
|
||||
if (bytes != sizeof(bh))
|
||||
{
|
||||
g_writeln("g_save_to_bpp: write error");
|
||||
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
|
||||
}
|
||||
bytes = write(fd, &dh, sizeof(dh));
|
||||
if (bytes != sizeof(dh))
|
||||
{
|
||||
g_writeln("g_save_to_bpp: write error");
|
||||
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
|
||||
}
|
||||
data += stride_bytes * height;
|
||||
data -= stride_bytes;
|
||||
@ -3225,7 +3319,7 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
line_ptr = line;
|
||||
for (i1 = 0; i1 < width; i1++)
|
||||
{
|
||||
pixel = ((int*)data)[i1];
|
||||
pixel = ((int *)data)[i1];
|
||||
*(line_ptr++) = (pixel >> 0) & 0xff;
|
||||
*(line_ptr++) = (pixel >> 8) & 0xff;
|
||||
*(line_ptr++) = (pixel >> 16) & 0xff;
|
||||
@ -3233,7 +3327,7 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
bytes = write(fd, line, file_stride_bytes);
|
||||
if (bytes != file_stride_bytes)
|
||||
{
|
||||
g_writeln("g_save_to_bpp: write error");
|
||||
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
|
||||
}
|
||||
data -= stride_bytes;
|
||||
}
|
||||
@ -3246,14 +3340,16 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
bytes = write(fd, data, width * (bits_per_pixel / 8));
|
||||
if (bytes != width * (bits_per_pixel / 8))
|
||||
{
|
||||
g_writeln("g_save_to_bpp: write error");
|
||||
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
|
||||
}
|
||||
data -= stride_bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("g_save_to_bpp: unimp");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"g_save_to_bpp: unimplemented for: depth %d, bits_per_pixel %d",
|
||||
depth, bits_per_pixel);
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
@ -3267,7 +3363,7 @@ g_shmat(int shmid)
|
||||
#if defined(_WIN32)
|
||||
return 0;
|
||||
#else
|
||||
return shmat(shmid, 0, 0);
|
||||
return shmat(shmid, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -3398,7 +3494,7 @@ g_tcp4_bind_address(int sck, const char *port, const char *address)
|
||||
{
|
||||
return -1; /* bad address */
|
||||
}
|
||||
if (bind(sck, (struct sockaddr*) &s, sizeof(s)) < 0)
|
||||
if (bind(sck, (struct sockaddr *) &s, sizeof(s)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -23,6 +23,15 @@
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
struct exit_status
|
||||
{
|
||||
/* set to -1 when the process exited via a signal */
|
||||
uint8_t exit_code;
|
||||
|
||||
/* set to 0 when the process exited normally */
|
||||
uint8_t signal_no;
|
||||
};
|
||||
|
||||
#define g_tcp_can_recv g_sck_can_recv
|
||||
#define g_tcp_can_send g_sck_can_send
|
||||
#define g_tcp_recv g_sck_recv
|
||||
@ -38,21 +47,21 @@
|
||||
#define g_close_wait_obj g_delete_wait_obj
|
||||
|
||||
int g_rm_temp_dir(void);
|
||||
int g_mk_socket_path(const char* app_name);
|
||||
void g_init(const char* app_name);
|
||||
int g_mk_socket_path(const char *app_name);
|
||||
void g_init(const char *app_name);
|
||||
void g_deinit(void);
|
||||
void* g_malloc(int size, int zero);
|
||||
void g_free(void* ptr);
|
||||
void *g_malloc(int size, int zero);
|
||||
void g_free(void *ptr);
|
||||
void g_printf(const char *format, ...) printflike(1, 2);
|
||||
void g_sprintf(char* dest, const char* format, ...) \
|
||||
printflike(2, 3);
|
||||
int g_snprintf(char* dest, int len, const char* format, ...) \
|
||||
printflike(3, 4);
|
||||
void g_writeln(const char* format, ...) printflike(1, 2);
|
||||
void g_write(const char* format, ...) printflike(1, 2);
|
||||
void g_sprintf(char *dest, const char *format, ...) \
|
||||
printflike(2, 3);
|
||||
int g_snprintf(char *dest, int len, const char *format, ...) \
|
||||
printflike(3, 4);
|
||||
void g_writeln(const char *format, ...) printflike(1, 2);
|
||||
void g_write(const char *format, ...) printflike(1, 2);
|
||||
void g_hexdump(const char *p, int len);
|
||||
void g_memset(void* ptr, int val, int size);
|
||||
void g_memcpy(void* d_ptr, const void* s_ptr, int size);
|
||||
void g_memset(void *ptr, int val, int size);
|
||||
void g_memcpy(void *d_ptr, const void *s_ptr, int size);
|
||||
int g_getchar(void);
|
||||
int g_tcp_set_no_delay(int sck);
|
||||
int g_tcp_set_keepalive(int sck);
|
||||
@ -65,26 +74,26 @@ int g_sck_local_socket(void);
|
||||
int g_sck_vsock_socket(void);
|
||||
int g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid);
|
||||
void g_sck_close(int sck);
|
||||
int g_tcp_connect(int sck, const char* address, const char* port);
|
||||
int g_sck_local_connect(int sck, const char* port);
|
||||
int g_tcp_connect(int sck, const char *address, const char *port);
|
||||
int g_sck_local_connect(int sck, const char *port);
|
||||
int g_sck_set_non_blocking(int sck);
|
||||
int g_tcp_bind(int sck, const char *port);
|
||||
int g_sck_local_bind(int sck, const char* port);
|
||||
int g_sck_vsock_bind(int sck, const char* port);
|
||||
int g_sck_local_bind(int sck, const char *port);
|
||||
int g_sck_vsock_bind(int sck, const char *port);
|
||||
int g_sck_vsock_bind_address(int sck, const char *port, const char *address);
|
||||
int g_tcp_bind_address(int sck, const char* port, const char* address);
|
||||
int g_tcp_bind_address(int sck, const char *port, const char *address);
|
||||
int g_sck_listen(int sck);
|
||||
int g_tcp_accept(int sck);
|
||||
int g_sck_accept(int sck, char *addr, int addr_bytes,
|
||||
char *port, int port_bytes);
|
||||
int g_sck_recv(int sck, void* ptr, int len, int flags);
|
||||
int g_sck_send(int sck, const void* ptr, int len, int flags);
|
||||
char *port, int port_bytes);
|
||||
int g_sck_recv(int sck, void *ptr, int len, int flags);
|
||||
int g_sck_send(int sck, const void *ptr, int len, int flags);
|
||||
int g_sck_last_error_would_block(int sck);
|
||||
int g_sck_socket_ok(int sck);
|
||||
int g_sck_can_send(int sck, int millis);
|
||||
int g_sck_can_recv(int sck, int millis);
|
||||
int g_sck_select(int sck1, int sck2);
|
||||
void g_write_ip_address(int rcv_sck, char* ip_address, int bytes);
|
||||
void g_write_ip_address(int rcv_sck, char *ip_address, int bytes);
|
||||
void g_sleep(int msecs);
|
||||
tintptr g_create_wait_obj(const char *name);
|
||||
tintptr g_create_wait_obj_from_socket(tintptr socket, int write);
|
||||
@ -93,40 +102,40 @@ int g_set_wait_obj(tintptr obj);
|
||||
int g_reset_wait_obj(tintptr obj);
|
||||
int g_is_wait_obj_set(tintptr obj);
|
||||
int g_delete_wait_obj(tintptr obj);
|
||||
int g_obj_wait(tintptr* read_objs, int rcount, tintptr* write_objs,
|
||||
int wcount,int mstimeout);
|
||||
void g_random(char* data, int len);
|
||||
int g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs,
|
||||
int wcount, int mstimeout);
|
||||
void g_random(char *data, int len);
|
||||
int g_abs(int i);
|
||||
int g_memcmp(const void* s1, const void* s2, int len);
|
||||
int g_file_open(const char* file_name);
|
||||
int g_memcmp(const void *s1, const void *s2, int len);
|
||||
int g_file_open(const char *file_name);
|
||||
int g_file_open_ex(const char *file_name, int aread, int awrite,
|
||||
int acreate, int atrunc);
|
||||
int acreate, int atrunc);
|
||||
int g_file_close(int fd);
|
||||
int g_file_read(int fd, char* ptr, int len);
|
||||
int g_file_read(int fd, char *ptr, int len);
|
||||
int g_file_write(int fd, const char *ptr, int len);
|
||||
int g_file_seek(int fd, int offset);
|
||||
int g_file_lock(int fd, int start, int len);
|
||||
int g_chmod_hex(const char* filename, int flags);
|
||||
int g_chown(const char* name, int uid, int gid);
|
||||
int g_mkdir(const char* dirname);
|
||||
char* g_get_current_dir(char* dirname, int maxlen);
|
||||
int g_chmod_hex(const char *filename, int flags);
|
||||
int g_chown(const char *name, int uid, int gid);
|
||||
int g_mkdir(const char *dirname);
|
||||
char *g_get_current_dir(char *dirname, int maxlen);
|
||||
int g_set_current_dir(const char *dirname);
|
||||
int g_file_exist(const char* filename);
|
||||
int g_file_exist(const char *filename);
|
||||
int g_file_readable(const char *filename);
|
||||
int g_directory_exist(const char* dirname);
|
||||
int g_create_dir(const char* dirname);
|
||||
int g_create_path(const char* path);
|
||||
int g_remove_dir(const char* dirname);
|
||||
int g_file_delete(const char* filename);
|
||||
int g_file_get_size(const char* filename);
|
||||
long g_load_library(char* in);
|
||||
int g_directory_exist(const char *dirname);
|
||||
int g_create_dir(const char *dirname);
|
||||
int g_create_path(const char *path);
|
||||
int g_remove_dir(const char *dirname);
|
||||
int g_file_delete(const char *filename);
|
||||
int g_file_get_size(const char *filename);
|
||||
long g_load_library(char *in);
|
||||
int g_free_library(long lib);
|
||||
void* g_get_proc_address(long lib, const char* name);
|
||||
int g_system(char* aexec);
|
||||
char* g_get_strerror(void);
|
||||
void *g_get_proc_address(long lib, const char *name);
|
||||
int g_system(char *aexec);
|
||||
char *g_get_strerror(void);
|
||||
int g_get_errno(void);
|
||||
int g_execvp(const char* p1, char* args[]);
|
||||
int g_execlp3(const char* a1, const char* a2, const char* a3);
|
||||
int g_execvp(const char *p1, char *args[]);
|
||||
int g_execlp3(const char *a1, const char *a2, const char *a3);
|
||||
void g_signal_child_stop(void (*func)(int));
|
||||
void g_signal_segfault(void (*func)(int));
|
||||
void g_signal_hang_up(void (*func)(int));
|
||||
@ -136,7 +145,7 @@ void g_signal_pipe(void (*func)(int));
|
||||
void g_signal_usr1(void (*func)(int));
|
||||
int g_fork(void);
|
||||
int g_setgid(int pid);
|
||||
int g_initgroups(const char* user, int gid);
|
||||
int g_initgroups(const char *user, int gid);
|
||||
int g_getuid(void);
|
||||
int g_getgid(void);
|
||||
int g_setuid(int pid);
|
||||
@ -145,22 +154,23 @@ int g_getlogin(char *name, unsigned int len);
|
||||
int g_setlogin(const char *name);
|
||||
int g_waitchild(void);
|
||||
int g_waitpid(int pid);
|
||||
struct exit_status g_waitpid_status(int pid);
|
||||
void g_clearenv(void);
|
||||
int g_setenv(const char* name, const char* value, int rewrite);
|
||||
char* g_getenv(const char* name);
|
||||
int g_setenv(const char *name, const char *value, int rewrite);
|
||||
char *g_getenv(const char *name);
|
||||
int g_exit(int exit_code);
|
||||
int g_getpid(void);
|
||||
int g_sigterm(int pid);
|
||||
int g_getuser_info(const char* username, int* gid, int* uid, char** shell,
|
||||
char** dir, char** gecos);
|
||||
int g_getgroup_info(const char* groupname, int* gid);
|
||||
int g_check_user_in_group(const char* username, int gid, int* ok);
|
||||
int g_getuser_info(const char *username, int *gid, int *uid, char **shell,
|
||||
char **dir, char **gecos);
|
||||
int g_getgroup_info(const char *groupname, int *gid);
|
||||
int g_check_user_in_group(const char *username, int gid, int *ok);
|
||||
int g_time1(void);
|
||||
int g_time2(void);
|
||||
int g_time3(void);
|
||||
int g_save_to_bmp(const char* filename, char* data, int stride_bytes,
|
||||
int width, int height, int depth, int bits_per_pixel);
|
||||
void * g_shmat(int shmid);
|
||||
int g_save_to_bmp(const char *filename, char *data, int stride_bytes,
|
||||
int width, int height, int depth, int bits_per_pixel);
|
||||
void *g_shmat(int shmid);
|
||||
int g_shmdt(const void *shmaddr);
|
||||
int g_gethostname(char *name, int len);
|
||||
int g_mirror_memcpy(void *dst, const void *src, int len);
|
||||
|
||||
521
common/parse.h
521
common/parse.h
@ -26,6 +26,7 @@
|
||||
#define PARSE_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "log.h"
|
||||
|
||||
#if defined(L_ENDIAN)
|
||||
#elif defined(B_ENDIAN)
|
||||
@ -54,51 +55,97 @@ struct stream
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check(s) ((s)->p <= (s)->end)
|
||||
#define s_check(s) s_check_rem(s, 0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_rem(s, n) ((s)->p + (n) <= (s)->end)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @returns true if there are at least n bytes remaining in the stream,
|
||||
* else false and logs an error message
|
||||
*/
|
||||
#define s_check_rem_and_log(s, n, msg_prefix) \
|
||||
( s_check_rem((s), (n)) ? \
|
||||
1 : \
|
||||
LOG(LOG_LEVEL_ERROR, \
|
||||
"%s Not enough bytes in the stream: expected %d, remaining %d", \
|
||||
(msg_prefix), (n), s_rem(s)) \
|
||||
&& 0 )
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_rem_out(s, n) ((s)->p + (n) <= (s)->data + (s)->size)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @returns true if there are at least n bytes remaining in the stream,
|
||||
* else false and logs an error message
|
||||
*/
|
||||
#define s_check_rem_out_and_log(s, n, msg_prefix) \
|
||||
( s_check_rem_out((s), (n)) ? \
|
||||
1 : \
|
||||
LOG(LOG_LEVEL_ERROR, \
|
||||
"%s Not enough bytes in the stream: expected %d, remaining %d", \
|
||||
(msg_prefix), (n), s_rem_out(s)) \
|
||||
&& 0 )
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_end(s) ((s)->p == (s)->end)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @returns true if there are exactly 0 bytes remaining in the stream,
|
||||
* else false and logs an error message
|
||||
*/
|
||||
#define s_check_end_and_log(s, msg_prefix) \
|
||||
( s_check_end((s)) ? \
|
||||
1 : \
|
||||
LOG(LOG_LEVEL_ERROR, \
|
||||
"%s Expected to be at the end of the stream, " \
|
||||
"but there are %d bytes remaining", \
|
||||
(msg_prefix), s_rem(s)) \
|
||||
&& 0 )
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_rem(s) ((int) ((s)->end - (s)->p))
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_rem_out(s) ((int) ((s)->data + (s)->size - (s)->p))
|
||||
|
||||
/******************************************************************************/
|
||||
#define make_stream(s) \
|
||||
(s) = (struct stream*)g_malloc(sizeof(struct stream), 1)
|
||||
|
||||
/******************************************************************************/
|
||||
#define init_stream(s, v) do \
|
||||
{ \
|
||||
if ((v) > (s)->size) \
|
||||
{ \
|
||||
g_free((s)->data); \
|
||||
(s)->data = (char*)g_malloc((v), 0); \
|
||||
(s)->size = (v); \
|
||||
} \
|
||||
(s)->p = (s)->data; \
|
||||
(s)->end = (s)->data; \
|
||||
(s)->next_packet = 0; \
|
||||
} while (0)
|
||||
if ((v) > (s)->size) \
|
||||
{ \
|
||||
g_free((s)->data); \
|
||||
(s)->data = (char*)g_malloc((v), 0); \
|
||||
(s)->size = (v); \
|
||||
} \
|
||||
(s)->p = (s)->data; \
|
||||
(s)->end = (s)->data; \
|
||||
(s)->next_packet = 0; \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define free_stream(s) do \
|
||||
{ \
|
||||
if ((s) != 0) \
|
||||
{ \
|
||||
g_free((s)->data); \
|
||||
} \
|
||||
g_free((s)); \
|
||||
} while (0)
|
||||
if ((s) != 0) \
|
||||
{ \
|
||||
g_free((s)->data); \
|
||||
} \
|
||||
g_free((s)); \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_push_layer(s, h, n) do \
|
||||
{ \
|
||||
(s)->h = (s)->p; \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
{ \
|
||||
(s)->h = (s)->p; \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_pop_layer(s, h) \
|
||||
@ -109,238 +156,238 @@ struct stream
|
||||
(s)->end = (s)->p
|
||||
|
||||
#define in_sint8(s, v) do \
|
||||
{ \
|
||||
(v) = *((signed char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((signed char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define in_uint8(s, v) do \
|
||||
{ \
|
||||
(v) = *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
/******************************************************************************/
|
||||
#define in_uint8_peek(s, v) do { v = *s->p; } while (0)
|
||||
/******************************************************************************/
|
||||
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
|
||||
#define in_sint16_le(s, v) do \
|
||||
{ \
|
||||
(v) = (signed short) \
|
||||
( \
|
||||
(*((unsigned char*)((s)->p + 0)) << 0) | \
|
||||
(*((unsigned char*)((s)->p + 1)) << 8) \
|
||||
); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = (signed short) \
|
||||
( \
|
||||
(*((unsigned char*)((s)->p + 0)) << 0) | \
|
||||
(*((unsigned char*)((s)->p + 1)) << 8) \
|
||||
); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
#else
|
||||
#define in_sint16_le(s, v) do \
|
||||
{ \
|
||||
(v) = *((signed short*)((s)->p)); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((signed short*)((s)->p)); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
|
||||
#define in_uint16_le(s, v) do \
|
||||
{ \
|
||||
(v) = (unsigned short) \
|
||||
( \
|
||||
(*((unsigned char*)((s)->p + 0)) << 0) | \
|
||||
(*((unsigned char*)((s)->p + 1)) << 8) \
|
||||
); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = (unsigned short) \
|
||||
( \
|
||||
(*((unsigned char*)((s)->p + 0)) << 0) | \
|
||||
(*((unsigned char*)((s)->p + 1)) << 8) \
|
||||
); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
#else
|
||||
#define in_uint16_le(s, v) do \
|
||||
{ \
|
||||
(v) = *((unsigned short*)((s)->p)); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((unsigned short*)((s)->p)); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
#define in_uint16_be(s, v) do \
|
||||
{ \
|
||||
(v) = *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
|
||||
#define in_uint32_le(s, v) do \
|
||||
{ \
|
||||
(v) = (unsigned int) \
|
||||
( \
|
||||
(*((unsigned char*)((s)->p + 0)) << 0) | \
|
||||
(*((unsigned char*)((s)->p + 1)) << 8) | \
|
||||
(*((unsigned char*)((s)->p + 2)) << 16) | \
|
||||
(*((unsigned char*)((s)->p + 3)) << 24) \
|
||||
); \
|
||||
(s)->p += 4; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = (unsigned int) \
|
||||
( \
|
||||
(*((unsigned char*)((s)->p + 0)) << 0) | \
|
||||
(*((unsigned char*)((s)->p + 1)) << 8) | \
|
||||
(*((unsigned char*)((s)->p + 2)) << 16) | \
|
||||
(*((unsigned char*)((s)->p + 3)) << 24) \
|
||||
); \
|
||||
(s)->p += 4; \
|
||||
} while (0)
|
||||
#else
|
||||
#define in_uint32_le(s, v) do \
|
||||
{ \
|
||||
(v) = *((unsigned int*)((s)->p)); \
|
||||
(s)->p += 4; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((unsigned int*)((s)->p)); \
|
||||
(s)->p += 4; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
|
||||
#define in_uint64_le(s, v) do \
|
||||
{ \
|
||||
(v) = (tui64) \
|
||||
( \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 0)))) << 0) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 1)))) << 8) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 2)))) << 16) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 3)))) << 24) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 4)))) << 32) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 5)))) << 40) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 6)))) << 48) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 7)))) << 56) \
|
||||
); \
|
||||
(s)->p += 8; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = (tui64) \
|
||||
( \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 0)))) << 0) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 1)))) << 8) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 2)))) << 16) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 3)))) << 24) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 4)))) << 32) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 5)))) << 40) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 6)))) << 48) | \
|
||||
(((tui64)(*((unsigned char*)((s)->p + 7)))) << 56) \
|
||||
); \
|
||||
(s)->p += 8; \
|
||||
} while (0)
|
||||
#else
|
||||
#define in_uint64_le(s, v) do \
|
||||
{ \
|
||||
(v) = *((tui64*)((s)->p)); \
|
||||
(s)->p += 8; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((tui64*)((s)->p)); \
|
||||
(s)->p += 8; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
#define in_uint32_be(s, v) do \
|
||||
{ \
|
||||
(v) = *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
(v) <<= 8; \
|
||||
(v) |= *((unsigned char*)((s)->p)); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define out_uint8(s, v) do \
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)(v); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)(v); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
|
||||
#define out_uint16_le(s, v) do \
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
#else
|
||||
#define out_uint16_le(s, v) do \
|
||||
{ \
|
||||
*((unsigned short*)((s)->p)) = (unsigned short)(v); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((unsigned short*)((s)->p)) = (unsigned short)(v); \
|
||||
(s)->p += 2; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
#define out_uint16_be(s, v) do \
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
|
||||
#define out_uint32_le(s, v) do \
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 16); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 24); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 16); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 24); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
#else
|
||||
#define out_uint32_le(s, v) do \
|
||||
{ \
|
||||
*((unsigned int*)((s)->p)) = (v); \
|
||||
(s)->p += 4; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((unsigned int*)((s)->p)) = (v); \
|
||||
(s)->p += 4; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
|
||||
#define out_uint64_le(s, v) do \
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 16); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 24); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 32); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 40); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 48); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 56); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 0); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 16); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 24); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 32); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 40); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 48); \
|
||||
(s)->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 56); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
#else
|
||||
#define out_uint64_le(s, v) do \
|
||||
{ \
|
||||
*((tui64*)((s)->p)) = (v); \
|
||||
(s)->p += 8; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((tui64*)((s)->p)) = (v); \
|
||||
(s)->p += 8; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
#define out_uint32_be(s, v) do \
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 24); \
|
||||
s->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 16); \
|
||||
s->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
s->p++; \
|
||||
*((s)->p) = (unsigned char)(v); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
{ \
|
||||
*((s)->p) = (unsigned char)((v) >> 24); \
|
||||
s->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 16); \
|
||||
s->p++; \
|
||||
*((s)->p) = (unsigned char)((v) >> 8); \
|
||||
s->p++; \
|
||||
*((s)->p) = (unsigned char)(v); \
|
||||
(s)->p++; \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define in_uint8p(s, v, n) do \
|
||||
{ \
|
||||
(v) = (s)->p; \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
{ \
|
||||
(v) = (s)->p; \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define in_uint8a(s, v, n) do \
|
||||
{ \
|
||||
g_memcpy((v), (s)->p, (n)); \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
{ \
|
||||
g_memcpy((v), (s)->p, (n)); \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define in_uint8s(s, n) \
|
||||
@ -348,10 +395,10 @@ struct stream
|
||||
|
||||
/******************************************************************************/
|
||||
#define out_uint8p(s, v, n) do \
|
||||
{ \
|
||||
g_memcpy((s)->p, (v), (n)); \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
{ \
|
||||
g_memcpy((s)->p, (v), (n)); \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define out_uint8a(s, v, n) \
|
||||
@ -359,10 +406,10 @@ struct stream
|
||||
|
||||
/******************************************************************************/
|
||||
#define out_uint8s(s, n) do \
|
||||
{ \
|
||||
g_memset((s)->p, 0, (n)); \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
{ \
|
||||
g_memset((s)->p, 0, (n)); \
|
||||
(s)->p += (n); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* @brief allocate a new stream
|
||||
@ -371,11 +418,11 @@ struct stream
|
||||
* @param _l length of new stream
|
||||
******************************************************************************/
|
||||
#define xstream_new(_s, _l) \
|
||||
do \
|
||||
{ \
|
||||
make_stream((_s)); \
|
||||
init_stream((_s), (_l)); \
|
||||
} while (0)
|
||||
do \
|
||||
{ \
|
||||
make_stream((_s)); \
|
||||
init_stream((_s), (_l)); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief release a previously allocated stream
|
||||
@ -401,63 +448,63 @@ do \
|
||||
#define xstream_wr_s32_le(_s, _var) TODO
|
||||
|
||||
#define xstream_rd_u64_le(_s, _v) \
|
||||
do \
|
||||
{ \
|
||||
_v = \
|
||||
(tui64)(*((unsigned char *)_s->p)) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 1))) << 8) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 2))) << 16) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 3))) << 24) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 4))) << 32) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 5))) << 40) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 6))) << 48) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 7))) << 56); \
|
||||
_s->p += 8; \
|
||||
} while (0)
|
||||
do \
|
||||
{ \
|
||||
_v = \
|
||||
(tui64)(*((unsigned char *)_s->p)) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 1))) << 8) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 2))) << 16) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 3))) << 24) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 4))) << 32) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 5))) << 40) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 6))) << 48) | \
|
||||
(((tui64) (*(((unsigned char *)_s->p) + 7))) << 56); \
|
||||
_s->p += 8; \
|
||||
} while (0)
|
||||
|
||||
#define xstream_wr_u64_le(_s, _v) \
|
||||
do \
|
||||
{ \
|
||||
*(((unsigned char *) _s->p) + 0) = (unsigned char) ((_v >> 0) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 1) = (unsigned char) ((_v >> 8) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 2) = (unsigned char) ((_v >> 16) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 3) = (unsigned char) ((_v >> 24) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 4) = (unsigned char) ((_v >> 32) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 5) = (unsigned char) ((_v >> 40) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 6) = (unsigned char) ((_v >> 48) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 7) = (unsigned char) ((_v >> 56) & 0xff); \
|
||||
_s->p += 8; \
|
||||
} while (0)
|
||||
do \
|
||||
{ \
|
||||
*(((unsigned char *) _s->p) + 0) = (unsigned char) ((_v >> 0) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 1) = (unsigned char) ((_v >> 8) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 2) = (unsigned char) ((_v >> 16) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 3) = (unsigned char) ((_v >> 24) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 4) = (unsigned char) ((_v >> 32) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 5) = (unsigned char) ((_v >> 40) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 6) = (unsigned char) ((_v >> 48) & 0xff); \
|
||||
*(((unsigned char *) _s->p) + 7) = (unsigned char) ((_v >> 56) & 0xff); \
|
||||
_s->p += 8; \
|
||||
} while (0)
|
||||
|
||||
/* copy data into stream */
|
||||
#define xstream_copyin(_s, _dest, _len) \
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_s)->p, (_dest), (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_s)->p, (_dest), (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
|
||||
/* copy data out of stream */
|
||||
#define xstream_copyout(_dest, _s, _len) \
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_dest), (_s)->p, (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_dest), (_s)->p, (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
|
||||
#define xstream_rd_string(_dest, _s, _len) \
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_dest), (_s)->p, (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_dest), (_s)->p, (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
|
||||
#define xstream_wr_string(_s, _src, _len) \
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_s)->p, (_src), (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
do \
|
||||
{ \
|
||||
g_memcpy((_s)->p, (_src), (_len)); \
|
||||
(_s)->p += (_len); \
|
||||
} while (0)
|
||||
|
||||
#define xstream_len(_s) (int) ((_s)->p - (_s)->data)
|
||||
#define xstream_seek(_s, _len) (_s)->p += (_len)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -56,21 +56,21 @@ typedef struct pixman_region16 pixman_region16_t;
|
||||
/* creation/destruction */
|
||||
void pixman_region_init (pixman_region16_t *region);
|
||||
void pixman_region_init_rect (pixman_region16_t *region,
|
||||
int x,
|
||||
int y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
/**/ int x,
|
||||
/**/ int y,
|
||||
/**/ unsigned int width,
|
||||
/**/ unsigned int height);
|
||||
void pixman_region_fini (pixman_region16_t *region);
|
||||
pixman_bool_t pixman_region_union (pixman_region16_t *new_reg,
|
||||
pixman_region16_t *reg1,
|
||||
pixman_region16_t *reg2);
|
||||
/**/ pixman_region16_t *reg1,
|
||||
/**/ pixman_region16_t *reg2);
|
||||
pixman_bool_t pixman_region_subtract (pixman_region16_t *reg_d,
|
||||
pixman_region16_t *reg_m,
|
||||
pixman_region16_t *reg_s);
|
||||
/**/ pixman_region16_t *reg_m,
|
||||
/**/ pixman_region16_t *reg_s);
|
||||
pixman_bool_t pixman_region_intersect (pixman_region16_t *new_reg,
|
||||
pixman_region16_t *reg1,
|
||||
pixman_region16_t *reg2);
|
||||
pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region,
|
||||
int *n_rects);
|
||||
/**/ pixman_region16_t *reg1,
|
||||
/**/ pixman_region16_t *reg2);
|
||||
pixman_box16_t *pixman_region_rectangles (pixman_region16_t *region,
|
||||
/**/ int *n_rects);
|
||||
|
||||
#endif
|
||||
|
||||
100
common/rail.h
100
common/rail.h
@ -72,76 +72,76 @@
|
||||
|
||||
struct rail_icon_info
|
||||
{
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
int cmap_bytes;
|
||||
int mask_bytes;
|
||||
int data_bytes;
|
||||
char* mask;
|
||||
char* cmap;
|
||||
char* data;
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
int cmap_bytes;
|
||||
int mask_bytes;
|
||||
int data_bytes;
|
||||
char *mask;
|
||||
char *cmap;
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct rail_window_rect
|
||||
{
|
||||
short left;
|
||||
short top;
|
||||
short right;
|
||||
short bottom;
|
||||
short left;
|
||||
short top;
|
||||
short right;
|
||||
short bottom;
|
||||
};
|
||||
|
||||
struct rail_notify_icon_infotip
|
||||
{
|
||||
int timeout;
|
||||
int flags;
|
||||
char* text;
|
||||
char* title;
|
||||
int timeout;
|
||||
int flags;
|
||||
char *text;
|
||||
char *title;
|
||||
};
|
||||
|
||||
struct rail_window_state_order
|
||||
{
|
||||
int owner_window_id;
|
||||
int style;
|
||||
int extended_style;
|
||||
int show_state;
|
||||
char* title_info;
|
||||
int client_offset_x;
|
||||
int client_offset_y;
|
||||
int client_area_width;
|
||||
int client_area_height;
|
||||
int rp_content;
|
||||
int root_parent_handle;
|
||||
int window_offset_x;
|
||||
int window_offset_y;
|
||||
int window_client_delta_x;
|
||||
int window_client_delta_y;
|
||||
int window_width;
|
||||
int window_height;
|
||||
int num_window_rects;
|
||||
struct rail_window_rect* window_rects;
|
||||
int visible_offset_x;
|
||||
int visible_offset_y;
|
||||
int num_visibility_rects;
|
||||
struct rail_window_rect* visibility_rects;
|
||||
int owner_window_id;
|
||||
int style;
|
||||
int extended_style;
|
||||
int show_state;
|
||||
char *title_info;
|
||||
int client_offset_x;
|
||||
int client_offset_y;
|
||||
int client_area_width;
|
||||
int client_area_height;
|
||||
int rp_content;
|
||||
int root_parent_handle;
|
||||
int window_offset_x;
|
||||
int window_offset_y;
|
||||
int window_client_delta_x;
|
||||
int window_client_delta_y;
|
||||
int window_width;
|
||||
int window_height;
|
||||
int num_window_rects;
|
||||
struct rail_window_rect *window_rects;
|
||||
int visible_offset_x;
|
||||
int visible_offset_y;
|
||||
int num_visibility_rects;
|
||||
struct rail_window_rect *visibility_rects;
|
||||
};
|
||||
|
||||
struct rail_notify_state_order
|
||||
{
|
||||
int version;
|
||||
char* tool_tip;
|
||||
struct rail_notify_icon_infotip infotip;
|
||||
int state;
|
||||
int icon_cache_entry;
|
||||
int icon_cache_id;
|
||||
struct rail_icon_info icon_info;
|
||||
int version;
|
||||
char *tool_tip;
|
||||
struct rail_notify_icon_infotip infotip;
|
||||
int state;
|
||||
int icon_cache_entry;
|
||||
int icon_cache_id;
|
||||
struct rail_icon_info icon_info;
|
||||
};
|
||||
|
||||
struct rail_monitored_desktop_order
|
||||
{
|
||||
int active_window_id;
|
||||
int num_window_ids;
|
||||
int* window_ids;
|
||||
int active_window_id;
|
||||
int num_window_ids;
|
||||
int *window_ids;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -64,8 +64,8 @@ static inline void
|
||||
RSA_get0_key(const RSA *key, const BIGNUM **n, const BIGNUM **e,
|
||||
const BIGNUM **d)
|
||||
{
|
||||
*n = key->n;
|
||||
*d = key->d;
|
||||
*n = key->n;
|
||||
*d = key->d;
|
||||
}
|
||||
|
||||
static inline int
|
||||
@ -75,7 +75,7 @@ DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||
* parameters MUST be non-NULL. q may remain NULL.
|
||||
*/
|
||||
if ((dh->p == NULL && p == NULL)
|
||||
|| (dh->g == NULL && g == NULL))
|
||||
|| (dh->g == NULL && g == NULL))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -230,7 +230,7 @@ ssl_md5_complete(void *md5_info, char *data)
|
||||
|
||||
/*****************************************************************************/
|
||||
void *
|
||||
ssl_des3_encrypt_info_create(const char *key, const char* ivec)
|
||||
ssl_des3_encrypt_info_create(const char *key, const char *ivec)
|
||||
{
|
||||
EVP_CIPHER_CTX *des3_ctx;
|
||||
const tui8 *lkey;
|
||||
@ -246,7 +246,7 @@ ssl_des3_encrypt_info_create(const char *key, const char* ivec)
|
||||
|
||||
/*****************************************************************************/
|
||||
void *
|
||||
ssl_des3_decrypt_info_create(const char *key, const char* ivec)
|
||||
ssl_des3_decrypt_info_create(const char *key, const char *ivec)
|
||||
{
|
||||
EVP_CIPHER_CTX *des3_ctx;
|
||||
const tui8 *lkey;
|
||||
@ -348,7 +348,7 @@ ssl_hmac_transform(void *hmac, const char *data, int len)
|
||||
const tui8 *ldata;
|
||||
|
||||
hmac_ctx = (HMAC_CTX *) hmac;
|
||||
ldata = (const tui8*) data;
|
||||
ldata = (const tui8 *) data;
|
||||
HMAC_Update(hmac_ctx, ldata, len);
|
||||
}
|
||||
|
||||
@ -357,7 +357,7 @@ void
|
||||
ssl_hmac_complete(void *hmac, char *data, int len)
|
||||
{
|
||||
HMAC_CTX *hmac_ctx;
|
||||
tui8* ldata;
|
||||
tui8 *ldata;
|
||||
tui32 llen;
|
||||
|
||||
hmac_ctx = (HMAC_CTX *) hmac;
|
||||
@ -464,7 +464,7 @@ ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
|
||||
int diff;
|
||||
|
||||
if ((exp_len != 4) || ((mod_len != 64) && (mod_len != 256)) ||
|
||||
((pri_len != 64) && (pri_len != 256)))
|
||||
((pri_len != 64) && (pri_len != 256)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -532,7 +532,8 @@ see also
|
||||
*/
|
||||
static DH *ssl_get_dh2236()
|
||||
{
|
||||
static unsigned char dh2236_p[] = {
|
||||
static unsigned char dh2236_p[] =
|
||||
{
|
||||
0x0E, 0xF8, 0x69, 0x0B, 0x35, 0x2F, 0x62, 0x59, 0xF7, 0xAF, 0x4E, 0x19,
|
||||
0xB5, 0x9B, 0xD2, 0xEB, 0x33, 0x78, 0x1D, 0x43, 0x1D, 0xB6, 0xE4, 0xA3,
|
||||
0x63, 0x47, 0x6A, 0xD4, 0xA8, 0x28, 0x11, 0x8C, 0x3F, 0xC8, 0xF1, 0x32,
|
||||
@ -558,7 +559,8 @@ static DH *ssl_get_dh2236()
|
||||
0x70, 0xAC, 0x58, 0x3A, 0x3C, 0x18, 0x15, 0x54, 0x84, 0xA8, 0xAA, 0x41,
|
||||
0x26, 0x7B, 0xE0, 0xA3,
|
||||
};
|
||||
static unsigned char dh2236_g[] = {
|
||||
static unsigned char dh2236_g[] =
|
||||
{
|
||||
0x02,
|
||||
};
|
||||
|
||||
@ -613,14 +615,13 @@ ssl_tls_create(struct trans *trans, const char *key, const char *cert)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
ssl_tls_print_error(const char *func, SSL *connection, int value)
|
||||
static int
|
||||
ssl_tls_log_error(const char *func, SSL *connection, int value)
|
||||
{
|
||||
switch (SSL_get_error(connection, value))
|
||||
{
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
g_writeln("ssl_tls_print_error: %s: Server closed TLS connection",
|
||||
func);
|
||||
LOG(LOG_LEVEL_ERROR, "%s: Server closed TLS connection", func);
|
||||
return 1;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
@ -628,16 +629,15 @@ ssl_tls_print_error(const char *func, SSL *connection, int value)
|
||||
return 0;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
g_writeln("ssl_tls_print_error: %s: I/O error", func);
|
||||
LOG(LOG_LEVEL_ERROR, "%s: I/O error", func);
|
||||
return 1;
|
||||
|
||||
case SSL_ERROR_SSL:
|
||||
g_writeln("ssl_tls_print_error: %s: Failure in SSL library (protocol error?)",
|
||||
func);
|
||||
LOG(LOG_LEVEL_ERROR, "%s: Failure in SSL library (protocol error?)", func);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
g_writeln("ssl_tls_print_error: %s: Unknown error", func);
|
||||
LOG(LOG_LEVEL_ERROR, "%s: Unknown SSL error", func);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -694,7 +694,7 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
|
||||
self->ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if (self->ctx == NULL)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "ssl_tls_accept: SSL_CTX_new failed");
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to negotiate a TLS connection with the client");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -708,20 +708,19 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
|
||||
DH *dh = ssl_get_dh2236();
|
||||
if (dh == NULL)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "ssl_tls_accept: ssl_get_dh2236 failed");
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to generate DHE parameters for TLS");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_set_tmp_dh(self->ctx, dh) != 1)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR,
|
||||
"ssl_tls_accept: SSL_CTX_set_tmp_dh failed");
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to setup DHE parameters for TLS");
|
||||
return 1;
|
||||
}
|
||||
DH_free(dh); // ok to free, copied into ctx by SSL_CTX_set_tmp_dh()
|
||||
|
||||
#if defined(SSL_CTX_set_ecdh_auto)
|
||||
if(!SSL_CTX_set_ecdh_auto(self->ctx, 1))
|
||||
if (!SSL_CTX_set_ecdh_auto(self->ctx, 1))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "TLS ecdh auto failed to be enabled");
|
||||
}
|
||||
@ -729,27 +728,26 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
|
||||
|
||||
if (g_strlen(tls_ciphers) > 1)
|
||||
{
|
||||
log_message(LOG_LEVEL_TRACE, "ssl_tls_accept: tls_ciphers=%s",
|
||||
tls_ciphers);
|
||||
LOG(LOG_LEVEL_TRACE, "tls_ciphers=%s", tls_ciphers);
|
||||
if (SSL_CTX_set_cipher_list(self->ctx, tls_ciphers) == 0)
|
||||
{
|
||||
g_writeln("ssl_tls_accept: invalid cipher options");
|
||||
LOG(LOG_LEVEL_ERROR, "Invalid TLS cipher options %s", tls_ciphers);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
SSL_CTX_set_read_ahead(self->ctx, 0);
|
||||
|
||||
if (SSL_CTX_use_RSAPrivateKey_file(self->ctx, self->key, SSL_FILETYPE_PEM)
|
||||
if (SSL_CTX_use_PrivateKey_file(self->ctx, self->key, SSL_FILETYPE_PEM)
|
||||
<= 0)
|
||||
{
|
||||
g_writeln("ssl_tls_accept: SSL_CTX_use_RSAPrivateKey_file failed");
|
||||
LOG(LOG_LEVEL_ERROR, "Error loading TLS private key from %s", self->key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(self->ctx, self->cert) <= 0)
|
||||
{
|
||||
g_writeln("ssl_tls_accept: SSL_CTX_use_certificate_chain_file failed");
|
||||
LOG(LOG_LEVEL_ERROR, "Error loading TLS certificate chain from %s", self->cert);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -757,22 +755,24 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
|
||||
|
||||
if (self->ssl == NULL)
|
||||
{
|
||||
g_writeln("ssl_tls_accept: SSL_new failed");
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to create an SSL structure");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SSL_set_fd(self->ssl, self->trans->sck) < 1)
|
||||
{
|
||||
g_writeln("ssl_tls_accept: SSL_set_fd failed");
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to set up an SSL structure on fd %d",
|
||||
(int)self->trans->sck);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
while (1)
|
||||
{
|
||||
connection_status = SSL_accept(self->ssl);
|
||||
|
||||
if (connection_status <= 0)
|
||||
{
|
||||
if (ssl_tls_print_error("SSL_accept", self->ssl, connection_status))
|
||||
if (ssl_tls_log_error("SSL_accept", self->ssl, connection_status))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -797,7 +797,7 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
|
||||
}
|
||||
}
|
||||
|
||||
g_writeln("ssl_tls_accept: TLS connection accepted");
|
||||
LOG(LOG_LEVEL_TRACE, "TLS connection accepted");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -823,7 +823,7 @@ ssl_tls_disconnect(struct ssl_tls *self)
|
||||
status = SSL_shutdown(self->ssl);
|
||||
if (status <= 0)
|
||||
{
|
||||
if (ssl_tls_print_error("SSL_shutdown", self->ssl, status))
|
||||
if (ssl_tls_log_error("SSL_shutdown", self->ssl, status))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -844,10 +844,14 @@ ssl_tls_delete(struct ssl_tls *self)
|
||||
if (self != NULL)
|
||||
{
|
||||
if (self->ssl)
|
||||
{
|
||||
SSL_free(self->ssl);
|
||||
}
|
||||
|
||||
if (self->ctx)
|
||||
{
|
||||
SSL_CTX_free(self->ctx);
|
||||
}
|
||||
|
||||
g_delete_wait_obj(self->rwo);
|
||||
|
||||
@ -862,7 +866,8 @@ ssl_tls_read(struct ssl_tls *tls, char *data, int length)
|
||||
int status;
|
||||
int break_flag;
|
||||
|
||||
while(1) {
|
||||
while (1)
|
||||
{
|
||||
status = SSL_read(tls->ssl, data, length);
|
||||
|
||||
switch (SSL_get_error(tls->ssl, status))
|
||||
@ -888,7 +893,7 @@ ssl_tls_read(struct ssl_tls *tls, char *data, int length)
|
||||
return 0;
|
||||
|
||||
default:
|
||||
ssl_tls_print_error("SSL_read", tls->ssl, status);
|
||||
ssl_tls_log_error("SSL_read", tls->ssl, status);
|
||||
status = -1;
|
||||
break_flag = 1;
|
||||
break;
|
||||
@ -915,7 +920,8 @@ ssl_tls_write(struct ssl_tls *tls, const char *data, int length)
|
||||
int status;
|
||||
int break_flag;
|
||||
|
||||
while(1) {
|
||||
while (1)
|
||||
{
|
||||
status = SSL_write(tls->ssl, data, length);
|
||||
|
||||
switch (SSL_get_error(tls->ssl, status))
|
||||
@ -941,7 +947,7 @@ ssl_tls_write(struct ssl_tls *tls, const char *data, int length)
|
||||
return 0;
|
||||
|
||||
default:
|
||||
ssl_tls_print_error("SSL_write", tls->ssl, status);
|
||||
ssl_tls_log_error("SSL_write", tls->ssl, status);
|
||||
status = -1;
|
||||
break_flag = 1;
|
||||
break;
|
||||
@ -1016,68 +1022,68 @@ ssl_get_protocols_from_string(const char *str, long *ssl_protocols)
|
||||
if (g_pos(str, ",TLSv1.3,") >= 0)
|
||||
{
|
||||
#if defined(SSL_OP_NO_TLSv1_3)
|
||||
log_message(LOG_LEVEL_DEBUG, "TLSv1.3 enabled");
|
||||
LOG(LOG_LEVEL_DEBUG, "TLSv1.3 enabled");
|
||||
protocols &= ~SSL_OP_NO_TLSv1_3;
|
||||
#else
|
||||
log_message(LOG_LEVEL_WARNING,
|
||||
"TLSv1.3 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"TLSv1.3 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
rv |= (1 << 6);
|
||||
#endif
|
||||
}
|
||||
if (g_pos(str, ",TLSv1.2,") >= 0)
|
||||
{
|
||||
#if defined(SSL_OP_NO_TLSv1_2)
|
||||
log_message(LOG_LEVEL_DEBUG, "TLSv1.2 enabled");
|
||||
LOG(LOG_LEVEL_DEBUG, "TLSv1.2 enabled");
|
||||
protocols &= ~SSL_OP_NO_TLSv1_2;
|
||||
#else
|
||||
log_message(LOG_LEVEL_WARNING,
|
||||
"TLSv1.2 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"TLSv1.2 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
rv |= (1 << 1);
|
||||
#endif
|
||||
}
|
||||
if (g_pos(str, ",TLSv1.1,") >= 0)
|
||||
{
|
||||
#if defined(SSL_OP_NO_TLSv1_1)
|
||||
log_message(LOG_LEVEL_DEBUG, "TLSv1.1 enabled");
|
||||
LOG(LOG_LEVEL_DEBUG, "TLSv1.1 enabled");
|
||||
protocols &= ~SSL_OP_NO_TLSv1_1;
|
||||
#else
|
||||
log_message(LOG_LEVEL_WARNING,
|
||||
"TLSv1.1 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"TLSv1.1 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
rv |= (1 << 2);
|
||||
#endif
|
||||
}
|
||||
if (g_pos(str, ",TLSv1,") >= 0)
|
||||
{
|
||||
#if defined(SSL_OP_NO_TLSv1)
|
||||
log_message(LOG_LEVEL_DEBUG, "TLSv1 enabled");
|
||||
LOG(LOG_LEVEL_DEBUG, "TLSv1 enabled");
|
||||
protocols &= ~SSL_OP_NO_TLSv1;
|
||||
#else
|
||||
log_message(LOG_LEVEL_WARNING,
|
||||
"TLSv1 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"TLSv1 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
rv |= (1 << 3);
|
||||
#endif
|
||||
}
|
||||
if (g_pos(str, ",SSLv3,") >= 0)
|
||||
{
|
||||
#if defined(SSL_OP_NO_SSLv3)
|
||||
log_message(LOG_LEVEL_DEBUG, "SSLv3 enabled");
|
||||
LOG(LOG_LEVEL_DEBUG, "SSLv3 enabled");
|
||||
protocols &= ~SSL_OP_NO_SSLv3;
|
||||
#else
|
||||
log_message(LOG_LEVEL_WARNING,
|
||||
"SSLv3 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"SSLv3 enabled by config, "
|
||||
"but not supported by system OpenSSL");
|
||||
rv |= (1 << 4);
|
||||
#endif
|
||||
}
|
||||
if (protocols == bad_protocols)
|
||||
{
|
||||
log_message(LOG_LEVEL_WARNING, "No SSL/TLS protocols enabled. "
|
||||
"At least one protocol should be enabled to accept "
|
||||
"TLS connections.");
|
||||
LOG(LOG_LEVEL_WARNING, "No SSL/TLS protocols enabled. "
|
||||
"At least one protocol should be enabled to accept "
|
||||
"TLS connections.");
|
||||
rv |= (1 << 5);
|
||||
}
|
||||
*ssl_protocols = protocols;
|
||||
|
||||
@ -26,38 +26,38 @@ int
|
||||
ssl_init(void);
|
||||
int
|
||||
ssl_finish(void);
|
||||
void*
|
||||
void *
|
||||
ssl_rc4_info_create(void);
|
||||
void
|
||||
ssl_rc4_info_delete(void* rc4_info);
|
||||
ssl_rc4_info_delete(void *rc4_info);
|
||||
void
|
||||
ssl_rc4_set_key(void* rc4_info, char* key, int len);
|
||||
ssl_rc4_set_key(void *rc4_info, char *key, int len);
|
||||
void
|
||||
ssl_rc4_crypt(void* rc4_info, char* data, int len);
|
||||
void*
|
||||
ssl_rc4_crypt(void *rc4_info, char *data, int len);
|
||||
void *
|
||||
ssl_sha1_info_create(void);
|
||||
void
|
||||
ssl_sha1_info_delete(void* sha1_info);
|
||||
ssl_sha1_info_delete(void *sha1_info);
|
||||
void
|
||||
ssl_sha1_clear(void* sha1_info);
|
||||
ssl_sha1_clear(void *sha1_info);
|
||||
void
|
||||
ssl_sha1_transform(void* sha1_info, const char *data, int len);
|
||||
ssl_sha1_transform(void *sha1_info, const char *data, int len);
|
||||
void
|
||||
ssl_sha1_complete(void* sha1_info, char* data);
|
||||
void*
|
||||
ssl_sha1_complete(void *sha1_info, char *data);
|
||||
void *
|
||||
ssl_md5_info_create(void);
|
||||
void
|
||||
ssl_md5_info_delete(void* md5_info);
|
||||
ssl_md5_info_delete(void *md5_info);
|
||||
void
|
||||
ssl_md5_clear(void* md5_info);
|
||||
ssl_md5_clear(void *md5_info);
|
||||
void
|
||||
ssl_md5_transform(void* md5_info, char* data, int len);
|
||||
ssl_md5_transform(void *md5_info, char *data, int len);
|
||||
void
|
||||
ssl_md5_complete(void* md5_info, char* data);
|
||||
ssl_md5_complete(void *md5_info, char *data);
|
||||
void *
|
||||
ssl_des3_encrypt_info_create(const char *key, const char* ivec);
|
||||
ssl_des3_encrypt_info_create(const char *key, const char *ivec);
|
||||
void *
|
||||
ssl_des3_decrypt_info_create(const char *key, const char* ivec);
|
||||
ssl_des3_decrypt_info_create(const char *key, const char *ivec);
|
||||
void
|
||||
ssl_des3_info_delete(void *des3);
|
||||
int
|
||||
@ -78,8 +78,8 @@ int
|
||||
ssl_mod_exp(char *out, int out_len, const char *in, int in_len,
|
||||
const char *mod, int mod_len, const char *exp, int exp_len);
|
||||
int
|
||||
ssl_gen_key_xrdp1(int key_size_in_bits, const char* exp, int exp_len,
|
||||
char* mod, int mod_len, char* pri, int pri_len);
|
||||
ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
|
||||
char *mod, int mod_len, char *pri, int pri_len);
|
||||
|
||||
/* ssl_tls */
|
||||
struct ssl_tls
|
||||
|
||||
@ -24,9 +24,13 @@
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "string_calls.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
#include "defines.h"
|
||||
|
||||
unsigned int
|
||||
g_format_info_string(char *dest, unsigned int len,
|
||||
@ -139,6 +143,36 @@ g_text2bool(const char *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
g_get_display_num_from_display(const char *display_text)
|
||||
{
|
||||
int rv = -1;
|
||||
const char *p;
|
||||
|
||||
/* Skip over the hostname part of the DISPLAY */
|
||||
if (display_text != NULL && (p = strchr(display_text, ':')) != NULL)
|
||||
{
|
||||
++p; /* Skip the ':' */
|
||||
|
||||
/* Cater for the (still supported) double-colon. See
|
||||
* https://www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html */
|
||||
if (*p == ':')
|
||||
{
|
||||
++p;
|
||||
}
|
||||
|
||||
/* Check it starts with a digit, to avoid oddities like DISPLAY=":zz.0"
|
||||
* being parsed successfully */
|
||||
if (isdigit(*p))
|
||||
{
|
||||
rv = g_atoi(p);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns length of text */
|
||||
int
|
||||
@ -470,6 +504,129 @@ g_bytes_to_hexstr(const void *bytes, int num_bytes, char *out_str,
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* convert a byte array into a hex dump */
|
||||
char *
|
||||
g_bytes_to_hexdump(const char *src, int len)
|
||||
{
|
||||
unsigned char *line;
|
||||
int i;
|
||||
int dump_number_lines;
|
||||
int dump_line_length;
|
||||
int dump_length;
|
||||
int dump_offset;
|
||||
int thisline;
|
||||
int offset;
|
||||
char *dump_buffer;
|
||||
|
||||
#define HEX_DUMP_SOURCE_BYTES_PER_LINE (16)
|
||||
#ifdef _WIN32
|
||||
#define HEX_DUMP_NEWLINE_SIZE (2)
|
||||
#else
|
||||
#ifdef _MACOS
|
||||
#define HEX_DUMP_NEWLINE_SIZE (1)
|
||||
#else
|
||||
#define HEX_DUMP_NEWLINE_SIZE (1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
dump_line_length = (4 + 3 /* = 4 offset + 3 space */
|
||||
+ ((2 + 1) * HEX_DUMP_SOURCE_BYTES_PER_LINE) /* + (2 hex char + 1 space) per source byte */
|
||||
+ 2 /* + 2 space */
|
||||
+ HEX_DUMP_SOURCE_BYTES_PER_LINE
|
||||
+ HEX_DUMP_NEWLINE_SIZE);
|
||||
|
||||
dump_number_lines = (len / HEX_DUMP_SOURCE_BYTES_PER_LINE) + 1; /* +1 to round up */
|
||||
dump_length = (dump_number_lines *dump_line_length /* hex dump lines */
|
||||
+ 1); /* terminating NULL */
|
||||
dump_buffer = (char *)g_malloc(dump_length, 1);
|
||||
if (dump_buffer == NULL)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
||||
"Failed to allocate buffer for hex dump of size %d",
|
||||
dump_length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = (unsigned char *)src;
|
||||
offset = 0;
|
||||
dump_offset = 0;
|
||||
|
||||
while (offset < len)
|
||||
{
|
||||
g_sprintf(dump_buffer + dump_offset, "%04x ", offset);
|
||||
dump_offset += 7;
|
||||
thisline = len - offset;
|
||||
|
||||
if (thisline > HEX_DUMP_SOURCE_BYTES_PER_LINE)
|
||||
{
|
||||
thisline = HEX_DUMP_SOURCE_BYTES_PER_LINE;
|
||||
}
|
||||
|
||||
for (i = 0; i < thisline; i++)
|
||||
{
|
||||
g_sprintf(dump_buffer + dump_offset, "%02x ", line[i]);
|
||||
dump_offset += 3;
|
||||
}
|
||||
|
||||
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
|
||||
{
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
}
|
||||
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
|
||||
for (i = 0; i < thisline; i++)
|
||||
{
|
||||
dump_buffer[dump_offset++] = (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.';
|
||||
}
|
||||
|
||||
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
|
||||
{
|
||||
dump_buffer[dump_offset++] = ' ';
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
dump_buffer[dump_offset++] = '\r';
|
||||
dump_buffer[dump_offset++] = '\n';
|
||||
#else
|
||||
#ifdef _MACOS
|
||||
dump_buffer[dump_offset++] = '\r';
|
||||
#else
|
||||
dump_buffer[dump_offset++] = '\n';
|
||||
#endif
|
||||
#endif
|
||||
offset += thisline;
|
||||
line += thisline;
|
||||
|
||||
|
||||
if (dump_offset % dump_line_length != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
||||
"BUG: dump_offset (%d) at the end of a line is not a "
|
||||
"multiple of the line length (%d)",
|
||||
dump_offset, dump_line_length);
|
||||
}
|
||||
|
||||
}
|
||||
if (dump_offset > dump_length)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
||||
"BUG: dump_offset (%d) is larger than the dump_buffer length (%d)",
|
||||
dump_offset, dump_length);
|
||||
dump_buffer[0] = '\0';
|
||||
return dump_buffer;
|
||||
}
|
||||
|
||||
/* replace the last new line with the end of the string since log_message
|
||||
will add a new line */
|
||||
dump_buffer[dump_offset - HEX_DUMP_NEWLINE_SIZE] = '\0';
|
||||
return dump_buffer;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
g_pos(const char *str, const char *to_find)
|
||||
@ -651,3 +808,49 @@ g_strtrim(char *str, int trim_flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
char *
|
||||
g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int src_len)
|
||||
{
|
||||
int len = 0;
|
||||
int joiner_len;
|
||||
int i = 0;
|
||||
int dest_remaining;
|
||||
char *dest_pos = dest;
|
||||
char *dest_end;
|
||||
|
||||
if (dest == NULL || dest_len < 1)
|
||||
{
|
||||
return dest;
|
||||
}
|
||||
if (src == NULL || src_len < 1)
|
||||
{
|
||||
dest[0] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
dest[0] = '\0';
|
||||
dest_end = dest + dest_len - 1;
|
||||
joiner_len = g_strlen(joiner);
|
||||
for (i = 0; i < src_len - 1 && dest_pos < dest_end; i++)
|
||||
{
|
||||
len = g_strlen(src[i]);
|
||||
dest_remaining = dest_end - dest_pos;
|
||||
g_strncat(dest_pos, src[i], dest_remaining);
|
||||
dest_pos += MIN(len, dest_remaining);
|
||||
|
||||
if (dest_pos < dest_end)
|
||||
{
|
||||
dest_remaining = dest_end - dest_pos;
|
||||
g_strncat(dest_pos, joiner, dest_remaining);
|
||||
dest_pos += MIN(joiner_len, dest_remaining);
|
||||
}
|
||||
}
|
||||
|
||||
if (i == src_len - 1 && dest_pos < dest_end)
|
||||
{
|
||||
g_strncat(dest_pos, src[i], dest_end - dest_pos);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@ -80,6 +80,66 @@ g_bool2text(int value);
|
||||
int
|
||||
g_text2bool(const char *s);
|
||||
|
||||
/**
|
||||
* Joins an array of strings into a single string.
|
||||
*
|
||||
* Note: The joiner is placed between each source string. The joiner is not
|
||||
* placed after the last source string. If there is only one source string,
|
||||
* then the result string will be equal to the source string.
|
||||
*
|
||||
* Note: any content that is present in dest will be overwritten with the new
|
||||
* joined string.
|
||||
*
|
||||
* Note: If the destination array is not large enough to hold the entire
|
||||
* contents of the joined string, then the joined string will be truncated
|
||||
* to fit in the destination array.
|
||||
*
|
||||
* @param[out] dest The destination array to write the joined string into.
|
||||
* @param[in] dest_len The max number of characters to write to the destination
|
||||
* array including the terminating null. Must be > 0
|
||||
* @param[in] joiner The string to concatenate between each source string.
|
||||
* The joiner string may be NULL which is processed as a zero length string.
|
||||
* @param[in] src An array of strings to join. The array must be non-null.
|
||||
* Array items may be NULL and are processed as zero length strings.
|
||||
* @param[in] src_len The number of strings to join in the src array. Must be > 0
|
||||
* @return A pointer to the begining of the joined string (ie. returns dest).
|
||||
*/
|
||||
char *
|
||||
g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int src_len);
|
||||
|
||||
/**
|
||||
* Converts a binary array into a hux dump suitable for displaying to a user.
|
||||
*
|
||||
* The format of the hex dump is:
|
||||
* 0000 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 ................
|
||||
* /\ /\ /\
|
||||
* | | |
|
||||
* | | ascii representation of bytes
|
||||
* | hex representation of bytes
|
||||
* offset from beginning of the byte array in hex
|
||||
*
|
||||
* Note: the ascii representation uses '.' for all non-printable
|
||||
* characters (eg. below 32 or above 127).
|
||||
*
|
||||
* Note: the string contains embedded new lines, but is not new line terminated.
|
||||
*
|
||||
* @param[in] src Value to convert
|
||||
* @param[in] len The number of bytes in src to convert
|
||||
* @return string containing the hex dump that must be free'd by the caller
|
||||
*/
|
||||
char *
|
||||
g_bytes_to_hexdump(const char *src, int len);
|
||||
|
||||
/**
|
||||
* Extracts the display number from an X11 display string
|
||||
*
|
||||
* @param Display string (i.e. g_getenv("DISPLAY"))
|
||||
*
|
||||
* @result <0 if the string could not be parsed, or >=0 for a display number
|
||||
*/
|
||||
int
|
||||
g_get_display_num_from_display(const char *display_text);
|
||||
|
||||
int g_strlen(const char *text);
|
||||
const char *g_strchr(const char *text, int c);
|
||||
char *g_strcpy(char *dest, const char *src);
|
||||
|
||||
@ -55,7 +55,7 @@ tc_thread_create(unsigned long (__stdcall *start_routine)(void *), void *arg)
|
||||
}
|
||||
#else
|
||||
int
|
||||
tc_thread_create(void * (* start_routine)(void *), void *arg)
|
||||
tc_thread_create(void *(* start_routine)(void *), void *arg)
|
||||
{
|
||||
int rv = 0;
|
||||
pthread_t thread = (pthread_t)0;
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
#include "arch.h"
|
||||
|
||||
int
|
||||
tc_thread_create(THREAD_RV (THREAD_CC * start_routine)(void*), void* arg);
|
||||
tc_thread_create(THREAD_RV (THREAD_CC *start_routine)(void *), void *arg);
|
||||
tbus
|
||||
tc_get_threadid(void);
|
||||
int
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "arch.h"
|
||||
#include "parse.h"
|
||||
#include "ssl_calls.h"
|
||||
#include "log.h"
|
||||
|
||||
#define MAX_SBYTES 0
|
||||
|
||||
@ -454,7 +455,7 @@ trans_force_read_s(struct trans *self, struct stream *in_s, int size)
|
||||
int rcvd;
|
||||
|
||||
if (self->status != TRANS_STATUS_UP ||
|
||||
size < 0 || !s_check_rem_out(in_s, size))
|
||||
size < 0 || !s_check_rem_out(in_s, size))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -635,7 +636,7 @@ trans_write_copy_s(struct trans *self, struct stream *out_s)
|
||||
if (self->si != 0)
|
||||
{
|
||||
if ((self->si->cur_source != XRDP_SOURCE_NONE) &&
|
||||
(self->si->cur_source != self->my_source))
|
||||
(self->si->cur_source != self->my_source))
|
||||
{
|
||||
self->si->source[self->si->cur_source] += size;
|
||||
wait_s->source = self->si->source + self->si->cur_source;
|
||||
@ -662,7 +663,7 @@ trans_write_copy_s(struct trans *self, struct stream *out_s)
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
trans_write_copy(struct trans* self)
|
||||
trans_write_copy(struct trans *self)
|
||||
{
|
||||
return trans_write_copy_s(self, self->out_s);
|
||||
}
|
||||
@ -824,7 +825,9 @@ trans_listen_address(struct trans *self, char *port, const char *address)
|
||||
{
|
||||
self->sck = g_tcp_socket();
|
||||
if (self->sck < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_tcp_set_non_blocking(self->sck);
|
||||
|
||||
@ -846,7 +849,9 @@ trans_listen_address(struct trans *self, char *port, const char *address)
|
||||
|
||||
self->sck = g_tcp_local_socket();
|
||||
if (self->sck < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_tcp_set_non_blocking(self->sck);
|
||||
|
||||
@ -975,13 +980,13 @@ trans_set_tls_mode(struct trans *self, const char *key, const char *cert,
|
||||
self->tls = ssl_tls_create(self, key, cert);
|
||||
if (self->tls == NULL)
|
||||
{
|
||||
g_writeln("trans_set_tls_mode: ssl_tls_create malloc error");
|
||||
LOG(LOG_LEVEL_ERROR, "trans_set_tls_mode: ssl_tls_create malloc error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ssl_tls_accept(self->tls, ssl_protocols, tls_ciphers) != 0)
|
||||
{
|
||||
g_writeln("trans_set_tls_mode: ssl_tls_accept failed");
|
||||
LOG(LOG_LEVEL_ERROR, "trans_set_tls_mode: ssl_tls_accept failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -40,9 +40,9 @@
|
||||
struct trans; /* forward declaration */
|
||||
struct xrdp_tls;
|
||||
|
||||
typedef int (*ttrans_data_in)(struct trans* self);
|
||||
typedef int (*ttrans_conn_in)(struct trans* self,
|
||||
struct trans* new_self);
|
||||
typedef int (*ttrans_data_in)(struct trans *self);
|
||||
typedef int (*ttrans_conn_in)(struct trans *self,
|
||||
struct trans *new_self);
|
||||
typedef int (*tis_term)(void);
|
||||
typedef int (*trans_recv_proc) (struct trans *self, char *ptr, int len);
|
||||
typedef int (*trans_send_proc) (struct trans *self, const char *data, int len);
|
||||
@ -97,13 +97,13 @@ struct trans
|
||||
int type1; /* 1 listener 2 server 3 client */
|
||||
ttrans_data_in trans_data_in;
|
||||
ttrans_conn_in trans_conn_in;
|
||||
void* callback_data;
|
||||
void *callback_data;
|
||||
int header_size;
|
||||
struct stream* in_s;
|
||||
struct stream* out_s;
|
||||
char* listen_filename;
|
||||
struct stream *in_s;
|
||||
struct stream *out_s;
|
||||
char *listen_filename;
|
||||
tis_term is_term; /* used to test for exit */
|
||||
struct stream* wait_s;
|
||||
struct stream *wait_s;
|
||||
char addr[256];
|
||||
char port[256];
|
||||
int no_stream_init_on_data_in;
|
||||
@ -118,43 +118,43 @@ struct trans
|
||||
enum xrdp_source my_source;
|
||||
};
|
||||
|
||||
struct trans*
|
||||
struct trans *
|
||||
trans_create(int mode, int in_size, int out_size);
|
||||
void
|
||||
trans_delete(struct trans* self);
|
||||
trans_delete(struct trans *self);
|
||||
void
|
||||
trans_delete_from_child(struct trans* self);
|
||||
trans_delete_from_child(struct trans *self);
|
||||
int
|
||||
trans_get_wait_objs(struct trans* self, tbus* objs, int* count);
|
||||
trans_get_wait_objs(struct trans *self, tbus *objs, int *count);
|
||||
int
|
||||
trans_get_wait_objs_rw(struct trans *self,
|
||||
tbus *robjs, int *rcount,
|
||||
tbus *wobjs, int *wcount, int *timeout);
|
||||
int
|
||||
trans_check_wait_objs(struct trans* self);
|
||||
trans_check_wait_objs(struct trans *self);
|
||||
int
|
||||
trans_force_read_s(struct trans* self, struct stream* in_s, int size);
|
||||
trans_force_read_s(struct trans *self, struct stream *in_s, int size);
|
||||
int
|
||||
trans_force_write_s(struct trans* self, struct stream* out_s);
|
||||
trans_force_write_s(struct trans *self, struct stream *out_s);
|
||||
int
|
||||
trans_force_read(struct trans* self, int size);
|
||||
trans_force_read(struct trans *self, int size);
|
||||
int
|
||||
trans_force_write(struct trans* self);
|
||||
trans_force_write(struct trans *self);
|
||||
int
|
||||
trans_write_copy(struct trans* self);
|
||||
trans_write_copy(struct trans *self);
|
||||
int
|
||||
trans_write_copy_s(struct trans* self, struct stream* out_s);
|
||||
trans_write_copy_s(struct trans *self, struct stream *out_s);
|
||||
int
|
||||
trans_connect(struct trans* self, const char* server, const char* port,
|
||||
trans_connect(struct trans *self, const char *server, const char *port,
|
||||
int timeout);
|
||||
int
|
||||
trans_listen_address(struct trans* self, char* port, const char* address);
|
||||
trans_listen_address(struct trans *self, char *port, const char *address);
|
||||
int
|
||||
trans_listen(struct trans* self, char* port);
|
||||
struct stream*
|
||||
trans_get_in_s(struct trans* self);
|
||||
struct stream*
|
||||
trans_get_out_s(struct trans* self, int size);
|
||||
trans_listen(struct trans *self, char *port);
|
||||
struct stream *
|
||||
trans_get_in_s(struct trans *self);
|
||||
struct stream *
|
||||
trans_get_out_s(struct trans *self, int size);
|
||||
int
|
||||
trans_set_tls_mode(struct trans *self, const char *key, const char *cert,
|
||||
long ssl_protocols, const char *tls_ciphers);
|
||||
|
||||
@ -19,149 +19,162 @@
|
||||
*/
|
||||
|
||||
#include "xrdp_constants.h"
|
||||
#include "ms-rdpbcgr.h"
|
||||
|
||||
#if !defined(XRDP_CLIENT_INFO_H)
|
||||
#define XRDP_CLIENT_INFO_H
|
||||
|
||||
struct monitor_info
|
||||
{
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
int is_primary;
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
int is_primary;
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about the xrdp client
|
||||
*
|
||||
* @note This structure is shared with xorgxrdp. If you change anything
|
||||
* above the 'private to xrdp below this line' comment, you MUST
|
||||
* bump the CLIENT_INFO_CURRENT_VERSION number so that the mismatch
|
||||
* can be detected.
|
||||
*/
|
||||
struct xrdp_client_info
|
||||
{
|
||||
int size; /* bytes for this structure */
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
/* bitmap cache info */
|
||||
int cache1_entries;
|
||||
int cache1_size;
|
||||
int cache2_entries;
|
||||
int cache2_size;
|
||||
int cache3_entries;
|
||||
int cache3_size;
|
||||
int bitmap_cache_persist_enable; /* 0 or 2 */
|
||||
int bitmap_cache_version; /* ored 1 = original version, 2 = v2, 4 = v3 */
|
||||
/* pointer info */
|
||||
int pointer_cache_entries;
|
||||
/* other */
|
||||
int use_bitmap_comp;
|
||||
int use_bitmap_cache;
|
||||
int op1; /* use smaller bitmap header, non cache */
|
||||
int op2; /* use smaller bitmap header in bitmap cache */
|
||||
int desktop_cache;
|
||||
int use_compact_packets; /* rdp5 smaller packets */
|
||||
char hostname[32];
|
||||
int build;
|
||||
int keylayout;
|
||||
char username[INFO_CLIENT_MAX_CB_LEN];
|
||||
char password[INFO_CLIENT_MAX_CB_LEN];
|
||||
char domain[INFO_CLIENT_MAX_CB_LEN];
|
||||
char program[INFO_CLIENT_MAX_CB_LEN];
|
||||
char directory[INFO_CLIENT_MAX_CB_LEN];
|
||||
int rdp_compression;
|
||||
int rdp_autologin;
|
||||
int crypt_level; /* 1, 2, 3 = low, medium, high */
|
||||
int channels_allowed; /* 0 = no channels 1 = channels */
|
||||
int sound_code; /* 1 = leave sound at server */
|
||||
int is_mce;
|
||||
int rdp5_performanceflags;
|
||||
int brush_cache_code; /* 0 = no cache 1 = 8x8 standard cache
|
||||
int size; /* bytes for this structure */
|
||||
int version; /* Should be CLIENT_INFO_CURRENT_VERSION */
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
/* bitmap cache info */
|
||||
int cache1_entries;
|
||||
int cache1_size;
|
||||
int cache2_entries;
|
||||
int cache2_size;
|
||||
int cache3_entries;
|
||||
int cache3_size;
|
||||
int bitmap_cache_persist_enable; /* 0 or 2 */
|
||||
int bitmap_cache_version; /* ored 1 = original version, 2 = v2, 4 = v3 */
|
||||
/* pointer info */
|
||||
int pointer_cache_entries;
|
||||
/* other */
|
||||
int use_bitmap_comp;
|
||||
int use_bitmap_cache;
|
||||
int op1; /* use smaller bitmap header, non cache */
|
||||
int op2; /* use smaller bitmap header in bitmap cache */
|
||||
int desktop_cache;
|
||||
int use_compact_packets; /* rdp5 smaller packets */
|
||||
char hostname[32];
|
||||
int build;
|
||||
int keylayout;
|
||||
char username[INFO_CLIENT_MAX_CB_LEN];
|
||||
char password[INFO_CLIENT_MAX_CB_LEN];
|
||||
char domain[INFO_CLIENT_MAX_CB_LEN];
|
||||
char program[INFO_CLIENT_MAX_CB_LEN];
|
||||
char directory[INFO_CLIENT_MAX_CB_LEN];
|
||||
int rdp_compression;
|
||||
int rdp_autologin;
|
||||
int crypt_level; /* 1, 2, 3 = low, medium, high */
|
||||
int channels_allowed; /* 0 = no channels 1 = channels */
|
||||
int sound_code; /* 1 = leave sound at server */
|
||||
int is_mce;
|
||||
int rdp5_performanceflags;
|
||||
int brush_cache_code; /* 0 = no cache 1 = 8x8 standard cache
|
||||
2 = arbitrary dimensions */
|
||||
char client_ip[256];
|
||||
int max_bpp;
|
||||
int jpeg; /* non standard bitmap cache v2 cap */
|
||||
int offscreen_support_level;
|
||||
int offscreen_cache_size;
|
||||
int offscreen_cache_entries;
|
||||
int rfx;
|
||||
char client_ip[256];
|
||||
int max_bpp;
|
||||
int jpeg; /* non standard bitmap cache v2 cap */
|
||||
int offscreen_support_level;
|
||||
int offscreen_cache_size;
|
||||
int offscreen_cache_entries;
|
||||
int rfx;
|
||||
|
||||
/* CAPSETTYPE_RAIL */
|
||||
int rail_support_level;
|
||||
/* CAPSETTYPE_WINDOW */
|
||||
int wnd_support_level;
|
||||
int wnd_num_icon_caches;
|
||||
int wnd_num_icon_cache_entries;
|
||||
/* codecs */
|
||||
int rfx_codec_id;
|
||||
int rfx_prop_len;
|
||||
char rfx_prop[64];
|
||||
int ns_codec_id;
|
||||
int ns_prop_len;
|
||||
char ns_prop[64];
|
||||
int jpeg_codec_id;
|
||||
int jpeg_prop_len;
|
||||
char jpeg_prop[64];
|
||||
int v3_codec_id;
|
||||
int rfx_min_pixel;
|
||||
char orders[32];
|
||||
int order_flags_ex;
|
||||
int use_bulk_comp;
|
||||
int pointer_flags; /* 0 color, 1 new, 2 no new */
|
||||
int use_fast_path;
|
||||
int require_credentials; /* when true, credentials *must* be passed on cmd line */
|
||||
char client_addr[256];
|
||||
char client_port[256];
|
||||
/* CAPSETTYPE_RAIL */
|
||||
int rail_support_level;
|
||||
/* CAPSETTYPE_WINDOW */
|
||||
int wnd_support_level;
|
||||
int wnd_num_icon_caches;
|
||||
int wnd_num_icon_cache_entries;
|
||||
/* codecs */
|
||||
int rfx_codec_id;
|
||||
int rfx_prop_len;
|
||||
char rfx_prop[64];
|
||||
int ns_codec_id;
|
||||
int ns_prop_len;
|
||||
char ns_prop[64];
|
||||
int jpeg_codec_id;
|
||||
int jpeg_prop_len;
|
||||
char jpeg_prop[64];
|
||||
int v3_codec_id;
|
||||
int rfx_min_pixel;
|
||||
char orders[32];
|
||||
int order_flags_ex;
|
||||
int use_bulk_comp;
|
||||
int pointer_flags; /* 0 color, 1 new, 2 no new */
|
||||
int use_fast_path;
|
||||
int require_credentials; /* when true, credentials *must* be passed on cmd line */
|
||||
char client_addr[256];
|
||||
char client_port[256];
|
||||
|
||||
int security_layer; /* 0 = rdp, 1 = tls , 2 = hybrid */
|
||||
int multimon; /* 0 = deny , 1 = allow */
|
||||
int monitorCount; /* number of monitors detected (max = 16) */
|
||||
struct monitor_info minfo[16]; /* client monitor data */
|
||||
struct monitor_info minfo_wm[16]; /* client monitor data, non-negative values */
|
||||
int security_layer; /* 0 = rdp, 1 = tls , 2 = hybrid */
|
||||
int multimon; /* 0 = deny , 1 = allow */
|
||||
int monitorCount; /* number of monitors detected (max = 16) */
|
||||
struct monitor_info minfo[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data */
|
||||
struct monitor_info minfo_wm[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data, non-negative values */
|
||||
|
||||
int keyboard_type;
|
||||
int keyboard_subtype;
|
||||
int keyboard_type;
|
||||
int keyboard_subtype;
|
||||
|
||||
int png_codec_id;
|
||||
int png_prop_len;
|
||||
char png_prop[64];
|
||||
int vendor_flags[4];
|
||||
int mcs_connection_type;
|
||||
int mcs_early_capability_flags;
|
||||
int png_codec_id;
|
||||
int png_prop_len;
|
||||
char png_prop[64];
|
||||
int vendor_flags[4];
|
||||
int mcs_connection_type;
|
||||
int mcs_early_capability_flags;
|
||||
|
||||
int max_fastpath_frag_bytes;
|
||||
int capture_code;
|
||||
int capture_format;
|
||||
int max_fastpath_frag_bytes;
|
||||
int capture_code;
|
||||
int capture_format;
|
||||
|
||||
char certificate[1024];
|
||||
char key_file[1024];
|
||||
char certificate[1024];
|
||||
char key_file[1024];
|
||||
|
||||
/* X11 keyboard layout - inferred from keyboard type/subtype */
|
||||
char model[16];
|
||||
char layout[16];
|
||||
char variant[16];
|
||||
char options[256];
|
||||
/* X11 keyboard layout - inferred from keyboard type/subtype */
|
||||
char model[16];
|
||||
char layout[16];
|
||||
char variant[16];
|
||||
char options[256];
|
||||
|
||||
/* !!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||
/* NO CHANGES ABOVE THIS LINE */
|
||||
/* !!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||
/* ==================================================================== */
|
||||
/* Private to xrdp below this line */
|
||||
/* ==================================================================== */
|
||||
|
||||
/* codec */
|
||||
int h264_codec_id;
|
||||
int h264_prop_len;
|
||||
char h264_prop[64];
|
||||
/* codec */
|
||||
int h264_codec_id;
|
||||
int h264_prop_len;
|
||||
char h264_prop[64];
|
||||
|
||||
int use_frame_acks;
|
||||
int max_unacknowledged_frame_count;
|
||||
int use_frame_acks;
|
||||
int max_unacknowledged_frame_count;
|
||||
|
||||
long ssl_protocols;
|
||||
char *tls_ciphers;
|
||||
long ssl_protocols;
|
||||
char *tls_ciphers;
|
||||
|
||||
int client_os_major;
|
||||
int client_os_minor;
|
||||
int client_os_major;
|
||||
int client_os_minor;
|
||||
|
||||
int no_orders_supported;
|
||||
int use_cache_glyph_v2;
|
||||
int rail_enable;
|
||||
int suppress_output;
|
||||
int no_orders_supported;
|
||||
int use_cache_glyph_v2;
|
||||
int rail_enable;
|
||||
int suppress_output;
|
||||
|
||||
int enable_token_login;
|
||||
char domain_user_separator[16];
|
||||
int enable_token_login;
|
||||
char domain_user_separator[16];
|
||||
};
|
||||
|
||||
/* yyyymmdd of last incompatible change to xrdp_client_info */
|
||||
#define CLIENT_INFO_CURRENT_VERSION 20210225
|
||||
|
||||
#endif
|
||||
|
||||
@ -95,8 +95,8 @@
|
||||
* not yet sorted out
|
||||
*/
|
||||
|
||||
#define MCS_CONNECT_INITIAL 0x7f65
|
||||
#define MCS_CONNECT_RESPONSE 0x7f66
|
||||
#define MCS_CONNECT_INITIAL 0x7f65 /* MCS BER: big endian, class=application (0x4000), constructed (0x2000), tag number > 30 (0x1f00), tag number=101 (0x0065) */
|
||||
#define MCS_CONNECT_RESPONSE 0x7f66 /* MCS BER: application 102 */
|
||||
|
||||
#define BER_TAG_BOOLEAN 1
|
||||
#define BER_TAG_INTEGER 2
|
||||
@ -180,7 +180,7 @@
|
||||
#define MASK_REMOVE_BITS(var, mask) (var &= ~mask)
|
||||
#define MASK_HAS_BITS(var, mask) ((var & mask)>0)
|
||||
#define MASK_CHANGE_BIT(var, mask, active) \
|
||||
(var = ((var & ~mask) | (active ? mask : 0)))
|
||||
(var = ((var & ~mask) | (active ? mask : 0)))
|
||||
|
||||
/* Clipboard constants, "borrowed" from GCC system headers in
|
||||
the w32 cross compiler */
|
||||
|
||||
35
configure.ac
35
configure.ac
@ -65,6 +65,10 @@ if test "x$with_systemdsystemunitdir" != xno; then
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
|
||||
|
||||
AC_ARG_ENABLE(tests,
|
||||
AC_HELP_STRING([--enable-tests],
|
||||
[Ensure dependencies for the tests are installed]),
|
||||
[ensure_tests_deps=yes], [])
|
||||
AC_ARG_ENABLE(pam, AS_HELP_STRING([--enable-pam],
|
||||
[Build PAM support (default: yes)]),
|
||||
[], [enable_pam=yes])
|
||||
@ -263,9 +267,9 @@ then
|
||||
AC_DEFINE([XRDP_ENABLE_IPV6],1,[Enable IPv6])
|
||||
fi
|
||||
|
||||
if test "x$enable_pam" != "xyes"
|
||||
if test "x$enable_pam" = "xyes"
|
||||
then
|
||||
AC_DEFINE([USE_NOPAM],1,[Disable PAM])
|
||||
AC_DEFINE([USE_PAM],1,[Enable PAM])
|
||||
fi
|
||||
|
||||
AS_IF( [test "x$enable_neutrinordp" = "xyes"] , [PKG_CHECK_MODULES(FREERDP, freerdp >= 1.0.0)] )
|
||||
@ -357,6 +361,24 @@ AC_CHECK_HEADER([X11/extensions/Xrandr.h], [],
|
||||
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
# perform unit tests if libcheck found
|
||||
if test "x$ensure_tests_deps" == "xyes"; then
|
||||
PKG_CHECK_MODULES([CHECK], [check >= 0.10.0],
|
||||
[perform_unit_tests=yes],
|
||||
[AC_MSG_ERROR([please install check, the unit test framework])])
|
||||
else
|
||||
PKG_CHECK_MODULES([CHECK], [check >= 0.10.0],
|
||||
[perform_unit_tests=yes],
|
||||
[perform_unit_tests=no])
|
||||
fi
|
||||
|
||||
if test "x$perform_unit_tests" == "xyes"; then
|
||||
AC_MSG_NOTICE([libcheck found, unit tests will be performed])
|
||||
else
|
||||
AC_MSG_NOTICE([libcheck not found, unit tests will be skipped])
|
||||
fi
|
||||
# -- end perform unit tests
|
||||
|
||||
AC_SUBST([moduledir], '${libdir}/xrdp')
|
||||
|
||||
AC_ARG_ENABLE([strict-locations],
|
||||
@ -397,6 +419,12 @@ AC_CONFIG_FILES([
|
||||
sesman/libscp/Makefile
|
||||
sesman/Makefile
|
||||
sesman/tools/Makefile
|
||||
tests/Makefile
|
||||
tests/common/Makefile
|
||||
tests/memtest/Makefile
|
||||
tools/Makefile
|
||||
tools/devel/Makefile
|
||||
tools/devel/tcp_proxy/Makefile
|
||||
vnc/Makefile
|
||||
xrdpapi/Makefile
|
||||
xrdp/Makefile
|
||||
@ -404,6 +432,7 @@ AC_CONFIG_FILES([
|
||||
xup/Makefile
|
||||
])
|
||||
|
||||
AC_REQUIRE_AUX_FILE([tap-driver.sh])
|
||||
AC_OUTPUT
|
||||
|
||||
echo ""
|
||||
@ -432,6 +461,8 @@ echo " libdir $libdir"
|
||||
echo " bindir $bindir"
|
||||
echo " sysconfdir $sysconfdir"
|
||||
echo ""
|
||||
echo " unit tests performable $perform_unit_tests"
|
||||
echo ""
|
||||
echo " CFLAGS = $CFLAGS"
|
||||
echo " LDFLAGS = $LDFLAGS"
|
||||
|
||||
|
||||
@ -15,10 +15,12 @@ EXTRA_DIST = $(man_MANS:=.in)
|
||||
SUBST_VARS = sed \
|
||||
-e 's|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \
|
||||
-e 's|@bindir[@]|$(bindir)|g' \
|
||||
-e 's|@sbindir[@]|$(sbindir)|g' \
|
||||
-e 's|@localstatedir[@]|$(localstatedir)|g' \
|
||||
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
|
||||
-e 's|@socketdir[@]|$(socketdir)|g' \
|
||||
-e 's|@xrdpconfdir[@]|$(sysconfdir)/xrdp|g'
|
||||
-e 's|@xrdpconfdir[@]|$(sysconfdir)/xrdp|g' \
|
||||
-e 's|@xrdphomeurl[@]|http://www.xrdp.org/|g'
|
||||
|
||||
subst_verbose = $(subst_verbose_@AM_V@)
|
||||
subst_verbose_ = $(subst_verbose_@AM_DEFAULT_V@)
|
||||
|
||||
@ -304,4 +304,6 @@ environment variables in the user's session.
|
||||
.BR xrdp (8),
|
||||
.BR xrdp.ini (5)
|
||||
|
||||
For more info on \fBxrdp\fR see http://www.xrdp.org/
|
||||
For more info on \fBxrdp\fR see
|
||||
.UR @xrdphomeurl@
|
||||
.UE
|
||||
|
||||
@ -57,4 +57,6 @@ description of \fBCHANSRV_LOG_PATH\fP above for the file's location.
|
||||
.BR xrdp\-sesman (8),
|
||||
.BR sesman.ini (5).
|
||||
|
||||
for more info on \fBxrdp\fR see http://www.xrdp.org/
|
||||
For more info on \fBxrdp\fR see
|
||||
.UR @xrdphomeurl@
|
||||
.UE
|
||||
|
||||
@ -61,7 +61,13 @@ Simone Fedele <ilsimo@users.sourceforge.net>
|
||||
.SH "SEE ALSO"
|
||||
.BR xrdp (8),
|
||||
.BR setxkbmap (1),
|
||||
.BR unicode (7),
|
||||
.URL "https://github.com/FreeRDP/FreeRDP/wiki/Keyboard" "Description of Keyboard Input mapping" .
|
||||
|
||||
for more info on \fBxrdp\fR see http://www.xrdp.org/
|
||||
.BR unicode (7)
|
||||
.PP
|
||||
Description of Keyboard Input mapping on the
|
||||
.UR https://github.com/FreeRDP/FreeRDP/wiki/Keyboard
|
||||
FreeRDP wiki
|
||||
.UE
|
||||
.PP
|
||||
For more info on \fBxrdp\fR see
|
||||
.UR @xrdphomeurl@
|
||||
.UE
|
||||
|
||||
@ -55,3 +55,8 @@ xrdp\-sesadmin.log
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR xrdp (8).
|
||||
|
||||
More info on \fBxrdp\fR can be found on the
|
||||
.UR @xrdphomeurl@
|
||||
xrdp homepage
|
||||
.UE
|
||||
|
||||
@ -13,7 +13,7 @@ xrdp\-sesman \- \fBxrdp\fR(8) session manager
|
||||
\-\-version
|
||||
.br
|
||||
.B xrdp\-sesman
|
||||
[ \-\-nodaemon ] [ --config /path/to/sesman.ini ]
|
||||
[\-\-nodaemon] [\-\-dump\-config] [\-\-config /path/to/sesman.ini]
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
\fBxrdp\-sesman\fR is \fBxrdp\fR(8) session manager.
|
||||
@ -34,6 +34,10 @@ Output version information and exit.
|
||||
\fB\-n\fR, \fB\-\-nodaemon\fR
|
||||
Starts \fBxrdp\-sesman\fR in foreground instead of starting it as a daemon.
|
||||
.TP
|
||||
\fB\-\-dump\-config\fR
|
||||
Print the configuration on stdout before starting the daemon.
|
||||
The default is not to do this.
|
||||
.TP
|
||||
\fB\-c\fR, \fB\-\-config\fR
|
||||
Specify a path to a different \fIsesman.ini\fR file. This option is intended
|
||||
to be used primarily for testing or for unusual configurations.
|
||||
@ -45,7 +49,7 @@ the system (notably \fBxrdp(8)\fR and \fBxrdp\-chansrv(8)\fR) will want
|
||||
to read it.
|
||||
.RE
|
||||
.SH "FILES"
|
||||
@bindir@/xrdp\-sesman
|
||||
@sbindir@/xrdp\-sesman
|
||||
.br
|
||||
@bindir@/xrdp\-sesrun
|
||||
.br
|
||||
@ -66,4 +70,6 @@ Simone Fedele <ilsimo@users.sourceforge.net>
|
||||
.BR xrdp (8),
|
||||
.BR xrdp.ini (5)
|
||||
|
||||
for more info on \fBxrdp\fR see http://www.xrdp.org/
|
||||
for more info on \fBxrdp\fR see
|
||||
.UR @xrdphomeurl@
|
||||
.UE
|
||||
|
||||
@ -77,7 +77,7 @@ properly. Note you would need to install the \fBxterm\fR utility
|
||||
first. The \fBgnome\-terminal\fR utility probably won't work here.
|
||||
|
||||
.SH "FILES"
|
||||
@bindir@/xrdp\-sesman
|
||||
@sbindir@/xrdp\-sesman
|
||||
.br
|
||||
@bindir@/xrdp\-sesrun
|
||||
.br
|
||||
@ -94,4 +94,6 @@ Simone Fedele <ilsimo@users.sourceforge.net>
|
||||
.BR xrdp (8),
|
||||
.BR xrdp.ini (5)
|
||||
|
||||
for more info on \fBxrdp\fR see http://www.xrdp.org/
|
||||
For more info on \fBxrdp\fR see
|
||||
.UR @xrdphomeurl@
|
||||
.UE
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
\-\-version
|
||||
.br
|
||||
.B xrdp
|
||||
[ \-\-nodaemon ] [ --port port ] [ --fork ] [ --config /path/to/xrdp.ini ]
|
||||
[\-\-nodaemon] [\-\-port port] [\-\-fork] [\-\-dump\-config] [\-\-config /path/to/xrdp.ini]
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
\fBxrdp\fR is a Remote Desktop Protocol (RDP) Server.
|
||||
@ -45,13 +45,17 @@ Fork a new process on a new connection. If not enabled, use a new thread
|
||||
for every connection. This overrides \fIfork\fR setting in
|
||||
\fIxrdp.ini\fR file.
|
||||
.TP
|
||||
\fB\-\-dump\-config\fR
|
||||
Print the configuration on stdout before starting the daemon.
|
||||
The default is not to do this.
|
||||
.TP
|
||||
\fB\-c\fR, \fB\-\-config\fR
|
||||
Specify a path to a different \fIxrdp.ini\fR file. This option is intended
|
||||
to be used primarily for testing or for unusual configurations.
|
||||
|
||||
|
||||
.SH "FILES"
|
||||
@bindir@/xrdp
|
||||
@sbindir@/xrdp
|
||||
.br
|
||||
@sysconfdir@/xrdp/xrdp.ini
|
||||
.br
|
||||
@ -70,4 +74,6 @@ Simone Fedele <ilsimo@users.sourceforge.net>
|
||||
.BR sesman.ini (5),
|
||||
.BR sesrun (8)
|
||||
|
||||
for more info on \fBxrdp\fR see http://www.xrdp.org/
|
||||
for more info on \fBxrdp\fR see
|
||||
.UR @xrdphomeurl@
|
||||
.UE
|
||||
|
||||
@ -232,7 +232,7 @@ This option can have one of the following values:
|
||||
|
||||
\fBINFO\fR or \fB3\fR \- Logs errors, warnings and informational messages
|
||||
|
||||
\fBDEBUG\fR or \fB4\fR \- Log everything. If \fBsesman\fR is compiled in debug mode, this options will output many more low\-level message, useful for developers
|
||||
\fBDEBUG\fR or \fB4\fR \- Log everything. If \fBxrdp-sesman\fR is compiled in debug mode, this options will output many more low\-level message, useful for developers
|
||||
|
||||
.TP
|
||||
\fBEnableSyslog\fR=\fI[true|false]\fR
|
||||
@ -338,6 +338,16 @@ values supported for a particular release of \fBxrdp\fR(8) are documented in
|
||||
Specifies the session type. The default, \fI0\fR, is Xvnc, \fI10\fR is
|
||||
X11rdp, and \fI20\fR is Xorg with xorgxrdp modules.
|
||||
|
||||
.TP
|
||||
\fBchansrvport\fR=\fBDISPLAY(\fR\fIn\fR\fB)\fR|\fI/path/to/domain-socket\fR
|
||||
Asks xrdp to connect to a manually started \fBxrdp-chansrv\fR instance.
|
||||
This can be useful if you wish to use to use xrdp to connect to a VNC session
|
||||
which has been started other than by \fBxrdp-sesman\fR, as you can then make
|
||||
use of \fBxrdp\-chansrv\fR facilities in the VNC session.
|
||||
|
||||
The first form of this setting is recommended, replacing \fIn\fR with the
|
||||
X11 display number of the session.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
This is an example \fBxrdp.ini\fR:
|
||||
|
||||
@ -369,8 +379,11 @@ password={base64}cGFzc3dvcmQhCg==
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR xrdp (8),
|
||||
.BR sesman (8),
|
||||
.BR sesrun (8),
|
||||
.BR xrdp\-chansrv (8),
|
||||
.BR xrdp\-sesman (8),
|
||||
.BR xrdp\-sesrun (8),
|
||||
.BR sesman.ini (5)
|
||||
|
||||
for more info on \fBxrdp\fR see http://www.xrdp.org/
|
||||
For more info on \fBxrdp\fR see
|
||||
.UR @xrdphomeurl@
|
||||
.UE
|
||||
|
||||
@ -132,19 +132,19 @@ libxrdp_force_read(struct trans *trans)
|
||||
|
||||
if (trans_force_read(trans, 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: header read error");
|
||||
return 0;
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: header read error");
|
||||
return NULL;
|
||||
}
|
||||
bytes = libxrdp_get_pdu_bytes(s->data);
|
||||
if (bytes < 4 || bytes > s->size)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: bad header length %d", bytes);
|
||||
return 0;
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: bad header length %d", bytes);
|
||||
return NULL;
|
||||
}
|
||||
if (trans_force_read(trans, bytes - 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: Can't read PDU");
|
||||
return 0;
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: Can't read PDU");
|
||||
return NULL;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -234,12 +234,16 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
|
||||
dead_lock_counter++;
|
||||
break;
|
||||
case PDUTYPE_CONFIRMACTIVEPDU:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received "
|
||||
"[MS-RDPBCGR] PDUTYPE_CONFIRMACTIVEPDU");
|
||||
xrdp_caps_process_confirm_active(rdp, s);
|
||||
break;
|
||||
case PDUTYPE_DATAPDU:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received "
|
||||
"[MS-RDPBCGR] PDUTYPE_DATAPDU");
|
||||
if (xrdp_rdp_process_data(rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_rdp_process_data failed");
|
||||
cont = 0;
|
||||
term = 1;
|
||||
}
|
||||
@ -247,13 +251,13 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
|
||||
case 2: /* FASTPATH_INPUT_EVENT */
|
||||
if (xrdp_fastpath_process_input_event(rdp->sec_layer->fastpath_layer, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_fastpath_process_input_event failed");
|
||||
cont = 0;
|
||||
term = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "unknown in libxrdp_process_data: code= %d", code);
|
||||
LOG(LOG_LEVEL_WARNING, "unknown code = %d (ignored)", code);
|
||||
dead_lock_counter++;
|
||||
break;
|
||||
}
|
||||
@ -262,8 +266,9 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
|
||||
{
|
||||
/*This situation can happen and this is a workaround*/
|
||||
cont = 0;
|
||||
LOG(LOG_LEVEL_ERROR, "Serious programming error: we were locked in a deadly loop");
|
||||
LOG(LOG_LEVEL_ERROR, "Remaining: %d", (int) (s->end - s->next_packet));
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Serious programming error: we were locked in a deadly loop. "
|
||||
"Remaining bytes: %d", (int) (s->end - s->next_packet));
|
||||
s->next_packet = 0;
|
||||
}
|
||||
|
||||
@ -292,7 +297,9 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_palette sending palette");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "sending palette (%s)",
|
||||
((session->client_info->use_fast_path & 1) ?
|
||||
"fastpath" : "slowpath"));
|
||||
|
||||
/* clear orders */
|
||||
libxrdp_orders_force_send(session);
|
||||
@ -301,25 +308,25 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
|
||||
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_palette: fastpath");
|
||||
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_init_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_palette: slowpath");
|
||||
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
|
||||
}
|
||||
|
||||
/* TS_UPDATE_PALETTE_DATA */
|
||||
out_uint16_le(s, RDP_UPDATE_PALETTE);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 256); /* # of colors */
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, RDP_UPDATE_PALETTE); /* updateType */
|
||||
out_uint16_le(s, 0); /* pad2Octets */
|
||||
out_uint16_le(s, 256); /* # of colors (low-bytes) */
|
||||
out_uint16_le(s, 0); /* # of colors (high-bytes) */
|
||||
|
||||
/* paletteEntries */
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
color = palette[i];
|
||||
@ -331,15 +338,24 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
|
||||
s_mark_end(s);
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_PALETTE "
|
||||
"paletteUpdateData = { updateType %d (UPDATETYPE_PALETTE), "
|
||||
"pad2Octets <ignored>, numberColors 256, "
|
||||
"paletteEntries <omitted from log> }", RDP_UPDATE_PALETTE);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_PALETTE) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_PALETTE_DATA "
|
||||
"updateType %d (UPDATETYPE_PALETTE), pad2Octets <ignored>, "
|
||||
"numberColors 256, paletteEntries <omitted from log>",
|
||||
RDP_UPDATE_PALETTE);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
}
|
||||
@ -364,24 +380,25 @@ libxrdp_send_bell(struct xrdp_session *session)
|
||||
{
|
||||
struct stream *s = (struct stream *)NULL;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_bell sending bell signal");
|
||||
/* see MS documentation: Server play sound PDU, TS_PLAY_SOUND_PDU_DATA */
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
if (xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_init_data failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_uint32_le(s, 440); /* frequency */
|
||||
out_uint32_le(s, 100); /* duration (ms) */
|
||||
out_uint32_le(s, 440); /* frequency */
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_PLAY_SOUND_PDU_DATA "
|
||||
"duration 100 ms, frequency 440 Hz");
|
||||
|
||||
if (xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_PLAY_SOUND) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_send_data failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -459,7 +476,7 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
|
||||
total_bufsize = 0;
|
||||
num_updates = 0;
|
||||
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
|
||||
out_uint16_le(s, RDP_UPDATE_BITMAP);
|
||||
out_uint16_le(s, RDP_UPDATE_BITMAP); /* updateType */
|
||||
p_num_updates = s->p;
|
||||
out_uint8s(s, 2); /* num_updates set later */
|
||||
|
||||
@ -562,6 +579,11 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
|
||||
|
||||
p_num_updates[0] = num_updates;
|
||||
p_num_updates[1] = num_updates >> 8;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA "
|
||||
"updateType %d (UPDATETYPE_BITMAP), numberRectangles %d, "
|
||||
"rectangles <omitted from log>",
|
||||
RDP_UPDATE_BITMAP, num_updates);
|
||||
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
|
||||
@ -666,6 +688,10 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
|
||||
}
|
||||
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA "
|
||||
"updateType %d (UPDATETYPE_BITMAP), numberRectangles 1, "
|
||||
"rectangles <omitted from log>",
|
||||
RDP_UPDATE_BITMAP);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
i = i + lines_sending;
|
||||
@ -690,7 +716,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
int j;
|
||||
int data_bytes;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_pointer sending cursor");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "sending cursor");
|
||||
if (bpp == 0)
|
||||
{
|
||||
bpp = 24;
|
||||
@ -700,14 +726,17 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
{
|
||||
if (bpp != 24)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error client does not support "
|
||||
"new cursors and bpp is %d", bpp);
|
||||
LOG(LOG_LEVEL_ERROR, "Send pointer: client does not support "
|
||||
"new cursors. The only valid bpp is 24, received %d", bpp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((bpp == 15) && (bpp != 16) && (bpp != 24) && (bpp != 32))
|
||||
|
||||
if ((bpp != 16) && (bpp != 24) && (bpp != 32))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Send pointer: invalid bpp value. Expected 16 or 24 or 32, "
|
||||
"received %d", bpp);
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
@ -718,6 +747,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath");
|
||||
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_init_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -729,7 +759,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
else
|
||||
{
|
||||
data_bytes = ((bpp + 7) / 8) * 32 * 32;
|
||||
out_uint16_le(s, bpp);
|
||||
out_uint16_le(s, bpp); /* TS_FP_POINTERATTRIBUTE -> newPointerUpdateData.xorBpp */
|
||||
}
|
||||
}
|
||||
else /* slowpath */
|
||||
@ -741,25 +771,34 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
out_uint16_le(s, RDP_POINTER_COLOR);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
data_bytes = 3072;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
|
||||
"messageType %d (TS_PTRMSGTYPE_COLOR), pad2Octets <ignored>",
|
||||
RDP_POINTER_COLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint16_le(s, RDP_POINTER_POINTER);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, bpp);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
|
||||
"messageType %d (TS_PTRMSGTYPE_POINTER), pad2Octets <ignored>",
|
||||
RDP_POINTER_POINTER);
|
||||
|
||||
out_uint16_le(s, bpp); /* TS_POINTERATTRIBUTE -> xorBpp */
|
||||
data_bytes = ((bpp + 7) / 8) * 32 * 32;
|
||||
}
|
||||
}
|
||||
|
||||
/* the TS_COLORPOINTERATTRIBUTE field which is shared by
|
||||
all of the pointer attribute PDU types */
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
out_uint16_le(s, x); /* hotSpot.xPos */
|
||||
out_uint16_le(s, y); /* hotSpot.yPos */
|
||||
out_uint16_le(s, 32); /* width */
|
||||
out_uint16_le(s, 32); /* height */
|
||||
out_uint16_le(s, 128); /* lengthAndMask */
|
||||
out_uint16_le(s, data_bytes); /* lengthXorMask */
|
||||
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
out_uint16_le(s, x);
|
||||
out_uint16_le(s, y);
|
||||
out_uint16_le(s, 32);
|
||||
out_uint16_le(s, 32);
|
||||
out_uint16_le(s, 128);
|
||||
out_uint16_le(s, data_bytes);
|
||||
|
||||
/* xorMaskData */
|
||||
switch (bpp)
|
||||
{
|
||||
//case 15: /* coverity: this is logically dead code */
|
||||
@ -802,25 +841,42 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
break;
|
||||
}
|
||||
|
||||
out_uint8a(s, mask, 128); /* mask */
|
||||
out_uint8a(s, mask, 128); /* andMaskData */
|
||||
out_uint8(s, 0); /* pad */
|
||||
s_mark_end(s);
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
if ((session->client_info->pointer_flags & 1) == 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_COLORPOINTERATTRIBUTE "
|
||||
"cachedPointerUpdateData = { cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log> }",
|
||||
cache_idx, x, y, data_bytes);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_COLOR) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_POINTERATTRIBUTE "
|
||||
"newPointerUpdateData.xorBpp %d, "
|
||||
"newPointerUpdateData.colorPtrAttr = { cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log> }",
|
||||
bpp, cache_idx, x, y, data_bytes);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_POINTER) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -828,6 +884,26 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((session->client_info->pointer_flags & 1) == 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_COLORPOINTERATTRIBUTE "
|
||||
"cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log>",
|
||||
cache_idx, x, y, data_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_POINTERATTRIBUTE "
|
||||
"xorBpp %d, colorPtrAttr = { cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log> }",
|
||||
bpp, cache_idx, x, y, data_bytes);
|
||||
}
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_POINTER);
|
||||
}
|
||||
@ -841,26 +917,26 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_set_pointer sending cursor index");
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath");
|
||||
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_init_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: slowpath");
|
||||
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
|
||||
out_uint16_le(s, RDP_POINTER_CACHED);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
|
||||
"messageType %d (TS_PTRMSGTYPE_CACHED), pad2Octets <ignored>",
|
||||
RDP_POINTER_CACHED);
|
||||
}
|
||||
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
@ -868,15 +944,20 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx)
|
||||
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_CACHEDPOINTERATTRIBUTE "
|
||||
"cachedPointerUpdateData.cacheIndex %d", cache_idx);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_CACHED) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_CACHEDPOINTERATTRIBUTE "
|
||||
"cacheIndex %d", cache_idx);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_POINTER);
|
||||
}
|
||||
@ -1084,12 +1165,14 @@ libxrdp_reset(struct xrdp_session *session,
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: session->client_info is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* this will send any lingering orders */
|
||||
if (xrdp_orders_reset((struct xrdp_orders *)session->orders) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_orders_reset failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1101,12 +1184,14 @@ libxrdp_reset(struct xrdp_session *session,
|
||||
session->check_for_app_input = 0;
|
||||
if (xrdp_rdp_send_deactivate((struct xrdp_rdp *)session->rdp) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_rdp_send_deactivate failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* this should do the resizing */
|
||||
if (xrdp_caps_send_demand_active((struct xrdp_rdp *)session->rdp) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_caps_send_demand_active failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1149,13 +1234,34 @@ libxrdp_orders_send_bitmap3(struct xrdp_session *session,
|
||||
cache_id, cache_idx, hints);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_get_channel_count(const struct xrdp_session *session)
|
||||
{
|
||||
int count = 0;
|
||||
const struct xrdp_rdp *rdp = (const struct xrdp_rdp *)session->rdp;
|
||||
const struct xrdp_mcs *mcs = rdp->sec_layer->mcs_layer;
|
||||
|
||||
if (mcs->channel_list == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"libxrdp_get_channel_count - No channel initialized");
|
||||
}
|
||||
else
|
||||
{
|
||||
count = mcs->channel_list->count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* this function gets the channel name and its flags, index is zero
|
||||
based. either channel_name or channel_flags can be passed in nil if
|
||||
they are not needed */
|
||||
int EXPORT_CC
|
||||
libxrdp_query_channel(struct xrdp_session *session, int index,
|
||||
libxrdp_query_channel(struct xrdp_session *session, int channel_id,
|
||||
char *channel_name, int *channel_flags)
|
||||
{
|
||||
int count = 0;
|
||||
@ -1174,26 +1280,29 @@ libxrdp_query_channel(struct xrdp_session *session, int index,
|
||||
|
||||
count = mcs->channel_list->count;
|
||||
|
||||
if (index < 0 || index >= count)
|
||||
if (channel_id < 0 || channel_id >= count)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel out of range %d", index);
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel: Channel index out of range. "
|
||||
"max channel index %d, received channel index %d",
|
||||
count, channel_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel_item = (struct mcs_channel_item *)
|
||||
list_get_item(mcs->channel_list, index);
|
||||
list_get_item(mcs->channel_list, channel_id);
|
||||
|
||||
if (channel_item == 0)
|
||||
if (channel_item == NULL)
|
||||
{
|
||||
/* this should not happen */
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is 0");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (channel_name != 0)
|
||||
{
|
||||
g_strncpy(channel_name, channel_item->name, 8);
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel %d name %s", index, channel_name);
|
||||
LOG(LOG_LEVEL_DEBUG, "libxrdp_query_channel - Channel %d name %s",
|
||||
channel_id, channel_name);
|
||||
}
|
||||
|
||||
if (channel_flags != 0)
|
||||
@ -1263,6 +1372,7 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
|
||||
|
||||
if (xrdp_channel_init(chan, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -1270,10 +1380,12 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
|
||||
/* here we make a copy of the data */
|
||||
out_uint8a(s, data, data_len);
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] Virtual Channel PDU "
|
||||
"data <omitted from log>");
|
||||
|
||||
if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: error, server channel data NOT sent to client channel");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -1295,15 +1407,20 @@ libxrdp_disable_channel(struct xrdp_session *session, int channel_id,
|
||||
mcs = rdp->sec_layer->mcs_layer;
|
||||
if (mcs->channel_list == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Channel list is NULL");
|
||||
return 1;
|
||||
}
|
||||
channel_item = (struct mcs_channel_item *)
|
||||
list_get_item(mcs->channel_list, channel_id);
|
||||
if (channel_item == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Channel item is NULL");
|
||||
return 1;
|
||||
}
|
||||
channel_item->disabled = is_disabled;
|
||||
LOG(LOG_LEVEL_DEBUG, "%s channel %d (%s)",
|
||||
(is_disabled ? "Disabling" : "Enabling"), channel_item->chanid,
|
||||
channel_item->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1524,6 +1641,7 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_surface:");
|
||||
if ((session->client_info->use_fast_path & 1) == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled");
|
||||
return 1;
|
||||
}
|
||||
max_bytes = session->client_info->max_fastpath_frag_bytes;
|
||||
@ -1537,10 +1655,16 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
cmd_bytes = 10 + 12;
|
||||
if (data_bytes + rdp_bytes + sec_bytes + cmd_bytes > max_bytes)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Too much data to send via fastpath. "
|
||||
"Max fastpath bytes %d, received bytes %d",
|
||||
max_bytes, (data_bytes + rdp_bytes + sec_bytes + cmd_bytes));
|
||||
return 1;
|
||||
}
|
||||
if (sec_bytes + rdp_bytes + cmd_bytes > pad_bytes)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Too much header to send via fastpath. "
|
||||
"Max fastpath header bytes %d, received bytes %d",
|
||||
pad_bytes, (rdp_bytes + sec_bytes + cmd_bytes));
|
||||
return 1;
|
||||
}
|
||||
g_memset(&ls, 0, sizeof(ls));
|
||||
@ -1556,6 +1680,13 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
out_uint16_le(s, destTop);
|
||||
out_uint16_le(s, destRight);
|
||||
out_uint16_le(s, destBottom);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SURFCMD_STREAM_SURF_BITS "
|
||||
"cmdType 0x%4.4x (CMDTYPE_STREAM_SURFACE_BITS), destLeft %d, "
|
||||
"destTop %d, destRight %d, destBottom %d, "
|
||||
"bitmapData <see TS_BITMAP_DATA_EX>",
|
||||
CMDTYPE_STREAM_SURFACE_BITS, destLeft, destTop, destRight,
|
||||
destBottom);
|
||||
|
||||
/* TS_BITMAP_DATA_EX */
|
||||
out_uint8(s, bpp);
|
||||
out_uint8(s, 0);
|
||||
@ -1564,9 +1695,17 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
out_uint16_le(s, width);
|
||||
out_uint16_le(s, height);
|
||||
out_uint32_le(s, data_bytes);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding field bitmapData [MS-RDPBCGR] TS_BITMAP_DATA_EX "
|
||||
"bpp %d, flags 0x00, reserved 0, codecID %d, width %d, "
|
||||
"height %d, bitmapDataLength %d, exBitmapDataHeader <not present>, "
|
||||
"bitmapData <omitted from log>",
|
||||
bpp, codecID, width, height, data_bytes);
|
||||
|
||||
/* 4 = FASTPATH_UPDATETYPE_SURFCMDS */
|
||||
if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"libxrdp_fastpath_send_surface: xrdp_rdp_send_fastpath failed");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -1583,10 +1722,12 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session,
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_frame_marker:");
|
||||
if ((session->client_info->use_fast_path & 1) == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled");
|
||||
return 1;
|
||||
}
|
||||
if (session->client_info->use_frame_acks == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Fastpath frame acks is disabled");
|
||||
return 1;
|
||||
}
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
@ -1597,9 +1738,15 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session,
|
||||
out_uint16_le(s, frame_action);
|
||||
out_uint32_le(s, frame_id);
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FRAME_MARKER "
|
||||
"cmdType 0x0004 (CMDTYPE_FRAME_MARKER), frameAction 0x%4.4x, "
|
||||
"frameId %d", frame_action, frame_id);
|
||||
|
||||
/* 4 = FASTPATH_UPDATETYPE_SURFCMDS */
|
||||
if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"libxrdp_fastpath_send_frame_marker: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -1614,7 +1761,6 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data,
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_session_info:");
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
return xrdp_rdp_send_session_info(rdp, data, data_bytes);
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "file.h"
|
||||
#include "libxrdpinc.h"
|
||||
#include "xrdp_client_info.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
/* iso */
|
||||
@ -549,9 +550,9 @@ xrdp_codec_jpeg_compress(void *handle,
|
||||
int cy, /* height of area to compress */
|
||||
int quality, /* higher numbers compress less */
|
||||
char *out_data, /* dest for jpg image */
|
||||
int *io_len /* length of out_data and on return */
|
||||
/* len of compressed data */
|
||||
);
|
||||
int *io_len /* length of out_data and on return
|
||||
len of compressed data */
|
||||
);
|
||||
|
||||
void *
|
||||
xrdp_jpeg_init(void);
|
||||
@ -559,7 +560,7 @@ int
|
||||
xrdp_jpeg_deinit(void *handle);
|
||||
|
||||
/* xrdp_channel.c */
|
||||
struct xrdp_channel*
|
||||
struct xrdp_channel *
|
||||
xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer);
|
||||
void
|
||||
xrdp_channel_delete(struct xrdp_channel *self);
|
||||
|
||||
@ -203,9 +203,28 @@ int
|
||||
libxrdp_orders_send_bitmap3(struct xrdp_session *session,
|
||||
int width, int height, int bpp, char *data,
|
||||
int cache_id, int cache_idx, int hints);
|
||||
/**
|
||||
* Returns the number of channels in the session
|
||||
*
|
||||
* This value is one more than the last valid channel ID
|
||||
*
|
||||
* @param session RDP session
|
||||
* @return Number of available channels
|
||||
*/
|
||||
int
|
||||
libxrdp_query_channel(struct xrdp_session *session, int index,
|
||||
libxrdp_get_channel_count(const struct xrdp_session *session);
|
||||
int
|
||||
libxrdp_query_channel(struct xrdp_session *session, int channel_id,
|
||||
char *channel_name, int *channel_flags);
|
||||
/**
|
||||
* Gets the channel ID for the named channel
|
||||
*
|
||||
* Channel IDs are in the range 0..(channel_count-1)
|
||||
*
|
||||
* @param session RDP session
|
||||
* @param name name of channel
|
||||
* @return channel ID, or -1 if the channel cannot be found
|
||||
*/
|
||||
int
|
||||
libxrdp_get_channel_id(struct xrdp_session *session, const char *name);
|
||||
int
|
||||
|
||||
@ -77,7 +77,8 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 10 + 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_general: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 12, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -103,6 +104,9 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process [MS-RDPBCGR] TS_ORDER_CAPABILITYSET (2.2.7.1.3) message.
|
||||
*/
|
||||
static int
|
||||
xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
@ -112,10 +116,10 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
int ex_flags;
|
||||
int cap_flags;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "order capabilities");
|
||||
if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_order: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 84, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 20); /* Terminal desc, pad */
|
||||
@ -127,33 +131,53 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
in_uint16_le(s, cap_flags); /* Capability flags */
|
||||
in_uint8a(s, order_caps, 32); /* Orders supported */
|
||||
g_memcpy(self->client_info.orders, order_caps, 32);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dest blt-0 %d", order_caps[0]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "pat blt-1 %d", order_caps[1]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "screen blt-2 %d", order_caps[2]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "memblt-3-13 %d %d", order_caps[3], order_caps[13]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "triblt-4-14 %d %d", order_caps[4], order_caps[14]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "line-8 %d", order_caps[8]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "line-9 %d", order_caps[9]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "rect-10 %d", order_caps[10]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "desksave-11 %d", order_caps[11]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "polygon-20 %d", order_caps[20]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "polygon2-21 %d", order_caps[21]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "polyline-22 %d", order_caps[22]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse-25 %d", order_caps[25]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse2-26 %d", order_caps[26]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "text2-27 %d", order_caps[27]);
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "order_caps dump", order_caps, 32);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: terminalDescriptor (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveXGranularity (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveYGranularity (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: maximumOrderLevel (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: numberFonts (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderFlags 0x%4.4x", cap_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 0: DstBlt %d", order_caps[0]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 1: PatBlt %d", order_caps[1]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 2: ScrBlt %d", order_caps[2]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 3,13: MemBlt %d %d", order_caps[3], order_caps[13]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 4,14: Mem3Blt %d %d", order_caps[4], order_caps[14]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 5-6: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 7: DrawNineGrid %d", order_caps[7]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 8: LineTo %d", order_caps[8]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 9: MultiDrawNineGrid %d", order_caps[9]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 10: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 11: SaveBitmap %d", order_caps[11]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 12-14: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 15: MultiDstBlt %d", order_caps[15]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 16: MultiPatBlt %d", order_caps[16]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 17: MultiScrBlt %d", order_caps[17]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 18: MultiOpaqueRect %d", order_caps[18]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 19: FastIndex %d", order_caps[19]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 20: PolygonSC %d", order_caps[20]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 21: PolygonCB %d", order_caps[21]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 22: Polyline %d", order_caps[22]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 23: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 24: FastGlyph %d", order_caps[24]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 25: EllipseSC %d", order_caps[25]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 26: EllipseCB %d", order_caps[26]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 27: GlyphIndex %d", order_caps[27]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 28-31: unused index");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: order_caps", order_caps, 32);
|
||||
|
||||
in_uint8s(s, 2); /* Text capability flags */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: textFlags (ignored as per protocol spec)");
|
||||
/* read extended order support flags */
|
||||
in_uint16_le(s, ex_flags); /* Ex flags */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupportExFlags 0x%4.4x", ex_flags);
|
||||
|
||||
if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */
|
||||
{
|
||||
self->client_info.order_flags_ex = ex_flags;
|
||||
if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: bitmap cache v3 supported");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: bitmap cache v3 supported");
|
||||
self->client_info.bitmap_cache_version |= 4;
|
||||
}
|
||||
}
|
||||
@ -161,15 +185,15 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
|
||||
self->client_info.desktop_cache = i;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "desktop cache size %d", i);
|
||||
in_uint8s(s, 4); /* Unknown */
|
||||
in_uint8s(s, 4); /* Unknown */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveSize %d", i);
|
||||
in_uint8s(s, 4); /* Pad */
|
||||
in_uint8s(s, 4); /* Pad */
|
||||
|
||||
/* check if libpainter should be used for drawing, instead of orders */
|
||||
if (!(order_caps[TS_NEG_DSTBLT_INDEX] && order_caps[TS_NEG_PATBLT_INDEX] &&
|
||||
order_caps[TS_NEG_SCRBLT_INDEX] && order_caps[TS_NEG_MEMBLT_INDEX]))
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: not enough orders supported by client, using painter.");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: not enough orders supported by client, using painter.");
|
||||
self->client_info.no_orders_supported = 1;
|
||||
}
|
||||
|
||||
@ -186,7 +210,8 @@ xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 36, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 1;
|
||||
@ -229,7 +254,8 @@ xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 2 + 2 + 4 + 4 + 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache2: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 16, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 2;
|
||||
@ -271,7 +297,8 @@ xrdp_caps_process_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_cache_v3_codec_id: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 1, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, codec_id);
|
||||
@ -421,13 +448,24 @@ xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
|
||||
if (len < 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_rail: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 4, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.rail_support_level = i32;
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_rail: rail_support_level %d",
|
||||
self->client_info.rail_support_level);
|
||||
LOG(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - CAPSTYPE_RAIL "
|
||||
"RailSupportLevel 0x%8.8x (%s%s%s%s%s%s%s%s)",
|
||||
self->client_info.rail_support_level,
|
||||
(self->client_info.rail_support_level & 0x01) ? "TS_RAIL_LEVEL_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x02) ? "TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x04) ? "TS_RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x08) ? "TS_RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x10) ? "TS_RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x20) ? "TS_RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x40) ? "TS_RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x80) ? "TS_RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED " : ""
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -448,8 +486,8 @@ xrdp_caps_process_window(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
self->client_info.wnd_num_icon_caches = i32;
|
||||
in_uint16_le(s, i32);
|
||||
self->client_info.wnd_num_icon_cache_entries = i32;
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_window wnd_support_level %d "
|
||||
"wnd_num_icon_caches %d wnd_num_icon_cache_entries %d",
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_window wnd_support_level %d, "
|
||||
"wnd_num_icon_caches %d, wnd_num_icon_cache_entries %d",
|
||||
self->client_info.wnd_support_level,
|
||||
self->client_info.wnd_num_icon_caches,
|
||||
self->client_info.wnd_num_icon_cache_entries);
|
||||
@ -593,6 +631,7 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
logging in debug mode */
|
||||
UNUSED_VAR(cmdFlags);
|
||||
#endif
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_surface_cmds:");
|
||||
in_uint32_le(s, cmdFlags);
|
||||
in_uint8s(s, 4); /* reserved */
|
||||
@ -601,6 +640,9 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU (2.2.1.13.2.1) message.
|
||||
*/
|
||||
int
|
||||
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
{
|
||||
@ -612,7 +654,6 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
int len;
|
||||
char *p;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_caps_process_confirm_active");
|
||||
in_uint8s(s, 4); /* rdp_shareid */
|
||||
in_uint8s(s, 2); /* userid */
|
||||
in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
|
||||
@ -620,118 +661,169 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
in_uint8s(s, source_len);
|
||||
in_uint16_le(s, num_caps);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU "
|
||||
"shareID (ignored), originatorID (ignored), lengthSourceDescriptor %d, "
|
||||
"lengthCombinedCapabilities %d, sourceDescriptor (ignored), "
|
||||
"numberCapabilities %d", source_len, cap_len, num_caps);
|
||||
|
||||
if ((cap_len < 0) || (cap_len > 1024 * 1024))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU "
|
||||
"lengthCombinedCapabilities %d is too long (> %d)",
|
||||
cap_len, 1024 * 1024);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (index = 0; index < num_caps; index++)
|
||||
{
|
||||
p = s->p;
|
||||
if (!s_check_rem(s, 4))
|
||||
if (!s_check_rem_and_log(s, 4,
|
||||
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_confirm_active: error 1");
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, type);
|
||||
in_uint16_le(s, len);
|
||||
if ((len < 4) || !s_check_rem(s, len - 4))
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType %d, lengthCapability %d", type, len);
|
||||
if (len < 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Protocol error [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"lengthCapability must be greater than 3, received %d", len);
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem_and_log(s, len - 4,
|
||||
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_confirm_active: error: len %d, "
|
||||
"remaining %d", len, (int) (s->end - s->p));
|
||||
return 1;
|
||||
}
|
||||
len -= 4;
|
||||
switch (type)
|
||||
{
|
||||
case CAPSTYPE_GENERAL:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GENERAL");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_GENERAL");
|
||||
xrdp_caps_process_general(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_BITMAP:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAP");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BITMAP - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_ORDER:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ORDER");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_ORDER");
|
||||
xrdp_caps_process_order(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_BITMAPCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BMPCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BITMAPCACHE");
|
||||
xrdp_caps_process_bmpcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_CONTROL:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_CONTROL");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_CONTROL - Ignored");
|
||||
break;
|
||||
case 6:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = 6");
|
||||
xrdp_caps_process_cache_v3_codec_id(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_ACTIVATION:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ACTIVAION");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_ACTIVATION - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_POINTER:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_POINTER");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_POINTER");
|
||||
xrdp_caps_process_pointer(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_SHARE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SHARE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_SHARE - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_COLORCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_COLORCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_COLORCACHE - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_SOUND:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SOUND");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_SOUND - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_INPUT:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_INPUT");
|
||||
xrdp_caps_process_input(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_FONT:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_FONT");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_FONT - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_BRUSH:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BRUSH");
|
||||
xrdp_caps_process_brushcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_GLYPHCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GLYPHCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_GLYPHCACHE");
|
||||
xrdp_caps_process_glyphcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_OFFSCREENCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_OFFSCREENCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_OFFSCREENCACHE");
|
||||
xrdp_caps_process_offscreen_bmpcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_BITMAPCACHE_REV2:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAPCACHE_REV2");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BITMAPCACHE_REV2");
|
||||
xrdp_caps_process_bmpcache2(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_VIRTUALCHANNEL:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_VIRTUALCHANNEL");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_VIRTUALCHANNEL - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_DRAWNINGRIDCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWNINGRIDCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_DRAWNINGRIDCACHE - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_DRAWGDIPLUS:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWGDIPLUS");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_DRAWGDIPLUS - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_RAIL:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_RAIL");
|
||||
xrdp_caps_process_rail(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_WINDOW:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_WINDOW");
|
||||
xrdp_caps_process_window(self, s, len);
|
||||
break;
|
||||
case CAPSSETTYPE_MULTIFRAGMENTUPDATE:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSSETTYPE_MULTIFRAGMENTUPDATE");
|
||||
xrdp_caps_process_multifragmentupdate(self, s, len);
|
||||
break;
|
||||
case CAPSETTYPE_SURFACE_COMMANDS:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSETTYPE_SURFACE_COMMANDS");
|
||||
xrdp_caps_process_surface_cmds(self, s, len);
|
||||
break;
|
||||
case CAPSSETTYPE_BITMAP_CODECS:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSSETTYPE_BITMAP_CODECS");
|
||||
xrdp_caps_process_codecs(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_FRAME_ACKNOWLEDGE:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_FRAME_ACKNOWLEDGE");
|
||||
xrdp_caps_process_frame_ack(self, s, len);
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_WARNING, "unknown in xrdp_caps_process_confirm_active %d", type);
|
||||
LOG(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = %d is unknown - Ignored", type);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -741,7 +833,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
if (self->client_info.no_orders_supported &&
|
||||
(self->client_info.offscreen_support_level != 0))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_caps_process_confirm_active: not enough orders "
|
||||
LOG(LOG_LEVEL_WARNING, "Client Capability: not enough orders "
|
||||
"supported by client, client wants off screen bitmap but "
|
||||
"offscreen bitmaps disabled");
|
||||
self->client_info.offscreen_support_level = 0;
|
||||
@ -749,7 +841,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
self->client_info.offscreen_cache_entries = 0;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_caps_process_confirm_active");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Completed processing received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU");
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
@ -771,10 +863,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_caps_send_demand_active");
|
||||
|
||||
if (xrdp_rdp_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -797,6 +889,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, CAPSTYPE_SHARE_LEN);
|
||||
out_uint16_le(s, self->mcs_channel);
|
||||
out_uint16_be(s, 0xb5e2); /* 0x73e1 */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_SHARE "
|
||||
"channel ID = 0x%x", self->mcs_channel);
|
||||
|
||||
/* Output general capability set */
|
||||
caps_count++;
|
||||
@ -820,6 +915,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 0); /* Compression level */
|
||||
out_uint8(s, 1); /* refreshRectSupport */
|
||||
out_uint8(s, 1); /* suppressOutputSupport */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_GENERAL TODO");
|
||||
|
||||
/* Output bitmap capability set */
|
||||
caps_count++;
|
||||
@ -837,11 +934,15 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_BITMAP TODO");
|
||||
|
||||
/* Output font capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_FONT);
|
||||
out_uint16_le(s, CAPSTYPE_FONT_LEN);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_FONT");
|
||||
|
||||
/* Output order capability set */
|
||||
caps_count++;
|
||||
@ -895,6 +996,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint32_le(s, 0x0f4240); /* desk save */
|
||||
out_uint32_le(s, 1); /* ? */
|
||||
out_uint32_le(s, 0); /* ? */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_ORDER "
|
||||
"TODO");
|
||||
|
||||
/* Output bmpcodecs capability set */
|
||||
caps_count++;
|
||||
@ -912,6 +1016,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint8(s, 0x01); /* fAllowDynamicFidelity */
|
||||
out_uint8(s, 0x01); /* fAllowSubsampling */
|
||||
out_uint8(s, 0x03); /* colorLossLevel */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"NSCODEC "
|
||||
"fAllowDynamicFidelity = 0x01,"
|
||||
"fAllowSubsampling = 0x01,"
|
||||
"colorLossLevel = 0x03");
|
||||
#if defined(XRDP_RFXCODEC) || defined(XRDP_NEUTRINORDP)
|
||||
/* remotefx */
|
||||
codec_caps_count++;
|
||||
@ -919,12 +1028,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 4); /* codecPropertiesLength */
|
||||
out_uint32_le(s, 0); /* reserved */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"REMOTEFX");
|
||||
/* image remotefx */
|
||||
codec_caps_count++;
|
||||
out_uint8a(s, XR_CODEC_GUID_IMAGE_REMOTEFX, 16);
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 4); /* codecPropertiesLength */
|
||||
out_uint32_le(s, 0); /* reserved */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"IMAGE_REMOTEFX");
|
||||
#endif
|
||||
/* jpeg */
|
||||
codec_caps_count++;
|
||||
@ -932,6 +1045,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 1); /* codecPropertiesLength */
|
||||
out_uint8(s, 75); /* jpeg compression ratio */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"JPEG: "
|
||||
"jpeg compression ratio = 75");
|
||||
/* calculate and set size and count */
|
||||
codec_caps_size = (int)(s->p - codec_caps_size_ptr);
|
||||
codec_caps_size += 2; /* 2 bytes for CAPSTYPE_BMPCODECS above */
|
||||
@ -945,6 +1061,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, CAPSTYPE_COLORCACHE_LEN);
|
||||
out_uint16_le(s, 6); /* cache size */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_COLORCACHE: "
|
||||
"colorTableCacheSize = 6");
|
||||
|
||||
/* Output pointer capability set */
|
||||
caps_count++;
|
||||
@ -953,8 +1072,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 1); /* Colour pointer */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_POINTER: "
|
||||
"colorPointerFlag = true"
|
||||
"colorPointerCacheSize = 0x19"
|
||||
"pointerCacheSize = 0x19");
|
||||
|
||||
/* Output input capability set */
|
||||
/* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/b3bc76ae-9ee5-454f-b197-ede845ca69cc */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_INPUT);
|
||||
out_uint16_le(s, CAPSTYPE_INPUT_LEN);
|
||||
@ -970,6 +1095,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
}
|
||||
out_uint16_le(s, flags);
|
||||
out_uint8s(s, 82);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_INPUT: "
|
||||
"inputFlags = 0x%x", flags);
|
||||
|
||||
if (self->client_info.rail_enable) /* MS-RDPERP 3.3.5.1.4 */
|
||||
{
|
||||
@ -980,6 +1108,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint32_le(s, 3); /* See: https://msdn.microsoft.com/en-us/library/cc242518.aspx
|
||||
TS_RAIL_LEVEL_SUPPORTED
|
||||
TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_RAIL: "
|
||||
"RailSupportLevel = "
|
||||
"TS_RAIL_LEVEL_SUPPORTED | TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED");
|
||||
|
||||
/* Window List Capability Set */
|
||||
caps_count++;
|
||||
@ -988,6 +1120,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint32_le(s, TS_WINDOW_LEVEL_SUPPORTED_EX);
|
||||
out_uint8(s, 3); /* NumIconCaches */
|
||||
out_uint16_le(s, 12); /* NumIconCacheEntries */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_WINDOW: "
|
||||
"WndSupportLevel = TS_WINDOW_LEVEL_SUPPORTED_EX, "
|
||||
"NumIconCaches = 3,"
|
||||
"NumIconCacheEntries = 12");
|
||||
}
|
||||
|
||||
/* 6 - bitmap cache v3 codecid */
|
||||
@ -995,6 +1132,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 0x0006);
|
||||
out_uint16_le(s, 5);
|
||||
out_uint8(s, 0); /* client sets */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"0x0006 = 0");
|
||||
|
||||
if (self->client_info.use_fast_path & FASTPATH_OUTPUT_SUPPORTED) /* fastpath output on */
|
||||
{
|
||||
@ -1003,12 +1142,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE);
|
||||
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN);
|
||||
out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSSETTYPE_MULTIFRAGMENTUPDATE = 3MB");
|
||||
|
||||
/* frame acks */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE);
|
||||
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE_LEN);
|
||||
out_uint32_le(s, 2); /* 2 frames in flight */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_FRAME_ACKNOWLEDGE = 2 frames");
|
||||
|
||||
/* surface commands */
|
||||
caps_count++;
|
||||
@ -1018,6 +1161,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
SURFCMDS_FRAMEMARKER |
|
||||
SURFCMDS_STREAMSUFRACEBITS)); /* cmdFlags */
|
||||
out_uint32_le(s, 0); /* reserved */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSETTYPE_SURFACE_COMMANDS = "
|
||||
"SURFCMDS_SETSURFACEBITS | SURFCMDS_FRAMEMARKER | SURFCMDS_STREAMSUFRACEBITS");
|
||||
}
|
||||
|
||||
out_uint8s(s, 4); /* pad */
|
||||
@ -1033,12 +1179,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
caps_count_ptr[2] = caps_count >> 16;
|
||||
caps_count_ptr[3] = caps_count >> 24;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: sending PDUTYPE_DEMANDACTIVEPDU "
|
||||
"message with the server's capabilities");
|
||||
if (xrdp_rdp_send(self, s, PDUTYPE_DEMANDACTIVEPDU) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out (1) xrdp_caps_send_demand_active");
|
||||
|
||||
/* send Monitor Layout PDU for dual monitor */
|
||||
if (self->client_info.monitorCount > 0 &&
|
||||
|
||||
@ -43,6 +43,19 @@
|
||||
#define XRDP_DRDYNVC_STATUS_OPEN 2
|
||||
#define XRDP_DRDYNVC_STATUS_CLOSE_SENT 3
|
||||
|
||||
#define XRDP_DRDYNVC_STATUS_TO_STR(status) \
|
||||
((status) == XRDP_DRDYNVC_STATUS_CLOSED ? "CLOSED" : \
|
||||
(status) == XRDP_DRDYNVC_STATUS_OPEN_SENT ? "OPEN_SENT" : \
|
||||
(status) == XRDP_DRDYNVC_STATUS_OPEN ? "OPEN" : \
|
||||
(status) == XRDP_DRDYNVC_STATUS_CLOSE_SENT ? "CLOSE_SENT" : \
|
||||
"unknown" \
|
||||
)
|
||||
|
||||
#define XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id) \
|
||||
(xrdp_channel_get_item((self), (chan_id)) != NULL \
|
||||
? xrdp_channel_get_item((self), (chan_id))->name \
|
||||
: "unknown")
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns pointer or nil on error */
|
||||
static struct mcs_channel_item *
|
||||
@ -52,7 +65,7 @@ xrdp_channel_get_item(struct xrdp_channel *self, int channel_id)
|
||||
|
||||
if (self->mcs_layer->channel_list == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_get_item - No channel initialized");
|
||||
LOG(LOG_LEVEL_WARNING, "Channel list is NULL, returning NULL");
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
@ -95,6 +108,7 @@ xrdp_channel_init(struct xrdp_channel *self, struct stream *s)
|
||||
{
|
||||
if (xrdp_sec_init(self->sec_layer, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_init: xrdp_sec_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -115,13 +129,17 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - no such channel");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Request to send a message to non-existent channel_id %d",
|
||||
channel_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (channel->disabled)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_channel_send, channel disabled");
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"Request to send a message to the disabled channel %s (%d)",
|
||||
channel->name, channel_id);
|
||||
return 0; /* not an error */
|
||||
}
|
||||
|
||||
@ -145,10 +163,12 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
|
||||
// }
|
||||
|
||||
out_uint32_le(s, flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] CHANNEL_PDU_HEADER "
|
||||
"length %d, flags 0x%8.8x", total_data_len, flags);
|
||||
|
||||
if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - failure sending data");
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send: xrdp_sec_send failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -183,18 +203,28 @@ xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s,
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session->callback is nil");
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "session->callback is NULL");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session is nil");
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "session is NULL");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Write a variable length unsigned int (1, 2, or 4 bytes) to the stream.
|
||||
*
|
||||
* The number of bytes written is the minimum number of bytes needed to
|
||||
* represent the value.
|
||||
*
|
||||
* @param s the stream to write to
|
||||
* @param val the value to write
|
||||
* @return the DYNVC cbId length code for the number of bytes written (see [MS-RDPEDYC] 2.2.2.1)
|
||||
*/
|
||||
static int
|
||||
drdynvc_insert_uint_124(struct stream *s, uint32_t val)
|
||||
{
|
||||
@ -220,6 +250,17 @@ drdynvc_insert_uint_124(struct stream *s, uint32_t val)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Read a variable length unsigned int (1, 2, or 4 bytes) from the stream.
|
||||
*
|
||||
* The number of bytes read is determined by the cbId bit field flag in the
|
||||
* cmd argument (see [MS-RDPEDYC] 2.2.2.1).
|
||||
*
|
||||
* @param s [in] the stream to read from
|
||||
* @param cmd [in] the cmd byte which contains the cbId bit field flag
|
||||
* @param chan_id_p [out] a pointer to the value read from the stream
|
||||
* @return error code
|
||||
*/
|
||||
static int
|
||||
drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
{
|
||||
@ -229,7 +270,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
cbChId = cmd & 0x03;
|
||||
if (cbChId == 0)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] channel id"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -237,7 +278,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
}
|
||||
else if (cbChId == 1)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] channel id"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -245,7 +286,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] channel id"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -256,6 +297,9 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_CAPS_RSP message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_capability_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -264,18 +308,22 @@ drdynvc_process_capability_response(struct xrdp_channel *self,
|
||||
int cap_version;
|
||||
int rv;
|
||||
|
||||
/* skip padding */
|
||||
in_uint8s(s, 1);
|
||||
/* read client's version */
|
||||
in_uint16_le(s, cap_version);
|
||||
if ((cap_version != 2) && (cap_version != 3))
|
||||
if (!s_check_rem_and_log(s, 3, "Parsing [MS-RDPEDYC] DYNVC_CAPS_RSP"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "drdynvc_process_capability_response: incompatible DVC "
|
||||
"version %d detected", cap_version);
|
||||
return 1;
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO, "drdynvc_process_capability_response: DVC version %d selected",
|
||||
cap_version);
|
||||
in_uint8s(s, 1); /* skip padding */
|
||||
in_uint16_le(s, cap_version); /* Version */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CAPS_RSP "
|
||||
"version %d", cap_version);
|
||||
|
||||
if ((cap_version != 2) && (cap_version != 3))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Dynamic Virtual Channel version %d is not supported",
|
||||
cap_version);
|
||||
return 1;
|
||||
}
|
||||
self->drdynvc_state = 1;
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
rv = session->callback(session->id, 0x5558, 0, 0, 0, 0);
|
||||
@ -283,6 +331,9 @@ drdynvc_process_capability_response(struct xrdp_channel *self,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_CREATE_RSP message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_open_channel_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -292,22 +343,27 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self,
|
||||
uint32_t chan_id;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP failed");
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, creation_status);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_open_channel_response: chan_id 0x%x "
|
||||
"creation_status %d", chan_id, creation_status);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
in_uint32_le(s, creation_status); /* CreationStatus */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP "
|
||||
"ChannelId %d, CreationStatus %d", chan_id, creation_status);
|
||||
if (chan_id > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP for an "
|
||||
"invalid channel id. Max allowed 255, received %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
if (creation_status == 0)
|
||||
{
|
||||
@ -317,14 +373,26 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self,
|
||||
{
|
||||
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"Dynamic Virtual Channel %s (%d) updated: status = %s",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id,
|
||||
XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status));
|
||||
if (drdynvc->open_response != NULL)
|
||||
{
|
||||
return drdynvc->open_response(session->id, chan_id, creation_status);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
|
||||
"callback 'open_response' is NULL",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_CLOSE message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_close_channel_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -333,26 +401,45 @@ drdynvc_process_close_channel_response(struct xrdp_channel *self,
|
||||
uint32_t chan_id;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"drdynvc_process_close_channel_response: drdynvc_get_chan_id failed");
|
||||
return 1;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_close_channel_response: chan_id 0x%x", chan_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CLOSE "
|
||||
"ChannelId %d", chan_id);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received message for an invalid "
|
||||
"channel id. channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"Dynamic Virtual Channel %s (%d) updated: status = %s",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id,
|
||||
XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status));
|
||||
|
||||
if (drdynvc->close_response != NULL)
|
||||
{
|
||||
return drdynvc->close_response(session->id, chan_id);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
|
||||
"callback 'close_response' is NULL",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_DATA_FIRST message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_data_first(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -364,40 +451,47 @@ drdynvc_process_data_first(struct xrdp_channel *self,
|
||||
int total_bytes;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST failed");
|
||||
return 1;
|
||||
}
|
||||
len = (cmd >> 2) & 0x03;
|
||||
if (len == 0)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, total_bytes);
|
||||
in_uint8(s, total_bytes); /* Length */
|
||||
}
|
||||
else if (len == 1)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, total_bytes);
|
||||
in_uint16_le(s, total_bytes); /* Length */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, total_bytes);
|
||||
in_uint32_le(s, total_bytes); /* Length */
|
||||
}
|
||||
bytes = (int) (s->end - s->p);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data_first: bytes %d total_bytes %d", bytes, total_bytes);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST "
|
||||
"ChannelId %d, Length %d, Data (omitted from the log)",
|
||||
chan_id, total_bytes);
|
||||
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST for an "
|
||||
"invalid channel id. Max allowed 255, received %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
@ -406,10 +500,17 @@ drdynvc_process_data_first(struct xrdp_channel *self,
|
||||
return drdynvc->data_first(session->id, chan_id, s->p,
|
||||
bytes, total_bytes);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
|
||||
"callback 'data_first' is NULL",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_DATA message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_data(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -419,15 +520,20 @@ drdynvc_process_data(struct xrdp_channel *self,
|
||||
int bytes;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "drdynvc_process_data: drdynvc_get_chan_id failed");
|
||||
return 1;
|
||||
}
|
||||
bytes = (int) (s->end - s->p);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data: bytes %d", bytes);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA "
|
||||
"ChannelId %d, (re-assembled) Length %d, Data (omitted from the log)",
|
||||
chan_id, bytes);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received message for an invalid "
|
||||
"channel id. channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
@ -435,10 +541,18 @@ drdynvc_process_data(struct xrdp_channel *self,
|
||||
{
|
||||
return drdynvc->data(session->id, chan_id, s->p, bytes);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
|
||||
"callback 'data' is NULL",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Process a [MS-RDPBCGR] 2.2.6.1 Virtual Channel PDU and re-assemble the
|
||||
* data chunks as needed.
|
||||
*/
|
||||
static int
|
||||
xrdp_channel_process_drdynvc(struct xrdp_channel *self,
|
||||
struct mcs_channel_item *channel,
|
||||
@ -451,61 +565,82 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self,
|
||||
int rv;
|
||||
struct stream *ls;
|
||||
|
||||
if (!s_check_rem(s, 8))
|
||||
if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] CHANNEL_PDU_HEADER"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, total_length);
|
||||
in_uint32_le(s, flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: total_length %d flags 0x%8.8x",
|
||||
total_length, flags);
|
||||
in_uint32_le(s, total_length); /* length */
|
||||
in_uint32_le(s, flags); /* flags */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER "
|
||||
"length %d, flags 0x%8.8x", total_length, flags);
|
||||
ls = NULL;
|
||||
switch (flags & 3)
|
||||
{
|
||||
case 0:
|
||||
case 0: /* not first chunk and not last chunk */
|
||||
length = (int) (s->end - s->p);
|
||||
if (!s_check_rem_out(self->s, length))
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (middle) "
|
||||
"length %d", length);
|
||||
if (length > s_rem_out(self->s))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than "
|
||||
"the remaining chunk buffer size. length %d, remaining %d",
|
||||
length, s_rem_out(self->s));
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
|
||||
in_uint8s(s, length); /* virtualChannelData */
|
||||
return 0;
|
||||
case 1:
|
||||
case 1: /* CHANNEL_FLAG_FIRST */
|
||||
free_stream(self->s);
|
||||
make_stream(self->s);
|
||||
init_stream(self->s, total_length);
|
||||
length = (int) (s->end - s->p);
|
||||
if (!s_check_rem_out(self->s, length))
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first) "
|
||||
"length %d", length);
|
||||
if (length > s_rem_out(self->s))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than "
|
||||
"the remaining chunk buffer size. length %d, remaining %d",
|
||||
length, s_rem_out(self->s));
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
|
||||
in_uint8s(s, length); /* virtualChannelData */
|
||||
return 0;
|
||||
case 2:
|
||||
case 2: /* CHANNEL_FLAG_LAST */
|
||||
length = (int) (s->end - s->p);
|
||||
if (!s_check_rem_out(self->s, length))
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (last) "
|
||||
"length %d", length);
|
||||
if (length > s_rem_out(self->s))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than "
|
||||
"the remaining chunk buffer size. length %d, remaining %d",
|
||||
length, s_rem_out(self->s));
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
|
||||
in_uint8s(s, length); /* virtualChannelData */
|
||||
ls = self->s;
|
||||
break;
|
||||
case 3:
|
||||
case 3: /* CHANNEL_FLAG_FIRST and CHANNEL_FLAG_LAST */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first and last) "
|
||||
"length %d", total_length);
|
||||
ls = s;
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_process_drdynvc: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] data chunk with "
|
||||
"unknown flag 0x%8.8x", (int) (flags & 3));
|
||||
return 1;
|
||||
}
|
||||
if (ls == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "BUG: ls must not be NULL");
|
||||
return 1;
|
||||
}
|
||||
in_uint8(ls, cmd); /* read command */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: cmd 0x%x", cmd);
|
||||
in_uint8(ls, cmd); /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPEDYC] "
|
||||
"cbId %d, Sp %d, Cmd 0x%2.2x",
|
||||
(cmd & 0x03), (cmd & 0x0c) >> 2, (cmd & 0xf0) >> 4);
|
||||
rv = 1;
|
||||
switch (cmd & 0xf0)
|
||||
{
|
||||
@ -525,16 +660,17 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self,
|
||||
rv = drdynvc_process_data(self, cmd, s);
|
||||
break;
|
||||
default:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: got unknown "
|
||||
"command 0x%x", cmd);
|
||||
LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPEDYC] with "
|
||||
"unknown command 0x%2.2x", cmd);
|
||||
break;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: rv %d", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Process a static ([MS-RDPBCGR] 2.2.6) or dynamic (MS-RDPEDYC 2.2.3)
|
||||
* virtual channel message.
|
||||
* returns error */
|
||||
/* This is called from the secure layer to process an incoming non global
|
||||
channel packet.
|
||||
'chanid' passed in here is the mcs channel id so it MCS_GLOBAL_CHANNEL
|
||||
@ -557,12 +693,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
|
||||
channel = xrdp_channel_get_item(self, channel_id);
|
||||
if (channel == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_process, channel not found");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Received a message for an unknown channel id. channel id %d",
|
||||
chanid);
|
||||
return 1;
|
||||
}
|
||||
if (channel->disabled)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_channel_process, channel disabled");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Received a message for the disabled channel %s (%d)",
|
||||
channel->name, chanid);
|
||||
return 0; /* not an error */
|
||||
}
|
||||
if (channel_id == self->drdynvc_channel_id)
|
||||
@ -570,14 +710,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
|
||||
return xrdp_channel_process_drdynvc(self, channel, s);
|
||||
}
|
||||
rv = 0;
|
||||
in_uint32_le(s, length);
|
||||
in_uint32_le(s, flags);
|
||||
in_uint32_le(s, length); /* length */
|
||||
in_uint32_le(s, flags); /* flags */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER "
|
||||
"length %d, flags 0x%8.8x", length, flags);
|
||||
rv = xrdp_channel_call_callback(self, s, channel_id, length, flags);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* drdynvc */
|
||||
/* Send a [MS-RDPEDYC] DYNVC_CAPS_VERSION2 message */
|
||||
static int
|
||||
xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
{
|
||||
@ -592,11 +734,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_send_capability_request: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
phold = s->p;
|
||||
out_uint8(s, 0x50); /* insert cmd */
|
||||
out_uint8(s, 0x50); /* insert cbId (2 bits), Sp (2 bits), cmd (4 bits) */
|
||||
out_uint8(s, 0x00); /* insert padding */
|
||||
out_uint16_le(s, 2); /* insert version */
|
||||
/* channel priority unused for now */
|
||||
@ -609,8 +753,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
total_data_len = (int) (s->end - phold);
|
||||
flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
channel_id = self->drdynvc_channel_id;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CAPS_VERSION2 "
|
||||
"cbId 0, Sp 0, Cmd 0x05, Version 2, PriorityCharge0 0, "
|
||||
"PriorityCharge1 0, PriorityCharge2 0, PriorityCharge3 0");
|
||||
if (xrdp_channel_send(self, s, channel_id, total_data_len, flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_send_capability_request: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -627,7 +776,12 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
|
||||
struct mcs_channel_item *ci;
|
||||
struct mcs_channel_item *dci;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_drdynvc_start:");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: drdynvc_channel_id %d", self->drdynvc_channel_id);
|
||||
if (self->drdynvc_channel_id != -1)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: already started");
|
||||
return 0;
|
||||
}
|
||||
dci = NULL;
|
||||
count = self->mcs_layer->channel_list->count;
|
||||
for (index = 0; index < count; index++)
|
||||
@ -645,12 +799,24 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
|
||||
if (dci != NULL)
|
||||
{
|
||||
self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"Initializing Dynamic Virtual Channel with channel id %d",
|
||||
self->drdynvc_channel_id);
|
||||
xrdp_channel_drdynvc_send_capability_request(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Dynamic Virtual Channel named 'drdynvc' not found, "
|
||||
"channel not initialized");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_CREATE_REQ message to request the creation of a channel.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
int flags, struct xrdp_drdynvc_procs *procs,
|
||||
@ -670,33 +836,46 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_open: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0); /* set later */
|
||||
ChId = 1;
|
||||
while (self->drdynvcs[ChId].status != XRDP_DRDYNVC_STATUS_CLOSED)
|
||||
{
|
||||
ChId++;
|
||||
if (ChId > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Attempting to create a new channel when the maximum "
|
||||
"number of channels have already been created. "
|
||||
"XRDP only supports 255 open channels.");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
|
||||
name_length = g_strlen(name);
|
||||
out_uint8a(s, name, name_length + 1);
|
||||
out_uint8a(s, name, name_length + 1); /* ChannelName */
|
||||
chan_pri = 0;
|
||||
/* cbId (low 2 bits), Pri (2 bits), Cmd (hi 4 bits) */
|
||||
cmd_ptr[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CREATE_REQ "
|
||||
"cbId %d, Pri %d, Cmd 0x%2.2x, ChannelId %d, ChannelName [%s]",
|
||||
cbChId, chan_pri, CMD_DVC_OPEN_CHANNEL, ChId, name);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Sending [MS-RDPEDYC] DYNVC_CREATE_REQ failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -711,6 +890,9 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_CLOSE message to request the closing of a channel.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
|
||||
{
|
||||
@ -724,33 +906,48 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
|
||||
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Attempting to close an invalid channel id. "
|
||||
"channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
if ((self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) &&
|
||||
(self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN_SENT))
|
||||
{
|
||||
/* not open */
|
||||
LOG(LOG_LEVEL_ERROR, "Attempting to close a channel that is not open. "
|
||||
"channel id %d, channel status %s",
|
||||
chan_id,
|
||||
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status));
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_close: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0); /* set later */
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
|
||||
/* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
|
||||
cmd_ptr[0] = CMD_DVC_CLOSE_CHANNEL | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CLOSE "
|
||||
"cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d",
|
||||
cbChId, CMD_DVC_OPEN_CHANNEL, ChId);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_open: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -760,6 +957,9 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_DATA_FIRST message.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes,
|
||||
@ -776,37 +976,53 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid "
|
||||
"channel id. channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that "
|
||||
"is not open. channel id %d, channel status %s",
|
||||
chan_id,
|
||||
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status));
|
||||
return 1;
|
||||
}
|
||||
if (data_bytes > 1590)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. "
|
||||
"data_bytes %d", chan_id, data_bytes);
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_data_first: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0); /* set later */
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes);
|
||||
out_uint8p(s, data, data_bytes);
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
|
||||
cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes); /* Length */
|
||||
out_uint8p(s, data, data_bytes); /* Data */
|
||||
/* cbId (low 2 bits), Len (2 bits), Cmd (hi 4 bits) */
|
||||
cmd_ptr[0] = CMD_DVC_DATA_FIRST | (cbTotalDataSize << 2) | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA_FIRST "
|
||||
"cbId %d, Len %d, Cmd 0x%2.2x, ChannelId %d, Length %d",
|
||||
cbChId, cbTotalDataSize, CMD_DVC_DATA_FIRST, ChId, total_data_bytes);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_data_first: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -815,6 +1031,9 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_DATA message.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes)
|
||||
@ -829,36 +1048,52 @@ xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
|
||||
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid "
|
||||
"channel id. channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that "
|
||||
"is not open. channel id %d, channel status %s",
|
||||
chan_id,
|
||||
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status));
|
||||
return 1;
|
||||
}
|
||||
if (data_bytes > 1590)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. "
|
||||
"data_bytes %d", chan_id, data_bytes);
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_data: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0); /* set later */
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
out_uint8p(s, data, data_bytes);
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
|
||||
out_uint8p(s, data, data_bytes); /* Data */
|
||||
/* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
|
||||
cmd_ptr[0] = CMD_DVC_DATA | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA "
|
||||
"cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d",
|
||||
cbChId, CMD_DVC_DATA_FIRST, ChId);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_data: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -30,12 +30,11 @@ xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans)
|
||||
{
|
||||
struct xrdp_fastpath *self;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_create");
|
||||
self = (struct xrdp_fastpath *)g_malloc(sizeof(struct xrdp_fastpath), 1);
|
||||
self->sec_layer = owner;
|
||||
self->trans = trans;
|
||||
self->session = owner->rdp_layer->session;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_create");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -63,13 +62,13 @@ int
|
||||
xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
|
||||
{
|
||||
int fp_hdr;
|
||||
int len = 0; /* unused */
|
||||
int len = 0;
|
||||
int byte;
|
||||
char *holdp;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_recv");
|
||||
|
||||
holdp = s->p;
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -84,7 +83,7 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
|
||||
byte &= ~(0x80);
|
||||
len = (byte << 8);
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU length2"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -97,7 +96,10 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
|
||||
len = byte;
|
||||
}
|
||||
s->next_packet = holdp + len;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_recv");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_FP_INPUT_PDU "
|
||||
"fpInputHeader.action (ignored), fpInputHeader.numEvents %d, "
|
||||
"fpInputHeader.flags 0x%1.1x, length %d",
|
||||
self->numEvents, self->secFlags, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -134,6 +136,10 @@ xrdp_fastpath_session_callback(struct xrdp_fastpath *self, int msg,
|
||||
self->session->callback(self->session->id, msg,
|
||||
param1, param2, param3, param4);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Bug: session is NULL");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -163,11 +169,14 @@ xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self,
|
||||
int code;
|
||||
flags = 0;
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, code); /* keyCode (1 byte) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT "
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
|
||||
"keyCode %d", eventFlags, code);
|
||||
|
||||
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
|
||||
{
|
||||
@ -205,13 +214,16 @@ xrdp_fastpath_process_EVENT_MOUSE(struct xrdp_fastpath *self,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2 + 2 + 2))
|
||||
if (!s_check_rem_and_log(s, 2 + 2 + 2, "Parsing [MS-RDPBCGR] TS_FP_POINTER_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */
|
||||
in_uint16_le(s, xPos); /* xPos (2 bytes) */
|
||||
in_uint16_le(s, yPos); /* yPos (2 bytes) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTER_EVENT "
|
||||
"eventHeader.eventFlags 0x00, eventHeader.eventCode (ignored), "
|
||||
"pointerFlags 0x%4.4x, xPos %d, yPos %d", pointerFlags, xPos, yPos);
|
||||
|
||||
xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSE,
|
||||
xPos, yPos, pointerFlags, 0);
|
||||
@ -235,13 +247,18 @@ xrdp_fastpath_process_EVENT_MOUSEX(struct xrdp_fastpath *self,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2 + 2 + 2))
|
||||
if (!s_check_rem_and_log(s, 2 + 2 + 2,
|
||||
"Parsing [MS-RDPBCGR] TS_FP_POINTERX_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */
|
||||
in_uint16_le(s, xPos); /* xPos (2 bytes) */
|
||||
in_uint16_le(s, yPos); /* yPos (2 bytes) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTERX_EVENT "
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
|
||||
"pointerFlags 0x%4.4x, xPos %d, yPos %d",
|
||||
eventFlags, pointerFlags, xPos, yPos);
|
||||
|
||||
xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSEX,
|
||||
xPos, yPos, pointerFlags, 0);
|
||||
@ -263,6 +280,10 @@ xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self,
|
||||
* status of the keyboard toggle keys.
|
||||
*/
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_SYNC_EVENT"
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), ",
|
||||
eventFlags);
|
||||
|
||||
xrdp_fastpath_session_callback(self, RDP_INPUT_SYNCHRONIZE,
|
||||
eventFlags, 0, 0, 0);
|
||||
|
||||
@ -279,11 +300,16 @@ xrdp_fastpath_process_EVENT_UNICODE(struct xrdp_fastpath *self,
|
||||
int code;
|
||||
|
||||
flags = 0;
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, code); /* unicode (2 byte) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT"
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
|
||||
"unicodeCode %d",
|
||||
eventFlags, code);
|
||||
|
||||
if (eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)
|
||||
{
|
||||
flags |= KBD_FLAG_UP;
|
||||
@ -315,7 +341,7 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
|
||||
/* process fastpath input events */
|
||||
for (i = 0; i < self->numEvents; i++)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_EVENT eventHeader"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -323,6 +349,9 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
|
||||
|
||||
eventFlags = (eventHeader & 0x1F);
|
||||
eventCode = (eventHeader >> 5);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_INPUT_EVENT"
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode 0x%1.1x",
|
||||
eventFlags, eventCode);
|
||||
|
||||
switch (eventCode)
|
||||
{
|
||||
@ -367,8 +396,8 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_fastpath_process_input_event: unknown "
|
||||
"eventCode %d", eventCode);
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_fastpath_process_input_event: "
|
||||
"unknown eventCode %d", eventCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,11 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
* iso layer
|
||||
*
|
||||
* Note: [ITU-T X.224] and [ISO/IEC 8073] are essentially two specifications
|
||||
* of the same protocol (see [ITU-T X.224] Appendix I – Differences between
|
||||
* ITU-T Rec. X.224 (1993) and ISO/IEC 8073:1992). The RDP protocol
|
||||
* specification [MS-RDPBCGR] makes reference to the [ITU-T X.224] specificaiton.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
@ -36,11 +41,9 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans)
|
||||
{
|
||||
struct xrdp_iso *self;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_create");
|
||||
self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1);
|
||||
self->mcs_layer = owner;
|
||||
self->trans = trans;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_create");
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -77,8 +80,10 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
|
||||
!g_file_readable(client_info->key_file))
|
||||
{
|
||||
/* certificate or privkey is not readable */
|
||||
LOG(LOG_LEVEL_WARNING, "No readable certificates or "
|
||||
"private keys, cannot accept TLS connections");
|
||||
LOG(LOG_LEVEL_ERROR, "Cannot accept TLS connections because "
|
||||
"certificate or private key file is not readable. "
|
||||
"certificate file: [%s], private key file: [%s]",
|
||||
client_info->certificate, client_info->key_file);
|
||||
self->failureCode = SSL_CERT_NOT_ON_SERVER;
|
||||
rv = 1; /* error */
|
||||
}
|
||||
@ -89,6 +94,8 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Server requires TLS for security, "
|
||||
"but the client did not request TLS.");
|
||||
self->failureCode = SSL_REQUIRED_BY_SERVER;
|
||||
rv = 1; /* error */
|
||||
}
|
||||
@ -116,40 +123,52 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Process a [MS-RDPBCGR] RDP_NEG_REQ message.
|
||||
* returns error
|
||||
*/
|
||||
static int
|
||||
xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
|
||||
{
|
||||
int flags;
|
||||
int len;
|
||||
|
||||
if (!s_check_rem(s, 7))
|
||||
if (!s_check_rem_and_log(s, 7, "Parsing [MS-RDPBCGR] RDP_NEG_REQ"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: unexpected end-of-record");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, flags);
|
||||
/* The type field has already been read to determine that this function
|
||||
should be called */
|
||||
in_uint8(s, flags); /* flags */
|
||||
if (flags != 0x0 && flags != 0x8 && flags != 0x1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, flags: %x", flags);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unsupported [MS-RDPBCGR] RDP_NEG_REQ flags: 0x%2.2x", flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint16_le(s, len);
|
||||
in_uint16_le(s, len); /* length */
|
||||
if (len != 8)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, length: %x", len);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Protocol error: [MS-RDPBCGR] RDP_NEG_REQ length must be 8, "
|
||||
"received %d", len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint32_le(s, self->requestedProtocol);
|
||||
in_uint32_le(s, self->requestedProtocol); /* requestedProtocols */
|
||||
|
||||
/* TODO: why is requestedProtocols flag value bigger than 0xb invalid? */
|
||||
if (self->requestedProtocol > 0xb)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, requestedProtocol: %x",
|
||||
self->requestedProtocol);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unknown requested protocol flag [MS-RDPBCGR] RDP_NEG_REQ, "
|
||||
"requestedProtocol 0x%8.8x", self->requestedProtocol);
|
||||
return 1;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received struct [MS-RDPBCGR] RDP_NEG_REQ "
|
||||
"flags 0x%2.2x, length 8, requestedProtocol 0x%8.8x",
|
||||
flags, self->requestedProtocol);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -163,6 +182,10 @@ xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
|
||||
* On exit, the TPKT header and the fixed part of the PDU header will have been
|
||||
* removed from the stream.
|
||||
*
|
||||
* @param self
|
||||
* @param s [in]
|
||||
* @param code [out]
|
||||
* @param len [out]
|
||||
* Returns error
|
||||
*****************************************************************************/
|
||||
static int
|
||||
@ -175,83 +198,110 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len)
|
||||
|
||||
if (s != self->trans->in_s)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_iso_recv_msg error logic");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Bug: the input stream is not the same stream as the "
|
||||
"transport input stream");
|
||||
}
|
||||
|
||||
/* TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */
|
||||
if (!s_check_rem(s, 6))
|
||||
/* [ITU-T T.123] TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */
|
||||
if (!s_check_rem_and_log(s, 6,
|
||||
"Parsing [ITU-T T.123] TPKT header and [ITU-T X.224] TPDU header"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, ver);
|
||||
in_uint8s(s, 3); /* Skip reserved field, plus length */
|
||||
in_uint8(s, *len);
|
||||
in_uint8(s, *code);
|
||||
/* [ITU-T T.123] TPKT header */
|
||||
in_uint8(s, ver); /* version */
|
||||
in_uint8s(s, 3); /* Skip reserved field (1 byte), plus length (2 bytes) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T T.123] TPKT "
|
||||
"version %d, length (ignored)", ver);
|
||||
|
||||
/* [ITU-T X.224] TPDU header */
|
||||
in_uint8(s, *len); /* LI (length indicator) */
|
||||
in_uint8(s, *code); /* TPDU code */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T X.224] TPDU "
|
||||
"length indicator %d, TDPU code 0x%2.2x", *len, *code);
|
||||
|
||||
if (ver != 3)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: bad ver");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unsupported [ITU-T T.123] TPKT header version: %d", ver);
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T T.123] TPKT header", s->data, 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*len == 255)
|
||||
{
|
||||
/* X.224 13.2.1 - reserved value */
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: reserved length encountered");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"[ITU-T X.224] TPDU header: unsupported use of reserved length value");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T X.224] TPDU header", s->data + 4, 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*code == ISO_PDU_DT)
|
||||
{
|
||||
/* Data PDU : X.224 13.7 */
|
||||
if (!s_check_rem(s, 1))
|
||||
/* Data PDU : X.224 13.7 class 0 */
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T X.224] DT-TPDU (Data) header"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 1);
|
||||
in_uint8s(s, 1); /* EOT (End of TSDU Mark) (upper 1 bit) and
|
||||
TPDU-NR (Data TPDU Number) (lower 7 bits) */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other supported PDUs : X.224 13.x */
|
||||
if (!s_check_rem(s, 5))
|
||||
/* Other supported X.224 class 0 PDUs all have 5 bytes remaining
|
||||
in the fixed header :
|
||||
CR Connection request (13.3)
|
||||
CC Connection confirm (13.4)
|
||||
DR Disconnect request (13.5) */
|
||||
if (!s_check_rem_and_log(s, 5, "Parsing [ITU-T X.224] Other PDU header"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 5);
|
||||
in_uint8s(s, 5); /* DST-REF (2 bytes)
|
||||
SRC-REF (2 bytes)
|
||||
[CR, CC] CLASS OPTION (1 byte) or [DR] REASON (1 byte) */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Process the header of a [ITU-T X.224] DT-TPDU (Data) message.
|
||||
*
|
||||
* returns error
|
||||
*/
|
||||
int
|
||||
xrdp_iso_recv(struct xrdp_iso *self, struct stream *s)
|
||||
{
|
||||
int code;
|
||||
int len;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_recv");
|
||||
|
||||
if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv xrdp_iso_recv_msg return non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv: xrdp_iso_recv_msg failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (code != ISO_PDU_DT || len != 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv code != ISO_PDU_DT or length != 2");
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv only supports processing "
|
||||
"[ITU-T X.224] DT-TPDU (Data) headers. Received TPDU header: "
|
||||
"length indicator %d, TDPU code 0x%2.2x", len, code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_recv");
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [ITU-T X.224] CC-TPDU (Connection Confirm) message with
|
||||
* [ITU-T T.123] TPKT header.
|
||||
*
|
||||
* returns error
|
||||
*/
|
||||
static int
|
||||
xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
{
|
||||
@ -266,35 +316,44 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
init_stream(s, 8192);
|
||||
|
||||
holdp = s->p;
|
||||
/* tpkt */
|
||||
/* [ITU-T T.123] TPKT header */
|
||||
out_uint8(s, 3); /* version */
|
||||
out_uint8(s, 0); /* pad */
|
||||
out_uint8(s, 0); /* reserved (padding) */
|
||||
len_ptr = s->p;
|
||||
out_uint16_be(s, 0); /* length, set later */
|
||||
/* iso */
|
||||
|
||||
/* [ITU-T X.224] CC-TPDU */
|
||||
len_indicator_ptr = s->p;
|
||||
out_uint8(s, 0); /* length indicator, set later */
|
||||
out_uint8(s, 0); /* length indicator, set later */
|
||||
out_uint8(s, ISO_PDU_CC); /* Connection Confirm PDU */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0x1234);
|
||||
out_uint8(s, 0);
|
||||
/* rdpNegData */
|
||||
out_uint16_be(s, 0); /* DST-REF */
|
||||
out_uint16_be(s, 0x1234); /* SRC-REF */
|
||||
out_uint8(s, 0); /* CLASS OPTION */
|
||||
|
||||
/* [MS-RDPBCGR] 2.2.1.2 rdpNegData */
|
||||
if (self->rdpNegData)
|
||||
{
|
||||
if (self->failureCode)
|
||||
{
|
||||
out_uint8(s, RDP_NEG_FAILURE);
|
||||
out_uint8(s, 0); /* no flags */
|
||||
out_uint16_le(s, 8); /* must be 8 */
|
||||
out_uint32_le(s, self->failureCode); /* failure code */
|
||||
/* [MS-RDPBCGR] RDP_NEG_FAILURE */
|
||||
out_uint8(s, RDP_NEG_FAILURE); /* type*/
|
||||
out_uint8(s, 0); /* flags (none) */
|
||||
out_uint16_le(s, 8); /* length (must be 8) */
|
||||
out_uint32_le(s, self->failureCode); /* failureCode */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_FAILURE "
|
||||
"flags 0, length 8, failureCode 0x%8.8x", self->failureCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint8(s, RDP_NEG_RSP);
|
||||
/* [MS-RDPBCGR] RDP_NEG_RSP */
|
||||
out_uint8(s, RDP_NEG_RSP); /* type*/
|
||||
//TODO: hardcoded flags
|
||||
out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */
|
||||
out_uint16_le(s, 8); /* must be 8 */
|
||||
out_uint32_le(s, self->selectedProtocol); /* selected protocol */
|
||||
out_uint16_le(s, 8); /* length (must be 8) */
|
||||
out_uint32_le(s, self->selectedProtocol); /* selectedProtocol */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_RSP "
|
||||
"flags 0, length 8, selectedProtocol 0x%8.8x",
|
||||
self->selectedProtocol);
|
||||
}
|
||||
}
|
||||
s_mark_end(s);
|
||||
@ -305,8 +364,15 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
len_ptr[1] = len;
|
||||
len_indicator_ptr[0] = len_indicator;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT "
|
||||
"version 3, length %d", len);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) "
|
||||
"length indicator %d, DST-REF 0, SRC-REF 0, CLASS OPTION 0",
|
||||
len_indicator);
|
||||
|
||||
if (trans_write_copy_s(self->trans, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -317,7 +383,7 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
/*****************************************************************************
|
||||
* Process an X.224 connection request PDU
|
||||
*
|
||||
* See MS-RDPCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1.
|
||||
* See MS-RDPBCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1.
|
||||
*
|
||||
* From the latter, in particular:-
|
||||
* - The length embedded in the TPKT header MUST be examined for
|
||||
@ -339,22 +405,26 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
struct stream *s;
|
||||
int expected_pdu_len;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_incoming");
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: receive connection request");
|
||||
s = libxrdp_force_read(self->trans);
|
||||
if (s == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_recv_msg returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (code != ISO_PDU_CR)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming only supports processing "
|
||||
"[ITU-T X.224] CR-TPDU (Connection Request) headers. "
|
||||
"Received TPDU header: length indicator %d, TDPU code 0x%2.2x",
|
||||
len, code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -369,38 +439,47 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
expected_pdu_len = (s->end - s->p) + 6;
|
||||
if (len != expected_pdu_len)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: X.224 CR-TPDU length exp %d got %d",
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Invalid length indicator in [ITU-T X.224] CR-TPDU (Connection Request). "
|
||||
"expected %d, received %d",
|
||||
expected_pdu_len, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* process connection request */
|
||||
/* process connection request [MS-RDPBCGR] 2.2.1.1 */
|
||||
while (s_check_rem(s, 1))
|
||||
{
|
||||
in_uint8(s, cc_type);
|
||||
in_uint8(s, cc_type); /* type or 'C' */
|
||||
switch (cc_type)
|
||||
{
|
||||
default:
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
||||
"Ignoring unknown structure type in [ITU-T X.224] CR-TPDU (Connection Request). "
|
||||
"type 0x%2.2x", cc_type);
|
||||
break;
|
||||
case RDP_NEG_REQ: /* rdpNegReq 1 */
|
||||
self->rdpNegData = 1;
|
||||
if (xrdp_iso_process_rdp_neg_req(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_process_rdpNegReq returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"[ITU-T X.224] Connection Sequence: failed");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case RDP_CORRELATION_INFO: /* rdpCorrelationInfo 6 */
|
||||
// TODO
|
||||
if (!s_check_rem(s, 1 + 2 + 16 + 16))
|
||||
if (!s_check_rem_and_log(s, 1 + 2 + 16 + 16,
|
||||
"Parsing [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: short correlation info");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 1 + 2 + 16 + 16);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"Received struct [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO "
|
||||
"(all fields ignored)");
|
||||
break;
|
||||
case 'C': /* Cookie */
|
||||
case 'C': /* Cookie or routingToken */
|
||||
/* The routingToken and cookie fields are both ASCII
|
||||
* strings starting with the word 'Cookie: ' and
|
||||
* ending with CR+LF. We ignore both, so we do
|
||||
@ -417,6 +496,9 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"Received struct [MS-RDPBCGR] routingToken or cookie "
|
||||
"(ignored)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -425,13 +507,14 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
rv = xrdp_iso_negotiate_security(self);
|
||||
|
||||
/* send connection confirm back to client */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: send connection confirmation");
|
||||
if (xrdp_iso_send_cc(self) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_send_cc returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: send connection confirmation failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_incoming");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: completed");
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -446,27 +529,39 @@ xrdp_iso_init(struct xrdp_iso *self, struct stream *s)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Sends a message with the [ITU-T T.123] TPKT header (T.123 section 8) and
|
||||
* [ITU-T X.224] DT-TPDU (Data) header (X.224 section 13)
|
||||
* returns error
|
||||
*/
|
||||
int
|
||||
xrdp_iso_send(struct xrdp_iso *self, struct stream *s)
|
||||
{
|
||||
int len;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_send");
|
||||
s_pop_layer(s, iso_hdr);
|
||||
len = (int) (s->end - s->p);
|
||||
out_uint8(s, 3);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_be(s, len);
|
||||
out_uint8(s, 2);
|
||||
out_uint8(s, ISO_PDU_DT);
|
||||
out_uint8(s, 0x80);
|
||||
/* [ITU-T T.123] TPKT header */
|
||||
out_uint8(s, 3); /* version */
|
||||
out_uint8(s, 0); /* reserved (padding) */
|
||||
out_uint16_be(s, len); /* length */
|
||||
|
||||
/* [ITU-T X.224] DT-TPDU (Data) header */
|
||||
out_uint8(s, 2); /* LI (length indicator) */
|
||||
out_uint8(s, ISO_PDU_DT); /* TPDU code */
|
||||
out_uint8(s, 0x80); /* EOT (End of TSDU Mark) (upper 1 bit) and
|
||||
TPDU-NR (Data TPDU Number) (lower 7 bits) */
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT "
|
||||
"version 3, length %d", len);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T X.224] DT-TPDU (Data) "
|
||||
"length indicator 2, TPDU code 0x%2.2x, EOT 1, TPDU-NR 0x00",
|
||||
ISO_PDU_DT);
|
||||
|
||||
if (trans_write_copy_s(self->trans, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_send: trans_write_copy_s failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_send");
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -969,6 +969,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
|
||||
{
|
||||
/* compressed data longer than uncompressed data */
|
||||
/* give up */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Compression algorithim produced a compressed "
|
||||
"buffer which is larger than the uncompressed buffer. "
|
||||
"compression ratio %f, flags 0x%x",
|
||||
(float) len / (float) opb_index, enc->flags);
|
||||
enc->historyOffset = 0;
|
||||
g_memset(hash_table, 0, enc->buf_len * 2);
|
||||
g_memset(enc->historyBuffer, 0, enc->buf_len);
|
||||
@ -982,10 +986,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
|
||||
enc->flags |= enc->flagsHold;
|
||||
enc->flagsHold = 0;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "\n");
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "compression ratio: %f", (float) len / (float) enc->bytes_in_opb);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Compression successful. compression ratio %f, "
|
||||
"flags 0x%x, bytes_in_opb %d, historyOffset %d, uncompressed len %d",
|
||||
(float) len / (float) enc->bytes_in_opb, enc->flags,
|
||||
enc->bytes_in_opb, enc->historyOffset, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -83,6 +83,7 @@ xrdp_orders_reset(struct xrdp_orders *self)
|
||||
{
|
||||
if (xrdp_orders_force_send(self) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_reset: xrdp_orders_force_send failed");
|
||||
return 1;
|
||||
}
|
||||
g_free(self->orders_state.text_data);
|
||||
@ -109,23 +110,29 @@ xrdp_orders_init(struct xrdp_orders *self)
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: fastpath");
|
||||
if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_fastpath failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count_ptr = self->out_s->p;
|
||||
out_uint8s(self->out_s, 2); /* number of orders, set later */
|
||||
// LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TODO");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: slowpath");
|
||||
if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_data failed");
|
||||
return 1;
|
||||
}
|
||||
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS);
|
||||
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); /* updateType */
|
||||
out_uint8s(self->out_s, 2); /* pad */
|
||||
self->order_count_ptr = self->out_s->p;
|
||||
out_uint8s(self->out_s, 2); /* number of orders, set later */
|
||||
out_uint8s(self->out_s, 2); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TS_UPDATE_ORDERS_PDU_DATA "
|
||||
"updateType %d (UPDATETYPE_ORDERS), pad2OctetsA <ignored>, "
|
||||
"numberOrders <to be set later>, pad2OctetsB <ignored>",
|
||||
RDP_UPDATE_ORDERS);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -154,6 +161,8 @@ xrdp_orders_send(struct xrdp_orders *self)
|
||||
if (xrdp_rdp_send_fastpath(self->rdp_layer,
|
||||
self->out_s, 0) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send: xrdp_rdp_send_fastpath failed");
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
@ -162,6 +171,8 @@ xrdp_orders_send(struct xrdp_orders *self)
|
||||
if (xrdp_rdp_send_data(self->rdp_layer, self->out_s,
|
||||
RDP_DATA_PDU_UPDATE) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send: xrdp_rdp_send_data failed");
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
@ -225,6 +236,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
|
||||
{
|
||||
if (max_size > max_order_size)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Requested orders max_size (%d) "
|
||||
"is greater than the client connection max_size (%d)",
|
||||
max_size, max_order_size);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
@ -237,7 +251,8 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
|
||||
size = (int)(self->out_s->p - self->order_count_ptr);
|
||||
if (size < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "error in xrdp_orders_check, size too small: %d bytes", size);
|
||||
LOG(LOG_LEVEL_ERROR, "Bug: order data length cannot be negative. "
|
||||
"Found length %d bytes", size);
|
||||
return 1;
|
||||
}
|
||||
if (size > max_order_size)
|
||||
@ -245,7 +260,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
|
||||
/* this suggests someone calls this function without passing the
|
||||
correct max_size so we end up putting more into the buffer
|
||||
than we indicate we can */
|
||||
LOG(LOG_LEVEL_WARNING, "error in xrdp_orders_check, size too big: %d bytes", size);
|
||||
LOG(LOG_LEVEL_WARNING, "Ignoring Bug: order data length "
|
||||
"is larger than maximum length. Expected %d, actual %d",
|
||||
max_order_size, size);
|
||||
/* We where getting called with size already greater than
|
||||
max_order_size
|
||||
Which I suspect was because the sending of text did not include
|
||||
@ -2175,15 +2192,23 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette,
|
||||
|
||||
if (xrdp_orders_check(self, 2000) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_send_palette: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_STANDARD | TS_SECONDARY;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] DRAWING_ORDER "
|
||||
"controlFlags 0x%2.2x (TS_STANDARD | TS_SECONDARY)", order_flags);
|
||||
|
||||
len = 1027 - 7; /* length after type minus 7 */
|
||||
out_uint16_le(self->out_s, len);
|
||||
out_uint16_le(self->out_s, 0); /* flags */
|
||||
out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* type */
|
||||
out_uint16_le(self->out_s, len); /* orderLength */
|
||||
out_uint16_le(self->out_s, 0); /* extraFlags */
|
||||
out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* orderType */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] SECONDARY_DRAWING_ORDER_HEADER "
|
||||
"orderLength %d, extraFlags 0x0000, orderType 0x%2.2x (TS_CACHE_COLOR_TABLE)",
|
||||
len, TS_CACHE_COLOR_TABLE);
|
||||
|
||||
out_uint8(self->out_s, cache_id);
|
||||
out_uint16_le(self->out_s, 256); /* num colors */
|
||||
|
||||
@ -2194,7 +2219,9 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette,
|
||||
out_uint8(self->out_s, palette[i] >> 16);
|
||||
out_uint8(self->out_s, 0);
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPEGDI] CACHE_COLOR_TABLE_ORDER "
|
||||
"cacheIndex %d, numberColors 256, colorTable <omitted from log>",
|
||||
cache_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -42,12 +42,19 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
|
||||
order_size = 11;
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_delete: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -55,6 +62,12 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, "
|
||||
"FieldsPresentFlags 0x%8.8x (WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED), "
|
||||
"WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Window");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -75,12 +88,19 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
|
||||
order_size = 14;
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_cached_icon: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -89,10 +109,17 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Cached Icon");
|
||||
|
||||
/* CacheEntry (2 bytes) */
|
||||
out_uint16_le(self->out_s, cache_entry);
|
||||
/* CacheId (1 byte) */
|
||||
out_uint8(self->out_s, cache_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO "
|
||||
"CacheEntry %d, CacheId %d", cache_entry, cache_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -134,6 +161,18 @@ xrdp_orders_send_ts_icon(struct stream *s, int cache_entry, int cache_id,
|
||||
}
|
||||
|
||||
out_uint8p(s, icon_info->data, icon_info->data_bytes);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order fields [MS-RDPERP] TS_ICON_INFO "
|
||||
"CacheEntry %d, CacheId %d, Bpp %d, Width %d, Height %d, "
|
||||
"CbColorTable <%s>, "
|
||||
"CbBitsMask %d, CbBitsColor %d, BitsMask <omitted from log>, "
|
||||
"ColorTable <%s>, "
|
||||
"BitsColor <omitted from log>",
|
||||
cache_entry, cache_id, icon_info->bpp, icon_info->width,
|
||||
icon_info->height,
|
||||
(use_cmap ? "present, omitted from log" : "not present"),
|
||||
icon_info->mask_bytes, icon_info->data_bytes,
|
||||
(use_cmap ? "present, omitted from log" : "not present")
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -169,12 +208,19 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_icon: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -183,6 +229,10 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Window Icon");
|
||||
|
||||
xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info);
|
||||
|
||||
@ -372,23 +422,36 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_new_update: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Window (TS_WINDOW_INFO)");
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
|
||||
{
|
||||
/* ownerWindowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->owner_window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"OwnerWindowId 0x%8.8x", window_state->owner_window_id);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
|
||||
@ -397,18 +460,28 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->style);
|
||||
/* extendedStyle (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->extended_style);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"Style 0x%8.8x, ExtendedStyle 0x%8.8x",
|
||||
window_state->style, window_state->extended_style);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
|
||||
{
|
||||
/* showState (1 byte) */
|
||||
out_uint8(self->out_s, window_state->show_state);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"ShowState 0x%2.2x", window_state->show_state);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
|
||||
{
|
||||
/* titleInfo */
|
||||
xrdp_orders_send_as_unicode(self->out_s, window_state->title_info);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"TitleInfo %s", window_state->title_info);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
|
||||
@ -417,26 +490,61 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->client_offset_x);
|
||||
/* clientOffsetY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->client_offset_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"ClientOffsetX %d, ClientOffsetY %d",
|
||||
window_state->client_offset_x, window_state->client_offset_y);
|
||||
}
|
||||
|
||||
/* TODO: The [MS-RDPERP] spec says that:
|
||||
* The ClientAreaWidth and ClientAreaHeight field only appears if the WndSupportLevel field of the
|
||||
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
|
||||
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
|
||||
*/
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
|
||||
{
|
||||
/* clientAreaWidth (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->client_area_width);
|
||||
/* clientAreaHeight (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->client_area_height);
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"ClientAreaWidth %d, ClientAreaHeight %d",
|
||||
window_state->client_area_width, window_state->client_area_height);
|
||||
}
|
||||
/* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields:
|
||||
* WindowLeftResizeMargin (optional)
|
||||
* WindowRightResizeMargin (optional)
|
||||
* WindowTopResizeMargin (optional)
|
||||
* WindowBottomResizeMargin (optional)
|
||||
*/
|
||||
|
||||
/* TODO: The [MS-RDPERP] spec says that:
|
||||
* The RPContent field only appears if the WndSupportLevel field of the
|
||||
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
|
||||
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
|
||||
*/
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
|
||||
{
|
||||
/* RPContent (1 byte) */
|
||||
out_uint8(self->out_s, window_state->rp_content);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"RPContent 0x%2.2x", window_state->rp_content);
|
||||
}
|
||||
|
||||
/* TODO: The [MS-RDPERP] spec says that:
|
||||
* The RootParentHandle field only appears if the WndSupportLevel field of the
|
||||
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
|
||||
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
|
||||
*/
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
|
||||
{
|
||||
/* rootParentHandle (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->root_parent_handle);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"RootParentHandle 0x%8.8x", window_state->root_parent_handle);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
|
||||
@ -445,6 +553,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->window_offset_x);
|
||||
/* windowOffsetY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->window_offset_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"WindowOffsetX %d, WindowOffsetY %d",
|
||||
window_state->window_offset_x, window_state->window_offset_y);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
|
||||
@ -453,6 +565,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->window_client_delta_x);
|
||||
/* windowClientDeltaY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->window_client_delta_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"WindowClientDeltaX %d, WindowClientDeltaY %d",
|
||||
window_state->window_client_delta_x, window_state->window_client_delta_y);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
|
||||
@ -461,6 +577,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->window_width);
|
||||
/* windowHeight (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->window_height);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"WindowWidth %d, WindowHeight %d",
|
||||
window_state->window_width, window_state->window_height);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
|
||||
@ -475,6 +595,9 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint16_le(self->out_s, window_state->window_rects[index].right);
|
||||
out_uint16_le(self->out_s, window_state->window_rects[index].bottom);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"NumWindowRects %d, WindowRects <omitted from log>",
|
||||
window_state->num_window_rects);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
|
||||
@ -483,6 +606,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->visible_offset_x);
|
||||
/* visibleOffsetY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->visible_offset_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"VisibleOffsetX %d, VisibleOffsetY %d",
|
||||
window_state->visible_offset_x, window_state->visible_offset_y);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
|
||||
@ -497,7 +624,17 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint16_le(self->out_s, window_state->visibility_rects[index].right);
|
||||
out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"NumVisibilityRects %d, VisibilityRects <omitted from log>",
|
||||
window_state->num_visibility_rects);
|
||||
}
|
||||
/* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields:
|
||||
* OverlayDescription (optional, variable)
|
||||
* TaskbarButton (optional)
|
||||
* EnforceServerZOrder (optional)
|
||||
* AppBarState (optional)
|
||||
* AppBarEdge (optional)
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -516,12 +653,19 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
|
||||
order_size = 15;
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_notify_delete: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -531,6 +675,11 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
/* notifyIconId (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Notification Icons");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -610,12 +759,19 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_notify_new_update: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -624,17 +780,27 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
/* notifyIconId (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Notification Icons");
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
|
||||
{
|
||||
/* Version (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_state->version);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"Version %d", notify_state->version);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
|
||||
{
|
||||
/* ToolTip (variable) UNICODE_STRING */
|
||||
xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"ToolTip %s", notify_state->tool_tip);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
|
||||
@ -644,12 +810,20 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, notify_state->infotip.flags);
|
||||
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text);
|
||||
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] TS_NOTIFY_ICON_INFOTIP "
|
||||
"Timeout %d, InfoFlags 0x%8.8x, InfoTipText %s, Title %s",
|
||||
notify_state->infotip.timeout, notify_state->infotip.flags,
|
||||
notify_state->infotip.text, notify_state->infotip.title);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
|
||||
{
|
||||
/* State (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_state->state);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"State %d", notify_state->state);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_ICON)
|
||||
@ -666,6 +840,10 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
out_uint16_le(self->out_s, notify_state->icon_cache_entry);
|
||||
/* CacheId (1 byte) */
|
||||
out_uint8(self->out_s, notify_state->icon_cache_id);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO "
|
||||
"CacheEntry %d, CacheId %d",
|
||||
notify_state->icon_cache_entry, notify_state->icon_cache_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -704,21 +882,37 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_monitored_desktop: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_DESKTOP_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x",
|
||||
order_size, field_present_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] %s",
|
||||
((field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_NONE) ?
|
||||
"Non-Monitored Desktop" : "Actively Monitored Desktop"));
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
|
||||
{
|
||||
/* ActiveWindowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, mdo->active_window_id);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"ActiveWindowId 0x%8.8x", mdo->active_window_id);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
|
||||
@ -731,6 +925,10 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
|
||||
{
|
||||
out_uint32_le(self->out_s, mdo->window_ids[index]);
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"NumWindowIds %d, WindowIds <omitted from log>",
|
||||
mdo->num_window_ids);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
17
mc/mc.c
17
mc/mc.c
@ -23,17 +23,18 @@
|
||||
#endif
|
||||
|
||||
#include "mc.h"
|
||||
#include "log.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* return error */
|
||||
int
|
||||
lib_mod_start(struct mod *mod, int w, int h, int bpp)
|
||||
{
|
||||
LIB_DEBUG(mod, "in lib_mod_start");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_start");
|
||||
mod->width = w;
|
||||
mod->height = h;
|
||||
mod->bpp = bpp;
|
||||
LIB_DEBUG(mod, "out lib_mod_start");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_start");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -42,8 +43,8 @@ lib_mod_start(struct mod *mod, int w, int h, int bpp)
|
||||
int
|
||||
lib_mod_connect(struct mod *mod)
|
||||
{
|
||||
LIB_DEBUG(mod, "in lib_mod_connect");
|
||||
LIB_DEBUG(mod, "out lib_mod_connect");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_connect");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_connect");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -53,8 +54,8 @@ int
|
||||
lib_mod_event(struct mod *mod, int msg, long param1, long param2,
|
||||
long param3, long param4)
|
||||
{
|
||||
LIB_DEBUG(mod, "in lib_mod_event");
|
||||
LIB_DEBUG(mod, "out lib_mod_event");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_event");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_event");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -63,8 +64,8 @@ lib_mod_event(struct mod *mod, int msg, long param1, long param2,
|
||||
int
|
||||
lib_mod_signal(struct mod *mod)
|
||||
{
|
||||
LIB_DEBUG(mod, "in lib_mod_signal");
|
||||
LIB_DEBUG(mod, "out lib_mod_signal");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_signal");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_signal");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
134
mc/mc.h
134
mc/mc.h
@ -30,73 +30,73 @@ struct source_info;
|
||||
|
||||
struct mod
|
||||
{
|
||||
int size; /* size of this struct */
|
||||
int version; /* internal version */
|
||||
/* client functions */
|
||||
int (*mod_start)(struct mod* v, int w, int h, int bpp);
|
||||
int (*mod_connect)(struct mod* v);
|
||||
int (*mod_event)(struct mod* v, int msg, long param1, long param2,
|
||||
long param3, long param4);
|
||||
int (*mod_signal)(struct mod* v);
|
||||
int (*mod_end)(struct mod* v);
|
||||
int (*mod_set_param)(struct mod *v, const char *name, const char *value);
|
||||
int (*mod_session_change)(struct mod* v, int, int);
|
||||
int (*mod_get_wait_objs)(struct mod* v, tbus* read_objs, int* rcount,
|
||||
tbus* write_objs, int* wcount, int* timeout);
|
||||
int (*mod_check_wait_objs)(struct mod* v);
|
||||
tintptr mod_dumby[100 - 9]; /* align, 100 minus the number of mod
|
||||
int size; /* size of this struct */
|
||||
int version; /* internal version */
|
||||
/* client functions */
|
||||
int (*mod_start)(struct mod *v, int w, int h, int bpp);
|
||||
int (*mod_connect)(struct mod *v);
|
||||
int (*mod_event)(struct mod *v, int msg, long param1, long param2,
|
||||
long param3, long param4);
|
||||
int (*mod_signal)(struct mod *v);
|
||||
int (*mod_end)(struct mod *v);
|
||||
int (*mod_set_param)(struct mod *v, const char *name, const char *value);
|
||||
int (*mod_session_change)(struct mod *v, int, int);
|
||||
int (*mod_get_wait_objs)(struct mod *v, tbus *read_objs, int *rcount,
|
||||
tbus *write_objs, int *wcount, int *timeout);
|
||||
int (*mod_check_wait_objs)(struct mod *v);
|
||||
tintptr mod_dumby[100 - 9]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
/* server functions */
|
||||
int (*server_begin_update)(struct mod* v);
|
||||
int (*server_end_update)(struct mod* v);
|
||||
int (*server_fill_rect)(struct mod* v, int x, int y, int cx, int cy);
|
||||
int (*server_screen_blt)(struct mod* v, int x, int y, int cx, int cy,
|
||||
int srcx, int srcy);
|
||||
int (*server_paint_rect)(struct mod* v, int x, int y, int cx, int cy,
|
||||
char* data, int width, int height, int srcx, int srcy);
|
||||
int (*server_set_cursor)(struct mod* v, int x, int y, char* data, char* mask);
|
||||
int (*server_palette)(struct mod* v, int* palette);
|
||||
int (*server_msg)(struct mod* v, const char* msg, int code);
|
||||
int (*server_is_term)(struct mod* v);
|
||||
int (*server_set_clip)(struct mod* v, int x, int y, int cx, int cy);
|
||||
int (*server_reset_clip)(struct mod* v);
|
||||
int (*server_set_fgcolor)(struct mod* v, int fgcolor);
|
||||
int (*server_set_bgcolor)(struct mod* v, int bgcolor);
|
||||
int (*server_set_opcode)(struct mod* v, int opcode);
|
||||
int (*server_set_mixmode)(struct mod* v, int mixmode);
|
||||
int (*server_set_brush)(struct mod* v, int x_origin, int y_origin,
|
||||
int style, char* pattern);
|
||||
int (*server_set_pen)(struct mod* v, int style,
|
||||
int width);
|
||||
int (*server_draw_line)(struct mod* v, int x1, int y1, int x2, int y2);
|
||||
int (*server_add_char)(struct mod* v, int font, int character,
|
||||
int offset, int baseline,
|
||||
int width, int height, char* data);
|
||||
int (*server_draw_text)(struct mod* v, int font,
|
||||
int flags, int mixmode, int clip_left, int clip_top,
|
||||
int clip_right, int clip_bottom,
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char* data, int data_len);
|
||||
int (*server_reset)(struct mod* v, int width, int height, int bpp);
|
||||
int (*server_query_channel)(struct mod* v, int index,
|
||||
char* channel_name,
|
||||
int* channel_flags);
|
||||
int (*server_get_channel_id)(struct mod* v, const char *name);
|
||||
int (*server_send_to_channel)(struct mod* v, int channel_id,
|
||||
char* data, int data_len,
|
||||
int total_data_len, int flags);
|
||||
int (*server_bell_trigger)(struct mod* v);
|
||||
tintptr server_dumby[100 - 25]; /* align, 100 minus the number of server
|
||||
/* server functions */
|
||||
int (*server_begin_update)(struct mod *v);
|
||||
int (*server_end_update)(struct mod *v);
|
||||
int (*server_fill_rect)(struct mod *v, int x, int y, int cx, int cy);
|
||||
int (*server_screen_blt)(struct mod *v, int x, int y, int cx, int cy,
|
||||
int srcx, int srcy);
|
||||
int (*server_paint_rect)(struct mod *v, int x, int y, int cx, int cy,
|
||||
char *data, int width, int height, int srcx, int srcy);
|
||||
int (*server_set_cursor)(struct mod *v, int x, int y, char *data, char *mask);
|
||||
int (*server_palette)(struct mod *v, int *palette);
|
||||
int (*server_msg)(struct mod *v, const char *msg, int code);
|
||||
int (*server_is_term)(struct mod *v);
|
||||
int (*server_set_clip)(struct mod *v, int x, int y, int cx, int cy);
|
||||
int (*server_reset_clip)(struct mod *v);
|
||||
int (*server_set_fgcolor)(struct mod *v, int fgcolor);
|
||||
int (*server_set_bgcolor)(struct mod *v, int bgcolor);
|
||||
int (*server_set_opcode)(struct mod *v, int opcode);
|
||||
int (*server_set_mixmode)(struct mod *v, int mixmode);
|
||||
int (*server_set_brush)(struct mod *v, int x_origin, int y_origin,
|
||||
int style, char *pattern);
|
||||
int (*server_set_pen)(struct mod *v, int style,
|
||||
int width);
|
||||
int (*server_draw_line)(struct mod *v, int x1, int y1, int x2, int y2);
|
||||
int (*server_add_char)(struct mod *v, int font, int character,
|
||||
int offset, int baseline,
|
||||
int width, int height, char *data);
|
||||
int (*server_draw_text)(struct mod *v, int font,
|
||||
int flags, int mixmode, int clip_left, int clip_top,
|
||||
int clip_right, int clip_bottom,
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char *data, int data_len);
|
||||
int (*server_reset)(struct mod *v, int width, int height, int bpp);
|
||||
int (*server_query_channel)(struct mod *v, int index,
|
||||
char *channel_name,
|
||||
int *channel_flags);
|
||||
int (*server_get_channel_id)(struct mod *v, const char *name);
|
||||
int (*server_send_to_channel)(struct mod *v, int channel_id,
|
||||
char *data, int data_len,
|
||||
int total_data_len, int flags);
|
||||
int (*server_bell_trigger)(struct mod *v);
|
||||
tintptr server_dumby[100 - 25]; /* align, 100 minus the number of server
|
||||
functions above */
|
||||
/* common */
|
||||
tintptr handle; /* pointer to self as long */
|
||||
tintptr wm;
|
||||
tintptr painter;
|
||||
struct source_info *si;
|
||||
/* mod data */
|
||||
int sck;
|
||||
int width;
|
||||
int height;
|
||||
int bpp;
|
||||
/* common */
|
||||
tintptr handle; /* pointer to self as long */
|
||||
tintptr wm;
|
||||
tintptr painter;
|
||||
struct source_info *si;
|
||||
/* mod data */
|
||||
int sck;
|
||||
int width;
|
||||
int height;
|
||||
int bpp;
|
||||
};
|
||||
|
||||
@ -239,8 +239,8 @@ convert_bitmap(int in_bpp, int out_bpp, char *bmpdata,
|
||||
return out;
|
||||
}
|
||||
|
||||
g_writeln("convert_bitmap: error unknown conversion from %d to %d",
|
||||
in_bpp, out_bpp);
|
||||
LOG(LOG_LEVEL_WARNING, "convert_bitmap: error unknown conversion from %d to %d",
|
||||
in_bpp, out_bpp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -341,7 +341,7 @@ convert_color(int in_bpp, int out_bpp, int in_color, int *palette)
|
||||
return in_color;
|
||||
}
|
||||
|
||||
g_writeln("convert_color: error unknown conversion from %d to %d",
|
||||
in_bpp, out_bpp);
|
||||
LOG(LOG_LEVEL_WARNING, "convert_color: error unknown conversion from %d to %d",
|
||||
in_bpp, out_bpp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -79,11 +79,16 @@ struct mod
|
||||
int (*mod_get_wait_objs)(struct mod *v, tbus *read_objs, int *rcount,
|
||||
tbus *write_objs, int *wcount, int *timeout);
|
||||
int (*mod_check_wait_objs)(struct mod *v);
|
||||
int (*mod_frame_ack)(struct mod* mod, int flags, int frame_id);
|
||||
int (*mod_suppress_output)(struct mod* mod, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
int (*mod_frame_ack)(struct mod *mod, int flags, int frame_id);
|
||||
int (*mod_suppress_output)(struct mod *mod, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
int (*mod_server_monitor_resize)(struct mod *mod,
|
||||
int width, int height);
|
||||
int (*mod_server_monitor_full_invalidate)(struct mod *mod,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct mod *mod);
|
||||
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
|
||||
functions above */
|
||||
/* server functions */
|
||||
int (*server_begin_update)(struct mod *v);
|
||||
int (*server_end_update)(struct mod *v);
|
||||
@ -157,27 +162,27 @@ struct mod
|
||||
int flags);
|
||||
int (*server_set_pointer_ex)(struct mod *mod, int x, int y, char *data,
|
||||
char *mask, int bpp);
|
||||
int (*server_add_char_alpha)(struct mod* mod, int font, int character,
|
||||
int (*server_add_char_alpha)(struct mod *mod, int font, int character,
|
||||
int offset, int baseline,
|
||||
int width, int height, char* data);
|
||||
int (*server_create_os_surface_bpp)(struct mod* v, int rdpindex,
|
||||
int width, int height, char *data);
|
||||
int (*server_create_os_surface_bpp)(struct mod *v, int rdpindex,
|
||||
int width, int height, int bpp);
|
||||
int (*server_paint_rect_bpp)(struct mod* v, int x, int y, int cx, int cy,
|
||||
char* data, int width, int height,
|
||||
int (*server_paint_rect_bpp)(struct mod *v, int x, int y, int cx, int cy,
|
||||
char *data, int width, int height,
|
||||
int srcx, int srcy, int bpp);
|
||||
int (*server_composite)(struct mod* v, int srcidx, int srcformat,
|
||||
int srcwidth, int srcrepeat, int* srctransform,
|
||||
int (*server_composite)(struct mod *v, int srcidx, int srcformat,
|
||||
int srcwidth, int srcrepeat, int *srctransform,
|
||||
int mskflags, int mskidx, int mskformat,
|
||||
int mskwidth, int mskrepeat, int op,
|
||||
int srcx, int srcy, int mskx, int msky,
|
||||
int dstx, int dsty, int width, int height,
|
||||
int dstformat);
|
||||
int (*server_paint_rects)(struct mod* v,
|
||||
int (*server_paint_rects)(struct mod *v,
|
||||
int num_drects, short *drects,
|
||||
int num_crects, short *crects,
|
||||
char *data, int width, int height,
|
||||
int flags, int frame_id);
|
||||
int (*server_session_info)(struct mod* v, const char *data,
|
||||
int (*server_session_info)(struct mod *v, const char *data,
|
||||
int data_bytes);
|
||||
tintptr server_dumby[100 - 44]; /* align, 100 minus the number of server
|
||||
functions above */
|
||||
|
||||
@ -129,6 +129,12 @@ fi
|
||||
make_args="FILESDIR=$FILESDIR PREFIX=$FILESDIR CFGDIR=$FILESDIR"
|
||||
;;
|
||||
*) make_args="FILESDIR=$FILESDIR PREFIX=$FILESDIR USE_Z3=yes"
|
||||
# Check that the Z3 development files appear to be installed
|
||||
# before trying to create z3_version.h. Otherwise we may
|
||||
# mislead the user as to what needs to be done.
|
||||
if [ ! -f /usr/include/z3.h ]; then
|
||||
echo "** libz3-dev (or equivalent) does not appear to be installed" >&2
|
||||
fi
|
||||
if [ ! -f /usr/include/z3_version.h ]; then
|
||||
create_z3_version_h
|
||||
fi
|
||||
|
||||
@ -1,21 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -eufx
|
||||
|
||||
FEATURE_SET="$1"
|
||||
ARCH="$2"
|
||||
shift
|
||||
shift
|
||||
FEATURE_SET=min
|
||||
ARCH=amd64
|
||||
|
||||
if [ $# -ge 1 ]; then
|
||||
FEATURE_SET="$1"
|
||||
shift
|
||||
fi
|
||||
if [ $# -ge 1 ]; then
|
||||
ARCH="$1"
|
||||
shift
|
||||
fi
|
||||
APT_EXTRA_ARGS="$@"
|
||||
|
||||
if [ -z "$FEATURE_SET" ]; then
|
||||
FEATURE_SET=min
|
||||
fi
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
ARCH=amd64
|
||||
fi
|
||||
|
||||
|
||||
# common build tools for all architectures and feature sets
|
||||
PACKAGES=" \
|
||||
autoconf \
|
||||
@ -26,7 +24,8 @@ PACKAGES=" \
|
||||
libtool \
|
||||
make \
|
||||
nasm \
|
||||
pkg-config\
|
||||
pkg-config \
|
||||
check \
|
||||
"
|
||||
|
||||
case "$ARCH"
|
||||
@ -77,7 +76,6 @@ in
|
||||
libxfixes-dev:i386 \
|
||||
libxrandr-dev:i386 \
|
||||
libxrender-dev:i386 \
|
||||
openssl:i386 \
|
||||
libfuse-dev:i386"
|
||||
|
||||
dpkg --add-architecture i386
|
||||
|
||||
@ -15,10 +15,6 @@ if XRDP_DEBUG
|
||||
AM_CPPFLAGS += -DXRDP_DEBUG
|
||||
endif
|
||||
|
||||
if SESMAN_NOPAM
|
||||
AUTH_C = verify_user.c
|
||||
AUTH_LIB = -lcrypt
|
||||
else
|
||||
if SESMAN_BSD
|
||||
AUTH_C = verify_user_bsd.c
|
||||
AUTH_LIB =
|
||||
@ -31,6 +27,10 @@ if SESMAN_KERBEROS
|
||||
AUTH_C = verify_user_kerberos.c
|
||||
AUTH_LIB = -lkrb5
|
||||
else
|
||||
if SESMAN_NOPAM
|
||||
AUTH_C = verify_user.c
|
||||
AUTH_LIB = -lcrypt
|
||||
else
|
||||
AUTH_C = verify_user_pam.c
|
||||
AUTH_LIB = -lpam
|
||||
endif
|
||||
|
||||
@ -18,7 +18,7 @@ endif
|
||||
CHANSRV_EXTRA_LIBS =
|
||||
|
||||
if XRDP_FUSE
|
||||
AM_CPPFLAGS += -DXRDP_FUSE $(FUSE_CFLAGS)
|
||||
AM_CPPFLAGS += -DXRDP_FUSE $(FUSE_CFLAGS) -DFUSE_USE_VERSION=26
|
||||
CHANSRV_EXTRA_LIBS += $(FUSE_LIBS)
|
||||
endif
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ static tbus g_thread_done_event = 0;
|
||||
|
||||
struct config_chansrv *g_cfg = NULL;
|
||||
|
||||
int g_display_num = 0;
|
||||
int g_display_num = -1;
|
||||
int g_cliprdr_chan_id = -1; /* cliprdr */
|
||||
int g_rdpsnd_chan_id = -1; /* rdpsnd */
|
||||
int g_rdpdr_chan_id = -1; /* rdpdr */
|
||||
@ -1557,65 +1557,6 @@ x_server_fatal_handler(void)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
get_display_num_from_display(char *display_text)
|
||||
{
|
||||
int index;
|
||||
int mode;
|
||||
int host_index;
|
||||
int disp_index;
|
||||
int scre_index;
|
||||
char host[256];
|
||||
char disp[256];
|
||||
char scre[256];
|
||||
|
||||
g_memset(host, 0, 256);
|
||||
g_memset(disp, 0, 256);
|
||||
g_memset(scre, 0, 256);
|
||||
|
||||
index = 0;
|
||||
host_index = 0;
|
||||
disp_index = 0;
|
||||
scre_index = 0;
|
||||
mode = 0;
|
||||
|
||||
while (display_text[index] != 0)
|
||||
{
|
||||
if (display_text[index] == ':')
|
||||
{
|
||||
mode = 1;
|
||||
}
|
||||
else if (display_text[index] == '.')
|
||||
{
|
||||
mode = 2;
|
||||
}
|
||||
else if (mode == 0)
|
||||
{
|
||||
host[host_index] = display_text[index];
|
||||
host_index++;
|
||||
}
|
||||
else if (mode == 1)
|
||||
{
|
||||
disp[disp_index] = display_text[index];
|
||||
disp_index++;
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
scre[scre_index] = display_text[index];
|
||||
scre_index++;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
host[host_index] = 0;
|
||||
disp[disp_index] = 0;
|
||||
scre[scre_index] = 0;
|
||||
g_display_num = g_atoi(disp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
main_cleanup(void)
|
||||
@ -1728,7 +1669,7 @@ main(int argc, char **argv)
|
||||
char text[256];
|
||||
const char *config_path;
|
||||
char log_path[256];
|
||||
char *display_text;
|
||||
const char *display_text;
|
||||
char log_file[256];
|
||||
enum logReturns error;
|
||||
struct log_config *logconfig;
|
||||
@ -1743,6 +1684,21 @@ main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
display_text = g_getenv("DISPLAY");
|
||||
if (display_text == NULL)
|
||||
{
|
||||
g_writeln("DISPLAY is not set");
|
||||
main_cleanup();
|
||||
return 1;
|
||||
}
|
||||
g_display_num = g_get_display_num_from_display(display_text);
|
||||
if (g_display_num < 0)
|
||||
{
|
||||
g_writeln("Unable to get display from DISPLAY='%s'", display_text);
|
||||
main_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The user is unable at present to override the sysadmin-provided
|
||||
* sesman.ini location */
|
||||
@ -1755,11 +1711,6 @@ main(int argc, char **argv)
|
||||
config_dump(g_cfg);
|
||||
|
||||
pid = g_getpid();
|
||||
display_text = g_getenv("DISPLAY");
|
||||
if (display_text != NULL)
|
||||
{
|
||||
get_display_num_from_display(display_text);
|
||||
}
|
||||
|
||||
/* starting logging subsystem */
|
||||
g_snprintf(log_file, 255, "%s/xrdp-chansrv.%d.log", log_path, g_display_num);
|
||||
@ -1813,13 +1764,6 @@ main(int argc, char **argv)
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text);
|
||||
|
||||
if (g_display_num == 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, display is zero");
|
||||
main_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num);
|
||||
g_snprintf(text, 255, "xrdp_chansrv_%8.8x_main_term", pid);
|
||||
g_term_event = g_create_wait_obj(text);
|
||||
|
||||
@ -130,7 +130,12 @@ void xfuse_devredir_cb_file_close(struct state_close *fip)
|
||||
** **
|
||||
******************************************************************************/
|
||||
|
||||
#define FUSE_USE_VERSION 26
|
||||
/* FUSE_USE_VERSION must be defined globally for other parts of
|
||||
* xrdp-chansrv which include <fuse_lowlevel.h> for definitions. Check
|
||||
* it's actually defined here */
|
||||
#ifndef FUSE_USE_VERSION
|
||||
#error Define FUSE_USE_VERSION in the make system and recompile
|
||||
#endif
|
||||
|
||||
#include <fuse_lowlevel.h>
|
||||
#include <stdio.h>
|
||||
@ -789,7 +794,7 @@ xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex)
|
||||
if (g_xfs == NULL)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"xfuse_add_clip_dir_item() called with no filesystem")
|
||||
"xfuse_add_clip_dir_item() called with no filesystem");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -273,7 +273,11 @@ xfs_create_xfs_fs(mode_t umask, uid_t uid, gid_t gid)
|
||||
xfs->free_list = NULL;
|
||||
xfs->generation = 1;
|
||||
|
||||
/* xfs->inode_table check should be superfluous here, but it
|
||||
* prevents cppcheck 2.2/2.3 generating a false positive nullPointer
|
||||
* report */
|
||||
if (!grow_xfs(xfs, INODE_TABLE_ALLOCATION_INITIAL) ||
|
||||
xfs->inode_table == NULL ||
|
||||
(xino1 = g_new0(XFS_INODE_ALL, 1)) == NULL ||
|
||||
(xino2 = g_new0(XFS_INODE_ALL, 1)) == NULL)
|
||||
{
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "string_calls.h"
|
||||
|
||||
#define PCSC_API
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
@ -153,66 +155,6 @@ lhexdump(void *p, int len)
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
get_display_num_from_display(const char *display_text)
|
||||
{
|
||||
int rv;
|
||||
int index;
|
||||
int mode;
|
||||
int host_index;
|
||||
int disp_index;
|
||||
int scre_index;
|
||||
char host[256];
|
||||
char disp[256];
|
||||
char scre[256];
|
||||
|
||||
memset(host, 0, 256);
|
||||
memset(disp, 0, 256);
|
||||
memset(scre, 0, 256);
|
||||
|
||||
index = 0;
|
||||
host_index = 0;
|
||||
disp_index = 0;
|
||||
scre_index = 0;
|
||||
mode = 0;
|
||||
|
||||
while (display_text[index] != 0)
|
||||
{
|
||||
if (display_text[index] == ':')
|
||||
{
|
||||
mode = 1;
|
||||
}
|
||||
else if (display_text[index] == '.')
|
||||
{
|
||||
mode = 2;
|
||||
}
|
||||
else if (mode == 0)
|
||||
{
|
||||
host[host_index] = display_text[index];
|
||||
host_index++;
|
||||
}
|
||||
else if (mode == 1)
|
||||
{
|
||||
disp[disp_index] = display_text[index];
|
||||
disp_index++;
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
scre[scre_index] = display_text[index];
|
||||
scre_index++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
host[host_index] = 0;
|
||||
disp[disp_index] = 0;
|
||||
scre[scre_index] = 0;
|
||||
LLOGLN(10, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]",
|
||||
host, disp, scre));
|
||||
rv = atoi(disp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
connect_to_chansrv(void)
|
||||
@ -252,11 +194,11 @@ connect_to_chansrv(void)
|
||||
LLOGLN(0, ("connect_to_chansrv: error, home not set"));
|
||||
return 1;
|
||||
}
|
||||
dis = get_display_num_from_display(xrdp_display);
|
||||
if (dis < 10)
|
||||
dis = g_get_display_num_from_display(xrdp_display);
|
||||
if (dis < 0)
|
||||
{
|
||||
/* DISPLAY must be > 9 */
|
||||
LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis));
|
||||
LLOGLN(0, ("connect_to_chansrv: error, don't understand DISPLAY='%s'",
|
||||
xrdp_display));
|
||||
return 1;
|
||||
}
|
||||
g_sck = socket(PF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
@ -41,6 +41,7 @@ struct sesman_startup_params
|
||||
int no_daemon;
|
||||
int help;
|
||||
int version;
|
||||
int dump_config;
|
||||
};
|
||||
|
||||
int g_sck;
|
||||
@ -127,6 +128,10 @@ sesman_process_params(int argc, char **argv,
|
||||
{
|
||||
startup_params->version = 1;
|
||||
}
|
||||
else if (nocase_matches(option, "--dump-config", NULL))
|
||||
{
|
||||
startup_params->dump_config = 1;
|
||||
}
|
||||
else if (nocase_matches(option, "-c", "--config", NULL))
|
||||
{
|
||||
index++;
|
||||
@ -305,11 +310,12 @@ static void
|
||||
print_help(void)
|
||||
{
|
||||
g_printf("Usage: xrdp-sesman [options]\n");
|
||||
g_printf(" -k, --kill shut down xrdp-sesman\n");
|
||||
g_printf(" -h, --help show help\n");
|
||||
g_printf(" -v, --version show version\n");
|
||||
g_printf(" -n, --nodaemon don't fork into background\n");
|
||||
g_printf(" -c, --config specify new path to sesman.ini\n");
|
||||
g_printf(" -k, --kill shut down xrdp-sesman\n");
|
||||
g_printf(" -h, --help show help\n");
|
||||
g_printf(" -v, --version show version\n");
|
||||
g_printf(" -n, --nodaemon don't fork into background\n");
|
||||
g_printf(" -c, --config specify new path to sesman.ini\n");
|
||||
g_writeln(" --dump-config display config on stdout on startup");
|
||||
g_deinit();
|
||||
}
|
||||
|
||||
@ -415,12 +421,6 @@ main(int argc, char **argv)
|
||||
g_exit(kill_running_sesman(pid_file));
|
||||
}
|
||||
|
||||
daemon = !startup_params.no_daemon;
|
||||
if (!daemon)
|
||||
{
|
||||
g_printf("starting sesman in foreground...\n");
|
||||
}
|
||||
|
||||
if (g_file_exist(pid_file))
|
||||
{
|
||||
g_printf("xrdp-sesman is already running.\n");
|
||||
@ -440,15 +440,14 @@ main(int argc, char **argv)
|
||||
g_exit(1);
|
||||
}
|
||||
|
||||
/* not to spit on the console, show config summary only when running
|
||||
* in foreground */
|
||||
if (!daemon)
|
||||
if (startup_params.dump_config)
|
||||
{
|
||||
config_dump(g_cfg);
|
||||
}
|
||||
|
||||
/* starting logging subsystem */
|
||||
log_error = log_start(startup_params.sesman_ini, "xrdp-sesman");
|
||||
log_error = log_start(startup_params.sesman_ini, "xrdp-sesman",
|
||||
startup_params.dump_config);
|
||||
|
||||
if (log_error != LOG_STARTUP_OK)
|
||||
{
|
||||
@ -481,6 +480,7 @@ main(int argc, char **argv)
|
||||
LOG(LOG_LEVEL_TRACE, " reconnect_sh = %s", g_cfg->reconnect_sh);
|
||||
LOG(LOG_LEVEL_TRACE, " auth_file_path = %s", g_cfg->auth_file_path);
|
||||
|
||||
daemon = !startup_params.no_daemon;
|
||||
if (daemon)
|
||||
{
|
||||
/* not to spit on the console, shut up stdout/stderr before anything's logged */
|
||||
|
||||
336
sesman/session.c
336
sesman/session.c
@ -116,23 +116,19 @@ session_get_bydata(const char *name, int width, int height, int bpp, int type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s",
|
||||
policy, name, width, height, bpp, type, client_ip);
|
||||
#endif
|
||||
|
||||
while (tmp != 0)
|
||||
{
|
||||
#if 0
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s",
|
||||
tmp->item,
|
||||
tmp->item->name,
|
||||
tmp->item->width, tmp->item->height,
|
||||
tmp->item->bpp, tmp->item->type,
|
||||
tmp->item->client_ip);
|
||||
#endif
|
||||
|
||||
if (g_strncmp(name, tmp->item->name, 255) == 0 &&
|
||||
(!(policy & SESMAN_CFG_SESS_POLICY_D) ||
|
||||
@ -173,12 +169,14 @@ x_server_running_check_ports(int display)
|
||||
|
||||
if (!x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
g_sprintf(text, "/tmp/.X%d-lock", display);
|
||||
x_running = g_file_exist(text);
|
||||
}
|
||||
|
||||
if (!x_running) /* check 59xx */
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
if ((sck = g_tcp_socket()) != -1)
|
||||
{
|
||||
g_sprintf(text, "59%2.2d", display);
|
||||
@ -189,6 +187,7 @@ x_server_running_check_ports(int display)
|
||||
|
||||
if (!x_running) /* check 60xx */
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
if ((sck = g_tcp_socket()) != -1)
|
||||
{
|
||||
g_sprintf(text, "60%2.2d", display);
|
||||
@ -199,6 +198,7 @@ x_server_running_check_ports(int display)
|
||||
|
||||
if (!x_running) /* check 62xx */
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
if ((sck = g_tcp_socket()) != -1)
|
||||
{
|
||||
g_sprintf(text, "62%2.2d", display);
|
||||
@ -209,34 +209,44 @@ x_server_running_check_ports(int display)
|
||||
|
||||
if (!x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
g_sprintf(text, XRDP_CHANSRV_STR, display);
|
||||
x_running = g_file_exist(text);
|
||||
}
|
||||
|
||||
if (!x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
g_sprintf(text, CHANSRV_PORT_OUT_STR, display);
|
||||
x_running = g_file_exist(text);
|
||||
}
|
||||
|
||||
if (!x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
g_sprintf(text, CHANSRV_PORT_IN_STR, display);
|
||||
x_running = g_file_exist(text);
|
||||
}
|
||||
|
||||
if (!x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
g_sprintf(text, CHANSRV_API_STR, display);
|
||||
x_running = g_file_exist(text);
|
||||
}
|
||||
|
||||
if (!x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
g_sprintf(text, XRDP_X11RDP_STR, display);
|
||||
x_running = g_file_exist(text);
|
||||
}
|
||||
|
||||
if (x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
|
||||
}
|
||||
|
||||
return x_running;
|
||||
}
|
||||
|
||||
@ -259,10 +269,20 @@ x_server_running(int display)
|
||||
|
||||
if (!x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
g_sprintf(text, "/tmp/.X%d-lock", display);
|
||||
x_running = g_file_exist(text);
|
||||
}
|
||||
|
||||
if (x_running)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
|
||||
}
|
||||
|
||||
return x_running;
|
||||
}
|
||||
|
||||
@ -314,7 +334,9 @@ session_get_avail_display_from_chain(void)
|
||||
display++;
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_ERROR, "X server -- no display in range is available");
|
||||
LOG(LOG_LEVEL_ERROR, "X server -- no display in range (%d to %d) is available",
|
||||
g_cfg->sess.x11_display_offset,
|
||||
g_cfg->sess.x11_display_offset + g_cfg->sess.max_sessions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -328,14 +350,16 @@ wait_for_xserver(int display)
|
||||
/* wait up to 10 secs for x server to start */
|
||||
i = 0;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
|
||||
|
||||
while (!x_server_running(display))
|
||||
{
|
||||
i++;
|
||||
|
||||
if (i > 40)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"X server for display %d startup timeout",
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Timed out waiting for X server on display %d to startup",
|
||||
display);
|
||||
break;
|
||||
}
|
||||
@ -357,13 +381,16 @@ session_start_chansrv(char *username, int display)
|
||||
chansrv_pid = g_fork();
|
||||
if (chansrv_pid == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting the xrdp channel server for display %d", display);
|
||||
|
||||
chansrv_params = list_create();
|
||||
chansrv_params->auto_free = 1;
|
||||
|
||||
/* building parameters */
|
||||
g_snprintf(exe_path, sizeof(exe_path), "%s/xrdp-chansrv",
|
||||
XRDP_SBIN_PATH);
|
||||
|
||||
|
||||
list_add_item(chansrv_params, (intptr_t) g_strdup(exe_path));
|
||||
list_add_item(chansrv_params, 0); /* mandatory */
|
||||
|
||||
@ -373,9 +400,8 @@ session_start_chansrv(char *username, int display)
|
||||
|
||||
/* executing chansrv */
|
||||
g_execvp(exe_path, (char **) (chansrv_params->items));
|
||||
|
||||
/* should not get here */
|
||||
LOG(LOG_LEVEL_ALWAYS, "error starting chansrv "
|
||||
"- user %s - pid %d", username, g_getpid());
|
||||
list_delete(chansrv_params);
|
||||
g_exit(1);
|
||||
}
|
||||
@ -390,13 +416,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
{
|
||||
int display = 0;
|
||||
int pid = 0;
|
||||
int i = 0;
|
||||
char geometry[32];
|
||||
char depth[32];
|
||||
char screen[32]; /* display number */
|
||||
char text[256];
|
||||
char execvpparams[2048];
|
||||
char *xserver; /* absolute/relative path to Xorg/X11rdp/Xvnc */
|
||||
char *xserver = NULL; /* absolute/relative path to Xorg/X11rdp/Xvnc */
|
||||
char *passwd_file;
|
||||
char **pp1 = (char **)NULL;
|
||||
struct session_chain *temp = (struct session_chain *)NULL;
|
||||
@ -421,7 +446,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
/* check to limit concurrent sessions */
|
||||
if (g_session_count >= g_cfg->sess.max_sessions)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "max concurrent session limit "
|
||||
LOG(LOG_LEVEL_ERROR, "max concurrent session limit "
|
||||
"exceeded. login for user %s denied", s->username);
|
||||
return 0;
|
||||
}
|
||||
@ -430,8 +455,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
|
||||
if (temp == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "cannot create new chain "
|
||||
"element - user %s", s->username);
|
||||
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
|
||||
"chain element - user %s", s->username);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -440,7 +465,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
if (temp->item == 0)
|
||||
{
|
||||
g_free(temp);
|
||||
LOG(LOG_LEVEL_ERROR, "cannot create new session "
|
||||
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
|
||||
"item - user %s", s->username);
|
||||
return 0;
|
||||
}
|
||||
@ -459,11 +484,16 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"[session start] (display %d): Failed to fork for scp with "
|
||||
"errno: %d, description: %s",
|
||||
display, g_get_errno(), g_get_strerror());
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "calling auth_start_session from pid %d",
|
||||
g_getpid());
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"[session start] (display %d): calling auth_start_session from pid %d",
|
||||
display, g_getpid());
|
||||
auth_start_session(data, display);
|
||||
g_delete_wait_obj(g_term_event);
|
||||
g_tcp_close(g_sck);
|
||||
@ -494,15 +524,16 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
*/
|
||||
if (g_setsid() < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"setsid failed - pid %d", g_getpid());
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"[session start] (display %d): setsid failed - pid %d",
|
||||
display, g_getpid());
|
||||
}
|
||||
|
||||
if (g_setlogin(s->username) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"setlogin failed for user %s - pid %d", s->username,
|
||||
g_getpid());
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"[session start] (display %d): setlogin failed for user %s - pid %d",
|
||||
display, s->username, g_getpid());
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,6 +552,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
child forks wm, and waits, todo */
|
||||
if (window_manager_pid == -1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Failed to fork for the window manager on display %d", display);
|
||||
}
|
||||
else if (window_manager_pid == 0)
|
||||
{
|
||||
@ -540,79 +573,74 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
g_set_current_dir(s->directory);
|
||||
}
|
||||
}
|
||||
if (s->program != 0)
|
||||
if (s->program != 0 && s->program[0] != 0)
|
||||
{
|
||||
if (s->program[0] != 0)
|
||||
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"starting program with parameters: %s ",
|
||||
s->program);
|
||||
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
|
||||
{
|
||||
const char *params[] = {"sh", "-c", s->program, NULL};
|
||||
g_execvp("/bin/sh", (char **)params);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_execlp3(s->program, s->program, 0);
|
||||
}
|
||||
LOG(LOG_LEVEL_ALWAYS,
|
||||
"error starting program %s for user %s - pid %d",
|
||||
s->program, s->username, g_getpid());
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting user requested window manager on "
|
||||
"display %d with embeded arguments using a shell: %s",
|
||||
display, s->program);
|
||||
const char *params[] = {"sh", "-c", s->program, NULL};
|
||||
g_execvp("/bin/sh", (char **)params);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting user requested window manager on "
|
||||
"display %d: %s", display, s->program);
|
||||
g_execlp3(s->program, s->program, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "The user session on display %d did "
|
||||
"not request a specific window manager", display);
|
||||
}
|
||||
|
||||
/* try to execute user window manager if enabled */
|
||||
if (g_cfg->enable_user_wm)
|
||||
{
|
||||
g_sprintf(text, "%s/%s", g_getenv("HOME"), g_cfg->user_wm);
|
||||
if (g_file_exist(text))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting window manager on display %d"
|
||||
"from user home directory: %s", display, text);
|
||||
g_execlp3(text, g_cfg->user_wm, 0);
|
||||
LOG(LOG_LEVEL_ALWAYS, "error starting user "
|
||||
"wm for user %s - pid %d", s->username, g_getpid());
|
||||
/* logging parameters */
|
||||
LOG(LOG_LEVEL_DEBUG, "errno: %d, "
|
||||
"description: %s", g_get_errno(), g_get_strerror());
|
||||
LOG(LOG_LEVEL_DEBUG, "execlp3 parameter "
|
||||
"list:");
|
||||
LOG(LOG_LEVEL_DEBUG, " argv[0] = %s",
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"The user home directory window manager configuration "
|
||||
"is enabled but window manager program does not exist: %s",
|
||||
text);
|
||||
LOG(LOG_LEVEL_DEBUG, " argv[1] = %s",
|
||||
g_cfg->user_wm);
|
||||
}
|
||||
}
|
||||
/* if we're here something happened to g_execlp3
|
||||
so we try running the default window manager */
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting the default window manager on display %d: %s",
|
||||
display, g_cfg->default_wm);
|
||||
g_execlp3(g_cfg->default_wm, g_cfg->default_wm, 0);
|
||||
|
||||
LOG(LOG_LEVEL_ALWAYS, "error starting default "
|
||||
"wm for user %s - pid %d", s->username, g_getpid());
|
||||
/* logging parameters */
|
||||
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
|
||||
"%s", g_get_errno(), g_get_strerror());
|
||||
LOG(LOG_LEVEL_DEBUG, "execlp3 parameter list:");
|
||||
LOG(LOG_LEVEL_DEBUG, " argv[0] = %s",
|
||||
g_cfg->default_wm);
|
||||
LOG(LOG_LEVEL_DEBUG, " argv[1] = %s",
|
||||
g_cfg->default_wm);
|
||||
|
||||
/* still a problem starting window manager just start xterm */
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"No window manager on display %d started, "
|
||||
"so falling back to starting xterm for user debugging",
|
||||
display);
|
||||
g_execlp3("xterm", "xterm", 0);
|
||||
|
||||
/* should not get here */
|
||||
LOG(LOG_LEVEL_ALWAYS, "error starting xterm "
|
||||
"for user %s - pid %d", s->username, g_getpid());
|
||||
/* logging parameters */
|
||||
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
|
||||
"%s", g_get_errno(), g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "another Xserver might "
|
||||
"already be active on display %d - see log", display);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"There is no X server active on display %d", display);
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "aborting connection...");
|
||||
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
|
||||
"the window manager on display %d, aborting connection",
|
||||
display);
|
||||
g_exit(0);
|
||||
}
|
||||
else
|
||||
@ -621,6 +649,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
child becomes X */
|
||||
if (display_pid == -1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Failed to fork for the X server on display %d", display);
|
||||
}
|
||||
else if (display_pid == 0) /* child */
|
||||
{
|
||||
@ -641,7 +671,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
g_cfg->env_values);
|
||||
}
|
||||
|
||||
|
||||
/* setting Xserver environment variables */
|
||||
g_snprintf(text, 255, "%d", g_cfg->sess.max_idle_time);
|
||||
g_setenv("XRDP_SESMAN_MAX_IDLE_TIME", text, 1);
|
||||
g_snprintf(text, 255, "%d", g_cfg->sess.max_disc_time);
|
||||
@ -663,6 +693,13 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
/* Add the entry in XAUTHORITY file or exit if error */
|
||||
if (add_xauth_cookie(display, authfile) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error setting the xauth cookie for display %d in file %s",
|
||||
display, authfile);
|
||||
|
||||
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
|
||||
"the X server on display %d, aborting connection",
|
||||
display);
|
||||
g_exit(1);
|
||||
}
|
||||
|
||||
@ -678,8 +715,9 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Failed to disable setuid on X server: %s",
|
||||
g_get_strerror());
|
||||
"[session start] (display %d): Failed to disable "
|
||||
"setuid on X server: %s",
|
||||
display, g_get_strerror());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -703,17 +741,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
|
||||
pp1 = (char **) xserver_params->items;
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
|
||||
|
||||
/* some args are passed via env vars */
|
||||
g_sprintf(geometry, "%d", s->width);
|
||||
g_setenv("XRDP_START_WIDTH", geometry, 1);
|
||||
|
||||
g_sprintf(geometry, "%d", s->height);
|
||||
g_setenv("XRDP_START_HEIGHT", geometry, 1);
|
||||
|
||||
/* fire up Xorg */
|
||||
g_execvp(xserver, pp1);
|
||||
}
|
||||
else if (type == SESMAN_SESSION_TYPE_XVNC)
|
||||
{
|
||||
@ -748,8 +781,6 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
/* make sure it ends with a zero */
|
||||
list_add_item(xserver_params, 0);
|
||||
pp1 = (char **)xserver_params->items;
|
||||
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
|
||||
g_execvp(xserver, pp1);
|
||||
}
|
||||
else if (type == SESMAN_SESSION_TYPE_XRDP)
|
||||
{
|
||||
@ -777,72 +808,105 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
/* make sure it ends with a zero */
|
||||
list_add_item(xserver_params, 0);
|
||||
pp1 = (char **)xserver_params->items;
|
||||
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
|
||||
g_execvp(xserver, pp1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ALWAYS, "bad session type - "
|
||||
"user %s - pid %d", s->username, g_getpid());
|
||||
LOG(LOG_LEVEL_ERROR, "Unknown session type: %d", type);
|
||||
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
|
||||
"to start the X server on display %d, aborting connection",
|
||||
display);
|
||||
g_exit(1);
|
||||
}
|
||||
|
||||
/* fire up X server */
|
||||
LOG(LOG_LEVEL_INFO, "Starting X server on display %d: %s",
|
||||
display, dumpItemsToString(xserver_params, execvpparams, 2048));
|
||||
g_execvp(xserver, pp1);
|
||||
|
||||
/* should not get here */
|
||||
LOG(LOG_LEVEL_ALWAYS, "error starting X server "
|
||||
"- user %s - pid %d", s->username, g_getpid());
|
||||
|
||||
/* logging parameters */
|
||||
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
|
||||
"%s", g_get_errno(), g_get_strerror());
|
||||
LOG(LOG_LEVEL_DEBUG, "execve parameter list size: "
|
||||
"%d", (xserver_params)->count);
|
||||
|
||||
for (i = 0; i < (xserver_params->count); i++)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, " argv[%d] = %s",
|
||||
i, (char *)list_get_item(xserver_params, i));
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error starting X server on display %d", display);
|
||||
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
|
||||
"to start the X server on display %d, aborting connection",
|
||||
display);
|
||||
|
||||
list_delete(xserver_params);
|
||||
g_exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int wm_wait_time;
|
||||
struct exit_status wm_exit_status;
|
||||
struct exit_status xserver_exit_status;
|
||||
struct exit_status chansrv_exit_status;
|
||||
|
||||
wait_for_xserver(display);
|
||||
chansrv_pid = session_start_chansrv(s->username, display);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Session started successfully for user %s on display %d",
|
||||
s->username, display);
|
||||
|
||||
/* Monitor the amount of time we wait for the
|
||||
* window manager. This is approximately how long the window
|
||||
* manager was running for */
|
||||
LOG(LOG_LEVEL_INFO, "waiting for window manager "
|
||||
"(pid %d) to exit", window_manager_pid);
|
||||
LOG(LOG_LEVEL_INFO, "Session in progress on display %d, waiting "
|
||||
"until the window manager (pid %d) exits to end the session",
|
||||
display, window_manager_pid);
|
||||
wm_wait_time = g_time1();
|
||||
g_waitpid(window_manager_pid);
|
||||
wm_exit_status = g_waitpid_status(window_manager_pid);
|
||||
wm_wait_time = g_time1() - wm_wait_time;
|
||||
if (wm_exit_status.exit_code > 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
|
||||
"exited with non-zero exit code %d and signal %d. This "
|
||||
"could indicate a window manager config problem",
|
||||
window_manager_pid, display, wm_exit_status.exit_code,
|
||||
wm_exit_status.signal_no);
|
||||
}
|
||||
if (wm_wait_time < 10)
|
||||
{
|
||||
/* This could be a config issue. Log a significant error */
|
||||
LOG(LOG_LEVEL_ALWAYS, "window manager exited quickly "
|
||||
"(%d secs). Window manager config problem?",
|
||||
wm_wait_time);
|
||||
LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
|
||||
"exited quickly (%d secs). This could indicate a window "
|
||||
"manager config problem",
|
||||
window_manager_pid, display, wm_wait_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "window manager (pid %d) was running "
|
||||
"for approximately %d seconds.",
|
||||
window_manager_pid, wm_wait_time);
|
||||
LOG(LOG_LEVEL_DEBUG, "Window manager (pid %d, display %d) "
|
||||
"was running for %d seconds.",
|
||||
window_manager_pid, display, wm_wait_time);
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO, "Cleaning up session. Calling "
|
||||
"auth_stop_session and auth_end from pid %d", g_getpid());
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Calling auth_stop_session and auth_end from pid %d",
|
||||
g_getpid());
|
||||
auth_stop_session(data);
|
||||
auth_end(data);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Terminating X server (pid %d) on display %d",
|
||||
display_pid, display);
|
||||
g_sigterm(display_pid);
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "Terminating the xrdp channel server (pid %d) "
|
||||
"on display %d", chansrv_pid, display);
|
||||
g_sigterm(chansrv_pid);
|
||||
|
||||
/* make sure socket cleanup happen after child process exit */
|
||||
g_waitpid(display_pid);
|
||||
g_waitpid(chansrv_pid);
|
||||
xserver_exit_status = g_waitpid_status(display_pid);
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"X server on display %d (pid %d) returned exit code %d "
|
||||
"and signal number %d",
|
||||
display, display_pid, xserver_exit_status.exit_code,
|
||||
xserver_exit_status.signal_no);
|
||||
|
||||
chansrv_exit_status = g_waitpid_status(chansrv_pid);
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"xrdp channel server for display %d (pid %d) "
|
||||
"exit code %d and signal number %d",
|
||||
display, chansrv_pid, chansrv_exit_status.exit_code,
|
||||
chansrv_exit_status.signal_no);
|
||||
|
||||
cleanup_sockets(display);
|
||||
g_deinit();
|
||||
@ -852,6 +916,10 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Starting session: session_pid %d, "
|
||||
"display :%d.0, width %d, height %d, bpp %d, client ip %s, "
|
||||
"user name %s",
|
||||
pid, display, s->width, s->height, s->bpp, s->client_ip, s->username);
|
||||
temp->item->pid = pid;
|
||||
temp->item->display = display;
|
||||
temp->item->width = s->width;
|
||||
@ -898,6 +966,7 @@ session_reconnect_fork(int display, char *username, long data)
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Failed to fork for session reconnection script");
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
@ -910,9 +979,25 @@ session_reconnect_fork(int display, char *username, long data)
|
||||
|
||||
if (g_file_exist(g_cfg->reconnect_sh))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting session reconnection script on display %d: %s",
|
||||
display, g_cfg->reconnect_sh);
|
||||
g_execlp3(g_cfg->reconnect_sh, g_cfg->reconnect_sh, 0);
|
||||
|
||||
/* should not get here */
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error starting session reconnection script on display %d: %s",
|
||||
display, g_cfg->reconnect_sh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Session reconnection script file does not exist: %s",
|
||||
g_cfg->reconnect_sh);
|
||||
}
|
||||
|
||||
/* TODO: why is this existing with a success error code when the
|
||||
reconnect script failed to be executed? */
|
||||
g_exit(0);
|
||||
}
|
||||
|
||||
@ -972,7 +1057,9 @@ session_kill(int pid)
|
||||
if (tmp->item->pid == pid)
|
||||
{
|
||||
/* deleting the session */
|
||||
LOG(LOG_LEVEL_INFO, "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s", tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip);
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ terminated session: username %s, display :%d.0, session_pid %d, ip %s",
|
||||
tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip);
|
||||
g_free(tmp->item);
|
||||
|
||||
if (prev == 0)
|
||||
@ -1011,8 +1098,7 @@ session_sigkill_all(void)
|
||||
{
|
||||
if (tmp->item == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "found null session "
|
||||
"descriptor!");
|
||||
LOG(LOG_LEVEL_ERROR, "found null session descriptor!");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1045,8 +1131,7 @@ session_get_bypid(int pid)
|
||||
{
|
||||
if (tmp->item == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "session descriptor for "
|
||||
"pid %d is null!", pid);
|
||||
LOG(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!", pid);
|
||||
g_free(dummy);
|
||||
return 0;
|
||||
}
|
||||
@ -1078,15 +1163,14 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
|
||||
|
||||
tmp = g_sessions;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for session by user: %s", user);
|
||||
while (tmp != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "user: %s", user);
|
||||
|
||||
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
|
||||
"result=%d", (tmp->item->status), flags,
|
||||
((tmp->item->status) & flags));
|
||||
LOG(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
|
||||
"result=%d", (tmp->item->status), flags,
|
||||
((tmp->item->status) & flags));
|
||||
|
||||
if ((tmp->item->status) & flags)
|
||||
{
|
||||
@ -1169,7 +1253,7 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
|
||||
int
|
||||
cleanup_sockets(int display)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "cleanup_sockets:");
|
||||
LOG(LOG_LEVEL_INFO, "cleanup_sockets:");
|
||||
char file[256];
|
||||
int error;
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ sig_sesman_reload_cfg(int sig)
|
||||
g_cfg = cfg;
|
||||
|
||||
/* start again logging subsystem */
|
||||
error = log_start(g_cfg->sesman_ini, "xrdp-sesman");
|
||||
error = log_start(g_cfg->sesman_ini, "xrdp-sesman", 0);
|
||||
|
||||
if (error != LOG_STARTUP_OK)
|
||||
{
|
||||
|
||||
@ -38,6 +38,9 @@ xrdp_sesadmin_SOURCES = \
|
||||
xrdp_dis_SOURCES = \
|
||||
dis.c
|
||||
|
||||
xrdp_dis_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la
|
||||
|
||||
xrdp_xcon_SOURCES = \
|
||||
xcon.c
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "xrdp_sockets.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -36,7 +37,6 @@ int main(int argc, char **argv)
|
||||
int dis;
|
||||
struct sockaddr_un sa;
|
||||
size_t len;
|
||||
char *p;
|
||||
char *display;
|
||||
|
||||
if (argc != 1)
|
||||
@ -54,7 +54,12 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
dis = strtol(display + 1, &p, 10);
|
||||
dis = g_get_display_num_from_display(display);
|
||||
if (dis < 0)
|
||||
{
|
||||
printf("Can't parse DISPLAY='%s'\n", display);
|
||||
return 1;
|
||||
}
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sun_family = AF_UNIX;
|
||||
sprintf(sa.sun_path, XRDP_DISCONNECT_STR, dis);
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#endif
|
||||
|
||||
#include "sesman.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
#include "arch.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#include <krb5.h>
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
#include "arch.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#include <security/pam_userpass.h>
|
||||
|
||||
|
||||
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@ -1 +0,0 @@
|
||||
!Makefile
|
||||
7
tests/Makefile.am
Normal file
7
tests/Makefile.am
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
EXTRA_DIST = \
|
||||
readme.txt
|
||||
|
||||
SUBDIRS = \
|
||||
common \
|
||||
memtest
|
||||
26
tests/common/Makefile.am
Normal file
26
tests/common/Makefile.am
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/common
|
||||
|
||||
if XRDP_DEBUG
|
||||
AM_CPPFLAGS += -DXRDP_DEBUG
|
||||
endif
|
||||
|
||||
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
|
||||
$(top_srcdir)/tap-driver.sh
|
||||
|
||||
TESTS = test_common
|
||||
check_PROGRAMS = test_common
|
||||
|
||||
test_common_SOURCES = \
|
||||
test_common.h \
|
||||
test_common_main.c \
|
||||
test_string_calls.c
|
||||
|
||||
test_common_CFLAGS = \
|
||||
@CHECK_CFLAGS@
|
||||
|
||||
test_common_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
@CHECK_LIBS@
|
||||
9
tests/common/test_common.h
Normal file
9
tests/common/test_common.h
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef TEST_COMMON_H
|
||||
#define TEST_COMMON_H
|
||||
|
||||
#include <check.h>
|
||||
|
||||
Suite *make_suite_test_string(void);
|
||||
|
||||
#endif /* TEST_COMMON_H */
|
||||
23
tests/common/test_common_main.c
Normal file
23
tests/common/test_common_main.c
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config_ac.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
#include "test_common.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
int number_failed;
|
||||
SRunner *sr;
|
||||
|
||||
sr = srunner_create (make_suite_test_string());
|
||||
// srunner_add_suite(sr, make_list_suite());
|
||||
|
||||
srunner_set_tap(sr, "-");
|
||||
srunner_run_all (sr, CK_ENV);
|
||||
number_failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
240
tests/common/test_string_calls.c
Normal file
240
tests/common/test_string_calls.c
Normal file
@ -0,0 +1,240 @@
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config_ac.h"
|
||||
#endif
|
||||
|
||||
#include "test_common.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#define RESULT_LEN 1024
|
||||
|
||||
START_TEST(test_strnjoin__when_src_is_null__returns_empty_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char **src = NULL;
|
||||
char result[RESULT_LEN];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, RESULT_LEN, " ", src, 0);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_src_has_null_item__returns_joined_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value, NULL };
|
||||
char result[RESULT_LEN];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, RESULT_LEN, " ", src, 2);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "test_value ");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_src_has_one_item__returns_copied_source_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *expected_value = "test_value";
|
||||
const char *src[] = { expected_value };
|
||||
char result[RESULT_LEN];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, RESULT_LEN, " ", src, 1);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, expected_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_src_has_two_items__returns_joined_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value, test_value };
|
||||
char result[RESULT_LEN];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, RESULT_LEN, " ", src, 2);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "test_value test_value");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_joiner_is_empty_string__returns_joined_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value, test_value };
|
||||
char result[RESULT_LEN];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, RESULT_LEN, "", src, 2);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "test_valuetest_value");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_joiner_is_NULL__returns_joined_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value, test_value };
|
||||
char result[RESULT_LEN];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, RESULT_LEN, NULL, src, 2);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "test_valuetest_value");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_destination_is_NULL__returns_NULL)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value };
|
||||
char *result = NULL;
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, 0, " ", src, 1);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_ptr_eq(result, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_destination_is_shorter_than_src__returns_partial_src_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value };
|
||||
char result[5];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, 5, " ", src, 1);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "test");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_destination_is_shorter_than_src_plus_joiner__returns_partial_joined_string)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value, test_value};
|
||||
char result[16];
|
||||
result[0] = '\0';
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, 16, " joiner ", src, 2);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "test_value join");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_destination_has_contents__returns_joined_string_with_content_overwritten)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *test_value = "test_value";
|
||||
const char *src[] = { test_value, test_value};
|
||||
char result[RESULT_LEN] = "1234567890";
|
||||
|
||||
/* test */
|
||||
|
||||
g_strnjoin(result, RESULT_LEN, " ", src, 2);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_str_eq(result, "test_value test_value");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strnjoin__when_always__then_doesnt_write_beyond_end_of_destination)
|
||||
{
|
||||
/* setup */
|
||||
|
||||
const char *src[] = { "a","b","c"};
|
||||
char result[5+1+1]; /* a-b-c + term null + guard value */
|
||||
|
||||
/* test */
|
||||
|
||||
result[6] = '\x7f';
|
||||
g_strnjoin(result, 5 + 1, "-", src, 3);
|
||||
|
||||
/* verify */
|
||||
|
||||
ck_assert_int_eq(result[6], '\x7f');
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/******************************************************************************/
|
||||
Suite *
|
||||
make_suite_test_string(void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc_strnjoin;
|
||||
|
||||
s = suite_create("String");
|
||||
|
||||
tc_strnjoin = tcase_create("strnjoin");
|
||||
suite_add_tcase(s, tc_strnjoin);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_is_null__returns_empty_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_null_item__returns_joined_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_one_item__returns_copied_source_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_two_items__returns_joined_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_joiner_is_empty_string__returns_joined_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_joiner_is_NULL__returns_joined_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_NULL__returns_NULL);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_shorter_than_src__returns_partial_src_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_shorter_than_src_plus_joiner__returns_partial_joined_string);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_has_contents__returns_joined_string_with_content_overwritten);
|
||||
tcase_add_test(tc_strnjoin, test_strnjoin__when_always__then_doesnt_write_beyond_end_of_destination);
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
|
||||
OBJS = libmem.o memtest.o
|
||||
|
||||
#CFLAGS = -O2 -Wall
|
||||
CFLAGS = -g
|
||||
|
||||
all: memtest
|
||||
|
||||
memtest: $(OBJS)
|
||||
$(CC) -o memtest $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) librdp.a
|
||||
21
tests/memtest/Makefile.am
Normal file
21
tests/memtest/Makefile.am
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/common
|
||||
|
||||
if XRDP_DEBUG
|
||||
AM_CPPFLAGS += -DXRDP_DEBUG
|
||||
endif
|
||||
|
||||
check_PROGRAMS = \
|
||||
memtest
|
||||
|
||||
memtest_SOURCES = \
|
||||
libmem.h \
|
||||
libmem.c \
|
||||
memtest.c
|
||||
|
||||
memtest_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la
|
||||
|
||||
TESTS = \
|
||||
memtest
|
||||
@ -1,414 +1,411 @@
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#define ALIGN_BY 32
|
||||
#define ALIGN_BY_M1 (ALIGN_BY - 1)
|
||||
#define ALIGN(_in) (((_in) + ALIGN_BY_M1) & (~ALIGN_BY_M1))
|
||||
|
||||
#define LLOG_LEVEL 1
|
||||
#define LLOGLN(_log_level, _params) \
|
||||
do { \
|
||||
if (_log_level < LLOG_LEVEL) \
|
||||
{ \
|
||||
printf _params ; \
|
||||
printf ("\n") ; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct mem_item
|
||||
{
|
||||
unsigned int addr;
|
||||
int bytes;
|
||||
struct mem_item* next;
|
||||
struct mem_item* prev;
|
||||
unsigned int addr;
|
||||
int bytes;
|
||||
struct mem_item *next;
|
||||
struct mem_item *prev;
|
||||
};
|
||||
|
||||
struct mem_info
|
||||
{
|
||||
unsigned int addr;
|
||||
int bytes;
|
||||
int flags;
|
||||
struct mem_item* free_head;
|
||||
struct mem_item* free_tail;
|
||||
struct mem_item* used_head;
|
||||
struct mem_item* used_tail;
|
||||
int total_bytes;
|
||||
unsigned int addr;
|
||||
int bytes;
|
||||
int flags;
|
||||
struct mem_item *free_head;
|
||||
struct mem_item *free_tail;
|
||||
struct mem_item *used_head;
|
||||
struct mem_item *used_tail;
|
||||
int total_bytes;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
libmem_free_mem_item(struct mem_info* self, struct mem_item* mi)
|
||||
libmem_free_mem_item(struct mem_info *self, struct mem_item *mi)
|
||||
{
|
||||
if (self == 0 || mi == 0)
|
||||
{
|
||||
if (self == 0 || mi == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
mi->prev->next = mi->next;
|
||||
}
|
||||
if (mi->next != 0)
|
||||
{
|
||||
mi->next->prev = mi->prev;
|
||||
}
|
||||
if (mi == self->free_head)
|
||||
{
|
||||
self->free_head = mi->next;
|
||||
}
|
||||
if (mi == self->free_tail)
|
||||
{
|
||||
self->free_tail = mi->prev;
|
||||
}
|
||||
if (mi == self->used_head)
|
||||
{
|
||||
self->used_head = mi->next;
|
||||
}
|
||||
if (mi == self->used_tail)
|
||||
{
|
||||
self->used_tail = mi->prev;
|
||||
}
|
||||
free(mi);
|
||||
return 0;
|
||||
}
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
mi->prev->next = mi->next;
|
||||
}
|
||||
if (mi->next != 0)
|
||||
{
|
||||
mi->next->prev = mi->prev;
|
||||
}
|
||||
if (mi == self->free_head)
|
||||
{
|
||||
self->free_head = mi->next;
|
||||
}
|
||||
if (mi == self->free_tail)
|
||||
{
|
||||
self->free_tail = mi->prev;
|
||||
}
|
||||
if (mi == self->used_head)
|
||||
{
|
||||
self->used_head = mi->next;
|
||||
}
|
||||
if (mi == self->used_tail)
|
||||
{
|
||||
self->used_tail = mi->prev;
|
||||
}
|
||||
free(mi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void*
|
||||
void *
|
||||
libmem_init(unsigned int addr, int bytes)
|
||||
{
|
||||
struct mem_info* self;
|
||||
struct mem_item* mi;
|
||||
struct mem_info *self;
|
||||
struct mem_item *mi;
|
||||
|
||||
self = (struct mem_info*)malloc(sizeof(struct mem_info));
|
||||
memset(self, 0, sizeof(struct mem_info));
|
||||
self->addr = addr;
|
||||
self->bytes = bytes;
|
||||
//self->flags = 1;
|
||||
mi = (struct mem_item*)malloc(sizeof(struct mem_item));
|
||||
memset(mi, 0, sizeof(struct mem_item));
|
||||
mi->addr = addr;
|
||||
mi->bytes = bytes;
|
||||
self->free_head = mi;
|
||||
self->free_tail = mi;
|
||||
return self;
|
||||
self = (struct mem_info *)malloc(sizeof(struct mem_info));
|
||||
memset(self, 0, sizeof(struct mem_info));
|
||||
self->addr = addr;
|
||||
self->bytes = bytes;
|
||||
//self->flags = 1;
|
||||
mi = (struct mem_item *)malloc(sizeof(struct mem_item));
|
||||
memset(mi, 0, sizeof(struct mem_item));
|
||||
mi->addr = addr;
|
||||
mi->bytes = bytes;
|
||||
self->free_head = mi;
|
||||
self->free_tail = mi;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
libmem_deinit(void* aself)
|
||||
libmem_deinit(void *aself)
|
||||
{
|
||||
struct mem_info* self;
|
||||
struct mem_info *self;
|
||||
|
||||
self = (struct mem_info*)aself;
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (self->free_head != 0)
|
||||
{
|
||||
libmem_free_mem_item(self, self->free_head);
|
||||
}
|
||||
while (self->used_head != 0)
|
||||
{
|
||||
libmem_free_mem_item(self, self->used_head);
|
||||
}
|
||||
free(self);
|
||||
self = (struct mem_info *)aself;
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (self->free_head != 0)
|
||||
{
|
||||
libmem_free_mem_item(self, self->free_head);
|
||||
}
|
||||
while (self->used_head != 0)
|
||||
{
|
||||
libmem_free_mem_item(self, self->used_head);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static int
|
||||
libmem_add_used_item(struct mem_info* self, unsigned int addr, int bytes)
|
||||
libmem_add_used_item(struct mem_info *self, unsigned int addr, int bytes)
|
||||
{
|
||||
struct mem_item* mi;
|
||||
struct mem_item* new_mi;
|
||||
int added;
|
||||
struct mem_item *mi;
|
||||
struct mem_item *new_mi;
|
||||
int added;
|
||||
|
||||
if (self == 0 || addr == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (self->used_head == 0)
|
||||
{
|
||||
/* add first item */
|
||||
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->used_head = new_mi;
|
||||
self->used_tail = new_mi;
|
||||
return 0;
|
||||
}
|
||||
added = 0;
|
||||
mi = self->used_head;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (mi->addr > addr)
|
||||
if (self == 0 || addr == 0)
|
||||
{
|
||||
/* add before */
|
||||
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
new_mi->prev = mi->prev;
|
||||
new_mi->next = mi;
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
mi->prev->next = new_mi;
|
||||
}
|
||||
mi->prev = new_mi;
|
||||
if (self->used_head == mi)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (self->used_head == 0)
|
||||
{
|
||||
/* add first item */
|
||||
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->used_head = new_mi;
|
||||
}
|
||||
added = 1;
|
||||
break;
|
||||
self->used_tail = new_mi;
|
||||
return 0;
|
||||
}
|
||||
mi = mi->next;
|
||||
}
|
||||
if (!added)
|
||||
{
|
||||
/* add last */
|
||||
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->used_tail->next = new_mi;
|
||||
new_mi->prev = self->used_tail;
|
||||
self->used_tail = new_mi;
|
||||
}
|
||||
return 0;
|
||||
added = 0;
|
||||
mi = self->used_head;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (mi->addr > addr)
|
||||
{
|
||||
/* add before */
|
||||
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
new_mi->prev = mi->prev;
|
||||
new_mi->next = mi;
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
mi->prev->next = new_mi;
|
||||
}
|
||||
mi->prev = new_mi;
|
||||
if (self->used_head == mi)
|
||||
{
|
||||
self->used_head = new_mi;
|
||||
}
|
||||
added = 1;
|
||||
break;
|
||||
}
|
||||
mi = mi->next;
|
||||
}
|
||||
if (!added)
|
||||
{
|
||||
/* add last */
|
||||
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->used_tail->next = new_mi;
|
||||
new_mi->prev = self->used_tail;
|
||||
self->used_tail = new_mi;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static int
|
||||
libmem_add_free_item(struct mem_info* self, unsigned int addr, int bytes)
|
||||
libmem_add_free_item(struct mem_info *self, unsigned int addr, int bytes)
|
||||
{
|
||||
struct mem_item* mi;
|
||||
struct mem_item* new_mi;
|
||||
int added;
|
||||
struct mem_item *mi;
|
||||
struct mem_item *new_mi;
|
||||
int added;
|
||||
|
||||
if (self == 0 || addr == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (self->free_head == 0)
|
||||
{
|
||||
/* add first item */
|
||||
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->free_head = new_mi;
|
||||
self->free_tail = new_mi;
|
||||
return 0;
|
||||
}
|
||||
added = 0;
|
||||
mi = self->free_head;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (mi->addr > addr)
|
||||
if (self == 0 || addr == 0)
|
||||
{
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
if (mi->prev->addr + mi->prev->bytes == addr)
|
||||
{
|
||||
/* don't need to add, just make prev bigger */
|
||||
mi->prev->bytes += bytes;
|
||||
if (mi->prev->addr + mi->prev->bytes == mi->addr)
|
||||
{
|
||||
/* here we can remove one */
|
||||
mi->prev->bytes += mi->bytes;
|
||||
libmem_free_mem_item(self, mi);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (addr + bytes == mi->addr)
|
||||
{
|
||||
/* don't need to add here either */
|
||||
mi->addr = addr;
|
||||
mi->bytes += bytes;
|
||||
return 0;
|
||||
}
|
||||
/* add before */
|
||||
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
new_mi->prev = mi->prev;
|
||||
new_mi->next = mi;
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
mi->prev->next = new_mi;
|
||||
}
|
||||
mi->prev = new_mi;
|
||||
if (self->free_head == mi)
|
||||
{
|
||||
self->free_head = new_mi;
|
||||
}
|
||||
added = 1;
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
mi = mi->next;
|
||||
}
|
||||
if (!added)
|
||||
{
|
||||
/* add last */
|
||||
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->free_tail->next = new_mi;
|
||||
new_mi->prev = self->free_tail;
|
||||
self->free_tail = new_mi;
|
||||
}
|
||||
return 0;
|
||||
if (self->free_head == 0)
|
||||
{
|
||||
/* add first item */
|
||||
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->free_head = new_mi;
|
||||
self->free_tail = new_mi;
|
||||
return 0;
|
||||
}
|
||||
added = 0;
|
||||
mi = self->free_head;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (mi->addr > addr)
|
||||
{
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
if (mi->prev->addr + mi->prev->bytes == addr)
|
||||
{
|
||||
/* don't need to add, just make prev bigger */
|
||||
mi->prev->bytes += bytes;
|
||||
if (mi->prev->addr + mi->prev->bytes == mi->addr)
|
||||
{
|
||||
/* here we can remove one */
|
||||
mi->prev->bytes += mi->bytes;
|
||||
libmem_free_mem_item(self, mi);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (addr + bytes == mi->addr)
|
||||
{
|
||||
/* don't need to add here either */
|
||||
mi->addr = addr;
|
||||
mi->bytes += bytes;
|
||||
return 0;
|
||||
}
|
||||
/* add before */
|
||||
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
new_mi->prev = mi->prev;
|
||||
new_mi->next = mi;
|
||||
if (mi->prev != 0)
|
||||
{
|
||||
mi->prev->next = new_mi;
|
||||
}
|
||||
mi->prev = new_mi;
|
||||
if (self->free_head == mi)
|
||||
{
|
||||
self->free_head = new_mi;
|
||||
}
|
||||
added = 1;
|
||||
break;
|
||||
}
|
||||
mi = mi->next;
|
||||
}
|
||||
if (!added)
|
||||
{
|
||||
/* add last */
|
||||
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
|
||||
memset(new_mi, 0, sizeof(struct mem_item));
|
||||
new_mi->addr = addr;
|
||||
new_mi->bytes = bytes;
|
||||
self->free_tail->next = new_mi;
|
||||
new_mi->prev = self->free_tail;
|
||||
self->free_tail = new_mi;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
libmem_print(struct mem_info* self)
|
||||
libmem_print(struct mem_info *self)
|
||||
{
|
||||
struct mem_item* mi;
|
||||
struct mem_item *mi;
|
||||
|
||||
LLOGLN(0, ("libmem_print:"));
|
||||
LLOGLN(0, (" used_head %p", self->used_head));
|
||||
LLOGLN(0, (" used_tail %p", self->used_tail));
|
||||
mi = self->used_head;
|
||||
if (mi != 0)
|
||||
{
|
||||
LLOGLN(0, (" used list"));
|
||||
while (mi != 0)
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libmem_print:");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " used_head %p", self->used_head);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " used_tail %p", self->used_tail);
|
||||
mi = self->used_head;
|
||||
if (mi != 0)
|
||||
{
|
||||
LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d",
|
||||
mi, mi->prev, mi->next, mi->addr, mi->bytes));
|
||||
mi = mi->next;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " used list");
|
||||
while (mi != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " ptr %p prev %p next %p addr 0x%8.8x bytes %d",
|
||||
mi, mi->prev, mi->next, mi->addr, mi->bytes);
|
||||
mi = mi->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
LLOGLN(0, (" free_head %p", self->free_head));
|
||||
LLOGLN(0, (" free_tail %p", self->free_tail));
|
||||
mi = self->free_head;
|
||||
if (mi != 0)
|
||||
{
|
||||
LLOGLN(0, (" free list"));
|
||||
while (mi != 0)
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " free_head %p", self->free_head);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " free_tail %p", self->free_tail);
|
||||
mi = self->free_head;
|
||||
if (mi != 0)
|
||||
{
|
||||
LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d",
|
||||
mi, mi->prev, mi->next, mi->addr, mi->bytes));
|
||||
mi = mi->next;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " free list");
|
||||
while (mi != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " ptr %p prev %p next %p addr 0x%8.8x bytes %d",
|
||||
mi, mi->prev, mi->next, mi->addr, mi->bytes);
|
||||
mi = mi->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
unsigned int
|
||||
libmem_alloc(void* obj, int bytes)
|
||||
libmem_alloc(void *obj, int bytes)
|
||||
{
|
||||
struct mem_info* self;
|
||||
struct mem_item* mi;
|
||||
unsigned int addr;
|
||||
struct mem_info *self;
|
||||
struct mem_item *mi;
|
||||
unsigned int addr;
|
||||
|
||||
if (bytes < 1)
|
||||
{
|
||||
if (bytes < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
bytes = ALIGN(bytes);
|
||||
self = (struct mem_info *)obj;
|
||||
addr = 0;
|
||||
mi = self->free_head;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (bytes <= mi->bytes)
|
||||
{
|
||||
addr = mi->addr;
|
||||
mi->bytes -= bytes;
|
||||
mi->addr += bytes;
|
||||
if (mi->bytes < 1)
|
||||
{
|
||||
libmem_free_mem_item(self, mi);
|
||||
}
|
||||
break;
|
||||
}
|
||||
mi = mi->next;
|
||||
}
|
||||
if (addr != 0)
|
||||
{
|
||||
self->total_bytes += bytes;
|
||||
libmem_add_used_item(self, addr, bytes);
|
||||
if (self->flags & 1)
|
||||
{
|
||||
libmem_print(self);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "libmem_alloc: error");
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libmem_free(void *obj, unsigned int addr)
|
||||
{
|
||||
struct mem_info *self;
|
||||
struct mem_item *mi;
|
||||
|
||||
if (addr == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
self = (struct mem_info *)obj;
|
||||
mi = self->used_tail;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (mi->addr == addr)
|
||||
{
|
||||
self->total_bytes -= mi->bytes;
|
||||
libmem_add_free_item(self, mi->addr, mi->bytes);
|
||||
libmem_free_mem_item(self, mi);
|
||||
if (self->flags & 1)
|
||||
{
|
||||
libmem_print(self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
mi = mi->prev;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "libmem_free: error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libmem_set_flags(void *obj, int flags)
|
||||
{
|
||||
struct mem_info *self;
|
||||
|
||||
self = (struct mem_info *)obj;
|
||||
self->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
bytes = ALIGN(bytes);
|
||||
self = (struct mem_info*)obj;
|
||||
addr = 0;
|
||||
mi = self->free_head;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (bytes <= mi->bytes)
|
||||
{
|
||||
addr = mi->addr;
|
||||
mi->bytes -= bytes;
|
||||
mi->addr += bytes;
|
||||
if (mi->bytes < 1)
|
||||
{
|
||||
libmem_free_mem_item(self, mi);
|
||||
}
|
||||
break;
|
||||
}
|
||||
mi = mi->next;
|
||||
}
|
||||
if (addr != 0)
|
||||
{
|
||||
self->total_bytes += bytes;
|
||||
libmem_add_used_item(self, addr, bytes);
|
||||
if (self->flags & 1)
|
||||
{
|
||||
libmem_print(self);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("libmem_alloc: error"));
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libmem_free(void* obj, unsigned int addr)
|
||||
libmem_clear_flags(void *obj, int flags)
|
||||
{
|
||||
struct mem_info* self;
|
||||
struct mem_item* mi;
|
||||
struct mem_info *self;
|
||||
|
||||
if (addr == 0)
|
||||
{
|
||||
self = (struct mem_info *)obj;
|
||||
self->flags &= ~flags;
|
||||
return 0;
|
||||
}
|
||||
self = (struct mem_info*)obj;
|
||||
mi = self->used_tail;
|
||||
while (mi != 0)
|
||||
{
|
||||
if (mi->addr == addr)
|
||||
{
|
||||
self->total_bytes -= mi->bytes;
|
||||
libmem_add_free_item(self, mi->addr, mi->bytes);
|
||||
libmem_free_mem_item(self, mi);
|
||||
if (self->flags & 1)
|
||||
{
|
||||
libmem_print(self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
mi = mi->prev;
|
||||
}
|
||||
LLOGLN(0, ("libmem_free: error"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libmem_set_flags(void* obj, int flags)
|
||||
libmem_get_alloced_bytes(void *obj)
|
||||
{
|
||||
struct mem_info* self;
|
||||
struct mem_info *self;
|
||||
|
||||
self = (struct mem_info*)obj;
|
||||
self->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libmem_clear_flags(void* obj, int flags)
|
||||
{
|
||||
struct mem_info* self;
|
||||
|
||||
self = (struct mem_info*)obj;
|
||||
self->flags &= ~flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libmem_get_alloced_bytes(void* obj)
|
||||
{
|
||||
struct mem_info* self;
|
||||
|
||||
self = (struct mem_info*)obj;
|
||||
return self->total_bytes;
|
||||
self = (struct mem_info *)obj;
|
||||
return self->total_bytes;
|
||||
}
|
||||
|
||||
@ -2,19 +2,19 @@
|
||||
#ifndef _LIBMEM_C
|
||||
#define _LIBMEM_C
|
||||
|
||||
void*
|
||||
void *
|
||||
libmem_init(unsigned int addr, int bytes);
|
||||
void
|
||||
libmem_deinit(void* aself);
|
||||
libmem_deinit(void *aself);
|
||||
unsigned int
|
||||
libmem_alloc(void* obj, int bytes);
|
||||
libmem_alloc(void *obj, int bytes);
|
||||
int
|
||||
libmem_free(void* obj, unsigned int addr);
|
||||
libmem_free(void *obj, unsigned int addr);
|
||||
int
|
||||
libmem_set_flags(void* obj, int flags);
|
||||
libmem_set_flags(void *obj, int flags);
|
||||
int
|
||||
libmem_clear_flags(void* obj, int flags);
|
||||
libmem_clear_flags(void *obj, int flags);
|
||||
int
|
||||
libmem_get_alloced_bytes(void* obj);
|
||||
libmem_get_alloced_bytes(void *obj);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,60 +1,72 @@
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "libmem.h"
|
||||
#include "log.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void* obj;
|
||||
unsigned int addr1;
|
||||
unsigned int addr2;
|
||||
unsigned int addr3;
|
||||
unsigned int addr4;
|
||||
unsigned int addr5;
|
||||
int index;
|
||||
int rd;
|
||||
void *obj;
|
||||
unsigned int addr1;
|
||||
unsigned int addr2;
|
||||
unsigned int addr3;
|
||||
unsigned int addr4;
|
||||
unsigned int addr5;
|
||||
int index;
|
||||
int rd;
|
||||
struct log_config *config;
|
||||
|
||||
srand(time(0));
|
||||
obj = libmem_init(0x80000000, 64 * 1024 * 1024);
|
||||
for (index = 0; index < 256; index++)
|
||||
{
|
||||
rd = rand() & 0xffff;
|
||||
printf("1 rd %d\n", rd);
|
||||
addr1 = libmem_alloc(obj, rd);
|
||||
rd = rand() & 0xffff;
|
||||
printf("2 rd %d\n", rd);
|
||||
addr2 = libmem_alloc(obj, rd);
|
||||
rd = rand() & 0xffff;
|
||||
printf("3 rd %d\n", rd);
|
||||
addr3 = libmem_alloc(obj, rd);
|
||||
rd = rand() & 0xffff;
|
||||
printf("4 rd %d\n", rd);
|
||||
addr4 = libmem_alloc(obj, rd);
|
||||
addr5 = libmem_alloc(obj, rd);
|
||||
libmem_free(obj, addr1);
|
||||
printf("5\n");
|
||||
addr1 = libmem_alloc(obj, 64);
|
||||
printf("6\n");
|
||||
libmem_free(obj, addr3);
|
||||
printf("7\n");
|
||||
addr3 = libmem_alloc(obj, 64 * 1024);
|
||||
libmem_free(obj, addr5);
|
||||
addr5 = libmem_alloc(obj, 64 * 1024);
|
||||
printf("8\n");
|
||||
libmem_free(obj, addr1);
|
||||
printf("9\n");
|
||||
libmem_free(obj, addr2);
|
||||
printf("10\n");
|
||||
libmem_free(obj, addr3);
|
||||
libmem_free(obj, addr4);
|
||||
if (index == 255)
|
||||
config = log_config_init_for_console(LOG_LEVEL_DEBUG, NULL);
|
||||
log_start_from_param(config);
|
||||
log_config_free(config);
|
||||
|
||||
srand(time(0));
|
||||
obj = libmem_init(0x80000000, 64 * 1024 * 1024);
|
||||
for (index = 0; index < 256; index++)
|
||||
{
|
||||
libmem_set_flags(obj, 1);
|
||||
rd = rand() & 0xffff;
|
||||
printf("1 rd %d\n", rd);
|
||||
addr1 = libmem_alloc(obj, rd);
|
||||
rd = rand() & 0xffff;
|
||||
printf("2 rd %d\n", rd);
|
||||
addr2 = libmem_alloc(obj, rd);
|
||||
rd = rand() & 0xffff;
|
||||
printf("3 rd %d\n", rd);
|
||||
addr3 = libmem_alloc(obj, rd);
|
||||
rd = rand() & 0xffff;
|
||||
printf("4 rd %d\n", rd);
|
||||
addr4 = libmem_alloc(obj, rd);
|
||||
addr5 = libmem_alloc(obj, rd);
|
||||
libmem_free(obj, addr1);
|
||||
printf("5\n");
|
||||
addr1 = libmem_alloc(obj, 64);
|
||||
printf("6\n");
|
||||
libmem_free(obj, addr3);
|
||||
printf("7\n");
|
||||
addr3 = libmem_alloc(obj, 64 * 1024);
|
||||
libmem_free(obj, addr5);
|
||||
addr5 = libmem_alloc(obj, 64 * 1024);
|
||||
printf("8\n");
|
||||
libmem_free(obj, addr1);
|
||||
printf("9\n");
|
||||
libmem_free(obj, addr2);
|
||||
printf("10\n");
|
||||
libmem_free(obj, addr3);
|
||||
libmem_free(obj, addr4);
|
||||
if (index == 255)
|
||||
{
|
||||
libmem_set_flags(obj, 1);
|
||||
}
|
||||
libmem_free(obj, addr5);
|
||||
}
|
||||
libmem_free(obj, addr5);
|
||||
}
|
||||
libmem_deinit(obj);
|
||||
return 0;
|
||||
libmem_deinit(obj);
|
||||
log_end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
|
||||
CFLAGS = -O2 -Wall
|
||||
LDFLAGS =
|
||||
OBJS = main.o
|
||||
LIBS = -ldl
|
||||
|
||||
all: tcp_proxy
|
||||
|
||||
tcp_proxy: $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o tcp_proxy $(OBJS) $(LIBS)
|
||||
|
||||
.PHONY clean:
|
||||
rm -f $(OBJS) tcp_proxy
|
||||
@ -1,701 +0,0 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
int g_loc_io_count = 0; // bytes read from local port
|
||||
int g_rem_io_count = 0; // bytes read from remote port
|
||||
|
||||
static int g_terminated = 0;
|
||||
static char g_buf[1024 * 32];
|
||||
|
||||
|
||||
typedef unsigned short tui16;
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_memset(void *ptr, int val, int size)
|
||||
{
|
||||
memset(ptr, val, size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_printf(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vfprintf(stdout, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_writeln(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vfprintf(stdout, format, ap);
|
||||
va_end(ap);
|
||||
g_printf("\n");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_hexdump(char *p, int len)
|
||||
{
|
||||
unsigned char *line;
|
||||
int i;
|
||||
int thisline;
|
||||
int offset;
|
||||
|
||||
line = (unsigned char *)p;
|
||||
offset = 0;
|
||||
|
||||
while (offset < len)
|
||||
{
|
||||
g_printf("%04x ", offset);
|
||||
thisline = len - offset;
|
||||
|
||||
if (thisline > 16)
|
||||
{
|
||||
thisline = 16;
|
||||
}
|
||||
|
||||
for (i = 0; i < thisline; i++)
|
||||
{
|
||||
g_printf("%02x ", line[i]);
|
||||
}
|
||||
|
||||
for (; i < 16; i++)
|
||||
{
|
||||
g_printf(" ");
|
||||
}
|
||||
|
||||
for (i = 0; i < thisline; i++)
|
||||
{
|
||||
g_printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
|
||||
}
|
||||
|
||||
g_writeln("%s", "");
|
||||
offset += thisline;
|
||||
line += thisline;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_socket(void)
|
||||
{
|
||||
int rv;
|
||||
int option_value;
|
||||
socklen_t option_len;
|
||||
|
||||
rv = (int)socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (rv < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
option_len = sizeof(option_value);
|
||||
if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
|
||||
&option_len) == 0)
|
||||
{
|
||||
if (option_value == 0)
|
||||
{
|
||||
option_value = 1;
|
||||
option_len = sizeof(option_value);
|
||||
setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
|
||||
option_len);
|
||||
}
|
||||
}
|
||||
|
||||
option_len = sizeof(option_value);
|
||||
|
||||
if (getsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
|
||||
&option_len) == 0)
|
||||
{
|
||||
if (option_value < (1024 * 32))
|
||||
{
|
||||
option_value = 1024 * 32;
|
||||
option_len = sizeof(option_value);
|
||||
setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
|
||||
option_len);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_set_non_blocking(int sck)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
i = fcntl(sck, F_GETFL);
|
||||
i = i | O_NONBLOCK;
|
||||
fcntl(sck, F_SETFL, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_bind(int sck, const char* port)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
|
||||
memset(&s, 0, sizeof(struct sockaddr_in));
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons((tui16)atoi(port));
|
||||
s.sin_addr.s_addr = INADDR_ANY;
|
||||
return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_listen(int sck)
|
||||
{
|
||||
return listen(sck, 2);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_select(int sck1, int sck2)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval time;
|
||||
int max = 0;
|
||||
int rv = 0;
|
||||
|
||||
g_memset(&rfds, 0, sizeof(fd_set));
|
||||
g_memset(&time, 0, sizeof(struct timeval));
|
||||
|
||||
time.tv_sec = 0;
|
||||
time.tv_usec = 0;
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
if (sck1 > 0)
|
||||
{
|
||||
FD_SET(((unsigned int)sck1), &rfds);
|
||||
}
|
||||
|
||||
if (sck2 > 0)
|
||||
{
|
||||
FD_SET(((unsigned int)sck2), &rfds);
|
||||
}
|
||||
|
||||
max = sck1;
|
||||
|
||||
if (sck2 > max)
|
||||
{
|
||||
max = sck2;
|
||||
}
|
||||
|
||||
rv = select(max + 1, &rfds, 0, 0, &time);
|
||||
|
||||
if (rv > 0)
|
||||
{
|
||||
rv = 0;
|
||||
|
||||
if (FD_ISSET(((unsigned int)sck1), &rfds))
|
||||
{
|
||||
rv = rv | 1;
|
||||
}
|
||||
|
||||
if (FD_ISSET(((unsigned int)sck2), &rfds))
|
||||
{
|
||||
rv = rv | 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_recv(int sck, void *ptr, int len, int flags)
|
||||
{
|
||||
return recv(sck, ptr, len, flags);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_tcp_close(int sck)
|
||||
{
|
||||
if (sck == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
close(sck);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_send(int sck, const void *ptr, int len, int flags)
|
||||
{
|
||||
return send(sck, ptr, len, flags);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
g_sleep(int msecs)
|
||||
{
|
||||
usleep(msecs * 1000);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_last_error_would_block(int sck)
|
||||
{
|
||||
return (errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINPROGRESS);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_accept(int sck)
|
||||
{
|
||||
int ret ;
|
||||
struct sockaddr_in s;
|
||||
unsigned int i;
|
||||
|
||||
i = sizeof(struct sockaddr_in);
|
||||
memset(&s, 0, i);
|
||||
ret = accept(sck, (struct sockaddr *)&s, &i);
|
||||
return ret ;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_connect(int sck, const char* address, const char* port)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
struct hostent* h;
|
||||
|
||||
g_memset(&s, 0, sizeof(struct sockaddr_in));
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons((tui16)atoi(port));
|
||||
s.sin_addr.s_addr = inet_addr(address);
|
||||
if (s.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
h = gethostbyname(address);
|
||||
if (h != 0)
|
||||
{
|
||||
if (h->h_name != 0)
|
||||
{
|
||||
if (h->h_addr_list != 0)
|
||||
{
|
||||
if ((*(h->h_addr_list)) != 0)
|
||||
{
|
||||
s.sin_addr.s_addr = *((int*)(*(h->h_addr_list)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_socket_ok(int sck)
|
||||
{
|
||||
int opt;
|
||||
socklen_t opt_len = sizeof(opt);
|
||||
|
||||
if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char *)(&opt), &opt_len) == 0)
|
||||
{
|
||||
if (opt == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_init(const char *app_name)
|
||||
{
|
||||
setlocale(LC_CTYPE, "");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_tcp_can_send(int sck, int millis)
|
||||
{
|
||||
fd_set wfds;
|
||||
struct timeval time;
|
||||
int rv;
|
||||
|
||||
time.tv_sec = millis / 1000;
|
||||
time.tv_usec = (millis * 1000) % 1000000;
|
||||
FD_ZERO(&wfds);
|
||||
|
||||
if (sck > 0)
|
||||
{
|
||||
FD_SET(((unsigned int)sck), &wfds);
|
||||
rv = select(sck + 1, 0, &wfds, 0, &time);
|
||||
|
||||
if (rv > 0)
|
||||
{
|
||||
return g_tcp_socket_ok(sck);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_signal_user_interrupt(void (*func)(int))
|
||||
{
|
||||
signal(SIGINT, func);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_signal_terminate(void (*func)(int))
|
||||
{
|
||||
signal(SIGTERM, func);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
g_signal_usr1(void (*func)(int))
|
||||
{
|
||||
signal(SIGUSR1, func);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
g_strcasecmp(const char *c1, const char *c2)
|
||||
{
|
||||
return strcasecmp(c1, c2);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
|
||||
{
|
||||
int lis_sck;
|
||||
int acc_sck;
|
||||
int con_sck;
|
||||
int sel;
|
||||
int count;
|
||||
int sent;
|
||||
int error;
|
||||
int i;
|
||||
int acc_to_con;
|
||||
int con_to_acc;
|
||||
|
||||
acc_to_con = 0;
|
||||
con_to_acc = 0;
|
||||
acc_sck = 0;
|
||||
|
||||
/* create the listening socket and setup options */
|
||||
lis_sck = g_tcp_socket();
|
||||
g_tcp_set_non_blocking(lis_sck);
|
||||
error = g_tcp_bind(lis_sck, local_port);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
g_writeln("bind failed");
|
||||
}
|
||||
|
||||
/* listen for an incoming connection */
|
||||
if (error == 0)
|
||||
{
|
||||
error = g_tcp_listen(lis_sck);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
g_writeln("listening for connection");
|
||||
}
|
||||
}
|
||||
|
||||
/* accept an incoming connection */
|
||||
if (error == 0)
|
||||
{
|
||||
while ((!g_terminated) && (error == 0))
|
||||
{
|
||||
acc_sck = g_tcp_accept(lis_sck);
|
||||
|
||||
if ((acc_sck == -1) && g_tcp_last_error_would_block(lis_sck))
|
||||
{
|
||||
g_sleep(100);
|
||||
}
|
||||
else if (acc_sck == -1)
|
||||
{
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
error = g_terminated;
|
||||
}
|
||||
|
||||
/* stop listening */
|
||||
g_tcp_close(lis_sck);
|
||||
lis_sck = 0;
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
g_writeln("got connection");
|
||||
}
|
||||
}
|
||||
|
||||
/* connect outgoing socket */
|
||||
con_sck = 0;
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
con_sck = g_tcp_socket();
|
||||
g_tcp_set_non_blocking(con_sck);
|
||||
error = g_tcp_connect(con_sck, remote_ip, remote_port);
|
||||
|
||||
if ((error == -1) && g_tcp_last_error_would_block(con_sck))
|
||||
{
|
||||
error = 0;
|
||||
i = 0;
|
||||
|
||||
while ((!g_tcp_can_send(con_sck, 100)) && (!g_terminated) && (i < 100))
|
||||
{
|
||||
g_sleep(100);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i > 99)
|
||||
{
|
||||
g_writeln("timeout connecting");
|
||||
error = 1;
|
||||
}
|
||||
|
||||
if (g_terminated)
|
||||
{
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((error != 0) && (!g_terminated))
|
||||
{
|
||||
g_writeln("error connecting to remote\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
while ((!g_terminated) && (error == 0))
|
||||
{
|
||||
sel = g_tcp_select(con_sck, acc_sck);
|
||||
|
||||
if (sel == 0)
|
||||
{
|
||||
g_sleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sel & 1)
|
||||
{
|
||||
// can read from con_sck w/o blocking
|
||||
count = g_tcp_recv(con_sck, g_buf, 1024 * 16, 0);
|
||||
error = count < 1;
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
g_loc_io_count += count;
|
||||
con_to_acc += count;
|
||||
|
||||
if (hexdump)
|
||||
{
|
||||
g_writeln("from remove, the socket from connect");
|
||||
g_hexdump(g_buf, count);
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_writeln("local_io_count: %d\tremote_io_count: %d",
|
||||
g_loc_io_count, g_rem_io_count);
|
||||
#endif
|
||||
sent = 0;
|
||||
|
||||
while ((sent < count) && (error == 0) && (!g_terminated))
|
||||
{
|
||||
i = g_tcp_send(acc_sck, g_buf + sent, count - sent, 0);
|
||||
|
||||
if ((i == -1) && g_tcp_last_error_would_block(acc_sck))
|
||||
{
|
||||
g_tcp_can_send(acc_sck, 1000);
|
||||
}
|
||||
else if (i < 1)
|
||||
{
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sent += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sel & 2)
|
||||
{
|
||||
// can read from acc_sck w/o blocking
|
||||
count = g_tcp_recv(acc_sck, g_buf, 1024 * 16, 0);
|
||||
error = count < 1;
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
g_rem_io_count += count;
|
||||
acc_to_con += count;
|
||||
|
||||
if (hexdump)
|
||||
{
|
||||
g_writeln("from accepted, the socket from accept");
|
||||
g_hexdump(g_buf, count);
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_writeln("local_io_count: %d\tremote_io_count: %d",
|
||||
g_loc_io_count, g_rem_io_count);
|
||||
#endif
|
||||
sent = 0;
|
||||
|
||||
while ((sent < count) && (error == 0) && (!g_terminated))
|
||||
{
|
||||
i = g_tcp_send(con_sck, g_buf + sent, count - sent, 0);
|
||||
|
||||
if ((i == -1) && g_tcp_last_error_would_block(con_sck))
|
||||
{
|
||||
g_tcp_can_send(con_sck, 1000);
|
||||
}
|
||||
else if (i < 1)
|
||||
{
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sent += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_tcp_close(lis_sck);
|
||||
g_tcp_close(con_sck);
|
||||
g_tcp_close(acc_sck);
|
||||
g_writeln("acc_to_con %d", acc_to_con);
|
||||
g_writeln("con_to_acc %d", con_to_acc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
usage(void)
|
||||
{
|
||||
g_writeln("tcp_proxy <local-port> <remote-ip> <remote-port> [dump]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
proxy_shutdown(int sig)
|
||||
{
|
||||
g_writeln("shutting down");
|
||||
g_terminated = 1;
|
||||
}
|
||||
|
||||
void
|
||||
clear_counters(int sig)
|
||||
{
|
||||
g_writeln("cleared counters at: local_io_count: %d remote_io_count: %d",
|
||||
g_loc_io_count, g_rem_io_count);
|
||||
g_loc_io_count = 0;
|
||||
g_rem_io_count = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int dump;
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_init("tcp_proxy");
|
||||
g_signal_user_interrupt(proxy_shutdown); /* SIGINT */
|
||||
g_signal_usr1(clear_counters); /* SIGUSR1 */
|
||||
g_signal_terminate(proxy_shutdown); /* SIGTERM */
|
||||
|
||||
if (argc < 5)
|
||||
{
|
||||
while (!g_terminated)
|
||||
{
|
||||
g_loc_io_count = 0;
|
||||
g_rem_io_count = 0;
|
||||
main_loop(argv[1], argv[2], argv[3], 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dump = g_strcasecmp(argv[4], "dump") == 0;
|
||||
|
||||
while (!g_terminated)
|
||||
{
|
||||
main_loop(argv[1], argv[2], argv[3], dump);
|
||||
}
|
||||
}
|
||||
|
||||
g_deinit();
|
||||
return 0;
|
||||
}
|
||||
3
tools/Makefile.am
Normal file
3
tools/Makefile.am
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
SUBDIRS = \
|
||||
devel
|
||||
6
tools/devel/Makefile.am
Normal file
6
tools/devel/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
EXTRA_DIST = \
|
||||
gtcp_proxy
|
||||
|
||||
SUBDIRS = \
|
||||
tcp_proxy
|
||||
@ -332,7 +332,9 @@ static void *tcp_proxy(void *arg)
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
if (tcp_can_send(con_skt, 100))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
}
|
||||
@ -452,7 +454,9 @@ static void show_msg(int not_main_window, int style,
|
||||
GtkWidget *dialog;
|
||||
|
||||
if (not_main_window)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
dialog = gtk_message_dialog_new(GTK_WINDOW(NULL),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
@ -465,7 +469,9 @@ static void show_msg(int not_main_window, int style,
|
||||
gtk_widget_destroy(dialog);
|
||||
|
||||
if (not_main_window)
|
||||
{
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -475,12 +481,16 @@ static void show_msg(int not_main_window, int style,
|
||||
static void show_status(int not_main_thread, char *msg)
|
||||
{
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
gtk_statusbar_push(GTK_STATUSBAR(g_statusbar), CONTEXT_ID, msg);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -490,12 +500,16 @@ static void show_status(int not_main_thread, char *msg)
|
||||
static void clear_status(int not_main_thread)
|
||||
{
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
gtk_statusbar_remove_all(GTK_STATUSBAR(g_statusbar), CONTEXT_ID);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -505,12 +519,16 @@ static void clear_status(int not_main_thread)
|
||||
static void enable_btn_start(int not_main_thread)
|
||||
{
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(g_btn_start), TRUE);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -520,12 +538,16 @@ static void enable_btn_start(int not_main_thread)
|
||||
static void disable_btn_start(int not_main_thread)
|
||||
{
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(g_btn_start), FALSE);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -569,12 +591,16 @@ static void show_loc_port_stats(int not_main_thread, int count)
|
||||
sprintf(buf, "%d", count);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
gtk_entry_set_text(GTK_ENTRY(g_tbx_loc_stats), buf);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -588,12 +614,16 @@ static void show_rem_port_stats(int not_main_thread, int count)
|
||||
sprintf(buf, "%d", count);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
gtk_entry_set_text(GTK_ENTRY(g_tbx_rem_stats), buf);
|
||||
|
||||
if (not_main_thread)
|
||||
{
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,7 +30,9 @@ int tcp_socket_create(void)
|
||||
|
||||
/* in win32 a socket is an unsigned int, in linux, it's an int */
|
||||
if ((rv = (int) socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
option_len = sizeof(option_value);
|
||||
|
||||
@ -157,7 +159,9 @@ int tcp_last_error_would_block()
|
||||
void tcp_close(int skt)
|
||||
{
|
||||
if (skt <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
closesocket(skt);
|
||||
@ -180,7 +184,9 @@ int tcp_socket(void)
|
||||
|
||||
/* in win32 a socket is an unsigned int, in linux, it's an int */
|
||||
if ((rv = (int) socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
option_len = sizeof(option_value);
|
||||
|
||||
@ -295,7 +301,9 @@ int tcp_socket_ok(int skt)
|
||||
if (getsockopt(skt, SOL_SOCKET, SO_ERROR, (char *) (&opt), &opt_len) == 0)
|
||||
{
|
||||
if (opt == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -323,15 +331,21 @@ int tcp_select(int sck1, int sck2)
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
if (sck1 > 0)
|
||||
{
|
||||
FD_SET(((unsigned int) sck1), &rfds);
|
||||
}
|
||||
|
||||
if (sck2 > 0)
|
||||
{
|
||||
FD_SET(((unsigned int) sck2), &rfds);
|
||||
}
|
||||
|
||||
max = sck1;
|
||||
|
||||
if (sck2 > max)
|
||||
{
|
||||
max = sck2;
|
||||
}
|
||||
|
||||
rv = select(max + 1, &rfds, 0, 0, &time);
|
||||
|
||||
@ -340,10 +354,14 @@ int tcp_select(int sck1, int sck2)
|
||||
rv = 0;
|
||||
|
||||
if (FD_ISSET(((unsigned int) sck1), &rfds))
|
||||
{
|
||||
rv = rv | 1;
|
||||
}
|
||||
|
||||
if (FD_ISSET(((unsigned int)sck2), &rfds))
|
||||
{
|
||||
rv = rv | 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user