Merge branch 'devel' into v0.9

This commit is contained in:
Koichiro IWAO 2019-08-20 00:35:10 +09:00
commit 21ff90a89b
No known key found for this signature in database
GPG Key ID: 9F72CDBC01BF10EB
29 changed files with 1862 additions and 453 deletions

View File

@ -15,6 +15,7 @@ min_amd64_deps: &min_amd64_deps
- libssl-dev
- libx11-dev
- libxrandr-dev
- libxfixes-dev
min_amd64_conf: &min_amd64_conf
env:

20
NEWS.md
View File

@ -1,3 +1,21 @@
# Release notes for xrdp v1.9.11 (2019/08/19)
## New features
* Suppress output (do not draw screen when client window is minimized) #1330
* Audio input (microphone) redirection compatible with [MS-RDPEAI](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeai/d04ffa42-5a0f-4f80-abb1-cc26f71c9452) #1369
* Now xrdp can listen on more than one port #1124 #1366
## Bug fixes
* Fix the issue audio redirection sometimes sounds with long delay #1363
* Check term event for more responsive shutdown #1372
## Known issues
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
-----------------------
# Release notes for xrdp v0.9.10 (2019/04/18)
## Special thanks
@ -11,7 +29,7 @@ Thank you for matt335672 contributing to lots of improvements in drive redirecti
* Fix the issue reconnecting to session causes duplicate drive entries in fuse fs #1299
* Fix default_wm and reconnect_sh refer wrong path after sesman caught SIGUP #1315 #1331
* Shutdown xrdp more responsively #1325
* Improve remote file lookup in drive redirection #996 #1327
* Improve remote file lookup in drive redirection #996 #1327
* Overwriting & appending to existing files is are now supported #1327
## Other changes

View File

@ -2,7 +2,7 @@
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/neutrinolabs/xrdp)
![Apache-License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)
*Current Version:* 0.9.10
*Current Version:* 0.9.11
# xrdp - an open source RDP server

View File

@ -1041,6 +1041,25 @@ g_sck_vsock_bind(int sck, const char *port)
#endif
}
/*****************************************************************************/
int
g_sck_vsock_bind_address(int sck, const char *port, const char *address)
{
#if defined(XRDP_ENABLE_VSOCK)
struct sockaddr_vm s;
g_memset(&s, 0, sizeof(struct sockaddr_vm));
s.svm_family = AF_VSOCK;
s.svm_port = atoi(port);
s.svm_cid = atoi(address);
return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_vm));
#else
return -1;
#endif
}
#if defined(XRDP_ENABLE_IPV6)
/*****************************************************************************/
/* Helper function for g_tcp_bind_address. */
@ -3823,3 +3842,153 @@ g_mirror_memcpy(void *dst, const void *src, int len)
return 0;
}
/*****************************************************************************/
int
g_tcp4_socket(void)
{
#if defined(XRDP_ENABLE_IPV6ONLY)
return -1;
#else
int rv;
int option_value;
socklen_t option_len;
rv = 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);
if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR,
(char *) &option_value, option_len) < 0)
{
}
}
}
return rv;
#endif
}
/*****************************************************************************/
int
g_tcp4_bind_address(int sck, const char *port, const char *address)
{
#if defined(XRDP_ENABLE_IPV6ONLY)
return -1;
#else
struct sockaddr_in s;
memset(&s, 0, sizeof(s));
s.sin_family = AF_INET;
s.sin_addr.s_addr = htonl(INADDR_ANY);
s.sin_port = htons((uint16_t) atoi(port));
if (inet_aton(address, &s.sin_addr) < 0)
{
return -1; /* bad address */
}
if (bind(sck, (struct sockaddr*) &s, sizeof(s)) < 0)
{
return -1;
}
return 0;
#endif
}
/*****************************************************************************/
int
g_tcp6_socket(void)
{
#if defined(XRDP_ENABLE_IPV6)
int rv;
int option_value;
socklen_t option_len;
rv = socket(AF_INET6, SOCK_STREAM, 0);
if (rv < 0)
{
return -1;
}
option_len = sizeof(option_value);
if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY,
(char *) &option_value, &option_len) == 0)
{
#if defined(XRDP_ENABLE_IPV6ONLY)
if (option_value == 0)
{
option_value = 1;
#else
if (option_value != 0)
{
option_value = 0;
#endif
option_len = sizeof(option_value);
if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY,
(char *) &option_value, option_len) < 0)
{
}
}
}
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);
if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR,
(char *) &option_value, option_len) < 0)
{
}
}
}
return rv;
#else
return -1;
#endif
}
/*****************************************************************************/
int
g_tcp6_bind_address(int sck, const char *port, const char *address)
{
#if defined(XRDP_ENABLE_IPV6)
int rv;
int error;
struct addrinfo hints;
struct addrinfo *list;
struct addrinfo *i;
rv = -1;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = 0;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
error = getaddrinfo(address, port, &hints, &list);
if (error == 0)
{
i = list;
while ((i != NULL) && (rv < 0))
{
rv = bind(sck, i->ai_addr, i->ai_addrlen);
i = i->ai_next;
}
freeaddrinfo(list);
}
else
{
return -1;
}
return rv;
#else
return -1;
#endif
}

View File

@ -71,6 +71,7 @@ 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_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_sck_listen(int sck);
int g_tcp_accept(int sck);
@ -183,6 +184,10 @@ 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);
int g_tcp4_socket(void);
int g_tcp4_bind_address(int sck, const char *port, const char *address);
int g_tcp6_socket(void);
int g_tcp6_bind_address(int sck, const char *port, const char *address);
/* glib-style wrappers */
#define g_new(struct_type, n_structs) \

View File

@ -875,7 +875,43 @@ trans_listen_address(struct trans *self, char *port, const char *address)
g_tcp_set_non_blocking(self->sck);
if (g_sck_vsock_bind(self->sck, port) == 0)
if (g_sck_vsock_bind_address(self->sck, port, address) == 0)
{
if (g_tcp_listen(self->sck) == 0)
{
self->status = TRANS_STATUS_UP; /* ok */
self->type1 = TRANS_TYPE_LISTENER; /* listener */
return 0;
}
}
}
else if (self->mode == TRANS_MODE_TCP4) /* tcp4 */
{
self->sck = g_tcp4_socket();
if (self->sck < 0)
{
return 1;
}
g_tcp_set_non_blocking(self->sck);
if (g_tcp4_bind_address(self->sck, port, address) == 0)
{
if (g_tcp_listen(self->sck) == 0)
{
self->status = TRANS_STATUS_UP; /* ok */
self->type1 = TRANS_TYPE_LISTENER; /* listener */
return 0;
}
}
}
else if (self->mode == TRANS_MODE_TCP6) /* tcp6 */
{
self->sck = g_tcp6_socket();
if (self->sck < 0)
{
return 1;
}
g_tcp_set_non_blocking(self->sck);
if (g_tcp6_bind_address(self->sck, port, address) == 0)
{
if (g_tcp_listen(self->sck) == 0)
{
@ -885,7 +921,6 @@ trans_listen_address(struct trans *self, char *port, const char *address)
}
}
}
return 1;
}

