Merge branch 'devel' into v0.9
This commit is contained in:
commit
164e45b6d1
26
NEWS.md
26
NEWS.md
@ -1,3 +1,29 @@
|
||||
# Release notes for xrdp v0.9.9 (2018/12/25)
|
||||
|
||||
# Release cycle
|
||||
From the next release, release cycle will be changed from quarterly to every
|
||||
4 months. xrdp will be released in April, August, December.
|
||||
|
||||
# New features
|
||||
* Disconnection by idle timeout (requires xorgxrdp v0.2.9 or later) #1227
|
||||
* Glyph cache v2 (fixes no font issue on iOS/macOS/Android client) #367 #1235
|
||||
|
||||
# Bug fixes
|
||||
* Fix xrdp-chansrv crashes caused in drive redirection #1202 #1225
|
||||
* Fix build with FDK AAC v2 #1257
|
||||
* Do not enable RemoteApp if the INFO_RAIL flag is not set (RDP-RDP proxy) #1253
|
||||
|
||||
# Other changes
|
||||
* Add Spanish Latin Amarican keyboard #1237 #1240 #1244
|
||||
* Dynamic channel improvements #1222 #1224
|
||||
* Remove some deprecated sesman session types #1232
|
||||
* Refactoring and cleanups
|
||||
|
||||
# Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
# Release notes for xrdp v0.9.8 (2018/09/25)
|
||||
|
||||
## Deprecation notice
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
[](https://gitter.im/neutrinolabs/xrdp)
|
||||

|
||||
|
||||
*Current Version:* 0.9.8
|
||||
*Current Version:* 0.9.9
|
||||
|
||||
# xrdp - an open source RDP server
|
||||
|
||||
|
||||
@ -154,6 +154,8 @@ struct xrdp_client_info
|
||||
int client_os_minor;
|
||||
|
||||
int no_orders_supported;
|
||||
int use_cache_glyph_v2;
|
||||
int rail_enable;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -201,6 +201,11 @@
|
||||
#define OSMINORTYPE_PSEUDO_XSERVER 0x0008
|
||||
#define OSMINORTYPE_WINDOWS_RT 0x0009
|
||||
|
||||
/* Window List Capability Set: WndSupportLevel (MS-RDPERP 2.2.1.1.2) */
|
||||
#define TS_WINDOW_LEVEL_NOT_SUPPORTED 0x00000000
|
||||
#define TS_WINDOW_LEVEL_SUPPORTED 0x00000001
|
||||
#define TS_WINDOW_LEVEL_SUPPORTED_EX 0x00000002
|
||||
|
||||
/* Extended Info Packet: performanceFlags (MS-RDPBCGR 2.2.1.11.1.1.1) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP5_DISABLE_NOTHING 0x00
|
||||
@ -370,6 +375,7 @@
|
||||
#define RDP_COMPRESSION 0x0080
|
||||
#define RDP_LOGON_BLOB 0x0100
|
||||
#define RDP_LOGON_LEAVE_AUDIO 0x2000
|
||||
#define RDP_LOGON_RAIL 0x8000
|
||||
|
||||
/* Compression Flags (MS-RDPBCGR 3.1.8.2.1) */
|
||||
/* TODO: to be renamed, not used anywhere */
|
||||
@ -379,15 +385,14 @@
|
||||
#define RDP_MPPC_DICT_SIZE 8192 /* RDP 4.0 | MS-RDPBCGR 3.1.8 */
|
||||
|
||||
/* Drawing Order: controlFlags (MS-RDPEGDI 2.2.2.2.1, ) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP_ORDER_STANDARD 0x01
|
||||
#define RDP_ORDER_SECONDARY 0x02
|
||||
#define RDP_ORDER_BOUNDS 0x04
|
||||
#define RDP_ORDER_CHANGE 0x08
|
||||
#define RDP_ORDER_DELTA 0x10
|
||||
#define RDP_ORDER_LASTBOUNDS 0x20
|
||||
#define RDP_ORDER_SMALL 0x40
|
||||
#define RDP_ORDER_TINY 0x80
|
||||
#define TS_STANDARD 0x01
|
||||
#define TS_SECONDARY 0x02
|
||||
#define TS_BOUNDS 0x04
|
||||
#define TS_TYPE_CHANGE 0x08
|
||||
#define TS_DELTA_COORDINATES 0x10
|
||||
#define TS_ZERO_BOUNDS_DELTAS 0x20
|
||||
#define TS_ZERO_FIELD_BYTE_BIT0 0x40
|
||||
#define TS_ZERO_FIELD_BYTE_BIT1 0x80
|
||||
|
||||
/* Drawing Order: orderType (MS-RDPEGDI 2.2.2.2.1.1.2) ? */
|
||||
#define RDP_ORDER_DESTBLT 0
|
||||
@ -403,98 +408,94 @@
|
||||
#define RDP_ORDER_COMPOSITE 37 /* 0x25 */
|
||||
|
||||
/* Secondary Drawing Order Header: orderType (MS-RDPEGDI 2.2.2.2.1.2.1.1) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP_ORDER_RAW_BMPCACHE 0
|
||||
#define RDP_ORDER_COLCACHE 1
|
||||
#define RDP_ORDER_BMPCACHE 2
|
||||
#define RDP_ORDER_FONTCACHE 3
|
||||
#define RDP_ORDER_RAW_BMPCACHE2 4
|
||||
#define RDP_ORDER_BMPCACHE2 5
|
||||
#define RDP_ORDER_BRUSHCACHE 7
|
||||
#define RDP_ORDER_BMPCACHE3 8
|
||||
#define TS_CACHE_BITMAP_UNCOMPRESSED 0x00
|
||||
#define TS_CACHE_COLOR_TABLE 0x01
|
||||
#define TS_CACHE_BITMAP_COMPRESSED 0x02
|
||||
#define TS_CACHE_GLYPH 0x03
|
||||
#define TS_CACHE_BITMAP_UNCOMPRESSED_REV2 0x04
|
||||
#define TS_CACHE_BITMAP_COMPRESSED_REV2 0x05
|
||||
#define TS_CACHE_BRUSH 0x07
|
||||
#define TS_CACHE_BITMAP_COMPRESSED_REV3 0x08
|
||||
|
||||
/* Maps to generalCapabilitySet in T.128 page 138 */
|
||||
|
||||
/* Capability Set: capabilitySetType (MS-RDPBCGR 2.2.1.13.1.1.1) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP_CAPSET_GENERAL 0x0001
|
||||
#define RDP_CAPLEN_GENERAL 0x18
|
||||
#define CAPSTYPE_GENERAL 0x0001
|
||||
#define CAPSTYPE_GENERAL_LEN 0x18
|
||||
|
||||
#define RDP_CAPSET_BITMAP 0x0002
|
||||
#define RDP_CAPLEN_BITMAP 0x1C
|
||||
#define CAPSTYPE_BITMAP 0x0002
|
||||
#define CAPSTYPE_BITMAP_LEN 0x1C
|
||||
|
||||
#define RDP_CAPSET_ORDER 0x0003
|
||||
#define RDP_CAPLEN_ORDER 0x58
|
||||
#define ORDER_CAP_NEGOTIATE 2
|
||||
#define ORDER_CAP_NOSUPPORT 4
|
||||
#define CAPSTYPE_ORDER 0x0003
|
||||
#define CAPSTYPE_ORDER_LEN 0x58
|
||||
#define ORDER_CAP_NEGOTIATE 2 /* NEGOTIATEORDERSUPPORT? not used */
|
||||
#define ORDER_CAP_NOSUPPORT 4 /* not used */
|
||||
|
||||
#define RDP_CAPSET_BMPCACHE 0x0004
|
||||
#define RDP_CAPLEN_BMPCACHE 0x28
|
||||
#define CAPSTYPE_BITMAPCACHE 0x0004
|
||||
#define CAPSTYPE_BITMAPCACHE_LEN 0x28
|
||||
|
||||
#define RDP_CAPSET_CONTROL 0x0005
|
||||
#define RDP_CAPLEN_CONTROL 0x0C
|
||||
#define CAPSTYPE_CONTROL 0x0005
|
||||
#define CAPSTYPE_CONTROL_LEN 0x0C
|
||||
|
||||
#define RDP_CAPSET_ACTIVATE 0x0007
|
||||
#define RDP_CAPLEN_ACTIVATE 0x0C
|
||||
#define CAPSTYPE_ACTIVATION 0x0007
|
||||
#define CAPSTYPE_ACTIVATION_LEN 0x0C
|
||||
|
||||
#define RDP_CAPSET_POINTER 0x0008
|
||||
#define RDP_CAPLEN_POINTER 0x0a
|
||||
#define RDP_CAPLEN_POINTER_MONO 0x08
|
||||
#define CAPSTYPE_POINTER 0x0008
|
||||
#define CAPSTYPE_POINTER_LEN 0x0a
|
||||
#define CAPSTYPE_POINTER_MONO_LEN 0x08
|
||||
|
||||
#define RDP_CAPSET_SHARE 0x0009
|
||||
#define RDP_CAPLEN_SHARE 0x08
|
||||
#define CAPSTYPE_SHARE 0x0009
|
||||
#define CAPSTYPE_SHARE_LEN 0x08
|
||||
|
||||
#define RDP_CAPSET_COLCACHE 0x000A
|
||||
#define RDP_CAPLEN_COLCACHE 0x08
|
||||
#define CAPSTYPE_COLORCACHE 0x000A
|
||||
#define CAPSTYPE_COLORCACHE_LEN 0x08
|
||||
|
||||
#define RDP_CAPSET_SOUND 0x000C
|
||||
#define CAPSTYPE_SOUND 0x000C
|
||||
|
||||
#define RDP_CAPSET_INPUT 0x000D
|
||||
#define RDP_CAPLEN_INPUT 0x58
|
||||
#define CAPSTYPE_INPUT 0x000D
|
||||
#define CAPSTYPE_INPUT_LEN 0x58
|
||||
|
||||
#define RDP_CAPSET_FONT 0x000E
|
||||
#define RDP_CAPLEN_FONT 0x04
|
||||
#define CAPSTYPE_FONT 0x000E
|
||||
#define CAPSTYPE_FONT_LEN 0x04
|
||||
|
||||
#define RDP_CAPSET_BRUSHCACHE 0x000F
|
||||
#define RDP_CAPLEN_BRUSHCACHE 0x08
|
||||
#define CAPSTYPE_BRUSH 0x000F
|
||||
#define CAPSTYPE_BRUSH_LEN 0x08
|
||||
|
||||
#define RDP_CAPSET_GLYPHCACHE 0x0010
|
||||
#define RDP_CAPSET_OFFSCREENCACHE 0x0011
|
||||
#define CAPSTYPE_GLYPHCACHE 0x0010
|
||||
#define CAPSTYPE_OFFSCREENCACHE 0x0011
|
||||
|
||||
#define RDP_CAPSET_BITMAP_OFFSCREEN 0x0012
|
||||
#define RDP_CAPLEN_BITMAP_OFFSCREEN 0x08
|
||||
#define CAPSTYPE_BITMAPCACHE_HOSTSUPPORT 0x0012
|
||||
#define CAPSTYPE_BITMAPCACHE_HOSTSUPPORT_LEN 0x08
|
||||
|
||||
#define RDP_CAPSET_BMPCACHE2 0x0013
|
||||
#define RDP_CAPLEN_BMPCACHE2 0x28
|
||||
#define BMPCACHE2_FLAG_PERSIST ((long)1<<31)
|
||||
#define CAPSTYPE_BITMAPCACHE_REV2 0x0013
|
||||
#define CAPSTYPE_BITMAPCACHE_REV2_LEN 0x28
|
||||
#define BMPCACHE2_FLAG_PERSIST ((long)1<<31)
|
||||
|
||||
#define RDP_CAPSET_VIRCHAN 0x0014
|
||||
#define RDP_CAPLEN_VIRCHAN 0x08
|
||||
#define CAPSTYPE_VIRTUALCHANNEL 0x0014
|
||||
#define CAPSTYPE_VIRTUALCHANNEL_LEN 0x08
|
||||
|
||||
#define RDP_CAPSET_DRAWNINEGRIDCACHE 0x0015
|
||||
#define RDP_CAPSET_DRAWGDIPLUS 0x0016
|
||||
#define RDP_CAPSET_RAIL 0x0017
|
||||
#define RDP_CAPSET_WINDOW 0x0018
|
||||
#define CAPSTYPE_DRAWNINGRIDCACHE 0x0015
|
||||
#define CAPSTYPE_DRAWGDIPLUS 0x0016
|
||||
#define CAPSTYPE_RAIL 0x0017
|
||||
#define CAPSTYPE_WINDOW 0x0018
|
||||
|
||||
#define RDP_CAPSET_COMPDESK 0x0019
|
||||
#define RDP_CAPLEN_COMPDESK 0x06
|
||||
#define CAPSSETTYPE_COMPDESK 0x0019
|
||||
#define CAPSSETTYPE_COMPDESK_LEN 0x06
|
||||
|
||||
#define RDP_CAPSET_MULTIFRAGMENT 0x001A
|
||||
#define RDP_CAPLEN_MULTIFRAGMENT 0x08
|
||||
#define CAPSSETTYPE_MULTIFRAGMENTUPDATE 0x001A
|
||||
#define CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN 0x08
|
||||
|
||||
#define RDP_CAPSET_LPOINTER 0x001B
|
||||
#define RDP_CAPLEN_LPOINTER 0x06
|
||||
#define CAPSETTYPE_LARGE_POINTER 0x001B
|
||||
#define CAPSETTYPE_LARGE_POINTER_LEN 0x06
|
||||
|
||||
#define RDP_CAPSET_FRAME_ACKNOWLEDGE 0x001E
|
||||
#define RDP_CAPLEN_FRAME_ACKNOWLEDGE 0x08
|
||||
|
||||
#define RDP_CAPSET_SURFCMDS 0x001C
|
||||
#define RDP_CAPLEN_SURFCMDS 0x0C
|
||||
|
||||
#define RDP_CAPSET_BMPCODECS 0x001D
|
||||
#define RDP_CAPLEN_BMPCODECS 0x1C
|
||||
#define CAPSETTYPE_SURFACE_COMMANDS 0x001C
|
||||
#define CAPSETTYPE_SURFACE_COMMANDS_LEN 0x0C
|
||||
|
||||
#define CAPSSETTYPE_BITMAP_CODECS 0x001D
|
||||
#define CAPSSETTYPE_BITMAP_CODECS_LEN 0x1C
|
||||
|
||||
#define CAPSTYPE_FRAME_ACKNOWLEDGE 0x001E
|
||||
#define CAPSTYPE_FRAME_ACKNOWLEDGE_LEN 0x08
|
||||
|
||||
/* TS_SECURITY_HEADER: flags (MS-RDPBCGR 2.2.8.1.1.2.1) */
|
||||
/* TODO: to be renamed */
|
||||
@ -588,6 +589,12 @@
|
||||
#define KBD_FLAG_CAPITAL 0x0004
|
||||
#define TS_SYNC_KANA_LOCK 0x0008
|
||||
|
||||
/* Glyph Cache Capability Set: GlyphSupportLevel (MS-RDPBCGR 2.2.7.1.8) */
|
||||
#define GLYPH_SUPPORT_NONE 0x0000
|
||||
#define GLYPH_SUPPORT_PARTIAL 0x0001
|
||||
#define GLYPH_SUPPORT_FULL 0x0002
|
||||
#define GLYPH_SUPPORT_ENCODE 0x0003
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Constants come from other Microsoft products
|
||||
@ -664,12 +671,12 @@
|
||||
#define LICENCE_SIGNATURE_SIZE 16
|
||||
|
||||
|
||||
/* RDP PDU codes */
|
||||
#define RDP_PDU_DEMAND_ACTIVE 1
|
||||
#define RDP_PDU_CONFIRM_ACTIVE 3
|
||||
#define RDP_PDU_REDIRECT 4
|
||||
#define RDP_PDU_DEACTIVATE 6
|
||||
#define RDP_PDU_DATA 7
|
||||
/* PDU Types (MS-RDPBCGR 2.2.8.1.1.1.1) */
|
||||
#define PDUTYPE_DEMANDACTIVEPDU 0x1
|
||||
#define PDUTYPE_CONFIRMACTIVEPDU 0x3
|
||||
#define PDUTYPE_DEACTIVATEALLPDU 0x6
|
||||
#define PDUTYPE_DATAPDU 0x7
|
||||
#define PDUTYPE_SERVER_REDIR_PKT 0xA
|
||||
|
||||
/* See T.128 */
|
||||
/* not used anywhere */
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Process this file with autoconf to produce a configure script
|
||||
|
||||
AC_PREREQ(2.65)
|
||||
AC_INIT([xrdp], [0.9.8], [xrdp-devel@googlegroups.com])
|
||||
AC_INIT([xrdp], [0.9.9], [xrdp-devel@googlegroups.com])
|
||||
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
|
||||
AM_INIT_AUTOMAKE([1.7.2 foreign])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
@ -139,6 +139,13 @@ within 60 seconds after the user disconnects.
|
||||
Sets the time limit (in seconds) before a disconnected session is killed.
|
||||
If set to \fI0\fR, automatic killing is disabled.
|
||||
|
||||
.TP
|
||||
\fBIdleTimeLimit\fR=\fInumber\fR
|
||||
Sets the time limit (in seconds) before an idle session is disconnected.
|
||||
Idle means no keyboard inputs and no mouse moves/clicks here.
|
||||
If set to \fI0\fR, idle sessions will never be disconnected by timeout.
|
||||
This works only with xorgxrdp session. Moreover, xorgxrdp must be v0.2.9 or later.
|
||||
|
||||
.TP
|
||||
\fBPolicy\fR=\fI[Default|UBD|UBI|UBC|UBDI|UBDC]\fR
|
||||
Session allocation policy. By default, a new session is created
|
||||
|
||||
@ -45,6 +45,7 @@ dist_startscript_DATA = \
|
||||
km-0000041d.ini \
|
||||
km-00000807.ini \
|
||||
km-00000809.ini \
|
||||
km-0000080a.ini \
|
||||
km-0000080c.ini \
|
||||
km-00000813.ini \
|
||||
km-00000816.ini \
|
||||
|
||||
1055
instfiles/km-0000080a.ini
Normal file
1055
instfiles/km-0000080a.ini
Normal file
File diff suppressed because it is too large
Load Diff
@ -230,10 +230,10 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
|
||||
case 0:
|
||||
dead_lock_counter++;
|
||||
break;
|
||||
case RDP_PDU_CONFIRM_ACTIVE: /* 3 */
|
||||
case PDUTYPE_CONFIRMACTIVEPDU:
|
||||
xrdp_caps_process_confirm_active(rdp, s);
|
||||
break;
|
||||
case RDP_PDU_DATA: /* 7 */
|
||||
case PDUTYPE_DATAPDU:
|
||||
if (xrdp_rdp_process_data(rdp, s) != 0)
|
||||
{
|
||||
DEBUG(("libxrdp_process_data returned non zero"));
|
||||
@ -1263,6 +1263,93 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_disable_channel(struct xrdp_session *session, int channel_id,
|
||||
int is_disabled)
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
struct xrdp_mcs *mcs;
|
||||
struct mcs_channel_item *channel_item;
|
||||
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
mcs = rdp->sec_layer->mcs_layer;
|
||||
if (mcs->channel_list == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
channel_item = (struct mcs_channel_item *)
|
||||
list_get_item(mcs->channel_list, channel_id);
|
||||
if (channel_item == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
channel_item->disabled = is_disabled;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_drdynvc_open(struct xrdp_session *session, const char *name,
|
||||
int flags, struct xrdp_drdynvc_procs *procs,
|
||||
int *chan_id)
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
struct xrdp_sec *sec;
|
||||
struct xrdp_channel *chan;
|
||||
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
sec = rdp->sec_layer;
|
||||
chan = sec->chan_layer;
|
||||
return xrdp_channel_drdynvc_open(chan, name, flags, procs, chan_id);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_drdynvc_close(struct xrdp_session *session, int chan_id)
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
struct xrdp_sec *sec;
|
||||
struct xrdp_channel *chan;
|
||||
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
sec = rdp->sec_layer;
|
||||
chan = sec->chan_layer;
|
||||
return xrdp_channel_drdynvc_close(chan, chan_id);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_drdynvc_data_first(struct xrdp_session *session, int chan_id,
|
||||
const char *data, int data_bytes,
|
||||
int total_data_bytes)
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
struct xrdp_sec *sec;
|
||||
struct xrdp_channel *chan;
|
||||
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
sec = rdp->sec_layer;
|
||||
chan = sec->chan_layer;
|
||||
return xrdp_channel_drdynvc_data_first(chan, chan_id, data, data_bytes,
|
||||
total_data_bytes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_drdynvc_data(struct xrdp_session *session, int chan_id,
|
||||
const char *data, int data_bytes)
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
struct xrdp_sec *sec;
|
||||
struct xrdp_channel *chan;
|
||||
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
sec = rdp->sec_layer;
|
||||
chan = sec->chan_layer;
|
||||
return xrdp_channel_drdynvc_data(chan, chan_id, data, data_bytes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_send_brush(struct xrdp_session *session,
|
||||
|
||||
@ -51,6 +51,8 @@ struct mcs_channel_item
|
||||
char name[16];
|
||||
int flags;
|
||||
int chanid;
|
||||
int disabled;
|
||||
int pad0;
|
||||
};
|
||||
|
||||
/* mcs */
|
||||
@ -128,11 +130,27 @@ struct xrdp_sec
|
||||
int is_security_header_present; /* boolean */
|
||||
};
|
||||
|
||||
struct xrdp_drdynvc
|
||||
{
|
||||
int chan_id;
|
||||
int status; /* see XRDP_DRDYNVC_STATUS_* */
|
||||
int flags;
|
||||
int pad0;
|
||||
int (*open_response)(intptr_t id, int chan_id, int creation_status);
|
||||
int (*close_response)(intptr_t id, int chan_id);
|
||||
int (*data_first)(intptr_t id, int chan_id, char *data, int bytes, int total_bytes);
|
||||
int (*data)(intptr_t id, int chan_id, char *data, int bytes);
|
||||
};
|
||||
|
||||
/* channel */
|
||||
struct xrdp_channel
|
||||
{
|
||||
struct xrdp_sec *sec_layer;
|
||||
struct xrdp_mcs *mcs_layer;
|
||||
int drdynvc_channel_id;
|
||||
int drdynvc_state;
|
||||
struct stream *s;
|
||||
struct xrdp_drdynvc drdynvcs[256];
|
||||
};
|
||||
|
||||
/* rdp */
|
||||
@ -285,7 +303,6 @@ struct xrdp_mppc_enc
|
||||
tui16 *hash_table;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
compress_rdp(struct xrdp_mppc_enc *enc, tui8 *srcData, int len);
|
||||
struct xrdp_mppc_enc *
|
||||
@ -553,6 +570,21 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
|
||||
int
|
||||
xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
|
||||
int chanid);
|
||||
int
|
||||
xrdp_channel_drdynvc_start(struct xrdp_channel *self);
|
||||
int
|
||||
xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
int flags, struct xrdp_drdynvc_procs *procs,
|
||||
int *chan_id);
|
||||
int
|
||||
xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id);
|
||||
int
|
||||
xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes,
|
||||
int total_data_bytes);
|
||||
int
|
||||
xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes);
|
||||
|
||||
/* xrdp_fastpath.c */
|
||||
struct xrdp_fastpath *
|
||||
|
||||
@ -76,6 +76,14 @@ struct xrdp_session
|
||||
struct source_info si;
|
||||
};
|
||||
|
||||
struct xrdp_drdynvc_procs
|
||||
{
|
||||
int (*open_response)(intptr_t id, int chan_id, int creation_status);
|
||||
int (*close_response)(intptr_t id, int chan_id);
|
||||
int (*data_first)(intptr_t id, int chan_id, char *data, int bytes, int total_bytes);
|
||||
int (*data)(intptr_t id, int chan_id, char *data, int bytes);
|
||||
};
|
||||
|
||||
struct xrdp_session *
|
||||
libxrdp_init(tbus id, struct trans *trans);
|
||||
int
|
||||
@ -195,6 +203,22 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
|
||||
char *data, int data_len,
|
||||
int total_data_len, int flags);
|
||||
int
|
||||
libxrdp_disable_channel(struct xrdp_session *session, int channel_id,
|
||||
int is_disabled);
|
||||
int
|
||||
libxrdp_drdynvc_open(struct xrdp_session *session, const char *name,
|
||||
int flags, struct xrdp_drdynvc_procs *procs,
|
||||
int *chan_id);
|
||||
int
|
||||
libxrdp_drdynvc_close(struct xrdp_session *session, int chan_id);
|
||||
int
|
||||
libxrdp_drdynvc_data_first(struct xrdp_session *session, int chan_id,
|
||||
const char *data, int data_bytes,
|
||||
int total_data_bytes);
|
||||
int
|
||||
libxrdp_drdynvc_data(struct xrdp_session *session, int chan_id,
|
||||
const char *data, int data_bytes);
|
||||
int
|
||||
libxrdp_orders_send_brush(struct xrdp_session *session,
|
||||
int width, int height, int bpp, int type,
|
||||
int size, char *data, int cache_id);
|
||||
|
||||
@ -360,6 +360,33 @@ xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_caps_process_glyphcache(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int glyph_support_level;
|
||||
|
||||
if (len < 40 + 4 + 2 + 2) /* MS-RDPBCGR 2.2.7.1.8 */
|
||||
{
|
||||
g_writeln("xrdp_caps_process_glyphcache: error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 40); /* glyph cache */
|
||||
in_uint8s(s, 4); /* frag cache */
|
||||
in_uint16_le(s, glyph_support_level);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
|
||||
if (glyph_support_level == GLYPH_SUPPORT_ENCODE)
|
||||
{
|
||||
self->client_info.use_cache_glyph_v2 = 1;
|
||||
}
|
||||
g_writeln("xrdp_caps_process_glyphcache: support level %d ",
|
||||
glyph_support_level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_caps_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s,
|
||||
@ -610,88 +637,89 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
len -= 4;
|
||||
switch (type)
|
||||
{
|
||||
case RDP_CAPSET_GENERAL:
|
||||
DEBUG(("RDP_CAPSET_GENERAL"));
|
||||
case CAPSTYPE_GENERAL:
|
||||
DEBUG(("CAPSTYPE_GENERAL"));
|
||||
xrdp_caps_process_general(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BITMAP:
|
||||
DEBUG(("RDP_CAPSET_BITMAP"));
|
||||
case CAPSTYPE_BITMAP:
|
||||
DEBUG(("CAPSTYPE_BITMAP"));
|
||||
break;
|
||||
case RDP_CAPSET_ORDER:
|
||||
DEBUG(("RDP_CAPSET_ORDER"));
|
||||
case CAPSTYPE_ORDER:
|
||||
DEBUG(("CAPSTYPE_ORDER"));
|
||||
xrdp_caps_process_order(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BMPCACHE:
|
||||
DEBUG(("RDP_CAPSET_BMPCACHE"));
|
||||
case CAPSTYPE_BITMAPCACHE:
|
||||
DEBUG(("CAPSTYPE_BMPCACHE"));
|
||||
xrdp_caps_process_bmpcache(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_CONTROL:
|
||||
DEBUG(("RDP_CAPSET_CONTROL"));
|
||||
case CAPSTYPE_CONTROL:
|
||||
DEBUG(("CAPSTYPE_CONTROL"));
|
||||
break;
|
||||
case 6:
|
||||
xrdp_caps_process_cache_v3_codec_id(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_ACTIVATE:
|
||||
DEBUG(("RDP_CAPSET_ACTIVATE"));
|
||||
case CAPSTYPE_ACTIVATION:
|
||||
DEBUG(("CAPSTYPE_ACTIVAION"));
|
||||
break;
|
||||
case RDP_CAPSET_POINTER:
|
||||
DEBUG(("RDP_CAPSET_POINTER"));
|
||||
case CAPSTYPE_POINTER:
|
||||
DEBUG(("CAPSTYPE_POINTER"));
|
||||
xrdp_caps_process_pointer(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_SHARE:
|
||||
DEBUG(("RDP_CAPSET_SHARE"));
|
||||
case CAPSTYPE_SHARE:
|
||||
DEBUG(("CAPSTYPE_SHARE"));
|
||||
break;
|
||||
case RDP_CAPSET_COLCACHE:
|
||||
DEBUG(("RDP_CAPSET_COLCACHE"));
|
||||
case CAPSTYPE_COLORCACHE:
|
||||
DEBUG(("CAPSTYPE_COLORCACHE"));
|
||||
break;
|
||||
case RDP_CAPSET_SOUND:
|
||||
DEBUG(("--0x0C"));
|
||||
case CAPSTYPE_SOUND:
|
||||
DEBUG(("CAPSTYPE_SOUND"));
|
||||
break;
|
||||
case RDP_CAPSET_INPUT:
|
||||
case CAPSTYPE_INPUT:
|
||||
xrdp_caps_process_input(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_FONT:
|
||||
DEBUG(("--0x0D"));
|
||||
case CAPSTYPE_FONT:
|
||||
DEBUG(("CAPSTYPE_FONT"));
|
||||
break;
|
||||
case RDP_CAPSET_BRUSHCACHE:
|
||||
case CAPSTYPE_BRUSH:
|
||||
xrdp_caps_process_brushcache(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_GLYPHCACHE:
|
||||
DEBUG(("--0x11"));
|
||||
case CAPSTYPE_GLYPHCACHE:
|
||||
DEBUG(("CAPSTYPE_GLYPHCACHE"));
|
||||
xrdp_caps_process_glyphcache(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_OFFSCREENCACHE:
|
||||
DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE"));
|
||||
case CAPSTYPE_OFFSCREENCACHE:
|
||||
DEBUG(("CAPSTYPE_OFFSCREENCACHE"));
|
||||
xrdp_caps_process_offscreen_bmpcache(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BMPCACHE2:
|
||||
DEBUG(("RDP_CAPSET_BMPCACHE2"));
|
||||
case CAPSTYPE_BITMAPCACHE_REV2:
|
||||
DEBUG(("CAPSTYPE_BITMAPCACHE_REV2"));
|
||||
xrdp_caps_process_bmpcache2(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_VIRCHAN:
|
||||
DEBUG(("--0x14"));
|
||||
case CAPSTYPE_VIRTUALCHANNEL:
|
||||
DEBUG(("CAPSTYPE_VIRTUALCHANNEL"));
|
||||
break;
|
||||
case RDP_CAPSET_DRAWNINEGRIDCACHE:
|
||||
DEBUG(("--0x15"));
|
||||
case CAPSTYPE_DRAWNINGRIDCACHE:
|
||||
DEBUG(("CAPSTYPE_DRAWNINGRIDCACHE"));
|
||||
break;
|
||||
case RDP_CAPSET_DRAWGDIPLUS:
|
||||
DEBUG(("--0x16"));
|
||||
case CAPSTYPE_DRAWGDIPLUS:
|
||||
DEBUG(("CAPSTYPE_DRAWGDIPLUS"));
|
||||
break;
|
||||
case RDP_CAPSET_RAIL:
|
||||
case CAPSTYPE_RAIL:
|
||||
xrdp_caps_process_rail(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_WINDOW:
|
||||
case CAPSTYPE_WINDOW:
|
||||
xrdp_caps_process_window(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_MULTIFRAGMENT:
|
||||
case CAPSSETTYPE_MULTIFRAGMENTUPDATE:
|
||||
xrdp_caps_process_multifragmentupdate(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_SURFCMDS:
|
||||
case CAPSETTYPE_SURFACE_COMMANDS:
|
||||
xrdp_caps_process_surface_cmds(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BMPCODECS:
|
||||
case CAPSSETTYPE_BITMAP_CODECS:
|
||||
xrdp_caps_process_codecs(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_FRAME_ACKNOWLEDGE:
|
||||
case CAPSTYPE_FRAME_ACKNOWLEDGE:
|
||||
xrdp_caps_process_frame_ack(self, s, len);
|
||||
break;
|
||||
default:
|
||||
@ -757,29 +785,27 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
|
||||
/* Output share capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_SHARE);
|
||||
out_uint16_le(s, RDP_CAPLEN_SHARE);
|
||||
out_uint16_le(s, CAPSTYPE_SHARE);
|
||||
out_uint16_le(s, CAPSTYPE_SHARE_LEN);
|
||||
out_uint16_le(s, self->mcs_channel);
|
||||
out_uint16_be(s, 0xb5e2); /* 0x73e1 */
|
||||
|
||||
/* Output general capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */
|
||||
out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */
|
||||
out_uint16_le(s, 1); /* OS major type */
|
||||
out_uint16_le(s, 3); /* OS minor type */
|
||||
out_uint16_le(s, CAPSTYPE_GENERAL);
|
||||
out_uint16_le(s, CAPSTYPE_GENERAL_LEN);
|
||||
out_uint16_le(s, OSMAJORTYPE_WINDOWS);
|
||||
out_uint16_le(s, OSMINORTYPE_WINDOWS_NT);
|
||||
out_uint16_le(s, 0x200); /* Protocol version */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, 0); /* Compression types */
|
||||
/* NO_BITMAP_COMPRESSION_HDR 0x0400
|
||||
FASTPATH_OUTPUT_SUPPORTED 0x0001 */
|
||||
if (self->client_info.use_fast_path & 1)
|
||||
{
|
||||
out_uint16_le(s, 0x401);
|
||||
out_uint16_le(s, NO_BITMAP_COMPRESSION_HDR | FASTPATH_OUTPUT_SUPPORTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint16_le(s, 0x400);
|
||||
out_uint16_le(s, NO_BITMAP_COMPRESSION_HDR);
|
||||
}
|
||||
out_uint16_le(s, 0); /* Update capability */
|
||||
out_uint16_le(s, 0); /* Remote unshare capability */
|
||||
@ -788,8 +814,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
|
||||
/* Output bitmap capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */
|
||||
out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */
|
||||
out_uint16_le(s, CAPSTYPE_BITMAP);
|
||||
out_uint16_le(s, CAPSTYPE_BITMAP_LEN);
|
||||
out_uint16_le(s, self->client_info.bpp); /* Preferred BPP */
|
||||
out_uint16_le(s, 1); /* Receive 1 BPP */
|
||||
out_uint16_le(s, 1); /* Receive 4 BPP */
|
||||
@ -805,13 +831,13 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
|
||||
/* Output font capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_FONT); /* 14 */
|
||||
out_uint16_le(s, RDP_CAPLEN_FONT); /* 4 */
|
||||
out_uint16_le(s, CAPSTYPE_FONT);
|
||||
out_uint16_le(s, CAPSTYPE_FONT_LEN);
|
||||
|
||||
/* Output order capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */
|
||||
out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */
|
||||
out_uint16_le(s, CAPSTYPE_ORDER);
|
||||
out_uint16_le(s, CAPSTYPE_ORDER_LEN);
|
||||
out_uint8s(s, 16);
|
||||
out_uint32_be(s, 0x40420f00);
|
||||
out_uint16_le(s, 1); /* Cache X granularity */
|
||||
@ -863,7 +889,7 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
|
||||
/* Output bmpcodecs capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_BMPCODECS);
|
||||
out_uint16_le(s, CAPSSETTYPE_BITMAP_CODECS);
|
||||
codec_caps_size_ptr = s->p;
|
||||
out_uint8s(s, 2); /* cap len set later */
|
||||
codec_caps_count = 0;
|
||||
@ -899,30 +925,30 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint8(s, 75); /* jpeg compression ratio */
|
||||
/* calculate and set size and count */
|
||||
codec_caps_size = (int)(s->p - codec_caps_size_ptr);
|
||||
codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */
|
||||
codec_caps_size += 2; /* 2 bytes for CAPSTYPE_BMPCODECS above */
|
||||
codec_caps_size_ptr[0] = codec_caps_size;
|
||||
codec_caps_size_ptr[1] = codec_caps_size >> 8;
|
||||
codec_caps_count_ptr[0] = codec_caps_count;
|
||||
|
||||
/* Output color cache capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_COLCACHE);
|
||||
out_uint16_le(s, RDP_CAPLEN_COLCACHE);
|
||||
out_uint16_le(s, CAPSTYPE_COLORCACHE);
|
||||
out_uint16_le(s, CAPSTYPE_COLORCACHE_LEN);
|
||||
out_uint16_le(s, 6); /* cache size */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
|
||||
/* Output pointer capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_POINTER);
|
||||
out_uint16_le(s, RDP_CAPLEN_POINTER);
|
||||
out_uint16_le(s, CAPSTYPE_POINTER);
|
||||
out_uint16_le(s, CAPSTYPE_POINTER_LEN);
|
||||
out_uint16_le(s, 1); /* Colour pointer */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
|
||||
/* Output input capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_INPUT); /* 13(0xd) */
|
||||
out_uint16_le(s, RDP_CAPLEN_INPUT); /* 88(0x58) */
|
||||
out_uint16_le(s, CAPSTYPE_INPUT);
|
||||
out_uint16_le(s, CAPSTYPE_INPUT_LEN);
|
||||
|
||||
flags = INPUT_FLAG_SCANCODES |
|
||||
INPUT_FLAG_MOUSEX |
|
||||
@ -936,20 +962,24 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, flags);
|
||||
out_uint8s(s, 82);
|
||||
|
||||
/* Remote Programs Capability Set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */
|
||||
out_uint16_le(s, 8);
|
||||
out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED
|
||||
TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
|
||||
if (self->client_info.rail_enable) /* MS-RDPERP 3.3.5.1.4 */
|
||||
{
|
||||
/* Remote Programs Capability Set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_RAIL);
|
||||
out_uint16_le(s, 8); /* LengthCapability: MS-RDPERP 2.2.1.1.1 */
|
||||
out_uint32_le(s, 3); /* See: https://msdn.microsoft.com/en-us/library/cc242518.aspx
|
||||
TS_RAIL_LEVEL_SUPPORTED
|
||||
TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
|
||||
|
||||
/* Window List Capability Set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */
|
||||
out_uint16_le(s, 11);
|
||||
out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */
|
||||
out_uint8(s, 3); /* NumIconCaches */
|
||||
out_uint16_le(s, 12); /* NumIconCacheEntries */
|
||||
/* Window List Capability Set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_WINDOW);
|
||||
out_uint16_le(s, 11); /* LengthCapability: MS-RDPERP 2.2.1.1.2 */
|
||||
out_uint32_le(s, TS_WINDOW_LEVEL_SUPPORTED_EX);
|
||||
out_uint8(s, 3); /* NumIconCaches */
|
||||
out_uint16_le(s, 12); /* NumIconCacheEntries */
|
||||
}
|
||||
|
||||
/* 6 - bitmap cache v3 codecid */
|
||||
caps_count++;
|
||||
@ -961,20 +991,20 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
{
|
||||
/* multifragment update */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_MULTIFRAGMENT); /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */
|
||||
out_uint16_le(s, RDP_CAPLEN_MULTIFRAGMENT);
|
||||
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE);
|
||||
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN);
|
||||
out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */
|
||||
|
||||
/* frame acks */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_FRAME_ACKNOWLEDGE); /* CAPSETTYPE_FRAME_ACKNOWLEDGE */
|
||||
out_uint16_le(s, RDP_CAPLEN_FRAME_ACKNOWLEDGE);
|
||||
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE);
|
||||
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE_LEN);
|
||||
out_uint32_le(s, 2); /* 2 frames in flight */
|
||||
|
||||
/* surface commands */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_SURFCMDS); /* CAPSETTYPE_SURFACE_COMMANDS */
|
||||
out_uint16_le(s, RDP_CAPLEN_SURFCMDS); /* lengthCapability */
|
||||
out_uint16_le(s, CAPSETTYPE_SURFACE_COMMANDS);
|
||||
out_uint16_le(s, CAPSETTYPE_SURFACE_COMMANDS_LEN);
|
||||
out_uint32_le(s, (SURFCMDS_SETSURFACEBITS |
|
||||
SURFCMDS_FRAMEMARKER |
|
||||
SURFCMDS_STREAMSUFRACEBITS)); /* cmdFlags */
|
||||
@ -994,7 +1024,7 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
caps_count_ptr[2] = caps_count >> 16;
|
||||
caps_count_ptr[3] = caps_count >> 24;
|
||||
|
||||
if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0)
|
||||
if (xrdp_rdp_send(self, s, PDUTYPE_DEMANDACTIVEPDU) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
|
||||
@ -31,6 +31,17 @@
|
||||
#define CHANNEL_FLAG_LAST 0x02
|
||||
#define CHANNEL_FLAG_SHOW_PROTOCOL 0x10
|
||||
|
||||
#define CMD_DVC_OPEN_CHANNEL 0x10
|
||||
#define CMD_DVC_DATA_FIRST 0x20
|
||||
#define CMD_DVC_DATA 0x30
|
||||
#define CMD_DVC_CLOSE_CHANNEL 0x40
|
||||
#define CMD_DVC_CAPABILITY 0x50
|
||||
|
||||
#define XRDP_DRDYNVC_STATUS_CLOSED 0
|
||||
#define XRDP_DRDYNVC_STATUS_OPEN_SENT 1
|
||||
#define XRDP_DRDYNVC_STATUS_OPEN 2
|
||||
#define XRDP_DRDYNVC_STATUS_CLOSE_SENT 3
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns pointer or nil on error */
|
||||
static struct mcs_channel_item *
|
||||
@ -58,6 +69,7 @@ xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer)
|
||||
self = (struct xrdp_channel *)g_malloc(sizeof(struct xrdp_channel), 1);
|
||||
self->sec_layer = owner;
|
||||
self->mcs_layer = mcs_layer;
|
||||
self->drdynvc_channel_id = -1;
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -70,7 +82,7 @@ xrdp_channel_delete(struct xrdp_channel *self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
free_stream(self->s);
|
||||
g_memset(self, 0, sizeof(struct xrdp_channel));
|
||||
g_free(self);
|
||||
}
|
||||
@ -106,6 +118,12 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (channel->disabled)
|
||||
{
|
||||
g_writeln("xrdp_channel_send, channel disabled");
|
||||
return 0; /* not an error */
|
||||
}
|
||||
|
||||
s_pop_layer(s, channel_hdr);
|
||||
out_uint32_le(s, total_data_len);
|
||||
|
||||
@ -175,6 +193,333 @@ xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s,
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
drdynvc_insert_uint_124(struct stream *s, uint32_t val)
|
||||
{
|
||||
int ret_val;
|
||||
|
||||
if (val <= 0xff)
|
||||
{
|
||||
out_uint8(s, val);
|
||||
ret_val = 0;
|
||||
}
|
||||
else if (val <= 0xffff)
|
||||
{
|
||||
out_uint16_le(s, val);
|
||||
ret_val = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint32_le(s, val);
|
||||
ret_val = 2;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
{
|
||||
int cbChId;
|
||||
int chan_id;
|
||||
|
||||
cbChId = cmd & 0x03;
|
||||
if (cbChId == 0)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, chan_id);
|
||||
}
|
||||
else if (cbChId == 1)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, chan_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, chan_id);
|
||||
}
|
||||
*chan_id_p = chan_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
drdynvc_process_capability_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
{
|
||||
struct xrdp_session *session;
|
||||
int cap_version;
|
||||
int rv;
|
||||
|
||||
/* skip padding */
|
||||
in_uint8s(s, 1);
|
||||
/* read client's version */
|
||||
in_uint16_le(s, cap_version);
|
||||
if ((cap_version != 2) && (cap_version != 3))
|
||||
{
|
||||
g_writeln("drdynvc_process_capability_response: incompatible DVC "
|
||||
"version %d detected", cap_version);
|
||||
return 1;
|
||||
}
|
||||
g_writeln("drdynvc_process_capability_response: DVC version %d selected",
|
||||
cap_version);
|
||||
self->drdynvc_state = 1;
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
rv = session->callback(session->id, 0x5558, 0, 0, 0, 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
drdynvc_process_open_channel_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
{
|
||||
struct xrdp_session *session;
|
||||
int creation_status;
|
||||
uint32_t chan_id;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, creation_status);
|
||||
//g_writeln("drdynvc_process_open_channel_response: chan_id 0x%x "
|
||||
// "creation_status %d", chan_id, creation_status);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
if (creation_status == 0)
|
||||
{
|
||||
drdynvc->status = XRDP_DRDYNVC_STATUS_OPEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
|
||||
}
|
||||
if (drdynvc->open_response != NULL)
|
||||
{
|
||||
return drdynvc->open_response(session->id, chan_id, creation_status);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
drdynvc_process_close_channel_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
{
|
||||
struct xrdp_session *session;
|
||||
uint32_t chan_id;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
//g_writeln("drdynvc_process_close_channel_response: chan_id 0x%x", chan_id);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
|
||||
if (drdynvc->close_response != NULL)
|
||||
{
|
||||
return drdynvc->close_response(session->id, chan_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
drdynvc_process_data_first(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
{
|
||||
struct xrdp_session *session;
|
||||
uint32_t chan_id;
|
||||
int len;
|
||||
int bytes;
|
||||
int total_bytes;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
len = (cmd >> 2) & 0x03;
|
||||
if (len == 0)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, total_bytes);
|
||||
}
|
||||
else if (len == 1)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, total_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, total_bytes);
|
||||
}
|
||||
bytes = (int) (s->end - s->p);
|
||||
//g_writeln("drdynvc_process_data_first: bytes %d total_bytes %d", bytes, total_bytes);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
if (drdynvc->data_first != NULL)
|
||||
{
|
||||
return drdynvc->data_first(session->id, chan_id, s->p,
|
||||
bytes, total_bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
drdynvc_process_data(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
{
|
||||
struct xrdp_session *session;
|
||||
uint32_t chan_id;
|
||||
int bytes;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
bytes = (int) (s->end - s->p);
|
||||
//g_writeln("drdynvc_process_data: bytes %d", bytes);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
if (drdynvc->data != NULL)
|
||||
{
|
||||
return drdynvc->data(session->id, chan_id, s->p, bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_channel_process_drdynvc(struct xrdp_channel *self,
|
||||
struct mcs_channel_item *channel,
|
||||
struct stream *s)
|
||||
{
|
||||
int total_length;
|
||||
int length;
|
||||
int flags;
|
||||
int cmd;
|
||||
int rv;
|
||||
struct stream *ls;
|
||||
|
||||
if (!s_check_rem(s, 8))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, total_length);
|
||||
in_uint32_le(s, flags);
|
||||
//g_writeln("xrdp_channel_process_drdynvc: total_length %d flags 0x%8.8x",
|
||||
// total_length, flags);
|
||||
ls = NULL;
|
||||
switch (flags & 3)
|
||||
{
|
||||
case 0:
|
||||
length = (int) (s->end - s->p);
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
return 0;
|
||||
case 1:
|
||||
free_stream(self->s);
|
||||
make_stream(self->s);
|
||||
init_stream(self->s, total_length);
|
||||
length = (int) (s->end - s->p);
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
return 0;
|
||||
case 2:
|
||||
length = (int) (s->end - s->p);
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
ls = self->s;
|
||||
break;
|
||||
case 3:
|
||||
ls = s;
|
||||
break;
|
||||
default:
|
||||
g_writeln("xrdp_channel_process_drdynvc: error");
|
||||
return 1;
|
||||
}
|
||||
if (ls == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(ls, cmd); /* read command */
|
||||
//g_writeln("xrdp_channel_process_drdynvc: cmd 0x%x", cmd);
|
||||
rv = 1;
|
||||
switch (cmd & 0xf0)
|
||||
{
|
||||
case CMD_DVC_CAPABILITY:
|
||||
rv = drdynvc_process_capability_response(self, cmd, s);
|
||||
break;
|
||||
case CMD_DVC_OPEN_CHANNEL:
|
||||
rv = drdynvc_process_open_channel_response(self, cmd, s);
|
||||
break;
|
||||
case CMD_DVC_CLOSE_CHANNEL:
|
||||
rv = drdynvc_process_close_channel_response(self, cmd, s);
|
||||
break;
|
||||
case CMD_DVC_DATA_FIRST:
|
||||
rv = drdynvc_process_data_first(self, cmd, s);
|
||||
break;
|
||||
case CMD_DVC_DATA:
|
||||
rv = drdynvc_process_data(self, cmd, s);
|
||||
break;
|
||||
default:
|
||||
g_writeln("xrdp_channel_process_drdynvc: got unknown "
|
||||
"command 0x%x", cmd);
|
||||
break;
|
||||
}
|
||||
//g_writeln("xrdp_channel_process_drdynvc: rv %d", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* This is called from the secure layer to process an incoming non global
|
||||
@ -191,23 +536,319 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
|
||||
int channel_id;
|
||||
struct mcs_channel_item *channel;
|
||||
|
||||
|
||||
/* this assumes that the channels are in order of chanid(mcs channel id)
|
||||
but they should be, see xrdp_sec_process_mcs_data_channels
|
||||
the first channel should be MCS_GLOBAL_CHANNEL + 1, second
|
||||
one should be MCS_GLOBAL_CHANNEL + 2, and so on */
|
||||
channel_id = (chanid - MCS_GLOBAL_CHANNEL) - 1;
|
||||
channel = xrdp_channel_get_item(self, channel_id);
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
g_writeln("xrdp_channel_process, channel not found");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (channel->disabled)
|
||||
{
|
||||
g_writeln("xrdp_channel_process, channel disabled");
|
||||
return 0; /* not an error */
|
||||
}
|
||||
if (channel_id == self->drdynvc_channel_id)
|
||||
{
|
||||
return xrdp_channel_process_drdynvc(self, channel, s);
|
||||
}
|
||||
rv = 0;
|
||||
in_uint32_le(s, length);
|
||||
in_uint32_le(s, flags);
|
||||
rv = xrdp_channel_call_callback(self, s, channel_id, length, flags);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* drdynvc */
|
||||
static int
|
||||
xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
{
|
||||
struct stream *s;
|
||||
int flags;
|
||||
int total_data_len;
|
||||
int channel_id;
|
||||
char *phold;
|
||||
|
||||
/* setup stream */
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
phold = s->p;
|
||||
out_uint8(s, 0x50); /* insert cmd */
|
||||
out_uint8(s, 0x00); /* insert padding */
|
||||
out_uint16_le(s, 2); /* insert version */
|
||||
/* channel priority unused for now */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 0 */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 1 */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 2 */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 3 */
|
||||
s_mark_end(s);
|
||||
/* send command to client */
|
||||
total_data_len = (int) (s->end - phold);
|
||||
flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
channel_id = self->drdynvc_channel_id;
|
||||
if (xrdp_channel_send(self, s, channel_id, total_data_len, flags) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_channel_drdynvc_start(struct xrdp_channel *self)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
struct mcs_channel_item *ci;
|
||||
struct mcs_channel_item *dci;
|
||||
|
||||
g_writeln("xrdp_channel_drdynvc_start:");
|
||||
dci = NULL;
|
||||
count = self->mcs_layer->channel_list->count;
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
ci = (struct mcs_channel_item *)
|
||||
list_get_item(self->mcs_layer->channel_list, index);
|
||||
if (ci != NULL)
|
||||
{
|
||||
if (g_strcasecmp(ci->name, "drdynvc") == 0)
|
||||
{
|
||||
dci = ci;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dci != NULL)
|
||||
{
|
||||
self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1;
|
||||
xrdp_channel_drdynvc_send_capability_request(self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
int flags, struct xrdp_drdynvc_procs *procs,
|
||||
int *chan_id)
|
||||
{
|
||||
struct stream *s;
|
||||
int ChId;
|
||||
int cbChId;
|
||||
int chan_pri;
|
||||
int static_channel_id;
|
||||
int name_length;
|
||||
int total_data_len;
|
||||
int static_flags;
|
||||
char *cmd_ptr;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
ChId = 1;
|
||||
while (self->drdynvcs[ChId].status != XRDP_DRDYNVC_STATUS_CLOSED)
|
||||
{
|
||||
ChId++;
|
||||
if (ChId > 255)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
name_length = g_strlen(name);
|
||||
out_uint8a(s, name, name_length + 1);
|
||||
chan_pri = 0;
|
||||
cmd_ptr[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
*chan_id = ChId;
|
||||
self->drdynvcs[ChId].open_response = procs->open_response;
|
||||
self->drdynvcs[ChId].close_response = procs->close_response;
|
||||
self->drdynvcs[ChId].data_first = procs->data_first;
|
||||
self->drdynvcs[ChId].data = procs->data;
|
||||
self->drdynvcs[ChId].status = XRDP_DRDYNVC_STATUS_OPEN_SENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
|
||||
{
|
||||
struct stream *s;
|
||||
int ChId;
|
||||
int cbChId;
|
||||
int static_channel_id;
|
||||
int total_data_len;
|
||||
int static_flags;
|
||||
char *cmd_ptr;
|
||||
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if ((self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) &&
|
||||
(self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN_SENT))
|
||||
{
|
||||
/* not open */
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
cmd_ptr[0] = CMD_DVC_CLOSE_CHANNEL | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
self->drdynvcs[ChId].status = XRDP_DRDYNVC_STATUS_CLOSE_SENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes,
|
||||
int total_data_bytes)
|
||||
{
|
||||
struct stream *s;
|
||||
int ChId;
|
||||
int cbChId;
|
||||
int cbTotalDataSize;
|
||||
int static_channel_id;
|
||||
int total_data_len;
|
||||
int static_flags;
|
||||
char *cmd_ptr;
|
||||
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (data_bytes > 1590)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes);
|
||||
out_uint8p(s, data, data_bytes);
|
||||
cmd_ptr[0] = CMD_DVC_DATA_FIRST | (cbTotalDataSize << 2) | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes)
|
||||
{
|
||||
struct stream *s;
|
||||
int ChId;
|
||||
int cbChId;
|
||||
int static_channel_id;
|
||||
int total_data_len;
|
||||
int static_flags;
|
||||
char *cmd_ptr;
|
||||
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (data_bytes > 1590)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
out_uint8p(s, data, data_bytes);
|
||||
cmd_ptr[0] = CMD_DVC_DATA | cbChId;
|
||||
static_channel_id = self->drdynvc_channel_id;
|
||||
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,7 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_SECONDARY;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
@ -76,7 +76,7 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_SECONDARY;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
@ -170,7 +170,7 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_SECONDARY;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
@ -373,7 +373,7 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_SECONDARY;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
@ -517,7 +517,7 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_SECONDARY;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
@ -611,7 +611,7 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_SECONDARY;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
@ -705,7 +705,7 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_SECONDARY;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
|
||||
@ -269,7 +269,7 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info)
|
||||
g_strncpy(client_info->key_file, value, 1023);
|
||||
}
|
||||
|
||||
if (!g_file_readable(client_info->key_file))
|
||||
if (!g_file_readable(client_info->key_file))
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR, "Cannot read private key file %s: %s",
|
||||
client_info->key_file, g_get_strerror());
|
||||
@ -561,7 +561,7 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
DEBUG(("in xrdp_rdp_send_data"));
|
||||
s_pop_layer(s, rdp_hdr);
|
||||
len = (int)(s->end - s->p);
|
||||
pdutype = 0x10 | RDP_PDU_DATA;
|
||||
pdutype = 0x10 | PDUTYPE_DATAPDU;
|
||||
pdulen = len;
|
||||
dlen = len;
|
||||
ctype = 0;
|
||||
@ -1125,6 +1125,7 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s)
|
||||
g_writeln("yeah, up_and_running");
|
||||
DEBUG(("up_and_running set"));
|
||||
xrdp_rdp_send_data_update_sync(self);
|
||||
xrdp_channel_drdynvc_start(self->sec_layer->chan_layer);
|
||||
}
|
||||
|
||||
DEBUG(("out xrdp_rdp_process_data_font"));
|
||||
@ -1295,7 +1296,7 @@ xrdp_rdp_send_deactivate(struct xrdp_rdp *self)
|
||||
|
||||
s_mark_end(s);
|
||||
|
||||
if (xrdp_rdp_send(self, s, RDP_PDU_DEACTIVATE) != 0)
|
||||
if (xrdp_rdp_send(self, s, PDUTYPE_DEACTIVATEALLPDU) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
DEBUG(("out xrdp_rdp_send_deactivate error"));
|
||||
|
||||
@ -701,6 +701,12 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
|
||||
DEBUG(("flag RDP_LOGON_LEAVE_AUDIO found"));
|
||||
}
|
||||
|
||||
if (flags & RDP_LOGON_RAIL)
|
||||
{
|
||||
self->rdp_layer->client_info.rail_enable = 1;
|
||||
DEBUG(("flag RDP_LOGON_RAIL found"));
|
||||
}
|
||||
|
||||
if ((flags & RDP_LOGON_AUTO) && (!self->rdp_layer->client_info.is_mce))
|
||||
/* todo, for now not allowing autologon and mce both */
|
||||
{
|
||||
@ -1840,57 +1846,54 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
|
||||
{
|
||||
int num_channels;
|
||||
int index;
|
||||
struct xrdp_client_info *client_info = (struct xrdp_client_info *)NULL;
|
||||
struct xrdp_client_info *client_info;
|
||||
struct mcs_channel_item *channel_item;
|
||||
|
||||
client_info = &(self->rdp_layer->client_info);
|
||||
|
||||
|
||||
DEBUG(("processing channels, channels_allowed is %d", client_info->channels_allowed));
|
||||
|
||||
DEBUG(("processing channels, channels_allowed is %d",
|
||||
client_info->channels_allowed));
|
||||
/* this is an option set in xrdp.ini */
|
||||
if (client_info->channels_allowed != 1) /* are channels on? */
|
||||
if (client_info->channels_allowed == 0) /* are channels on? */
|
||||
{
|
||||
g_writeln("xrdp_sec_process_mcs_data_channels: all channels are disabled by configuration");
|
||||
log_message(LOG_LEVEL_INFO, "all channels are disabled by "
|
||||
"configuration");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint32_le(s, num_channels);
|
||||
|
||||
if (num_channels > 31)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (index = 0; index < num_channels; index++)
|
||||
{
|
||||
struct mcs_channel_item *channel_item;
|
||||
|
||||
channel_item = (struct mcs_channel_item *)
|
||||
g_malloc(sizeof(struct mcs_channel_item), 1);
|
||||
channel_item = g_new0(struct mcs_channel_item, 1);
|
||||
if (!s_check_rem(s, 12))
|
||||
{
|
||||
g_free(channel_item);
|
||||
return 1;
|
||||
}
|
||||
in_uint8a(s, channel_item->name, 8);
|
||||
if (g_strlen(channel_item->name) == 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_WARNING, "xrdp_sec_process_mcs_data_channels: got an empty channel name, ignoring it");
|
||||
g_free(channel_item);
|
||||
continue;
|
||||
}
|
||||
in_uint32_le(s, channel_item->flags);
|
||||
channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1);
|
||||
list_add_item(self->mcs_layer->channel_list, (tintptr) channel_item);
|
||||
DEBUG(("got channel flags %8.8x name %s", channel_item->flags,
|
||||
channel_item->name));
|
||||
if (g_strlen(channel_item->name) > 0)
|
||||
{
|
||||
channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1);
|
||||
log_message(LOG_LEVEL_INFO, "adding channel item name %s chan_id "
|
||||
"%d flags 0x%8.8x", channel_item->name,
|
||||
channel_item->chanid, channel_item->flags);
|
||||
list_add_item(self->mcs_layer->channel_list,
|
||||
(intptr_t) channel_item);
|
||||
DEBUG(("got channel flags %8.8x name %s", channel_item->flags,
|
||||
channel_item->name));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(channel_item);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1527,7 +1527,7 @@ lfreerdp_pre_connect(freerdp *instance)
|
||||
instance->settings->password = g_strdup(mod->password);
|
||||
instance->settings->domain = g_strdup(mod->domain);
|
||||
|
||||
if (mod->client_info.rail_support_level > 0)
|
||||
if (mod->client_info.rail_enable && (mod->client_info.rail_support_level > 0))
|
||||
{
|
||||
LLOGLN(0, ("Railsupport !!!!!!!!!!!!!!!!!!"));
|
||||
instance->settings->remote_app = 1;
|
||||
|
||||
@ -56,8 +56,6 @@ xrdp_chansrv_SOURCES = \
|
||||
clipboard_file.h \
|
||||
devredir.c \
|
||||
devredir.h \
|
||||
drdynvc.c \
|
||||
drdynvc.h \
|
||||
fifo.c \
|
||||
fifo.h \
|
||||
irp.c \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -24,46 +24,20 @@
|
||||
#include "parse.h"
|
||||
#include "log.h"
|
||||
|
||||
#define MAX_DVC_CHANNELS 32
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/* data in struct trans::callback_data */
|
||||
struct xrdp_api_data
|
||||
{
|
||||
int chan_id;
|
||||
char header[64];
|
||||
int flags;
|
||||
|
||||
/* for dynamic virtual channels */
|
||||
struct trans *transp;
|
||||
int dvc_chan_id;
|
||||
int is_connected;
|
||||
};
|
||||
|
||||
int
|
||||
g_is_term(void);
|
||||
|
||||
int send_channel_data(int chan_id, char *data, int size);
|
||||
int send_channel_data(int chan_id, const char *data, int size);
|
||||
int send_rail_drawing_orders(char* data, int size);
|
||||
int main_cleanup(void);
|
||||
int add_timeout(int msoffset, void (*callback)(void* data), void* data);
|
||||
int find_empty_slot_in_dvc_channels(void);
|
||||
struct xrdp_api_data * struct_from_dvc_chan_id(tui32 dvc_chan_id);
|
||||
int remove_struct_with_chan_id(tui32 dvc_chan_id);
|
||||
|
||||
#define LOG_LEVEL 5
|
||||
|
||||
@ -97,4 +71,25 @@ int remove_struct_with_chan_id(tui32 dvc_chan_id);
|
||||
((GGET_UINT16(_ptr, (_offset) + 2)) << 16)
|
||||
#endif
|
||||
|
||||
struct chansrv_drdynvc_procs
|
||||
{
|
||||
int (*open_response)(int chan_id, int creation_status);
|
||||
int (*close_response)(int chan_id);
|
||||
int (*data_first)(int chan_id, char *data, int bytes, int total_bytes);
|
||||
int (*data)(int chan_id, char *data, int bytes);
|
||||
};
|
||||
|
||||
int
|
||||
chansrv_drdynvc_open(const char *name, int flags,
|
||||
struct chansrv_drdynvc_procs *procs, int *chan_id);
|
||||
int
|
||||
chansrv_drdynvc_close(int chan_id);
|
||||
int
|
||||
chansrv_drdynvc_data_first(int chan_id, const char *data, int data_bytes,
|
||||
int total_data_bytes);
|
||||
int
|
||||
chansrv_drdynvc_data(int chan_id, const char *data, int data_bytes);
|
||||
int
|
||||
chansrv_drdynvc_send_data(int chan_id, const char *data, int data_bytes);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1228,10 +1228,17 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
|
||||
{
|
||||
XRDP_INODE *xinode;
|
||||
XRDP_INODE *xinodep;
|
||||
time_t cur_time;
|
||||
|
||||
if ((name == NULL) || (strlen(name) == 0))
|
||||
return NULL;
|
||||
|
||||
/* Do we have an inode table yet? */
|
||||
if (xfuse_init_xrdp_fs())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xinode = g_new0(XRDP_INODE, 1);
|
||||
if (xinode == NULL)
|
||||
{
|
||||
@ -1239,14 +1246,16 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cur_time = time(0);
|
||||
|
||||
xinode->parent_inode = pinode;
|
||||
xinode->inode = g_xrdp_fs.next_node++;
|
||||
xinode->nlink = 1;
|
||||
xinode->uid = getuid();
|
||||
xinode->gid = getgid();
|
||||
xinode->atime = time(0);
|
||||
xinode->mtime = time(0);
|
||||
xinode->ctime = time(0);
|
||||
xinode->atime = cur_time;
|
||||
xinode->mtime = cur_time;
|
||||
xinode->ctime = cur_time;
|
||||
xinode->device_id = device_id;
|
||||
xinode->is_synced = 1;
|
||||
strcpy(xinode->name, name);
|
||||
|
||||
@ -1,531 +0,0 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2012 LK.Rashinkar@gmail.com
|
||||
*
|
||||
* 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(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "drdynvc.h"
|
||||
|
||||
extern int g_drdynvc_chan_id; /* in chansrv.c */
|
||||
int g_drdynvc_inited = 0;
|
||||
|
||||
static int drdynvc_send_capability_request(uint16_t version);
|
||||
static int drdynvc_process_capability_response(struct stream* s, unsigned char cmd);
|
||||
static int drdynvc_process_open_channel_response(struct stream *s, unsigned char cmd);
|
||||
static int drdynvc_process_close_channel_response(struct stream *s, unsigned char cmd);
|
||||
static int drdynvc_process_data_first(struct stream* s, unsigned char cmd);
|
||||
static int drdynvc_process_data(struct stream* s, unsigned char cmd);
|
||||
static int drdynvc_insert_uint_124(struct stream *s, uint32_t val);
|
||||
static int drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p);
|
||||
|
||||
/**
|
||||
* bring up dynamic virtual channel
|
||||
*
|
||||
* @return 0 on success, -1 on response
|
||||
******************************************************************************/
|
||||
int
|
||||
drdynvc_init(void)
|
||||
{
|
||||
/* bring up X11 */
|
||||
xcommon_init();
|
||||
|
||||
/* let client know what version of DVC we support */
|
||||
drdynvc_send_capability_request(2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* let DVC Manager on client end know what version of protocol we support
|
||||
* client will respond with version that it supports
|
||||
*
|
||||
* @return 0 on success, -1 on response
|
||||
******************************************************************************/
|
||||
static int
|
||||
drdynvc_send_capability_request(uint16_t version)
|
||||
{
|
||||
struct stream *s;
|
||||
int bytes_in_stream;
|
||||
|
||||
/* setup stream */
|
||||
make_stream(s);
|
||||
init_stream(s, MAX_PDU_SIZE);
|
||||
|
||||
out_uint8(s, 0x50); /* insert cmd */
|
||||
out_uint8(s, 0x00); /* insert padding */
|
||||
out_uint16_le(s, version); /* insert version */
|
||||
|
||||
/* channel priority unused for now */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 0 */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 1 */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 2 */
|
||||
out_uint16_le(s, 0x0000); /* priority charge 3 */
|
||||
|
||||
/* send command to client */
|
||||
bytes_in_stream = stream_length_before_p(s);
|
||||
send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream);
|
||||
free_stream(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process capability response received from DVC manager at client end
|
||||
*
|
||||
* @param s stream containing client response
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
******************************************************************************/
|
||||
static int
|
||||
drdynvc_process_capability_response(struct stream *s, unsigned char cmd)
|
||||
{
|
||||
int cap_version;
|
||||
|
||||
/* skip padding */
|
||||
in_uint8s(s, 1);
|
||||
|
||||
/* read client's version */
|
||||
in_uint16_le(s, cap_version);
|
||||
|
||||
if ((cap_version != 2) && (cap_version != 3))
|
||||
{
|
||||
LOG(0, ("drdynvc_process_capability_response: incompatible DVC "
|
||||
"version %d detected", cap_version));
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG(0, ("drdynvc_process_capability_response: DVC version %d selected",
|
||||
cap_version));
|
||||
g_drdynvc_inited = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new dynamic virtual channel
|
||||
*
|
||||
* @pram channel_id channel id number
|
||||
* @pram channel_name name of channel
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
******************************************************************************/
|
||||
int
|
||||
drdynvc_send_open_channel_request(int chan_pri, unsigned int chan_id,
|
||||
char *chan_name)
|
||||
{
|
||||
struct stream *s;
|
||||
int bytes_in_stream;
|
||||
int cbChId;
|
||||
int name_length;
|
||||
|
||||
if ((chan_name == NULL) || (strlen(chan_name) == 0))
|
||||
{
|
||||
LOG(0, ("drdynvc_send_open_channel_request: bad channel name specified"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, MAX_PDU_SIZE);
|
||||
|
||||
name_length = strlen(chan_name);
|
||||
|
||||
/* dummy command for now */
|
||||
out_uint8(s, 0);
|
||||
|
||||
/* insert channel id */
|
||||
cbChId = drdynvc_insert_uint_124(s, chan_id);
|
||||
|
||||
/* insert channel name */
|
||||
out_uint8a(s, chan_name, name_length + 1);
|
||||
|
||||
/* insert command */
|
||||
s->data[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId;
|
||||
|
||||
/* send command */
|
||||
bytes_in_stream = stream_length_before_p(s);
|
||||
send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream);
|
||||
free_stream(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
drdynvc_process_open_channel_response(struct stream *s, unsigned char cmd)
|
||||
{
|
||||
struct xrdp_api_data *adp;
|
||||
|
||||
uint32_t chan_id;
|
||||
int creation_status;
|
||||
|
||||
drdynvc_get_chan_id(s, cmd, &chan_id);
|
||||
in_uint32_le(s, creation_status);
|
||||
|
||||
/* LK_TODO now do something using useful! */
|
||||
|
||||
if (creation_status < 0)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get struct xrdp_api_data containing this channel id */
|
||||
if ((adp = struct_from_dvc_chan_id(chan_id)) == NULL)
|
||||
{
|
||||
LOG(0, ("drdynvc_process_open_channel_response: error : "
|
||||
"could not find xrdp_api_data containing chan_id %d", chan_id));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
adp->is_connected = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
drdynvc_send_close_channel_request(unsigned int chan_id)
|
||||
{
|
||||
struct stream *s;
|
||||
int bytes_in_stream;
|
||||
int cbChId;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, MAX_PDU_SIZE);
|
||||
|
||||
/* insert dummy cmd for now */
|
||||
out_uint8(s, 0);
|
||||
|
||||
/* insert channel id */
|
||||
cbChId = drdynvc_insert_uint_124(s, chan_id);
|
||||
|
||||
/* insert command */
|
||||
s->data[0] = CMD_DVC_CLOSE_CHANNEL | cbChId;
|
||||
|
||||
/* send command */
|
||||
bytes_in_stream = stream_length_before_p(s);
|
||||
send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream);
|
||||
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
drdynvc_process_close_channel_response(struct stream *s, unsigned char cmd)
|
||||
{
|
||||
uint32_t chan_id;
|
||||
|
||||
drdynvc_get_chan_id(s, cmd, &chan_id);
|
||||
|
||||
/* LK_TODO now do something using useful! */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* send data to client
|
||||
*
|
||||
* @param chan_id the virtual channel to write to
|
||||
* @param data data to write
|
||||
* @param data_size number of bytes to write
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
******************************************************************************/
|
||||
int drdynvc_write_data(uint32_t chan_id, char *data, int data_size)
|
||||
{
|
||||
struct stream *s;
|
||||
char *saved_ptr;
|
||||
int cbChId;
|
||||
int Len;
|
||||
int bytes_in_stream;
|
||||
int frag_size;
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
LOG(0, ("drdynvc_write_data: data is NULL\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data_size <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, MAX_PDU_SIZE);
|
||||
|
||||
/* this is a dummy write */
|
||||
out_uint8(s, 0);
|
||||
|
||||
/* insert channel id */
|
||||
cbChId = drdynvc_insert_uint_124(s, chan_id);
|
||||
|
||||
/* will data fit into one pkt? */
|
||||
bytes_in_stream = stream_length_before_p(s);
|
||||
|
||||
if ((bytes_in_stream + data_size) <= MAX_PDU_SIZE)
|
||||
{
|
||||
/* yes it will - insert data */
|
||||
out_uint8p(s, data, data_size);
|
||||
|
||||
/* insert command */
|
||||
s->data[0] = CMD_DVC_DATA | cbChId;
|
||||
|
||||
/* write data to client */
|
||||
bytes_in_stream = stream_length_before_p(s);
|
||||
send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream);
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no it won't - fragment it */
|
||||
|
||||
saved_ptr = s->p;
|
||||
|
||||
/* let client know how much data to expect */
|
||||
Len = drdynvc_insert_uint_124(s, data_size);
|
||||
|
||||
/* insert data into first fragment */
|
||||
frag_size = MAX_PDU_SIZE - stream_length_before_p(s);
|
||||
out_uint8p(s, data, frag_size);
|
||||
|
||||
/* insert command */
|
||||
s->data[0] = CMD_DVC_DATA_FIRST | Len << 2 | cbChId;
|
||||
|
||||
/* write first fragment to client */
|
||||
bytes_in_stream = stream_length_before_p(s);
|
||||
send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream);
|
||||
data_size -= frag_size;
|
||||
data += frag_size;
|
||||
s->data[0] = CMD_DVC_DATA | cbChId;
|
||||
s->p = saved_ptr;
|
||||
|
||||
/* now send rest of the data using CMD_DVC_DATA */
|
||||
while (data_size > 0)
|
||||
{
|
||||
frag_size = MAX_PDU_SIZE - stream_length_before_p(s);
|
||||
|
||||
if (frag_size > data_size)
|
||||
{
|
||||
frag_size = data_size;
|
||||
}
|
||||
|
||||
out_uint8p(s, data, frag_size);
|
||||
bytes_in_stream = stream_length_before_p(s);
|
||||
send_channel_data(g_drdynvc_chan_id, s->data, bytes_in_stream);
|
||||
data_size -= frag_size;
|
||||
data += frag_size;
|
||||
s->p = saved_ptr;
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
drdynvc_process_data_first(struct stream *s, unsigned char cmd)
|
||||
{
|
||||
struct xrdp_api_data *adp;
|
||||
struct stream *ls;
|
||||
|
||||
uint32_t chan_id;
|
||||
int bytes_in_stream;
|
||||
int Len;
|
||||
|
||||
drdynvc_get_chan_id(s, cmd, &chan_id);
|
||||
|
||||
Len = (cmd >> 2) & 0x03;
|
||||
|
||||
/* skip data_len */
|
||||
if (Len == 0)
|
||||
{
|
||||
in_uint8s(s, 1);
|
||||
}
|
||||
else if (Len == 1)
|
||||
{
|
||||
in_uint8s(s, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint8s(s, 4);
|
||||
}
|
||||
|
||||
bytes_in_stream = stream_length_after_p(s);
|
||||
|
||||
/* get struct xrdp_api_data containing this channel id */
|
||||
if ((adp = struct_from_dvc_chan_id(chan_id)) == NULL)
|
||||
{
|
||||
LOG(0, ("drdynvc_process_data_first: error : "
|
||||
"could not find xrdp_api_data containing chan_id %d", chan_id));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ls = trans_get_out_s(adp->transp, MAX_PDU_SIZE);
|
||||
out_uint8p(ls, s->p, bytes_in_stream);
|
||||
s_mark_end(ls);
|
||||
trans_force_write(adp->transp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
drdynvc_process_data(struct stream *s, unsigned char cmd)
|
||||
{
|
||||
struct xrdp_api_data *adp;
|
||||
struct stream *ls;
|
||||
|
||||
uint32_t chan_id;
|
||||
int bytes_in_stream;
|
||||
|
||||
drdynvc_get_chan_id(s, cmd, &chan_id);
|
||||
bytes_in_stream = stream_length_after_p(s);
|
||||
|
||||
/* get struct xrdp_api_data containing this channel id */
|
||||
if ((adp = struct_from_dvc_chan_id(chan_id)) == NULL)
|
||||
{
|
||||
LOG(0, ("drdynvc_process_data: error : "
|
||||
"could not find xrdp_api_data containing chan_id %d", chan_id));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ls = trans_get_out_s(adp->transp, MAX_PDU_SIZE);
|
||||
out_uint8p(ls, s->p, bytes_in_stream);
|
||||
s_mark_end(ls);
|
||||
trans_force_write(adp->transp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process incoming data on a dynamic virtual channel
|
||||
*
|
||||
* @pram s stream containing the incoming data
|
||||
* @pram chan_id LK_TODO
|
||||
* @pram chan_flags LK_TODO
|
||||
* @pram length LK_TODO
|
||||
* @pram total_length LK_TODO
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
******************************************************************************/
|
||||
int
|
||||
drdynvc_data_in(struct stream *s, int chan_id, int chan_flags, int length,
|
||||
int total_length)
|
||||
{
|
||||
unsigned char cmd;
|
||||
|
||||
in_uint8(s, cmd); /* read command */
|
||||
|
||||
switch (cmd & 0xf0)
|
||||
{
|
||||
case CMD_DVC_CAPABILITY:
|
||||
drdynvc_process_capability_response(s, cmd);
|
||||
break;
|
||||
|
||||
case CMD_DVC_OPEN_CHANNEL:
|
||||
drdynvc_process_open_channel_response(s, cmd);
|
||||
break;
|
||||
|
||||
case CMD_DVC_CLOSE_CHANNEL:
|
||||
drdynvc_process_close_channel_response(s, cmd);
|
||||
break;
|
||||
|
||||
case CMD_DVC_DATA_FIRST:
|
||||
drdynvc_process_data_first(s, cmd);
|
||||
break;
|
||||
|
||||
case CMD_DVC_DATA:
|
||||
drdynvc_process_data(s, cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(0, ("drdynvc_data_in: got unknown command 0x%x", cmd));
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* insert a byte, short or 32bit value into specified stream
|
||||
*
|
||||
* @param s stream used for insertion
|
||||
* @param val value to insert
|
||||
*
|
||||
* @return 0 for byte insertions
|
||||
* @return 1 for short insertion
|
||||
* @return 2 for uint32_t insertions
|
||||
******************************************************************************/
|
||||
static int
|
||||
drdynvc_insert_uint_124(struct stream *s, uint32_t val)
|
||||
{
|
||||
int ret_val;
|
||||
|
||||
if (val <= 0xff)
|
||||
{
|
||||
out_uint8(s, val);
|
||||
ret_val = 0;
|
||||
}
|
||||
else if (val <= 0xffff)
|
||||
{
|
||||
out_uint16_le(s, val);
|
||||
ret_val = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint32_le(s, val);
|
||||
ret_val = 2;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* extract channel id from stream
|
||||
*
|
||||
* @param s stream containing channel id
|
||||
* @param cmd first byte in stream
|
||||
* @param chan_id return channel id here
|
||||
******************************************************************************/
|
||||
static int
|
||||
drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
{
|
||||
int cbChId;
|
||||
int chan_id;
|
||||
|
||||
cbChId = cmd & 0x03;
|
||||
|
||||
if (cbChId == 0)
|
||||
{
|
||||
in_uint8(s, chan_id);
|
||||
}
|
||||
else if (cbChId == 1)
|
||||
{
|
||||
in_uint16_le(s, chan_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint32_le(s, chan_id);
|
||||
}
|
||||
|
||||
*chan_id_p = chan_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2012 LK.Rashinkar@gmail.com
|
||||
*
|
||||
* 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 _DRDYNVC_H_
|
||||
#define _DRDYNVC_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "arch.h"
|
||||
#include "chansrv.h"
|
||||
#include "xcommon.h"
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "trans.h"
|
||||
|
||||
/* move this to tsmf.c */
|
||||
#define TSMF_CHAN_ID 0x1000
|
||||
|
||||
/* get number of bytes in stream before s->p */
|
||||
#define stream_length_before_p(s) (int) ((s)->p - (s)->data)
|
||||
|
||||
/* get number of bytes in stream after s->p */
|
||||
#define stream_length_after_p(s) (int) ((s)->end - (s)->p)
|
||||
|
||||
#define rewind_stream(s) do \
|
||||
{ \
|
||||
(s)->p = (s)->data; \
|
||||
(s)->end = (s)->data; \
|
||||
} while (0)
|
||||
|
||||
/* max number of bytes we can send in one pkt */
|
||||
#define MAX_PDU_SIZE 1600
|
||||
|
||||
/* commands used to manage dynamic virtual channels */
|
||||
#define CMD_DVC_OPEN_CHANNEL 0x10
|
||||
#define CMD_DVC_DATA_FIRST 0x20
|
||||
#define CMD_DVC_DATA 0x30
|
||||
#define CMD_DVC_CLOSE_CHANNEL 0x40
|
||||
#define CMD_DVC_CAPABILITY 0x50
|
||||
|
||||
int drdynvc_init(void);
|
||||
int drdynvc_send_open_channel_request(int chan_pri, unsigned int chan_id,
|
||||
char *chan_name);
|
||||
int drdynvc_send_close_channel_request(unsigned int chan_id);
|
||||
int drdynvc_write_data(uint32_t chan_id, char *data, int data_size);
|
||||
int drdynvc_data_in(struct stream* s, int chan_id, int chan_flags,
|
||||
int length, int total_length);
|
||||
|
||||
#endif
|
||||
@ -38,6 +38,12 @@
|
||||
#if defined(XRDP_FDK_AAC)
|
||||
#include <fdk-aac/aacenc_lib.h>
|
||||
static HANDLE_AACENCODER g_fdk_aac_encoder = 0;
|
||||
|
||||
#define AACENCODER_LIB_VER_GTEQ(vl0, vl1, vl2) \
|
||||
(defined(AACENCODER_LIB_VL0) && \
|
||||
((AACENCODER_LIB_VL0 > vl0) || \
|
||||
(AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 >= vl1) || \
|
||||
(AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 == vl1 && AACENCODER_LIB_VL2 > vl2)))
|
||||
#endif
|
||||
|
||||
#if defined(XRDP_OPUS)
|
||||
@ -598,7 +604,12 @@ sound_wave_compress_fdk_aac(char *data, int data_bytes, int *format_index)
|
||||
LOG(0, (" inBufFillLevel %d", info.inBufFillLevel));
|
||||
LOG(0, (" inputChannels %d", info.inputChannels));
|
||||
LOG(0, (" frameLength %d", info.frameLength));
|
||||
#if AACENCODER_LIB_VER_GTEQ(4, 0, 0)
|
||||
LOG(0, (" nDelay %d", info.nDelay));
|
||||
LOG(0, (" nDelayCore %d", info.nDelayCore));
|
||||
#else
|
||||
LOG(0, (" encoderDelay %d", info.encoderDelay));
|
||||
#endif
|
||||
LOG(0, (" confBuf"));
|
||||
LOG(0, (" confSize %d", info.confSize));
|
||||
}
|
||||
|
||||
@ -44,6 +44,12 @@ KillDisconnected=false
|
||||
; min 60 seconds
|
||||
DisconnectedTimeLimit=0
|
||||
|
||||
;; IdleTimeLimit (specify in second) - wait before disconnect idle sessions
|
||||
; Type: integer
|
||||
; Default: 0
|
||||
; Set to 0 to disable idle disconnection.
|
||||
IdleTimeLimit=0
|
||||
|
||||
;; Policy - session allocation policy
|
||||
; Type: enum [ "Default" | "UBD" | "UBI" | "UBC" | "UBDI" | "UBDC" ]
|
||||
; Default: Xrdp:<User,BitPerPixel> and Xvnc:<User,BitPerPixel,DisplaySize>
|
||||
@ -84,13 +90,6 @@ param=tcp
|
||||
param=-logfile
|
||||
param=.xorgxrdp.%s.log
|
||||
|
||||
[X11rdp]
|
||||
param=X11rdp
|
||||
param=-bs
|
||||
param=-nolisten
|
||||
param=tcp
|
||||
param=-uds
|
||||
|
||||
[Xvnc]
|
||||
param=Xvnc
|
||||
param=-bs
|
||||
|
||||
@ -138,6 +138,8 @@ int
|
||||
callback(intptr_t id, int msg, intptr_t param1, intptr_t param2,
|
||||
intptr_t param3, intptr_t param4);
|
||||
int
|
||||
xrdp_wm_drdynvc_up(intptr_t id);
|
||||
int
|
||||
xrdp_wm_delete_all_children(struct xrdp_wm* self);
|
||||
int
|
||||
xrdp_wm_show_log(struct xrdp_wm *self);
|
||||
@ -367,6 +369,8 @@ xrdp_bitmap_compress(char* in_data, int width, int height,
|
||||
int e);
|
||||
|
||||
/* xrdp_mm.c */
|
||||
int
|
||||
xrdp_mm_drdynvc_up(struct xrdp_mm* self);
|
||||
struct xrdp_mm*
|
||||
xrdp_mm_create(struct xrdp_wm* owner);
|
||||
void
|
||||
|
||||
@ -162,16 +162,6 @@ ip=127.0.0.1
|
||||
port=-1
|
||||
code=20
|
||||
|
||||
[X11rdp]
|
||||
name=X11rdp
|
||||
lib=libxup.@lib_extension@
|
||||
username=ask
|
||||
password=ask
|
||||
ip=127.0.0.1
|
||||
port=-1
|
||||
xserverbpp=24
|
||||
code=10
|
||||
|
||||
[Xvnc]
|
||||
name=Xvnc
|
||||
lib=libvnc.@lib_extension@
|
||||
@ -182,15 +172,6 @@ port=-1
|
||||
#xserverbpp=24
|
||||
#delay_ms=2000
|
||||
|
||||
[console]
|
||||
name=console
|
||||
lib=libvnc.@lib_extension@
|
||||
ip=127.0.0.1
|
||||
port=5900
|
||||
username=na
|
||||
password=ask
|
||||
#delay_ms=2000
|
||||
|
||||
[vnc-any]
|
||||
name=vnc-any
|
||||
lib=libvnc.@lib_extension@
|
||||
@ -203,15 +184,6 @@ password=ask
|
||||
#pamsessionmng=127.0.0.1
|
||||
#delay_ms=2000
|
||||
|
||||
[sesman-any]
|
||||
name=sesman-any
|
||||
lib=libvnc.@lib_extension@
|
||||
ip=ask
|
||||
port=-1
|
||||
username=ask
|
||||
password=ask
|
||||
#delay_ms=2000
|
||||
|
||||
[neutrinordp-any]
|
||||
name=neutrinordp-any
|
||||
lib=libxrdpneutrinordp.@lib_extension@
|
||||
|
||||
@ -74,8 +74,9 @@ rdp_layout_br=0x00000416
|
||||
rdp_layout_ru=0x00000419
|
||||
rdp_layout_se=0x0000041D
|
||||
rdp_layout_ch=0x00000807
|
||||
rdp_layout_ch_fr=0x0000100c
|
||||
rdp_layout_ch_fr=0x0000100C
|
||||
rdp_layout_gb=0x00000809
|
||||
rdp_layout_latam=0x0000080A
|
||||
rdp_layout_be=0x00000813
|
||||
rdp_layout_pt=0x00000816
|
||||
|
||||
@ -97,6 +98,7 @@ rdp_layout_se=se
|
||||
rdp_layout_ch=ch
|
||||
rdp_layout_ch_fr=ch(fr)
|
||||
rdp_layout_gb=gb
|
||||
rdp_layout_latam=latam
|
||||
rdp_layout_be=be
|
||||
rdp_layout_pt=pt
|
||||
|
||||
@ -132,5 +134,6 @@ rdp_layout_se=se
|
||||
rdp_layout_ch=ch
|
||||
rdp_layout_ch_fr=ch(fr)
|
||||
rdp_layout_gb=gb
|
||||
rdp_layout_latam=latam
|
||||
rdp_layout_be=be
|
||||
rdp_layout_pt=pt
|
||||
|
||||
741
xrdp/xrdp_mm.c
741
xrdp/xrdp_mm.c
@ -679,71 +679,28 @@ xrdp_mm_trans_send_channel_setup(struct xrdp_mm *self, struct trans *trans)
|
||||
return trans_force_write(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int
|
||||
xrdp_mm_trans_send_channel_data_response(struct xrdp_mm *self,
|
||||
struct trans *trans)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
s = trans_get_out_s(trans, 8192);
|
||||
|
||||
if (s == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_uint32_le(s, 0); /* version */
|
||||
out_uint32_le(s, 8 + 8); /* size */
|
||||
out_uint32_le(s, 7); /* msg id */
|
||||
out_uint32_le(s, 8); /* size */
|
||||
s_mark_end(s);
|
||||
return trans_force_write(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error
|
||||
init is done, sent channel setup */
|
||||
static int
|
||||
xrdp_mm_trans_process_init_response(struct xrdp_mm *self, struct trans *trans)
|
||||
{
|
||||
return xrdp_mm_trans_send_channel_setup(self, trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error
|
||||
data coming in from the channel handler, send it to the client */
|
||||
static int
|
||||
xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct trans *trans)
|
||||
xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct stream *s)
|
||||
{
|
||||
struct stream *s;
|
||||
int size;
|
||||
int total_size;
|
||||
int chan_id;
|
||||
int chan_flags;
|
||||
int rv;
|
||||
|
||||
s = trans_get_in_s(trans);
|
||||
|
||||
if (s == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint16_le(s, chan_id);
|
||||
in_uint16_le(s, chan_flags);
|
||||
in_uint16_le(s, size);
|
||||
in_uint32_le(s, total_size);
|
||||
rv = xrdp_mm_trans_send_channel_data_response(self, trans);
|
||||
rv = 0;
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
if (is_channel_allowed(self->wm, chan_id))
|
||||
{
|
||||
rv = libxrdp_send_to_channel(self->wm->session, chan_id, s->p, size, total_size,
|
||||
chan_flags);
|
||||
}
|
||||
rv = libxrdp_send_to_channel(self->wm->session, chan_id, s->p, size, total_size,
|
||||
chan_flags);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -970,12 +927,11 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s)
|
||||
{
|
||||
int size;
|
||||
int flags;
|
||||
int rv = 0;
|
||||
int rv;
|
||||
int window_id;
|
||||
struct rail_window_state_order rwso;
|
||||
|
||||
g_writeln("xrdp_mm_process_rail_update_window_text:");
|
||||
|
||||
in_uint32_le(s, window_id);
|
||||
in_uint32_le(s, flags);
|
||||
g_writeln(" update window title info: 0x%8.8x", window_id);
|
||||
@ -1006,17 +962,12 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s)
|
||||
/* returns error
|
||||
process alternate secondary drawing orders for rail channel */
|
||||
static int
|
||||
xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans)
|
||||
xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct stream *s)
|
||||
{
|
||||
struct stream* s;
|
||||
int order_type;
|
||||
int rv = 0;
|
||||
int rv;
|
||||
|
||||
s = trans_get_in_s(trans);
|
||||
if (s == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
rv = 0;
|
||||
in_uint32_le(s, order_type);
|
||||
|
||||
switch(order_type)
|
||||
@ -1040,6 +991,302 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
xrdp_mm_drdynvc_up(struct xrdp_mm* self)
|
||||
{
|
||||
LLOGLN(0, ("xrdp_mm_drdynvc_up:"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* open response from client going to channel server */
|
||||
static int
|
||||
xrdp_mm_drdynvc_open_response(intptr_t id, int chan_id, int creation_status)
|
||||
{
|
||||
struct trans *trans;
|
||||
struct stream *s;
|
||||
struct xrdp_wm* wm;
|
||||
struct xrdp_process *pro;
|
||||
int chansrv_chan_id;
|
||||
|
||||
LLOGLN(10, ("xrdp_mm_drdynvc_open_response: chan_id %d creation_status %d",
|
||||
chan_id, creation_status));
|
||||
pro = (struct xrdp_process *) id;
|
||||
wm = pro->wm;
|
||||
trans = wm->mm->chan_trans;
|
||||
s = trans_get_out_s(trans, 8192);
|
||||
if (s == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
out_uint32_le(s, 0); /* version */
|
||||
out_uint32_le(s, 24); /* size */
|
||||
out_uint32_le(s, 13); /* msg id */
|
||||
out_uint32_le(s, 16); /* size */
|
||||
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
|
||||
out_uint32_le(s, chansrv_chan_id);
|
||||
out_uint32_le(s, creation_status); /* status */
|
||||
s_mark_end(s);
|
||||
return trans_write_copy(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* close response from client going to channel server */
|
||||
static int
|
||||
xrdp_mm_drdynvc_close_response(intptr_t id, int chan_id)
|
||||
{
|
||||
struct trans *trans;
|
||||
struct stream *s;
|
||||
struct xrdp_wm* wm;
|
||||
struct xrdp_process *pro;
|
||||
int chansrv_chan_id;
|
||||
|
||||
pro = (struct xrdp_process *) id;
|
||||
wm = pro->wm;
|
||||
trans = wm->mm->chan_trans;
|
||||
s = trans_get_out_s(trans, 8192);
|
||||
if (s == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
out_uint32_le(s, 0); /* version */
|
||||
out_uint32_le(s, 20); /* size */
|
||||
out_uint32_le(s, 15); /* msg id */
|
||||
out_uint32_le(s, 12); /* size */
|
||||
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
|
||||
out_uint32_le(s, chansrv_chan_id);
|
||||
s_mark_end(s);
|
||||
return trans_write_copy(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* part data from client going to channel server */
|
||||
static int
|
||||
xrdp_mm_drdynvc_data_first(intptr_t id, int chan_id, char *data,
|
||||
int bytes, int total_bytes)
|
||||
{
|
||||
struct trans *trans;
|
||||
struct stream *s;
|
||||
struct xrdp_wm* wm;
|
||||
struct xrdp_process *pro;
|
||||
int chansrv_chan_id;
|
||||
|
||||
pro = (struct xrdp_process *) id;
|
||||
wm = pro->wm;
|
||||
trans = wm->mm->chan_trans;
|
||||
s = trans_get_out_s(trans, 8192);
|
||||
if (s == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
out_uint32_le(s, 0); /* version */
|
||||
out_uint32_le(s, 8 + 8 + 4 + 4 + 4 + bytes);
|
||||
out_uint32_le(s, 17); /* msg id */
|
||||
out_uint32_le(s, 8 + 4 + 4 + 4 + bytes);
|
||||
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
|
||||
out_uint32_le(s, chansrv_chan_id);
|
||||
out_uint32_le(s, bytes);
|
||||
out_uint32_le(s, total_bytes);
|
||||
out_uint8a(s, data, bytes);
|
||||
s_mark_end(s);
|
||||
return trans_write_copy(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data from client going to channel server */
|
||||
static int
|
||||
xrdp_mm_drdynvc_data(intptr_t id, int chan_id, char *data, int bytes)
|
||||
{
|
||||
struct trans *trans;
|
||||
struct stream *s;
|
||||
struct xrdp_wm* wm;
|
||||
struct xrdp_process *pro;
|
||||
int chansrv_chan_id;
|
||||
|
||||
pro = (struct xrdp_process *) id;
|
||||
wm = pro->wm;
|
||||
trans = wm->mm->chan_trans;
|
||||
s = trans_get_out_s(trans, 8192);
|
||||
if (s == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
out_uint32_le(s, 0); /* version */
|
||||
out_uint32_le(s, 8 + 8 + 4 + 4 + bytes);
|
||||
out_uint32_le(s, 19); /* msg id */
|
||||
out_uint32_le(s, 8 + 4 + 4 + bytes);
|
||||
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
|
||||
out_uint32_le(s, chansrv_chan_id);
|
||||
out_uint32_le(s, bytes);
|
||||
out_uint8a(s, data, bytes);
|
||||
s_mark_end(s);
|
||||
return trans_write_copy(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* open message from channel server going to client */
|
||||
static int
|
||||
xrdp_mm_trans_process_drdynvc_channel_open(struct xrdp_mm* self,
|
||||
struct stream *s)
|
||||
{
|
||||
int name_bytes;
|
||||
int flags;
|
||||
int error;
|
||||
int chan_id;
|
||||
int chansrv_chan_id;
|
||||
char *name;
|
||||
struct xrdp_drdynvc_procs procs;
|
||||
|
||||
if (!s_check_rem(s, 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, name_bytes);
|
||||
if ((name_bytes < 1) || (name_bytes > 1024))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
name = g_new(char, name_bytes + 1);
|
||||
if (name == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem(s, name_bytes))
|
||||
{
|
||||
g_free(name);
|
||||
return 1;
|
||||
}
|
||||
in_uint8a(s, name, name_bytes);
|
||||
name[name_bytes] = 0;
|
||||
if (!s_check_rem(s, 8))
|
||||
{
|
||||
g_free(name);
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, flags);
|
||||
in_uint32_le(s, chansrv_chan_id);
|
||||
if (flags == 0)
|
||||
{
|
||||
/* open static channel, not supported */
|
||||
g_free(name);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* dynamic channel */
|
||||
g_memset(&procs, 0, sizeof(procs));
|
||||
procs.open_response = xrdp_mm_drdynvc_open_response;
|
||||
procs.close_response = xrdp_mm_drdynvc_close_response;
|
||||
procs.data_first = xrdp_mm_drdynvc_data_first;
|
||||
procs.data = xrdp_mm_drdynvc_data;
|
||||
chan_id = 0;
|
||||
error = libxrdp_drdynvc_open(self->wm->session, name, flags, &procs,
|
||||
&chan_id);
|
||||
if (error != 0)
|
||||
{
|
||||
g_free(name);
|
||||
return 1;
|
||||
}
|
||||
self->xr2cr_cid_map[chan_id] = chansrv_chan_id;
|
||||
self->cs2xr_cid_map[chansrv_chan_id] = chan_id;
|
||||
}
|
||||
g_free(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* close message from channel server going to client */
|
||||
static int
|
||||
xrdp_mm_trans_process_drdynvc_channel_close(struct xrdp_mm* self,
|
||||
struct stream *s)
|
||||
{
|
||||
int chansrv_chan_id;
|
||||
int chan_id;
|
||||
int error;
|
||||
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, chansrv_chan_id);
|
||||
chan_id = self->cs2xr_cid_map[chansrv_chan_id];
|
||||
/* close dynamic channel */
|
||||
error = libxrdp_drdynvc_close(self->wm->session, chan_id);
|
||||
if (error != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data from channel server going to client */
|
||||
static int
|
||||
xrdp_mm_trans_process_drdynvc_data_first(struct xrdp_mm* self,
|
||||
struct stream *s)
|
||||
{
|
||||
int chansrv_chan_id;
|
||||
int chan_id;
|
||||
int error;
|
||||
int data_bytes;
|
||||
int total_bytes;
|
||||
char *data;
|
||||
|
||||
if (!s_check_rem(s, 12))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, chansrv_chan_id);
|
||||
in_uint32_le(s, data_bytes);
|
||||
in_uint32_le(s, total_bytes);
|
||||
if ((!s_check_rem(s, data_bytes)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8p(s, data, data_bytes);
|
||||
chan_id = self->cs2xr_cid_map[chansrv_chan_id];
|
||||
error = libxrdp_drdynvc_data_first(self->wm->session, chan_id, data,
|
||||
data_bytes, total_bytes);
|
||||
if (error != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data from channel server going to client */
|
||||
static int
|
||||
xrdp_mm_trans_process_drdynvc_data(struct xrdp_mm* self,
|
||||
struct stream *s)
|
||||
{
|
||||
int chansrv_chan_id;
|
||||
int chan_id;
|
||||
int error;
|
||||
int data_bytes;
|
||||
char *data;
|
||||
|
||||
if (!s_check_rem(s, 8))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, chansrv_chan_id);
|
||||
in_uint32_le(s, data_bytes);
|
||||
if ((!s_check_rem(s, data_bytes)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8p(s, data, data_bytes);
|
||||
chan_id = self->cs2xr_cid_map[chansrv_chan_id];
|
||||
error = libxrdp_drdynvc_data(self->wm->session, chan_id, data, data_bytes);
|
||||
if (error != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error
|
||||
process a message for the channel handler */
|
||||
@ -1051,6 +1298,7 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans,
|
||||
int id;
|
||||
int size;
|
||||
char *next_msg;
|
||||
char *s_end;
|
||||
|
||||
rv = 0;
|
||||
|
||||
@ -1059,31 +1307,47 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans,
|
||||
next_msg = s->p;
|
||||
in_uint32_le(s, id);
|
||||
in_uint32_le(s, size);
|
||||
if (size < 8)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem(s, size - 8))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
next_msg += size;
|
||||
|
||||
s_end = s->end;
|
||||
s->end = next_msg;
|
||||
LLOGLN(10, ("xrdp_mm_chan_process_msg: got msg id %d", id));
|
||||
switch (id)
|
||||
{
|
||||
case 2: /* channel init response */
|
||||
rv = xrdp_mm_trans_process_init_response(self, trans);
|
||||
break;
|
||||
case 4: /* channel setup response */
|
||||
break;
|
||||
case 6: /* channel data response */
|
||||
break;
|
||||
case 8: /* channel data */
|
||||
rv = xrdp_mm_trans_process_channel_data(self, trans);
|
||||
rv = xrdp_mm_trans_process_channel_data(self, s);
|
||||
break;
|
||||
case 10: /* rail alternate secondary drawing orders */
|
||||
rv = xrdp_mm_process_rail_drawing_orders(self, trans);
|
||||
rv = xrdp_mm_process_rail_drawing_orders(self, s);
|
||||
break;
|
||||
case 12:
|
||||
rv = xrdp_mm_trans_process_drdynvc_channel_open(self, s);
|
||||
break;
|
||||
case 14:
|
||||
rv = xrdp_mm_trans_process_drdynvc_channel_close(self, s);
|
||||
break;
|
||||
case 16:
|
||||
rv = xrdp_mm_trans_process_drdynvc_data_first(self, s);
|
||||
break;
|
||||
case 18:
|
||||
rv = xrdp_mm_trans_process_drdynvc_data(self, s);
|
||||
break;
|
||||
default:
|
||||
log_message(LOG_LEVEL_ERROR,"xrdp_mm_chan_process_msg: unknown id %d", id);
|
||||
break;
|
||||
}
|
||||
|
||||
s->end = s_end;
|
||||
if (rv != 0)
|
||||
{
|
||||
break;
|
||||
LLOGLN(0, ("xrdp_mm_chan_process_msg: error rv %d id %d", rv, id));
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
s->p = next_msg;
|
||||
@ -1116,40 +1380,28 @@ xrdp_mm_chan_data_in(struct trans *trans)
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 4); /* id */
|
||||
in_uint32_le(s, size);
|
||||
error = trans_force_read(trans, size - 8);
|
||||
|
||||
if (error == 0)
|
||||
if (trans->extra_flags == 0)
|
||||
{
|
||||
/* here, the entire message block is read in, process it */
|
||||
error = xrdp_mm_chan_process_msg(self, trans, s);
|
||||
in_uint8s(s, 4); /* id */
|
||||
in_uint32_le(s, size);
|
||||
LLOGLN(10, ("xrdp_mm_chan_data_in: got header, size %d", size));
|
||||
if (size > 8)
|
||||
{
|
||||
self->chan_trans->header_size = size;
|
||||
trans->extra_flags = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* here, the entire message block is read in, process it */
|
||||
error = xrdp_mm_chan_process_msg(self, trans, s);
|
||||
self->chan_trans->header_size = 8;
|
||||
trans->extra_flags = 0;
|
||||
init_stream(s, 0);
|
||||
LLOGLN(10, ("xrdp_mm_chan_data_in: got whole message, reset for "
|
||||
"next header"));
|
||||
return error;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_mm_chan_send_init(struct xrdp_mm *self)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
s = trans_get_out_s(self->chan_trans, 8192);
|
||||
|
||||
if (s == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_uint32_le(s, 0); /* version */
|
||||
out_uint32_le(s, 8 + 8); /* size */
|
||||
out_uint32_le(s, 1); /* msg id */
|
||||
out_uint32_le(s, 8); /* size */
|
||||
s_mark_end(s);
|
||||
return trans_force_write(self->chan_trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* connect to chansrv */
|
||||
static int
|
||||
@ -1177,6 +1429,8 @@ xrdp_mm_connect_chansrv(struct xrdp_mm *self, const char *ip, const char *port)
|
||||
self->chan_trans->trans_data_in = xrdp_mm_chan_data_in;
|
||||
self->chan_trans->header_size = 8;
|
||||
self->chan_trans->callback_data = self;
|
||||
self->chan_trans->no_stream_init_on_data_in = 1;
|
||||
self->chan_trans->extra_flags = 0;
|
||||
|
||||
/* try to connect up to 4 times */
|
||||
for (index = 0; index < 4; index++)
|
||||
@ -1200,10 +1454,10 @@ xrdp_mm_connect_chansrv(struct xrdp_mm *self, const char *ip, const char *port)
|
||||
|
||||
if (self->chan_trans_up)
|
||||
{
|
||||
if (xrdp_mm_chan_send_init(self) != 0)
|
||||
if (xrdp_mm_trans_send_channel_setup(self, self->chan_trans) != 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR,"xrdp_mm_connect_chansrv: error in "
|
||||
"xrdp_mm_chan_send_init");
|
||||
"xrdp_mm_trans_send_channel_setup");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1227,6 +1481,47 @@ static void cleanup_sesman_connection(struct xrdp_mm *self)
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* does the section in xrdp.ini has any channel.*=true | false */
|
||||
static int
|
||||
xrdp_mm_update_allowed_channels(struct xrdp_mm *self)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
int chan_id;
|
||||
int disabled;
|
||||
const char *name;
|
||||
const char *value;
|
||||
const char *chan_name;
|
||||
struct xrdp_session *session;
|
||||
|
||||
session = self->wm->session;
|
||||
count = self->login_names->count;
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
name = (const char *) list_get_item(self->login_names, index);
|
||||
if (g_strncasecmp(name, "channel.", 8) == 0)
|
||||
{
|
||||
value = (const char *) list_get_item(self->login_values, index);
|
||||
chan_name = name + 8;
|
||||
chan_id = libxrdp_get_channel_id(session, chan_name);
|
||||
disabled = !g_text2bool(value);
|
||||
libxrdp_disable_channel(session, chan_id, disabled);
|
||||
if (disabled)
|
||||
{
|
||||
g_writeln("xrdp_mm_update_allowed_channels: channel %s "
|
||||
"channel id %d is disabled", chan_name, chan_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("xrdp_mm_update_allowed_channels: channel %s "
|
||||
"channel id %d is allowed", chan_name, chan_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s)
|
||||
@ -1271,7 +1566,7 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s)
|
||||
{
|
||||
g_snprintf(port, 255, "%d", 7200 + display);
|
||||
}
|
||||
|
||||
xrdp_mm_update_allowed_channels(self);
|
||||
xrdp_mm_connect_chansrv(self, ip, port);
|
||||
}
|
||||
}
|
||||
@ -2068,7 +2363,8 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self,
|
||||
|
||||
if ((self->chan_trans != 0) && self->chan_trans_up)
|
||||
{
|
||||
trans_get_wait_objs(self->chan_trans, read_objs, rcount);
|
||||
trans_get_wait_objs_rw(self->chan_trans, read_objs, rcount,
|
||||
write_objs, wcount, timeout);
|
||||
}
|
||||
|
||||
if (self->mod != 0)
|
||||
@ -2975,220 +3271,6 @@ server_reset(struct xrdp_mod *mod, int width, int height, int bpp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read the channel section of the ini file into lists
|
||||
* return 1 on success 0 on failure */
|
||||
int read_allowed_channel_names(struct list *names, struct list *values)
|
||||
{
|
||||
int fd;
|
||||
int ret = 0;
|
||||
char cfg_file[256];
|
||||
|
||||
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
|
||||
fd = g_file_open(cfg_file);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
names->auto_free = 1;
|
||||
values->auto_free = 1;
|
||||
|
||||
/* all values in this section can be valid channel names */
|
||||
if (file_read_section(fd, "channels", names, values) == 0)
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR,"Failure reading channel section of configuration");
|
||||
}
|
||||
|
||||
g_file_close(fd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* internal function return -1 if name is not in list
|
||||
* otherwise return the index 0->count-1*/
|
||||
int
|
||||
find_name_in_lists(char *inName, struct list *names)
|
||||
{
|
||||
int reply = -1; /*means not in the list*/
|
||||
int index;
|
||||
char *name;
|
||||
|
||||
for (index = 0; index < names->count; index++)
|
||||
{
|
||||
name = (char *)list_get_item(names, index);
|
||||
if ( (name != 0) && (g_strncasecmp(name, inName, MAX_CHANNEL_NAME) == 0) )
|
||||
{
|
||||
reply = index;
|
||||
break; /* stop loop - item found*/
|
||||
}
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
#define CHANNEL_NAME_PREFIX "channel."
|
||||
/* update the channel lists from connection specific overrides
|
||||
* return 1 on success 0 on failure */
|
||||
int update_allowed_channel_names(struct xrdp_wm *wm, struct list *names, struct list *values)
|
||||
{
|
||||
int ret = 1;
|
||||
int index;
|
||||
int oldindex;
|
||||
char *val;
|
||||
char *name;
|
||||
//wm->mm->login_names,wm->mm->login_values
|
||||
for (index = 0; index < wm->mm->login_names->count; index++)
|
||||
{
|
||||
name = (char *)list_get_item(wm->mm->login_names, index);
|
||||
if ( (name != 0) && (g_strncmp( name, CHANNEL_NAME_PREFIX, g_strlen(CHANNEL_NAME_PREFIX)) == 0 ) )
|
||||
{
|
||||
name += g_strlen(CHANNEL_NAME_PREFIX);
|
||||
// locate and remove from list
|
||||
oldindex = find_name_in_lists(name, names);
|
||||
if (oldindex >= 0)
|
||||
{
|
||||
list_remove_item(names, oldindex);
|
||||
list_remove_item(values, oldindex);
|
||||
}
|
||||
val = (char *)list_get_item(wm->mm->login_values, index);
|
||||
// (re)add to lists
|
||||
list_add_item(names, (tbus)g_strdup(name));
|
||||
list_add_item(values, (tbus)g_strdup(val));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* internal function return 1 if name is in list of channels
|
||||
* and if the value is allowed */
|
||||
int
|
||||
is_channel_enabled(char *inName, struct list *names, struct list *values)
|
||||
{
|
||||
int reply = 0; /*means not in the list*/
|
||||
int index;
|
||||
char *val;
|
||||
|
||||
index = find_name_in_lists(inName, names);
|
||||
if ( index >= 0 )
|
||||
{
|
||||
val = (char *)list_get_item(values, index);
|
||||
reply = g_text2bool(val);
|
||||
if (reply == 0)
|
||||
{
|
||||
log_message(LOG_LEVEL_INFO,"This channel is disabled: %s", inName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_LEVEL_INFO,"This channel is disabled (not in List): %s", inName);
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
/* internal function only used once per session
|
||||
* creates the list of allowed channels and store the information
|
||||
* in wm struct */
|
||||
void init_channel_allowed(struct xrdp_wm *wm)
|
||||
{
|
||||
int error;
|
||||
int i;
|
||||
char channelname[MAX_CHANNEL_NAME];
|
||||
int index = 0;
|
||||
int allowindex = 0;
|
||||
struct list *names;
|
||||
struct list *values;
|
||||
|
||||
/* first reset allowedchannels */
|
||||
for (i = 0; i < MAX_NR_CHANNELS; i++)
|
||||
{
|
||||
/* 0 is a valid channel so we use -1 to mark the index as unused */
|
||||
wm->allowedchannels[i] = -1;
|
||||
}
|
||||
|
||||
names = list_create();
|
||||
values = list_create();
|
||||
/* You can override the list of allowed channels individually for each
|
||||
* session type. */
|
||||
if ( read_allowed_channel_names(names, values)
|
||||
&& update_allowed_channel_names(wm, names, values) )
|
||||
{
|
||||
do
|
||||
{
|
||||
/* libxrdp_query_channel return 1 on error*/
|
||||
error = libxrdp_query_channel(wm->session, index, channelname, NULL);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
/* examples of channel names: rdpdr ; rdpsnd ; drdynvc ; cliprdr */
|
||||
if (is_channel_enabled(channelname, names, values))
|
||||
{
|
||||
log_message(LOG_LEVEL_INFO,"The following channel is allowed: %s (%d)", channelname, index);
|
||||
wm->allowedchannels[allowindex] = index;
|
||||
allowindex++;
|
||||
|
||||
if (allowindex >= MAX_NR_CHANNELS)
|
||||
{
|
||||
log_message(LOG_LEVEL_ALWAYS,"Programming error in is_channel_allowed");
|
||||
error = 1; /* end loop */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_LEVEL_INFO,"The following channel is not allowed: %s (%d)", channelname, index);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
while ((error == 0) && (index < MAX_NR_CHANNELS));
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message(LOG_LEVEL_ERROR,"Error reading channel section in inifile");
|
||||
}
|
||||
|
||||
list_delete(names);
|
||||
list_delete(values);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* This function returns 1 if the channelID is allowed by rule set
|
||||
* returns 0 if not allowed */
|
||||
int is_channel_allowed(struct xrdp_wm *wm, int channel_id)
|
||||
{
|
||||
int i;
|
||||
int reply = 0; /* not allowed */
|
||||
|
||||
/* The first time each client is using this function we have to
|
||||
* define the list of allowed channels */
|
||||
if (wm->allowedinitialized == 0)
|
||||
{
|
||||
init_channel_allowed(wm);
|
||||
log_message(LOG_LEVEL_DEBUG,"The allow channel list now initialized for this session");
|
||||
wm->allowedinitialized = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_NR_CHANNELS; i++)
|
||||
{
|
||||
if (channel_id == wm->allowedchannels[i])
|
||||
{
|
||||
/*g_writeln("Channel allowed: %d",channel_id);*/
|
||||
reply = 1; /*channel allowed*/
|
||||
break;
|
||||
}
|
||||
else if (wm->allowedchannels[i] == -1)
|
||||
{
|
||||
/* We are in the unused space of the allowedchannels list
|
||||
* We can end the loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*return 0 if the index is not found*/
|
||||
int
|
||||
@ -3235,25 +3317,18 @@ server_send_to_channel(struct xrdp_mod *mod, int channel_id,
|
||||
|
||||
wm = (struct xrdp_wm *)(mod->wm);
|
||||
|
||||
if (is_channel_allowed(wm, channel_id))
|
||||
if (wm->mm->usechansrv)
|
||||
{
|
||||
if (wm->mm->usechansrv)
|
||||
{
|
||||
/*
|
||||
* Xvnc backend reaches here
|
||||
* should not return 1 as this case is not an error
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Xvnc backend reaches here
|
||||
* should not return 1 as this case is not an error
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vnc proxy mode reaches here */
|
||||
return libxrdp_send_to_channel(wm->session, channel_id, data, data_len,
|
||||
total_data_len, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
/* vnc proxy mode reaches here */
|
||||
return libxrdp_send_to_channel(wm->session, channel_id, data, data_len,
|
||||
total_data_len, flags);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@ -295,6 +295,8 @@ struct xrdp_mm
|
||||
int delete_chan_trans; /* boolean set when done with channel connection */
|
||||
int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */
|
||||
struct xrdp_encoder *encoder;
|
||||
int cs2xr_cid_map[256];
|
||||
int xr2cr_cid_map[256];
|
||||
};
|
||||
|
||||
struct xrdp_key_info
|
||||
@ -376,8 +378,6 @@ struct xrdp_wm
|
||||
struct xrdp_bitmap* target_surface; /* either screen or os surface */
|
||||
int current_surface_index;
|
||||
int hints;
|
||||
int allowedchannels[MAX_NR_CHANNELS];
|
||||
int allowedinitialized ;
|
||||
char pamerrortxt[256];
|
||||
|
||||
/* configuration derived from xrdp.ini */
|
||||
|
||||
102
xrdp/xrdp_wm.c
102
xrdp/xrdp_wm.c
@ -27,6 +27,18 @@
|
||||
#include "xrdp.h"
|
||||
#include "log.h"
|
||||
|
||||
#define LLOG_LEVEL 1
|
||||
#define LLOGLN(_level, _args) \
|
||||
do \
|
||||
{ \
|
||||
if (_level < LLOG_LEVEL) \
|
||||
{ \
|
||||
g_write("xrdp:xrdp_wm [%10.10u]: ", g_time3()); \
|
||||
g_writeln _args ; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_wm *
|
||||
xrdp_wm_create(struct xrdp_process *owner,
|
||||
@ -563,6 +575,69 @@ xrdp_wm_init(struct xrdp_wm *self)
|
||||
|
||||
load_xrdp_config(self->xrdp_config, self->screen->bpp);
|
||||
|
||||
/* global channels allow */
|
||||
names = list_create();
|
||||
names->auto_free = 1;
|
||||
values = list_create();
|
||||
values->auto_free = 1;
|
||||
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
|
||||
if (file_by_name_read_section(cfg_file, "Channels", names, values) == 0)
|
||||
{
|
||||
int error;
|
||||
int ii;
|
||||
int chan_id;
|
||||
int chan_flags;
|
||||
int disabled;
|
||||
char chan_name[16];
|
||||
|
||||
ii = 0;
|
||||
error = libxrdp_query_channel(self->session, ii, chan_name,
|
||||
&chan_flags);
|
||||
while (error == 0)
|
||||
{
|
||||
r = NULL;
|
||||
for (index = 0; index < names->count; index++)
|
||||
{
|
||||
q = (char *) list_get_item(names, index);
|
||||
if (g_strcasecmp(q, chan_name) == 0)
|
||||
{
|
||||
r = (char *) list_get_item(values, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r == NULL)
|
||||
{
|
||||
/* not found, disable the channel */
|
||||
chan_id = libxrdp_get_channel_id(self->session, chan_name);
|
||||
libxrdp_disable_channel(self->session, chan_id, 1);
|
||||
g_writeln("xrdp_wm_init: channel %s channel id %d is "
|
||||
"disabled", chan_name, chan_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* found */
|
||||
chan_id = libxrdp_get_channel_id(self->session, q);
|
||||
disabled = !g_text2bool(r);
|
||||
libxrdp_disable_channel(self->session, chan_id, disabled);
|
||||
if (disabled)
|
||||
{
|
||||
g_writeln("xrdp_wm_init: channel %s channel id %d is "
|
||||
"disabled", chan_name, chan_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("xrdp_wm_init: channel %s channel id %d is "
|
||||
"allowed", chan_name, chan_id);
|
||||
}
|
||||
}
|
||||
ii++;
|
||||
error = libxrdp_query_channel(self->session, ii, chan_name,
|
||||
&chan_flags);
|
||||
}
|
||||
}
|
||||
list_delete(names);
|
||||
list_delete(values);
|
||||
|
||||
xrdp_wm_load_static_colors_plus(self, autorun_name);
|
||||
xrdp_wm_load_static_pointers(self);
|
||||
self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color;
|
||||
@ -1758,27 +1833,21 @@ xrdp_wm_process_channel_data(struct xrdp_wm *self,
|
||||
tbus param3, tbus param4)
|
||||
{
|
||||
int rv;
|
||||
int chanid ;
|
||||
rv = 1;
|
||||
|
||||
if (self->mm->mod != 0)
|
||||
{
|
||||
chanid = LOWORD(param1);
|
||||
|
||||
if (is_channel_allowed(self, chanid))
|
||||
if (self->mm->usechansrv)
|
||||
{
|
||||
if (self->mm->usechansrv)
|
||||
rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
|
||||
param3, param4);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->mm->mod->mod_event != 0)
|
||||
{
|
||||
rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
|
||||
param3, param4);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->mm->mod->mod_event != 0)
|
||||
{
|
||||
rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2,
|
||||
param3, param4);
|
||||
}
|
||||
rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2,
|
||||
param3, param4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1844,6 +1913,9 @@ callback(intptr_t id, int msg, intptr_t param1, intptr_t param2,
|
||||
//g_writeln("callback: frame ack %d", param1);
|
||||
xrdp_mm_frame_ack(wm->mm, param1);
|
||||
break;
|
||||
case 0x5558:
|
||||
xrdp_mm_drdynvc_up(wm->mm);
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -44,24 +44,21 @@
|
||||
|
||||
struct wts_obj
|
||||
{
|
||||
int fd;
|
||||
int status;
|
||||
char name[9];
|
||||
char dname[128];
|
||||
int display_num;
|
||||
uint32_t flags;
|
||||
int fd;
|
||||
int display_num;
|
||||
};
|
||||
|
||||
/* helper functions used by WTSxxx API - do not invoke directly */
|
||||
static int get_display_num_from_display(char *display_text);
|
||||
static int send_init(struct wts_obj *wts);
|
||||
static int can_send(int sck, int millis);
|
||||
static int can_recv(int sck, int millis);
|
||||
|
||||
static const unsigned char g_xrdpapi_magic[12] =
|
||||
{
|
||||
0x78, 0x32, 0x10, 0x67, 0x00, 0x92, 0x30, 0x56, 0xff, 0xd8, 0xa9, 0x1f
|
||||
};
|
||||
static int
|
||||
get_display_num_from_display(char *display_text);
|
||||
static int
|
||||
can_send(int sck, int millis);
|
||||
static int
|
||||
can_recv(int sck, int millis);
|
||||
static int
|
||||
mysend(int sck, const void* adata, int bytes);
|
||||
static int
|
||||
myrecv(int sck, void* adata, int bytes);
|
||||
|
||||
/*
|
||||
* Opens a handle to the server end of a specified virtual channel - this
|
||||
@ -100,22 +97,27 @@ void *
|
||||
WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct wts_obj *wts;
|
||||
char *display_text;
|
||||
int bytes;
|
||||
unsigned long llong;
|
||||
struct sockaddr_un s;
|
||||
struct wts_obj *wts;
|
||||
char *display_text;
|
||||
int bytes;
|
||||
unsigned long long1;
|
||||
struct sockaddr_un s;
|
||||
char *connect_data;
|
||||
int chan_name_bytes;
|
||||
int lerrno;
|
||||
|
||||
if (SessionId != WTS_CURRENT_SESSION)
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: bad SessionId"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
wts = (struct wts_obj *) calloc(1, sizeof(struct wts_obj));
|
||||
|
||||
if (wts == NULL)
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: calloc failed"));
|
||||
return 0;
|
||||
}
|
||||
wts->fd = -1;
|
||||
wts->flags = flags;
|
||||
display_text = getenv("DISPLAY");
|
||||
|
||||
if (display_text != 0)
|
||||
@ -133,16 +135,17 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName,
|
||||
/* we use unix domain socket to communicate with chansrv */
|
||||
if ((wts->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: socket failed"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set non blocking */
|
||||
llong = fcntl(wts->fd, F_GETFL);
|
||||
llong = llong | O_NONBLOCK;
|
||||
if (fcntl(wts->fd, F_SETFL, llong) < 0)
|
||||
long1 = fcntl(wts->fd, F_GETFL);
|
||||
long1 = long1 | O_NONBLOCK;
|
||||
if (fcntl(wts->fd, F_SETFL, long1) < 0)
|
||||
{
|
||||
LLOGLN(10, ("WTSVirtualChannelOpenEx: set non-block mode failed"));
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: set non-block mode failed"));
|
||||
}
|
||||
|
||||
/* connect to chansrv session */
|
||||
@ -153,17 +156,93 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName,
|
||||
s.sun_path[bytes - 1] = 0;
|
||||
bytes = sizeof(struct sockaddr_un);
|
||||
|
||||
if (connect(wts->fd, (struct sockaddr *) &s, bytes) == 0)
|
||||
if (connect(wts->fd, (struct sockaddr *) &s, bytes) < 0)
|
||||
{
|
||||
LLOGLN(10, ("WTSVirtualChannelOpenEx: connected ok, name %s", pVirtualName));
|
||||
strncpy(wts->name, pVirtualName, 8);
|
||||
|
||||
/* wait for connection to complete and send init */
|
||||
if (send_init(wts) == 0)
|
||||
lerrno = errno;
|
||||
if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) ||
|
||||
(lerrno == EINPROGRESS))
|
||||
{
|
||||
/* all ok */
|
||||
wts->status = 1;
|
||||
/* ok */
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: connect failed"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* wait for connection to complete */
|
||||
if (!can_send(wts->fd, 500))
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: can_send failed"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chan_name_bytes = strlen(pVirtualName);
|
||||
bytes = 4 + 4 + 4 + chan_name_bytes + 4;
|
||||
|
||||
LLOGLN(10, ("WTSVirtualChannelOpenEx: chan_name_bytes %d bytes %d pVirtualName %s", chan_name_bytes, bytes, pVirtualName));
|
||||
|
||||
connect_data = (char *) calloc(bytes, 1);
|
||||
if (connect_data == NULL)
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: calloc failed"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
connect_data[0] = (bytes >> 0) & 0xFF;
|
||||
connect_data[1] = (bytes >> 8) & 0xFF;
|
||||
connect_data[2] = (bytes >> 16) & 0xFF;
|
||||
connect_data[3] = (bytes >> 24) & 0xFF;
|
||||
|
||||
/* version here(4-7), just leave 0 */
|
||||
|
||||
connect_data[8] = (chan_name_bytes >> 0) & 0xFF;
|
||||
connect_data[9] = (chan_name_bytes >> 8) & 0xFF;
|
||||
connect_data[10] = (chan_name_bytes >> 16) & 0xFF;
|
||||
connect_data[11] = (chan_name_bytes >> 24) & 0xFF;
|
||||
|
||||
memcpy(connect_data + 12, pVirtualName, chan_name_bytes);
|
||||
|
||||
connect_data[4 + 4 + 4 + chan_name_bytes + 0] = (flags >> 0) & 0xFF;
|
||||
connect_data[4 + 4 + 4 + chan_name_bytes + 1] = (flags >> 8) & 0xFF;
|
||||
connect_data[4 + 4 + 4 + chan_name_bytes + 2] = (flags >> 16) & 0xFF;
|
||||
connect_data[4 + 4 + 4 + chan_name_bytes + 3] = (flags >> 24) & 0xFF;
|
||||
|
||||
LLOGLN(10, ("WTSVirtualChannelOpenEx: calling mysend with %d bytes", bytes));
|
||||
|
||||
if (mysend(wts->fd, connect_data, bytes) != bytes)
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: mysend failed"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
LLOGLN(10, ("WTSVirtualChannelOpenEx: sent ok"));
|
||||
|
||||
if (!can_recv(wts->fd, 500))
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: can_recv failed"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get response */
|
||||
if (myrecv(wts->fd, connect_data, 4) != 4)
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: myrecv failed"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((connect_data[0] != 0) || (connect_data[1] != 0) ||
|
||||
(connect_data[2] != 0) || (connect_data[3] != 0))
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelOpenEx: connect_data not ok"));
|
||||
free(wts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wts;
|
||||
@ -179,18 +258,18 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName,
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
mysend(int sck, const void* adata, int bytes)
|
||||
mysend(int sck, const void *adata, int bytes)
|
||||
{
|
||||
int sent;
|
||||
int error;
|
||||
const char* data;
|
||||
const char *data;
|
||||
|
||||
#if defined(SO_NOSIGPIPE)
|
||||
const int on = 1;
|
||||
setsockopt(sck, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
|
||||
#endif
|
||||
|
||||
data = (const char*)adata;
|
||||
data = (const char *) adata;
|
||||
sent = 0;
|
||||
while (sent < bytes)
|
||||
{
|
||||
@ -207,6 +286,36 @@ mysend(int sck, const void* adata, int bytes)
|
||||
return sent;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
myrecv(int sck, void *adata, int bytes)
|
||||
{
|
||||
int recd;
|
||||
int error;
|
||||
char *data;
|
||||
|
||||
#if defined(SO_NOSIGPIPE)
|
||||
const int on = 1;
|
||||
setsockopt(sck, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
|
||||
#endif
|
||||
|
||||
data = (char *) adata;
|
||||
recd = 0;
|
||||
while (recd < bytes)
|
||||
{
|
||||
if (can_recv(sck, 100))
|
||||
{
|
||||
error = recv(sck, data + recd, bytes - recd, MSG_NOSIGNAL);
|
||||
if (error < 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
recd += error;
|
||||
}
|
||||
}
|
||||
return recd;
|
||||
}
|
||||
|
||||
/*
|
||||
* write data to client connection
|
||||
*
|
||||
@ -217,8 +326,7 @@ WTSVirtualChannelWrite(void *hChannelHandle, const char *Buffer,
|
||||
unsigned int Length, unsigned int *pBytesWritten)
|
||||
{
|
||||
struct wts_obj *wts;
|
||||
int rv;
|
||||
int header[4];
|
||||
int rv;
|
||||
|
||||
wts = (struct wts_obj *) hChannelHandle;
|
||||
|
||||
@ -230,29 +338,12 @@ WTSVirtualChannelWrite(void *hChannelHandle, const char *Buffer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wts->status != 1)
|
||||
{
|
||||
LLOGLN(10, ("WTSVirtualChannelWrite: wts->status != 1"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!can_send(wts->fd, 0))
|
||||
{
|
||||
return 1; /* can't write now, ok to try again */
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
memcpy(header, g_xrdpapi_magic, 12);
|
||||
header[3] = Length;
|
||||
if (mysend(wts->fd, header, 16) == 16)
|
||||
{
|
||||
rv = mysend(wts->fd, Buffer, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("WTSVirtualChannelWrite: header write failed"));
|
||||
return 0;
|
||||
}
|
||||
rv = mysend(wts->fd, Buffer, Length);
|
||||
|
||||
LLOGLN(10, ("WTSVirtualChannelWrite: mysend() returned %d", rv));
|
||||
|
||||
@ -263,14 +354,6 @@ WTSVirtualChannelWrite(void *hChannelHandle, const char *Buffer,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0 /* coverity: this is dead code */
|
||||
/* error, but is it ok to try again? */
|
||||
if ((rv == EWOULDBLOCK) || (rv == EAGAIN) || (rv == EINPROGRESS))
|
||||
{
|
||||
return 0; /* failed to send, but should try again */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fatal error */
|
||||
return 0;
|
||||
}
|
||||
@ -296,11 +379,6 @@ WTSVirtualChannelRead(void *hChannelHandle, unsigned int TimeOut,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wts->status != 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (can_recv(wts->fd, TimeOut))
|
||||
{
|
||||
rv = recv(wts->fd, Buffer, BufferSize, 0);
|
||||
@ -341,7 +419,7 @@ WTSVirtualChannelClose(void *hChannelHandle)
|
||||
|
||||
wts = (struct wts_obj *)hChannelHandle;
|
||||
|
||||
if (wts == 0)
|
||||
if (wts == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -364,12 +442,7 @@ WTSVirtualChannelQuery(void *hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
|
||||
|
||||
wts = (struct wts_obj *)hChannelHandle;
|
||||
|
||||
if (wts == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wts->status != 1)
|
||||
if (wts == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -378,6 +451,10 @@ WTSVirtualChannelQuery(void *hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
|
||||
{
|
||||
*pBytesReturned = 4;
|
||||
*ppBuffer = malloc(4);
|
||||
if (*ppBuffer == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(*ppBuffer, &(wts->fd), 4);
|
||||
}
|
||||
|
||||
@ -388,7 +465,7 @@ WTSVirtualChannelQuery(void *hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
|
||||
void
|
||||
WTSFreeMemory(void *pMemory)
|
||||
{
|
||||
if (pMemory != 0)
|
||||
if (pMemory != NULL)
|
||||
{
|
||||
free(pMemory);
|
||||
}
|
||||
@ -452,39 +529,6 @@ can_recv(int sck, int millis)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
send_init(struct wts_obj *wts)
|
||||
{
|
||||
char initmsg[64];
|
||||
|
||||
memset(initmsg, 0, 64);
|
||||
|
||||
/* insert channel name */
|
||||
strncpy(initmsg, wts->name, 8);
|
||||
|
||||
/* insert open mode flags */
|
||||
initmsg[16] = (wts->flags >> 0) & 0xff;
|
||||
initmsg[17] = (wts->flags >> 8) & 0xff;
|
||||
initmsg[18] = (wts->flags >> 16) & 0xff;
|
||||
initmsg[19] = (wts->flags >> 24) & 0xff;
|
||||
|
||||
if (!can_send(wts->fd, 500))
|
||||
{
|
||||
LLOGLN(10, ("send_init: send() will block!"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (send(wts->fd, initmsg, 64, 0) != 64)
|
||||
{
|
||||
LLOGLN(10, ("send_init: send() failed!"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
LLOGLN(10, ("send_init: sent ok!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
get_display_num_from_display(char *display_text)
|
||||
@ -513,7 +557,6 @@ get_display_num_from_display(char *display_text)
|
||||
disp[disp_index] = display_text[index];
|
||||
disp_index++;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user