diff options
-rw-r--r-- | common/os_calls.c | 82 | ||||
-rw-r--r-- | common/os_calls.h | 6 | ||||
-rw-r--r-- | configure.ac | 19 | ||||
-rw-r--r-- | freerdp1/xrdp-freerdp.c | 45 | ||||
-rw-r--r-- | instfiles/Makefile.am | 10 | ||||
-rw-r--r-- | instfiles/xrdp-sesman.service | 14 | ||||
-rw-r--r-- | instfiles/xrdp.service | 14 | ||||
-rw-r--r-- | libxrdp/xrdp_rdp.c | 5 | ||||
-rw-r--r-- | sesman/chansrv/Makefile.am | 22 | ||||
-rw-r--r-- | sesman/chansrv/sound.c | 529 | ||||
-rw-r--r-- | sesman/chansrv/sound.h | 91 | ||||
-rw-r--r-- | xorg/X11R7.6/rdp/rdp.h | 15 | ||||
-rw-r--r-- | xorg/X11R7.6/rdp/rdpdraw.c | 87 | ||||
-rw-r--r-- | xorg/X11R7.6/rdp/rdpmain.c | 10 | ||||
-rw-r--r-- | xrdp/xrdp.c | 77 | ||||
-rw-r--r-- | xrdp/xrdp.h | 5 | ||||
-rw-r--r-- | xrdp/xrdp.ini | 1 | ||||
-rw-r--r-- | xrdp/xrdp_listen.c | 74 | ||||
-rw-r--r-- | xrdp/xrdp_process.c | 4 | ||||
-rw-r--r-- | xrdp/xrdp_types.h | 10 |
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; }; |