View File

@ -24,9 +24,11 @@
#include "arch.h"
#include "parse.h"
#define TRANS_MODE_TCP 1
#define TRANS_MODE_TCP 1 /* tcp6 if defined, else tcp4 */
#define TRANS_MODE_UNIX 2
#define TRANS_MODE_VSOCK 3
#define TRANS_MODE_TCP4 4 /* tcp4 only */
#define TRANS_MODE_TCP6 6 /* tcp6 only */
#define TRANS_TYPE_LISTENER 1
#define TRANS_TYPE_SERVER 2

View File

@ -156,6 +156,7 @@ struct xrdp_client_info
int no_orders_supported;
int use_cache_glyph_v2;
int rail_enable;
int suppress_output;
};
#endif

View File

@ -1,7 +1,7 @@
# Process this file with autoconf to produce a configure script
AC_PREREQ(2.65)
AC_INIT([xrdp], [0.9.10], [xrdp-devel@googlegroups.com])
AC_INIT([xrdp], [0.9.11], [xrdp-devel@googlegroups.com])
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
AM_INIT_AUTOMAKE([1.7.2 foreign])
AC_CONFIG_MACRO_DIR([m4])

View File

@ -810,7 +810,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, 0); /* Update capability */
out_uint16_le(s, 0); /* Remote unshare capability */
out_uint16_le(s, 0); /* Compression level */
out_uint16_le(s, 0); /* Pad */
out_uint8(s, 1); /* refreshRectSupport */
out_uint8(s, 1); /* suppressOutputSupport */
/* Output bitmap capability set */
caps_count++;

View File

@ -1209,21 +1209,91 @@ xrdp_rdp_process_frame_ack(struct xrdp_rdp *self, struct stream *s)
return 0;
}
/*****************************************************************************/
static int
xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s)
{
int allowDisplayUpdates;
int left;
int top;
int right;
int bottom;
if (!s_check_rem(s, 1))
{
return 1;
}
in_uint8(s, allowDisplayUpdates);
g_writeln("xrdp_rdp_process_suppress: allowDisplayUpdates %d bytes "
"left %d", allowDisplayUpdates, (int) (s->end - s->p));
switch (allowDisplayUpdates)
{
case 0: /* SUPPRESS_DISPLAY_UPDATES */
self->client_info.suppress_output = 1;
g_writeln("xrdp_rdp_process_suppress: suppress_output %d",
self->client_info.suppress_output);
if (self->session->callback != 0)
{
self->session->callback(self->session->id, 0x5559, 1,
0, 0, 0);
}
break;
case 1: /* ALLOW_DISPLAY_UPDATES */
self->client_info.suppress_output = 0;
if (!s_check_rem(s, 11))
{
return 1;
}
in_uint8s(s, 3); /* pad */
in_uint16_le(s, left);
in_uint16_le(s, top);
in_uint16_le(s, right);
in_uint16_le(s, bottom);
g_writeln("xrdp_rdp_process_suppress: suppress_output %d "
"left %d top %d right %d bottom %d",
self->client_info.suppress_output,
left, top, right, bottom);
if (self->session->callback != 0)
{
self->session->callback(self->session->id, 0x5559, 0,
MAKELONG(left, top),
MAKELONG(right, bottom), 0);
}
break;
}
return 0;
}
/*****************************************************************************/
/* RDP_PDU_DATA */
int
xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s)
{
int data_type;
int uncompressedLength;
int pduType2;
int compressedType;
int compressedLength;
if (!s_check_rem(s, 12))
{
return 1;
}
in_uint8s(s, 6);
in_uint8s(s, 2); /* len */
in_uint8(s, data_type);
in_uint8s(s, 1); /* ctype */
in_uint8s(s, 2); /* clen */
DEBUG(("xrdp_rdp_process_data code %d", data_type));
switch (data_type)
in_uint16_le(s, uncompressedLength);
in_uint8(s, pduType2);
in_uint8(s, compressedType);
in_uint16_le(s, compressedLength);
if (compressedType != 0)
{
/* don't support compression */
return 1;
}
if (compressedLength > uncompressedLength)
{
return 1;
}
DEBUG(("xrdp_rdp_process_data pduType2 %d", pduType2));
switch (pduType2)
{
case RDP_DATA_PDU_POINTER: /* 27(0x1b) */
xrdp_rdp_process_data_pointer(self, s);
@ -1240,11 +1310,8 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s)
case 33: /* 33(0x21) ?? Invalidate an area I think */
xrdp_rdp_process_screen_update(self, s);
break;
case 35: /* 35(0x23) */
/* 35 ?? this comes when minimizing a full screen mstsc.exe 2600 */
/* I think this is saying the client no longer wants screen */
/* updates and it will issue a 33 above to catch up */
/* so minimized apps don't take bandwidth */
case 35: /* 35(0x23) PDUTYPE2_SUPPRESS_OUTPUT */
xrdp_rdp_process_suppress(self, s);
break;
case 36: /* 36(0x24) ?? disconnect query? */
/* when this message comes, send a 37 back so the client */
@ -1259,10 +1326,9 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s)
xrdp_rdp_process_frame_ack(self, s);
break;
default:
g_writeln("unknown in xrdp_rdp_process_data %d", data_type);
g_writeln("unknown in xrdp_rdp_process_data pduType2 %d", pduType2);
break;
}
return 0;
}
/*****************************************************************************/

View File

