diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 71d84a33..050cde77 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -45,7 +45,8 @@ xrdp_SOURCES = \ xrdp_painter.c \ xrdp_process.c \ xrdp_region.c \ - xrdp_wm.c + xrdp_wm.c \ + xrdp_encoder.c xrdp_LDADD = \ $(top_builddir)/common/libcommon.la \ @@ -70,4 +71,3 @@ xrdppkgdata_DATA = \ sans-10.fv1 \ cursor0.cur \ cursor1.cur - diff --git a/xrdp/xrdp_encoder.c b/xrdp/xrdp_encoder.c new file mode 100644 index 00000000..93544196 --- /dev/null +++ b/xrdp/xrdp_encoder.c @@ -0,0 +1,159 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2004-2014 + * + * 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. + * + * Encoder + */ + +#include "xrdp_encoder.h" +#include "xrdp.h" +#include "thread_calls.h" +#include "fifo.h" + +/** + * Init encoder + * + * @return 0 on success, -1 on failure + *****************************************************************************/ + +int init_xrdp_encoder(struct xrdp_mm *mm) +{ + char buf[1024]; + + g_writeln("xrdp_encoder.c: initing encoder"); + + if (!mm) + return -1; + + /* save mm so thread can access it */ + self = mm; + + /* setup required FIFOs */ + self->fifo_to_proc = fifo_create(); + self->fifo_processed = fifo_create(); + self->mutex = tc_mutex_create(); + + /* setup wait objects for signalling */ + g_snprintf(buf, 1024, "xrdp_encoder_%8.8x", g_getpid()); + self->xrdp_encoder_event = g_create_wait_obj(buf); + + /* create thread to process messages */ + tc_thread_create(proc_enc_msg, 0); + + return 0; +} + +/** + * Deinit xrdp encoder + *****************************************************************************/ + +void deinit_xrdp_encoder() +{ + XRDP_ENC_DATA *enc; + FIFO *fifo; + + g_writeln("xrdp_encoder.c: deiniting encoder"); + + if (!self) + return; + + /* destroy wait objects used for signalling */ + g_delete_wait_obj(self->xrdp_encoder_event); + + /* cleanup fifo_to_proc */ + fifo = self->fifo_to_proc; + if (fifo) + { + while (!fifo_is_empty(fifo)) + { + enc = fifo_remove_item(fifo); + if (!enc) + continue; + + g_free(enc->drects); + g_free(enc->crects); + g_free(enc); + } + + fifo_delete(fifo); + } + + /* cleanup fifo_processed */ + fifo = self->fifo_processed; + if (fifo) + { + while (!fifo_is_empty(fifo)) + { + enc = fifo_remove_item(fifo); + if (!enc) + continue; + + g_free(enc->drects); + g_free(enc->crects); + g_free(enc); + } + + fifo_delete(fifo); + } +} + +void *proc_enc_msg(void *arg) +{ + XRDP_ENC_DATA *enc; + FIFO *fifo_to_proc; + FIFO *fifo_processed; + tbus mutex; + tbus event; + + g_writeln("xrdp_encoder.c: process_enc_msg thread is running"); + + fifo_to_proc = self->fifo_to_proc; + fifo_processed = self->fifo_processed; + mutex = self->mutex; + event = self->xrdp_encoder_event; + + while (1) + { + /* get next msg */ + tc_mutex_lock(mutex); + enc = fifo_remove_item(fifo_to_proc); + tc_mutex_unlock(mutex); + + /* if no msg available, wait for signal */ + if (!enc) + { + g_writeln("###### JAY_TODO: waiting for msg...."); + g_tcp_can_recv(event, 1000); + g_reset_wait_obj(event); + continue; + } + + /* process msg in enc obj */ + g_writeln("###### JAY_TODO: got msg...."); + /* JAY_TODO */ + + /* done with msg */ + tc_mutex_lock(mutex); + fifo_add_item(fifo_processed, enc); + tc_mutex_unlock(mutex); + + /* signal completion */ + g_set_wait_obj(event); + + } /* end while (1) */ + + return 0; +} diff --git a/xrdp/xrdp_encoder.h b/xrdp/xrdp_encoder.h new file mode 100644 index 00000000..c538a378 --- /dev/null +++ b/xrdp/xrdp_encoder.h @@ -0,0 +1,10 @@ +#ifndef _XRDP_ENCODER_H +#define _XRDP_ENCODER_H + +struct xrdp_mm *self; + +int init_xrdp_encoder(struct xrdp_mm *mm); +void deinit_xrdp_encoder(); +void *proc_enc_msg(void *arg); + +#endif diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index b56b0168..61bb3c31 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -40,6 +40,10 @@ xrdp_mm_create(struct xrdp_wm *owner) self->login_names->auto_free = 1; self->login_values = list_create(); self->login_values->auto_free = 1; + + /* setup thread to handle codec mode messages */ + init_xrdp_encoder(self); + return self; } @@ -1875,6 +1879,11 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self, } } + if (self->in_codec_mode) + { + read_objs[(*rcount)++] = self->xrdp_encoder_event; + } + return rv; } @@ -1931,6 +1940,35 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self) self->delete_chan_trans = 0; } + if (self->in_codec_mode) + { + XRDP_ENC_DATA *enc; + + if (!g_is_wait_obj_set(self->xrdp_encoder_event)) + return rv; + + g_reset_wait_obj(self->xrdp_encoder_event); + tc_mutex_lock(self->mutex); + + while ((enc = fifo_remove_item(self->fifo_processed)) != 0) + { + tc_mutex_unlock(self->mutex); + + /* do something with msg */ + + /* JAY_TODO */ + + /* free enc */ + g_free(enc->drects); + g_free(enc->crects); + g_free(enc); + + tc_mutex_lock(self->mutex); + } + + tc_mutex_unlock(self->mutex); + } + return rv; } @@ -2140,17 +2178,68 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, /*****************************************************************************/ int DEFAULT_CC server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, - int num_crects, short *crects, - char *data, int width, int height, int flags) + int num_crects, short *crects, char *data, int width, + int height, int flags) { struct xrdp_wm* wm; + struct xrdp_mm* mm; struct xrdp_painter* p; struct xrdp_bitmap *b; short *s; int index; + int is_empty; + + wm = (struct xrdp_wm*)(mod->wm); + mm = wm->mm; + + if (mm->in_codec_mode) + { + /* copy formal params to XRDP_ENC_DATA */ + XRDP_ENC_DATA *enc_data = (XRDP_ENC_DATA *) g_malloc(sizeof(XRDP_ENC_DATA), 0); + if (!enc_data) + return 1; + + enc_data->drects = g_malloc(sizeof(short) * num_drects * 4, 0); + if (!enc_data->drects) + { + g_free(enc_data); + return 1; + } + + enc_data->crects = g_malloc(sizeof(short) * num_crects * 4, 0); + if (!enc_data->crects) + { + g_free(enc_data); + g_free(enc_data->drects); + return 1; + } + + g_memcpy(enc_data->drects, drects, sizeof(short) * num_drects * 4); + g_memcpy(enc_data->crects, crects, sizeof(short) * num_crects * 4); + + enc_data->mod = mod; + enc_data->num_drects = num_drects; + enc_data->num_crects = num_crects; + enc_data->data = data; + enc_data->width = width; + enc_data->height = height; + enc_data->flags = flags; + + /* insert into fifo for encoder thread to process */ + tc_mutex_lock(mm->mutex); + is_empty = fifo_is_empty(mm->fifo_to_proc); + fifo_add_item(mm->fifo_to_proc, (void *) enc_data); + tc_mutex_unlock(mm->mutex); + + /* signal xrdp_encoder thread */ + if (is_empty) + g_set_wait_obj(mm->xrdp_encoder_event); + + return 0; + } //g_writeln("server_paint_rects:"); - wm = (struct xrdp_wm*)(mod->wm); + p = (struct xrdp_painter*)(mod->painter); if (p == 0) { diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index b345e36c..b824f176 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -26,6 +26,7 @@ #include "xrdp_rail.h" #include "xrdp_constants.h" +#include "fifo.h" #define MAX_NR_CHANNELS 16 #define MAX_CHANNEL_NAME 16 @@ -262,12 +263,19 @@ struct xrdp_mm int (*mod_exit)(struct xrdp_mod*); struct xrdp_mod* mod; /* module interface */ int display; /* 10 for :10.0, 11 for :11.0, etc */ - int code; /* 0 Xvnc session 10 X11rdp session */ + int code; /* 0=Xvnc session, 10=X11rdp session, 20=xorg driver mode */ int sesman_controlled; /* true if this is a sesman session */ struct trans* chan_trans; /* connection to chansrv */ int chan_trans_up; /* true once connected to chansrv */ int delete_chan_trans; /* boolean set when done with channel connection */ int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */ + + /* for codec mode operations */ + int in_codec_mode; + tbus xrdp_encoder_event; + FIFO *fifo_to_proc; + FIFO *fifo_processed; + tbus mutex; }; struct xrdp_key_info @@ -581,4 +589,20 @@ struct xrdp_config struct xrdp_cfg_channels cfg_channels; }; +/* used when scheduling tasks in xrdp_encoder.c */ +struct xrdp_enc_data +{ + struct xrdp_mod *mod; + int num_drects; + short *drects; /* 4 * num_drects */ + int num_crects; + short *crects; /* 4 * num_crects */ + char *data; + int width; + int height; + int flags; +}; + +typedef struct xrdp_enc_data XRDP_ENC_DATA; + #endif