diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-08-20 00:29:09 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-08-20 00:29:09 -0500 |
commit | 57029de2707808c3e7d12568af3de87eaca71828 (patch) | |
tree | 0dd7aca471ffddede7d6ec8d54d075e515a9ca9e /sesman | |
parent | b62256d54dd71705a29da49bc8ee62d6ebd95230 (diff) | |
parent | c5862f367ca68763dd3070598a36ea82db7f3566 (diff) | |
download | xrdp-proprietary-57029de2707808c3e7d12568af3de87eaca71828.tar.gz xrdp-proprietary-57029de2707808c3e7d12568af3de87eaca71828.zip |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'sesman')
46 files changed, 3253 insertions, 787 deletions
diff --git a/sesman/access.c b/sesman/access.c index f4bfd30a..0037de3f 100644 --- a/sesman/access.c +++ b/sesman/access.c @@ -38,33 +38,33 @@ access_login_allowed(char* user) if ((0 == g_strncmp(user, "root", 5)) && (0 == g_cfg->sec.allow_root)) { - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "ROOT login attempted, but root login is disabled"); return 0; } if (0 == g_cfg->sec.ts_users_enable) { - LOG_DBG(&(g_cfg->log), "Terminal Server Users group is disabled, allowing authentication", + LOG_DBG("Terminal Server Users group is disabled, allowing authentication", 1); return 1; } if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "Cannot read user info! - login denied"); + log_message(LOG_LEVEL_ERROR, "Cannot read user info! - login denied"); return 0; } if (g_cfg->sec.ts_users == gid) { - LOG_DBG(&(g_cfg->log), "ts_users is user's primary group"); + LOG_DBG("ts_users is user's primary group"); return 1; } if (0 != g_check_user_in_group(user, g_cfg->sec.ts_users, &ok)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "Cannot read group info! - login denied"); + log_message(LOG_LEVEL_ERROR, "Cannot read group info! - login denied"); return 0; } @@ -73,7 +73,7 @@ access_login_allowed(char* user) return 1; } - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "login denied for user %s", user); + log_message(LOG_LEVEL_INFO, "login denied for user %s", user); return 0; } @@ -87,33 +87,33 @@ access_login_mng_allowed(char* user) if ((0 == g_strncmp(user, "root", 5)) && (0 == g_cfg->sec.allow_root)) { - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "[MNG] ROOT login attempted, but root login is disabled"); return 0; } if (0 == g_cfg->sec.ts_admins_enable) { - LOG_DBG(&(g_cfg->log), "[MNG] Terminal Server Admin group is disabled, allowing authentication", - 1); + LOG_DBG("[MNG] Terminal Server Admin group is disabled," + "allowing authentication",1); return 1; } if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "[MNG] Cannot read user info! - login denied"); + log_message(LOG_LEVEL_ERROR, "[MNG] Cannot read user info! - login denied"); return 0; } if (g_cfg->sec.ts_admins == gid) { - LOG_DBG(&(g_cfg->log), "[MNG] ts_users is user's primary group"); + LOG_DBG("[MNG] ts_users is user's primary group"); return 1; } if (0 != g_check_user_in_group(user, g_cfg->sec.ts_admins, &ok)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "[MNG] Cannot read group info! - login denied"); + log_message(LOG_LEVEL_ERROR, "[MNG] Cannot read group info! - login denied"); return 0; } @@ -122,7 +122,7 @@ access_login_mng_allowed(char* user) return 1; } - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "[MNG] login denied for user %s", user); + log_message(LOG_LEVEL_INFO, "[MNG] login denied for user %s", user); return 0; } diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 486d49a8..9d52d950 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -1,10 +1,21 @@ 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 \ @@ -17,7 +28,12 @@ xrdp_chansrv_SOURCES = \ chansrv.c \ sound.c \ clipboard.c \ - devredir.c + devredir.c \ + rail.c \ + xcommon.c + +xrdp_chansrv_LDFLAGS = \ + $(EXTRA_FLAGS) xrdp_chansrv_LDADD = \ -L/usr/X11R6/lib \ diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index eb892100..c7917d03 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -1,21 +1,20 @@ -/* - 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 -*/ +/** + * 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 "arch.h" #include "os_calls.h" @@ -29,16 +28,22 @@ #include "list.h" #include "file.h" #include "file_loc.h" +#include "log.h" +#include "rail.h" +#include "xcommon.h" #include "libraptorsmiface.h" static struct trans* g_lis_trans = 0; static struct trans* g_con_trans = 0; +static struct trans* g_api_lis_trans = 0; +static struct trans* g_api_con_trans = 0; static struct chan_item g_chan_items[32]; static int g_num_chan_items = 0; static int g_cliprdr_index = -1; static int g_rdpsnd_index = -1; static int g_rdpdr_index = -1; +static int g_rail_index = -1; static tbus g_term_event = 0; static tbus g_thread_done_event = 0; @@ -49,6 +54,21 @@ int g_display_num = 0; int g_cliprdr_chan_id = -1; /* cliprdr */ int g_rdpsnd_chan_id = -1; /* rdpsnd */ int g_rdpdr_chan_id = -1; /* rdpdr */ +int g_rail_chan_id = -1; /* rail */ + +char* g_exec_name; +tbus g_exec_event; +tbus g_exec_mutex; +tbus g_exec_sem; +int g_exec_pid = 0; + +/* data in struct trans::callback_data */ +struct xrdp_api_data +{ + int chan_id; + char header[64]; + int flags; +}; //#if 0 #include <stdio.h> @@ -77,55 +97,132 @@ void dprint(const char *fmt, ...) //#endif /*****************************************************************************/ +/* add data to chan_item, on its way to the client */ /* returns error */ -int APP_CC -send_channel_data(int chan_id, char* data, int size) +static int APP_CC +add_data_to_chan_item(struct chan_item* chan_item, char* data, int size) { - struct stream * s = (struct stream *)NULL; - int chan_flags = 0; - int total_size = 0; - int sent = 0; - int rv = 0; + struct stream* s; + struct chan_out_data* cod; + make_stream(s); + init_stream(s, size); + g_memcpy(s->data, data, size); + s->end = s->data + size; + cod = (struct chan_out_data*)g_malloc(sizeof(struct chan_out_data), 1); + cod->s = s; + if (chan_item->tail == 0) + { + chan_item->tail = cod; + chan_item->head = cod; + } + else + { + chan_item->tail->next = cod; + chan_item->tail = cod; + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int APP_CC +send_data_from_chan_item(struct chan_item* chan_item) +{ + struct stream* s; + struct chan_out_data* cod; + int bytes_left; + int size; + int chan_flags; + int error; + + if (chan_item->head == 0) + { + return 0; + } + cod = chan_item->head; + bytes_left = (int)(cod->s->end - cod->s->p); + size = MIN(1600, bytes_left); + chan_flags = 0; + if (cod->s->p == cod->s->data) + { + chan_flags |= 1; /* first */ + } + if (cod->s->p + size >= cod->s->end) + { + chan_flags |= 2; /* last */ + } s = trans_get_out_s(g_con_trans, 8192); - if (s == 0) + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ + out_uint32_le(s, 8); /* msg id */ + out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ + out_uint16_le(s, chan_item->id); + out_uint16_le(s, chan_flags); + out_uint16_le(s, size); + out_uint32_le(s, cod->s->size); + out_uint8a(s, cod->s->p, size); + s_mark_end(s); + LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- " + "size %d chan_flags 0x%8.8x", size, chan_flags)); + error = trans_force_write(g_con_trans); + if (error != 0) { return 1; } - rv = 0; - sent = 0; - total_size = size; - while (sent < total_size) + cod->s->p += size; + if (cod->s->p >= cod->s->end) { - size = MIN(1600, total_size - sent); - chan_flags = 0; - if (sent == 0) + free_stream(cod->s); + chan_item->head = chan_item->head->next; + if (chan_item->head == 0) { - chan_flags |= 1; /* first */ + chan_item->tail = 0; } - if (size + sent == total_size) + g_free(cod); + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int APP_CC +check_chan_items(void) +{ + int index; + + for (index = 0; index < g_num_chan_items; index++) + { + if (g_chan_items[index].head != 0) { - chan_flags |= 2; /* last */ + send_data_from_chan_item(g_chan_items + index); } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ - out_uint32_le(s, 8); /* msg id */ - out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ - out_uint16_le(s, chan_id); - out_uint16_le(s, chan_flags); - out_uint16_le(s, size); - out_uint32_le(s, total_size); - out_uint8a(s, data + sent, size); - s_mark_end(s); - rv = trans_force_write(g_con_trans); - if (rv != 0) + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +send_channel_data(int chan_id, char* data, int size) +{ + int index; + + LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: size %d", size)); + if (chan_id == -1) + { + return 1; + } + for (index = 0; index < g_num_chan_items; index++) + { + if (g_chan_items[index].id == chan_id) { - break; + add_data_to_chan_item(g_chan_items + index, data, size); + check_chan_items(); + return 0; } - sent += size; - s = trans_get_out_s(g_con_trans, 8192); } - return rv; + return 1; } /*****************************************************************************/ @@ -135,7 +232,7 @@ send_init_response_message(void) { struct stream * s = (struct stream *)NULL; - LOG(1, ("send_init_response_message:")); + LOGM((LOG_LEVEL_INFO, "send_init_response_message:")); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { @@ -157,7 +254,7 @@ send_channel_setup_response_message(void) { struct stream * s = (struct stream *)NULL; - LOG(10, ("send_channel_setup_response_message:")); + LOGM((LOG_LEVEL_DEBUG, "send_channel_setup_response_message:")); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { @@ -178,7 +275,7 @@ send_channel_data_response_message(void) { struct stream * s = (struct stream *)NULL; - LOG(10, ("send_channel_data_response_message:")); + LOGM((LOG_LEVEL_DEBUG, "send_channel_data_response_message:")); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { @@ -197,7 +294,7 @@ send_channel_data_response_message(void) static int APP_CC process_message_init(struct stream* s) { - LOG(10, ("process_message_init:")); + LOGM((LOG_LEVEL_DEBUG, "process_message_init:")); return send_init_response_message(); } @@ -206,21 +303,24 @@ process_message_init(struct stream* s) static int APP_CC process_message_channel_setup(struct stream* s) { - int num_chans = 0; - int index = 0; - int rv = 0; - struct chan_item* ci = (struct chan_item *)NULL; + int num_chans; + int index; + int rv; + struct chan_item* ci; g_num_chan_items = 0; g_cliprdr_index = -1; g_rdpsnd_index = -1; g_rdpdr_index = -1; + g_rail_index = -1; g_cliprdr_chan_id = -1; g_rdpsnd_chan_id = -1; g_rdpdr_chan_id = -1; - LOG(10, ("process_message_channel_setup:")); + g_rail_chan_id = -1; + LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup:")); in_uint16_le(s, num_chans); - LOG(10, ("process_message_channel_setup: num_chans %d", num_chans)); + LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: num_chans %d", + num_chans)); for (index = 0; index < num_chans; index++) { ci = &(g_chan_items[g_num_chan_items]); @@ -228,8 +328,8 @@ process_message_channel_setup(struct stream* s) in_uint8a(s, ci->name, 8); in_uint16_le(s, ci->id); in_uint16_le(s, ci->flags); - LOG(10, ("process_message_channel_setup: chan name '%s' " - "id %d flags %8.8x", ci->name, ci->id, ci->flags)); + LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: chan name '%s' " + "id %d flags %8.8x", ci->name, ci->id, ci->flags)); if (g_strcasecmp(ci->name, "cliprdr") == 0) { g_cliprdr_index = g_num_chan_items; @@ -245,6 +345,15 @@ process_message_channel_setup(struct stream* s) g_rdpdr_index = g_num_chan_items; g_rdpdr_chan_id = ci->id; } + else if (g_strcasecmp(ci->name, "rail") == 0) + { + g_rail_index = g_num_chan_items; + g_rail_chan_id = ci->id; + } + else + { + LOG(10, ("other %s", ci->name)); + } g_num_chan_items++; } rv = send_channel_setup_response_message(); @@ -275,13 +384,15 @@ process_message_channel_data(struct stream* s) int rv = 0; int length = 0; int total_length = 0; + struct stream* ls; in_uint16_le(s, chan_id); in_uint16_le(s, chan_flags); in_uint16_le(s, length); in_uint32_le(s, total_length); - LOG(10, ("process_message_channel_data: chan_id %d " - "chan_flags %d", chan_id, chan_flags)); + LOGM((LOG_LEVEL_DEBUG,"process_message_channel_data: chan_id %d " + "chan_flags %d", chan_id, chan_flags)); + LOG(10, ("process_message_channel_data")); rv = send_channel_data_response_message(); if (rv == 0) { @@ -297,6 +408,27 @@ process_message_channel_data(struct stream* s) { rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length); } + else if (chan_id == g_rail_chan_id) + { + rv = rail_data_in(s, chan_id, chan_flags, length, total_length); + } + else if (chan_id == ((struct xrdp_api_data*) + (g_api_con_trans->callback_data))->chan_id) + { + LOG(10, ("process_message_channel_data length %d total_length %d " + "chan_flags 0x%8.8x", length, total_length, chan_flags)); + ls = g_api_con_trans->out_s; + if (chan_flags & 1) /* first */ + { + init_stream(ls, total_length); + } + out_uint8a(ls, s->p, length); + if (chan_flags & 2) /* last */ + { + s_mark_end(ls); + trans_force_write(g_api_con_trans); + } + } } return rv; } @@ -307,6 +439,7 @@ static int APP_CC process_message_channel_data_response(struct stream* s) { LOG(10, ("process_message_channel_data_response:")); + check_chan_items(); return 0; } @@ -352,8 +485,8 @@ process_message(void) rv = process_message_channel_data_response(s); break; default: - LOG(0, ("process_message: error in process_message " - "unknown msg %d", id)); + LOGM((LOG_LEVEL_ERROR, "process_message: error in process_message ", + "unknown msg %d", id)); break; } if (rv != 0) @@ -361,9 +494,7 @@ process_message(void) LOG(0, ("process_message: error in process_message: rv %d", rv)); break; } - else { - s->p = next_msg; - } + s->p = next_msg; } return rv; } @@ -386,7 +517,7 @@ my_trans_data_in(struct trans* trans) { return 1; } - LOG(10, ("my_trans_data_in:")); + LOGM((LOG_LEVEL_DEBUG, "my_trans_data_in:")); s = trans_get_in_s(trans); in_uint32_le(s, id); in_uint32_le(s, size); @@ -400,6 +531,44 @@ my_trans_data_in(struct trans* trans) } /*****************************************************************************/ +/* returns error */ +int DEFAULT_CC +my_api_trans_data_in(struct trans* trans) +{ + struct stream* s; + int error; + struct xrdp_api_data* ad; + + LOG(10, ("my_api_trans_data_in:")); + if (trans == 0) + { + return 0; + } + if (trans != g_api_con_trans) + { + return 1; + } + LOGM((LOG_LEVEL_DEBUG, "my_api_trans_data_in:")); + s = trans_get_in_s(trans); + error = g_tcp_recv(trans->sck, s->data, 8192, 0); + if (error > 0) + { + LOG(10, ("my_api_trans_data_in: got data %d", error)); + ad = (struct xrdp_api_data*)(trans->callback_data); + if (send_channel_data(ad->chan_id, s->data, error) != 0) + { + LOG(0, ("my_api_trans_data_in: send_channel_data failed")); + } + } + else + { + LOG(10, ("my_api_trans_data_in: g_tcp_recv failed, or disconnected")); + return 1; + } + return 0; +} + +/*****************************************************************************/ int DEFAULT_CC my_trans_conn_in(struct trans* trans, struct trans* new_trans) { @@ -419,7 +588,7 @@ my_trans_conn_in(struct trans* trans, struct trans* new_trans) { return 1; } - LOG(10, ("my_trans_conn_in:")); + LOGM((LOG_LEVEL_DEBUG, "my_trans_conn_in:")); g_con_trans = new_trans; g_con_trans->trans_data_in = my_trans_data_in; g_con_trans->header_size = 8; @@ -430,6 +599,84 @@ my_trans_conn_in(struct trans* trans, struct trans* new_trans) } /*****************************************************************************/ +int DEFAULT_CC +my_api_trans_conn_in(struct trans* trans, struct trans* new_trans) +{ + struct xrdp_api_data* ad; + int error; + int index; + int found; + struct stream* s; + + if (trans == 0) + { + return 1; + } + if (trans != g_api_lis_trans) + { + return 1; + } + if (new_trans == 0) + { + return 1; + } + LOGM((LOG_LEVEL_DEBUG, "my_api_trans_conn_in:")); + + LOG(10, ("my_api_trans_conn_in: got incoming")); + + s = trans_get_in_s(new_trans); + s->end = s->data; + error = trans_force_read(new_trans, 64); + if (error != 0) + { + LOG(0, ("my_api_trans_conn_in: trans_force_read failed")); + trans_delete(new_trans); + } + s->end = s->data; + + ad = (struct xrdp_api_data*)g_malloc(sizeof(struct xrdp_api_data), 1); + + g_memcpy(ad->header, s->data, 64); + + ad->flags = GGET_UINT32(ad->header, 16); + + found = 0; + if (ad->flags | 1) /* WTS_CHANNEL_OPTION_DYNAMIC */ + { + /* TODO */ + found = 0; + } + else + { + for (index = 0; index < g_num_chan_items; index++) + { + LOG(10, (" %s %s", ad->header, g_chan_items[index].name)); + if (g_strcasecmp(ad->header, g_chan_items[index].name) == 0) + { + LOG(10, ("my_api_trans_conn_in: found it at %d", index)); + ad->chan_id = g_chan_items[index].id; + found = 1; + break; + } + } + } + LOG(10, ("my_api_trans_conn_in: found %d", found)); + if (!found) + { + ad->chan_id = -1; + } + + new_trans->callback_data = ad; + + trans_delete(g_api_con_trans); + g_api_con_trans = new_trans; + g_api_con_trans->trans_data_in = my_api_trans_data_in; + g_api_con_trans->header_size = 0; + + return 0; +} + +/*****************************************************************************/ static int APP_CC setup_listen(void) { @@ -443,7 +690,8 @@ setup_listen(void) if (g_use_unix_socket) { g_lis_trans = trans_create(2, 8192, 8192); - g_snprintf(port, 255, "/tmp/.xrdp/xrdp_chansrv_socket_%d", 7200 + g_display_num); + g_snprintf(port, 255, "/tmp/.xrdp/xrdp_chansrv_socket_%d", + 7200 + g_display_num); } else { @@ -454,7 +702,28 @@ setup_listen(void) error = trans_listen(g_lis_trans, port); if (error != 0) { - LOG(0, ("setup_listen: trans_listen failed for port %s", port)); + LOGM((LOG_LEVEL_ERROR, "setup_listen: trans_listen failed for port %s", + port)); + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +setup_api_listen(void) +{ + char port[256]; + int error = 0; + + g_api_lis_trans = trans_create(2, 8192, 8192); + g_snprintf(port, 255, "/tmp/.xrdp/xrdpapi_%d", g_display_num); + g_api_lis_trans->trans_conn_in = my_api_trans_conn_in; + error = trans_listen(g_api_lis_trans, port); + if (error != 0) + { + LOGM((LOG_LEVEL_ERROR, "setup_api_listen: trans_listen failed for port %s", + port)); return 1; } return 0; @@ -465,13 +734,14 @@ THREAD_RV THREAD_CC channel_thread_loop(void* in_val) { tbus objs[32]; - int num_objs = 0; - int timeout = 0; - int error = 0; - THREAD_RV rv = 0; + int num_objs; + int timeout; + int error; + THREAD_RV rv; - LOG(1, ("channel_thread_loop: thread start")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread start")); rv = 0; + setup_api_listen(); error = setup_listen(); if (error == 0) { @@ -479,33 +749,37 @@ channel_thread_loop(void* in_val) num_objs = 0; objs[num_objs] = g_term_event; num_objs++; - trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); + trans_get_wait_objs(g_lis_trans, objs, &num_objs); + trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { if (g_is_wait_obj_set(g_term_event)) { - LOG(0, ("channel_thread_loop: g_term_event set")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: g_term_event set")); clipboard_deinit(); sound_deinit(); dev_redir_deinit(); + rail_deinit(); break; } if (g_lis_trans != 0) { if (trans_check_wait_objs(g_lis_trans) != 0) { - LOG(0, ("channel_thread_loop: trans_check_wait_objs error")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: " + "trans_check_wait_objs error")); } } if (g_con_trans != 0) { if (trans_check_wait_objs(g_con_trans) != 0) { - LOG(0, ("channel_thread_loop: " - "trans_check_wait_objs error resetting")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: " + "trans_check_wait_objs error resetting")); clipboard_deinit(); sound_deinit(); dev_redir_deinit(); + rail_deinit(); /* delete g_con_trans */ trans_delete(g_con_trans); g_con_trans = 0; @@ -519,16 +793,40 @@ channel_thread_loop(void* in_val) } } } - clipboard_check_wait_objs(); + if (g_api_lis_trans != 0) + { + if (trans_check_wait_objs(g_api_lis_trans) != 0) + { + LOG(0, ("channel_thread_loop: trans_check_wait_objs failed")); + } + } + + LOG(10, ("0 %p", g_api_con_trans)); + if (g_api_con_trans != 0) + { + LOG(10, ("1 %p %d", g_api_con_trans, g_tcp_can_recv(g_api_con_trans->sck, 0))); + if (trans_check_wait_objs(g_api_con_trans) != 0) + { + LOG(10, ("channel_thread_loop: trans_check_wait_objs failed, " + "or disconnected")); + g_free(g_api_con_trans->callback_data); + trans_delete(g_api_con_trans); + g_api_con_trans = 0; + } + } + + xcommon_check_wait_objs(); sound_check_wait_objs(); dev_redir_check_wait_objs(); timeout = -1; num_objs = 0; objs[num_objs] = g_term_event; num_objs++; - trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); - trans_get_wait_objs(g_con_trans, objs, &num_objs, &timeout); - clipboard_get_wait_objs(objs, &num_objs, &timeout); + trans_get_wait_objs(g_lis_trans, objs, &num_objs); + trans_get_wait_objs(g_con_trans, objs, &num_objs); + trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); + trans_get_wait_objs(g_api_con_trans, objs, &num_objs); + xcommon_get_wait_objs(objs, &num_objs, &timeout); sound_get_wait_objs(objs, &num_objs, &timeout); dev_redir_get_wait_objs(objs, &num_objs, &timeout); } @@ -537,7 +835,11 @@ channel_thread_loop(void* in_val) g_lis_trans = 0; trans_delete(g_con_trans); g_con_trans = 0; - LOG(0, ("channel_thread_loop: thread stop")); + trans_delete(g_api_lis_trans); + g_api_lis_trans = 0; + trans_delete(g_api_con_trans); + g_api_con_trans = 0; + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread stop")); g_set_wait_obj(g_thread_done_event); return rv; } @@ -546,7 +848,7 @@ channel_thread_loop(void* in_val) void DEFAULT_CC term_signal_handler(int sig) { - LOG(1, ("term_signal_handler: got signal %d", sig)); + LOGM((LOG_LEVEL_INFO, "term_signal_handler: got signal %d", sig)); g_set_wait_obj(g_term_event); } @@ -554,26 +856,44 @@ term_signal_handler(int sig) void DEFAULT_CC nil_signal_handler(int sig) { - LOG(1, ("nil_signal_handler: got signal %d", sig)); - g_set_wait_obj(g_term_event); + LOGM((LOG_LEVEL_INFO, "nil_signal_handler: got signal %d", sig)); +} + +/*****************************************************************************/ +void DEFAULT_CC +child_signal_handler(int sig) +{ + int i1; + + LOG(10, ("child_signal_handler:")); + do + { + i1 = g_waitchild(); + if (i1 == g_exec_pid) + { + LOG(0, ("child_signal_handler: found pid %d", i1)); + //shutdownx(); + } + LOG(10, (" %d", i1)); + } while (i1 >= 0); } /*****************************************************************************/ static int APP_CC -get_display_num_from_display(char * display_text) +get_display_num_from_display(char* display_text) { - int index = 0; - int mode = 0; - int host_index = 0; - int disp_index = 0; - int scre_index = 0; - char host[256] = ""; - char disp[256] = ""; - char scre[256] = ""; - - g_memset(host,0,256); - g_memset(disp,0,256); - g_memset(scre,0,256); + int index; + int mode; + int host_index; + int disp_index; + int scre_index; + char host[256]; + char disp[256]; + char scre[256]; + + g_memset(host, 0, 256); + g_memset(disp, 0, 256); + g_memset(scre, 0, 256); index = 0; host_index = 0; @@ -620,6 +940,8 @@ main_cleanup(void) { g_delete_wait_obj(g_term_event); g_delete_wait_obj(g_thread_done_event); + g_delete_wait_obj(g_exec_event); + tc_mutex_delete(g_exec_mutex); g_deinit(); /* os_calls */ return 0; } @@ -628,15 +950,14 @@ main_cleanup(void) static int APP_CC read_ini(void) { - char filename[256] = ""; - struct list* names = (struct list *)NULL; - struct list* values = (struct list *)NULL; - char* name = (char *)NULL; - char* value = (char *)NULL; - int index = 0; - - g_memset(filename,0,(sizeof(char)*256)); + char filename[256]; + struct list* names; + struct list* values; + char* name; + char* value; + int index; + g_memset(filename,0,(sizeof(char) * 256)); names = list_create(); names->auto_free = 1; values = list_create(); @@ -666,51 +987,140 @@ read_ini(void) } /*****************************************************************************/ +static int APP_CC +run_exec(void) +{ + int pid; + + LOG(10, ("run_exec:")); + pid = g_fork(); + if (pid == 0) + { + trans_delete(g_con_trans); + g_close_wait_obj(g_term_event); + g_close_wait_obj(g_thread_done_event); + g_close_wait_obj(g_exec_event); + tc_mutex_delete(g_exec_mutex); + tc_sem_delete(g_exec_sem); + g_execlp3(g_exec_name, g_exec_name, 0); + g_exit(0); + } + g_exec_pid = pid; + tc_sem_inc(g_exec_sem); + + return 0; +} + +/*****************************************************************************/ int DEFAULT_CC main(int argc, char** argv) { + tbus waiters[4]; int pid = 0; - char text[256] = ""; - char* display_text = (char *)NULL; + char text[256]; + char* home_text; + char* display_text; + char log_file[256]; + enum logReturns error; + struct log_config logconfig; g_init("xrdp-chansrv"); /* os_calls */ + + home_text = g_getenv("HOME"); + if (home_text == 0) + { + g_writeln("error reading HOME environment variable"); + g_deinit(); + return 1; + } + read_ini(); pid = g_getpid(); - LOG(1, ("main: app started pid %d(0x%8.8x)", pid, pid)); + /* starting logging subsystem */ + g_memset(&logconfig, 0, sizeof(struct log_config)); + logconfig.program_name = "XRDP-Chansrv"; + g_snprintf(log_file, 255, "%s/xrdp-chansrv.log", home_text); + g_writeln("chansrv::main: using log file [%s]", log_file); + if (g_file_exist(log_file)) + { + g_file_delete(log_file); + } + logconfig.log_file = log_file; + logconfig.fd = -1; + logconfig.log_level = LOG_LEVEL_ERROR; + logconfig.enable_syslog = 0; + logconfig.syslog_level = 0; + error = log_start_from_param(&logconfig); + if (error != LOG_STARTUP_OK) + { + switch (error) + { + case LOG_ERROR_MALLOC: + g_writeln("error on malloc. cannot start logging. quitting."); + break; + case LOG_ERROR_FILE_OPEN: + g_writeln("error opening log file [%s]. quitting.", + getLogFile(text, 255)); + break; + default: + g_writeln("log_start error"); + break; + } + g_deinit(); + return 1; + } + LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid)); /* set up signal handler */ g_signal_kill(term_signal_handler); /* SIGKILL */ g_signal_terminate(term_signal_handler); /* SIGTERM */ g_signal_user_interrupt(term_signal_handler); /* SIGINT */ g_signal_pipe(nil_signal_handler); /* SIGPIPE */ + g_signal_child_stop(child_signal_handler); /* SIGCHLD */ display_text = g_getenv("DISPLAY"); - LOG(1, ("main: DISPLAY env var set to %s", display_text)); + LOGM((LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text)); get_display_num_from_display(display_text); if (g_display_num == 0) { - LOG(0, ("main: error, display is zero")); + LOGM((LOG_LEVEL_ERROR, "main: error, display is zero")); + g_deinit(); return 1; } - LOG(1, ("main: using DISPLAY %d", g_display_num)); + LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num)); g_snprintf(text, 255, "xrdp_chansrv_%8.8x_main_term", pid); g_term_event = g_create_wait_obj(text); g_snprintf(text, 255, "xrdp_chansrv_%8.8x_thread_done", pid); g_thread_done_event = g_create_wait_obj(text); + g_snprintf(text, 255, "xrdp_chansrv_%8.8x_exec", pid); + g_exec_event = g_create_wait_obj(text); + g_exec_mutex = tc_mutex_create(); + g_exec_sem = tc_sem_create(0); tc_thread_create(channel_thread_loop, 0); while (g_term_event > 0 && !g_is_wait_obj_set(g_term_event)) { - if (g_obj_wait(&g_term_event, 1, 0, 0, 0) != 0) + waiters[0] = g_term_event; + waiters[1] = g_exec_event; + if (g_obj_wait(waiters, 2, 0, 0, 0) != 0) + { + LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed")); + break; + } + if (g_is_wait_obj_set(g_term_event)) { - LOG(0, ("main: error, g_obj_wait failed")); break; } + if (g_is_wait_obj_set(g_exec_event)) + { + g_reset_wait_obj(g_exec_event); + run_exec(); + } } while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event)) { /* wait for thread to exit */ if (g_obj_wait(&g_thread_done_event, 1, 0, 0, 0) != 0) { - LOG(0, ("main: error, g_obj_wait failed")); + LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed")); break; } } @@ -718,7 +1128,7 @@ main(int argc, char** argv) raptor_sm_set_session_state(g_display_num, SM_STATUS_RUNNING); /* cleanup */ main_cleanup(); - LOG(1, ("main: app exiting pid %d(0x%8.8x)", pid, pid)); + LOGM((LOG_LEVEL_INFO, "main: app exiting pid %d(0x%8.8x)", pid, pid)); g_deinit(); return 0; } diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h index b265458f..ba593461 100644 --- a/sesman/chansrv/chansrv.h +++ b/sesman/chansrv/chansrv.h @@ -1,15 +1,41 @@ +/** + * 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(CHANSRV_H) #define CHANSRV_H #include "arch.h" #include "parse.h" +#include "log.h" + +struct chan_out_data +{ + struct stream* s; + struct chan_out_data* next; +}; struct chan_item { int id; int flags; char name[16]; + struct chan_out_data* head; + struct chan_out_data* tail; }; int APP_CC @@ -28,4 +54,25 @@ main_cleanup(void); } \ } +#define LOGM(_args) do { log_message _args ; } while (0) + +#ifndef GSET_UINT8 +#define GSET_UINT8(_ptr, _offset, _data) \ + *((unsigned char*) (((unsigned char*)(_ptr)) + (_offset))) = (unsigned char)(_data) +#define GGET_UINT8(_ptr, _offset) \ + (*((unsigned char*) (((unsigned char*)(_ptr)) + (_offset)))) +#define GSET_UINT16(_ptr, _offset, _data) \ + GSET_UINT8(_ptr, _offset, _data); \ + GSET_UINT8(_ptr, (_offset) + 1, (_data) >> 8) +#define GGET_UINT16(_ptr, _offset) \ + (GGET_UINT8(_ptr, _offset)) | \ + ((GGET_UINT8(_ptr, (_offset) + 1)) << 8) +#define GSET_UINT32(_ptr, _offset, _data) \ + GSET_UINT16(_ptr, _offset, _data); \ + GSET_UINT16(_ptr, (_offset) + 2, (_data) >> 16) +#define GGET_UINT32(_ptr, _offset) \ + (GGET_UINT16(_ptr, _offset)) | \ + ((GGET_UINT16(_ptr, (_offset) + 2)) << 16) +#endif + #endif diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index cf601a8e..3bea9704 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -1,25 +1,30 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * Copyright (C) Laxmikant Rashinkar 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. + */ /* - 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 - for help see http://tronche.com/gui/x/icccm/sec-2.html#s-2 .../kde/kdebase/workspace/klipper/clipboardpoll.cpp + Revision: + Aug 05, 2012: + Laxmikant Rashinkar (LK dot Rashinkar at gmail.com) + added clipboard support for BMP images */ #include <X11/Xlib.h> @@ -29,6 +34,29 @@ #include "parse.h" #include "os_calls.h" #include "chansrv.h" +#include "clipboard.h" +#include "xcommon.h" + +static char g_bmp_image_header[] = +{ + /* this is known to work */ + //0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* THIS IS BEING SENT BY WIN2008 */ + 0x42, 0x4d, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 +}; + +extern int g_cliprdr_chan_id; /* in chansrv.c */ + +extern Display* g_display; /* in xcommon.c */ +extern int g_x_socket; /* in xcommon.c */ +extern tbus g_x_wait_obj; /* in xcommon.c */ +extern Screen* g_screen; /* in xcommon.c */ +extern int g_screen_num; /* in xcommon.c */ + +int g_clip_up = 0; +int g_waiting_for_data_response = 0; +int g_waiting_for_data_response_time = 0; static Atom g_clipboard_atom = 0; static Atom g_clip_property_atom = 0; @@ -39,12 +67,9 @@ static Atom g_primary_atom = 0; static Atom g_secondary_atom = 0; static Atom g_get_time_atom = 0; static Atom g_utf8_atom = 0; -static int g_x_socket = 0; -static tbus g_x_wait_obj = 0; -static int g_clip_up = 0; +static Atom g_image_bmp_atom = 0; + static Window g_wnd = 0; -static Screen* g_screen = 0; -static int g_screen_num = 0; static int g_xfixes_event_base = 0; static int g_last_clip_size = 0; @@ -64,35 +89,20 @@ static int g_data_in_size = 0; static int g_data_in_time = 0; static int g_data_in_up_to_date = 0; static int g_got_format_announce = 0; -static int g_waiting_for_data_response = 0; -static int g_waiting_for_data_response_time = 0; -static Display* g_display = 0; +/* for image data */ +static int g_want_image_data = 0; +static XSelectionRequestEvent g_saved_selection_req_event; -extern int g_cliprdr_chan_id; /* in chansrv.c */ +/* for clipboard INCR transfers */ +static Atom g_incr_atom; +static Atom g_incr_atom_type; +static Atom g_incr_atom_target; +static char* g_incr_data = 0; +static int g_incr_data_size = 0; +static int g_incr_in_progress = 0; -/*****************************************************************************/ -int DEFAULT_CC -clipboard_error_handler(Display* dis, XErrorEvent* xer) -{ - char text[256]; - - XGetErrorText(dis, xer->error_code, text, 255); - LOG(1, ("error [%s]", text)); - return 0; -} - -/*****************************************************************************/ -/* The X server had an internal error. This is the last function called. - Do any cleanup that needs to be done on exit, like removing temporary files. - Don't worry about memory leaks */ -int DEFAULT_CC -clipboard_fatal_handler(Display* dis) -{ - LOG(1, ("fatal error, exiting")); - main_cleanup(); - return 0; -} +static int clipboard_format_id = CB_FORMAT_UNICODETEXT; /*****************************************************************************/ /* this is one way to get the current time from the x server */ @@ -100,10 +110,12 @@ static Time APP_CC clipboard_get_server_time(void) { XEvent xevent; + unsigned char no_text[4]; /* append nothing */ + no_text[0] = 0; XChangeProperty(g_display, g_wnd, g_get_time_atom, XA_STRING, 8, - PropModeAppend, "", 0); + PropModeAppend, no_text, 0); /* wait for PropertyNotify */ do { @@ -137,39 +149,20 @@ clipboard_init(void) int ver_min; Status st; - LOG(5, ("xrdp-chansrv: in clipboard_init")); + LOGM((LOG_LEVEL_DEBUG, "xrdp-chansrv: in clipboard_init")); if (g_clip_up) { return 0; } + xcommon_init(); clipboard_deinit(); rv = 0; - /* setting the error handlers can cause problem when shutting down - chansrv on some xlibs */ - //XSetErrorHandler(clipboard_error_handler); - //XSetIOErrorHandler(clipboard_fatal_handler); - g_display = XOpenDisplay(0); - if (g_display == 0) - { - LOG(0, ("clipboard_init: XOpenDisplay failed")); - rv = 1; - } - if (rv == 0) - { - g_x_socket = XConnectionNumber(g_display); - if (g_x_socket == 0) - { - LOG(0, ("clipboard_init: XConnectionNumber failed")); - rv = 2; - } - g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0); - } if (rv == 0) { g_clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False); if (g_clipboard_atom == None) { - LOG(0, ("clipboard_init: XInternAtom failed")); + LOGM((LOG_LEVEL_ERROR, "clipboard_init: XInternAtom failed")); rv = 3; } } @@ -177,17 +170,17 @@ clipboard_init(void) { if (!XFixesQueryExtension(g_display, &g_xfixes_event_base, &dummy)) { - LOG(0, ("clipboard_init: no xfixes")); + LOGM((LOG_LEVEL_ERROR, "clipboard_init: no xfixes")); rv = 5; } } if (rv == 0) { - LOG(0, ("clipboard_init: g_xfixes_event_base %d", g_xfixes_event_base)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_init: g_xfixes_event_base %d", + g_xfixes_event_base)); st = XFixesQueryVersion(g_display, &ver_maj, &ver_min); - LOG(0, ("clipboard_init st %d, maj %d min %d", st, ver_maj, ver_min)); - g_screen_num = DefaultScreen(g_display); - g_screen = ScreenOfDisplay(g_display, g_screen_num); + LOGM((LOG_LEVEL_DEBUG, "clipboard_init st %d, maj %d min %d", st, + ver_maj, ver_min)); g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM", False); g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM", @@ -198,6 +191,15 @@ clipboard_init(void) g_primary_atom = XInternAtom(g_display, "PRIMARY", False); g_secondary_atom = XInternAtom(g_display, "SECONDARY", False); g_utf8_atom = XInternAtom(g_display, "UTF8_STRING", False); + + g_image_bmp_atom = XInternAtom(g_display, "image/bmp", False); + g_incr_atom = XInternAtom(g_display, "INCR", False); + if (g_image_bmp_atom == None) + { + LOGM((LOG_LEVEL_ERROR, "clipboard_init: g_image_bmp_atom was " + "not allocated")); + } + g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, 4, 4, 0, 0, 0); input_mask = StructureNotifyMask | PropertyChangeMask; @@ -219,13 +221,13 @@ clipboard_init(void) out_uint32_le(s, 0); /* extra 4 bytes ? */ s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_init: data out, sending " - "CLIPRDR_CONNECT (clip_msg_id = 1)")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_init: data out, sending " + "CLIPRDR_CONNECT (clip_msg_id = 1)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); if (rv != 0) { - LOG(0, ("clipboard_init: send_channel_data failed " - "rv = %d", rv)); + LOGM((LOG_LEVEL_ERROR, "clipboard_init: send_channel_data failed " + "rv = %d", rv)); rv = 4; } free_stream(s); @@ -238,7 +240,7 @@ clipboard_init(void) } else { - LOG(0, ("xrdp-chansrv: clipboard_init: error on exit")); + LOGM((LOG_LEVEL_ERROR, "xrdp-chansrv: clipboard_init: error on exit")); } return rv; } @@ -247,27 +249,16 @@ clipboard_init(void) int APP_CC clipboard_deinit(void) { - if (g_x_wait_obj != 0) - { - g_delete_wait_obj_from_socket(g_x_wait_obj); - g_x_wait_obj = 0; - } if (g_wnd != 0) { XDestroyWindow(g_display, g_wnd); g_wnd = 0; } - g_x_socket = 0; g_free(g_last_clip_data); g_last_clip_data = 0; g_last_clip_size = 0; free_stream(g_ins); g_ins = 0; - if (g_display != 0) - { - XCloseDisplay(g_display); - g_display = 0; - } g_clip_up = 0; return 0; } @@ -279,12 +270,12 @@ clipboard_send_data_request(void) struct stream* s; int size; int rv; - int num_chars; - LOG(5, ("clipboard_send_data_request:")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_send_data_request:")); if (!g_got_format_announce) { - LOG(0, ("clipboard_send_data_request: error, no format announce")); + LOGM((LOG_LEVEL_ERROR, "clipboard_send_data_request: error, " + "no format announce")); return 0; } g_got_format_announce = 0; @@ -293,11 +284,11 @@ clipboard_send_data_request(void) out_uint16_le(s, 4); /* CLIPRDR_DATA_REQUEST */ out_uint16_le(s, 0); /* status */ out_uint32_le(s, 4); /* length */ - out_uint32_le(s, 0x0d); + out_uint32_le(s, clipboard_format_id); s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_data_request: data out, sending " - "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_data_request: data out, sending " + "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; @@ -319,16 +310,24 @@ clipboard_send_format_ack(void) out_uint32_le(s, 0); /* extra 4 bytes ? */ s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_format_ack: data out, sending " - "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_format_ack: data out, sending " + "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; } +static char windows_native_format[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /*****************************************************************************/ static int APP_CC -clipboard_send_format_announce(void) +clipboard_send_format_announce(tui32 format_id, char* format_name) { struct stream* s; int size; @@ -338,13 +337,13 @@ clipboard_send_format_announce(void) init_stream(s, 8192); out_uint16_le(s, 2); /* CLIPRDR_FORMAT_ANNOUNCE */ out_uint16_le(s, 0); /* status */ - out_uint32_le(s, 0x90); /* length */ - out_uint32_le(s, 0x0d); /* extra 4 bytes ? */ - out_uint8s(s, 0x90); + out_uint32_le(s, 4 + sizeof(windows_native_format)); /* length */ + out_uint32_le(s, format_id); + out_uint8p(s, windows_native_format, sizeof(windows_native_format)); s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_format_announce: data out, sending " - "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_format_announce: data out, sending " + "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; @@ -382,6 +381,39 @@ clipboard_out_unicode(struct stream* s, char* text, int num_chars) /*****************************************************************************/ static int APP_CC +clipboard_send_data_response_for_image(void) +{ + struct stream* s; + int size; + int rv; + + LOG(10, ("clipboard_send_data_response_for_image: g_last_clip_size %d\n", + g_last_clip_size)); + make_stream(s); + init_stream(s, 64 + g_last_clip_size); + out_uint16_le(s, 5); /* CLIPRDR_DATA_RESPONSE */ + out_uint16_le(s, 1); /* status */ + out_uint32_le(s, g_last_clip_size); /* length */ + /* insert image data */ + if (g_last_clip_type == g_image_bmp_atom) + { + /* do not insert first header */ + out_uint8p(s, g_last_clip_data + 14, g_last_clip_size - 14); + } + out_uint16_le(s, 0); /* nil for string */ + out_uint32_le(s, 0); + out_uint32_le(s, 0); + out_uint32_le(s, 0); + s_mark_end(s); + size = (int)(s->end - s->data); + /* HANGING HERE WHEN IMAGE DATA IS TOO BIG!!!! */ + rv = send_channel_data(g_cliprdr_chan_id, s->data, size); + free_stream(s); + return rv; +} + +/*****************************************************************************/ +static int APP_CC clipboard_send_data_response(void) { struct stream* s; @@ -393,12 +425,16 @@ clipboard_send_data_response(void) num_chars = 0; if (g_last_clip_data != 0) { + if (g_last_clip_type == g_image_bmp_atom) + { + return clipboard_send_data_response_for_image(); + } if ((g_last_clip_type == XA_STRING) || (g_last_clip_type == g_utf8_atom)) { num_chars = g_mbstowcs(0, g_last_clip_data, 0); if (num_chars < 0) { - LOG(0, ("clipboard_send_data_response: bad string")); + LOGM((LOG_LEVEL_ERROR, "clipboard_send_data_response: bad string")); num_chars = 0; } } @@ -412,16 +448,16 @@ clipboard_send_data_response(void) out_uint32_le(s, num_chars * 2 + 2); /* length */ if (clipboard_out_unicode(s, g_last_clip_data, num_chars) != num_chars * 2) { - LOG(0, ("clipboard_send_data_response: error " - "clipboard_out_unicode didn't write right number of bytes")); + LOGM((LOG_LEVEL_ERROR,"clipboard_send_data_response: error " + "clipboard_out_unicode didn't write right number of bytes")); } out_uint16_le(s, 0); /* nil for string */ out_uint32_le(s, 0); s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_data_response: data out, sending " - "CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d num_chars %d", - size, num_chars)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_data_response: data out, sending " + "CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d num_chars %d", + size, num_chars)); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; @@ -487,60 +523,134 @@ clipboard_refuse_selection(XSelectionRequestEvent* req) } /*****************************************************************************/ +/* sent by client or server when its local system clipboard is + updated with new clipboard data; contains Clipboard Format ID + and name pairs of new Clipboard Formats on the clipboard. */ static int APP_CC clipboard_process_format_announce(struct stream* s, int clip_msg_status, int clip_msg_len) { - Window owner; - - LOG(5, ("clipboard_process_format_announce: CLIPRDR_FORMAT_ANNOUNCE")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_process_format_announce: " + "CLIPRDR_FORMAT_ANNOUNCE")); //g_hexdump(s->p, s->end - s->p); clipboard_send_format_ack(); g_got_format_announce = 1; g_data_in_up_to_date = 0; if (clipboard_set_selection_owner() != 0) { - LOG(0, ("clipboard_process_format_announce: XSetSelectionOwner failed")); + LOGM((LOG_LEVEL_ERROR, "clipboard_process_format_announce: " + "XSetSelectionOwner failed")); } return 0; } /*****************************************************************************/ +/* response to CB_FORMAT_LIST; used to indicate whether + processing of the Format List PDU was successful */ static int APP_CC clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status, int clip_msg_len) { - LOG(5, ("clipboard_prcoess_format_ack: CLIPRDR_FORMAT_ACK")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_prcoess_format_ack: CLIPRDR_FORMAT_ACK")); //g_hexdump(s->p, s->end - s->p); return 0; } /*****************************************************************************/ +/* sent by recipient of CB_FORMAT_LIST; used to request data for one + of the formats that was listed in CB_FORMAT_LIST */ static int APP_CC clipboard_process_data_request(struct stream* s, int clip_msg_status, int clip_msg_len) { - LOG(5, ("clipboard_process_data_request: CLIPRDR_DATA_REQUEST")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_request: " + "CLIPRDR_DATA_REQUEST")); //g_hexdump(s->p, s->end - s->p); clipboard_send_data_response(); return 0; } /*****************************************************************************/ +/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether + processing of the CB_FORMAT_DATA_REQUEST was successful; if processing + was successful, CB_FORMAT_DATA_RESPONSE includes contents of requested + clipboard data. */ +static int APP_CC +clipboard_process_data_response_for_image(struct stream * s, + int clip_msg_status, + int clip_msg_len) +{ + XSelectionRequestEvent* lxev = &g_saved_selection_req_event; + char* cptr; + char cdata; + int len; + int index; + + LOGM((LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: " + "CLIPRDR_DATA_RESPONSE_FOR_IMAGE")); + g_waiting_for_data_response = 0; + len = (int)(s->end - s->p); + if (len < 1) + { + return 0; + } + if (g_last_clip_type == g_image_bmp_atom) + { + /* space for inserting bmp image header */ + len += 14; + cptr = (char*)g_malloc(len, 0); + if (cptr == 0) + { + return 0; + } + g_memcpy(cptr, g_bmp_image_header, 14); + index = 14; + } + else + { + return 0; + } + while (s_check(s)) + { + in_uint8(s, cdata); + cptr[index++] = cdata; + } + if (len >= 0) + { + g_data_in = cptr; + g_data_in_size = len; + g_data_in_time = clipboard_get_local_time(); + g_data_in_up_to_date = 1; + } + clipboard_provide_selection(lxev, lxev->target, 8, cptr, len); + return 0; +} + +/*****************************************************************************/ +/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether + processing of the CB_FORMAT_DATA_REQUEST was successful; if processing was + successful, CB_FORMAT_DATA_RESPONSE includes contents of requested + clipboard data. */ +/*****************************************************************************/ static int APP_CC clipboard_process_data_response(struct stream* s, int clip_msg_status, int clip_msg_len) { - XEvent xev; XSelectionRequestEvent* lxev; twchar* wtext; twchar wchr; int len; int index; - int wtext_size; int data_in_len; - LOG(5, ("clipboard_process_data_response: CLIPRDR_DATA_RESPONSE")); + if (g_want_image_data) + { + g_want_image_data = 0; + clipboard_process_data_response_for_image(s, clip_msg_status, clip_msg_len); + return 0; + } + LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_response: " + "CLIPRDR_DATA_RESPONSE")); g_waiting_for_data_response = 0; len = (int)(s->end - s->p); if (len < 1) @@ -580,7 +690,7 @@ clipboard_process_data_response(struct stream* s, int clip_msg_status, } g_data_in_size = len; g_wcstombs(g_data_in, wtext, len + 1); - g_data_in_time = clipboard_get_local_time(); + g_data_in_time = xcommon_get_local_time(); g_data_in_up_to_date = 1; } if (g_data_in != 0) @@ -591,8 +701,8 @@ clipboard_process_data_response(struct stream* s, int clip_msg_status, lxev = &(g_selection_request_event[index]); clipboard_provide_selection(lxev, lxev->target, 8, g_data_in, data_in_len); - LOG(5, ("clipboard_process_data_response: requestor %d data_in_len %d", - lxev->requestor, data_in_len)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_response: requestor %d " + "data_in_len %d", lxev->requestor, data_in_len)); } } g_selection_request_event_count = 0; @@ -641,24 +751,37 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, rv = 0; switch (clip_msg_id) { - case 2: /* CLIPRDR_FORMAT_ANNOUNCE */ + /* sent by client or server when its local system clipboard is */ + /* updated with new clipboard data; contains Clipboard Format ID */ + /* and name pairs of new Clipboard Formats on the clipboard. */ + case CB_FORMAT_LIST: /* CLIPRDR_FORMAT_ANNOUNCE */ rv = clipboard_process_format_announce(ls, clip_msg_status, clip_msg_len); break; - case 3: /* CLIPRDR_FORMAT_ACK */ + /* response to CB_FORMAT_LIST; used to indicate whether */ + /* processing of the Format List PDU was successful */ + case CB_FORMAT_LIST_RESPONSE: /* CLIPRDR_FORMAT_ACK */ rv = clipboard_prcoess_format_ack(ls, clip_msg_status, clip_msg_len); break; - case 4: /* CLIPRDR_DATA_REQUEST */ + /* sent by recipient of CB_FORMAT_LIST; used to request data for one */ + /* of the formats that was listed in CB_FORMAT_LIST */ + case CB_FORMAT_DATA_REQUEST: /* CLIPRDR_DATA_REQUEST */ rv = clipboard_process_data_request(ls, clip_msg_status, clip_msg_len); break; - case 5: /* CLIPRDR_DATA_RESPONSE */ + /* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */ + /* whether processing of the CB_FORMAT_DATA_REQUEST was */ + /* successful; if processing was successful, */ + /* CB_FORMAT_DATA_RESPONSE includes contents of requested */ + /* clipboard data. */ + case CB_FORMAT_DATA_RESPONSE: /* CLIPRDR_DATA_RESPONSE */ rv = clipboard_process_data_response(ls, clip_msg_status, clip_msg_len); break; default: - LOG(0, ("clipboard_data_in: unknown clip_msg_id %d", clip_msg_id)); + LOGM((LOG_LEVEL_ERROR, "clipboard_data_in: unknown clip_msg_id %d", + clip_msg_id)); break; } XFlush(g_display); @@ -668,7 +791,8 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, /*****************************************************************************/ /* this happens when a new app copies something to the clipboard 'CLIPBOARD' Atom - typedef struct { + typedef struct + { int type; unsigned long serial; Bool send_event; @@ -679,20 +803,20 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, Atom selection; Time timestamp; Time selection_timestamp; -} XFixesSelectionNotifyEvent; */ + } XFixesSelectionNotifyEvent; */ static int APP_CC clipboard_event_selection_owner_notify(XEvent* xevent) { XFixesSelectionNotifyEvent* lxevent; lxevent = (XFixesSelectionNotifyEvent*)xevent; - LOG(5, ("clipboard_event_selection_owner_notify: " - "window %d subtype %d owner %d g_wnd %d", - lxevent->window, lxevent->subtype, lxevent->owner, g_wnd)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_owner_notify: " + "window %d subtype %d owner %d g_wnd %d", + lxevent->window, lxevent->subtype, lxevent->owner, g_wnd)); if (lxevent->owner == g_wnd) { - LOG(5, ("clipboard_event_selection_owner_notify: skipping, " - "onwer == g_wnd")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_owner_notify: skipping, " + "onwer == g_wnd")); g_got_selection = 1; return 0; } @@ -721,12 +845,28 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, XGetWindowProperty(g_display, g_wnd, prop, 0, 0, 0, AnyPropertyType, <ype, &lfmt, &ln_items, &llen_after, &lxdata); - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } if (ltype == 0) { /* XGetWindowProperty failed */ return 1; } + + if (ltype == g_incr_atom) + { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR start")); + g_incr_in_progress = 1; + g_incr_atom_type = prop; + g_incr_data_size = 0; + g_free(g_incr_data); + g_incr_data = 0; + XDeleteProperty(g_display, g_wnd, prop); + return 0; + } + if (llen_after < 1) { /* no data, ok */ @@ -740,20 +880,29 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, if (ltype == 0) { /* XGetWindowProperty failed */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 1; } lxdata_size = (lfmt / 8) * ln_items; if (lxdata_size < 1) { /* should not happen */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 2; } if (llen_after > 0) { /* should not happen */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 3; } if (xdata != 0) @@ -761,7 +910,10 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, *xdata = (char*)g_malloc(lxdata_size, 0); g_memcpy(*xdata, lxdata, lxdata_size); } - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } if (xdata_size != 0) { *xdata_size = lxdata_size; @@ -807,34 +959,50 @@ clipboard_event_selection_notify(XEvent* xevent) int index; int convert_to_string; int convert_to_utf8; + int convert_to_bmp_image; int send_format_announce; int atom; - int* atoms; + Atom* atoms; Atom type; + tui32 format_id; + char format_name[32]; - LOG(5, ("clipboard_event_selection_notify:")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify:")); + data_size = 0; + n_items = 0; + fmt = 0; convert_to_string = 0; convert_to_utf8 = 0; + convert_to_bmp_image = 0; send_format_announce = 0; + format_id = 0; rv = 0; data = 0; type = 0; lxevent = (XSelectionEvent*)xevent; + g_memset(format_name, 0, 32); if (lxevent->property == None) { - LOG(0, ("clipboard_event_selection_notify: clip could " - "not be converted")); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: clip could " + "not be converted")); rv = 1; } if (rv == 0) { + /* we need this if the call below turns out to be a + clipboard INCR operation */ + if (!g_incr_in_progress) + { + g_incr_atom_target = lxevent->target; + } + rv = clipboard_get_window_property(lxevent->requestor, lxevent->property, &type, &fmt, &n_items, &data, &data_size); if (rv != 0) { - LOG(0, ("clipboard_event_selection_notify: " - "clipboard_get_window_property failed error %d", rv)); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: " + "clipboard_get_window_property failed error %d", rv)); } XDeleteProperty(g_display, lxevent->requestor, lxevent->property); } @@ -844,14 +1012,15 @@ clipboard_event_selection_notify(XEvent* xevent) { if (lxevent->target == g_targets_atom) { + /* on a 64 bit machine, actual_format_return of 32 implies long */ if ((type == XA_ATOM) && (fmt == 32)) { - atoms = (int*)data; + atoms = (Atom*)data; for (index = 0; index < n_items; index++) { atom = atoms[index]; - LOG(5, ("clipboard_event_selection_notify: %d %s %d", atom, - XGetAtomName(g_display, atom), XA_STRING)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify: %d %s %d", + atom, XGetAtomName(g_display, atom), XA_STRING)); if (atom == g_utf8_atom) { convert_to_utf8 = 1; @@ -860,47 +1029,71 @@ clipboard_event_selection_notify(XEvent* xevent) { convert_to_string = 1; } + else if (atom == g_image_bmp_atom) + { + convert_to_bmp_image = 1; + } } } else { - LOG(0, ("clipboard_event_selection_notify: error, target is " - "'TARGETS' and type[%d] or fmt[%d] not right, should be " - "type[%d], fmt[%d]", type, fmt, XA_ATOM, 32)); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: error, " + "target is 'TARGETS' and type[%d] or fmt[%d] not right, " + "should be type[%d], fmt[%d]", type, fmt, XA_ATOM, 32)); } } else if (lxevent->target == g_utf8_atom) { - LOG(5, ("clipboard_event_selection_notify: UTF8_STRING data_size %d", - data_size)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: UTF8_STRING " + "data_size %d", data_size)); g_free(g_last_clip_data); + g_last_clip_data = 0; g_last_clip_size = data_size; g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_type = g_utf8_atom; g_memcpy(g_last_clip_data, data, g_last_clip_size); g_last_clip_data[g_last_clip_size] = 0; send_format_announce = 1; + format_id = CB_FORMAT_UNICODETEXT; } else if (lxevent->target == XA_STRING) { - LOG(5, ("clipboard_event_selection_notify: XA_STRING data_size %d", - data_size)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: XA_STRING " + "data_size %d", data_size)); g_free(g_last_clip_data); + g_last_clip_data = 0; g_last_clip_size = data_size; g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_type = XA_STRING; g_memcpy(g_last_clip_data, data, g_last_clip_size); g_last_clip_data[g_last_clip_size] = 0; send_format_announce = 1; + format_id = CB_FORMAT_UNICODETEXT; + } + else if (lxevent->target == g_image_bmp_atom) + { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify: image/bmp " + "data_size %d", data_size)); + g_free(g_last_clip_data); + g_last_clip_data = 0; + g_last_clip_size = data_size; + g_last_clip_data = g_malloc(data_size, 0); + g_last_clip_type = g_image_bmp_atom; + g_memcpy(g_last_clip_data, data, data_size); + send_format_announce = 1; + format_id = CB_FORMAT_DIB; + g_strcpy(format_name, "image/bmp"); } else { - LOG(0, ("clipboard_event_selection_notify: unknown target")); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: " + "unknown target")); } } else { - LOG(0, ("clipboard_event_selection_notify: unknown selection")); + LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_notify: " + "unknown selection")); } } if (convert_to_utf8) @@ -913,9 +1106,14 @@ clipboard_event_selection_notify(XEvent* xevent) XConvertSelection(g_display, g_clipboard_atom, XA_STRING, g_clip_property_atom, g_wnd, lxevent->time); } + else if (convert_to_bmp_image) + { + XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom, + g_clip_property_atom, g_wnd, lxevent->time); + } if (send_format_announce) { - if (clipboard_send_format_announce() != 0) + if (clipboard_send_format_announce(format_id, format_name) != 0) { rv = 4; } @@ -939,12 +1137,17 @@ clipboard_event_selection_notify(XEvent* xevent) Atom property; Time time; } XSelectionRequestEvent; */ +/* + * When XGetWindowProperty and XChangeProperty talk about "format 32" it + * doesn't mean a 32bit value, but actually a long. So 32 means 4 bytes on + * a 32bit machine and 8 bytes on a 64 machine + */ static int APP_CC clipboard_event_selection_request(XEvent* xevent) { - XEvent xev; XSelectionRequestEvent* lxev; - tui32 ui32[8]; + XEvent xev; + Atom atom_buf[10]; Atom type; int fmt; int n_items; @@ -952,52 +1155,58 @@ clipboard_event_selection_request(XEvent* xevent) char* xdata; lxev = (XSelectionRequestEvent*)xevent; - LOG(5, ("clipboard_event_selection_request: g_wnd %d, " - ".requestor %d .owner %d .selection %d '%s' .target %d .property %d", - g_wnd, lxev->requestor, lxev->owner, lxev->selection, - XGetAtomName(g_display, lxev->selection), - lxev->target, lxev->property)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: g_wnd %d, " + ".requestor %d .owner %d .selection %d '%s' .target %d .property %d", + g_wnd, lxev->requestor, lxev->owner, lxev->selection, + XGetAtomName(g_display, lxev->selection), + lxev->target, lxev->property)); if (lxev->property == None) { - LOG(5, ("clipboard_event_selection_request: lxev->property is None")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "lxev->property is None")); } else if (lxev->target == g_targets_atom) { /* requestor is asking what the selection can be converted to */ - LOG(5, ("clipboard_event_selection_request: g_targets_atom")); - ui32[0] = g_targets_atom; - ui32[1] = g_timestamp_atom; - ui32[2] = g_multiple_atom; - ui32[3] = XA_STRING; - ui32[4] = g_utf8_atom; - return clipboard_provide_selection(lxev, XA_ATOM, 32, (char*)ui32, 5); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "g_targets_atom")); + atom_buf[0] = g_targets_atom; + atom_buf[1] = g_timestamp_atom; + atom_buf[2] = g_multiple_atom; + atom_buf[3] = XA_STRING; + atom_buf[4] = g_utf8_atom; + atom_buf[5] = g_image_bmp_atom; + return clipboard_provide_selection(lxev, XA_ATOM, 32, (char*)atom_buf, 6); } else if (lxev->target == g_timestamp_atom) { /* requestor is asking the time I got the selection */ - LOG(5, ("clipboard_event_selection_request: g_timestamp_atom")); - ui32[0] = g_selection_time; - return clipboard_provide_selection(lxev, XA_INTEGER, 32, (char*)ui32, 1); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "g_timestamp_atom")); + atom_buf[0] = g_selection_time; + return clipboard_provide_selection(lxev, XA_INTEGER, 32, (char*)atom_buf, 1); } else if (lxev->target == g_multiple_atom) { /* target, property pairs */ - LOG(5, ("clipboard_event_selection_request: g_multiple_atom")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "g_multiple_atom")); if (clipboard_get_window_property(xev.xselection.requestor, xev.xselection.property, &type, &fmt, &n_items, &xdata, &xdata_size) == 0) { - LOG(5, ("clipboard_event_selection_request: g_multiple_atom " - "n_items %d", n_items)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: g_multiple_atom " + "n_items %d", n_items)); /* todo */ g_free(xdata); } } else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom)) { - LOG(5, ("clipboard_event_selection_request: %s", - XGetAtomName(g_display, lxev->target))); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: %s", + XGetAtomName(g_display, lxev->target))); + clipboard_format_id = CB_FORMAT_UNICODETEXT; if (g_data_in_up_to_date) { return clipboard_provide_selection(lxev, lxev->target, 8, @@ -1005,7 +1214,8 @@ clipboard_event_selection_request(XEvent* xevent) } if (g_selection_request_event_count > 10) { - LOG(0, ("clipboard_event_selection_request: error, too many requests")); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_request: error, " + "too many requests")); } else { @@ -1015,16 +1225,28 @@ clipboard_event_selection_request(XEvent* xevent) { clipboard_send_data_request(); g_waiting_for_data_response = 1; - g_waiting_for_data_response_time = clipboard_get_local_time(); + g_waiting_for_data_response_time = xcommon_get_local_time(); } g_selection_request_event_count++; return 0; } } + else if (lxev->target == g_image_bmp_atom) + { + g_memcpy(&g_saved_selection_req_event, lxev, + sizeof(g_saved_selection_req_event)); + g_last_clip_type = g_image_bmp_atom; + g_want_image_data = 1; + clipboard_format_id = CB_FORMAT_DIB; + clipboard_send_data_request(); + g_waiting_for_data_response = 1; + g_waiting_for_data_response_time = clipboard_get_local_time(); + return 0; + } else { - LOG(0, ("clipboard_event_selection_request: unknown " - "target %s", XGetAtomName(g_display, lxev->target))); + LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_request: unknown " + "target %s", XGetAtomName(g_display, lxev->target))); } clipboard_refuse_selection(lxev); return 0; @@ -1045,7 +1267,7 @@ clipboard_event_selection_request(XEvent* xevent) static int APP_CC clipboard_event_selection_clear(XEvent* xevent) { - LOG(5, ("clipboard_event_selection_clear:")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_clear:")); return 0; } @@ -1064,92 +1286,132 @@ clipboard_event_selection_clear(XEvent* xevent) static int APP_CC clipboard_event_property_notify(XEvent* xevent) { + Atom actual_type_return; + int actual_format_return; + unsigned long nitems_returned; + unsigned long bytes_left; + unsigned char* data; + int rv; + int format_in_bytes; + int new_data_len; + char* cptr; + char format_name[32]; + LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d " ".state %d .atom %d", xevent->xproperty.window, xevent->xproperty.state, xevent->xproperty.atom)); - return 0; -} - -/*****************************************************************************/ -/* returns error - this is called to get any wait objects for the main loop - timeout can be nil */ -int APP_CC -clipboard_get_wait_objs(tbus* objs, int* count, int* timeout) -{ - int lcount; - - if ((!g_clip_up) || (objs == 0) || (count == 0)) + if (g_incr_in_progress && + (xevent->xproperty.atom == g_incr_atom_type) && + (xevent->xproperty.state == PropertyNewValue)) { - return 0; + rv = XGetWindowProperty(g_display, g_wnd, g_incr_atom_type, 0, 0, 0, + AnyPropertyType, &actual_type_return, &actual_format_return, + &nitems_returned, &bytes_left, (unsigned char **) &data); + if (data != 0) + { + XFree(data); + data = 0; + } + if (bytes_left <= 0) + { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR done")); + g_memset(format_name, 0, 32); + /* clipboard INCR cycle has completed */ + g_incr_in_progress = 0; + g_last_clip_size = g_incr_data_size; + g_last_clip_data = g_incr_data; + g_incr_data = 0; + g_last_clip_type = g_incr_atom_target; + if (g_incr_atom_target == g_image_bmp_atom) + { + g_snprintf(format_name, 31, "image/bmp"); + clipboard_send_format_announce(CB_FORMAT_DIB, format_name); + } + XDeleteProperty(g_display, g_wnd, g_incr_atom_type); + } + else + { + rv = XGetWindowProperty(g_display, g_wnd, g_incr_atom_type, 0, bytes_left, 0, + AnyPropertyType, &actual_type_return, &actual_format_return, + &nitems_returned, &bytes_left, (unsigned char **) &data); + + format_in_bytes = actual_format_return / 8; + if ((actual_format_return == 32) && (sizeof(long) == 8)) + { + /* on a 64 bit machine, actual_format_return of 32 implies long */ + format_in_bytes = 8; + } + new_data_len = nitems_returned * format_in_bytes; + cptr = (char*)g_malloc(g_incr_data_size + new_data_len, 0); + g_memcpy(cptr, g_incr_data, g_incr_data_size); + g_free(g_incr_data); + if (cptr == NULL) + { + g_incr_data = 0; + /* cannot add any more data */ + if (data != 0) + { + XFree(data); + } + XDeleteProperty(g_display, g_wnd, g_incr_atom_type); + return 0; + } + g_incr_data = cptr; + g_memcpy(g_incr_data + g_incr_data_size, data, new_data_len); + g_incr_data_size += new_data_len; + if (data) + { + XFree(data); + } + XDeleteProperty(g_display, g_wnd, g_incr_atom_type); + } } - lcount = *count; - objs[lcount] = g_x_wait_obj; - lcount++; - *count = lcount; return 0; } /*****************************************************************************/ +/* returns 0, event handled, 1 unhandled */ int APP_CC -clipboard_check_wait_objs(void) +clipboard_xevent(void* xevent) { - XEvent xevent; - int time_diff; + XEvent* lxevent; if (!g_clip_up) { - return 0; + return 1; } - if (g_is_wait_obj_set(g_x_wait_obj)) + lxevent = (XEvent*)xevent; + switch (lxevent->type) { - if (XPending(g_display) < 1) - { - /* something is wrong, should not get here */ - LOG(0, ("clipboard_check_wait_objs: sck closed")); - return 0; - } - if (g_waiting_for_data_response) - { - time_diff = clipboard_get_local_time() - - g_waiting_for_data_response_time; - if (time_diff > 1000) - { - LOG(0, ("clipboard_check_wait_objs: warning, waiting for " - "data response too long")); - } - } - while (XPending(g_display) > 0) - { - XNextEvent(g_display, &xevent); - switch (xevent.type) + case SelectionNotify: + clipboard_event_selection_notify(lxevent); + break; + case SelectionRequest: + clipboard_event_selection_request(lxevent); + break; + case SelectionClear: + clipboard_event_selection_clear(lxevent); + break; + case MappingNotify: + break; + case PropertyNotify: + clipboard_event_property_notify(lxevent); + break; + case UnmapNotify: + LOG(0, ("chansrv::clipboard_xevent: got UnmapNotify")); + break; + case ClientMessage: + LOG(0, ("chansrv::clipboard_xevent: got ClientMessage")); + break; + default: + if (lxevent->type == g_xfixes_event_base + + XFixesSetSelectionOwnerNotify) { - case SelectionNotify: - clipboard_event_selection_notify(&xevent); - break; - case SelectionRequest: - clipboard_event_selection_request(&xevent); - break; - case SelectionClear: - clipboard_event_selection_clear(&xevent); - break; - case MappingNotify: - break; - case PropertyNotify: - clipboard_event_property_notify(&xevent); - break; - default: - if (xevent.type == g_xfixes_event_base + - XFixesSetSelectionOwnerNotify) - { - clipboard_event_selection_owner_notify(&xevent); - break; - } - LOG(0, ("clipboard_check_wait_objs unknown type %d", - xevent.type)); - break; + clipboard_event_selection_owner_notify(lxevent); + break; } - } + /* we didn't handle this message */ + return 1; } return 0; } diff --git a/sesman/chansrv/clipboard.h b/sesman/chansrv/clipboard.h index d6c74403..2fe1d194 100644 --- a/sesman/chansrv/clipboard.h +++ b/sesman/chansrv/clipboard.h @@ -1,3 +1,21 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * Copyright (C) Laxmikant Rashinkar 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(CLIPBOARD_H) #define CLIPBOARD_H @@ -5,6 +23,22 @@ #include "arch.h" #include "parse.h" +#define CB_FORMAT_LIST 2 +#define CB_FORMAT_LIST_RESPONSE 3 +#define CB_FORMAT_DATA_REQUEST 4 +#define CB_FORMAT_DATA_RESPONSE 5 + +/* Clipboard Formats */ + +#define CB_FORMAT_RAW 0x0000 +#define CB_FORMAT_TEXT 0x0001 +#define CB_FORMAT_DIB 0x0008 +#define CB_FORMAT_UNICODETEXT 0x000D +#define CB_FORMAT_HTML 0xD010 +#define CB_FORMAT_PNG 0xD011 +#define CB_FORMAT_JPEG 0xD012 +#define CB_FORMAT_GIF 0xD013 + int APP_CC clipboard_init(void); int APP_CC @@ -13,8 +47,6 @@ int APP_CC clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, int total_length); int APP_CC -clipboard_get_wait_objs(tbus* objs, int* count, int* timeout); -int APP_CC -clipboard_check_wait_objs(void); +clipboard_xevent(void* xevent); #endif diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 8e660a49..dd244572 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -1,21 +1,20 @@ -/* - 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 -*/ +/** + * 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 "arch.h" #include "parse.h" diff --git a/sesman/chansrv/devredir.h b/sesman/chansrv/devredir.h index e0279093..3ec08a51 100644 --- a/sesman/chansrv/devredir.h +++ b/sesman/chansrv/devredir.h @@ -1,3 +1,20 @@ +/** + * 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(DEVREDIR_H) #define DEVREDIR_H diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c new file mode 100644 index 00000000..6b47f867 --- /dev/null +++ b/sesman/chansrv/rail.c @@ -0,0 +1,677 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 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. + */ + +/* + window manager info + http://www.freedesktop.org/wiki/Specifications/wm-spec +*/ + +#include <X11/Xlib.h> +#include "chansrv.h" +#include "rail.h" +#include "xcommon.h" +#include "log.h" +#include "os_calls.h" +#include "thread_calls.h" + +extern int g_rail_chan_id; /* in chansrv.c */ +extern int g_display_num; /* in chansrv.c */ +extern char* g_exec_name; /* in chansrv.c */ +extern tbus g_exec_event; /* in chansrv.c */ +extern tbus g_exec_mutex; /* in chansrv.c */ +extern tbus g_exec_sem; /* in chansrv.c */ + +extern Display* g_display; /* in xcommon.c */ +extern Screen* g_screen; /* in xcommon.c */ +extern Window g_root_window; /* in xcommon.c */ +extern Atom g_wm_delete_window_atom; /* in xcommon.c */ +extern Atom g_wm_protocols_atom; /* in xcommon.c */ + +int g_rail_up = 0; + +/* for rail_is_another_wm_running */ +static int g_rail_running = 1; + +/* Indicates a Client Execute PDU from client to server. */ +#define TS_RAIL_ORDER_EXEC 0x0001 +/* Indicates a Client Activate PDU from client to server. */ +#define TS_RAIL_ORDER_ACTIVATE 0x0002 +/* Indicates a Client System Parameters Update PDU from client + to server or a Server System Parameters Update PDU + from server to client. */ +#define TS_RAIL_ORDER_SYSPARAM 0x0003 +/* Indicates a Client System Command PDU from client to server. */ +#define TS_RAIL_ORDER_SYSCOMMAND 0x0004 +/* Indicates a bi-directional Handshake PDU. */ +#define TS_RAIL_ORDER_HANDSHAKE 0x0005 +/* Indicates a Client Notify Event PDU from client to server. */ +#define TS_RAIL_ORDER_NOTIFY_EVENT 0x0006 +/* Indicates a Client Window Move PDU from client to server. */ +#define TS_RAIL_ORDER_WINDOWMOVE 0x0008 +/* Indicates a Server Move/Size Start PDU and a Server Move/Size + End PDU from server to client. */ +#define TS_RAIL_ORDER_LOCALMOVESIZE 0x0009 +/* Indicates a Server Min Max Info PDU from server to client. */ +#define TS_RAIL_ORDER_MINMAXINFO 0x000a +/* Indicates a Client Information PDU from client to server. */ +#define TS_RAIL_ORDER_CLIENTSTATUS 0x000b +/* Indicates a Client System Menu PDU from client to server. */ +#define TS_RAIL_ORDER_SYSMENU 0x000c +/* Indicates a Server Language Bar Information PDU from server to + client, or a Client Language Bar Information PDU from client to server. */ +#define TS_RAIL_ORDER_LANGBARINFO 0x000d +/* Indicates a Server Execute Result PDU from server to client. */ +#define TS_RAIL_ORDER_EXEC_RESULT 0x0080 +/* Indicates a Client Get Application ID PDU from client to server. */ +#define TS_RAIL_ORDER_GET_APPID_REQ 0x000E +/* Indicates a Server Get Application ID Response PDU from + server to client. */ +#define TS_RAIL_ORDER_GET_APPID_RESP 0x000F + +/* Resize the window. */ +#define SC_SIZE 0xF000 +/* Move the window. */ +#define SC_MOVE 0xF010 +/* Minimize the window. */ +#define SC_MINIMIZE 0xF020 +/* Maximize the window. */ +#define SC_MAXIMIZE 0xF030 +/* Close the window. */ +#define SC_CLOSE 0xF060 +/* The ALT + SPACE key combination was pressed; display + the window's system menu. */ +#define SC_KEYMENU 0xF100 +/* Restore the window to its original shape and size. */ +#define SC_RESTORE 0xF120 +/* Perform the default action of the window's system menu. */ +#define SC_DEFAULT 0xF160 + +/******************************************************************************/ +static int APP_CC +is_window_valid_child_of_root(unsigned int window_id) +{ + int found; + unsigned int i; + unsigned int nchild; + Window r; + Window p; + Window* children; + + found = 0; + XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild); + for (i = 0; i < nchild; i++) + { + if (window_id == children[i]) + { + found = 1; + break; + } + } + XFree(children); + return found; +} + +/*****************************************************************************/ +static int APP_CC +rail_send_init(void) +{ + struct stream* s; + int bytes; + char* size_ptr; + + LOG(10, ("chansrv::rail_send_init:")); + make_stream(s); + init_stream(s, 8182); + out_uint16_le(s, TS_RAIL_ORDER_HANDSHAKE); + size_ptr = s->p; + out_uint16_le(s, 0); /* size, set later */ + out_uint32_le(s, 1); /* build number */ + 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_rail_chan_id, s->data, bytes); + free_stream(s); + return 0; +} + +/******************************************************************************/ +static int DEFAULT_CC +anotherWMRunning(Display* display, XErrorEvent* xe) +{ + g_rail_running = 0; + return -1; +} + +/******************************************************************************/ +static int APP_CC +rail_is_another_wm_running(void) +{ + XErrorHandler old; + + g_rail_running = 1; + old = XSetErrorHandler((XErrorHandler)anotherWMRunning); + XSelectInput(g_display, g_root_window, + PropertyChangeMask | StructureNotifyMask | + SubstructureRedirectMask | ButtonPressMask | + SubstructureNotifyMask | FocusChangeMask | + EnterWindowMask | LeaveWindowMask); + XSync(g_display, 0); + XSetErrorHandler((XErrorHandler)old); + g_rail_up = g_rail_running; + if (!g_rail_up) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +int APP_CC +rail_init(void) +{ + LOG(10, ("chansrv::rail_init:")); + xcommon_init(); + if (rail_is_another_wm_running()) + { + log_message(LOG_LEVEL_ERROR, "rail_init: another window manager " + "is running"); + } + rail_send_init(); + g_rail_up = 1; + return 0; +} + +/*****************************************************************************/ +int APP_CC +rail_deinit(void) +{ + if (g_rail_up) + { + /* no longer window manager */ + XSelectInput(g_display, g_root_window, 0); + g_rail_up = 0; + } + return 0; +} + +/*****************************************************************************/ +static char* APP_CC +read_uni(struct stream* s, int num_chars) +{ + twchar* rchrs; + char* rv; + int index; + int lchars; + + rchrs = 0; + rv = 0; + if (num_chars > 0) + { + rchrs = (twchar*)g_malloc((num_chars + 1) * sizeof(twchar), 0); + for (index = 0; index < num_chars; index++) + { + in_uint16_le(s, rchrs[index]); + } + rchrs[num_chars] = 0; + lchars = g_wcstombs(0, rchrs, 0); + if (lchars > 0) + { + rv = (char*)g_malloc((lchars + 1) * 4, 0); + g_wcstombs(rv, rchrs, lchars); + rv[lchars] = 0; + } + } + g_free(rchrs); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_exec(struct stream* s, int size) +{ + int pid; + int flags; + int ExeOrFileLength; + int WorkingDirLength; + int ArgumentsLen; + char* ExeOrFile; + char* WorkingDir; + char* Arguments; + + LOG(0, ("chansrv::rail_process_exec:")); + in_uint16_le(s, flags); + in_uint16_le(s, ExeOrFileLength); + in_uint16_le(s, WorkingDirLength); + in_uint16_le(s, ArgumentsLen); + ExeOrFile = read_uni(s, ExeOrFileLength); + WorkingDir = read_uni(s, WorkingDirLength); + Arguments = read_uni(s, ArgumentsLen); + LOG(10, (" flags 0x%8.8x ExeOrFileLength %d WorkingDirLength %d " + "ArgumentsLen %d ExeOrFile [%s] WorkingDir [%s] " + "Arguments [%s]", flags, ExeOrFileLength, WorkingDirLength, + ArgumentsLen, ExeOrFile, WorkingDir, Arguments)); + if (g_strlen(ExeOrFile) > 0) + { + LOG(10, ("rail_process_exec: pre")); + /* ask main thread to fork */ + tc_mutex_lock(g_exec_mutex); + g_exec_name = ExeOrFile; + g_set_wait_obj(g_exec_event); + tc_sem_dec(g_exec_sem); + tc_mutex_unlock(g_exec_mutex); + LOG(10, ("rail_process_exec: post")); + } + g_free(ExeOrFile); + g_free(WorkingDir); + g_free(Arguments); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_activate(struct stream* s, int size) +{ + int window_id; + int enabled; + + LOG(10, ("chansrv::rail_process_activate:")); + in_uint32_le(s, window_id); + in_uint8(s, enabled); + LOG(10, (" window_id 0x%8.8x enabled %d", window_id, enabled)); + if (enabled) + { + LOG(10, ("chansrv::rail_process_activate: calling XRaiseWindow 0x%8.8x", window_id)); + XRaiseWindow(g_display, window_id); + LOG(10, ("chansrv::rail_process_activate: calling XSetInputFocus 0x%8.8x", window_id)); + XSetInputFocus(g_display, window_id, RevertToParent, CurrentTime); + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_system_param(struct stream* s, int size) +{ + int system_param; + + LOG(10, ("chansrv::rail_process_system_param:")); + in_uint32_le(s, system_param); + LOG(10, (" system_param 0x%8.8x", system_param)); + return 0; +} + +/******************************************************************************/ +static int APP_CC +rail_close_window(int window_id) +{ + XEvent ce; + + LOG(0, ("chansrv::rail_close_window:")); + g_memset(&ce, 0, sizeof(ce)); + ce.xclient.type = ClientMessage; + ce.xclient.message_type = g_wm_protocols_atom; + ce.xclient.display = g_display; + ce.xclient.window = window_id; + ce.xclient.format = 32; + ce.xclient.data.l[0] = g_wm_delete_window_atom; + ce.xclient.data.l[1] = CurrentTime; + XSendEvent(g_display, window_id, False, NoEventMask, &ce); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_system_command(struct stream* s, int size) +{ + int window_id; + int command; + + LOG(10, ("chansrv::rail_process_system_command:")); + in_uint32_le(s, window_id); + in_uint16_le(s, command); + switch (command) + { + case SC_SIZE: + LOG(10, (" window_id 0x%8.8x SC_SIZE", window_id)); + break; + case SC_MOVE: + LOG(10, (" window_id 0x%8.8x SC_MOVE", window_id)); + break; + case SC_MINIMIZE: + LOG(10, (" window_id 0x%8.8x SC_MINIMIZE", window_id)); + break; + case SC_MAXIMIZE: + LOG(10, (" window_id 0x%8.8x SC_MAXIMIZE", window_id)); + break; + case SC_CLOSE: + LOG(10, (" window_id 0x%8.8x SC_CLOSE", window_id)); + rail_close_window(window_id); + break; + case SC_KEYMENU: + LOG(10, (" window_id 0x%8.8x SC_KEYMENU", window_id)); + break; + case SC_RESTORE: + LOG(10, (" window_id 0x%8.8x SC_RESTORE", window_id)); + break; + case SC_DEFAULT: + LOG(10, (" window_id 0x%8.8x SC_DEFAULT", window_id)); + break; + default: + LOG(10, (" window_id 0x%8.8x unknown command command %d", + window_id, command)); + break; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_handshake(struct stream* s, int size) +{ + int build_number; + + LOG(10, ("chansrv::rail_process_handshake:")); + in_uint32_le(s, build_number); + LOG(10, (" build_number 0x%8.8x", build_number)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_notify_event(struct stream* s, int size) +{ + int window_id; + int notify_id; + int message; + + LOG(10, ("chansrv::rail_process_notify_event:")); + in_uint32_le(s, window_id); + in_uint32_le(s, notify_id); + in_uint32_le(s, message); + LOG(10, (" window_id 0x%8.8x notify_id 0x%8.8x message 0x%8.8x", + window_id, notify_id, message)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_window_move(struct stream* s, int size) +{ + int window_id; + int left; + int top; + int right; + int bottom; + + LOG(10, ("chansrv::rail_process_window_move:")); + in_uint32_le(s, window_id); + in_uint16_le(s, left); + in_uint16_le(s, top); + in_uint16_le(s, right); + in_uint16_le(s, bottom); + LOG(10, (" window_id 0x%8.8x left %d top %d right %d bottom %d width %d height %d", + window_id, left, top, right, bottom, right - left, bottom - top)); + XMoveResizeWindow(g_display, window_id, left, top, right - left, bottom - top); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_local_move_size(struct stream* s, int size) +{ + int window_id; + int is_move_size_start; + int move_size_type; + int pos_x; + int pos_y; + + LOG(10, ("chansrv::rail_process_local_move_size:")); + in_uint32_le(s, window_id); + in_uint16_le(s, is_move_size_start); + in_uint16_le(s, move_size_type); + in_uint16_le(s, pos_x); + in_uint16_le(s, pos_y); + LOG(10, (" window_id 0x%8.8x is_move_size_start %d move_size_type %d " + "pos_x %d pos_y %d", window_id, is_move_size_start, move_size_type, + pos_x, pos_y)); + return 0; +} + +/*****************************************************************************/ +/* server to client only */ +static int APP_CC +rail_process_min_max_info(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_min_max_info:")); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_client_status(struct stream* s, int size) +{ + int flags; + + LOG(10, ("chansrv::rail_process_client_status:")); + in_uint32_le(s, flags); + LOG(10, (" flags 0x%8.8x", flags)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_sys_menu(struct stream* s, int size) +{ + int window_id; + int left; + int top; + + LOG(10, ("chansrv::rail_process_sys_menu:")); + in_uint32_le(s, window_id); + in_uint16_le(s, left); + in_uint16_le(s, top); + LOG(10, (" window_id 0x%8.8x left %d top %d", window_id, left, top)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_lang_bar_info(struct stream* s, int size) +{ + int language_bar_status; + + LOG(10, ("chansrv::rail_process_lang_bar_info:")); + in_uint32_le(s, language_bar_status); + LOG(10, (" language_bar_status 0x%8.8x", language_bar_status)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_appid_req(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_appid_req:")); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_appid_resp(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_appid_resp:")); + return 0; +} + +/*****************************************************************************/ +/* server to client only */ +static int APP_CC +rail_process_exec_result(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_exec_result:")); + return 0; +} + +/*****************************************************************************/ +/* data in from client ( client -> xrdp -> chansrv ) */ +int APP_CC +rail_data_in(struct stream* s, int chan_id, int chan_flags, int length, + int total_length) +{ + int code; + int size; + + LOG(10, ("chansrv::rail_data_in:")); + in_uint8(s, code); + in_uint8s(s, 1); + in_uint16_le(s, size); + switch (code) + { + case TS_RAIL_ORDER_EXEC: /* 1 */ + rail_process_exec(s, size); + break; + case TS_RAIL_ORDER_ACTIVATE: /* 2 */ + rail_process_activate(s, size); + break; + case TS_RAIL_ORDER_SYSPARAM: /* 3 */ + rail_process_system_param(s, size); + break; + case TS_RAIL_ORDER_SYSCOMMAND: /* 4 */ + rail_process_system_command(s, size); + break; + case TS_RAIL_ORDER_HANDSHAKE: /* 5 */ + rail_process_handshake(s, size); + break; + case TS_RAIL_ORDER_NOTIFY_EVENT: /* 6 */ + rail_process_notify_event(s, size); + break; + case TS_RAIL_ORDER_WINDOWMOVE: /* 8 */ + rail_process_window_move(s, size); + break; + case TS_RAIL_ORDER_LOCALMOVESIZE: /* 9 */ + rail_process_local_move_size(s, size); + break; + case TS_RAIL_ORDER_MINMAXINFO: /* 10 */ + rail_process_min_max_info(s, size); + break; + case TS_RAIL_ORDER_CLIENTSTATUS: /* 11 */ + rail_process_client_status(s, size); + break; + case TS_RAIL_ORDER_SYSMENU: /* 12 */ + rail_process_sys_menu(s, size); + break; + case TS_RAIL_ORDER_LANGBARINFO: /* 13 */ + rail_process_lang_bar_info(s, size); + break; + case TS_RAIL_ORDER_GET_APPID_REQ: /* 14 */ + rail_process_appid_req(s, size); + break; + case TS_RAIL_ORDER_GET_APPID_RESP: /* 15 */ + rail_process_appid_resp(s, size); + break; + case TS_RAIL_ORDER_EXEC_RESULT: /* 128 */ + rail_process_exec_result(s, size); + break; + default: + LOG(10, ("rail_data_in: unknown code %d size %d", code, size)); + break; + } + XFlush(g_display); + return 0; +} + +/*****************************************************************************/ +/* returns 0, event handled, 1 unhandled */ +int APP_CC +rail_xevent(void* xevent) +{ + XEvent* lxevent; + XWindowChanges xwc; + int rv; + int nchildren_return = 0; + Window root_return; + Window parent_return; + Window *children_return; + Window wreturn; + int revert_to; + XWindowAttributes wnd_attributes; + + LOG(10, ("chansrv::rail_xevent:")); + if (!g_rail_up) + { + return 1; + } + rv = 1; + lxevent = (XEvent*)xevent; + switch (lxevent->type) + { + case ConfigureRequest: + LOG(10, (" got ConfigureRequest window_id 0x%8.8x", lxevent->xconfigurerequest.window)); + g_memset(&xwc, 0, sizeof(xwc)); + xwc.x = lxevent->xconfigurerequest.x; + xwc.y = lxevent->xconfigurerequest.y; + xwc.width = lxevent->xconfigurerequest.width; + xwc.height = lxevent->xconfigurerequest.height; + xwc.border_width = lxevent->xconfigurerequest.border_width; + xwc.sibling = lxevent->xconfigurerequest.above; + xwc.stack_mode = lxevent->xconfigurerequest.detail; + XConfigureWindow(g_display, + lxevent->xconfigurerequest.window, + lxevent->xconfigurerequest.value_mask, + &xwc); + rv = 0; + break; + + case MapRequest: + LOG(10, (" got MapRequest")); + XMapWindow(g_display, lxevent->xmaprequest.window); + rv = 0; + break; + + case MapNotify: + LOG(10, (" got MapNotify")); + break; + + case UnmapNotify: + LOG(10, (" got UnmapNotify")); + break; + + case ConfigureNotify: + LOG(10, (" got ConfigureNotify")); + break; + + case FocusIn: + LOG(10, (" got FocusIn")); + break; + + case ButtonPress: + LOG(10, (" got ButtonPress")); + break; + + case EnterNotify: + LOG(10, (" got EnterNotify")); + break; + + case LeaveNotify: + LOG(10, (" got LeaveNotify")); + break; + + } + return rv; +} diff --git a/sesman/chansrv/rail.h b/sesman/chansrv/rail.h new file mode 100644 index 00000000..7dbcbc5a --- /dev/null +++ b/sesman/chansrv/rail.h @@ -0,0 +1,35 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 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. + */ + +#ifndef _RAIL_H_ +#define _RAIL_H_ + +#include "arch.h" +#include "parse.h" + +int APP_CC +rail_init(void); +int APP_CC +rail_deinit(void); +int APP_CC +rail_data_in(struct stream* s, int chan_id, int chan_flags, + int length, int total_length); +int APP_CC +rail_xevent(void* xevent); + +#endif diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index 8cca641d..e4d54bb0 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -1,32 +1,346 @@ +/** + * 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" +#include "thread_calls.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; + +#if defined(XRDP_SIMPLESOUND) +static void* DEFAULT_CC +read_raw_audio_data(void* arg); +#endif + +/*****************************************************************************/ +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(10, ("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(10, ("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; + + 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(); -extern int g_rdpsnd_chan_id; /* in chansrv.c */ + in_uint16_le(s, wTimeStamp); + in_uint8(s, cConfirmedBlockNo); + + LOG(10, ("sound_process_wave_confirm: wTimeStamp %d, cConfirmedBlockNo %d", + wTimeStamp, cConfirmedBlockNo)); + + 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; + + 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 */ + tc_thread_create(read_raw_audio_data, 0); + +#endif + return 0; } @@ -34,14 +348,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 +403,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 +424,130 @@ 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) + +static int DEFAULT_CC +sttrans_data_in(struct trans* self) +{ + LOG(0, ("sttrans_data_in:\n")); return 0; } + +/** + * read raw audio data from pulseaudio device and write it + * to a unix domain socket on which trans server is listening + */ + +static void* DEFAULT_CC +read_raw_audio_data(void* arg) +{ + pa_sample_spec samp_spec; + pa_simple* simple = NULL; + uint32_t bytes_read; + char* cptr; + int i; + int error; + struct trans* strans; + char path[256]; + struct stream* outs; + + strans = trans_create(TRANS_MODE_UNIX, 8192, 8192); + if (strans == 0) + { + LOG(0, ("read_raw_audio_data: trans_create failed\n")); + return 0; + } + strans->trans_data_in = sttrans_data_in; + g_snprintf(path, 255, "/tmp/xrdp_chansrv_audio_socket_%d", g_display_num); + if (trans_connect(strans, "", path, 100) != 0) + { + LOG(0, ("read_raw_audio_data: trans_connect failed\n")); + trans_delete(strans); + return 0; + } + + /* 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))); + g_sleep(1000); + } + + if (i == 60) + { + /* failed to connect to audio server */ + trans_delete(strans); + return NULL; + } + + /* insert header just once */ + outs = trans_get_out_s(strans, 8192); + out_uint32_le(outs, 0); + out_uint32_le(outs, AUDIO_BUF_SIZE + 8); + cptr = outs->p; + out_uint8s(outs, AUDIO_BUF_SIZE); + s_mark_end(outs); + + while (1) + { + /* read a block of raw audio data... */ + g_memset(cptr, 0, 4); + bytes_read = pa_simple_read(simple, cptr, AUDIO_BUF_SIZE, &error); + if (bytes_read < 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) + { + g_sleep(10); + continue; + } + if (trans_force_write_s(strans, outs) != 0) + { + LOG(0, ("read_raw_audio_data: ERROR writing audio data to server\n")); + break; + } + } + pa_simple_free(simple); + trans_delete(strans); + return NULL; +} + +#endif diff --git a/sesman/chansrv/sound.h b/sesman/chansrv/sound.h index 45448a5a..8171680d 100644 --- a/sesman/chansrv/sound.h +++ b/sesman/chansrv/sound.h @@ -1,20 +1,70 @@ +/** + * 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_ + +#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 + +#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); #endif diff --git a/sesman/chansrv/xcommon.c b/sesman/chansrv/xcommon.c new file mode 100644 index 00000000..70b52694 --- /dev/null +++ b/sesman/chansrv/xcommon.c @@ -0,0 +1,187 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 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 <X11/Xlib.h> +#include "arch.h" +#include "parse.h" +#include "os_calls.h" +#include "chansrv.h" +#include "log.h" +#include "clipboard.h" +#include "rail.h" + +extern int g_clip_up; /* in clipboard.c */ +extern int g_waiting_for_data_response; /* in clipboard.c */ +extern int g_waiting_for_data_response_time; /* in clipboard.c */ + +extern int g_rail_up; /* in rail.c */ + +Display* g_display = 0; +int g_x_socket = 0; +tbus g_x_wait_obj = 0; +Screen* g_screen = 0; +int g_screen_num = 0; +Window g_root_window = 0; +Atom g_wm_delete_window_atom = 0; +Atom g_wm_protocols_atom = 0; + +/*****************************************************************************/ +static int DEFAULT_CC +xcommon_error_handler(Display* dis, XErrorEvent* xer) +{ + char text[256]; + + XGetErrorText(dis, xer->error_code, text, 255); + LOGM((LOG_LEVEL_ERROR, "X error [%s](%d) opcodes %d/%d " + "resource 0x%lx", text, xer->error_code, + xer->request_code, xer->minor_code, xer->resourceid)); + return 0; +} + +/*****************************************************************************/ +/* The X server had an internal error. This is the last function called. + Do any cleanup that needs to be done on exit, like removing temporary files. + Don't worry about memory leaks */ +static int DEFAULT_CC +xcommon_fatal_handler(Display* dis) +{ + return 0; +} + +/*****************************************************************************/ +/* returns time in miliseconds + this is like g_time2 in os_calls, but not miliseconds since machine was + up, something else + this is a time value similar to what the xserver uses */ +int APP_CC +xcommon_get_local_time(void) +{ + return g_time3(); +} + +/******************************************************************************/ +/* this should be called first */ +int APP_CC +xcommon_init(void) +{ + if (g_display != 0) + { + LOG(10, ("xcommon_init: xcommon_init already called")); + return 0; + } + g_display = XOpenDisplay(0); + if (g_display == 0) + { + LOGM((LOG_LEVEL_ERROR, "xcommon_init: error, XOpenDisplay failed")); + return 1; + } + + LOG(0, ("xcommon_init: connected to display ok")); + + /* setting the error handlers can cause problem when shutting down + chansrv on some xlibs */ + XSetErrorHandler(xcommon_error_handler); + //XSetIOErrorHandler(xcommon_fatal_handler); + + g_x_socket = XConnectionNumber(g_display); + if (g_x_socket == 0) + { + LOGM((LOG_LEVEL_ERROR, "xcommon_init: XConnectionNumber failed")); + return 1; + } + + g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0); + g_screen_num = DefaultScreen(g_display); + g_screen = ScreenOfDisplay(g_display, g_screen_num); + + g_root_window = RootWindowOfScreen(g_screen); + + g_wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", 0); + g_wm_protocols_atom = XInternAtom(g_display, "WM_PROTOCOLS", 0); + + return 0; +} + +/*****************************************************************************/ +/* returns error + this is called to get any wait objects for the main loop + timeout can be nil */ +int APP_CC +xcommon_get_wait_objs(tbus* objs, int* count, int* timeout) +{ + int lcount; + + if (((!g_clip_up) && (!g_rail_up)) || (objs == 0) || (count == 0)) + { + LOG(10, ("xcommon_get_wait_objs: nothing to do")); + return 0; + } + lcount = *count; + objs[lcount] = g_x_wait_obj; + lcount++; + *count = lcount; + return 0; +} + +/*****************************************************************************/ +int APP_CC +xcommon_check_wait_objs(void) +{ + XEvent xevent; + int time_diff; + int clip_rv; + int rail_rv; + + if ((!g_clip_up) && (!g_rail_up)) + { + LOG(10, ("xcommon_check_wait_objs: nothing to do")); + return 0; + } + if (g_is_wait_obj_set(g_x_wait_obj)) + { + if (XPending(g_display) < 1) + { + /* something is wrong, should not get here */ + LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: sck closed")); + return 0; + } + if (g_waiting_for_data_response) + { + time_diff = xcommon_get_local_time() - + g_waiting_for_data_response_time; + if (time_diff > 10000) + { + LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: warning, " + "waiting for data response too long")); + } + } + while (XPending(g_display) > 0) + { + g_memset(&xevent, 0, sizeof(xevent)); + XNextEvent(g_display, &xevent); + + clip_rv = clipboard_xevent(&xevent); + rail_rv = rail_xevent(&xevent); + if ((clip_rv == 1) && (rail_rv == 1)) + { + LOG(10, ("xcommon_check_wait_objs unknown xevent type %d", xevent.type)); + } + } + } + return 0; +} diff --git a/sesman/chansrv/xcommon.h b/sesman/chansrv/xcommon.h new file mode 100644 index 00000000..d5aa7e46 --- /dev/null +++ b/sesman/chansrv/xcommon.h @@ -0,0 +1,34 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 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(XCOMMON_H) +#define XCOMMON_H + +#include "arch.h" +#include "parse.h" + +int APP_CC +xcommon_get_local_time(void); +int APP_CC +xcommon_init(void); +int APP_CC +xcommon_get_wait_objs(tbus* objs, int* count, int* timeout); +int APP_CC +xcommon_check_wait_objs(void); + +#endif diff --git a/sesman/config.c b/sesman/config.c index d81f7968..a4342676 100644 --- a/sesman/config.c +++ b/sesman/config.c @@ -29,28 +29,11 @@ #include "list.h" #include "file.h" #include "sesman.h" +#include "log.h" extern struct config_sesman* g_cfg; /* in sesman.c */ -/******************************************************************************/ -/** - * - * @brief Reads sesman configuration - * @param s translates the strings "1", "true" and "yes" in 1 (true) and other strings in 0 - * @return 0 on success, 1 on failure - * - */ -static int APP_CC -text2bool(char* s) -{ - if (0 == g_strcasecmp(s, "1") || - 0 == g_strcasecmp(s, "true") || - 0 == g_strcasecmp(s, "yes")) - { - return 1; - } - return 0; -} + /******************************************************************************/ int DEFAULT_CC @@ -66,16 +49,16 @@ config_read(struct config_sesman* cfg) fd = g_file_open(cfg_file); if (-1 == fd) { - if (g_cfg->log.fd >= 0) - { + //if (g_cfg->log.fd >= 0) + //{ /* logging is already active */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "error opening %s in \ + log_message(LOG_LEVEL_ALWAYS, "error opening %s in \ config_read", cfg_file); - } - else - { + //} + //else + //{ g_printf("error opening %s in config_read", cfg_file); - } + //} return 1; } g_memset(cfg, 0, sizeof(struct config_sesman)); @@ -95,7 +78,7 @@ config_read(struct config_sesman* cfg) config_read_rdp_params(fd, cfg, param_n, param_v); /* read logging config */ - config_read_logging(fd, &(cfg->log), param_n, param_v); + // config_read_logging(fd, &(cfg->log), param_n, param_v); /* read security config */ config_read_security(fd, &(cfg->sec), param_n, param_v); @@ -190,7 +173,7 @@ config_read_globals(int file, struct config_sesman* cf, struct list* param_n, return 0; } -/******************************************************************************/ +/****************************************************************************** int DEFAULT_CC config_read_logging(int file, struct log_config* lc, struct list* param_n, struct list* param_v) @@ -201,7 +184,7 @@ config_read_logging(int file, struct log_config* lc, struct list* param_n, list_clear(param_v); list_clear(param_n); - /* setting defaults */ + // setting defaults lc->program_name = g_strdup("sesman"); lc->log_file = 0; lc->fd = 0; @@ -244,7 +227,7 @@ config_read_logging(int file, struct log_config* lc, struct list* param_n, return 0; } - +*/ /******************************************************************************/ int DEFAULT_CC config_read_security(int file, struct config_security* sc, diff --git a/sesman/config.h b/sesman/config.h index 2a4ebd28..73fab38f 100644 --- a/sesman/config.h +++ b/sesman/config.h @@ -45,12 +45,13 @@ #define SESMAN_CFG_RDP_PARAMS "X11rdp" #define SESMAN_CFG_VNC_PARAMS "Xvnc" +/* #define SESMAN_CFG_LOGGING "Logging" #define SESMAN_CFG_LOG_FILE "LogFile" #define SESMAN_CFG_LOG_LEVEL "LogLevel" #define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog" #define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel" - +*/ #define SESMAN_CFG_SECURITY "Security" #define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry" #define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin" @@ -186,7 +187,7 @@ struct config_sesman * @var log * @brief Log configuration struct */ - struct log_config log; + //struct log_config log; /** * @var sec * @brief Security configuration options struct diff --git a/sesman/env.c b/sesman/env.c index 4bcb22e8..f7abe120 100644 --- a/sesman/env.c +++ b/sesman/env.c @@ -47,7 +47,7 @@ env_check_password_file(char* filename, char* password) fd = g_file_open(filename); if (fd == -1) { - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "can't read vnc password file - %s", filename); return 1; @@ -112,13 +112,13 @@ env_set_user(char* username, char* passwd_file, int display) /* we use auth_file_path as requested */ g_sprintf(passwd_file, g_cfg->auth_file_path, username); } - LOG_DBG(&(g_cfg->log), "pass file: %s", passwd_file); + LOG_DBG("pass file: %s", passwd_file); } } } else { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, + log_message(LOG_LEVEL_ERROR, "error getting user info for user %s", username); } return error; diff --git a/sesman/libscp/Makefile.am b/sesman/libscp/Makefile.am index de8513f8..eaf518a8 100644 --- a/sesman/libscp/Makefile.am +++ b/sesman/libscp/Makefile.am @@ -1,5 +1,5 @@ EXTRA_DIST = libscp_connection.h libscp_commands.h libscp.h libscp_session.h libscp_types_mng.h libscp_v1c_mng.h libscp_vX.h libscp_commands_mng.h libscp_init.h libscp_tcp.h libscp_v0.h libscp_v1s.h libscp_lock.h \ -libscp_types.h libscp_v1c.h libscp_v1s_mng.h +libscp_types.h libscp_v1c.h libscp_v1s_mng.h AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ @@ -27,5 +27,5 @@ libscp_la_SOURCES = \ libscp_vX.c libscp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la \ + $(top_builddir)/common/libcommon.la \ -lpthread diff --git a/sesman/libscp/libscp_connection.c b/sesman/libscp/libscp_connection.c index 0b09852e..bf49fb84 100644 --- a/sesman/libscp/libscp_connection.c +++ b/sesman/libscp/libscp_connection.c @@ -27,7 +27,7 @@ #include "libscp_connection.h" -extern struct log_config* s_log; +//extern struct log_config* s_log; struct SCP_CONNECTION* scp_connection_create(int sck) @@ -38,7 +38,7 @@ scp_connection_create(int sck) if (0 == conn) { - log_message(s_log, LOG_LEVEL_WARNING, "[connection:%d] connection create: malloc error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[connection:%d] connection create: malloc error", __LINE__); return 0; } diff --git a/sesman/libscp/libscp_init.c b/sesman/libscp/libscp_init.c index 22497ac2..4c48fb1f 100644 --- a/sesman/libscp/libscp_init.c +++ b/sesman/libscp/libscp_init.c @@ -27,22 +27,24 @@ #include "libscp_init.h" -struct log_config* s_log; +//struct log_config* s_log; /* server API */ int DEFAULT_CC -scp_init(struct log_config* log) +scp_init() { +/* if (0 == log) { return 1; } +*/ - s_log = log; + //s_log = log; scp_lock_init(); - log_message(s_log, LOG_LEVEL_WARNING, "[init:%d] libscp initialized", __LINE__); + log_message(LOG_LEVEL_WARNING, "[init:%d] libscp initialized", __LINE__); return 0; } diff --git a/sesman/libscp/libscp_init.h b/sesman/libscp/libscp_init.h index 5ac0ba02..92dbc659 100644 --- a/sesman/libscp/libscp_init.h +++ b/sesman/libscp/libscp_init.h @@ -42,7 +42,7 @@ * */ int DEFAULT_CC -scp_init(struct log_config* log); +scp_init(); #endif diff --git a/sesman/libscp/libscp_session.c b/sesman/libscp/libscp_session.c index 8ac94d25..3ed5070a 100644 --- a/sesman/libscp/libscp_session.c +++ b/sesman/libscp/libscp_session.c @@ -31,7 +31,7 @@ #include <sys/socket.h> #include <arpa/inet.h> -extern struct log_config* s_log; +//extern struct log_config* s_log; /*******************************************************************/ struct SCP_SESSION* @@ -42,7 +42,7 @@ scp_session_create() s = (struct SCP_SESSION*)g_malloc(sizeof(struct SCP_SESSION), 1); if (0 == s) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] session create: malloc error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] session create: malloc error", __LINE__); return 0; } return s; @@ -60,17 +60,20 @@ scp_session_set_type(struct SCP_SESSION* s, tui8 type) case SCP_SESSION_TYPE_XRDP: s->type = SCP_SESSION_TYPE_XRDP; break; + case SCP_GW_AUTHENTICATION: + s->type = SCP_GW_AUTHENTICATION; + break; case SCP_SESSION_TYPE_MANAGE: s->type = SCP_SESSION_TYPE_MANAGE; s->mng = (struct SCP_MNG_DATA*)g_malloc(sizeof(struct SCP_MNG_DATA), 1); if (NULL == s->mng) { - log_message(s_log, LOG_LEVEL_ERROR, "[session:%d] set_type: internal error", __LINE__); + log_message(LOG_LEVEL_ERROR, "[session:%d] set_type: internal error", __LINE__); return 1; } break; default: - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_type: unknown type", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_type: unknown type", __LINE__); return 1; } return 0; @@ -89,7 +92,7 @@ scp_session_set_version(struct SCP_SESSION* s, tui32 version) s->version = 1; break; default: - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_version: unknown version", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_version: unknown version", __LINE__); return 1; } return 0; @@ -149,7 +152,7 @@ scp_session_set_locale(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_locale: null locale", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_locale: null locale", __LINE__); s->locale[0]='\0'; return 1; } @@ -164,7 +167,7 @@ scp_session_set_username(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_username: null username", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_username: null username", __LINE__); return 1; } if (0 != s->username) @@ -174,7 +177,7 @@ scp_session_set_username(struct SCP_SESSION* s, char* str) s->username = g_strdup(str); if (0 == s->username) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_username: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_username: strdup error", __LINE__); return 1; } return 0; @@ -186,7 +189,7 @@ scp_session_set_password(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_password: null password", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_password: null password", __LINE__); return 1; } if (0 != s->password) @@ -196,7 +199,7 @@ scp_session_set_password(struct SCP_SESSION* s, char* str) s->password = g_strdup(str); if (0 == s->password) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_password: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_password: strdup error", __LINE__); return 1; } return 0; @@ -208,7 +211,7 @@ scp_session_set_domain(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_domain: null domain", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_domain: null domain", __LINE__); return 1; } if (0 != s->domain) @@ -218,7 +221,7 @@ scp_session_set_domain(struct SCP_SESSION* s, char* str) s->domain = g_strdup(str); if (0 == s->domain) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_domain: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_domain: strdup error", __LINE__); return 1; } return 0; @@ -230,7 +233,7 @@ scp_session_set_program(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_program: null program", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_program: null program", __LINE__); return 1; } if (0 != s->program) @@ -240,7 +243,7 @@ scp_session_set_program(struct SCP_SESSION* s, char* str) s->program = g_strdup(str); if (0 == s->program) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_program: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_program: strdup error", __LINE__); return 1; } return 0; @@ -252,7 +255,7 @@ scp_session_set_directory(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_directory: null directory", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_directory: null directory", __LINE__); return 1; } if (0 != s->directory) @@ -262,7 +265,7 @@ scp_session_set_directory(struct SCP_SESSION* s, char* str) s->directory = g_strdup(str); if (0 == s->directory) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_directory: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_directory: strdup error", __LINE__); return 1; } return 0; @@ -274,7 +277,7 @@ scp_session_set_client_ip(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_client_ip: null ip", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_client_ip: null ip", __LINE__); return 1; } if (0 != s->client_ip) @@ -284,7 +287,7 @@ scp_session_set_client_ip(struct SCP_SESSION* s, char* str) s->client_ip = g_strdup(str); if (0 == s->client_ip) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_client_ip: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_client_ip: strdup error", __LINE__); return 1; } return 0; @@ -296,7 +299,7 @@ scp_session_set_hostname(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_hostname: null hostname", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_hostname: null hostname", __LINE__); return 1; } if (0 != s->hostname) @@ -306,7 +309,7 @@ scp_session_set_hostname(struct SCP_SESSION* s, char* str) s->hostname = g_strdup(str); if (0 == s->hostname) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_hostname: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_hostname: strdup error", __LINE__); return 1; } return 0; @@ -318,7 +321,7 @@ scp_session_set_errstr(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_errstr: null string", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_errstr: null string", __LINE__); return 1; } if (0 != s->errstr) @@ -328,7 +331,7 @@ scp_session_set_errstr(struct SCP_SESSION* s, char* str) s->errstr = g_strdup(str); if (0 == s->errstr) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_errstr: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_errstr: strdup error", __LINE__); return 1; } return 0; @@ -359,7 +362,7 @@ scp_session_set_addr(struct SCP_SESSION* s, int type, void* addr) ret = inet_pton(AF_INET, addr, &ip4); if (ret == 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); inet_pton(AF_INET, "127.0.0.1", &ip4); g_memcpy(&(s->ipv4addr), &(ip4.s_addr), 4); return 1; @@ -375,7 +378,7 @@ scp_session_set_addr(struct SCP_SESSION* s, int type, void* addr) ret = inet_pton(AF_INET6, addr, &ip6); if (ret == 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); inet_pton(AF_INET, "::1", &ip6); g_memcpy(s->ipv6addr, &(ip6.s6_addr), 16); return 1; diff --git a/sesman/libscp/libscp_tcp.c b/sesman/libscp/libscp_tcp.c index 6ffa4693..459992fe 100644 --- a/sesman/libscp/libscp_tcp.c +++ b/sesman/libscp/libscp_tcp.c @@ -42,7 +42,7 @@ scp_tcp_force_recv(int sck, char* data, int len) int rcvd; int block; - LOG_DBG(s_log, "scp_tcp_force_recv()"); + LOG_DBG("scp_tcp_force_recv()"); block = scp_lock_fork_critical_section_start(); while (len > 0) @@ -84,7 +84,7 @@ scp_tcp_force_send(int sck, char* data, int len) int sent; int block; - LOG_DBG(s_log, "scp_tcp_force_send()"); + LOG_DBG("scp_tcp_force_send()"); block = scp_lock_fork_critical_section_start(); while (len > 0) diff --git a/sesman/libscp/libscp_types.h b/sesman/libscp/libscp_types.h index 7a54545a..e6521741 100644 --- a/sesman/libscp/libscp_types.h +++ b/sesman/libscp/libscp_types.h @@ -42,6 +42,10 @@ #define SCP_SESSION_TYPE_XVNC 0x00 #define SCP_SESSION_TYPE_XRDP 0x01 #define SCP_SESSION_TYPE_MANAGE 0x02 +/* SCP_GW_AUTHENTICATION can be used when XRDP + sesman act as a gateway + * XRDP sends this command to let sesman verify if the user is allowed + * to use the gateway */ +#define SCP_GW_AUTHENTICATION 0x04 #define SCP_ADDRESS_TYPE_IPV4 0x00 #define SCP_ADDRESS_TYPE_IPV6 0x01 diff --git a/sesman/libscp/libscp_v0.c b/sesman/libscp/libscp_v0.c index d46d6afa..f8b5a9d6 100644 --- a/sesman/libscp/libscp_v0.c +++ b/sesman/libscp/libscp_v0.c @@ -43,7 +43,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); init_stream(c->out_s, c->in_s->size); - LOG_DBG(s_log, "[v0:%d] starting connection", __LINE__); + LOG_DBG("[v0:%d] starting connection", __LINE__); g_tcp_set_non_blocking(c->in_sck); g_tcp_set_no_delay(c->in_sck); s_push_layer(c->out_s, channel_hdr, 8); @@ -59,7 +59,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } sz = g_strlen(s->username); @@ -83,27 +83,27 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (0 != version) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); return SCP_CLIENT_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 14) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: packet size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: packet size error", __LINE__); return SCP_CLIENT_STATE_SIZE_ERR; } @@ -111,7 +111,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } @@ -119,7 +119,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint16_be(c->in_s, sz); if (3 != sz) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } @@ -127,14 +127,14 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint16_be(c->in_s, sz); if (1 != sz) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: connection denied", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: connection denied", __LINE__); return SCP_CLIENT_STATE_CONNECTION_DENIED; } in_uint16_be(c->in_s, sz); s->display = sz; - LOG_DBG(s_log, "[v0:%d] connection terminated", __LINE__); + LOG_DBG("[v0:%d] connection terminated", __LINE__); return SCP_CLIENT_STATE_END; } @@ -152,20 +152,20 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) if (!skipVchk) { - LOG_DBG(s_log, "[v0:%d] starting connection", __LINE__); + LOG_DBG("[v0:%d] starting connection", __LINE__); if (0 == scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { c->in_s->end = c->in_s->data + 8; in_uint32_be(c->in_s, version); if (version != 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -175,7 +175,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) init_stream(c->in_s, 8196); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } c->in_s->end = c->in_s->data + (size - 8); @@ -187,7 +187,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) session = scp_session_create(); if (0 == session) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -208,7 +208,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) if (0 != scp_session_set_username(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -219,7 +219,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) if (0 != scp_session_set_password(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -277,9 +277,45 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) } } } + else if (code == SCP_GW_AUTHENTICATION) + { + /* g_writeln("Command is SCP_GW_AUTHENTICATION"); */ + session = scp_session_create(); + if (0 == session) + { + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);*/ + return SCP_SERVER_STATE_INTERNAL_ERR; + } + + scp_session_set_version(session, version); + scp_session_set_type(session, SCP_GW_AUTHENTICATION); + /* reading username */ + in_uint16_be(c->in_s, sz); + buf[sz]='\0'; + in_uint8a(c->in_s, buf, sz); + /* g_writeln("Received user name: %s",buf); */ + if (0 != scp_session_set_username(session, buf)) + { + scp_session_destroy(session); + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__);*/ + return SCP_SERVER_STATE_INTERNAL_ERR; + } + + /* reading password */ + in_uint16_be(c->in_s, sz); + buf[sz] = '\0'; + in_uint8a(c->in_s, buf, sz); + /* g_writeln("Received password: %s",buf); */ + if (0 != scp_session_set_password(session, buf)) + { + scp_session_destroy(session); + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); */ + return SCP_SERVER_STATE_INTERNAL_ERR; + } + } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -300,11 +336,11 @@ scp_v0s_allow_connection(struct SCP_CONNECTION* c, SCP_DISPLAY d) if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } - LOG_DBG(s_log, "[v0:%d] connection terminated (allowed)", __LINE__); + LOG_DBG("[v0:%d] connection terminated (allowed)", __LINE__); return SCP_SERVER_STATE_OK; } @@ -315,16 +351,39 @@ scp_v0s_deny_connection(struct SCP_CONNECTION* c) out_uint32_be(c->out_s, 0); /* version */ out_uint32_be(c->out_s, 14); /* size */ out_uint16_be(c->out_s, 3); /* cmd */ - out_uint16_be(c->out_s, 0); /* data */ - out_uint16_be(c->out_s, 0); /* data */ + out_uint16_be(c->out_s, 0); /* data = 0 - means NOT ok*/ + out_uint16_be(c->out_s, 0); /* reserved for display number*/ + s_mark_end(c->out_s); + + if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) + { + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + return SCP_SERVER_STATE_NETWORK_ERR; + } + + LOG_DBG("[v0:%d] connection terminated (denied)", __LINE__); + return SCP_SERVER_STATE_OK; +} + +/******************************************************************************/ +enum SCP_SERVER_STATES_E +scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value) +{ + out_uint32_be(c->out_s, 0); /* version */ + out_uint32_be(c->out_s, 14); /* size */ + /* cmd SCP_GW_AUTHENTICATION means authentication reply */ + out_uint16_be(c->out_s, SCP_GW_AUTHENTICATION); + out_uint16_be(c->out_s, value); /* reply code */ + out_uint16_be(c->out_s, 0); /* dummy data */ s_mark_end(c->out_s); + /* g_writeln("Total number of bytes that will be sent %d",c->out_s->end - c->out_s->data);*/ if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); */ return SCP_SERVER_STATE_NETWORK_ERR; } - LOG_DBG(s_log, "[v0:%d] connection terminated (denied)", __LINE__); + /* until syslog merge LOG_DBG(s_log, "[v0:%d] connection terminated (scp_v0s_deny_authentication)", __LINE__);*/ return SCP_SERVER_STATE_OK; } diff --git a/sesman/libscp/libscp_v0.h b/sesman/libscp/libscp_v0.h index 7c6fd4b2..92b835f0 100644 --- a/sesman/libscp/libscp_v0.h +++ b/sesman/libscp/libscp_v0.h @@ -73,5 +73,14 @@ scp_v0s_allow_connection(struct SCP_CONNECTION* c, SCP_DISPLAY d); enum SCP_SERVER_STATES_E scp_v0s_deny_connection(struct SCP_CONNECTION* c); +/** + * @brief send reply to an authentication request + * @param c connection descriptor + * @param value the reply code 0 means ok + * @return + */ +enum SCP_SERVER_STATES_E +scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value); + #endif diff --git a/sesman/libscp/libscp_v1c_mng.c b/sesman/libscp/libscp_v1c_mng.c index bb54bc79..88f86f4f 100644 --- a/sesman/libscp/libscp_v1c_mng.c +++ b/sesman/libscp/libscp_v1c_mng.c @@ -30,7 +30,7 @@ #include <stdlib.h> #include <stdio.h> -extern struct log_config* s_log; +//extern struct log_config* s_log; static enum SCP_CLIENT_STATES_E _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s); @@ -91,7 +91,7 @@ scp_v1c_mng_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } @@ -127,7 +127,7 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } @@ -137,42 +137,42 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); return SCP_CLIENT_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: size error", __LINE__); return SCP_CLIENT_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_CMD_MNG_LIST) /* session list */ { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } @@ -188,14 +188,14 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, (*scount) = sescnt; (*s) = NULL; - LOG_DBG(s_log, "[v1c_mng] end list - no session on TS"); + LOG_DBG("[v1c_mng] end list - no session on TS"); return SCP_CLIENT_STATE_LIST_OK; } ds = g_malloc(sizeof(struct SCP_DISCONNECTED_SESSION) * sescnt, 0); if (ds == 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: internal error", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } } @@ -240,7 +240,7 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, (*scount) = sescnt; (*s) = ds; - LOG_DBG(s_log, "[v1c_mng] end list"); + LOG_DBG("[v1c_mng] end list"); return SCP_CLIENT_STATE_LIST_OK; } @@ -350,14 +350,14 @@ _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); return SCP_CLIENT_STATE_VERSION_ERR; } @@ -367,21 +367,21 @@ _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) /* read the rest of the packet */ if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd == SCP_CMD_MNG_LOGIN_ALLOW) /* connection ok */ { - log_message(s_log, LOG_LEVEL_INFO, "[v1c_mng:%d] connection ok", __LINE__); + log_message(LOG_LEVEL_INFO, "[v1c_mng:%d] connection ok", __LINE__); return SCP_CLIENT_STATE_OK; } else if (cmd == SCP_CMD_MNG_LOGIN_DENY) /* connection denied */ @@ -391,10 +391,10 @@ _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint8a(c->in_s, buf, dim); scp_session_set_errstr(s, buf); - log_message(s_log, LOG_LEVEL_INFO, "[v1c_mng:%d] connection denied: %s", __LINE__ , s->errstr); + log_message(LOG_LEVEL_INFO, "[v1c_mng:%d] connection denied: %s", __LINE__ , s->errstr); return SCP_CLIENT_STATE_CONNECTION_DENIED; } - log_message(s_log, LOG_LEVEL_WARNING, "[v1c-mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c-mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } diff --git a/sesman/libscp/libscp_v1s.c b/sesman/libscp/libscp_v1s.c index e57a907e..e10af26c 100644 --- a/sesman/libscp/libscp_v1s.c +++ b/sesman/libscp/libscp_v1s.c @@ -30,7 +30,7 @@ #include "libscp_v1s.h" -extern struct log_config* s_log; +//extern struct log_config* s_log; /* server API */ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) @@ -46,18 +46,18 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (!skipVchk) { - if (0==scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) + if (0 == scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -65,14 +65,14 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES in_uint32_be(c->in_s, size); if (size < 12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -82,7 +82,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES /* if we are starting a management session */ if (cmdset == SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_DEBUG, "[v1s:%d] requested management connection", __LINE__); + log_message(LOG_LEVEL_DEBUG, "[v1s:%d] requested management connection", __LINE__); /* should return SCP_SERVER_STATE_START_MANAGE */ return scp_v1s_mng_accept(c, s); } @@ -90,7 +90,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES /* if we started with resource sharing... */ if (cmdset == SCP_COMMAND_SET_RSR) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -98,14 +98,14 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES in_uint16_be(c->in_s, cmd); if (cmd != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } session = scp_session_create(); if (0 == session) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (malloc returned NULL)", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (malloc returned NULL)", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } scp_session_set_version(session, 1); @@ -114,7 +114,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if ((sz != SCP_SESSION_TYPE_XVNC) && (sz != SCP_SESSION_TYPE_XRDP)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: unknown session type", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: unknown session type", __LINE__); return SCP_SERVER_STATE_SESSION_TYPE_ERR; } scp_session_set_type(session, sz); @@ -151,7 +151,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (0 != scp_session_set_hostname(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -162,7 +162,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (0 != scp_session_set_username(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -173,7 +173,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (0 != scp_session_set_password(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -208,7 +208,7 @@ scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, rlen+14)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -250,49 +250,49 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, 14+rlen)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } /* receive password & username */ if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version!=1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size<12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmdset); if (cmdset != SCP_COMMAND_SET_DEFAULT) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != 4) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -304,7 +304,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* if (0 != scp_session_set_username(s, buf)) { scp_session_destroy(s); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -315,7 +315,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* if (0 != scp_session_set_password(s, buf)) { scp_session_destroy(s); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -356,7 +356,7 @@ scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, 14)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -410,7 +410,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -420,42 +420,42 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version!=1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size<12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_DEFAULT) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != 41) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -542,7 +542,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -551,21 +551,21 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } @@ -573,14 +573,14 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_DEFAULT) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -603,7 +603,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC /* if we got here, the requested sid wasn't one from the list we sent */ /* we should kill the connection */ - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (no such session in list)", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (no such session in list)", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } else if (cmd == 44) @@ -619,7 +619,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC else { /* wrong response */ - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -656,7 +656,7 @@ scp_v1s_reconnect_session(struct SCP_CONNECTION* c, SCP_DISPLAY d) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } diff --git a/sesman/libscp/libscp_v1s_mng.c b/sesman/libscp/libscp_v1s_mng.c index 266c9962..599545ab 100644 --- a/sesman/libscp/libscp_v1s_mng.c +++ b/sesman/libscp/libscp_v1s_mng.c @@ -30,7 +30,7 @@ #include "libscp_v1s_mng.h" -extern struct log_config* s_log; +//extern struct log_config* s_log; static enum SCP_SERVER_STATES_E _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s); @@ -259,7 +259,7 @@ scp_v1s_mng_list_sessions(struct SCP_CONNECTION* c, struct SCP_SESSION* s, if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -279,14 +279,14 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } @@ -296,21 +296,21 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) /* read the rest of the packet */ if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd == SCP_CMD_MNG_LIST_REQ) /* request session list */ { - log_message(s_log, LOG_LEVEL_INFO, "[v1s_mng:%d] request session list", __LINE__); + log_message(LOG_LEVEL_INFO, "[v1s_mng:%d] request session list", __LINE__); return SCP_SERVER_STATE_MNG_LISTREQ; } else if (cmd == SCP_CMD_MNG_ACTION) /* execute an action */ @@ -320,7 +320,7 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint8a(c->in_s, buf, dim); scp_session_set_errstr(s, buf);*/ - log_message(s_log, LOG_LEVEL_INFO, "[v1s_mng:%d] action request", __LINE__); + log_message(LOG_LEVEL_INFO, "[v1s_mng:%d] action request", __LINE__); return SCP_SERVER_STATE_MNG_ACTION; } /* else if (cmd == 20) / * password change * / @@ -334,7 +334,7 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) return SCP_SERVER_STATE_SESSION_LIST; }*/ - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } diff --git a/sesman/lock.c b/sesman/lock.c index d5a91af6..83023cba 100644 --- a/sesman/lock.c +++ b/sesman/lock.c @@ -55,7 +55,7 @@ void APP_CC lock_chain_acquire(void) { /* lock the chain */ - LOG_DBG(&(g_cfg->log), "lock_chain_acquire()"); + LOG_DBG("lock_chain_acquire()"); tc_mutex_lock(g_lock_chain); } @@ -64,7 +64,7 @@ void APP_CC lock_chain_release(void) { /* unlock the chain */ - LOG_DBG(&(g_cfg->log), "lock_chain_release()"); + LOG_DBG("lock_chain_release()"); tc_mutex_unlock(g_lock_chain); } @@ -73,7 +73,7 @@ void APP_CC lock_socket_acquire(void) { /* lock socket variable */ - LOG_DBG(&(g_cfg->log), "lock_socket_acquire()"); + LOG_DBG("lock_socket_acquire()"); tc_sem_dec(g_lock_socket); } @@ -82,7 +82,7 @@ void APP_CC lock_socket_release(void) { /* unlock socket variable */ - LOG_DBG(&(g_cfg->log), "lock_socket_release()"); + LOG_DBG("lock_socket_release()"); tc_sem_inc(g_lock_socket); } @@ -91,7 +91,7 @@ void APP_CC lock_sync_acquire(void) { /* lock sync variable */ - LOG_DBG(&(g_cfg->log), "lock_sync_acquire()"); + LOG_DBG("lock_sync_acquire()"); tc_mutex_lock(g_sync_mutex); } @@ -100,7 +100,7 @@ void APP_CC lock_sync_release(void) { /* unlock socket variable */ - LOG_DBG(&(g_cfg->log), "lock_sync_release()"); + LOG_DBG("lock_sync_release()"); tc_mutex_unlock(g_sync_mutex); } @@ -109,7 +109,7 @@ void APP_CC lock_sync_sem_acquire(void) { /* dec sem */ - LOG_DBG(&(g_cfg->log), "lock_sync_sem_acquire()"); + LOG_DBG("lock_sync_sem_acquire()"); tc_sem_dec(g_sync_sem); } @@ -118,6 +118,6 @@ void APP_CC lock_sync_sem_release(void) { /* inc sem */ - LOG_DBG(&(g_cfg->log), "lock_sync_sem_release()"); + LOG_DBG("lock_sync_sem_release()"); tc_sem_inc(g_sync_sem); } diff --git a/sesman/scp.c b/sesman/scp.c index 439c046c..bbe495ea 100644 --- a/sesman/scp.c +++ b/sesman/scp.c @@ -43,7 +43,7 @@ scp_process_start(void* sck) /* making a local copy of the socket (it's on the stack) */ /* probably this is just paranoia */ scon.in_sck = g_thread_sck; - LOG_DBG(&(g_cfg->log), "started scp thread on socket %d", scon.in_sck); + LOG_DBG("started scp thread on socket %d", scon.in_sck); /* unlocking g_thread_sck */ lock_socket_release(); @@ -60,40 +60,40 @@ scp_process_start(void* sck) if (sdata->version == 0) { /* starts processing an scp v0 connection */ - LOG_DBG(&(g_cfg->log), "accept ok, go on with scp v0\n",0); + LOG_DBG("accept ok, go on with scp v0\n",0); scp_v0_process(&scon, sdata); } else { - LOG_DBG(&(g_cfg->log), "accept ok, go on with scp v1\n",0); - /*LOG_DBG(&(g_cfg->log), "user: %s\npass: %s",sdata->username, sdata->password);*/ + LOG_DBG("accept ok, go on with scp v1\n",0); + /*LOG_DBG("user: %s\npass: %s",sdata->username, sdata->password);*/ scp_v1_process(&scon, sdata); } break; case SCP_SERVER_STATE_START_MANAGE: /* starting a management session */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "starting a sesman management session..."); scp_v1_mng_process(&scon, sdata); break; case SCP_SERVER_STATE_VERSION_ERR: /* an unknown scp version was requested, so we shut down the */ /* connection (and log the fact) */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "unknown protocol version specified. connection refused."); break; case SCP_SERVER_STATE_NETWORK_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp network error."); + log_message(LOG_LEVEL_WARNING, "libscp network error."); break; case SCP_SERVER_STATE_SEQUENCE_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp sequence error."); + log_message(LOG_LEVEL_WARNING, "libscp sequence error."); break; case SCP_SERVER_STATE_INTERNAL_ERR: /* internal error occurred (eg. malloc() error, ecc.) */ - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "libscp internal error occurred."); + log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "unknown return from scp_vXs_accept()"); + log_message(LOG_LEVEL_ALWAYS, "unknown return from scp_vXs_accept()"); } g_tcp_close(scon.in_sck); free_stream(scon.in_s); diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c index 886aaa29..092585cf 100644 --- a/sesman/scp_v0.c +++ b/sesman/scp_v0.c @@ -40,8 +40,7 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) struct session_item* s_item; data = auth_userpass(s->username, s->password); - - if (data) + if (s->type == SCP_GW_AUTHENTICATION) { s_item = session_get_bydata(s->username, s->width, s->height, s->bpp, s->type); @@ -60,42 +59,51 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) display = s_item->display; if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, s_item->pid, s->client_ip); + log_message( LOG_LEVEL_INFO, "++ reconnected session: username %s, " + "display :%d.0, session_pid %d, ip %s", + s->username, display, s_item->pid, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, s_item->pid); + log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, " + "display :%d.0, session_pid %d", s->username, display, + s_item->pid); } + session_reconnect(display, s->username); auth_end(data); /* don't set data to null here */ } else { - LOG_DBG(&(g_cfg->log), "pre auth"); + LOG_DBG("pre auth"); if (1 == access_login_allowed(s->username)) { if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s, ip %s", s->username, s->client_ip); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): " + "username %s, ip %s", s->username, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s", s->username); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): " + "username %s", s->username); } if (SCP_SESSION_TYPE_XVNC == s->type) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xvnc session..."); + log_message( LOG_LEVEL_INFO, "starting Xvnc session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XVNC, - s->domain, s->program, s->directory, s->client_ip); + s->domain, s->program, s->directory, + s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting X11rdp session..."); + log_message(LOG_LEVEL_INFO, "starting X11rdp session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XRDP, - s->domain, s->program, s->directory, s->client_ip); + s->domain, s->program, s->directory, + s->client_ip); } } else @@ -118,4 +126,3 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) scp_v0s_deny_connection(c); } } - diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c index beb1c36b..d83dd7bc 100644 --- a/sesman/scp_v1.c +++ b/sesman/scp_v1.c @@ -58,9 +58,11 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) while ((!data) && ((retries == 0) || (current_try > 0))) { - LOG_DBG(&(g_cfg->log), "data %d - retry %d - currenttry %d - expr %d", data, retries, current_try, ((!data) && ((retries==0) || (current_try>0)))); + LOG_DBG("data %d - retry %d - currenttry %d - expr %d", + data, retries, current_try, + ((!data) && ((retries == 0) || (current_try > 0)))); - e=scp_v1s_request_password(c,s,"Wrong username and/or password"); + e = scp_v1s_request_password(c, s, "Wrong username and/or password"); switch (e) { @@ -85,7 +87,7 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (!data) { scp_v1s_deny_connection(c, "Login failed"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message( LOG_LEVEL_INFO, "Login failed for user %s. Connection terminated", s->username); scp_session_destroy(s); return; @@ -95,7 +97,7 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0 == access_login_allowed(s->username)) { scp_v1s_deny_connection(c, "Access to Terminal Server not allowed."); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "User %s not allowed on TS. Connection terminated", s->username); scp_session_destroy(s); return; @@ -116,24 +118,26 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (scount == 0) { /* no disconnected sessions - start a new one */ + log_message(LOG_LEVEL_DEBUG,"No disconnected sessions for this user" + "- we create a new one"); if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s, ip %s", s->username, s->client_ip); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): username %s, ip %s", s->username, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s", s->username); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): username %s", s->username); } if (SCP_SESSION_TYPE_XVNC == s->type) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xvnc session..."); + log_message(LOG_LEVEL_INFO, "starting Xvnc session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XVNC, s->domain, s->program, s->directory, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting X11rdp session..."); + log_message(LOG_LEVEL_INFO, "starting X11rdp session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XRDP, s->domain, s->program, s->directory, s->client_ip); @@ -161,28 +165,28 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) /*case SCP_SERVER_STATE_FORCE_NEW:*/ /* we should check for MaxSessions */ case SCP_SERVER_STATE_SELECTION_CANCEL: - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "Connection cancelled after session listing"); + log_message( LOG_LEVEL_INFO, "Connection cancelled after session listing"); break; case SCP_SERVER_STATE_OK: /* ok, reconnecting... */ sitem=session_get_bypid(sid); - if (0==sitem) + if (0 == sitem) { - e=scp_v1s_connection_error(c, "Internal error"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "Cannot find session item on the chain"); + e = scp_v1s_connection_error(c, "Internal error"); + log_message(LOG_LEVEL_INFO, "Cannot find session item on the chain"); } else { - display=sitem->display; + display = sitem->display; /*e=scp_v1s_reconnect_session(c, sitem, display);*/ e=scp_v1s_reconnect_session(c, display); if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, sitem->pid, s->client_ip); + log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, sitem->pid, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, sitem->pid); + log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, sitem->pid); } g_free(sitem); } @@ -211,27 +215,27 @@ static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f) switch (e) { case SCP_SERVER_STATE_VERSION_ERR: - LOG_DBG(&(g_cfg->log), "version error") + LOG_DBG("version error") case SCP_SERVER_STATE_SIZE_ERR: /* an unknown scp version was requested, so we shut down the */ /* connection (and log the fact) */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "protocol violation. connection closed."); break; case SCP_SERVER_STATE_NETWORK_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp network error."); + log_message(LOG_LEVEL_WARNING, "libscp network error."); break; case SCP_SERVER_STATE_SEQUENCE_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp sequence error."); + log_message(LOG_LEVEL_WARNING, "libscp sequence error."); break; case SCP_SERVER_STATE_INTERNAL_ERR: /* internal error occurred (eg. malloc() error, ecc.) */ - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "libscp internal error occurred."); + log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); break; default: /* dummy: scp_v1s_request_password won't generate any other */ /* error other than the ones before */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "unknown return from %s", f); + log_message(LOG_LEVEL_ALWAYS, "unknown return from %s", f); break; } } diff --git a/sesman/scp_v1_mng.c b/sesman/scp_v1_mng.c index a1773225..e4d97b77 100644 --- a/sesman/scp_v1_mng.c +++ b/sesman/scp_v1_mng.c @@ -49,7 +49,7 @@ scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (!data) { scp_v1s_mng_deny_connection(c, "Login failed"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "[MNG] Login failed for user %s. Connection terminated", s->username); scp_session_destroy(s); auth_end(data); @@ -60,7 +60,7 @@ scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0 == access_login_mng_allowed(s->username)) { scp_v1s_mng_deny_connection(c, "Access to Terminal Server not allowed."); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "[MNG] User %s not allowed on TS. Connection terminated", s->username); scp_session_destroy(s); auth_end(data); @@ -75,18 +75,18 @@ scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) switch (e) { case SCP_SERVER_STATE_MNG_ACTION: - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "Connection cancelled after session listing"); + log_message(LOG_LEVEL_INFO, "Connection cancelled after session listing"); break; case SCP_SERVER_STATE_MNG_LISTREQ: /* list disconnected sessions */ slist = session_get_byuser(NULL, &scount, SESMAN_SESSION_STATUS_ALL); - LOG_DBG(&(g_cfg->log), "sessions on TS: %d (slist: %x)", scount, slist); + LOG_DBG("sessions on TS: %d (slist: %x)", scount, slist); if (0 == slist) { // e=scp_v1s_connection_error(c, "Internal error"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "No sessions on Terminal Server"); + log_message(LOG_LEVEL_INFO, "No sessions on Terminal Server"); end = 0; } else @@ -114,27 +114,27 @@ static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f) switch (e) { case SCP_SERVER_STATE_VERSION_ERR: - LOG_DBG(&(g_cfg->log), "version error") + LOG_DBG("version error") case SCP_SERVER_STATE_SIZE_ERR: /* an unknown scp version was requested, so we shut down the */ /* connection (and log the fact) */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "protocol violation. connection closed."); break; case SCP_SERVER_STATE_NETWORK_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp network error."); + log_message(LOG_LEVEL_WARNING, "libscp network error."); break; case SCP_SERVER_STATE_SEQUENCE_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp sequence error."); + log_message(LOG_LEVEL_WARNING, "libscp sequence error."); break; case SCP_SERVER_STATE_INTERNAL_ERR: /* internal error occurred (eg. malloc() error, ecc.) */ - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "libscp internal error occurred."); + log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); break; default: /* dummy: scp_v1s_request_password won't generate any other */ /* error other than the ones before */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "unknown return from %s", f); + log_message(LOG_LEVEL_ALWAYS, "unknown return from %s", f); break; } } diff --git a/sesman/sesman.c b/sesman/sesman.c index 5a230417..b882c49d 100644 --- a/sesman/sesman.c +++ b/sesman/sesman.c @@ -54,7 +54,7 @@ sesman_main_loop(void) tbus robjs[8]; /*main program loop*/ - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "listening..."); + log_message(LOG_LEVEL_INFO, "listening..."); g_sck = g_tcp_socket(); g_tcp_set_non_blocking(g_sck); error = scp_tcp_bind(g_sck, g_cfg->listen_address, g_cfg->listen_port); @@ -103,7 +103,7 @@ sesman_main_loop(void) else { /* we've got a connection, so we pass it to scp code */ - LOG_DBG(&(g_cfg->log), "new connection"); + LOG_DBG("new connection"); thread_scp_start(in_sck); /* todo, do we have to wait here ? */ } @@ -113,13 +113,13 @@ sesman_main_loop(void) } else { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "listen error %d (%s)", + log_message(LOG_LEVEL_ERROR, "listen error %d (%s)", g_get_errno(), g_get_strerror()); } } else { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "bind error on " + log_message(LOG_LEVEL_ERROR, "bind error on " "port '%s': %d (%s)", g_cfg->listen_port, g_get_errno(), g_get_strerror()); } @@ -131,12 +131,13 @@ int DEFAULT_CC main(int argc, char** argv) { int fd; - int error; + enum logReturns error; int daemon = 1; int pid; char pid_s[8]; char text[256]; char pid_file[256]; + char cfg_file[256]; g_init("xrdp-sesman"); g_snprintf(pid_file, 255, "%s/xrdp-sesman.pid", XRDP_PID_PATH); @@ -242,7 +243,7 @@ main(int argc, char** argv) g_deinit(); g_exit(1); } - g_cfg->log.fd = -1; /* don't use logging before reading its config */ + //g_cfg->log.fd = -1; /* don't use logging before reading its config */ if (0 != config_read(g_cfg)) { g_printf("error reading config: %s\nquitting.\n", g_get_strerror()); @@ -250,18 +251,21 @@ main(int argc, char** argv) g_exit(1); } + g_snprintf(cfg_file,255,"%s/sesman.ini",XRDP_CFG_PATH); + /* starting logging subsystem */ - error = log_start(&(g_cfg->log)); + error = log_start(cfg_file,"XRDP-sesman"); if (error != LOG_STARTUP_OK) { switch (error) { case LOG_ERROR_MALLOC: - g_printf("error on malloc. cannot start logging. quitting.\n"); + g_writeln("error on malloc. cannot start logging. quitting."); break; case LOG_ERROR_FILE_OPEN: - g_printf("error opening log file [%s]. quitting.\n", g_cfg->log.log_file); + g_writeln("error opening log file [%s]. quitting.", + getLogFile(text, 255)); break; } g_deinit(); @@ -269,7 +273,7 @@ main(int argc, char** argv) } /* libscp initialization */ - scp_init(&(g_cfg->log)); + scp_init(); if (daemon) { @@ -317,10 +321,10 @@ main(int argc, char** argv) fd = g_file_open(pid_file); if (-1 == fd) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, + log_message(LOG_LEVEL_ERROR, "error opening pid file[%s]: %s", pid_file, g_get_strerror()); - log_end(&(g_cfg->log)); + log_end(); g_deinit(); g_exit(1); } @@ -330,7 +334,7 @@ main(int argc, char** argv) } /* start program main loop */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, + log_message(LOG_LEVEL_ALWAYS, "starting sesman with pid %d", g_pid); /* make sure the /tmp/.X11-unix directory exist */ @@ -358,10 +362,9 @@ main(int argc, char** argv) if (!daemon) { - log_end(&(g_cfg->log)); + log_end(); } g_deinit(); return 0; } - diff --git a/sesman/sesman.ini b/sesman/sesman.ini index 1d1d16bf..7f194074 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -19,9 +19,9 @@ IdleTimeLimit=0 DisconnectedTimeLimit=0 [Logging] -LogFile=/var/log/xrdp-sesman.log +LogFile=xrdp-sesman.log LogLevel=DEBUG -EnableSyslog=0 +EnableSyslog=1 SyslogLevel=DEBUG #[X11rdp] diff --git a/sesman/session.c b/sesman/session.c index 81484b80..46037187 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -60,6 +60,40 @@ static char* g_sync_client_ip; static tbus g_sync_data; static tui8 g_sync_type; static int g_sync_result; +static int g_sync_cmd; + +/** + * Creates a string consisting of all parameters that is hosted in the param list + * @param self + * @param outstr, allocate this buffer before you use this function + * @param len the allocated len for outstr + * @return + */ +char* APP_CC +dumpItemsToString(struct list* self, char *outstr, int len) +{ + g_memset(outstr,0,len); + int index; + tbus item; + int totalLen= 0; + + if (self->count == 0) + { + g_writeln("List is empty"); + } + for (index = 0; index < self->count; index++) + { + /* +1 = one space*/ + totalLen = totalLen + g_strlen((char*)list_get_item(self, index))+1; + if(len>totalLen) + { + g_strcat(outstr,(char*)list_get_item(self, index)); + g_strcat(outstr," "); + } + } + return outstr ; +} + /******************************************************************************/ struct session_item* DEFAULT_CC @@ -267,7 +301,7 @@ x_server_running(int display) /******************************************************************************/ static void DEFAULT_CC -session_start_sessvc(int xpid, int wmpid, long data) +session_start_sessvc(int xpid, int wmpid, long data, char* username, int display) { struct list * sessvc_params = (struct list *)NULL; char wmpid_str[25]; @@ -283,7 +317,7 @@ session_start_sessvc(int xpid, int wmpid, long data) /* new style waiting for clients */ g_sprintf(wmpid_str, "%d", wmpid); g_sprintf(xpid_str, "%d", xpid); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "starting xrdp-sessvc - xpid=%s - wmpid=%s", xpid_str, wmpid_str); @@ -298,23 +332,25 @@ session_start_sessvc(int xpid, int wmpid, long data) list_add_item(sessvc_params, (long)g_strdup(wmpid_str)); list_add_item(sessvc_params, 0); /* mandatory */ + env_set_user(username, 0, display); + /* executing sessvc */ g_execvp(exe_path, ((char**)sessvc_params->items)); /* should not get here */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, + log_message(LOG_LEVEL_ALWAYS, "error starting xrdp-sessvc - pid %d - xpid=%s - wmpid=%s", g_getpid(), xpid_str, wmpid_str); /* logging parameters */ /* no problem calling strerror for thread safety: other threads are blocked */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: %s", + log_message(LOG_LEVEL_DEBUG, "errno: %d, description: %s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "execve parameter list:"); + log_message(LOG_LEVEL_DEBUG, "execve parameter list:"); for (i = 0; i < (sessvc_params->count); i++) { - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[%d] = %s", i, + log_message(LOG_LEVEL_DEBUG, " argv[%d] = %s", i, (char*)list_get_item(sessvc_params, i)); } list_delete(sessvc_params); @@ -372,7 +408,7 @@ session_get_aval_display_from_chain(void) display++; } lock_chain_release(); - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "X server -- no display in range is available"); + log_message(LOG_LEVEL_ERROR, "X server -- no display in range is available"); return 0; } @@ -391,7 +427,7 @@ wait_for_xserver(int display) i++; if (i > 60) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, + log_message(LOG_LEVEL_ERROR, "X server for display %d startup timeout", display); break; @@ -474,6 +510,7 @@ session_start_fork(int width, int height, int bpp, char* username, struct list * xserver_params = (struct list *)NULL; time_t ltime; struct tm stime; + char execvpparams[2048]; /* initialize (zero out) local variables: */ g_memset(<ime,0,sizeof(time_t)); @@ -489,7 +526,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star /* check to limit concurrent sessions */ if (g_session_count >= g_cfg->sess.max_sessions) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "max concurrent session limit " + log_message(LOG_LEVEL_INFO, "max concurrent session limit " "exceeded. login for user %s denied", username); return 0; } @@ -497,7 +534,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star temp = (struct session_chain*)g_malloc(sizeof(struct session_chain), 0); if (temp == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "cannot create new chain " + log_message(LOG_LEVEL_ERROR, "cannot create new chain " "element - user %s", username); return 0; } @@ -505,7 +542,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star if (temp->item == 0) { g_free(temp); - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "cannot create new session " + log_message(LOG_LEVEL_ERROR, "cannot create new session " "item - user %s", username); return 0; } @@ -599,7 +636,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star if (program[0] != 0) { g_execlp3(program, program, 0); - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, + log_message(LOG_LEVEL_ALWAYS, "error starting program %s for user %s - pid %d", program, username, g_getpid()); } @@ -611,16 +648,16 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star if (g_file_exist(text)) { g_execlp3(text, g_cfg->user_wm, 0); - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting user " + log_message(LOG_LEVEL_ALWAYS,"error starting user " "wm for user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, " + log_message(LOG_LEVEL_DEBUG, "errno: %d, " "description: %s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,"execlp3 parameter " + log_message(LOG_LEVEL_DEBUG,"execlp3 parameter " "list:"); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[0] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[0] = %s", text); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[1] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[1] = %s", g_cfg->user_wm); } } @@ -629,25 +666,25 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star g_sprintf(text, "%s/%s", XRDP_CFG_PATH, g_cfg->default_wm); g_execlp3(text, g_cfg->default_wm, 0); - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting default " + log_message( LOG_LEVEL_ALWAYS,"error starting default " "wm for user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: " + log_message( LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,"execlp3 parameter list:"); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[0] = %s", + log_message(LOG_LEVEL_DEBUG,"execlp3 parameter list:"); + log_message(LOG_LEVEL_DEBUG, " argv[0] = %s", text); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[1] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[1] = %s", g_cfg->default_wm); /* still a problem starting window manager just start xterm */ g_execlp3("xterm", "xterm", 0); /* should not get here */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting xterm " + log_message(LOG_LEVEL_ALWAYS,"error starting xterm " "for user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: " + log_message(LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); } else @@ -656,7 +693,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "another Xserver is " "already active on display %d", display); } - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,"aborting connection..."); + log_message(LOG_LEVEL_DEBUG,"aborting connection..."); g_exit(0); } else /* parent (child sesman) */ @@ -691,6 +728,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star /* make sure it ends with a zero */ list_add_item(xserver_params, 0); pp1 = (char**)xserver_params->items; + log_message(LOG_LEVEL_INFO,"Xvnc start:%s",dumpItemsToString(xserver_params, execvpparams, 2048)); g_execvp("Xvnc", pp1); } else if (type == SESMAN_SESSION_TYPE_XRDP) @@ -743,24 +781,24 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star } else { - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "bad session type - " + log_message(LOG_LEVEL_ALWAYS, "bad session type - " "user %s - pid %d", username, g_getpid()); g_exit(1); } /* should not get here */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "error starting X server " + log_message(LOG_LEVEL_ALWAYS, "error starting X server " "- user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: " + log_message(LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "execve parameter list: " + log_message(LOG_LEVEL_DEBUG, "execve parameter list size: " "%d", (xserver_params)->count); for (i=0; i<(xserver_params->count); i++) { - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[%d] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[%d] = %s", i, (char*)list_get_item(xserver_params, i)); } list_delete(xserver_params); @@ -777,7 +815,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star g_snprintf(text, 255, ":%d.0", display); g_setenv("DISPLAY", text, 1); /* new style waiting for clients */ - session_start_sessvc(xpid, wmpid, data); + session_start_sessvc(xpid, wmpid, data, username, display); } } } @@ -813,6 +851,31 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star } /******************************************************************************/ +/* called with the main thread */ +static int APP_CC +session_reconnect_fork(int display, char* username) +{ + int pid; + char text[256]; + + pid = g_fork(); + if (pid == -1) + { + } + else if (pid == 0) + { + env_set_user(username, 0, display); + g_snprintf(text, 255, "%s/%s", XRDP_CFG_PATH, "reconnectwm.sh"); + if (g_file_exist(text)) + { + g_execlp3(text, g_cfg->default_wm, 0); + } + g_exit(0); + } + return display; +} + +/******************************************************************************/ /* called by a worker thread, ask the main thread to call session_sync_start and wait till done */ int DEFAULT_CC @@ -826,6 +889,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 258.0] In session_star /* lock mutex */ lock_sync_acquire(); /* set shared vars */ + g_sync_cmd = 0; g_sync_width = width; g_sync_height = height; g_sync_bpp = bpp; @@ -849,6 +913,27 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 258.0] In session_star } /******************************************************************************/ +/* called by a worker thread, ask the main thread to call session_sync_start + and wait till done */ +int DEFAULT_CC +session_reconnect(int display, char* username) +{ + /* lock mutex */ + lock_sync_acquire(); + /* set shared vars */ + g_sync_cmd = 1; + g_sync_width = display; + g_sync_username = username; + /* set event for main thread to see */ + g_set_wait_obj(g_sync_event); + /* wait for main thread to get done */ + lock_sync_sem_acquire(); + /* unlock mutex */ + lock_sync_release(); + return 0; +} + +/******************************************************************************/ /* called with the main thread */ int APP_CC session_sync_start(void) @@ -879,7 +964,7 @@ session_kill(int pid) { if (tmp->item == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "session descriptor for " + log_message(LOG_LEVEL_ERROR, "session descriptor for " "pid %d is null!", pid); if (prev == 0) { @@ -899,7 +984,7 @@ session_kill(int pid) if (tmp->item->pid == pid) { /* deleting the session */ - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s", tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip); + log_message(LOG_LEVEL_INFO, "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s", tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip); g_free(tmp->item); if (prev == 0) { @@ -943,7 +1028,7 @@ session_sigkill_all() { if (tmp->item == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "found null session " + log_message(LOG_LEVEL_ERROR, "found null session " "descriptor!"); } else @@ -969,7 +1054,7 @@ session_get_bypid(int pid) dummy = g_malloc(sizeof(struct session_item), 1); if (0 == dummy) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "internal error", pid); + log_message(LOG_LEVEL_ERROR, "internal error", pid); return 0; } @@ -981,7 +1066,7 @@ session_get_bypid(int pid) { if (tmp->item == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "session descriptor for " + log_message(LOG_LEVEL_ERROR, "session descriptor for " "pid %d is null!", pid); /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -1015,7 +1100,7 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) int count; int index; - count=0; + count = 0; /*THREAD-FIX require chain lock */ lock_chain_acquire(); @@ -1023,10 +1108,10 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) tmp = g_sessions; while (tmp != 0) { - LOG_DBG(&(g_cfg->log), "user: %s", user); + LOG_DBG("user: %s", user); if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256))) { - LOG_DBG(&(g_cfg->log), "session_get_byuser: status=%d, flags=%d, " + LOG_DBG("session_get_byuser: status=%d, flags=%d, " "result=%d", (tmp->item->status), flags, ((tmp->item->status) & flags)); if ((tmp->item->status) & flags) @@ -1039,9 +1124,9 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) tmp=tmp->next; } - if (count==0) + if (count == 0) { - (*cnt)=0; + (*cnt) = 0; /*THREAD-FIX release chain lock */ lock_chain_release(); return 0; @@ -1049,9 +1134,9 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) /* malloc() an array of disconnected sessions */ sess=g_malloc(count * sizeof(struct SCP_DISCONNECTED_SESSION),1); - if (sess==0) + if (sess == 0) { - (*cnt)=0; + (*cnt) = 0; /*THREAD-FIX release chain lock */ lock_chain_release(); return 0; diff --git a/sesman/session.h b/sesman/session.h index 23aed823..a8de90d5 100644 --- a/sesman/session.h +++ b/sesman/session.h @@ -107,6 +107,9 @@ session_start(int width, int height, int bpp, char* username, char* password, long data, tui8 type, char* domain, char* program, char* directory, char* client_ip); +int DEFAULT_CC +session_reconnect(int display, char* username); + /** * * @brief starts a session @@ -156,4 +159,3 @@ struct SCP_DISCONNECTED_SESSION* session_get_byuser(char* user, int* cnt, unsigned char flags); #endif - diff --git a/sesman/sessvc/Makefile.am b/sesman/sessvc/Makefile.am index 67740781..8ba24abd 100644 --- a/sesman/sessvc/Makefile.am +++ b/sesman/sessvc/Makefile.am @@ -15,4 +15,4 @@ xrdp_sessvc_SOURCES = \ sessvc.c xrdp_sessvc_LDADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff --git a/sesman/sig.c b/sesman/sig.c index 24f2e81c..151c0c57 100644 --- a/sesman/sig.c +++ b/sesman/sig.c @@ -40,15 +40,15 @@ sig_sesman_shutdown(int sig) { char pid_file[256]; - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "shutting down sesman %d", 1); + log_message(LOG_LEVEL_INFO, "shutting down sesman %d", 1); if (g_getpid() != g_pid) { - LOG_DBG(&(g_cfg->log), "g_getpid() [%d] differs from g_pid [%d]", (g_getpid()), g_pid); + LOG_DBG("g_getpid() [%d] differs from g_pid [%d]", (g_getpid()), g_pid); return; } - LOG_DBG(&(g_cfg->log), " - getting signal %d pid %d", sig, g_getpid()); + LOG_DBG(" - getting signal %d pid %d", sig, g_getpid()); g_set_wait_obj(g_term_event); @@ -66,51 +66,55 @@ sig_sesman_reload_cfg(int sig) { int error; struct config_sesman *cfg; + char cfg_file[256]; - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "receiving SIGHUP %d", 1); + log_message(LOG_LEVEL_WARNING, "receiving SIGHUP %d", 1); if (g_getpid() != g_pid) { - LOG_DBG(&(g_cfg->log), "g_getpid() [%d] differs from g_pid [%d]", g_getpid(), g_pid); + LOG_DBG("g_getpid() [%d] differs from g_pid [%d]", g_getpid(), g_pid); return; } cfg = g_malloc(sizeof(struct config_sesman), 1); if (0 == cfg) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "error creating new config: - keeping old cfg"); + log_message(LOG_LEVEL_ERROR, "error creating new config: - keeping old cfg"); return; } if (config_read(cfg) != 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "error reading config - keeping old cfg"); + log_message(LOG_LEVEL_ERROR, "error reading config - keeping old cfg"); return; } /* stop logging subsystem */ - log_end(&(g_cfg->log)); + log_end(); /* replace old config with new readed one */ g_cfg = cfg; + + g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH); /* start again logging subsystem */ - error = log_start(&(g_cfg->log)); + error = log_start(cfg_file,"XRDP-sesman"); if (error != LOG_STARTUP_OK) { + char buf[256]; switch (error) { case LOG_ERROR_MALLOC: g_printf("error on malloc. cannot restart logging. log stops here, sorry.\n"); break; case LOG_ERROR_FILE_OPEN: - g_printf("error reopening log file [%s]. log stops here, sorry.\n", g_cfg->log.log_file); + g_printf("error reopening log file [%s]. log stops here, sorry.\n", getLogFile(buf,255)); break; } } - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "configuration reloaded, log subsystem restarted"); + log_message(LOG_LEVEL_INFO, "configuration reloaded, log subsystem restarted"); } /******************************************************************************/ @@ -166,27 +170,27 @@ sig_handler_thread(void* arg) case SIGHUP: //reload cfg //we must stop & restart logging, or copy logging cfg!!!! - LOG_DBG(&(g_cfg->log), "sesman received SIGHUP", 0); + LOG_DBG("sesman received SIGHUP", 0); //return 0; break; case SIGCHLD: /* a session died */ - LOG_DBG(&(g_cfg->log), "sesman received SIGCHLD", 0); + LOG_DBG("sesman received SIGCHLD", 0); sig_sesman_session_end(SIGCHLD); break; case SIGINT: /* we die */ - LOG_DBG(&(g_cfg->log), "sesman received SIGINT", 0); + LOG_DBG("sesman received SIGINT", 0); sig_sesman_shutdown(recv_signal); break; case SIGKILL: /* we die */ - LOG_DBG(&(g_cfg->log), "sesman received SIGKILL", 0); + LOG_DBG("sesman received SIGKILL", 0); sig_sesman_shutdown(recv_signal); break; case SIGTERM: /* we die */ - LOG_DBG(&(g_cfg->log), "sesman received SIGTERM", 0); + LOG_DBG("sesman received SIGTERM", 0); sig_sesman_shutdown(recv_signal); break; } diff --git a/sesman/thread.c b/sesman/thread.c index 986a5d27..98a92533 100644 --- a/sesman/thread.c +++ b/sesman/thread.c @@ -22,7 +22,7 @@ * @file thread.c * @brief thread stuff... * @author Simone Fedele - * + * */ #include "sesman.h" @@ -62,14 +62,14 @@ thread_sighandler_start(void) sigaddset(&waitmask, SIGFPE); pthread_sigmask(SIG_UNBLOCK, &waitmask, NULL); - log_message(&(g_cfg->log), LOG_LEVEL_INFO,"starting signal handling thread..."); + log_message(LOG_LEVEL_INFO,"starting signal handling thread..."); ret = pthread_create(&g_thread_sighandler, NULL, sig_handler_thread, ""); pthread_detach(g_thread_sighandler); if (ret == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "signal handler thread started successfully"); + log_message(LOG_LEVEL_INFO, "signal handler thread started successfully"); return 0; } @@ -77,16 +77,16 @@ thread_sighandler_start(void) switch (ret) { case EINVAL: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid attributes for signal handling thread (creation returned EINVAL)"); + log_message(LOG_LEVEL_ERROR, "invalid attributes for signal handling thread (creation returned EINVAL)"); break; case EAGAIN: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "not enough resources to start signal handling thread (creation returned EAGAIN)"); + log_message(LOG_LEVEL_ERROR, "not enough resources to start signal handling thread (creation returned EAGAIN)"); break; case EPERM: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid permissions for signal handling thread (creation returned EPERM)"); + log_message(LOG_LEVEL_ERROR, "invalid permissions for signal handling thread (creation returned EPERM)"); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "unknown error starting signal handling thread"); + log_message(LOG_LEVEL_ERROR, "unknown error starting signal handling thread"); } return 1; @@ -100,13 +100,13 @@ thread_session_update_start(void) int ret; //starts the session update thread //that checks for idle time, destroys sessions, ecc... - -#warning this thread should always request lock_fork before read or write + +#warning this thread should always request lock_fork before read or write #warning (so we can Fork() In Peace) ret = pthread_create(&g_thread_updater, NULL, , ""); pthread_detach(g_thread_updater); - if (ret==0) + if (ret == 0) { log_message(&(g_cfg->log), LOG_LEVEL_INFO, "session update thread started successfully"); return 0; @@ -116,16 +116,16 @@ thread_session_update_start(void) switch (ret) { case EINVAL: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid attributes for session update thread (creation returned EINVAL)"); + log_message(LOG_LEVEL_ERROR, "invalid attributes for session update thread (creation returned EINVAL)"); break; case EAGAIN: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "not enough resources to start session update thread (creation returned EAGAIN)"); + log_message(LOG_LEVEL_ERROR, "not enough resources to start session update thread (creation returned EAGAIN)"); break; case EPERM: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid permissions for session update thread (creation returned EPERM)"); + log_message(LOG_LEVEL_ERROR, "invalid permissions for session update thread (creation returned EPERM)"); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "unknown error starting session update thread"); + log_message(LOG_LEVEL_ERROR, "unknown error starting session update thread"); } return 1; @@ -148,9 +148,9 @@ thread_scp_start(int skt) //ret = pthread_create(&th, NULL, scp_process_start, (void*) (&g_thread_sck)); pthread_detach(th); - if (ret == 0) + if (ret == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "scp thread on sck %d started successfully", skt); + log_message(LOG_LEVEL_INFO, "scp thread on sck %d started successfully", skt); return 0; } @@ -158,18 +158,17 @@ thread_scp_start(int skt) switch (ret) { case EINVAL: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid attributes for scp thread on sck %d (creation returned EINVAL)", skt); + log_message(LOG_LEVEL_ERROR, "invalid attributes for scp thread on sck %d (creation returned EINVAL)", skt); break; case EAGAIN: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "not enough resources to start scp thread on sck %d (creation returned EAGAIN)", skt); + log_message(LOG_LEVEL_ERROR, "not enough resources to start scp thread on sck %d (creation returned EAGAIN)", skt); break; case EPERM: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid permissions for scp thread on sck %d (creation returned EPERM)", skt); + log_message(LOG_LEVEL_ERROR, "invalid permissions for scp thread on sck %d (creation returned EPERM)", skt); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "unknown error starting scp thread on sck %d"); + log_message(LOG_LEVEL_ERROR, "unknown error starting scp thread on sck %d"); } return 1; } - diff --git a/sesman/tools/Makefile.am b/sesman/tools/Makefile.am index a48b0f11..ab3612d0 100644 --- a/sesman/tools/Makefile.am +++ b/sesman/tools/Makefile.am @@ -15,7 +15,8 @@ bin_PROGRAMS = \ xrdp-sesrun \ xrdp-sestest \ xrdp-sesadmin \ - xrdp-dis + xrdp-dis \ + xrdp-xcon xrdp_sesrun_SOURCES = \ sesrun.c \ @@ -31,14 +32,20 @@ xrdp_sesadmin_SOURCES = \ xrdp_dis_SOURCES = \ dis.c +xrdp_xcon_SOURCES = \ + xcon.c + xrdp_sesrun_LDADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la xrdp_sestest_LDADD = \ - $(top_srcdir)/common/libcommon.la \ - $(top_srcdir)/sesman/libscp/libscp.la + $(top_builddir)/common/libcommon.la \ + $(top_builddir)/sesman/libscp/libscp.la xrdp_sesadmin_LDADD = \ - $(top_srcdir)/common/libcommon.la \ - $(top_srcdir)/sesman/libscp/libscp.la + $(top_builddir)/common/libcommon.la \ + $(top_builddir)/sesman/libscp/libscp.la +xrdp_xcon_LDADD = \ + -L/usr/X11R6/lib \ + -lX11 diff --git a/sesman/tools/sesadmin.c b/sesman/tools/sesadmin.c index 4c612316..22f20c23 100644 --- a/sesman/tools/sesadmin.c +++ b/sesman/tools/sesadmin.c @@ -50,7 +50,7 @@ int main(int argc, char** argv) logging.log_file = g_strdup("xrdp-sesadmin.log"); logging.log_level = LOG_LEVEL_DEBUG; logging.enable_syslog = 0; - log_start(&logging); + log_start_from_param(&logging); for (idx = 0; idx < argc; idx++) { @@ -110,11 +110,11 @@ int main(int argc, char** argv) s = scp_session_create(); c = scp_connection_create(sock); - LOG_DBG(&logging, "Connecting to %s:%s with user %s (%s)\n", serv, port, user, pass); + LOG_DBG("Connecting to %s:%s with user %s (%s)\n", serv, port, user, pass); if (0 != g_tcp_connect(sock, serv, port)) { - LOG_DBG(&logging, "g_tcp_connect() error\n"); + LOG_DBG("g_tcp_connect() error\n"); return 1; } @@ -127,7 +127,7 @@ int main(int argc, char** argv) if (SCP_CLIENT_STATE_OK != e) { - LOG_DBG(&logging, "libscp error connecting: %s %d\n", s->errstr, (int)e); + LOG_DBG("libscp error connecting: %s %d\n", s->errstr, (int)e); } if (0 == g_strncmp(cmnd, "list", 5)) @@ -142,7 +142,7 @@ int main(int argc, char** argv) g_tcp_close(sock); scp_session_destroy(s); scp_connection_destroy(c); - log_end(&logging); + log_end(); return 0; } diff --git a/sesman/tools/sestest.c b/sesman/tools/sestest.c index 4382e160..c0784ba3 100644 --- a/sesman/tools/sestest.c +++ b/sesman/tools/sestest.c @@ -34,7 +34,7 @@ int main(int argc, char** argv) log.log_level=99; log.program_name=g_strdup("sestest"); log.log_file=g_strdup("sestest.log"); - log_start(&log); + log_start_from_param(&log); scp_init(&log); sock=g_tcp_socket(); @@ -206,7 +206,7 @@ menuSelect(tui32 choices) ret = scanf("%u", &sel); - while ((ret==0) || (sel > choices)) + while ((ret == 0) || (sel > choices)) { g_printf("invalid choice."); ret = scanf("%u", &sel); diff --git a/sesman/tools/xcon.c b/sesman/tools/xcon.c new file mode 100644 index 00000000..7a45a1cd --- /dev/null +++ b/sesman/tools/xcon.c @@ -0,0 +1,35 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/Xlib.h> + +Display* g_display = 0; +int g_x_socket = 0; + +int main(int argc, char** argv) +{ + fd_set rfds; + int i1; + XEvent xevent; + + g_display = XOpenDisplay(0); + if (g_display == 0) + { + printf("XOpenDisplay failed\n"); + return 0; + } + g_x_socket = XConnectionNumber(g_display); + while (1) + { + FD_ZERO(&rfds); + FD_SET(g_x_socket, &rfds); + i1 = select(g_x_socket + 1, &rfds, 0, 0, 0); + if (i1 < 0) + { + break; + } + XNextEvent(g_display, &xevent); + } + return 0; +} diff --git a/sesman/verify_user.c b/sesman/verify_user.c index cdc60b47..aaa1515c 100644 --- a/sesman/verify_user.c +++ b/sesman/verify_user.c @@ -302,21 +302,21 @@ auth_account_disabled(struct spwd* stp) { int today; - if (0==stp) + if (0 == stp) { /* if an invalid struct was passed we assume a disabled account */ return 1; } - today=g_time1()/SECS_PER_DAY; + today = g_time1() / SECS_PER_DAY; - LOG_DBG(&(g_cfg->log), "last %d",stp->sp_lstchg); - LOG_DBG(&(g_cfg->log), "min %d",stp->sp_min); - LOG_DBG(&(g_cfg->log), "max %d",stp->sp_max); - LOG_DBG(&(g_cfg->log), "inact %d",stp->sp_inact); - LOG_DBG(&(g_cfg->log), "warn %d",stp->sp_warn); - LOG_DBG(&(g_cfg->log), "expire %d",stp->sp_expire); - LOG_DBG(&(g_cfg->log), "today %d",today); + LOG_DBG("last %d",stp->sp_lstchg); + LOG_DBG("min %d",stp->sp_min); + LOG_DBG("max %d",stp->sp_max); + LOG_DBG("inact %d",stp->sp_inact); + LOG_DBG("warn %d",stp->sp_warn); + LOG_DBG("expire %d",stp->sp_expire); + LOG_DBG("today %d",today); if ((stp->sp_expire != -1) && (today >= stp->sp_expire)) { |