@ -27,6 +27,12 @@
#include "log.h"
#include <freerdp/settings.h>
#if defined(VERSION_STRUCT_RDP_FREERDP)
#if VERSION_STRUCT_RDP_FREERDP > 1
#define NEUTRINORDP_HAS_SUPPRESS_OUTPUT
#endif
#endif
#ifdef XRDP_DEBUG
#define LOG_LEVEL 99
#else
@ -541,6 +547,24 @@ lxrdp_check_wait_objs(struct mod *mod)
return 0;
}
/******************************************************************************/
static int
lxrdp_frame_ack(struct mod* mod, int flags, int frame_id)
{
return 0;
}
/******************************************************************************/
static int
lxrdp_suppress_output(struct mod* mod, int suppress,
int left, int top, int right, int bottom)
{
#if defined(NEUTRINORDP_HAS_SUPPRESS_OUTPUT)
mod->inst->SendSuppressOutput(mod->inst, !suppress, left, top, right, bottom);
#endif
return 0;
}
/******************************************************************************/
static void
lfreerdp_begin_paint(rdpContext *context)
@ -2009,6 +2033,8 @@ mod_init(void)
mod->mod_session_change = lxrdp_session_change;
mod->mod_get_wait_objs = lxrdp_get_wait_objs;
mod->mod_check_wait_objs = lxrdp_check_wait_objs;
mod->mod_frame_ack = lxrdp_frame_ack;
mod->mod_suppress_output = lxrdp_suppress_output;
mod->inst = freerdp_new();
mod->inst->PreConnect = lfreerdp_pre_connect;

View File

