From b9efd2ce2b9ac557ec300ae3836bbea9ce3f931c Mon Sep 17 00:00:00 2001 From: Nexarian Date: Sat, 16 Dec 2023 12:49:56 -0500 Subject: [PATCH 1/4] Initial rfx progressive integration - Mostly base functions and utilities necessary to enable RFX Progressive - Add more EGFX work & mode flags. - Update encoder. - Does not yet include caps determination to enable RFX progressive (yet). - Update protocol constants --- common/Makefile.am | 2 +- common/ms-rdpbcgr.h | 32 +++++++++----- common/xrdp_client_info.h | 8 ++++ common/xrdp_constants.h | 46 +++++++++++++++++++++ libxrdp/xrdp_sec.c | 25 ++++++++--- xrdp/xrdp_encoder.c | 87 ++++++++++++++++++++++++++++++--------- xrdp/xrdp_encoder.h | 9 ++++ xrdp/xrdp_mm.c | 8 +++- xrdp/xrdp_painter.c | 71 ++++++++++++++++++++------------ xrdp/xrdp_types.h | 10 ++++- xrdp/xrdp_wm.c | 17 ++++++-- 11 files changed, 245 insertions(+), 70 deletions(-) diff --git a/common/Makefile.am b/common/Makefile.am index 141addc8f6..baed9f0d54 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -71,6 +71,6 @@ libcommon_la_SOURCES = \ $(PIXMAN_SOURCES) libcommon_la_LIBADD = \ - -lpthread \ + -lpthread -lrt \ $(OPENSSL_LIBS) \ $(DLOPEN_LIBS) diff --git a/common/ms-rdpbcgr.h b/common/ms-rdpbcgr.h index 517b777ce8..6e39053543 100644 --- a/common/ms-rdpbcgr.h +++ b/common/ms-rdpbcgr.h @@ -52,19 +52,29 @@ /* TS_UD_HEADER: type ((2.2.1.3.1) */ /* TODO: to be renamed */ -#define SEC_TAG_CLI_INFO 0xc001 /* CS_CORE? */ -#define SEC_TAG_CLI_CRYPT 0xc002 /* CS_SECURITY? */ -#define SEC_TAG_CLI_CHANNELS 0xc003 /* CS_CHANNELS? */ -#define SEC_TAG_CLI_4 0xc004 /* CS_CLUSTER? */ -#define SEC_TAG_CLI_MONITOR 0xc005 /* CS_MONITOR */ -#define SEC_TAG_CLI_MONITOR_EX 0xc008 /* CS_MONITOR_EX */ +#define SEC_TAG_CLI_INFO 0xc001 /* CS_CORE? */ +#define SEC_TAG_CLI_CRYPT 0xc002 /* CS_SECURITY? */ +#define SEC_TAG_CLI_CHANNELS 0xc003 /* CS_CHANNELS? */ +#define SEC_TAG_CLI_4 0xc004 /* CS_CLUSTER? */ +#define SEC_TAG_CLI_MONITOR 0xc005 /* CS_MONITOR */ +#define SEC_TAG_CLI_MONITOR_EX 0xc008 /* CS_MONITOR_EX */ /* Client Core Data: colorDepth, postBeta2ColorDepth (2.2.1.3.2) */ -#define RNS_UD_COLOR_4BPP 0xCA00 -#define RNS_UD_COLOR_8BPP 0xCA01 -#define RNS_UD_COLOR_16BPP_555 0xCA02 -#define RNS_UD_COLOR_16BPP_565 0xCA03 -#define RNS_UD_COLOR_24BPP 0xCA04 +#define RNS_UD_COLOR_4BPP 0xCA00 +#define RNS_UD_COLOR_8BPP 0xCA01 +#define RNS_UD_COLOR_16BPP_555 0xCA02 +#define RNS_UD_COLOR_16BPP_565 0xCA03 +#define RNS_UD_COLOR_24BPP 0xCA04 + +/* Client Core Data: supportedColorDepths (2.2.1.3.2) */ +#define RNS_UD_24BPP_SUPPORT 0x0001 +#define RNS_UD_16BPP_SUPPORT 0x0002 +#define RNS_UD_15BPP_SUPPORT 0x0004 +#define RNS_UD_32BPP_SUPPORT 0x0008 + +/* Client Core Data: earlyCapabilityFlags (2.2.1.3.2) */ +#define RNS_UD_CS_WANT_32BPP_SESSION 0x0002 +#define RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL 0x0100 /* Client Core Data: connectionType (2.2.1.3.2) */ #define CONNECTION_TYPE_MODEM 0x01 diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index f2d91ad77b..a588f16c56 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -215,6 +215,14 @@ struct xrdp_client_info unsigned int session_physical_height; /* in mm */ int large_pointer_support_flags; + int gfx; +}; + +enum xrdp_encoder_flags +{ + NONE = 0, + ENCODE_COMPLETE = 1 << 0, + GFX_PROGRESSIVE_RFX = 1 << 1 }; /* yyyymmdd of last incompatible change to xrdp_client_info */ diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index 231d494ab9..9ab9d17901 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -291,4 +291,50 @@ #define XR_RDP_SCAN_LSHIFT 42 #define XR_RDP_SCAN_ALT 56 +// Since we're not guaranteed to have pixman, copy these directives. +#define XRDP_PIXMAN_TYPE_ARGB 2 +#define XRDP_PIXMAN_TYPE_ABGR 3 +#define XRDP_PIXMAN_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \ + ((type) << 16) | \ + ((a) << 12) | \ + ((r) << 8) | \ + ((g) << 4) | \ + ((b))) + +#define XRDP_a8b8g8r8 \ + XRDP_PIXMAN_FORMAT(32, XRDP_PIXMAN_TYPE_ABGR, 8, 8, 8, 8) + +#define XRDP_a8r8g8b8 \ + XRDP_PIXMAN_FORMAT(32, XRDP_PIXMAN_TYPE_ARGB, 8, 8, 8, 8) + +#define XRDP_r5g6b5 \ + XRDP_PIXMAN_FORMAT(16, XRDP_PIXMAN_TYPE_ARGB, 0, 5, 6, 5) + +#define XRDP_a1r5g5b5 \ + XRDP_PIXMAN_FORMAT(16, XRDP_PIXMAN_TYPE_ARGB, 1, 5, 5, 5) + +#define XRDP_r3g3b2 \ + XRDP_PIXMAN_FORMAT(8, XRDP_PIXMAN_TYPE_ARGB, 0, 3, 3, 2) + +// The last used constant in pixman is 63, so use 64+ +#define XRDP_nv12 \ + XRDP_PIXMAN_FORMAT(12, 64, 0, 0, 0, 0) + +#define XRDP_i420 \ + XRDP_PIXMAN_FORMAT(12, 65, 0, 0, 0, 0) + +#define XRDP_nv12_709fr \ + XRDP_PIXMAN_FORMAT(12, 66, 0, 0, 0, 0) + +#define XRDP_yuv444_709fr \ + XRDP_PIXMAN_FORMAT(32, 67, 0, 0, 0, 0) + +// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegfx/8131c1bc-1af8-4907-a05a-f72f4581160f +#define XRDP_yuv444_v1_stream_709fr \ + XRDP_PIXMAN_FORMAT(32, 68, 0, 0, 0, 0) + +// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegfx/781406c3-5e24-4f2b-b6ff-42b76bf64f6d +#define XRDP_yuv444_v2_stream_709fr \ + XRDP_PIXMAN_FORMAT(32, 69, 0, 0, 0, 0) + #endif diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 20665dfc4f..6c2057aeb1 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -2114,10 +2114,14 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) in_uint16_le(s, supportedColorDepths); LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " " supportedColorDepths %s", - supportedColorDepths == 0x0001 ? "RNS_UD_24BPP_SUPPORT" : - supportedColorDepths == 0x0002 ? "RNS_UD_16BPP_SUPPORT" : - supportedColorDepths == 0x0004 ? "RNS_UD_15BPP_SUPPORT" : - supportedColorDepths == 0x0008 ? "RNS_UD_32BPP_SUPPORT" : + supportedColorDepths == RNS_UD_24BPP_SUPPORT + ? "RNS_UD_24BPP_SUPPORT" : + supportedColorDepths == RNS_UD_16BPP_SUPPORT + ? "RNS_UD_16BPP_SUPPORT" : + supportedColorDepths == RNS_UD_15BPP_SUPPORT + ? "RNS_UD_15BPP_SUPPORT" : + supportedColorDepths == RNS_UD_32BPP_SUPPORT + ? "RNS_UD_32BPP_SUPPORT" : "unknown"); if (!s_check_rem(s, 2)) @@ -2129,11 +2133,20 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " " earlyCapabilityFlags 0x%4.4x", earlyCapabilityFlags); - if ((earlyCapabilityFlags & 0x0002) && (supportedColorDepths & 0x0008)) + if ((earlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION) + && (supportedColorDepths & RNS_UD_32BPP_SUPPORT)) { client_info->bpp = 32; } - + if (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) + { + LOG(LOG_LEVEL_INFO, "client supports gfx protocol"); + self->rdp_layer->client_info.gfx = 1; + } + else + { + LOG_DEVEL(LOG_LEVEL_INFO, "client DOES NOT support gfx"); + } if (!s_check_rem(s, 64)) { return 0; diff --git a/xrdp/xrdp_encoder.c b/xrdp/xrdp_encoder.c index 03203cd791..8c3d9d0b17 100644 --- a/xrdp/xrdp_encoder.c +++ b/xrdp/xrdp_encoder.c @@ -32,10 +32,17 @@ #include "rfxcodec_encode.h" #endif - - #define XRDP_SURCMD_PREFIX_BYTES 256 +#ifdef XRDP_RFXCODEC +/* LH3 LL3, HH3 HL3, HL2 LH2, LH1 HH2, HH1 HL1 todo check this */ +static const unsigned char g_rfx_quantization_values[] = +{ + 0x66, 0x66, 0x77, 0x88, 0x98, + 0x76, 0x77, 0x88, 0x98, 0xA9 +}; +#endif + /*****************************************************************************/ static int process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc); @@ -77,16 +84,24 @@ xrdp_encoder_create(struct xrdp_mm *mm) client_info = mm->wm->client_info; + /* RemoteFX 7.1 requires LAN but GFX does not */ if (client_info->mcs_connection_type != CONNECTION_TYPE_LAN) { - return 0; + if ((mm->egfx_flags & (XRDP_EGFX_H264 | XRDP_EGFX_RFX_PRO)) == 0) + { + return 0; + } } if (client_info->bpp < 24) { return 0; } - self = (struct xrdp_encoder *)g_malloc(sizeof(struct xrdp_encoder), 1); + self = g_new0(struct xrdp_encoder, 1); + if (self == NULL) + { + return NULL; + } self->mm = mm; if (client_info->jpeg_codec_id != 0) @@ -96,12 +111,29 @@ xrdp_encoder_create(struct xrdp_mm *mm) self->in_codec_mode = 1; self->codec_quality = client_info->jpeg_prop[0]; client_info->capture_code = 0; - client_info->capture_format = - /* XRDP_a8b8g8r8 */ - (32 << 24) | (3 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8; + client_info->capture_format = XRDP_a8b8g8r8; self->process_enc = process_enc_jpg; } #ifdef XRDP_RFXCODEC + else if (mm->egfx_flags & XRDP_EGFX_RFX_PRO) + { + LOG(LOG_LEVEL_INFO, + "xrdp_encoder_create: starting gfx rfx pro codec session"); + self->in_codec_mode = 1; + client_info->capture_code = 2; + self->process_enc = process_enc_rfx; + self->gfx = 1; + self->quants = (const char *) g_rfx_quantization_values; + self->num_quants = 2; + self->quant_idx_y = 0; + self->quant_idx_u = 1; + self->quant_idx_v = 1; + self->codec_handle = rfxcodec_encode_create( + mm->wm->screen->width, + mm->wm->screen->height, + RFX_FORMAT_YUV, + RFX_FLAGS_RLGR1 | RFX_FLAGS_PRO1); + } else if (client_info->rfx_codec_id != 0) { LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting rfx codec session"); @@ -120,9 +152,7 @@ xrdp_encoder_create(struct xrdp_mm *mm) self->codec_id = client_info->h264_codec_id; self->in_codec_mode = 1; client_info->capture_code = 3; - client_info->capture_format = - /* XRDP_nv12 */ - (12 << 24) | (64 << 16) | (0 << 12) | (0 << 8) | (0 << 4) | 0; + client_info->capture_format = XRDP_nv12; self->process_enc = process_enc_h264; } else @@ -131,7 +161,9 @@ xrdp_encoder_create(struct xrdp_mm *mm) return 0; } - LOG_DEVEL(LOG_LEVEL_INFO, "init_xrdp_encoder: initializing encoder codec_id %d", self->codec_id); + LOG_DEVEL(LOG_LEVEL_INFO, + "init_xrdp_encoder: initializing encoder codec_id %d", + self->codec_id); /* setup required FIFOs */ self->fifo_to_proc = fifo_create(xrdp_enc_data_destructor); @@ -146,8 +178,17 @@ xrdp_encoder_create(struct xrdp_mm *mm) self->xrdp_encoder_event_processed = g_create_wait_obj(buf); g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_term", pid); self->xrdp_encoder_term = g_create_wait_obj(buf); - self->max_compressed_bytes = client_info->max_fastpath_frag_bytes & ~15; - self->frames_in_flight = client_info->max_unacknowledged_frame_count; + if (client_info->gfx) + { + // Magic numbers... Why? + self->frames_in_flight = 2; + self->max_compressed_bytes = 3145728; + } + else + { + self->frames_in_flight = client_info->max_unacknowledged_frame_count; + self->max_compressed_bytes = client_info->max_fastpath_frag_bytes & ~15; + } /* make sure frames_in_flight is at least 1 */ self->frames_in_flight = MAX(self->frames_in_flight, 1); @@ -354,9 +395,9 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) tiles[index].y = y; tiles[index].cx = cx; tiles[index].cy = cy; - tiles[index].quant_y = 0; - tiles[index].quant_cb = 0; - tiles[index].quant_cr = 0; + tiles[index].quant_y = self->quant_idx_y; + tiles[index].quant_cb = self->quant_idx_u; + tiles[index].quant_cr = self->quant_idx_v; } count = enc->num_drects; @@ -376,9 +417,11 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) tiles_written = rfxcodec_encode(self->codec_handle, out_data + XRDP_SURCMD_PREFIX_BYTES, &out_data_bytes, enc->data, - enc->width, enc->height, enc->width * 4, + enc->width, enc->height, + enc->width * 4, rfxrects, enc->num_drects, - tiles, tiles_left, 0, 0); + tiles, enc->num_crects, + self->quants, self->num_quants); } } @@ -399,7 +442,11 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) enc_done->enc = enc; enc_done->cx = self->mm->wm->screen->width; enc_done->cy = self->mm->wm->screen->height; - + if (self->gfx) + { + enc_done->flags = (enum xrdp_encoder_flags) + ((int)enc_done->flags | GFX_PROGRESSIVE_RFX); + } enc_done->continuation = all_tiles_written > 0; if (tiles_written > 0) { @@ -429,7 +476,7 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) static int process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) { - LOG_DEVEL(LOG_LEVEL_INFO, "process_enc_x264:"); + LOG_DEVEL(LOG_LEVEL_INFO, "process_enc_h264: dummy func"); return 0; } diff --git a/xrdp/xrdp_encoder.h b/xrdp/xrdp_encoder.h index 59bebaa865..a5c32a58a2 100644 --- a/xrdp/xrdp_encoder.h +++ b/xrdp/xrdp_encoder.h @@ -3,6 +3,7 @@ #define _XRDP_ENCODER_H #include "arch.h" +#include "xrdp_client_info.h" struct fifo; struct xrdp_enc_data; @@ -27,6 +28,13 @@ struct xrdp_encoder int frame_id_server; /* last frame id received from Xorg */ int frame_id_server_sent; int frames_in_flight; + int gfx; + int gfx_ack_off; + const char *quants; + int num_quants; + int quant_idx_y; + int quant_idx_u; + int quant_idx_v; }; /* used when scheduling tasks in xrdp_encoder.c */ @@ -63,6 +71,7 @@ struct xrdp_enc_data_done int y; int cx; int cy; + enum xrdp_encoder_flags flags; }; typedef struct xrdp_enc_data_done XRDP_ENC_DATA_DONE; diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index ccade62ae7..8769a61d97 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -79,7 +79,13 @@ xrdp_mm_create(struct xrdp_wm *owner) self->wm->client_info->rfx_codec_id, self->wm->client_info->h264_codec_id); - self->encoder = xrdp_encoder_create(self); + if ((self->wm->client_info->gfx == 0) && + ((self->wm->client_info->h264_codec_id != 0) || + (self->wm->client_info->jpeg_codec_id != 0) || + (self->wm->client_info->rfx_codec_id != 0))) + { + self->encoder = xrdp_encoder_create(self); + } return self; } diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c index 50ab371af6..fce0d3780d 100644 --- a/xrdp/xrdp_painter.c +++ b/xrdp/xrdp_painter.c @@ -93,35 +93,54 @@ xrdp_painter_send_dirty(struct xrdp_painter *self) Bpp = 4; } - jndex = 0; - error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); - while (error == 0) - { - cx = rect.right - rect.left; - cy = rect.bottom - rect.top; - ldata = (char *)g_malloc(cx * cy * Bpp, 0); - if (ldata == 0) + if (self->session->client_info->gfx) + { + if (self->wm->screen_dirty_region == NULL) { - return 1; + self->wm->screen_dirty_region = xrdp_region_create(self->wm); } - src = self->wm->screen->data; - src += self->wm->screen->line_size * rect.top; - src += rect.left * Bpp; - dst = ldata; - for (index = 0; index < cy; index++) + jndex = 0; + error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); + while (error == 0) { - g_memcpy(dst, src, cx * Bpp); - src += self->wm->screen->line_size; - dst += cx * Bpp; + xrdp_region_add_rect(self->wm->screen_dirty_region, &rect); + jndex++; + error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); } - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_send_dirty: x %d y %d cx %d cy %d", - rect.left, rect.top, cx, cy); - libxrdp_send_bitmap(self->session, cx, cy, bpp, - ldata, rect.left, rect.top, cx, cy); - g_free(ldata); - - jndex++; + } + else + { + jndex = 0; error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); + while (error == 0) + { + cx = rect.right - rect.left; + cy = rect.bottom - rect.top; + ldata = (char *)g_malloc(cx * cy * Bpp, 0); + if (ldata == 0) + { + return 1; + } + src = self->wm->screen->data; + src += self->wm->screen->line_size * rect.top; + src += rect.left * Bpp; + dst = ldata; + for (index = 0; index < cy; index++) + { + g_memcpy(dst, src, cx * Bpp); + src += self->wm->screen->line_size; + dst += cx * Bpp; + } + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_send_dirty:" + " x %d y %d cx %d cy %d", + rect.left, rect.top, cx, cy); + libxrdp_send_bitmap(self->session, cx, cy, bpp, + ldata, rect.left, rect.top, cx, cy); + g_free(ldata); + + jndex++; + error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); + } } xrdp_region_delete(self->dirty_region); @@ -145,8 +164,8 @@ xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session) self->rop = 0xcc; /* copy will use 0xcc */ self->clip_children = 1; - - if (self->session->client_info->no_orders_supported) + if (self->session->client_info->no_orders_supported || + self->session->client_info->gfx) { #if defined(XRDP_PAINTER) if (painter_create(&(self->painter)) != PT_ERROR_NONE) diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 5f8a730027..d0bce05706 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -374,6 +374,13 @@ enum display_resize_state "unknown" \ ) +enum xrdp_egfx_flags +{ + XRDP_EGFX_NONE = 0, + XRDP_EGFX_H264 = 1, + XRDP_EGFX_RFX_PRO = 2 +}; + struct xrdp_mm { struct xrdp_wm *wm; /* owner */ @@ -410,7 +417,8 @@ struct xrdp_mm int dynamic_monitor_chanid; struct xrdp_egfx *egfx; int egfx_up; - + int egfx_flags; + int gfx_delay_autologin; /* Resize on-the-fly control */ struct display_control_monitor_layout_data *resize_data; struct list *resize_queue; diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 8a34b03393..8d0a48c317 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -767,10 +767,19 @@ xrdp_wm_init(struct xrdp_wm *self) list_add_strdup(self->mm->login_values, r); } - /* - * Skip the login box and go straight to the connection phase - */ - xrdp_wm_set_login_state(self, WMLS_START_CONNECT); + if (self->session->client_info->gfx && !self->mm->egfx_up) + { + /* gfx session but have not recieved caps advertise yet, + set flag so we will connect to backend later */ + self->mm->gfx_delay_autologin = 1; + } + else + { + /* + * Skip the login box and go straight to the connection phase + */ + xrdp_wm_set_login_state(self, WMLS_START_CONNECT); + } } else { From cef74f2c6f6f235f091fb09c3dab067dc558c59d Mon Sep 17 00:00:00 2001 From: Nexarian Date: Sun, 24 Dec 2023 15:35:28 -0500 Subject: [PATCH 2/4] More integration work from mainline_merge_shm - Introduce functional EGFX caps. - Prototype of RFX Progressive working. - Update resizing to work with it. - Refactoring --- common/xrdp_client_info.h | 3 +- xrdp/xrdp.h | 3 +- xrdp/xrdp_encoder.c | 32 +- xrdp/xrdp_mm.c | 635 ++++++++++++++++++++++++++++++++------ xrdp/xrdp_types.h | 14 +- xup/xup.c | 171 +++++----- 6 files changed, 658 insertions(+), 200 deletions(-) diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index a588f16c56..ad5012bb77 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -222,7 +222,8 @@ enum xrdp_encoder_flags { NONE = 0, ENCODE_COMPLETE = 1 << 0, - GFX_PROGRESSIVE_RFX = 1 << 1 + GFX_PROGRESSIVE_RFX = 1 << 1, + GFX_H264 = 1 << 2 }; /* yyyymmdd of last incompatible change to xrdp_client_info */ diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 0db9f35bf9..ba281fa002 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -543,7 +543,8 @@ server_set_pointer_large(struct xrdp_mod *mod, int x, int y, char *data, char *mask, int bpp, int width, int height); int -server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects, +server_paint_rects_ex(struct xrdp_mod *mod, + int num_drects, short *drects, int num_crects, short *crects, char *data, int left, int top, int width, int height, diff --git a/xrdp/xrdp_encoder.c b/xrdp/xrdp_encoder.c index 8c3d9d0b17..f7a08674b5 100644 --- a/xrdp/xrdp_encoder.c +++ b/xrdp/xrdp_encoder.c @@ -33,6 +33,7 @@ #endif #define XRDP_SURCMD_PREFIX_BYTES 256 +#define OUT_DATA_BYTES_DEFAULT_SIZE (16 * 1024 * 1024) #ifdef XRDP_RFXCODEC /* LH3 LL3, HH3 HL3, HL2 LH2, LH1 HH2, HH1 HL1 todo check this */ @@ -77,6 +78,8 @@ xrdp_enc_data_done_destructor(void *item, void *closure) struct xrdp_encoder * xrdp_encoder_create(struct xrdp_mm *mm) { + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_encoder_create:"); + struct xrdp_encoder *self; struct xrdp_client_info *client_info; char buf[1024]; @@ -106,7 +109,8 @@ xrdp_encoder_create(struct xrdp_mm *mm) if (client_info->jpeg_codec_id != 0) { - LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting jpeg codec session"); + LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: " + "starting jpeg codec session"); self->codec_id = client_info->jpeg_codec_id; self->in_codec_mode = 1; self->codec_quality = client_info->jpeg_prop[0]; @@ -136,7 +140,8 @@ xrdp_encoder_create(struct xrdp_mm *mm) } else if (client_info->rfx_codec_id != 0) { - LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting rfx codec session"); + LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: " + "starting rfx codec session"); self->codec_id = client_info->rfx_codec_id; self->in_codec_mode = 1; client_info->capture_code = 2; @@ -148,7 +153,8 @@ xrdp_encoder_create(struct xrdp_mm *mm) #endif else if (client_info->h264_codec_id != 0) { - LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting h264 codec session"); + LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: " + "starting h264 codec session"); self->codec_id = client_info->h264_codec_id; self->in_codec_mode = 1; client_info->capture_code = 3; @@ -277,15 +283,18 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) continue; } - LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_jpg: x %d y %d cx %d cy %d", x, y, cx, cy); + LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_jpg: x %d y %d cx %d cy %d", + x, y, cx, cy); out_data_bytes = MAX((cx + 4) * cy * 4, 8192); - if ((out_data_bytes < 1) || (out_data_bytes > 16 * 1024 * 1024)) + if ((out_data_bytes < 1) + || (out_data_bytes > OUT_DATA_BYTES_DEFAULT_SIZE)) { LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 2"); return 1; } - out_data = (char *) g_malloc(out_data_bytes + 256 + 2, 0); + out_data = (char *) g_malloc(out_data_bytes + + XRDP_SURCMD_PREFIX_BYTES + 2, 0); if (out_data == 0) { LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 3"); @@ -298,15 +307,18 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) enc->width, enc->height, enc->width * 4, x, y, cx, cy, quality, - out_data + 256 + 2, &out_data_bytes); + out_data + + XRDP_SURCMD_PREFIX_BYTES + 2, + &out_data_bytes); if (error < 0) { - LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: jpeg error %d bytes %d", - error, out_data_bytes); + LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: jpeg error %d " + "bytes %d", error, out_data_bytes); g_free(out_data); return 1; } - LOG_DEVEL(LOG_LEVEL_WARNING, "jpeg error %d bytes %d", error, out_data_bytes); + LOG_DEVEL(LOG_LEVEL_WARNING, + "jpeg error %d bytes %d", error, out_data_bytes); enc_done = (XRDP_ENC_DATA_DONE *) g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1); enc_done->comp_bytes = out_data_bytes + 2; diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 8769a61d97..78a8d95c5d 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -27,17 +27,15 @@ #include "guid.h" #include "ms-rdpedisp.h" #include "ms-rdpbcgr.h" - #include "scp.h" - #include - #include "xrdp_encoder.h" #include "xrdp_sockets.h" #include "xrdp_egfx.h" +#include "libxrdp.h" +#include "xrdp_channel.h" #include - /* Forward declarations */ static int xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port); @@ -49,8 +47,6 @@ struct xrdp_mm * xrdp_mm_create(struct xrdp_wm *owner) { struct xrdp_mm *self; - char buf[1024]; - int pid; self = (struct xrdp_mm *)g_malloc(sizeof(struct xrdp_mm), 1); self->wm = owner; @@ -58,17 +54,9 @@ xrdp_mm_create(struct xrdp_wm *owner) self->login_names->auto_free = 1; self->login_values = list_create(); self->login_values->auto_free = 1; - self->resize_queue = list_create(); - self->resize_queue->auto_free = 1; self->uid = -1; /* Never good to default UIDs to 0 */ - pid = g_getpid(); - /* setup wait objects for signalling */ - g_snprintf(buf, sizeof(buf), "xrdp_%8.8x_resize_ready", pid); - self->resize_ready = g_create_wait_obj(buf); - self->resize_data = NULL; - LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_create: bpp %d mcs_connection_type %d " "jpeg_codec_id %d v3_codec_id %d rfx_codec_id %d " "h264_codec_id %d", @@ -170,6 +158,7 @@ xrdp_mm_delete(struct xrdp_mm *self) list_delete(self->resize_queue); g_free(self->resize_data); g_delete_wait_obj(self->resize_ready); + xrdp_egfx_shutdown_full(self->egfx); g_free(self); } @@ -1090,6 +1079,30 @@ xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self, return 0; } +/******************************************************************************/ +static int +xrdp_mm_egfx_invalidate_all(struct xrdp_mm *self) +{ + struct xrdp_rect xr_rect; + struct xrdp_bitmap *screen; + int error; + + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_invalidate_all:"); + + screen = self->wm->screen; + + xr_rect.left = 0; + xr_rect.top = 0; + xr_rect.right = screen->width; + xr_rect.bottom = screen->height; + if (self->wm->screen_dirty_region == NULL) + { + self->wm->screen_dirty_region = xrdp_region_create(self->wm); + } + error = xrdp_region_add_rect(self->wm->screen_dirty_region, &xr_rect); + return error; +} + /******************************************************************************/ static int dynamic_monitor_open_response(intptr_t id, int chan_id, int creation_status) @@ -1139,6 +1152,265 @@ dynamic_monitor_data_first(intptr_t id, int chan_id, char *data, int bytes, return 0; } +/******************************************************************************/ +int +advance_resize_state_machine(struct xrdp_mm *mm, + enum display_resize_state new_state) +{ + struct display_control_monitor_layout_data *description = mm->resize_data; + LOG_DEVEL(LOG_LEVEL_INFO, + "advance_resize_state_machine:" + " Processing resize to: %d x %d." + " Advancing state from %s to %s." + " Previous state took %d MS.", + description->description.session_width, + description->description.session_height, + XRDP_DISPLAY_RESIZE_STATE_TO_STR(description->state), + XRDP_DISPLAY_RESIZE_STATE_TO_STR(new_state), + g_time3() - description->last_state_update_timestamp); + description->state = new_state; + description->last_state_update_timestamp = g_time3(); + g_set_wait_obj(mm->resize_ready); + return 0; +} + +/******************************************************************************/ +static int +xrdp_mm_egfx_caps_advertise(void *user, int caps_count, + int *versions, int *flagss) +{ + struct xrdp_mm *self; + struct xrdp_bitmap *screen; + int index; + int best_index; + int best_h264_index; + int best_pro_index; + int error; + int version; + int flags; + + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise:"); + self = (struct xrdp_mm *) user; + screen = self->wm->screen; + if (screen->data == NULL) + { + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: can not do gfx"); + } + best_index = -1; + best_h264_index = -1; + best_pro_index = -1; + for (index = 0; index < caps_count; index++) + { + version = versions[index]; + flags = flagss[index]; + LOG(LOG_LEVEL_INFO, " version 0x%8.8x flags 0x%8.8x (index: %d)", + version, flags, index); + switch (version) + { + case XR_RDPGFX_CAPVERSION_8: + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_81: + if (flags & XR_RDPGFX_CAPS_FLAG_AVC420_ENABLED) + { + best_h264_index = index; + } + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_10: + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_101: + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_102: + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_103: + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_104: + if (!(flags & XR_RDPGFX_CAPS_FLAG_AVC_DISABLED)) + { + best_h264_index = index; + } + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_105: + best_pro_index = index; + break; + case XR_RDPGFX_CAPVERSION_106: + best_pro_index = index; + break; + } + } + if (best_pro_index >= 0) + { + best_index = best_pro_index; + self->egfx_flags = XRDP_EGFX_RFX_PRO; + } + /* prefer h264, todo use setting in xrdp.ini for this */ + if (best_h264_index >= 0) + { +#if defined(XRDP_X264) || defined(XRDP_NVENC) + best_index = best_h264_index; + self->egfx_flags = XRDP_EGFX_H264; +#endif + } + if (best_index >= 0) + { + LOG(LOG_LEVEL_INFO, " replying version 0x%8.8x flags 0x%8.8x", + versions[best_index], flagss[best_index]); + error = xrdp_egfx_send_capsconfirm(self->egfx, + versions[best_index], + flagss[best_index]); + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: xrdp_egfx_send_capsconfirm " + "error %d best_index %d", error, best_index); + error = xrdp_egfx_send_reset_graphics(self->egfx, + screen->width, screen->height, + self->wm->client_info->display_sizes.monitorCount, + self->wm->client_info->display_sizes.minfo_wm); + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: xrdp_egfx_send_reset_graphics " + "error %d monitorCount %d", + error, self->wm->client_info->display_sizes.monitorCount); + self->egfx_up = 1; + xrdp_egfx_send_create_surface(self->egfx, self->egfx->surface_id, + screen->width, screen->height, + XR_PIXEL_FORMAT_XRGB_8888); + xrdp_egfx_send_map_surface(self->egfx, self->egfx->surface_id, 0, 0); + self->encoder = xrdp_encoder_create(self); + xrdp_mm_egfx_invalidate_all(self); + + if (self->resize_data != NULL + && self->resize_data->state == WMRZ_EGFX_INITALIZING) + { + advance_resize_state_machine(self, WMRZ_EGFX_INITIALIZED); + } + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: egfx created."); + if (self->gfx_delay_autologin) + { + self->gfx_delay_autologin = 0; + xrdp_wm_set_login_state(self->wm, WMLS_START_CONNECT); + } + } + else + { + struct xrdp_rect lrect; + + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: no good gfx, canceling"); + lrect.left = 0; + lrect.top = 0; + lrect.right = screen->width; + lrect.bottom = screen->height; + self->wm->client_info->gfx = 0; + xrdp_encoder_delete(self->encoder); + self->encoder = xrdp_encoder_create(self); + xrdp_bitmap_invalidate(screen, &lrect); + } + return 0; +} + +/*****************************************************************************/ +static int +xrdp_mm_update_module_frame_ack(struct xrdp_mm *self) +{ + int fif; + struct xrdp_encoder *encoder; + + encoder = self->encoder; + fif = encoder->frames_in_flight; + if (encoder->frame_id_client + fif > encoder->frame_id_server) + { + if (encoder->frame_id_server > encoder->frame_id_server_sent) + { + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_update_module_ack: " + "frame_id_server %d", encoder->frame_id_server); + encoder->frame_id_server_sent = encoder->frame_id_server; + self->mod->mod_frame_ack(self->mod, 0, encoder->frame_id_server); + } + } + return 0; +} + +static int +xrdp_mm_egfx_frame_ack(void *user, uint32_t queue_depth, int frame_id, + int frames_decoded) +{ + struct xrdp_mm *self; + struct xrdp_encoder *encoder; + + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack:"); + self = (struct xrdp_mm *) user; + encoder = self->encoder; + if (encoder == NULL) + { + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: encoder is nil"); + return 0; + } + if (queue_depth == XR_SUSPEND_FRAME_ACKNOWLEDGEMENT) + { + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: " + "queue_depth %d frame_id %d frames_decoded %d", + queue_depth, frame_id, frames_decoded); + if (encoder->gfx_ack_off == 0) + { + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: " + "client request turn off frame acks."); + encoder->gfx_ack_off = 1; + frame_id = -1; + } + } + else + { + if (encoder->gfx_ack_off) + { + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack: " + "client request turn on frame acks"); + encoder->gfx_ack_off = 0; + } + } + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack: " + "incoming %d, client %d, server %d", + frame_id, encoder->frame_id_client, encoder->frame_id_server); + if (frame_id < 0 || frame_id > encoder->frame_id_server) + { + /* if frame_id is negative or bigger then what server last sent + just ack all sent frames */ + /* some clients can send big number just to clear all + pending frames */ + encoder->frame_id_client = encoder->frame_id_server; + } + else + { + /* frame acks can come out of order so ignore older one */ + encoder->frame_id_client = MAX(frame_id, encoder->frame_id_client); + } + xrdp_mm_update_module_frame_ack(self); + return 0; +} + +/******************************************************************************/ +int +egfx_initialize(struct xrdp_mm *self) +{ + LOG_DEVEL(LOG_LEVEL_TRACE, "egfx_initialize"); + if (!(self->wm->client_info->mcs_early_capability_flags + & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL)) + { + return 0; + } + LOG_DEVEL(LOG_LEVEL_INFO, "egfx_initialize: gfx capable client"); + if (xrdp_egfx_create(self, &(self->egfx)) == 0) + { + self->egfx->user = self; + self->egfx->caps_advertise = xrdp_mm_egfx_caps_advertise; + self->egfx->frame_ack = xrdp_mm_egfx_frame_ack; + return 0; + } + LOG_DEVEL(LOG_LEVEL_INFO, "egfx_initialize: xrdp_egfx_create failed"); + return 1; +} + /******************************************************************************/ static const int MAXIMUM_MONITOR_SIZE = sizeof(struct monitor_info) * CLIENT_MONITOR_DATA_MAXIMUM_MONITORS; @@ -1162,27 +1434,6 @@ sync_dynamic_monitor_data(struct xrdp_wm *wm, MAXIMUM_MONITOR_SIZE); } -int -advance_resize_state_machine(struct xrdp_mm *mm, - enum display_resize_state new_state) -{ - struct display_control_monitor_layout_data *description = mm->resize_data; - LOG_DEVEL(LOG_LEVEL_INFO, - "advance_resize_state_machine:" - " Processing resize to: %d x %d." - " Advancing state from %s to %s." - " Previous state took %d MS.", - description->description.session_width, - description->description.session_height, - XRDP_DISPLAY_RESIZE_STATE_TO_STR(description->state), - XRDP_DISPLAY_RESIZE_STATE_TO_STR(new_state), - g_time3() - description->last_state_update_timestamp); - description->state = new_state; - description->last_state_update_timestamp = g_time3(); - g_set_wait_obj(mm->resize_ready); - return 0; -} - /******************************************************************************/ static int dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes) @@ -1269,7 +1520,8 @@ dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes) list_add_item(wm->mm->resize_queue, (tintptr)display_size_data); g_set_wait_obj(wm->mm->resize_ready); LOG(LOG_LEVEL_DEBUG, "dynamic_monitor_data:" - " received width %d, received height %d.", display_size_data->session_width, display_size_data->session_height); + " received width %d, received height %d.", + display_size_data->session_width, display_size_data->session_height); return 0; } @@ -1289,6 +1541,9 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) int error = 0; struct xrdp_mm *mm; struct xrdp_mod *module; + struct xrdp_rdp *rdp; + struct xrdp_sec *sec; + struct xrdp_channel *chan; LOG_DEVEL(LOG_LEVEL_TRACE, "process_display_control_monitor_layout_data:"); @@ -1326,6 +1581,56 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) xrdp_encoder_delete(mm->encoder); mm->encoder = NULL; } + if (mm->egfx == 0) + { + advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE); + } + else + { + advance_resize_state_machine(mm, WMRZ_EGFX_DELETE_SURFACE); + } + break; + case WMRZ_EGFX_DELETE_SURFACE: + if (error == 0 && module != 0) + { + xrdp_egfx_shutdown_delete_surface(mm->egfx); + } + advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSE); + break; + case WMRZ_EGFX_CONN_CLOSE: + if (error == 0 && module != 0) + { + xrdp_egfx_shutdown_close_connection(wm->mm->egfx); + } + advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSING); + break; + // Also processed in xrdp_egfx_close_response + case WMRZ_EGFX_CONN_CLOSING: + rdp = (struct xrdp_rdp *) (mm->wm->session->rdp); + sec = rdp->sec_layer; + chan = sec->chan_layer; + + // Continue to check to see if the connection is closed. If it + // ever is, advance the state machine! + if (chan->drdynvcs[mm->egfx->channel_id].status + == XRDP_DRDYNVC_STATUS_CLOSED + || (g_time3() - description->last_state_update_timestamp) > 100) + { + advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSED); + break; + } + g_set_wait_obj(mm->resize_ready); + break; + case WMRZ_EGFX_CONN_CLOSED: + advance_resize_state_machine(mm, WRMZ_EGFX_DELETE); + break; + case WRMZ_EGFX_DELETE: + if (error == 0 && module != 0) + { + xrdp_egfx_shutdown_delete(wm->mm->egfx); + mm->egfx = NULL; + mm->egfx_up = 0; + } advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE); break; case WMRZ_SERVER_MONITOR_RESIZE: @@ -1338,9 +1643,10 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) " mod_server_monitor_resize failed %d", error); return advance_error(error, mm); } - advance_resize_state_machine(mm, WMRZ_SERVER_VERSION_MESSAGE); + advance_resize_state_machine( + mm, WMRZ_SERVER_VERSION_MESSAGE_START); break; - case WMRZ_SERVER_VERSION_MESSAGE: + case WMRZ_SERVER_VERSION_MESSAGE_START: error = module->mod_server_version_message(module); if (error != 0) { @@ -1349,6 +1655,12 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) " mod_server_version_message failed %d", error); return advance_error(error, mm); } + advance_resize_state_machine( + mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING); + break; + // Not processed here. Processed in server_reset + // case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING: + case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED: advance_resize_state_machine(mm, WMRZ_XRDP_CORE_RESIZE); break; case WMRZ_XRDP_CORE_RESIZE: @@ -1400,6 +1712,22 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) return advance_error(error, mm); } sync_dynamic_monitor_data(wm, &(description->description)); + advance_resize_state_machine(mm, WMRZ_EGFX_INITIALIZE); + break; + case WMRZ_EGFX_INITIALIZE: + if (error == 0 && mm->egfx == NULL && mm->egfx_up == 0) + { + egfx_initialize(mm); + advance_resize_state_machine(mm, WMRZ_EGFX_INITALIZING); + } + else + { + advance_resize_state_machine(mm, WMRZ_EGFX_INITIALIZED); + } + break; + // Not processed here. Processed in xrdp_mm_egfx_caps_advertise + // case WMRZ_EGFX_INITALIZING: + case WMRZ_EGFX_INITIALIZED: advance_resize_state_machine(mm, WMRZ_ENCODER_CREATE); break; case WMRZ_ENCODER_CREATE: @@ -1450,7 +1778,7 @@ dynamic_monitor_process_queue(struct xrdp_mm *self) return 0; } - if (self->resize_data == NULL) + if (self->resize_data == NULL && self->resize_queue != NULL) { if (self->resize_queue->count <= 0) { @@ -1518,6 +1846,11 @@ dynamic_monitor_process_queue(struct xrdp_mm *self) " Resize data is not null."); } + if (self->resize_data == NULL) + { + return 0; + } + if (self->resize_data->state == WMRZ_COMPLETE) { LOG(LOG_LEVEL_INFO, "dynamic_monitor_process_queue: Clearing" @@ -1552,6 +1885,8 @@ dynamic_monitor_initialize(struct xrdp_mm *self) struct xrdp_drdynvc_procs d_procs; int flags; int error; + char buf[1024]; + int pid; LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_initialize:"); @@ -1567,9 +1902,20 @@ dynamic_monitor_initialize(struct xrdp_mm *self) &(self->dynamic_monitor_chanid)); if (error != 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_mm_drdynvc_up: " + LOG(LOG_LEVEL_ERROR, "dynamic_monitor_initialize: " "libxrdp_drdynvc_open failed %d", error); + return error; } + + // Initialize xrdp_mm specific variables. + self->resize_queue = list_create(); + self->resize_queue->auto_free = 1; + pid = g_getpid(); + /* setup wait objects for signaling */ + g_snprintf(buf, sizeof(buf), "xrdp_%8.8x_resize_ready", pid); + self->resize_ready = g_create_wait_obj(buf); + self->resize_data = NULL; + return error; } @@ -1583,6 +1929,12 @@ xrdp_mm_drdynvc_up(struct xrdp_mm *self) LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_drdynvc_up:"); + error = egfx_initialize(self); + if (error != 0) + { + return error; + } + enable_dynamic_resize = xrdp_mm_get_value(self, "enable_dynamic_resizing"); /* * User can disable dynamic resizing if necessary @@ -1593,10 +1945,17 @@ xrdp_mm_drdynvc_up(struct xrdp_mm *self) LOG(LOG_LEVEL_INFO, "User has disabled dynamic resizing."); return error; } + error = dynamic_monitor_initialize(self); + if (error != 0) + { + LOG(LOG_LEVEL_INFO, "Dynamic monitor initialize failed." + " Client likely does not support it."); + return error; + } ignore_marker = (struct display_control_monitor_layout_data *) - g_malloc(sizeof(struct display_control_monitor_layout_data), 1); + g_malloc(sizeof(struct display_control_monitor_layout_data), + 1); list_add_item(self->resize_queue, (tintptr)ignore_marker); - error = dynamic_monitor_initialize(self); return error; } @@ -2795,7 +3154,10 @@ xrdp_mm_connect_sm(struct xrdp_mm *self) } } - +#define MIN_MS_BETWEEN_FRAMES 40 +/* can not change this to zero yet, g_obj_wait in os_calls.c treats + everything less then 1 to mean wait forever */ +#define MIN_MS_TO_WAIT_FOR_MORE_UPDATES 1 /*****************************************************************************/ int xrdp_mm_get_wait_objs(struct xrdp_mm *self, @@ -2842,6 +3204,25 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self, read_objs[(*rcount)++] = self->resize_ready; } + if (self->wm->screen_dirty_region != NULL) + { + if (xrdp_region_not_empty(self->wm->screen_dirty_region)) + { + int now = g_time3(); + int next_screen_draw_time = self->wm->last_screen_draw_time + + MIN_MS_BETWEEN_FRAMES; + int diff = next_screen_draw_time - now; + int ltimeout = *timeout; + diff = MAX(diff, MIN_MS_TO_WAIT_FOR_MORE_UPDATES); + diff = MIN(diff, MIN_MS_BETWEEN_FRAMES); + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_get_wait_objs:" + " not empty diff %d", diff); + if ((ltimeout < 0) || (ltimeout > diff)) + { + *timeout = diff; + } + } + } return rv; } @@ -2919,28 +3300,6 @@ xrdp_mm_check_chan(struct xrdp_mm *self) return 0; } -/*****************************************************************************/ -static int -xrdp_mm_update_module_frame_ack(struct xrdp_mm *self) -{ - int fif; - struct xrdp_encoder *encoder; - - encoder = self->encoder; - fif = encoder->frames_in_flight; - if (encoder->frame_id_client + fif > encoder->frame_id_server) - { - if (encoder->frame_id_server > encoder->frame_id_server_sent) - { - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_update_module_ack: frame_id_server %d", - encoder->frame_id_server); - encoder->frame_id_server_sent = encoder->frame_id_server; - self->mod->mod_frame_ack(self->mod, 0, encoder->frame_id_server); - } - } - return 0; -} - /*****************************************************************************/ static int xrdp_mm_process_enc_done(struct xrdp_mm *self) @@ -2973,22 +3332,45 @@ xrdp_mm_process_enc_done(struct xrdp_mm *self) cy = enc_done->cy; if (enc_done->comp_bytes > 0) { - if (!enc_done->continuation) + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_process_enc_done: " + "x %d y %d cx %d cy %d frame_id %d use_frame_acks %d", + x, y, cx, cy, enc_done->enc->frame_id, + self->wm->client_info->use_frame_acks); + if (enc_done->flags & GFX_H264) { - libxrdp_fastpath_send_frame_marker(self->wm->session, 0, - enc_done->enc->frame_id); + LOG(LOG_LEVEL_INFO, "GFX H264 Unimplemeted."); } - libxrdp_fastpath_send_surface(self->wm->session, - enc_done->comp_pad_data, - enc_done->pad_bytes, - enc_done->comp_bytes, - x, y, x + cx, y + cy, - 32, self->encoder->codec_id, - cx, cy); - if (enc_done->last) + else if (enc_done->flags & GFX_PROGRESSIVE_RFX) /* gfx progressive rfx */ { - libxrdp_fastpath_send_frame_marker(self->wm->session, 1, - enc_done->enc->frame_id); + xrdp_egfx_send_frame_start(self->egfx, + enc_done->enc->frame_id, 0); + xrdp_egfx_send_wire_to_surface2(self->egfx, + self->egfx->surface_id, 9, 1, + XR_PIXEL_FORMAT_XRGB_8888, + enc_done->comp_pad_data + + enc_done->pad_bytes, + enc_done->comp_bytes); + xrdp_egfx_send_frame_end(self->egfx, enc_done->enc->frame_id); + } + else + { + if (!enc_done->continuation) + { + libxrdp_fastpath_send_frame_marker(self->wm->session, 0, + enc_done->enc->frame_id); + } + libxrdp_fastpath_send_surface(self->wm->session, + enc_done->comp_pad_data, + enc_done->pad_bytes, + enc_done->comp_bytes, + x, y, x + cx, y + cy, + 32, self->encoder->codec_id, + cx, cy); + if (enc_done->last) + { + libxrdp_fastpath_send_frame_marker(self->wm->session, 1, + enc_done->enc->frame_id); + } } } /* free enc_done */ @@ -2996,16 +3378,35 @@ xrdp_mm_process_enc_done(struct xrdp_mm *self) { enc = enc_done->enc; LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_process_enc_done: last set"); - if (self->wm->client_info->use_frame_acks == 0) + if (enc_done->flags & GFX_H264) /* gfx */ { - self->mod->mod_frame_ack(self->mod, - enc->flags, - enc->frame_id); + if (self->encoder->gfx_ack_off) + { + /* gfx and client turned off client frame acks */ + self->mod->mod_frame_ack(self->mod, + enc->flags, + enc->frame_id); + } + else + { + self->encoder->frame_id_server = enc->frame_id; + xrdp_mm_update_module_frame_ack(self); + } } else { - self->encoder->frame_id_server = enc->frame_id; - xrdp_mm_update_module_frame_ack(self); + if (self->wm->client_info->use_frame_acks == 0) + { + /* surface commmand and client does not do frame acks */ + self->mod->mod_frame_ack(self->mod, + enc->flags, + enc->frame_id); + } + else + { + self->encoder->frame_id_server = enc_done->enc->frame_id; + xrdp_mm_update_module_frame_ack(self); + } } g_free(enc->drects); g_free(enc->crects); @@ -3143,8 +3544,9 @@ xrdp_mm_frame_ack(struct xrdp_mm *self, int frame_id) return 1; } encoder = self->encoder; - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_frame_ack: incoming %d, client %d, server %d", - frame_id, encoder->frame_id_client, encoder->frame_id_server); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_frame_ack: " + "incoming %d, client %d, server %d", frame_id, + encoder->frame_id_client, encoder->frame_id_server); if ((frame_id < 0) || (frame_id > encoder->frame_id_server)) { /* if frame_id is negative or bigger then what server last sent @@ -3389,9 +3791,11 @@ server_paint_rects(struct xrdp_mod *mod, int num_drects, short *drects, /*****************************************************************************/ int -server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects, - int num_crects, short *crects, char *data, - int left, int top, int width, int height, +server_paint_rects_ex(struct xrdp_mod *mod, + int num_drects, short *drects, + int num_crects, short *crects, + char *data, int left, int top, + int width, int height, int flags, int frame_id, void *shmem_ptr, int shmem_bytes) { @@ -3406,7 +3810,7 @@ server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects, wm = (struct xrdp_wm *)(mod->wm); mm = wm->mm; - LOG_DEVEL(LOG_LEVEL_DEBUG, "server_paint_rects: %p", mm->encoder); + LOG(LOG_LEVEL_TRACE, "server_paint_rects_ex: %p", mm->encoder); if (mm->encoder != 0) { @@ -3477,7 +3881,12 @@ server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects, return 0; } - LOG(LOG_LEVEL_TRACE, "server_paint_rects:"); + if (wm->client_info->gfx) + { + LOG(LOG_LEVEL_DEBUG, "server_paint_rects: gfx session and no encoder"); + mm->mod->mod_frame_ack(mm->mod, flags, frame_id); + return 0; + } p = (struct xrdp_painter *)(mod->painter); if (p == 0) @@ -3796,8 +4205,16 @@ int server_reset(struct xrdp_mod *mod, int width, int height, int bpp) { struct xrdp_wm *wm; + struct xrdp_mm *mm; + + LOG(LOG_LEVEL_TRACE, "server_reset:"); wm = (struct xrdp_wm *)(mod->wm); + if (wm == 0) + { + return 1; + } + mm = wm->mm; if (wm->client_info == 0) { @@ -3810,6 +4227,42 @@ server_reset(struct xrdp_mod *mod, int width, int height, int bpp) return 0; } + // bpp of zero is impossible. + // This is a signal from xup that + // It is finished resizing. + if (bpp == 0) + { + if (mm == 0) + { + return 1; + } + if (!xrdp_wm_can_resize(wm)) + { + return 1; + } + if (mm->resize_data == NULL) + { + mm->mod->mod_server_monitor_full_invalidate(mm->mod, width, height); + return 0; + } + if (mm->resize_data != NULL + && mm->resize_data->state + == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING) + { + LOG(LOG_LEVEL_INFO, + "server_reset: Advancing server monitor resized."); + advance_resize_state_machine( + mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED); + } + else if (mm->resize_data != NULL + && mm->resize_data->description.session_height == 0 + && mm->resize_data->description.session_width == 0) + { + mm->mod->mod_server_monitor_full_invalidate(mm->mod, width, height); + } + return 0; + } + /* if same (and only one monitor on client) don't need to do anything */ if (wm->client_info->display_sizes.session_width == (uint32_t)width && wm->client_info->display_sizes.session_height == (uint32_t)height && diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index d0bce05706..06ccf4469b 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -28,6 +28,7 @@ #include "xrdp_constants.h" #include "fifo.h" #include "guid.h" +#include "xrdp_client_info.h" #define MAX_NR_CHANNELS 16 #define MAX_CHANNEL_NAME 16 @@ -343,7 +344,9 @@ enum display_resize_state WMRZ_EGFX_CONN_CLOSED, WRMZ_EGFX_DELETE, WMRZ_SERVER_MONITOR_RESIZE, - WMRZ_SERVER_VERSION_MESSAGE, + WMRZ_SERVER_VERSION_MESSAGE_START, + WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING, + WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED, WMRZ_XRDP_CORE_RESIZE, WMRZ_EGFX_INITIALIZE, WMRZ_EGFX_INITALIZING, @@ -362,7 +365,12 @@ enum display_resize_state (status) == WMRZ_EGFX_CONN_CLOSED ? "WMRZ_EGFX_CONN_CLOSED" : \ (status) == WRMZ_EGFX_DELETE ? "WMRZ_EGFX_DELETE" : \ (status) == WMRZ_SERVER_MONITOR_RESIZE ? "WMRZ_SERVER_MONITOR_RESIZE" : \ - (status) == WMRZ_SERVER_VERSION_MESSAGE ? "WMRZ_SERVER_VERSION_MESSAGE" : \ + (status) == WMRZ_SERVER_VERSION_MESSAGE_START ? \ + "WMRZ_SERVER_VERSION_MESSAGE_START" : \ + (status) == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING ? \ + "WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING" : \ + (status) == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED ? \ + "WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED" : \ (status) == WMRZ_XRDP_CORE_RESIZE ? "WMRZ_XRDP_CORE_RESIZE" : \ (status) == WMRZ_EGFX_INITIALIZE ? "WMRZ_EGFX_INITIALIZE" : \ (status) == WMRZ_EGFX_INITALIZING ? "WMRZ_EGFX_INITALIZING" : \ @@ -417,7 +425,7 @@ struct xrdp_mm int dynamic_monitor_chanid; struct xrdp_egfx *egfx; int egfx_up; - int egfx_flags; + enum xrdp_egfx_flags egfx_flags; int gfx_delay_autologin; /* Resize on-the-fly control */ struct display_control_monitor_layout_data *resize_data; diff --git a/xup/xup.c b/xup/xup.c index 4215d0bcf7..0b6cbd041a 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -1174,47 +1174,33 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s) in_uint16_le(s, height); bmpdata = 0; - if (flags == 0) /* screen */ + if (amod->screen_shmem_id_mapped == 0) { - /* Do we need to map (or remap) the memory - * area shared with the X server ? */ - if (amod->screen_shmem_id_mapped == 0 || - amod->screen_shmem_id != shmem_id) + amod->screen_shmem_id = shmem_id; + amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id); + if (amod->screen_shmem_pixels == (void *) -1) { - if (amod->screen_shmem_id_mapped != 0) - { - g_shmdt(amod->screen_shmem_pixels); - } - amod->screen_shmem_pixels = (char *) g_shmat(shmem_id); - if (amod->screen_shmem_pixels == (void *) -1) - { - /* failed */ - if (amod->screen_shmem_id_mapped == 0) - { - LOG(LOG_LEVEL_ERROR, - "Can't attach to shared memory id %d [%s]", - shmem_id, g_get_strerror()); - } - else - { - LOG(LOG_LEVEL_ERROR, - "Can't attach to shared memory id %d from id %d [%s]", - shmem_id, amod->screen_shmem_id, g_get_strerror()); - } - amod->screen_shmem_id = 0; - amod->screen_shmem_pixels = 0; - amod->screen_shmem_id_mapped = 0; - } - else - { - amod->screen_shmem_id = shmem_id; - amod->screen_shmem_id_mapped = 1; - } + /* failed */ + amod->screen_shmem_id = 0; + amod->screen_shmem_pixels = 0; + amod->screen_shmem_id_mapped = 0; } - - if (amod->screen_shmem_pixels != 0) + else + { + amod->screen_shmem_id_mapped = 1; + } + } + else if (amod->screen_shmem_id != shmem_id) + { + amod->screen_shmem_id = shmem_id; + g_shmdt(amod->screen_shmem_pixels); + amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id); + if (amod->screen_shmem_pixels == (void *) -1) { - bmpdata = amod->screen_shmem_pixels + shmem_offset; + /* failed */ + amod->screen_shmem_id = 0; + amod->screen_shmem_pixels = 0; + amod->screen_shmem_id_mapped = 0; } } else @@ -1225,7 +1211,10 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s) flags, frame_id, shmem_id, shmem_offset, width, height); } - + if (amod->screen_shmem_pixels != 0) + { + bmpdata = amod->screen_shmem_pixels + shmem_offset; + } if (bmpdata != 0) { rv = amod->server_paint_rects(amod, num_drects, ldrects, @@ -1238,9 +1227,6 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s) rv = 1; } - //LOG_DEVEL(LOG_LEVEL_TRACE, "frame_id %d", frame_id); - //send_paint_rect_ex_ack(amod, flags, frame_id); - g_free(lcrects); g_free(ldrects); @@ -1680,74 +1666,71 @@ lib_mod_process_message(struct mod *mod, struct stream *s) char *phold; LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message:"); + in_uint16_le(s, type); + in_uint16_le(s, num_orders); + in_uint32_le(s, len); + LOG_DEVEL(LOG_LEVEL_DEBUG, "lib_mod_process_message: type %d", type); + rv = 0; - if (rv == 0) + if (type == 1) /* original order list */ { - in_uint16_le(s, type); - in_uint16_le(s, num_orders); - in_uint32_le(s, len); - LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message: type %d", type); - - if (type == 1) /* original order list */ + for (index = 0; index < num_orders; index++) { - for (index = 0; index < num_orders; index++) - { - in_uint16_le(s, type); - rv = lib_mod_process_orders(mod, type, s); + in_uint16_le(s, type); + rv = lib_mod_process_orders(mod, type, s); - if (rv != 0) - { - break; - } - } - } - else if (type == 2) /* caps */ - { - LOG_DEVEL(LOG_LEVEL_TRACE, - "lib_mod_process_message: type 2 len %d", len); - for (index = 0; index < num_orders; index++) + if (rv != 0) { - phold = s->p; - in_uint16_le(s, type); - in_uint16_le(s, len); - - switch (type) - { - default: - LOG_DEVEL(LOG_LEVEL_TRACE, - "lib_mod_process_message: unknown" - " cap type %d len %d", - type, len); - break; - } - - s->p = phold + len; + break; } - - lib_send_client_info(mod); } - else if (type == 3) /* order list with len after type */ + } + else if (type == 2) /* caps */ + { + LOG_DEVEL(LOG_LEVEL_TRACE, + "lib_mod_process_message: type 2 len %d", len); + for (index = 0; index < num_orders; index++) { - for (index = 0; index < num_orders; index++) - { - phold = s->p; - in_uint16_le(s, type); - in_uint16_le(s, len); - rv = lib_mod_process_orders(mod, type, s); + phold = s->p; + in_uint16_le(s, type); + in_uint16_le(s, len); - if (rv != 0) - { + switch (type) + { + default: + LOG_DEVEL(LOG_LEVEL_TRACE, + "lib_mod_process_message: unknown" + " cap type %d len %d", + type, len); break; - } - - s->p = phold + len; } + s->p = phold + len; } - else + lib_send_client_info(mod); + } + else if (type == 3) /* order list with len after type */ + { + LOG_DEVEL(LOG_LEVEL_INFO, + "lib_mod_process_message: type 3 len %d", len); + for (index = 0; index < num_orders; index++) { - LOG_DEVEL(LOG_LEVEL_TRACE, "unknown type %d", type); + phold = s->p; + in_uint16_le(s, type); + in_uint16_le(s, len); + rv = lib_mod_process_orders(mod, type, s); + + if (rv != 0) + { + break; + } + + s->p = phold + len; } } + else + { + LOG_DEVEL(LOG_LEVEL_TRACE, "unknown type %d", type); + } return rv; } From 5814809cd769ed1b2ff32924c865221d2ca79186 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Tue, 2 Jan 2024 10:32:17 +0000 Subject: [PATCH 3/4] Bump CI version of FreeBSD to 13.2 --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 5830d224f2..f650248a8c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -4,7 +4,7 @@ FreeBSD_task: SSL: libressl matrix: freebsd_instance: - image_family: freebsd-12-4 + image_family: freebsd-13-2 prepare_script: - pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check imlib2 freetype2 cmocka - git submodule update --init --recursive From 170b88154a20f4278c5c8965f1d828fe0665f827 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Thu, 4 Jan 2024 16:13:29 +0000 Subject: [PATCH 4/4] Allow a zero timeout for g_obj_wait() At the moment, timeouts of -1 or 0 for g_obj_wait() both mean 'no timeout', i.e. wait forever. This commit changes a timeout of 0 to mean 'return immediately'. This is more consistent with poll() and WaitForMultipleObjects(), and can be used by the new encoder logic. There are a very few places on xrdp where a timeout of 0 is currently specified to mean 'wait forever'. These are replaced with values of -1. --- common/os_calls.c | 4 ++-- common/os_calls.h | 5 ++++- sesman/chansrv/chansrv.c | 4 ++-- sesman/sesexec/sesexec.c | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/common/os_calls.c b/common/os_calls.c index 765ad47284..c462819db8 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -1979,7 +1979,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount, handles[j++] = (HANDLE)(write_objs[i]); } - if (mstimeout < 1) + if (mstimeout < 0) { mstimeout = INFINITE; } @@ -2016,7 +2016,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount, } else { - if (mstimeout < 1) + if (mstimeout < 0) { mstimeout = -1; } diff --git a/common/os_calls.h b/common/os_calls.h index a9cf8f5d28..02758e8934 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -203,10 +203,13 @@ int g_delete_wait_obj(tintptr obj); * @param rcount Number of elements in read_objs * @param write_objs Array of write objects * @param rcount Number of elements in write_objs - * @param mstimeout Timeout in milliseconds. <= 0 means an infinite timeout. + * @param mstimeout Timeout in milliseconds. < 0 means an infinite timeout. * * @return 0 for success. The objects will need to be polled to * find out what is readable or writeable. + * + * An mstimeout of zero will return immediately, although + * error conditions may be checked for. */ int g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount, int mstimeout); diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 31daff4c05..80f0a2314f 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -1787,7 +1787,7 @@ main(int argc, char **argv) waiters[1] = g_exec_event; waiters[2] = g_sigchld_event; - if (g_obj_wait(waiters, 3, 0, 0, 0) != 0) + if (g_obj_wait(waiters, 3, 0, 0, -1) != 0) { LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, g_obj_wait failed"); break; @@ -1814,7 +1814,7 @@ main(int argc, char **argv) while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event)) { /* wait for thread to exit */ - if (g_obj_wait(&g_thread_done_event, 1, 0, 0, 0) != 0) + if (g_obj_wait(&g_thread_done_event, 1, 0, 0, -1) != 0) { LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, g_obj_wait failed"); break; diff --git a/sesman/sesexec/sesexec.c b/sesman/sesexec/sesexec.c index 563a0695dd..3e9763dded 100644 --- a/sesman/sesexec/sesexec.c +++ b/sesman/sesexec/sesexec.c @@ -283,7 +283,7 @@ sesexec_main_loop(void) continue; } - if (g_obj_wait(robjs, robjs_count, NULL, 0, 0) != 0) + if (g_obj_wait(robjs, robjs_count, NULL, 0, -1) != 0) { /* should not get here */ LOG(LOG_LEVEL_WARNING, "sesexec_main_loop: "