summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/os_calls.c82
-rw-r--r--common/os_calls.h6
-rw-r--r--configure.ac19
-rw-r--r--freerdp1/xrdp-freerdp.c45
-rw-r--r--instfiles/Makefile.am10
-rw-r--r--instfiles/xrdp-sesman.service14
-rw-r--r--instfiles/xrdp.service14
-rw-r--r--libxrdp/xrdp_rdp.c5
-rw-r--r--sesman/chansrv/Makefile.am22
-rw-r--r--sesman/chansrv/sound.c529
-rw-r--r--sesman/chansrv/sound.h91
-rw-r--r--xorg/X11R7.6/rdp/rdp.h15
-rw-r--r--xorg/X11R7.6/rdp/rdpdraw.c87
-rw-r--r--xorg/X11R7.6/rdp/rdpmain.c10
-rw-r--r--xrdp/xrdp.c77
-rw-r--r--xrdp/xrdp.h5
-rw-r--r--xrdp/xrdp.ini1
-rw-r--r--xrdp/xrdp_listen.c74
-rw-r--r--xrdp/xrdp_process.c4
-rw-r--r--xrdp/xrdp_types.h10
20 files changed, 1037 insertions, 83 deletions
diff --git a/common/os_calls.c b/common/os_calls.c
index dada66ce..453c0466 100644
--- a/common/os_calls.c
+++ b/common/os_calls.c
@@ -419,7 +419,6 @@ g_tcp_close(int sck)
{
return;
}
- shutdown(sck, 2);
#if defined(_WIN32)
closesocket(sck);
#else
@@ -567,31 +566,33 @@ g_tcp_accept(int sck)
/*****************************************************************************/
void APP_CC
-g_write_ip_address(int rcv_sck, char* ip_address)
+g_write_ip_address(int rcv_sck, char* ip_address, int bytes)
{
struct sockaddr_in s;
struct in_addr in;
int len;
int ip_port;
+ int ok;
- memset(&s,0,sizeof(&s));
+ ok = 0;
+ memset(&s, 0, sizeof(s));
len = sizeof(s);
- getpeername(rcv_sck,(struct sockaddr*)&s, &len);
-
- memset(&in,0,sizeof(in));
- in.s_addr = s.sin_addr.s_addr;
-
- ip_port = ntohs(s.sin_port);
-
- if (ip_port != 0)
+ if (getpeername(rcv_sck,(struct sockaddr*)&s, &len) == 0)
{
- sprintf(ip_address, "%s:%d - socket: %d", inet_ntoa(in), ip_port, rcv_sck);
+ memset(&in, 0, sizeof(in));
+ in.s_addr = s.sin_addr.s_addr;
+ ip_port = ntohs(s.sin_port);
+ if (ip_port != 0)
+ {
+ ok = 1;
+ snprintf(ip_address, bytes, "%s:%d - socket: %d", inet_ntoa(in),
+ ip_port, rcv_sck);
+ }
}
- else
+ if (!ok)
{
- sprintf(ip_address, "NULL:NULL - socket: %d", rcv_sck);
+ snprintf(ip_address, bytes, "NULL:NULL - socket: %d", rcv_sck);
}
-
}
/*****************************************************************************/
@@ -1002,6 +1003,19 @@ g_delete_wait_obj(tbus obj)
/*****************************************************************************/
/* returns error */
+/* close but do not delete the wait obj, used after fork */
+int APP_CC
+g_close_wait_obj(tbus obj)
+{
+#ifdef _WIN32
+#else
+ close((int)obj);
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
int APP_CC
g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount,
int mstimeout)
@@ -1395,6 +1409,44 @@ g_create_dir(const char* dirname)
}
/*****************************************************************************/
+/* will try to create directories up to last / in name
+ example /tmp/a/b/c/readme.txt will try to create /tmp/a/b/c
+ returns boolean */
+int APP_CC
+g_create_path(const char* path)
+{
+ char* pp;
+ char* sp;
+ char* copypath;
+ int status;
+
+ status = 1;
+ copypath = g_strdup(path);
+ pp = copypath;
+ sp = strchr(pp, '/');
+ while (sp != 0)
+ {
+ if (sp != pp)
+ {
+ *sp = 0;
+ if (!g_directory_exist(copypath))
+ {
+ if (!g_create_dir(copypath))
+ {
+ status = 0;
+ break;
+ }
+ }
+ *sp = '/';
+ }
+ pp = sp + 1;
+ sp = strchr(pp, '/');
+ }
+ g_free(copypath);
+ return status;
+}
+
+/*****************************************************************************/
/* returns boolean */
int APP_CC
g_remove_dir(const char* dirname)
diff --git a/common/os_calls.h b/common/os_calls.h
index 1a213dba..74c4a07b 100644
--- a/common/os_calls.h
+++ b/common/os_calls.h
@@ -104,7 +104,7 @@ g_tcp_can_recv(int sck, int millis);
int APP_CC
g_tcp_select(int sck1, int sck2);
void APP_CC
-g_write_ip_address(int rcv_sck, char* ip_address);
+g_write_ip_address(int rcv_sck, char* ip_address, int bytes);
void APP_CC
g_sleep(int msecs);
tbus APP_CC
@@ -122,6 +122,8 @@ g_is_wait_obj_set(tbus obj);
int APP_CC
g_delete_wait_obj(tbus obj);
int APP_CC
+g_close_wait_obj(tbus obj);
+int APP_CC
g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount,
int mstimeout);
void APP_CC
@@ -159,6 +161,8 @@ g_directory_exist(const char* dirname);
int APP_CC
g_create_dir(const char* dirname);
int APP_CC
+g_create_path(const char* path);
+int APP_CC
g_remove_dir(const char* dirname);
int APP_CC
g_file_delete(const char* filename);
diff --git a/configure.ac b/configure.ac
index dddd5a07..9a1f9d69 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,6 +7,14 @@ AM_INIT_AUTOMAKE([1.6 foreign])
AC_PROG_CC
AC_C_CONST
AC_PROG_LIBTOOL
+AC_ARG_WITH([systemdsystemunitdir],
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+ [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+if test "x$with_systemdsystemunitdir" != xno; then
+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
+
AC_ARG_ENABLE(nopam, AS_HELP_STRING([--enable-nopam],
[Build no PAM support (default: no)]),
[nopam=true], [nopam=false])
@@ -31,6 +39,10 @@ AC_ARG_ENABLE(jpeg, AS_HELP_STRING([--enable-jpeg],
[Build jpeg module (default: no)]),
[jpeg=true], [jpeg=false])
AM_CONDITIONAL(XRDP_JPEG, [test x$jpeg = xtrue])
+AC_ARG_ENABLE(simplesound, AS_HELP_STRING([--enable-simplesound],
+ [Build simple pulse audio interface (default: no)]),
+ [simplesound=true], [simplesound=false])
+AM_CONDITIONAL(XRDP_SIMPLESOUND, [test x$simplesound = xtrue])
AM_CONDITIONAL(GOT_PREFIX, test "x${prefix}" != "xNONE"])
@@ -58,6 +70,13 @@ then
[AC_MSG_ERROR([please install libjpeg-dev or libjpeg-devel])])
fi
+# checking for libpulse libpulse-simple
+if ! test -z "$enable_simplesound"
+then
+ AC_CHECK_HEADER([pulse/simple.h], [],
+ [AC_MSG_ERROR([please install libpulse-dev or libpulse-devel])])
+fi
+
# checking for Xlib, Xfixes
AC_CHECK_HEADER([X11/Xlib.h], [],
[AC_MSG_ERROR([please install libx11-dev or libX11-devel])])
diff --git a/freerdp1/xrdp-freerdp.c b/freerdp1/xrdp-freerdp.c
index 8e7aa3db..bad9d4ad 100644
--- a/freerdp1/xrdp-freerdp.c
+++ b/freerdp1/xrdp-freerdp.c
@@ -213,6 +213,10 @@ lxrdp_event(struct mod* mod, int msg, long param1, long param2,
mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0);
case 110:
break;
+ case 200:
+ /* Currently there are no (?) invalidate API in freeRDP that can receive this request*/
+ LLOGLN(0, ("Invalidate request sent from client - Ignored"));
+ break ;
case 0x5555:
chanid = LOWORD(param1);
flags = HIWORD(param1);
@@ -339,6 +343,11 @@ lxrdp_set_param(struct mod* mod, char* name, char* value)
{
g_strncpy(mod->password, value, 255);
}
+ else if (g_strcmp(name, "client_info") == 0)
+ {
+ /* This is a Struct and cannot be printed in next else*/
+ LLOGLN(10, ("Client_info struct ignored"));
+ }
else
{
LLOGLN(0, ("lxrdp_set_param: unknown name [%s] value [%s]", name, value));
@@ -711,6 +720,32 @@ lfreerdp_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap_orde
}
/******************************************************************************/
+/* Turn the bitmap upside down*/
+static void DEFAULT_CC
+lfreerdp_upsidedown(uint8* destination, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order, int server_Bpp)
+{
+ tui8* src;
+ tui8* dst;
+ int line_bytes;
+ int j ;
+ if(destination==NULL)
+ {
+ LLOGLN(0, ("lfreerdp_upsidedown : destination pointer is NULL !!!"));
+ return ;
+ }
+
+ line_bytes = server_Bpp * cache_bitmap_v2_order->bitmapWidth;
+ src = cache_bitmap_v2_order->bitmapDataStream;
+ dst = destination + ((cache_bitmap_v2_order->bitmapHeight) * line_bytes);
+ for (j = 0; j < cache_bitmap_v2_order->bitmapHeight; j++)
+ {
+ dst -= line_bytes;
+ g_memcpy(dst, src, line_bytes);
+ src += line_bytes;
+ }
+}
+
+/******************************************************************************/
static void DEFAULT_CC
lfreerdp_cache_bitmapV2(rdpContext* context,
CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order)
@@ -769,9 +804,11 @@ lfreerdp_cache_bitmapV2(rdpContext* context,
server_bpp, server_bpp);
}
else
- {
- g_memcpy(dst_data, cache_bitmap_v2_order->bitmapDataStream,
- width * height * server_Bpp);
+ {
+ /* Uncompressed bitmaps are upside down */
+ lfreerdp_upsidedown(dst_data, cache_bitmap_v2_order,server_Bpp);
+ LLOGLN(10, ("lfreerdp_cache_bitmapV2: upside down progressed"));
+ /* old: g_memcpy(dst_data, cache_bitmap_v2_order->bitmapDataStream,width * height * server_Bpp);*/
}
dst_data1 = convert_bitmap(server_bpp, client_bpp, dst_data,
width, height, mod->colormap);
@@ -1048,7 +1085,7 @@ lfreerdp_pointer_cached(rdpContext* context,
struct mod* mod;
int index;
- LLOGLN(0, ("lfreerdp_pointer_cached:"));
+ LLOGLN(10, ("lfreerdp_pointer_cached:"));
mod = ((struct mod_context*)context)->modi;
index = pointer_cached->cacheIndex;
mod->server_set_cursor(mod, mod->pointer_cache[index].hotx,
diff --git a/instfiles/Makefile.am b/instfiles/Makefile.am
index d6d86140..4cabd942 100644
--- a/instfiles/Makefile.am
+++ b/instfiles/Makefile.am
@@ -1,8 +1,16 @@
-EXTRA_DIST = xrdp.sh km-0407.ini km-0409.ini km-040c.ini km-0410.ini km-0419.ini km-041d.ini
+EXTRA_DIST = xrdp.sh km-0407.ini km-0409.ini km-040c.ini km-0410.ini km-0419.ini km-041d.ini \
+xrdp-sesman.service \
+xrdp.service
SUBDIRS = \
pam.d
+if HAVE_SYSTEMD
+systemdsystemunit_DATA = \
+ xrdp-sesman.service \
+ xrdp.service
+endif
+
startscriptdir=$(sysconfdir)/xrdp
startscript_DATA = \
diff --git a/instfiles/xrdp-sesman.service b/instfiles/xrdp-sesman.service
new file mode 100644
index 00000000..d40150cd
--- /dev/null
+++ b/instfiles/xrdp-sesman.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=xrdp session manager
+After=syslog.target network.target
+StopWhenUnneeded=true
+
+[Service]
+Type=forking
+PIDFile=/var/run/xrdp-sesman.pid
+EnvironmentFile=/etc/sysconfig/xrdp
+ExecStart=/usr/sbin/xrdp-sesman $SESMAN_OPTIONS
+ExecStop=/usr/sbin/xrdp-sesman $SESMAN_OPTIONS --kill
+
+[Install]
+WantedBy=multi-user.target
diff --git a/instfiles/xrdp.service b/instfiles/xrdp.service
new file mode 100644
index 00000000..7bb076d1
--- /dev/null
+++ b/instfiles/xrdp.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=xrdp daemon
+Requires=xrdp-sesman.service
+After=syslog.target network.target xrdp-sesman.service
+
+[Service]
+Type=forking
+PIDFile=/var/run/xrdp.pid
+EnvironmentFile=/etc/sysconfig/xrdp
+ExecStart=/usr/sbin/xrdp $XRDP_OPTIONS
+ExecStop=/usr/sbin/xrdp $XRDP_OPTIONS --kill
+
+[Install]
+WantedBy=multi-user.target
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
index bdbeed48..f25ec274 100644
--- a/libxrdp/xrdp_rdp.c
+++ b/libxrdp/xrdp_rdp.c
@@ -136,6 +136,7 @@ struct xrdp_rdp* APP_CC
xrdp_rdp_create(struct xrdp_session* session, struct trans* trans)
{
struct xrdp_rdp* self = (struct xrdp_rdp *)NULL;
+ int bytes;
DEBUG(("in xrdp_rdp_create"));
self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1);
@@ -153,7 +154,9 @@ xrdp_rdp_create(struct xrdp_session* session, struct trans* trans)
self->client_info.cache2_size = 1024;
self->client_info.cache3_entries = 262;
self->client_info.cache3_size = 4096;
- g_write_ip_address(trans->sck, self->client_info.client_ip); /* load client ip info */
+ /* load client ip info */
+ bytes = sizeof(self->client_info.client_ip) - 1;
+ g_write_ip_address(trans->sck, self->client_info.client_ip, bytes);
#if defined(XRDP_FREERDP1)
self->mppc_enc = mppc_enc_new(PROTO_RDP_50);
#endif
diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am
index 7cd1fa6c..fd8c260c 100644
--- a/sesman/chansrv/Makefile.am
+++ b/sesman/chansrv/Makefile.am
@@ -1,13 +1,25 @@
EXTRA_DIST = chansrv.h clipboard.h devredir.h sound.h
+EXTRA_DEFINES =
+EXTRA_INCLUDES =
+EXTRA_LIBS =
+EXTRA_FLAGS =
+
+if XRDP_SIMPLESOUND
+EXTRA_DEFINES += -DXRDP_SIMPLESOUND
+EXTRA_LIBS += -lpthread -lpulse -lpulse-simple
+endif
+
AM_CFLAGS = \
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
-DXRDP_SBIN_PATH=\"${sbindir}\" \
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
- -DXRDP_PID_PATH=\"${localstatedir}/run\"
+ -DXRDP_PID_PATH=\"${localstatedir}/run\" \
+ $(EXTRA_DEFINES)
INCLUDES = \
- -I$(top_srcdir)/common
+ -I$(top_srcdir)/common \
+ $(EXTRA_INCLUDES)
sbin_PROGRAMS = \
xrdp-chansrv
@@ -18,7 +30,11 @@ xrdp_chansrv_SOURCES = \
clipboard.c \
devredir.c
+xrdp_chansrv_LDFLAGS = \
+ $(EXTRA_FLAGS)
+
xrdp_chansrv_LDADD = \
-L/usr/X11R6/lib \
$(top_srcdir)/common/libcommon.la \
- -lX11 -lXfixes
+ -lX11 -lXfixes \
+ $(EXTRA_LIBS)
diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c
index 8cca641d..3d68faff 100644
--- a/sesman/chansrv/sound.c
+++ b/sesman/chansrv/sound.c
@@ -1,32 +1,343 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2009-2012
+ *
+ * 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 "sound.h"
+
+extern int g_rdpsnd_chan_id; /* in chansrv.c */
+extern int g_display_num; /* in chansrv.c */
+
+static struct trans *g_audio_l_trans = 0; // listener
+static struct trans *g_audio_c_trans = 0; // connection
+static int g_training_sent_time = 0;
+static int g_cBlockNo = 0;
+
+/*****************************************************************************/
+static int APP_CC
+sound_send_server_formats(void)
+{
+ struct stream* s;
+ int bytes;
+ char* size_ptr;
+
+ print_got_here();
+
+ make_stream(s);
+ init_stream(s, 8182);
+ out_uint16_le(s, SNDC_FORMATS);
+ size_ptr = s->p;
+ out_uint16_le(s, 0); /* size, set later */
+ out_uint32_le(s, 0); /* dwFlags */
+ out_uint32_le(s, 0); /* dwVolume */
+ out_uint32_le(s, 0); /* dwPitch */
+ out_uint16_le(s, 0); /* wDGramPort */
+ out_uint16_le(s, 1); /* wNumberOfFormats */
+ out_uint8(s, g_cBlockNo); /* cLastBlockConfirmed */
+ out_uint16_le(s, 2); /* wVersion */
+ out_uint8(s, 0); /* bPad */
+
+ /* sndFormats */
+ /*
+ wFormatTag 2 byte offset 0
+ nChannels 2 byte offset 2
+ nSamplesPerSec 4 byte offset 4
+ nAvgBytesPerSec 4 byte offset 8
+ nBlockAlign 2 byte offset 12
+ wBitsPerSample 2 byte offset 14
+ cbSize 2 byte offset 16
+ data variable offset 18
+ */
+
+ /* examples
+ 01 00 02 00 44 ac 00 00 10 b1 02 00 04 00 10 00 ....D...........
+ 00 00
+ 01 00 02 00 22 56 00 00 88 58 01 00 04 00 10 00 ...."V...X......
+ 00 00
+ */
+
+ out_uint16_le(s, 1); // wFormatTag - WAVE_FORMAT_PCM
+ out_uint16_le(s, 2); // num of channels
+ out_uint32_le(s, 44100); // samples per sec
+ out_uint32_le(s, 176400); // avg bytes per sec
+ out_uint16_le(s, 4); // block align
+ out_uint16_le(s, 16); // bits per sample
+ out_uint16_le(s, 0); // size
+
+ s_mark_end(s);
+ bytes = (int)((s->end - s->data) - 4);
+ size_ptr[0] = bytes;
+ size_ptr[1] = bytes >> 8;
+ bytes = (int)(s->end - s->data);
+ send_channel_data(g_rdpsnd_chan_id, s->data, bytes);
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+sound_send_training(void)
+{
+ struct stream* s;
+ int bytes;
+ int time;
+ char* size_ptr;
+
+ print_got_here();
+
+ make_stream(s);
+ init_stream(s, 8182);
+ out_uint16_le(s, SNDC_TRAINING);
+ size_ptr = s->p;
+ out_uint16_le(s, 0); /* size, set later */
+ time = g_time2();
+ g_training_sent_time = time;
+ out_uint16_le(s, time);
+ out_uint16_le(s, 1024);
+ out_uint8s(s, (1024 - 4));
+ s_mark_end(s);
+ bytes = (int)((s->end - s->data) - 4);
+ size_ptr[0] = bytes;
+ size_ptr[1] = bytes >> 8;
+ bytes = (int)(s->end - s->data);
+ send_channel_data(g_rdpsnd_chan_id, s->data, bytes);
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- xrdp: A Remote Desktop Protocol server.
- Copyright (C) Jay Sorg 2009-2010
+ 0000 07 02 26 00 03 00 80 00 ff ff ff ff 00 00 00 00 ..&.............
+ 0010 00 00 01 00 00 02 00 00 01 00 02 00 44 ac 00 00 ............D...
+ 0020 10 b1 02 00 04 00 10 00 00 00
*/
-#include "arch.h"
-#include "parse.h"
-#include "os_calls.h"
+static int APP_CC
+sound_process_formats(struct stream* s, int size)
+{
+ int num_formats;
+
+ print_got_here();
+
+ LOG(0, ("sound_process_formats:"));
+ if (size < 16)
+ {
+ return 1;
+ }
+ in_uint8s(s, 14);
+ in_uint16_le(s, num_formats);
+ if (num_formats > 0)
+ {
+ sound_send_training();
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+sound_send_wave_data(char* data, int data_bytes)
+{
+ struct stream* s;
+ int bytes;
+ int time;
+ char* size_ptr;
+
+ print_got_here();
+
+ if ((data_bytes < 4) || (data_bytes > 32 * 1024))
+ {
+ LOG(0, ("sound_send_wave_data: bad data_bytes %d", data_bytes));
+ }
+
+ /* part one of 2 PDU wave info */
+
+ LOG(3, ("sound_send_wave_data: sending %d bytes", data_bytes));
+
+ make_stream(s);
+ init_stream(s, data_bytes);
+ out_uint16_le(s, SNDC_WAVE);
+ size_ptr = s->p;
+ out_uint16_le(s, 0); /* size, set later */
+ time = g_time2();
+ out_uint16_le(s, time);
+ out_uint16_le(s, 0); /* wFormatNo */
+ g_cBlockNo++;
+ out_uint8(s, g_cBlockNo);
+
+ LOG(3, ("sound_send_wave_data: sending time %d, g_cBlockNo %d",
+ time & 0xffff, g_cBlockNo & 0xff));
+
+ out_uint8s(s, 3);
+ out_uint8a(s, data, 4);
+ s_mark_end(s);
+ bytes = (int)((s->end - s->data) - 4);
+ bytes += data_bytes;
+ bytes -= 4;
+ size_ptr[0] = bytes;
+ size_ptr[1] = bytes >> 8;
+ bytes = (int)(s->end - s->data);
+ send_channel_data(g_rdpsnd_chan_id, s->data, bytes);
+
+ /* part two of 2 PDU wave info */
+ init_stream(s, data_bytes);
+ out_uint32_le(s, 0);
+ out_uint8a(s, data + 4, data_bytes - 4);
+ s_mark_end(s);
+ bytes = (int)(s->end - s->data);
+ send_channel_data(g_rdpsnd_chan_id, s->data, bytes);
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+sound_process_training(struct stream* s, int size)
+{
+ int time_diff;
+ char buf[256];
+
+ print_got_here();
+
+ time_diff = g_time2() - g_training_sent_time;
+ LOG(0, ("sound_process_training: round trip time %u", time_diff));
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+sound_process_wave_confirm(struct stream* s, int size)
+{
+ int wTimeStamp;
+ int cConfirmedBlockNo;
+
+ print_got_here();
+
+ in_uint16_le(s, wTimeStamp);
+ in_uint8(s, cConfirmedBlockNo);
+
+ LOG(3, ("sound_process_wave_confirm: wTimeStamp %d, cConfirmedBlockNo %d",
+ wTimeStamp, cConfirmedBlockNo));
-extern int g_rdpsnd_chan_id; /* in chansrv.c */
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+process_pcm_message(int id, int size, struct stream* s)
+{
+ print_got_here();
+
+ sound_send_wave_data(s->p, size);
+ return 0;
+}
+
+/*****************************************************************************/
+/* data coming in from audio source, eg pulse, alsa */
+static int DEFAULT_CC
+sound_trans_audio_data_in(struct trans* trans)
+{
+ struct stream *s;
+ int id;
+ int size;
+ int error;
+
+ if (trans == 0)
+ {
+ return 0;
+ }
+ if (trans != g_audio_c_trans)
+ {
+ return 1;
+ }
+ s = trans_get_in_s(trans);
+ in_uint32_le(s, id);
+ in_uint32_le(s, size);
+ if ((id != 0) || (size > 32 * 1024 + 8) || (size < 1))
+ {
+ LOG(0, ("sound_trans_audio_data_in: bad message id %d size %d", id, size));
+ return 1;
+ }
+ error = trans_force_read(trans, size - 8);
+ if (error == 0)
+ {
+ /* here, the entire message block is read in, process it */
+ error = process_pcm_message(id, size - 8, s);
+ }
+ return error;
+}
+
+/*****************************************************************************/
+static int DEFAULT_CC
+sound_trans_audio_conn_in(struct trans *trans, struct trans *new_trans)
+{
+ print_got_here();
+
+ if (trans == 0)
+ {
+ return 1;
+ }
+ if (trans != g_audio_l_trans)
+ {
+ return 1;
+ }
+ if (g_audio_c_trans != 0) /* if already set, error */
+ {
+ return 1;
+ }
+ if (new_trans == 0)
+ {
+ return 1;
+ }
+ g_audio_c_trans = new_trans;
+ g_audio_c_trans->trans_data_in = sound_trans_audio_data_in;
+ g_audio_c_trans->header_size = 8;
+ trans_delete(g_audio_l_trans);
+ g_audio_l_trans = 0;
+ return 0;
+}
/*****************************************************************************/
int APP_CC
sound_init(void)
{
+ char port[256];
+ int error;
+ pthread_t thread;
+
+ print_got_here();
+ LOG(0, ("sound_init:"));
+
+ sound_send_server_formats();
+ g_audio_l_trans = trans_create(2, 33 * 1024, 8192);
+ g_snprintf(port, 255, "/tmp/xrdp_chansrv_audio_socket_%d", g_display_num);
+ g_audio_l_trans->trans_conn_in = sound_trans_audio_conn_in;
+ error = trans_listen(g_audio_l_trans, port);
+ if (error != 0)
+ {
+ LOG(0, ("sound_init: trans_listen failed"));
+ }
+
+#if defined(XRDP_SIMPLESOUND)
+
+ // start thread to read raw audio data from pulseaudio device
+ pthread_create(&thread, 0, read_raw_audio_data, NULL);
+ pthread_detach(thread);
+
+#endif
+
return 0;
}
@@ -34,14 +345,54 @@ sound_init(void)
int APP_CC
sound_deinit(void)
{
+ print_got_here();
+
+ if (g_audio_l_trans != 0)
+ {
+ trans_delete(g_audio_l_trans);
+ g_audio_l_trans = 0;
+ }
+ if (g_audio_c_trans != 0)
+ {
+ trans_delete(g_audio_c_trans);
+ g_audio_l_trans = 0;
+ }
+
return 0;
}
/*****************************************************************************/
+/* data in from client ( clinet -> xrdp -> chansrv ) */
int APP_CC
sound_data_in(struct stream* s, int chan_id, int chan_flags, int length,
int total_length)
{
+ int code;
+ int size;
+
+ print_got_here();
+
+ in_uint8(s, code);
+ in_uint8s(s, 1);
+ in_uint16_le(s, size);
+ switch (code)
+ {
+ case SNDC_WAVECONFIRM:
+ sound_process_wave_confirm(s, size);
+ break;
+
+ case SNDC_TRAINING:
+ sound_process_training(s, size);
+ break;
+
+ case SNDC_FORMATS:
+ sound_process_formats(s, size);
+ break;
+
+ default:
+ LOG(0, ("sound_data_in: unknown code %d size %d", code, size));
+ break;
+ }
return 0;
}
@@ -49,6 +400,20 @@ sound_data_in(struct stream* s, int chan_id, int chan_flags, int length,
int APP_CC
sound_get_wait_objs(tbus* objs, int* count, int* timeout)
{
+ int lcount;
+
+ lcount = *count;
+ if (g_audio_l_trans != 0)
+ {
+ objs[lcount] = g_audio_l_trans->sck;
+ lcount++;
+ }
+ if (g_audio_c_trans != 0)
+ {
+ objs[lcount] = g_audio_c_trans->sck;
+ lcount++;
+ }
+ *count = lcount;
return 0;
}
@@ -56,5 +421,129 @@ sound_get_wait_objs(tbus* objs, int* count, int* timeout)
int APP_CC
sound_check_wait_objs(void)
{
+ if (g_audio_l_trans != 0)
+ {
+ trans_check_wait_objs(g_audio_l_trans);
+ }
+
+ if (g_audio_c_trans != 0)
+ {
+ trans_check_wait_objs(g_audio_c_trans);
+ }
+
return 0;
}
+
+#if defined(XRDP_SIMPLESOUND)
+
+/**
+ * read raw audio data from pulseaudio device and write it
+ * to a unix domain socket on which trans server is listening
+ */
+
+static void *
+read_raw_audio_data(void* arg)
+{
+ struct sockaddr_un serv_addr;
+ pa_sample_spec samp_spec;
+ pa_simple* simple = NULL;
+
+ uint32_t bytes_read;
+ uint8_t audio_buf[AUDIO_BUF_SIZE + 8];
+ char* cptr;
+ int i;
+ int error;
+ int skt_fd;
+
+ // create client socket
+ if ((skt_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ LOG(0, ("read_raw_audio_data: error creating unix domain socket\n"));
+ return NULL;
+ }
+
+ // setup server address and bind to it
+ memset(&serv_addr, 0, sizeof(struct sockaddr_un));
+ serv_addr.sun_family = AF_UNIX;
+ g_snprintf(serv_addr.sun_path, 255, "/tmp/xrdp_chansrv_audio_socket_%d", g_display_num);
+
+ if (connect(skt_fd, (struct sockaddr *) &serv_addr, sizeof(struct sockaddr_un)) < 0)
+ {
+ LOG(0, ("read_raw_audio_data: error connecting to server\n"));
+ close(skt_fd);
+ return NULL;
+ }
+
+ // setup audio format
+ samp_spec.format = PA_SAMPLE_S16LE;
+ samp_spec.rate = 44100;
+ samp_spec.channels = 2;
+
+ // if we are root, then for first 8 seconds connection to pulseaudo server
+ // fails; if we are non-root, then connection succeeds on first attempt;
+ // for now we have changed code to be non-root, but this may change in the
+ // future - so pretend we are root and try connecting to pulseaudio server
+ // for upto one minute
+ for (i = 0; i < 60; i++)
+ {
+ simple = pa_simple_new(NULL, "xrdp", PA_STREAM_RECORD, NULL,
+ "record", &samp_spec, NULL, NULL, &error);
+ if (simple)
+ {
+ // connected to pulseaudio server
+ LOG(0, ("read_raw_audio_data: connected to pulseaudio server\n"));
+ break;
+ }
+ LOG(0, ("read_raw_audio_data: ERROR creating PulseAudio async interface\n"));
+ LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error)));
+ sleep(1);
+ }
+
+ if (i == 60)
+ {
+ // failed to connect to audio server
+ close(skt_fd);
+ return NULL;
+ }
+
+ // insert header just once
+ cptr = audio_buf;
+ ins_uint32_le(cptr, 0);
+ ins_uint32_le(cptr, AUDIO_BUF_SIZE + 8);
+
+ while (1)
+ {
+ // read a block of raw audio data...
+ if ((bytes_read = pa_simple_read(simple, cptr, AUDIO_BUF_SIZE, &error)) < 0)
+ {
+ LOG(0, ("read_raw_audio_data: ERROR reading from pulseaudio stream\n"));
+ LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error)));
+ break;
+ }
+
+ // bug workaround:
+ // even when there is no audio data, pulseaudio is returning without
+ // errors but the data itself is zero; we use this zero data to
+ // determine that there is no audio data present
+ if (*cptr == 0 && *(cptr + 1) == 0 && *(cptr + 2) == 0 && *(cptr + 3) == 0)
+ {
+ usleep(10000);
+ continue;
+ }
+
+ // ... and write it to a unix domain socket
+ if (write(skt_fd, audio_buf, AUDIO_BUF_SIZE + 8) < 0)
+ {
+ LOG(0, ("read_raw_audio_data: ERROR writing audio data to server\n"));
+ break;
+ }
+ }
+
+done:
+
+ pa_simple_free(simple);
+ close(skt_fd);
+ return NULL;
+}
+
+#endif
diff --git a/sesman/chansrv/sound.h b/sesman/chansrv/sound.h
index 45448a5a..a2d1704a 100644
--- a/sesman/chansrv/sound.h
+++ b/sesman/chansrv/sound.h
@@ -1,20 +1,101 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2009-2012
+ *
+ * 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.
+ */
-#if !defined(SOUND_H)
-#define SOUND_H
+#ifndef _SOUND_H_
+#define _SOUND_H_
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#if defined(XRDP_SIMPLESOUND)
+#include <pulse/simple.h>
+#include <pulse/error.h>
+#endif
#include "arch.h"
#include "parse.h"
+#include "os_calls.h"
+#include "chansrv.h"
+#include "trans.h"
+
+#define _DEBUG_RDPSND
+
+#ifdef DEBUG_RDPSND
+#include <stdio.h>
+#define print_got_here() printf("****** got here: %s : %s : %d\n", \
+ __FILE__, __func__, __LINE__);
+#else
+#define print_got_here()
+#endif
+
+/**
+ * insert a uint32_t value into specified byte array
+ *
+ * @param p pointer to byte array
+ * @param v value to insert into byte array
+ */
+
+#if defined(B_ENDIAN) || defined(NEED_ALIGN)
+#define ins_uint32_le(p, v) \
+{ \
+ *p++ = (unsigned char) v; \
+ *p++ = (unsigned char) (v >> 8); \
+ *p++ = (unsigned char) (v >> 16); \
+ *p++ = (unsigned char) (v >> 24); \
+}
+#else
+#define ins_uint32_le(p, v) \
+{ \
+ *((uint32_t *) p) = v; \
+ p += 4; \
+}
+#endif
+
+#define AUDIO_BUF_SIZE 2048
+
+#define SNDC_CLOSE 0x01
+#define SNDC_WAVE 0x02
+#define SNDC_SETVOLUME 0x03
+#define SNDC_SETPITCH 0x04
+#define SNDC_WAVECONFIRM 0x05
+#define SNDC_TRAINING 0x06
+#define SNDC_FORMATS 0x07
+#define SNDC_CRYPTKEY 0x08
+#define SNDC_WAVEENCRYPT 0x09
+#define SNDC_UDPWAVE 0x0A
+#define SNDC_UDPWAVELAST 0x0B
+#define SNDC_QUALITYMODE 0x0C
int APP_CC
sound_init(void);
int APP_CC
sound_deinit(void);
int APP_CC
-sound_data_in(struct stream* s, int chan_id, int chan_flags, int length,
- int total_length);
-int APP_CC
sound_get_wait_objs(tbus* objs, int* count, int* timeout);
int APP_CC
sound_check_wait_objs(void);
+int APP_CC
+sound_data_in(struct stream* s, int chan_id, int chan_flags,
+ int length, int total_length);
+
+#if defined(XRDP_SIMPLESOUND)
+static void*
+read_raw_audio_data(void* arg);
+#endif
#endif
diff --git a/xorg/X11R7.6/rdp/rdp.h b/xorg/X11R7.6/rdp/rdp.h
index 5cd84a5d..0da7d967 100644
--- a/xorg/X11R7.6/rdp/rdp.h
+++ b/xorg/X11R7.6/rdp/rdp.h
@@ -128,6 +128,11 @@ struct _rdpScreenInfoRec
/* Window Procedures */
CreateWindowProcPtr CreateWindow;
DestroyWindowProcPtr DestroyWindow;
+ PositionWindowProcPtr PositionWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+ WindowExposuresProcPtr WindowExposures;
CreateColormapProcPtr CreateColormap;
DestroyColormapProcPtr DestroyColormap;
@@ -252,6 +257,16 @@ Bool
rdpCreateWindow(WindowPtr pWindow);
Bool
rdpDestroyWindow(WindowPtr pWindow);
+Bool
+rdpPositionWindow(WindowPtr pWindow, int x, int y);
+Bool
+rdpRealizeWindow(WindowPtr pWindow);
+Bool
+rdpUnrealizeWindow(WindowPtr pWindow);
+Bool
+rdpChangeWindowAttributes(WindowPtr pWindow, unsigned long mask);
+void
+rdpWindowExposures(WindowPtr pWindow, RegionPtr pRegion, RegionPtr pBSRegion);
Bool
rdpCreateGC(GCPtr pGC);
diff --git a/xorg/X11R7.6/rdp/rdpdraw.c b/xorg/X11R7.6/rdp/rdpdraw.c
index f35e4de1..7cc7c66a 100644
--- a/xorg/X11R7.6/rdp/rdpdraw.c
+++ b/xorg/X11R7.6/rdp/rdpdraw.c
@@ -452,7 +452,7 @@ rdpCreateWindow(WindowPtr pWindow)
rdpWindowRec* priv;
Bool rv;
- //ErrorF("rdpCreateWindow:\n");
+ ErrorF("rdpCreateWindow:\n");
priv = GETWINPRIV(pWindow);
//ErrorF(" %p status %d\n", priv, priv->status);
pScreen = pWindow->drawable.pScreen;
@@ -470,7 +470,7 @@ rdpDestroyWindow(WindowPtr pWindow)
rdpWindowRec* priv;
Bool rv;
- //ErrorF("rdpDestroyWindow:\n");
+ ErrorF("rdpDestroyWindow:\n");
priv = GETWINPRIV(pWindow);
pScreen = pWindow->drawable.pScreen;
pScreen->DestroyWindow = g_rdpScreen.DestroyWindow;
@@ -481,6 +481,89 @@ rdpDestroyWindow(WindowPtr pWindow)
/******************************************************************************/
Bool
+rdpPositionWindow(WindowPtr pWindow, int x, int y)
+{
+ ScreenPtr pScreen;
+ rdpWindowRec* priv;
+ Bool rv;
+
+ ErrorF("rdpPositionWindow:\n");
+ priv = GETWINPRIV(pWindow);
+ pScreen = pWindow->drawable.pScreen;
+ pScreen->PositionWindow = g_rdpScreen.PositionWindow;
+ rv = pScreen->PositionWindow(pWindow, x, y);
+ pScreen->PositionWindow = rdpPositionWindow;
+ return rv;
+}
+
+/******************************************************************************/
+Bool
+rdpRealizeWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen;
+ rdpWindowRec* priv;
+ Bool rv;
+
+ ErrorF("rdpRealizeWindow:\n");
+ priv = GETWINPRIV(pWindow);
+ pScreen = pWindow->drawable.pScreen;
+ pScreen->RealizeWindow = g_rdpScreen.RealizeWindow;
+ rv = pScreen->RealizeWindow(pWindow);
+ pScreen->RealizeWindow = rdpRealizeWindow;
+ return rv;
+}
+
+/******************************************************************************/
+Bool
+rdpUnrealizeWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen;
+ rdpWindowRec* priv;
+ Bool rv;
+
+ ErrorF("rdpUnrealizeWindow:\n");
+ priv = GETWINPRIV(pWindow);
+ pScreen = pWindow->drawable.pScreen;
+ pScreen->UnrealizeWindow = g_rdpScreen.UnrealizeWindow;
+ rv = pScreen->UnrealizeWindow(pWindow);
+ pScreen->UnrealizeWindow = rdpUnrealizeWindow;
+ return rv;
+}
+
+/******************************************************************************/
+Bool
+rdpChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
+{
+ ScreenPtr pScreen;
+ rdpWindowRec* priv;
+ Bool rv;
+
+ ErrorF("rdpChangeWindowAttributes:\n");
+ priv = GETWINPRIV(pWindow);
+ pScreen = pWindow->drawable.pScreen;
+ pScreen->ChangeWindowAttributes = g_rdpScreen.ChangeWindowAttributes;
+ rv = pScreen->ChangeWindowAttributes(pWindow, mask);
+ pScreen->ChangeWindowAttributes = rdpChangeWindowAttributes;
+ return rv;
+}
+
+/******************************************************************************/
+void
+rdpWindowExposures(WindowPtr pWindow, RegionPtr pRegion, RegionPtr pBSRegion)
+{
+ ScreenPtr pScreen;
+ rdpWindowRec* priv;
+
+ ErrorF("rdpWindowExposures:\n");
+ priv = GETWINPRIV(pWindow);
+ pScreen = pWindow->drawable.pScreen;
+ pScreen->WindowExposures = g_rdpScreen.WindowExposures;
+ pScreen->WindowExposures(pWindow, pRegion, pBSRegion);
+ pScreen->WindowExposures = rdpWindowExposures;
+}
+
+/******************************************************************************/
+Bool
rdpCreateGC(GCPtr pGC)
{
rdpGCRec* priv;
diff --git a/xorg/X11R7.6/rdp/rdpmain.c b/xorg/X11R7.6/rdp/rdpmain.c
index b8b3840f..c453cb05 100644
--- a/xorg/X11R7.6/rdp/rdpmain.c
+++ b/xorg/X11R7.6/rdp/rdpmain.c
@@ -347,6 +347,11 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv)
/* Window Procedures */
g_rdpScreen.CreateWindow = pScreen->CreateWindow;
g_rdpScreen.DestroyWindow = pScreen->DestroyWindow;
+ g_rdpScreen.ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
+ g_rdpScreen.RealizeWindow = pScreen->RealizeWindow;
+ g_rdpScreen.UnrealizeWindow = pScreen->UnrealizeWindow;
+ g_rdpScreen.PositionWindow = pScreen->PositionWindow;
+ g_rdpScreen.WindowExposures = pScreen->WindowExposures;
g_rdpScreen.CopyWindow = pScreen->CopyWindow;
g_rdpScreen.ClearToBackground = pScreen->ClearToBackground;
@@ -390,6 +395,11 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv)
/* Window Procedures */
pScreen->CreateWindow = rdpCreateWindow;
pScreen->DestroyWindow = rdpDestroyWindow;
+ pScreen->ChangeWindowAttributes = rdpChangeWindowAttributes;
+ pScreen->RealizeWindow = rdpRealizeWindow;
+ pScreen->UnrealizeWindow = rdpUnrealizeWindow;
+ pScreen->PositionWindow = rdpPositionWindow;
+ pScreen->WindowExposures = rdpWindowExposures;
}
pScreen->CopyWindow = rdpCopyWindow;
diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c
index ccebd8d3..83d2f0a2 100644
--- a/xrdp/xrdp.c
+++ b/xrdp/xrdp.c
@@ -48,6 +48,7 @@ g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
if (tc_threadid_equal(tc_get_threadid(), g_threadid))
{
/* this is the main thread, call the function directly */
+ /* in fork mode, this always happens too */
sync_result = sync_func(sync_param1, sync_param2);
}
else
@@ -90,6 +91,32 @@ xrdp_shutdown(int sig)
}
/*****************************************************************************/
+void DEFAULT_CC
+xrdp_child(int sig)
+{
+ g_waitchild();
+}
+
+/*****************************************************************************/
+/* called in child just after fork */
+int APP_CC
+xrdp_child_fork(void)
+{
+ int pid;
+ char text[256];
+
+ /* close, don't delete these */
+ g_close_wait_obj(g_term_event);
+ g_close_wait_obj(g_sync_event);
+ pid = g_getpid();
+ g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
+ g_term_event = g_create_wait_obj(text);
+ g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
+ g_sync_event = g_create_wait_obj(text);
+ return 0;
+}
+
+/*****************************************************************************/
int APP_CC
g_is_term(void)
{
@@ -214,6 +241,12 @@ xrdp_process_params(int argc, char** argv,
startup_params->port);
}
}
+ else if ((g_strncasecmp(option, "-f", 255) == 0) ||
+ (g_strncasecmp(option, "--fork", 255) == 0))
+ {
+ startup_params->fork = 1;
+ g_writeln("--fork parameter found, ini override");
+ }
else
{
return 1;
@@ -319,7 +352,7 @@ main(int argc, char** argv)
}
if (fd == -1)
{
- g_writeln("problem opening to xrdp.pid");
+ g_writeln("problem opening to xrdp.pid [%s]", pid_file);
g_writeln("maybe its not running");
}
else
@@ -349,9 +382,11 @@ main(int argc, char** argv)
g_writeln("See http://xrdp.sourceforge.net for more information.");
g_writeln("");
g_writeln("Usage: xrdp [options]");
- g_writeln(" -h: show help");
- g_writeln(" -nodaemon: don't fork into background");
- g_writeln(" -kill: shut down xrdp");
+ g_writeln(" --help: show help");
+ g_writeln(" --nodaemon: don't fork into background");
+ g_writeln(" --kill: shut down xrdp");
+ g_writeln(" --port: tcp listen port");
+ g_writeln(" --fork: fork on new connection");
g_writeln("");
g_deinit();
g_exit(0);
@@ -376,6 +411,10 @@ main(int argc, char** argv)
}
if (!no_daemon)
{
+
+ /* make sure containing directory exists */
+ g_create_path(pid_file);
+
/* make sure we can write to pid file */
fd = g_file_open(pid_file); /* xrdp.pid */
if (fd == -1)
@@ -411,16 +450,6 @@ main(int argc, char** argv)
g_exit(0);
}
g_sleep(1000);
- g_file_close(0);
- g_file_close(1);
- g_file_close(2);
- g_file_open("/dev/null");
- g_file_open("/dev/null");
- g_file_open("/dev/null");
- /* end of daemonizing code */
- }
- if (!no_daemon)
- {
/* write the pid to file */
pid = g_getpid();
fd = g_file_open(pid_file); /* xrdp.pid */
@@ -436,6 +465,14 @@ main(int argc, char** argv)
g_file_write(fd, text, g_strlen(text));
g_file_close(fd);
}
+ g_sleep(1000);
+ g_file_close(0);
+ g_file_close(1);
+ g_file_close(2);
+ g_file_open("/dev/null");
+ g_file_open("/dev/null");
+ g_file_open("/dev/null");
+ /* end of daemonizing code */
}
g_threadid = tc_get_threadid();
g_listen = xrdp_listen_create();
@@ -443,6 +480,7 @@ main(int argc, char** argv)
g_signal_kill(xrdp_shutdown); /* SIGKILL */
g_signal_pipe(pipe_sig); /* SIGPIPE */
g_signal_terminate(xrdp_shutdown); /* SIGTERM */
+ g_signal_child_stop(xrdp_child); /* SIGCHLD */
g_sync_mutex = tc_mutex_create();
g_sync1_mutex = tc_mutex_create();
pid = g_getpid();
@@ -454,14 +492,19 @@ main(int argc, char** argv)
{
g_writeln("error creating g_term_event");
}
- xrdp_listen_main_loop(g_listen, startup_params);
+ g_listen->startup_params = startup_params;
+ xrdp_listen_main_loop(g_listen);
xrdp_listen_delete(g_listen);
tc_mutex_delete(g_sync_mutex);
tc_mutex_delete(g_sync1_mutex);
g_delete_wait_obj(g_term_event);
g_delete_wait_obj(g_sync_event);
- /* delete the xrdp.pid file */
- g_file_delete(pid_file);
+ /* only main process should delete pid file */
+ if ((!no_daemon) && (pid == g_getpid()))
+ {
+ /* delete the xrdp.pid file */
+ g_file_delete(pid_file);
+ }
g_free(startup_params);
g_deinit();
return 0;
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 9b280bfc..0bc4a24d 100644
--- a/xrdp/xrdp.h
+++ b/xrdp/xrdp.h
@@ -159,8 +159,7 @@ xrdp_listen_create(void);
void APP_CC
xrdp_listen_delete(struct xrdp_listen* self);
int APP_CC
-xrdp_listen_main_loop(struct xrdp_listen* self,
- struct xrdp_startup_params* startup_param);
+xrdp_listen_main_loop(struct xrdp_listen* self);
/* xrdp_region.c */
struct xrdp_region* APP_CC
@@ -384,6 +383,8 @@ int DEFAULT_CC
server_msg(struct xrdp_mod* mod, char* msg, int code);
int DEFAULT_CC
server_is_term(struct xrdp_mod* mod);
+int APP_CC
+xrdp_child_fork(void);
int DEFAULT_CC
server_set_clip(struct xrdp_mod* mod, int x, int y, int cx, int cy);
int DEFAULT_CC
diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini
index 232cf3d7..115d2708 100644
--- a/xrdp/xrdp.ini
+++ b/xrdp/xrdp.ini
@@ -6,6 +6,7 @@ port=3389
crypt_level=low
channel_code=1
max_bpp=24
+fork=yes
#black=000000
#grey=d6d3ce
#dark_grey=808080
diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c
index 23f532a8..bbdd729a 100644
--- a/xrdp/xrdp_listen.c
+++ b/xrdp/xrdp_listen.c
@@ -28,17 +28,26 @@ static tbus g_process_sem = 0;
static struct xrdp_process* g_process = 0;
/*****************************************************************************/
-struct xrdp_listen* APP_CC
-xrdp_listen_create(void)
+static int
+xrdp_listen_create_pro_done(struct xrdp_listen* self)
{
- struct xrdp_listen* self;
int pid;
char text[256];
pid = g_getpid();
- self = (struct xrdp_listen*)g_malloc(sizeof(struct xrdp_listen), 1);
g_snprintf(text, 255, "xrdp_%8.8x_listen_pro_done_event", pid);
self->pro_done_event = g_create_wait_obj(text);
+ return 0;
+}
+
+/*****************************************************************************/
+struct xrdp_listen* APP_CC
+xrdp_listen_create(void)
+{
+ struct xrdp_listen* self;
+
+ self = (struct xrdp_listen*)g_malloc(sizeof(struct xrdp_listen), 1);
+ xrdp_listen_create_pro_done(self);
self->process_list = list_create();
if (g_process_sem == 0)
{
@@ -165,6 +174,17 @@ xrdp_listen_get_port_address(char* port, int port_bytes,
val = (char*)list_get_item(values, index);
g_strncpy(address, val, address_bytes - 1);
}
+ if (g_strcasecmp(val, "fork") == 0)
+ {
+ val = (char*)list_get_item(values, index);
+ if ((g_strcasecmp(val, "yes") == 0) ||
+ (g_strcasecmp(val, "on") == 0) ||
+ (g_strcasecmp(val, "true") == 0) ||
+ (g_atoi(val) != 0))
+ {
+ startup_param->fork = 1;
+ }
+ }
}
}
}
@@ -181,6 +201,41 @@ xrdp_listen_get_port_address(char* port, int port_bytes,
}
/*****************************************************************************/
+static int APP_CC
+xrdp_listen_fork(struct xrdp_listen* self, struct trans* server_trans)
+{
+ int pid;
+ struct xrdp_process* process;
+
+ pid = g_fork();
+ if (pid == 0)
+ {
+ /* child */
+ /* recreate some main globals */
+ xrdp_child_fork();
+ /* recreate the process done wait object, not used in fork mode */
+ /* close, don't delete this */
+ g_close_wait_obj(self->pro_done_event);
+ xrdp_listen_create_pro_done(self);
+ /* delete listener, child need not listen */
+ trans_delete(self->listen_trans);
+ self->listen_trans = 0;
+ /* new connect instance */
+ process = xrdp_process_create(self, 0);
+ process->server_trans = server_trans;
+ g_process = process;
+ xrdp_process_run(0);
+ xrdp_process_delete(process);
+ /* mark this process to exit */
+ g_set_term(1);
+ return 0;
+ }
+ /* parent */
+ trans_delete(server_trans);
+ return 0;
+}
+
+/*****************************************************************************/
/* a new connection is coming in */
int DEFAULT_CC
xrdp_listen_conn_in(struct trans* self, struct trans* new_self)
@@ -189,6 +244,10 @@ xrdp_listen_conn_in(struct trans* self, struct trans* new_self)
struct xrdp_listen* lis;
lis = (struct xrdp_listen*)(self->callback_data);
+ if (lis->startup_params->fork)
+ {
+ return xrdp_listen_fork(lis, new_self);
+ }
process = xrdp_process_create(lis, lis->pro_done_event);
if (xrdp_listen_add_pro(lis, process) == 0)
{
@@ -208,8 +267,7 @@ xrdp_listen_conn_in(struct trans* self, struct trans* new_self)
/*****************************************************************************/
/* wait for incoming connections */
int APP_CC
-xrdp_listen_main_loop(struct xrdp_listen* self,
- struct xrdp_startup_params* startup_param)
+xrdp_listen_main_loop(struct xrdp_listen* self)
{
int error;
int robjs_count;
@@ -226,7 +284,7 @@ xrdp_listen_main_loop(struct xrdp_listen* self,
self->status = 1;
if (xrdp_listen_get_port_address(port, sizeof(port),
address, sizeof(address),
- startup_param) != 0)
+ self->startup_params) != 0)
{
g_writeln("xrdp_listen_main_loop: xrdp_listen_get_port failed");
self->status = -1;
@@ -276,7 +334,7 @@ xrdp_listen_main_loop(struct xrdp_listen* self,
}
if (trans_check_wait_objs(self->listen_trans) != 0)
{
- break;
+ break;
}
}
/* stop listening */
diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c
index 905db928..df69d057 100644
--- a/xrdp/xrdp_process.c
+++ b/xrdp/xrdp_process.c
@@ -187,6 +187,10 @@ xrdp_process_main_loop(struct xrdp_process* self)
}
libxrdp_disconnect(self->session);
}
+ else
+ {
+ g_writeln("xrdp_process_main_loop: libxrdp_process_incomming failed");
+ }
xrdp_process_mod_end(self);
libxrdp_exit(self->session);
self->session = 0;
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index ce646a66..0366fd83 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -310,6 +310,7 @@ struct xrdp_listen
struct trans* listen_trans; /* in tcp listen mode */
struct list* process_list;
tbus pro_done_event;
+ struct xrdp_startup_params* startup_params;
};
/* region */
@@ -395,12 +396,12 @@ struct xrdp_bitmap
#define DEFAULT_ELEMENT_TOP 35
#define DEFAULT_BUTTON_W 60
#define DEFAULT_BUTTON_H 23
-#define DEFAULT_COMBO_W 140
+#define DEFAULT_COMBO_W 210
#define DEFAULT_COMBO_H 21
-#define DEFAULT_EDIT_W 140
+#define DEFAULT_EDIT_W 210
#define DEFAULT_EDIT_H 21
-#define DEFAULT_WND_LOGIN_W 400
-#define DEFAULT_WND_LOGIN_H 200
+#define DEFAULT_WND_LOGIN_W 500
+#define DEFAULT_WND_LOGIN_H 250
#define DEFAULT_WND_HELP_W 340
#define DEFAULT_WND_HELP_H 300
#define DEFAULT_WND_LOG_W 400
@@ -431,4 +432,5 @@ struct xrdp_startup_params
int no_daemon;
int help;
int version;
+ int fork;
};