@ -58,7 +58,7 @@ struct pointer_item
int bpp;
};
#define CURRENT_MOD_VER 3
#define CURRENT_MOD_VER 4
struct mod
{
@ -76,8 +76,11 @@ 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);
tintptr mod_dumby[100 - 9]; /* 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);
tintptr mod_dumby[100 - 11]; /* 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);

View File

@ -70,7 +70,9 @@ xrdp_chansrv_SOURCES = \
sound.c \
sound.h \
xcommon.c \
xcommon.h
xcommon.h \
audin.c \
audin.h
xrdp_chansrv_LDFLAGS = \
$(X_LIBS)

518
sesman/chansrv/audin.c Normal file
View File

@ -0,0 +1,518 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2019
*
* 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.
*
* MS-RDPEAI
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "os_calls.h"
#include "chansrv.h"
#include "log.h"
#include "xrdp_constants.h"
#include "fifo.h"
#define MSG_SNDIN_VERSION 1
#define MSG_SNDIN_FORMATS 2
#define MSG_SNDIN_OPEN 3
#define MSG_SNDIN_OPEN_REPLY 4
#define MSG_SNDIN_DATA_INCOMING 5
#define MSG_SNDIN_DATA 6
#define MSG_SNDIN_FORMATCHANGE 7
#define AUDIN_VERSION 0x00000001
#define AUDIN_NAME "AUDIO_INPUT"
#define AUDIN_FLAGS 1 /* WTS_CHANNEL_OPTION_DYNAMIC */
extern FIFO g_in_fifo; /* in sound.c */
extern int g_bytes_in_fifo; /* in sound.c */
struct xr_wave_format_ex
{
int wFormatTag;
int nChannels;
int nSamplesPerSec;
int nAvgBytesPerSec;
int nBlockAlign;
int wBitsPerSample;
int cbSize;
uint8_t *data;
};
static uint8_t g_pcm_44100_data[] = { 0 };
static struct xr_wave_format_ex g_pcm_44100 =
{
WAVE_FORMAT_PCM, /* wFormatTag */
2, /* num of channels */
44100, /* samples per sec */
176400, /* avg bytes per sec */
4, /* block align */
16, /* bits per sample */
0, /* data size */
g_pcm_44100_data /* data */
};
static struct chansrv_drdynvc_procs g_audin_info;
static int g_audin_chanid;
static struct stream *g_in_s;
static struct xr_wave_format_ex *g_server_formats[] =
{
&g_pcm_44100,
NULL
};
static struct xr_wave_format_ex **g_client_formats = NULL;
static int g_current_format = 0; /* index in g_client_formats */
/*****************************************************************************/
static int
cleanup_client_formats(void)
{
int index;
if (g_client_formats == NULL)
{
return 0;
}
index = 0;
while (g_client_formats[index] != NULL)
{
g_free(g_client_formats[index]->data);
g_free(g_client_formats[index]);
index++;
}
g_free(g_client_formats);
g_client_formats = NULL;
return 0;
}
/*****************************************************************************/
static int
audin_send_version(int chan_id)
{
int error;
int bytes;
struct stream *s;
LOG(0, ("audin_send_version:"));
make_stream(s);
init_stream(s, 32);
out_uint8(s, MSG_SNDIN_VERSION);
out_uint32_le(s, AUDIN_VERSION);
s_mark_end(s);
bytes = (int) (s->end - s->data);
error = chansrv_drdynvc_data(chan_id, s->data, bytes);
free_stream(s);
return error;
}
/*****************************************************************************/
static int
audin_send_formats(int chan_id)
{
int error;
int bytes;
int num_formats;
int index;
struct stream *s;
struct xr_wave_format_ex *wf;
LOG(0, ("audin_send_formats:"));
num_formats = sizeof(g_server_formats) /
sizeof(g_server_formats[0]) - 1;
make_stream(s);
init_stream(s, 8192 * num_formats);
out_uint8(s, MSG_SNDIN_FORMATS);
out_uint32_le(s, num_formats);
out_uint32_le(s, 0); /* cbSizeFormatsPacket */
for (index = 0; index < num_formats; index++)
{
wf = g_server_formats[index];
LOG(0, ("audin_send_formats: sending format wFormatTag 0x%4.4x "
"nChannels %d nSamplesPerSec %d",
wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec));
out_uint16_le(s, wf->wFormatTag);
out_uint16_le(s, wf->nChannels);
out_uint32_le(s, wf->nSamplesPerSec);
out_uint32_le(s, wf->nAvgBytesPerSec);
out_uint16_le(s, wf->nBlockAlign);
out_uint16_le(s, wf->wBitsPerSample);
out_uint16_le(s, wf->cbSize);
if (wf->cbSize > 0)
{
out_uint8p(s, wf->data, wf->cbSize);
}
}
s_mark_end(s);
bytes = (int) (s->end - s->data);
error = chansrv_drdynvc_data(chan_id, s->data, bytes);
free_stream(s);
return error;
}
/*****************************************************************************/
static int
audin_send_open(int chan_id)
{
int error;
int bytes;
struct stream *s;
struct xr_wave_format_ex *wf;
LOG(0, ("audin_send_open:"));
make_stream(s);
init_stream(s, 8192);
out_uint8(s, MSG_SNDIN_OPEN);
out_uint32_le(s, 2048); /* FramesPerPacket */
out_uint32_le(s, g_current_format); /* initialFormat */
wf = g_client_formats[g_current_format];
out_uint16_le(s, wf->wFormatTag);
out_uint16_le(s, wf->nChannels);
out_uint32_le(s, wf->nSamplesPerSec);
out_uint32_le(s, wf->nAvgBytesPerSec);
out_uint16_le(s, wf->nBlockAlign);
out_uint16_le(s, wf->wBitsPerSample);
bytes = wf->cbSize;
out_uint16_le(s, bytes);
if (bytes > 0)
{
out_uint8p(s, wf->data, bytes);
}
s_mark_end(s);
bytes = (int) (s->end - s->data);
error = chansrv_drdynvc_data(chan_id, s->data, bytes);
free_stream(s);
return error;
}
/*****************************************************************************/
static int
audin_process_version(int chan_id, struct stream *s)
{
int version;
LOG(0, ("audin_process_version:"));
if (!s_check_rem(s, 4))
{
LOG(0, ("audin_process_version: parse error"));
return 1;
}
in_uint32_le(s, version);
LOG(0, ("audin_process_version: version %d", version));
return audin_send_formats(chan_id);
}
/*****************************************************************************/
static int
audin_process_formats(int chan_id, struct stream *s)
{
int index;
int num_formats;
struct xr_wave_format_ex *wf;
LOG(0, ("audin_process_formats:"));
cleanup_client_formats();
if (!s_check_rem(s, 8))
{
LOG(0, ("audin_process_formats: parse error"));
return 1;
}
in_uint32_le(s, num_formats);
in_uint8s(s, 4); /* cbSizeFormatsPacket */
g_client_formats = g_new0(struct xr_wave_format_ex *, num_formats + 1);
for (index = 0; index < num_formats; index++)
{
if (!s_check_rem(s, 18))
{
LOG(0, ("audin_process_formats: parse error"));
return 1;
}
wf = g_new0(struct xr_wave_format_ex, 1);
g_client_formats[index] = wf;
in_uint16_le(s, wf->wFormatTag);
in_uint16_le(s, wf->nChannels);
in_uint32_le(s, wf->nSamplesPerSec);
in_uint32_le(s, wf->nAvgBytesPerSec);
in_uint16_le(s, wf->nBlockAlign);
in_uint16_le(s, wf->wBitsPerSample);
in_uint16_le(s, wf->cbSize);
LOG(0, ("audin_process_formats: recved format wFormatTag 0x%4.4x "
"nChannels %d nSamplesPerSec %d",
wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec));
if (wf->cbSize > 0)
{
if (!s_check_rem(s, wf->cbSize))
{
LOG(0, ("audin_process_formats: parse error"));
return 1;
}
wf->data = g_new0(uint8_t, wf->cbSize);
in_uint8a(s, wf->data, wf->cbSize);
}
}
audin_send_open(chan_id);
return 0;
}
/*****************************************************************************/
static int
audin_process_open_reply(int chan_id, struct stream *s)
{
int result;
if (!s_check_rem(s, 4))
{
LOG(0, ("audin_process_open_reply: parse error"));
return 1;
}
in_uint32_le(s, result);
LOG(0, ("audin_process_open_reply: result 0x%8.8x", result));
return 0;
}
/*****************************************************************************/
static int
audin_process_incoming_data(int chan_id, struct stream *s)
{
LOG(10, ("audin_process_incoming_data:"));
return 0;
}
/*****************************************************************************/
static int
audin_process_data(int chan_id, struct stream *s)
{
int data_bytes;
struct stream *ls;
data_bytes = (int) (s->end - s->p);
LOG(10, ("audin_process_data: data_bytes %d", data_bytes));
xstream_new(ls, data_bytes);
g_memcpy(ls->data, s->p, data_bytes);
ls->p += data_bytes;
s_mark_end(ls);
fifo_insert(&g_in_fifo, (void *) ls);
g_bytes_in_fifo += data_bytes;
return 0;
}
/*****************************************************************************/
static int
audin_process_format_change(int chan_id, struct stream *s)
{
LOG(0, ("audin_process_format_change:"));
if (!s_check_rem(s, 4))
{
LOG(0, ("audin_process_format_change: parse error"));
return 1;
}
in_uint32_le(s, g_current_format);
LOG(0, ("audin_process_format_change: g_current_format %d",
g_current_format));
return 0;
}
/*****************************************************************************/
static int
audin_process_msg(int chan_id, struct stream *s)
{
int code;
LOG(10, ("audin_process_msg:"));
if (!s_check_rem(s, 1))
{
LOG(0, ("audin_process_msg: parse error"));
return 1;
}
in_uint8(s, code);
LOG(10, ("audin_process_msg: code %d", code));
switch (code)
{
case MSG_SNDIN_VERSION:
return audin_process_version(chan_id, s);
case MSG_SNDIN_FORMATS:
return audin_process_formats(chan_id, s);
case MSG_SNDIN_OPEN_REPLY:
return audin_process_open_reply(chan_id, s);
case MSG_SNDIN_DATA_INCOMING:
return audin_process_incoming_data(chan_id, s);
case MSG_SNDIN_DATA:
return audin_process_data(chan_id, s);
case MSG_SNDIN_FORMATCHANGE:
return audin_process_format_change(chan_id, s);
default:
LOG(0, ("audin_process_msg: unprocessed code %d", code));
break;
}
return 0;
}
/*****************************************************************************/
static int
audin_open_response(int chan_id, int creation_status)
{
LOG(0, ("audin_open_response: creation_status 0x%8.8x", creation_status));
if (creation_status == 0)
{
return audin_send_version(chan_id);
}
return 0;
}
/*****************************************************************************/
static int
audin_close_response(int chan_id)
{
LOG(0, ("audin_close_response:"));
g_audin_chanid = 0;
cleanup_client_formats();
free_stream(g_in_s);
g_in_s = NULL;
return 0;
}
/*****************************************************************************/
static int
audin_data_fragment(int chan_id, char *data, int bytes)
{
int rv;
int left;
LOG(10, ("audin_data_fragment:"));
if (!s_check_rem(g_in_s, bytes))
{
left = (int) (g_in_s->end - g_in_s->p);
LOG(0, ("audin_data_fragment: error bytes %d left %d", bytes, left));
return 1;
}
out_uint8a(g_in_s, data, bytes);
if (g_in_s->p == g_in_s->end)
{
g_in_s->p = g_in_s->data;
rv = audin_process_msg(chan_id, g_in_s);
free_stream(g_in_s);
g_in_s = NULL;
return rv;
}
return 0;
}
/*****************************************************************************/
static int
audin_data_first(int chan_id, char *data, int bytes, int total_bytes)
{
LOG(10, ("audin_data_first:"));
if (g_in_s != NULL)
{
LOG(0, ("audin_data_first: warning g_in_s is not nil"));
free_stream(g_in_s);
}
make_stream(g_in_s);
init_stream(g_in_s, total_bytes);
g_in_s->end = g_in_s->data + total_bytes;
return audin_data_fragment(chan_id, data, bytes);
}
/*****************************************************************************/
static int
audin_data(int chan_id, char *data, int bytes)
{
struct stream ls;
LOG(10, ("audin_data:"));
//g_hexdump(data, bytes);
if (g_in_s == NULL)
{
g_memset(&ls, 0, sizeof(ls));
ls.data = data;
ls.p = ls.data;
ls.end = ls.p + bytes;
return audin_process_msg(chan_id, &ls);
}
return audin_data_fragment(chan_id, data, bytes);
}
/*****************************************************************************/
int
audin_init(void)
{
LOG(0, ("audin_init:"));
g_memset(&g_audin_info, 0, sizeof(g_audin_info));
g_audin_info.open_response = audin_open_response;
g_audin_info.close_response = audin_close_response;
g_audin_info.data_first = audin_data_first;
g_audin_info.data = audin_data;
g_audin_chanid = 0;
g_in_s = NULL;
return 0;
}
/*****************************************************************************/
int
audin_deinit(void)
{
LOG(0, ("audin_deinit:"));
return 0;
}
/*****************************************************************************/
int
audin_start(void)
{
int error;
struct stream* s;
LOG(0, ("audin_start:"));
if (g_audin_chanid != 0)
{
return 1;
}
/* if there is any data in FIFO, discard it */
while ((s = (struct stream *) fifo_remove(&g_in_fifo)) != NULL)
{
xstream_free(s);
}
g_bytes_in_fifo = 0;
error = chansrv_drdynvc_open(AUDIN_NAME, AUDIN_FLAGS,
&g_audin_info, /* callback functions */
&g_audin_chanid); /* chansrv chan_id */
LOG(0, ("audin_start: error %d g_audin_chanid %d", error, g_audin_chanid));
return error;
}
/*****************************************************************************/
int
audin_stop(void)
{
LOG(0, ("audin_stop:"));
chansrv_drdynvc_close(g_audin_chanid);
return 0;
}

