Files
xrdp/xrdp_accel_assist/xrdp_accel_assist.c
T
2025-02-16 17:34:51 -08:00

1032 lines
28 KiB
C

/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2020-2024
*
* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "arch.h"
#include "parse.h"
#include "trans.h"
#include "os_calls.h"
#include "string_calls.h"
#include "log.h"
#include "xrdp_accel_assist.h"
#include "xrdp_accel_assist_x11.h"
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
#define GFX_MAP_SIZE 3145728
struct xorgxrdp_info
{
struct trans *xorg_trans;
struct trans *xrdp_trans;
struct source_info si;
int shmem_fd_ret;
int shmem_bytes_ret;
int idr_count;
int pad0;
};
static int g_display_num = 0;
/*****************************************************************************/
static int
gfx_wiretosurface1(struct xorgxrdp_info *xi, struct stream *s)
{
void *addr;
int surface_id;
int codec_id;
int pixel_format;
int flags;
int num_rects_c;
struct xh_rect *crects;
int num_rects_d;
int index;
int left;
int top;
int width;
int height;
int cdata_bytes;
int rv;
int encoder_flags;
char *flags_pointer;
char *final_pointer;
(void)pixel_format;
(void)codec_id;
(void)surface_id;
(void)rv;
if (xi->shmem_fd_ret != -1)
{
LOG(LOG_LEVEL_ERROR, "gfx_wiretosurface1: xi->shmem_fd_ret "
"should be -1, it is %d", xi->shmem_fd_ret);
}
if (g_alloc_shm_map_fd(&addr, &(xi->shmem_fd_ret), GFX_MAP_SIZE) != 0)
{
return 1;
}
LOG_DEVEL(LOG_LEVEL_INFO, "gfx_wiretosurface1: addr %p fd %d",
addr, xi->shmem_fd_ret);
if (!s_check_rem(s, 11))
{
g_munmap(addr, GFX_MAP_SIZE);
g_file_close(xi->shmem_fd_ret);
xi->shmem_fd_ret = -1;
return 1;
}
in_uint16_le(s, surface_id);
in_uint16_le(s, codec_id);
in_uint8(s, pixel_format);
flags_pointer = s->p;
in_uint32_le(s, flags);
LOG_DEVEL(LOG_LEVEL_INFO, "gfx_wiretosurface1: surface_id %d codec_id %d "
"pixel_format %d flags %d",
surface_id, codec_id, pixel_format, flags);
in_uint16_le(s, num_rects_d);
if ((num_rects_d < 1) || (num_rects_d > 16 * 1024) ||
(!s_check_rem(s, num_rects_d * 8)))
{
g_munmap(addr, GFX_MAP_SIZE);
g_file_close(xi->shmem_fd_ret);
xi->shmem_fd_ret = -1;
return 1;
}
in_uint8s(s, num_rects_d * 8);
if (!s_check_rem(s, 2))
{
g_munmap(addr, GFX_MAP_SIZE);
g_file_close(xi->shmem_fd_ret);
xi->shmem_fd_ret = -1;
return 1;
}
in_uint16_le(s, num_rects_c);
if ((num_rects_c < 1) || (num_rects_c > 16 * 1024) ||
(!s_check_rem(s, num_rects_c * 8)))
{
g_munmap(addr, GFX_MAP_SIZE);
g_file_close(xi->shmem_fd_ret);
xi->shmem_fd_ret = -1;
return 1;
}
crects = g_new0(struct xh_rect, num_rects_c);
if (crects == NULL)
{
g_munmap(addr, GFX_MAP_SIZE);
g_file_close(xi->shmem_fd_ret);
xi->shmem_fd_ret = -1;
return 1;
}
for (index = 0; index < num_rects_c; index++)
{
in_uint16_le(s, crects[index].x);
in_uint16_le(s, crects[index].y);
in_uint16_le(s, crects[index].w);
in_uint16_le(s, crects[index].h);
}
if (!s_check_rem(s, 8))
{
g_munmap(addr, GFX_MAP_SIZE);
g_file_close(xi->shmem_fd_ret);
xi->shmem_fd_ret = -1;
g_free(crects);
return 1;
}
in_uint16_le(s, left);
in_uint16_le(s, top);
in_uint16_le(s, width);
in_uint16_le(s, height);
final_pointer = s->p;
(void)left;
(void)top;
cdata_bytes = GFX_MAP_SIZE;
encoder_flags = 0;
if (xi->idr_count > 0)
{
encoder_flags = XH_ENC_FLAGS_FORCEIDR;
xi->idr_count--;
}
rv = xrdp_accel_assist_x11_encode_pixmap(0, 0,
width, height, surface_id,
num_rects_c, crects,
addr, &cdata_bytes,
encoder_flags);
LOG_DEVEL(LOG_LEVEL_INFO, "gfx_wiretosurface1: rv %d cdata_bytes %d",
rv, cdata_bytes);
s->p = flags_pointer;
flags |= 1;
out_uint32_le(s, flags); /* set already encoded bit */
s->p = final_pointer;
xi->shmem_bytes_ret = cdata_bytes;
g_free(crects);
g_munmap(addr, GFX_MAP_SIZE);
/* do not close xi->shmem_fd_ret here, it will get closed after sent */
return 0;
}
/*****************************************************************************/
static int
xorg_process_message_62(struct xorgxrdp_info *xi, struct stream *s)
{
int recv_bytes;
int total_cmd_bytes;
int total_shm_bytes;
int cmd_bytes;
int cmd_id;
int fd;
unsigned int num_fds;
char msg[4];
char *total_holdp;
char *total_holdend;
char *holdp;
char *holdend;
if (!s_check_rem(s, 4))
{
return 1;
}
in_uint32_le(s, total_cmd_bytes);
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_62: "
"total_cmd_bytes %d",
total_cmd_bytes);
if ((total_cmd_bytes < 1) || (total_cmd_bytes > 32 * 1024) ||
(!s_check_rem(s, total_cmd_bytes)))
{
return 1;
}
total_holdp = s->p;
total_holdend = s->end;
s->end = s->p + total_cmd_bytes;
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_62: "
"rem %d",
(int)(s->end - s->p));
while (s_check_rem(s, 8))
{
holdp = s->p;
in_uint16_le(s, cmd_id);
in_uint8s(s, 2); /* flags */
in_uint32_le(s, cmd_bytes);
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_62: "
"cmd_id %d cmd_bytes %d",
cmd_id, cmd_bytes);
if ((cmd_bytes < 8) || (cmd_bytes > 32 * 1024) ||
(!s_check_rem(s, cmd_bytes - 8)))
{
return 1;
}
holdend = s->end;
s->end = holdp + cmd_bytes;
switch (cmd_id)
{
case 0x0001: /* XR_RDPGFX_CMDID_WIRETOSURFACE_1 */
if (gfx_wiretosurface1(xi, s) != 0)
{
return 1;
}
break;
case 0x000E: /* XR_RDPGFX_CMDID_RESETGRAPHICS */
LOG(LOG_LEVEL_INFO, "xorg_process_message_62: "
"XR_RDPGFX_CMDID_RESETGRAPHICS detected");
break;
}
/* setup for next cmd */
s->p = holdp + cmd_bytes;
s->end = holdend;
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_62: "
"rem %d",
(int)(s->end - s->p));
}
s->p = total_holdp + total_cmd_bytes;
s->end = total_holdend;
if (!s_check_rem(s, 4))
{
return 1;
}
in_uint32_le(s, total_shm_bytes);
s->p -= 4;
out_uint32_le(s, xi->shmem_bytes_ret);
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_62: "
"total_shm_bytes %d",
total_shm_bytes);
if (total_shm_bytes < 1)
{
/* return no error */
return 0;
}
num_fds = 0;
if (g_tcp_can_recv(xi->xorg_trans->sck, 5000) == 0)
{
return 1;
}
recv_bytes = g_sck_recv_fd_set(xi->xorg_trans->sck, msg, 4,
&fd, 1, &num_fds);
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_62: "
"g_sck_recv_fd_set rv %d fd %d, num_fds %d",
recv_bytes, fd, num_fds);
if (recv_bytes == 4)
{
if (num_fds == 1)
{
g_file_close(fd);
/* return no error */
return 0;
}
}
return 1;
}
/*****************************************************************************/
static int
xorg_process_message_63(struct xorgxrdp_info *xi, struct stream *s)
{
int recv_bytes;
unsigned int num_fds;
char msg[4];
if (xi->shmem_fd_ret != -1)
{
LOG(LOG_LEVEL_ERROR, "xorg_process_message_63: xi->shmem_fd_ret "
"should be -1, it is %d", xi->shmem_fd_ret);
}
num_fds = -1;
if (g_tcp_can_recv(xi->xorg_trans->sck, 5000) == 0)
{
return 1;
}
recv_bytes = g_sck_recv_fd_set(xi->xorg_trans->sck, msg, 4,
&(xi->shmem_fd_ret), 1, &num_fds);
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_63: "
"g_sck_recv_fd_set rv %d fd %d, num_fds %d",
recv_bytes, xi->shmem_fd_ret, num_fds);
if (recv_bytes == 4)
{
if (num_fds == 1)
{
return 0;
}
}
return 1;
}
/*****************************************************************************/
static int
xorg_process_message_64(struct xorgxrdp_info *xi, struct stream *s)
{
int num_drects;
int num_crects;
int flags;
int shmem_bytes;
int shmem_offset;
int frame_id;
int left;
int top;
int width;
int height;
int twidth;
int theight;
int cdata_bytes;
int index;
int recv_bytes;
int encoder_flags;
enum encoder_result rv;
struct xh_rect *crects;
char *bmpdata;
char msg[4];
unsigned int num_fds;
void *shmem_ptr;
(void)twidth;
(void)theight;
(void)frame_id;
/* dirty pixels */
in_uint16_le(s, num_drects);
in_uint8s(s, 8 * num_drects);
/* copied pixels */
in_uint16_le(s, num_crects);
crects = g_new(struct xh_rect, num_crects);
for (index = 0; index < num_crects; index++)
{
in_uint16_le(s, crects[index].x);
in_uint16_le(s, crects[index].y);
in_uint16_le(s, crects[index].w);
in_uint16_le(s, crects[index].h);
}
char *flag_pointer = s->p;
in_uint32_le(s, flags);
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_64: flags 0x%8.8X", flags);
in_uint32_le(s, frame_id);
in_uint32_le(s, shmem_bytes);
in_uint32_le(s, shmem_offset);
in_uint16_le(s, left);
in_uint16_le(s, top);
in_uint16_le(s, width);
in_uint16_le(s, height);
in_uint16_le(s, twidth);
in_uint16_le(s, theight);
char *final_pointer = s->p;
if (xi->shmem_fd_ret != -1)
{
LOG(LOG_LEVEL_ERROR, "xorg_process_message_64: xi->shmem_fd_ret "
"should be -1, it is %d", xi->shmem_fd_ret);
}
num_fds = -1;
if (g_tcp_can_recv(xi->xorg_trans->sck, 5000) == 0)
{
g_free(crects);
return 1;
}
recv_bytes = g_sck_recv_fd_set(xi->xorg_trans->sck, msg, 4,
&(xi->shmem_fd_ret), 1, &num_fds);
LOG_DEVEL(LOG_LEVEL_INFO, "xorg_process_message_64: "
"g_sck_recv_fd_set rv %d fd %d, num_fds %d",
recv_bytes, xi->shmem_fd_ret, num_fds);
shmem_ptr = NULL;
if (recv_bytes == 4)
{
if (num_fds == 1)
{
if (g_file_map(xi->shmem_fd_ret, 1, 1, shmem_bytes,
&shmem_ptr) == 0)
{
bmpdata = (char *)shmem_ptr;
bmpdata += shmem_offset;
if ((bmpdata != NULL) && (flags & 1))
{
cdata_bytes = 16 * 1024 * 1024;
encoder_flags = 0;
if (xi->idr_count > 0)
{
encoder_flags = XH_ENC_FLAGS_FORCEIDR;
xi->idr_count--;
}
rv = xrdp_accel_assist_x11_encode_pixmap(left, top,
width, height,
(flags >> 28) & 0xF,
num_crects, crects,
bmpdata + 4,
&cdata_bytes, encoder_flags);
if (rv == ENCODER_ERROR)
{
LOG(LOG_LEVEL_ERROR, "error %d", rv);
}
if (rv == KEY_FRAME_ENCODED)
{
s->p = flag_pointer;
out_uint32_le(s, flags | 1 | 2);
s->p = final_pointer;
}
bmpdata[0] = cdata_bytes;
bmpdata[1] = cdata_bytes >> 8;
bmpdata[2] = cdata_bytes >> 16;
bmpdata[3] = cdata_bytes >> 24;
LOG_DEVEL(LOG_LEVEL_INFO, "cdata_bytes %d", cdata_bytes);
}
}
}
else
{
LOG(LOG_LEVEL_INFO,
"xorg_process_message_64: num_fds %d", num_fds);
}
}
else
{
LOG(LOG_LEVEL_INFO,
"xorg_process_message_64: recv_bytes %d", recv_bytes);
}
if (shmem_ptr != NULL)
{
g_munmap(shmem_ptr, shmem_bytes);
}
g_free(crects);
return 0;
}
/*****************************************************************************/
/* data going from xorg to xrdp */
static int
xorg_process_message(struct xorgxrdp_info *xi, struct stream *s)
{
int type;
int num;
int size;
int index;
char *phold;
char *endhold;
int width;
int height;
int magic;
int con_id;
int mon_id;
int ret;
xi->shmem_fd_ret = -1;
in_uint16_le(s, type);
in_uint16_le(s, num);
in_uint32_le(s, size);
if (type == 3)
{
for (index = 0; index < num; index++)
{
phold = s->p;
in_uint16_le(s, type);
in_uint16_le(s, size);
endhold = s->end;
s->end = phold + size;
switch (type)
{
case 62:
/* process_server_egfx_shmfd */
if (xorg_process_message_62(xi, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xorg_process_message: "
"xorg_process_message_62 failed");
return 1;
}
break;
case 63:
/* process_server_set_pointer_shmfd */
if (xorg_process_message_63(xi, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xorg_process_message: "
"xorg_process_message_63 failed");
return 1;
}
break;
case 64:
/* process_server_paint_rect_shmfd */
if (xorg_process_message_64(xi, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xorg_process_message: "
"xorg_process_message_64 failed");
return 1;
}
break;
}
s->p = phold + size;
s->end = endhold;
}
}
else if (type == 100)
{
for (index = 0; index < num; index++)
{
phold = s->p;
in_uint16_le(s, type);
in_uint16_le(s, size);
LOG(LOG_LEVEL_DEBUG, "100 type %d size %d", type, size);
switch (type)
{
case 1:
LOG(LOG_LEVEL_DEBUG, "calling xrdp_accel_assist_x11_delete_all_pixmaps");
xrdp_accel_assist_x11_delete_all_pixmaps();
break;
case 2:
in_uint16_le(s, width);
in_uint16_le(s, height);
in_uint32_le(s, magic);
in_uint32_le(s, con_id);
in_uint32_le(s, mon_id);
LOG(LOG_LEVEL_DEBUG, "calling xrdp_accel_assist_x11_create_pixmap");
xrdp_accel_assist_x11_create_pixmap(width, height, magic,
con_id, mon_id);
break;
}
s->p = phold + size;
}
/* this will force I frames for 10 frames */
xi->idr_count = 10;
LOG(LOG_LEVEL_INFO, "setting idr_count to %d", xi->idr_count);
}
s->p = s->data;
if (xi->shmem_fd_ret == -1)
{
/* no shared memory, ok */
ret = trans_write_copy_s(xi->xrdp_trans, s);
return ret;
}
/* using posix shared memory, got to pass fd on to xrdp */
ret = trans_force_write_s(xi->xrdp_trans, s);
if (ret)
{
return ret;
}
ret = g_sck_send_fd_set(xi->xrdp_trans->sck, "int", 4,
&(xi->shmem_fd_ret), 1);
if (ret < 0)
{
return 1;
}
g_file_close(xi->shmem_fd_ret);
return 0;
}
/*****************************************************************************/
static int
xorg_data_in(struct trans *trans)
{
struct stream *s;
int len;
struct xorgxrdp_info *xi;
xi = (struct xorgxrdp_info *) (trans->callback_data);
s = trans_get_in_s(trans);
switch (trans->extra_flags)
{
case 1:
s->p = s->data;
in_uint8s(s, 4);
in_uint32_le(s, len);
if ((len < 0) || (len > 128 * 1024))
{
LOG(LOG_LEVEL_ERROR, "bad size %d", len);
return 1;
}
if (len > 0)
{
trans->header_size = len + 8;
trans->extra_flags = 2;
break;
}
/* fall through */
case 2:
s->p = s->data;
if (xorg_process_message(xi, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xorg_process_message failed");
return 1;
}
init_stream(s, 0);
trans->header_size = 8;
trans->extra_flags = 1;
break;
}
return 0;
}
/*****************************************************************************/
/* data going from xrdp to xorg */
static int
xrdp_process_message(struct xorgxrdp_info *xi, struct stream *s)
{
int len;
int msg_type1;
int msg_type2;
in_uint32_le(s, len);
in_uint16_le(s, msg_type1);
if (msg_type1 == 103) /* client message */
{
in_uint32_le(s, msg_type2);
if (msg_type2 == 200) /* invalidate */
{
LOG(LOG_LEVEL_DEBUG, "Invalidate found (len: %d, msg1: %d, msg2: %d)", len, msg_type1, msg_type2);
}
else if (msg_type2 == 300) /* resize */
{
LOG(LOG_LEVEL_DEBUG, "Resize 300 found (len: %d, msg1: %d, msg2: %d)", len, msg_type1, msg_type2);
}
else if (msg_type2 == 302) /* resize */
{
LOG(LOG_LEVEL_DEBUG, "Resize 302 found (len: %d, msg1: %d, msg2: %d)", len, msg_type1, msg_type2);
}
}
/* Reset read pointer */
s->p = s->data;
return trans_write_copy_s(xi->xorg_trans, s);
}
/*****************************************************************************/
static int
xrdp_data_in(struct trans *trans)
{
struct stream *s;
int len;
struct xorgxrdp_info *xi;
xi = (struct xorgxrdp_info *) (trans->callback_data);
s = trans_get_in_s(trans);
switch (trans->extra_flags)
{
case 1:
s->p = s->data;
in_uint32_le(s, len);
if ((len < 0) || (len > 128 * 1024))
{
LOG(LOG_LEVEL_ERROR, "bad size %d", len);
return 1;
}
if (len > 0)
{
trans->header_size = len;
trans->extra_flags = 2;
break;
}
/* fall through */
case 2:
s->p = s->data;
if (xrdp_process_message(xi, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_process_message failed");
return 1;
}
init_stream(s, 0);
trans->header_size = 4;
trans->extra_flags = 1;
break;
}
return 0;
}
/*****************************************************************************/
static void
sigpipe_func(int sig)
{
(void) sig;
}
/*****************************************************************************/
static int
get_log_path(char *path, int bytes)
{
char *log_path;
int rv;
rv = 1;
log_path = g_getenv("XRDP_ACCEL_ASSIST_LOG_PATH");
if (log_path == 0)
{
log_path = g_getenv("XDG_DATA_HOME");
if (log_path != 0)
{
g_snprintf(path, bytes, "%s%s", log_path, "/xrdp");
if (g_directory_exist(path) || (g_mkdir(path) == 0))
{
rv = 0;
}
}
}
else
{
g_snprintf(path, bytes, "%s", log_path);
if (g_directory_exist(path) || (g_mkdir(path) == 0))
{
rv = 0;
}
}
if (rv != 0)
{
log_path = g_getenv("HOME");
if (log_path != 0)
{
g_snprintf(path, bytes, "%s%s", log_path, "/.local");
if (g_directory_exist(path) || (g_mkdir(path) == 0))
{
g_snprintf(path, bytes, "%s%s", log_path, "/.local/share");
if (g_directory_exist(path) || (g_mkdir(path) == 0))
{
g_snprintf(path, bytes, "%s%s", log_path, "/.local/share/xrdp");
if (g_directory_exist(path) || (g_mkdir(path) == 0))
{
rv = 0;
}
}
}
}
}
return rv;
}
/*****************************************************************************/
static enum logLevels
get_log_level(const char *level_str, enum logLevels default_level)
{
static const char *levels[] = {
"LOG_LEVEL_ALWAYS",
"LOG_LEVEL_ERROR",
"LOG_LEVEL_WARNING",
"LOG_LEVEL_INFO",
"LOG_LEVEL_DEBUG",
"LOG_LEVEL_TRACE"
};
unsigned int i;
if (level_str == NULL || level_str[0] == 0)
{
return default_level;
}
for (i = 0; i < ARRAYSIZE(levels); ++i)
{
if (g_strcasecmp(levels[i], level_str) == 0)
{
return (enum logLevels) i;
}
}
return default_level;
}
/*****************************************************************************/
static int
get_display_num_from_display(char *display_text)
{
int index;
int mode;
int host_index;
int disp_index;
int scre_index;
char host[256];
char disp[256];
char scre[256];
g_memset(host, 0, 256);
g_memset(disp, 0, 256);
g_memset(scre, 0, 256);
index = 0;
host_index = 0;
disp_index = 0;
scre_index = 0;
mode = 0;
while (display_text[index] != 0)
{
if (display_text[index] == ':')
{
mode = 1;
}
else if (display_text[index] == '.')
{
mode = 2;
}
else if (mode == 0)
{
host[host_index] = display_text[index];
host_index++;
}
else if (mode == 1)
{
disp[disp_index] = display_text[index];
disp_index++;
}
else if (mode == 2)
{
scre[scre_index] = display_text[index];
scre_index++;
}
index++;
}
host[host_index] = 0;
disp[disp_index] = 0;
scre[scre_index] = 0;
g_display_num = g_atoi(disp);
return 0;
}
/*****************************************************************************/
static int
xrdp_accel_assist_setup_log(void)
{
struct log_config logconfig;
enum logLevels log_level;
char log_path[256];
char log_file[256];
char *display_text;
int error;
if (get_log_path(log_path, 255) != 0)
{
g_writeln("error reading XRDP_ACCEL_ASSIST_LOG_PATH and HOME "
"environment variable");
g_deinit();
return 1;
}
display_text = g_getenv("DISPLAY");
if (display_text != NULL)
{
get_display_num_from_display(display_text);
}
g_snprintf(log_file, 255, "%s/xrdp-accel-assist.%d.log", log_path,
g_display_num);
g_writeln("xrdp-accel-assist::xrdp_accel_assist_setup_log: using "
"log file [%s]", log_file);
if (g_file_exist(log_file))
{
g_file_delete(log_file);
}
log_level = get_log_level(g_getenv("XRDP_ACCEL_ASSIST_LOG_LEVEL"),
LOG_LEVEL_INFO);
logconfig.log_file = log_file;
logconfig.fd = -1;
logconfig.log_level = log_level;
logconfig.enable_syslog = 0;
logconfig.syslog_level = LOG_LEVEL_ALWAYS;
logconfig.program_name = "xrdp_accel_assist";
logconfig.enable_console = 0;
logconfig.enable_pid = 1;
#ifdef LOG_PER_LOGGER_LEVEL
logconfig.per_logger_level = NULL;
#endif
error = log_start_from_param(&logconfig);
return error;
}
/*****************************************************************************/
int
main(int argc, char **argv)
{
int xorg_fd;
int xrdp_fd;
int error;
intptr_t robjs[16];
int robj_count;
intptr_t wobjs[16];
int wobj_count;
int timeout;
struct xorgxrdp_info xi;
if (argc < 2)
{
g_writeln("need to pass -d");
return 0;
}
if (strcmp(argv[1], "-d") != 0)
{
g_writeln("need to pass -d");
return 0;
}
g_init("xrdp_accel_assist");
if (xrdp_accel_assist_setup_log() != 0)
{
return 1;
}
LOG(LOG_LEVEL_INFO, "startup");
g_memset(&xi, 0, sizeof(xi));
g_signal_pipe(sigpipe_func);
if (xrdp_accel_assist_x11_init() != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_accel_assist_x11_init failed");
return 1;
}
xorg_fd = g_atoi(g_getenv("XORGXRDP_XORG_FD"));
LOG(LOG_LEVEL_INFO, "xorg_fd: %d", xorg_fd);
xrdp_fd = g_atoi(g_getenv("XORGXRDP_XRDP_FD"));
LOG(LOG_LEVEL_INFO, "xrdp_fd: %d", xrdp_fd);
xi.xorg_trans = trans_create(TRANS_MODE_UNIX, 128 * 1024, 128 * 1024);
xi.xorg_trans->sck = xorg_fd;
xi.xorg_trans->status = TRANS_STATUS_UP;
xi.xorg_trans->trans_data_in = xorg_data_in;
xi.xorg_trans->header_size = 8;
xi.xorg_trans->no_stream_init_on_data_in = 1;
xi.xorg_trans->extra_flags = 1;
xi.xorg_trans->callback_data = &xi;
xi.xorg_trans->si = &(xi.si);
xi.xorg_trans->my_source = XORGXRDP_SOURCE_XORG;
xi.xrdp_trans = trans_create(TRANS_MODE_UNIX, 128 * 1024, 128 * 1024);
xi.xrdp_trans->sck = xrdp_fd;
xi.xrdp_trans->status = TRANS_STATUS_UP;
xi.xrdp_trans->trans_data_in = xrdp_data_in;
xi.xrdp_trans->no_stream_init_on_data_in = 1;
xi.xrdp_trans->header_size = 4;
xi.xrdp_trans->extra_flags = 1;
xi.xrdp_trans->callback_data = &xi;
xi.xrdp_trans->si = &(xi.si);
xi.xrdp_trans->my_source = XORGXRDP_SOURCE_XRDP;
for (;;)
{
robj_count = 0;
wobj_count = 0;
timeout = -1;
error = trans_get_wait_objs_rw(xi.xorg_trans, robjs, &robj_count,
wobjs, &wobj_count, &timeout);
if (error != 0)
{
LOG(LOG_LEVEL_INFO, "trans_get_wait_objs_rw failed");
break;
}
error = trans_get_wait_objs_rw(xi.xrdp_trans, robjs, &robj_count,
wobjs, &wobj_count, &timeout);
if (error != 0)
{
LOG(LOG_LEVEL_INFO, "trans_get_wait_objs_rw failed");
break;
}
error = xrdp_accel_assist_x11_get_wait_objs(robjs, &robj_count);
if (error != 0)
{
LOG(LOG_LEVEL_INFO, "xrdp_accel_assist_x11_get_wait_objs failed");
break;
}
error = g_obj_wait(robjs, robj_count, wobjs, wobj_count, timeout);
if (error != 0)
{
LOG(LOG_LEVEL_INFO, "g_obj_wait failed");
break;
}
error = trans_check_wait_objs(xi.xorg_trans);
if (error != 0)
{
LOG(LOG_LEVEL_INFO, "xorg_trans trans_check_wait_objs failed");
break;
}
error = trans_check_wait_objs(xi.xrdp_trans);
if (error != 0 && error != 10)
{
LOG(LOG_LEVEL_ERROR, "xrdp_trans trans_check_wait_objs failed");
break;
}
error = xrdp_accel_assist_x11_check_wait_objs();
if (error != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_accel_assist_x11_check_wait_objs failed");
break;
}
}
LOG(LOG_LEVEL_INFO, "exit");
return 0;
}