34
sesman/chansrv/audin.h Normal file
View File

@ -0,0 +1,34 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2019
*
* 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.
*
* MS-RDPEAI
*
*/
#ifndef _AUDIN_H_
#define _AUDIN_H_
int
audin_init(void);
int
audin_deinit(void);
int
audin_start(void);
int
audin_stop(void);
#endif

View File

@ -37,6 +37,7 @@
#include "xcommon.h"
#include "chansrv_fuse.h"
#include "xrdp_sockets.h"
#include "audin.h"
static struct trans *g_lis_trans = 0;
static struct trans *g_con_trans = 0;
@ -415,6 +416,8 @@ process_message_channel_setup(struct stream *s)
rail_init();
}
audin_init();
return rv;
}

View File

@ -34,6 +34,8 @@
#include "xrdp_constants.h"
#include "xrdp_sockets.h"
#include "chansrv_common.h"
#include "list.h"
#include "audin.h"
#if defined(XRDP_FDK_AAC)
#include <fdk-aac/aacenc_lib.h>
@ -70,9 +72,11 @@ static struct trans *g_audio_c_trans_in = 0; /* connection */
static int g_training_sent_time = 0;
static int g_cBlockNo = 0;
static int g_bytes_in_stream = 0;
static FIFO g_in_fifo;
static int g_bytes_in_fifo = 0;
static int g_unacked_frames = 0;
FIFO g_in_fifo;
int g_bytes_in_fifo = 0;
static int g_time_diff = 0;
static int g_best_time_diff = 0;
static struct stream *g_stream_inp = NULL;
static struct stream *g_stream_incoming_packet = NULL;
@ -81,10 +85,11 @@ static struct stream *g_stream_incoming_packet = NULL;
static char g_buffer[MAX_BBUF_SIZE];
static int g_buf_index = 0;
static int g_sent_time[256];
static int g_sent_flag[256];
static int g_bbuf_size = 1024 * 8; /* may change later */
static struct list *g_ack_time_diff = 0;
struct xr_wave_format_ex
{
int wFormatTag;
@ -236,6 +241,8 @@ static struct xr_wave_format_ex *g_wave_inp_formats[] =
0
};
static int g_rdpsnd_can_rec = 0;
static int g_client_input_format_index = 0;
static int g_server_input_format_index = 0;
@ -340,7 +347,7 @@ sound_send_training(void)
out_uint16_le(s, SNDC_TRAINING);
size_ptr = s->p;
out_uint16_le(s, 0); /* size, set later */
time = g_time2();
time = g_time3();
g_training_sent_time = time;
out_uint16_le(s, time);
out_uint16_le(s, 1024);
@ -883,18 +890,6 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
return 1;
}
LOG(20, ("sound_send_wave_data_chunk: g_sent_flag[%d] = %d",
g_cBlockNo + 1, g_sent_flag[(g_cBlockNo + 1) & 0xff]));
if (g_sent_flag[(g_cBlockNo + 1) & 0xff] & 1)
{
LOG(10, ("sound_send_wave_data_chunk: no room"));
return 2;
}
else
{
LOG(10, ("sound_send_wave_data_chunk: got room"));
}
/* compress, if available */
format_index = g_current_client_format_index;
data_bytes = sound_wave_compress(data, data_bytes, &format_index);
@ -908,14 +903,12 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
out_uint16_le(s, SNDC_WAVE);
size_ptr = s->p;
out_uint16_le(s, 0); /* size, set later */
time = g_time2();
time = g_time3();
out_uint16_le(s, time);
out_uint16_le(s, format_index); /* wFormatNo */
g_cBlockNo++;
g_unacked_frames++;
out_uint8(s, g_cBlockNo);
g_sent_time[g_cBlockNo & 0xff] = time;
g_sent_flag[g_cBlockNo & 0xff] = 1;
LOG(10, ("sound_send_wave_data_chunk: sending time %d, g_cBlockNo %d",
time & 0xffff, g_cBlockNo & 0xff));
@ -956,6 +949,13 @@ sound_send_wave_data(char *data, int data_bytes)
int res;
LOG(10, ("sound_send_wave_data: sending %d bytes", data_bytes));
if (g_time_diff > g_best_time_diff + 250)
{
data_bytes = data_bytes / 4;
data_bytes = data_bytes & ~3;
g_memset(data, 0, data_bytes);
g_time_diff = 0;
}
data_index = 0;
error = 0;
while (data_bytes > 0)
@ -1005,17 +1005,8 @@ sound_send_close(void)
LOG(10, ("sound_send_close:"));
/* send any left over data */
if (g_buf_index)
{
if (sound_send_wave_data_chunk(g_buffer, g_buf_index) != 0)
{
LOG(10, ("sound_send_close: sound_send_wave_data_chunk failed"));
return 1;
}
}
g_best_time_diff = 0;
g_buf_index = 0;
g_memset(g_sent_flag, 0, sizeof(g_sent_flag));
/* send close msg */
make_stream(s);
@ -1040,7 +1031,7 @@ sound_process_training(struct stream *s, int size)
{
int time_diff;
time_diff = g_time2() - g_training_sent_time;
time_diff = g_time3() - g_training_sent_time;
LOG(0, ("sound_process_training: round trip time %u", time_diff));
return 0;
}
@ -1052,42 +1043,39 @@ sound_process_wave_confirm(struct stream *s, int size)
{
int wTimeStamp;
int cConfirmedBlockNo;
int cleared_count;
int time;
int time_diff;
int block_no;
int block_no_clamped;
int found;
int index;
int acc;
time = g_time2();
time = g_time3();
in_uint16_le(s, wTimeStamp);
in_uint8(s, cConfirmedBlockNo);
time_diff = time - g_sent_time[cConfirmedBlockNo & 0xff];
cleared_count = 0;
found = 0;
block_no = g_cBlockNo;
for (index = 0; index < g_unacked_frames; index++)
{
block_no_clamped = block_no & 0xff;
if ((cConfirmedBlockNo == block_no_clamped) || found)
{
found = 1;
if (g_sent_flag[block_no_clamped] & 1)
{
LOG(10, ("sound_process_wave_confirm: clearing %d",
block_no_clamped));
g_sent_flag[block_no_clamped] &= ~1;
cleared_count++;
}
}
block_no--;
}
LOG(10, ("sound_process_wave_confirm: wTimeStamp %d, "
"cConfirmedBlockNo %d time diff %d cleared_count %d "
"g_unacked_frames %d", wTimeStamp, cConfirmedBlockNo, time_diff,
cleared_count, g_unacked_frames));
g_unacked_frames -= cleared_count;
"cConfirmedBlockNo %d time diff %d",
wTimeStamp, cConfirmedBlockNo, time_diff));
acc = 0;
list_add_item(g_ack_time_diff, time_diff);
if (g_ack_time_diff->count >= 50)
{
while (g_ack_time_diff->count > 50)
{
list_remove_item(g_ack_time_diff, 0);
}
for (index = 0; index < g_ack_time_diff->count; index++)
{
acc += list_get_item(g_ack_time_diff, index);
}
acc = acc / g_ack_time_diff->count;
if ((g_best_time_diff < 1) || (g_best_time_diff > acc))
{
g_best_time_diff = acc;
}
}
g_time_diff = acc;
return 0;
}
@ -1219,7 +1207,6 @@ sound_init(void)
{
LOG(0, ("sound_init:"));
g_memset(g_sent_flag, 0, sizeof(g_sent_flag));
g_stream_incoming_packet = NULL;
/* init sound output */
@ -1242,6 +1229,12 @@ sound_init(void)
g_client_does_mp3lame = 0;
g_client_mp3lame_index = 0;
if (g_ack_time_diff == 0)
{
g_ack_time_diff = list_create();
}
list_clear(g_ack_time_diff);
return 0;
}
@ -1570,6 +1563,10 @@ sound_process_input_formats(struct stream *s, int size)
LOG(10, ("sound_process_input_formats: size=%d", size));
if (g_getenv("XRDP_NO_RDPSND_REC") == NULL)
{
g_rdpsnd_can_rec = 1;
}
in_uint8s(s, 8); /* skip 8 bytes */
in_uint16_le(s, num_formats);
in_uint8s(s, 2); /* skip version */
@ -1782,11 +1779,25 @@ sound_sndsrvr_source_data_in(struct trans *trans)
}
else if (cmd == PA_CMD_START_REC)
{
sound_input_start_recording();
if (g_rdpsnd_can_rec)
{
sound_input_start_recording();
}
else
{
audin_start();
}
}
else if (cmd == PA_CMD_STOP_REC)
{
sound_input_stop_recording();
if (g_rdpsnd_can_rec)
{
sound_input_stop_recording();
}
else
{
audin_stop();
}
}
xstream_free(s);

120
vnc/vnc.c
View File

@ -380,20 +380,23 @@ lib_mod_event(struct vnc *v, int msg, long param1, long param2,
}
else if (msg == 200) /* invalidate */
{
/* FramebufferUpdateRequest */
init_stream(s, 8192);
out_uint8(s, 3);
out_uint8(s, 0);
x = (param1 >> 16) & 0xffff;
out_uint16_be(s, x);
y = param1 & 0xffff;
out_uint16_be(s, y);
cx = (param2 >> 16) & 0xffff;
out_uint16_be(s, cx);
cy = param2 & 0xffff;
out_uint16_be(s, cy);
s_mark_end(s);
error = lib_send_copy(v, s);
if (v->suppress_output == 0)
{
/* FramebufferUpdateRequest */
init_stream(s, 8192);
out_uint8(s, 3);
out_uint8(s, 0);
x = (param1 >> 16) & 0xffff;
out_uint16_be(s, x);
y = param1 & 0xffff;
out_uint16_be(s, y);
cx = (param2 >> 16) & 0xffff;
out_uint16_be(s, cx);
cy = param2 & 0xffff;
out_uint16_be(s, cy);
s_mark_end(s);
error = lib_send_copy(v, s);
}
}
free_stream(s);
@ -742,16 +745,19 @@ lib_framebuffer_update(struct vnc *v)
if (error == 0)
{
/* FramebufferUpdateRequest */
init_stream(s, 8192);
out_uint8(s, 3);
out_uint8(s, 1);
out_uint16_be(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, v->mod_width);
out_uint16_be(s, v->mod_height);
s_mark_end(s);
error = lib_send_copy(v, s);
if (v->suppress_output == 0)
{
/* FramebufferUpdateRequest */
init_stream(s, 8192);
out_uint8(s, 3);
out_uint8(s, 1);
out_uint16_be(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, v->mod_width);
out_uint16_be(s, v->mod_height);
s_mark_end(s);
error = lib_send_copy(v, s);
}
}
free_stream(s);
@ -916,7 +922,7 @@ lib_mod_process_message(struct vnc *v, struct stream *s)
}
else
{
g_sprintf(text, "VNC unknown in lib_mod_signal %d", type);
g_sprintf(text, "VNC unknown in lib_mod_process_message %d", type);
v->server_msg(v, text, 1);
}
}
@ -1340,17 +1346,20 @@ lib_mod_connect(struct vnc *v)
if (error == 0)
{
/* FramebufferUpdateRequest */
init_stream(s, 8192);
out_uint8(s, 3);
out_uint8(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, v->mod_width);
out_uint16_be(s, v->mod_height);
v->server_msg(v, "VNC sending framebuffer update request", 0);
s_mark_end(s);
error = trans_force_write_s(v->trans, s);
if (v->suppress_output == 0)
{
/* FramebufferUpdateRequest */
init_stream(s, 8192);
out_uint8(s, 3);
out_uint8(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, v->mod_width);
out_uint16_be(s, v->mod_height);
v->server_msg(v, "VNC sending framebuffer update request", 0);
s_mark_end(s);
error = trans_force_write_s(v->trans, s);
}
}
if (error == 0)
@ -1492,6 +1501,43 @@ lib_mod_check_wait_objs(struct vnc *v)
return rv;
}
/******************************************************************************/
/* return error */
int
lib_mod_frame_ack(struct vnc* v, int flags, int frame_id)
{
return 0;
}
/******************************************************************************/
/* return error */
int
lib_mod_suppress_output(struct vnc* v, int suppress,
int left, int top, int right, int bottom)
{
int error;
struct stream *s;
error = 0;
v->suppress_output = suppress;
if (suppress == 0)
{
/* FramebufferUpdateRequest */
make_stream(s);
init_stream(s, 8192);
out_uint8(s, 3);
out_uint8(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, 0);
out_uint16_be(s, v->mod_width);
out_uint16_be(s, v->mod_height);
s_mark_end(s);
error = lib_send_copy(v, s);
free_stream(s);
}
return error;
}
/******************************************************************************/
tintptr EXPORT_CC
mod_init(void)
@ -1511,6 +1557,8 @@ mod_init(void)
v->mod_set_param = lib_mod_set_param;
v->mod_get_wait_objs = lib_mod_get_wait_objs;
v->mod_check_wait_objs = lib_mod_check_wait_objs;
v->mod_frame_ack = lib_mod_frame_ack;
v->mod_suppress_output = lib_mod_suppress_output;
return (tintptr) v;
}

View File

@ -24,7 +24,7 @@
#include "os_calls.h"
#include "defines.h"
#define CURRENT_MOD_VER 3
#define CURRENT_MOD_VER 4
struct vnc
{
@ -42,8 +42,11 @@ struct vnc
int (*mod_get_wait_objs)(struct vnc* v, tbus* read_objs, int* rcount,
tbus* write_objs, int* wcount, int* timeout);
int (*mod_check_wait_objs)(struct vnc* v);
tintptr mod_dumby[100 - 9]; /* align, 100 minus the number of mod
functions above */
int (*mod_frame_ack)(struct vnc* v, int flags, int frame_id);
int (*mod_suppress_output)(struct vnc* v, int suppress,
int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
functions above */
/* server functions */
int (*server_begin_update)(struct vnc* v);
int (*server_end_update)(struct vnc* v);
@ -116,4 +119,5 @@ struct vnc
struct trans *trans;
int got_guid;
tui8 guid[16];
int suppress_output;
};

View File

@ -575,6 +575,16 @@ main(int argc, char **argv)
if (!no_daemon)
{
/* if can't listen, exit with failure status */
if (xrdp_listen_test(startup_params) != 0)
{
log_message(LOG_LEVEL_ERROR, "Failed to start xrdp daemon, "
"possibly address already in use.");
g_deinit();
/* must exit with failure status,
or systemd cannot detect xrdp daemon couldn't start properly */
g_exit(1);
}
/* start of daemonizing code */
pid = g_fork();
@ -587,16 +597,6 @@ main(int argc, char **argv)
if (0 != pid)
{
/* if can't listen, exit with failure status */
if (xrdp_listen_test() != 0)
{
log_message(LOG_LEVEL_ERROR, "Failed to start xrdp daemon, "
"possibly address already in use.");
g_deinit();
/* must exit with failure status,
or systemd cannot detect xrdp daemon couldn't start properly */
g_exit(1);
}
g_writeln("daemon process %d started ok", pid);
/* exit, this is the main process */
g_deinit();

View File

@ -170,7 +170,7 @@ xrdp_listen_delete(struct xrdp_listen* self);
int
xrdp_listen_main_loop(struct xrdp_listen* self);
int
xrdp_listen_test(void);
xrdp_listen_test(struct xrdp_startup_params *startup_params);
/* xrdp_region.c */
struct xrdp_region*
@ -371,6 +371,9 @@ xrdp_bitmap_compress(char* in_data, int width, int height,
/* xrdp_mm.c */
int
xrdp_mm_drdynvc_up(struct xrdp_mm* self);
int
xrdp_mm_suppress_output(struct xrdp_mm* self, int suppress,
int left, int top, int right, int bottom);
struct xrdp_mm*
xrdp_mm_create(struct xrdp_wm* owner);
void

View File

@ -4,29 +4,54 @@ ini_version=1
; fork a new process for each incoming connection
fork=true
; tcp port to listen
; ports to listen on, number alone means listen on all interfaces
; 0.0.0.0 or :: if ipv6 is configured
; space between multiple occurrences
;
; Examples:
; port=3389
; port=unix://./tmp/xrdp.socket
; port=tcp://.:3389 127.0.0.1:3389
; port=tcp://:3389 *:3389
; port=tcp://<any ipv4 format addr>:3389 192.168.1.1:3389
; port=tcp6://.:3389 ::1:3389
; port=tcp6://:3389 *:3389
; port=tcp6://{<any ipv6 format addr>}:3389 {FC00:0:0:0:0:0:0:1}:3389
; port=vsock://<cid>:<port>
port=3389
; 'port' above should be connected to with vsock instead of tcp
; use this only with number alone in port above
; prefer use vsock://<cid>:<port> above
use_vsock=false
; regulate if the listening socket use socket option tcp_nodelay
; no buffering will be performed in the TCP stack
tcp_nodelay=true
; regulate if the listening socket use socket option keepalive
; if the network connection disappear without close messages the connection will be closed
tcp_keepalive=true
; set tcp send/recv buffer (for experts)
#tcp_send_buffer_bytes=32768
#tcp_recv_buffer_bytes=32768
; security layer can be 'tls', 'rdp' or 'negotiate'
; for client compatible layer
security_layer=negotiate
; minimum security level allowed for client
; minimum security level allowed for client for classic RDP encryption
; use tls_ciphers to configure TLS encryption
; can be 'none', 'low', 'medium', 'high', 'fips'
crypt_level=high
; X.509 certificate and private key
; openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365
certificate=
key_file=
; set SSL protocols
; can be comma separated list of 'SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3'
ssl_protocols=TLSv1.2, TLSv1.3

File diff suppressed because it is too large Load Diff

View File

@ -999,6 +999,25 @@ xrdp_mm_drdynvc_up(struct xrdp_mm* self)
return 0;
}
/******************************************************************************/
int
xrdp_mm_suppress_output(struct xrdp_mm* self, int suppress,
int left, int top, int right, int bottom)
{
LLOGLN(0, ("xrdp_mm_suppress_output: suppress %d "
"left %d top %d right %d bottom %d",
suppress, left, top, right, bottom));
if (self->mod != NULL)
{
if (self->mod->mod_suppress_output != NULL)
{
self->mod->mod_suppress_output(self->mod, suppress,
left, top, right, bottom);
}
}
return 0;
}
/*****************************************************************************/
/* open response from client going to channel server */
static int

View File

@ -48,7 +48,9 @@ struct xrdp_mod
tbus* write_objs, int* wcount, int* timeout);
int (*mod_check_wait_objs)(struct xrdp_mod* v);
int (*mod_frame_ack)(struct xrdp_mod* v, int flags, int frame_id);
tintptr mod_dumby[100 - 10]; /* align, 100 minus the number of mod
int (*mod_suppress_output)(struct xrdp_mod* v, int suppress,
int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
functions above */
/* server functions */
int (*server_begin_update)(struct xrdp_mod* v);
@ -403,8 +405,9 @@ struct xrdp_process
struct xrdp_listen
{
int status;
struct trans* listen_trans; /* in tcp listen mode */
struct list* process_list;
struct list *trans_list; /* list of struct trans* */
struct list *process_list;
struct list *fork_list;
tbus pro_done_event;
struct xrdp_startup_params* startup_params;
};
@ -525,14 +528,17 @@ struct xrdp_mod_data
struct xrdp_startup_params
{
char port[128];
char port[1024];
int kill;
int no_daemon;
int help;
int version;
int fork;
int send_buffer_bytes;
int recv_buffer_bytes;
int tcp_send_buffer_bytes;
int tcp_recv_buffer_bytes;
int tcp_nodelay;
int tcp_keepalive;
int use_vsock;
};
/*

View File

@ -1916,6 +1916,11 @@ callback(intptr_t id, int msg, intptr_t param1, intptr_t param2,
case 0x5558:
xrdp_mm_drdynvc_up(wm->mm);
break;
case 0x5559:
xrdp_mm_suppress_output(wm->mm, param1,
LOWORD(param2), HIWORD(param2),
LOWORD(param3), HIWORD(param3));
break;
}
return rv;
}

View File

@ -226,6 +226,11 @@ lib_mod_connect(struct mod *mod)
break;
}
if (mod->server_is_term(mod))
{
break;
}
i++;
if (i >= 60)
@ -1143,6 +1148,33 @@ send_paint_rect_ex_ack(struct mod *mod, int flags, int frame_id)
return 0;
}
/******************************************************************************/
/* return error */
static int
send_suppress_output(struct mod *mod, int suppress,
int left, int top, int right, int bottom)
{
int len;
struct stream *s;
make_stream(s);
init_stream(s, 8192);
s_push_layer(s, iso_hdr, 4);
out_uint16_le(s, 108);
out_uint32_le(s, suppress);
out_uint32_le(s, left);
out_uint32_le(s, top);
out_uint32_le(s, right);
out_uint32_le(s, bottom);
s_mark_end(s);
len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
lib_send_copy(mod, s);
free_stream(s);
return 0;
}
/******************************************************************************/
/* return error */
static int
@ -1556,6 +1588,18 @@ lib_mod_frame_ack(struct mod *amod, int flags, int frame_id)
return 0;
}
/******************************************************************************/
/* return error */
int
lib_mod_suppress_output(struct mod *amod, int suppress,
int left, int top, int right, int bottom)
{
LLOGLN(10, ("lib_mod_suppress_output: suppress 0x%8.8x left %d top %d "
"right %d bottom %d", suppress, left, top, right, bottom));
send_suppress_output(amod, suppress, left, top, right, bottom);
return 0;
}
/******************************************************************************/
tintptr EXPORT_CC
mod_init(void)
@ -1575,6 +1619,7 @@ mod_init(void)
mod->mod_get_wait_objs = lib_mod_get_wait_objs;
mod->mod_check_wait_objs = lib_mod_check_wait_objs;
mod->mod_frame_ack = lib_mod_frame_ack;
mod->mod_suppress_output = lib_mod_suppress_output;
return (tintptr) mod;
}

View File

@ -26,7 +26,7 @@
#include "xrdp_client_info.h"
#include "xrdp_rail.h"
#define CURRENT_MOD_VER 3
#define CURRENT_MOD_VER 4
struct mod
{
@ -45,7 +45,9 @@ struct mod
tbus* write_objs, int* wcount, int* timeout);
int (*mod_check_wait_objs)(struct mod* v);
int (*mod_frame_ack)(struct mod* v, int flags, int frame_id);
tintptr mod_dumby[100 - 10]; /* align, 100 minus the number of mod
int (*mod_suppress_output)(struct mod* v, int suppress,
int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
functions above */
/* server functions */
int (*server_begin_update)(struct mod* v);