summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/man/sesman.ini.5.in7
-rw-r--r--libxrdp/libxrdp.c87
-rw-r--r--libxrdp/libxrdp.h34
-rw-r--r--libxrdp/libxrdpinc.h24
-rw-r--r--libxrdp/xrdp_channel.c649
-rw-r--r--libxrdp/xrdp_rdp.c1
-rw-r--r--libxrdp/xrdp_sec.c45
-rw-r--r--sesman/chansrv/Makefile.am2
-rw-r--r--sesman/chansrv/chansrv.c1251
-rw-r--r--sesman/chansrv/chansrv.h49
-rw-r--r--sesman/chansrv/drdynvc.c531
-rw-r--r--sesman/chansrv/drdynvc.h67
-rw-r--r--sesman/sesman.ini.in6
-rw-r--r--xrdp/xrdp.h4
-rw-r--r--xrdp/xrdp_mm.c739
-rw-r--r--xrdp/xrdp_types.h4
-rw-r--r--xrdp/xrdp_wm.c102
-rw-r--r--xrdpapi/xrdpapi.c269
18 files changed, 2227 insertions, 1644 deletions
diff --git a/docs/man/sesman.ini.5.in b/docs/man/sesman.ini.5.in
index 4fad8eb4..2074985c 100644
--- a/docs/man/sesman.ini.5.in
+++ b/docs/man/sesman.ini.5.in
@@ -140,6 +140,13 @@ 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
for the combination <User,BitPerPixel> when using Xrdp, and
diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c
index 99da37f8..2720fab2 100644
--- a/libxrdp/libxrdp.c
+++ b/libxrdp/libxrdp.c
@@ -1264,6 +1264,93 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
}
/*****************************************************************************/
+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,
int width, int height, int bpp, int type,
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
index 0ac5f635..98c8f030 100644
--- a/libxrdp/libxrdp.h
+++ b/libxrdp/libxrdp.h
@@ -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 *
diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h
index 38bd4b34..c236bec9 100644
--- a/libxrdp/libxrdpinc.h
+++ b/libxrdp/libxrdpinc.h
@@ -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);
diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c
index 4f4f3ef3..9662582e 100644
--- a/libxrdp/xrdp_channel.c
+++ b/libxrdp/xrdp_channel.c
@@ -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);
@@ -176,6 +194,333 @@ xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s,
}
/*****************************************************************************/
+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
channel packet.
@@ -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;
+}
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
index 099cec47..494d23e8 100644
--- a/libxrdp/xrdp_rdp.c
+++ b/libxrdp/xrdp_rdp.c
@@ -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"));
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index 0436edf2..2fbad018 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -1840,57 +1840,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)
+ in_uint32_le(s, channel_item->flags);
+ 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
{
- 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));
}
-
return 0;
}
diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am
index 35273283..05007757 100644
--- a/sesman/chansrv/Makefile.am
+++ b/sesman/chansrv/Makefile.am
@@ -56,8 +56,6 @@ xrdp_chansrv_SOURCES = \
clipboard_file.h \
devredir.c \
devredir.h \
- drdynvc.c \
- drdynvc.h \
fifo.c \
fifo.h \
irp.c \
diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c
index 6ec05e53..7a0de556 100644
--- a/sesman/chansrv/chansrv.c
+++ b/sesman/chansrv/chansrv.c
@@ -36,7 +36,6 @@
#include "rail.h"
#include "xcommon.h"
#include "chansrv_fuse.h"
-#include "drdynvc.h"
#include "xrdp_sockets.h"
static struct trans *g_lis_trans = 0;
@@ -49,25 +48,17 @@ static int g_cliprdr_index = -1;
static int g_rdpsnd_index = -1;
static int g_rdpdr_index = -1;
static int g_rail_index = -1;
-static int g_drdynvc_index = -1;
-
-/* state info for dynamic virtual channels */
-static struct xrdp_api_data *g_dvc_channels[MAX_DVC_CHANNELS];
static tbus g_term_event = 0;
static tbus g_thread_done_event = 0;
static int g_use_unix_socket = 0;
-static const unsigned char g_xrdpapi_magic[12] =
-{ 0x78, 0x32, 0x10, 0x67, 0x00, 0x92, 0x30, 0x56, 0xff, 0xd8, 0xa9, 0x1f };
-
int g_display_num = 0;
int g_cliprdr_chan_id = -1; /* cliprdr */
int g_rdpsnd_chan_id = -1; /* rdpsnd */
int g_rdpdr_chan_id = -1; /* rdpdr */
int g_rail_chan_id = -1; /* rail */
-int g_drdynvc_chan_id = -1; /* drdynvc */
char *g_exec_name;
tbus g_exec_event;
@@ -76,10 +67,36 @@ tbus g_exec_sem;
int g_exec_pid = 0;
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
+/* max total channel bytes size */
+#define MAX_CHANNEL_BYTES (1 * 1024 * 1024 * 1024) /* 1 GB */
+#define MAX_CHANNEL_FRAG_BYTES 1600
+
+#define CHANSRV_DRDYNVC_STATUS_CLOSED 0
+#define CHANSRV_DRDYNVC_STATUS_OPEN_SENT 1
+#define CHANSRV_DRDYNVC_STATUS_OPEN 2
+#define CHANSRV_DRDYNVC_STATUS_CLOSE_SENT 3
+
+struct chansrv_drdynvc
+{
+ int chan_id;
+ int status; /* see CHANSRV_DRDYNVC_STATUS_* */
+ int flags;
+ int pad0;
+ 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);
+ struct trans *xrdp_api_trans;
+};
+
+static struct chansrv_drdynvc g_drdynvcs[256];
-/* each time we create a DVC we need a unique DVC channel id */
-/* this variable gets bumped up once per DVC we create */
-tui32 g_dvc_chan_id = 100;
+/* data in struct trans::callback_data */
+struct xrdp_api_data
+{
+ int chan_flags;
+ int chan_id;
+};
struct timeout_obj
{
@@ -226,151 +243,60 @@ g_is_term(void)
}
/*****************************************************************************/
-/* add data to chan_item, on its way to the client */
-/* returns error */
-static int
-add_data_to_chan_item(struct chan_item *chan_item, char *data, int size)
-{
- struct stream *s;
- struct chan_out_data *cod;
-
- make_stream(s);
- init_stream(s, size);
- g_memcpy(s->data, data, size);
- s->end = s->data + size;
- cod = (struct chan_out_data *)g_malloc(sizeof(struct chan_out_data), 1);
- cod->s = s;
-
- if (chan_item->tail == 0)
- {
- chan_item->tail = cod;
- chan_item->head = cod;
- }
- else
- {
- chan_item->tail->next = cod;
- chan_item->tail = cod;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
+/* send data to a static virtual channel
+ size can be > MAX_CHANNEL_FRAG_BYTES, in which case, > 1 message
+ will be sent*/
/* returns error */
-static int
-send_data_from_chan_item(struct chan_item *chan_item)
+int
+send_channel_data(int chan_id, const char *data, int size)
{
- struct stream *s;
- struct chan_out_data *cod;
- int bytes_left;
- int size;
+ int sending_bytes;
int chan_flags;
int error;
+ int total_size;
+ struct stream *s;
- if (chan_item->head == 0)
- {
- return 0;
- }
-
- cod = chan_item->head;
- bytes_left = (int)(cod->s->end - cod->s->p);
- size = MIN(1600, bytes_left);
- chan_flags = 0;
-
- if (cod->s->p == cod->s->data)
- {
- chan_flags |= 1; /* first */
- }
-
- if (cod->s->p + size >= cod->s->end)
- {
- chan_flags |= 2; /* last */
- }
-
- s = trans_get_out_s(g_con_trans, 8192);
- out_uint32_le(s, 0); /* version */
- out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */
- out_uint32_le(s, 8); /* msg id */
- out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */
- out_uint16_le(s, chan_item->id);
- out_uint16_le(s, chan_flags);
- out_uint16_le(s, size);
- out_uint32_le(s, cod->s->size);
- out_uint8a(s, cod->s->p, size);
- s_mark_end(s);
- LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- "
- "size %d chan_flags 0x%8.8x", size, chan_flags));
-
- error = trans_write_copy(g_con_trans);
- if (error != 0)
+ if ((chan_id < 0) || (chan_id > 31) ||
+ (data == NULL) ||
+ (size < 1) || (size > MAX_CHANNEL_BYTES))
{
+ /* bad param */
return 1;
}
-
- cod->s->p += size;
-
- if (cod->s->p >= cod->s->end)
+ total_size = size;
+ chan_flags = 1; /* first */
+ while (size > 0)
{
- free_stream(cod->s);
- chan_item->head = chan_item->head->next;
-
- if (chan_item->head == 0)
+ sending_bytes = MIN(MAX_CHANNEL_FRAG_BYTES, size);
+ if (sending_bytes >= size)
{
- chan_item->tail = 0;
+ chan_flags |= 2; /* last */
}
-
- g_free(cod);
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-/* returns error */
-static int
-check_chan_items(void)
-{
- int index;
-
- for (index = 0; index < g_num_chan_items; index++)
- {
- if (g_chan_items[index].head != 0)
+ s = trans_get_out_s(g_con_trans, 26 + sending_bytes);
+ if (s == NULL)
{
- send_data_from_chan_item(g_chan_items + index);
+ return 2;
}
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-/* returns error */
-int
-send_channel_data(int chan_id, char *data, int size)
-{
- int index;
-
- //g_writeln("send_channel_data chan_id %d size %d", chan_id, size);
-
- LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: size %d", size));
-
- if (chan_id == -1)
- {
- g_writeln("send_channel_data: error, chan_id is -1");
- return 1;
- }
-
- for (index = 0; index < g_num_chan_items; index++)
- {
- if (g_chan_items[index].id == chan_id)
+ out_uint32_le(s, 0); /* version */
+ out_uint32_le(s, 26 + sending_bytes);
+ out_uint32_le(s, 8); /* msg id */
+ out_uint32_le(s, 18 + sending_bytes);
+ out_uint16_le(s, chan_id);
+ out_uint16_le(s, chan_flags);
+ out_uint16_le(s, sending_bytes);
+ out_uint32_le(s, total_size);
+ out_uint8a(s, data, sending_bytes);
+ s_mark_end(s);
+ size -= sending_bytes;
+ data += sending_bytes;
+ error = trans_write_copy(g_con_trans);
+ if (error != 0)
{
- add_data_to_chan_item(g_chan_items + index, data, size);
- check_chan_items();
- return 0;
+ return 3;
}
+ chan_flags = 0;
}
-
- return 1;
+ return 0;
}
/*****************************************************************************/
@@ -401,92 +327,12 @@ send_rail_drawing_orders(char* data, int size)
/*****************************************************************************/
/* returns error */
static int
-send_init_response_message(void)
-{
- struct stream *s = (struct stream *)NULL;
-
- LOGM((LOG_LEVEL_INFO, "send_init_response_message:"));
- s = trans_get_out_s(g_con_trans, 8192);
-
- if (s == 0)
- {
- return 1;
- }
-
- out_uint32_le(s, 0); /* version */
- out_uint32_le(s, 8 + 8); /* size */
- out_uint32_le(s, 2); /* msg id */
- out_uint32_le(s, 8); /* size */
- s_mark_end(s);
- return trans_write_copy(g_con_trans);
-}
-
-/*****************************************************************************/
-/* returns error */
-static int
-send_channel_setup_response_message(void)
-{
- struct stream *s = (struct stream *)NULL;
-
- LOGM((LOG_LEVEL_DEBUG, "send_channel_setup_response_message:"));
- s = trans_get_out_s(g_con_trans, 8192);
-
- if (s == 0)
- {
- return 1;
- }
-
- out_uint32_le(s, 0); /* version */
- out_uint32_le(s, 8 + 8); /* size */
- out_uint32_le(s, 4); /* msg id */
- out_uint32_le(s, 8); /* size */
- s_mark_end(s);
- return trans_write_copy(g_con_trans);
-}
-
-/*****************************************************************************/
-/* returns error */
-static int
-send_channel_data_response_message(void)
-{
- struct stream *s = (struct stream *)NULL;
-
- LOGM((LOG_LEVEL_DEBUG, "send_channel_data_response_message:"));
- s = trans_get_out_s(g_con_trans, 8192);
-
- if (s == 0)
- {
- return 1;
- }
-
- out_uint32_le(s, 0); /* version */
- out_uint32_le(s, 8 + 8); /* size */
- out_uint32_le(s, 6); /* msg id */
- out_uint32_le(s, 8); /* size */
- s_mark_end(s);
- return trans_write_copy(g_con_trans);
-}
-
-/*****************************************************************************/
-/* returns error */
-static int
-process_message_init(struct stream *s)
-{
- LOGM((LOG_LEVEL_DEBUG, "process_message_init:"));
- return send_init_response_message();
-}
-
-/*****************************************************************************/
-/* returns error */
-static int
process_message_channel_setup(struct stream *s)
{
int num_chans;
int index;
int rv;
struct chan_item *ci;
- struct chan_out_data *cod;
- struct chan_out_data *old_cod;
g_num_chan_items = 0;
g_cliprdr_index = -1;
@@ -497,7 +343,6 @@ process_message_channel_setup(struct stream *s)
g_rdpsnd_chan_id = -1;
g_rdpdr_chan_id = -1;
g_rail_chan_id = -1;
- g_drdynvc_chan_id = -1;
LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup:"));
in_uint16_le(s, num_chans);
LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: num_chans %d",
@@ -509,25 +354,6 @@ process_message_channel_setup(struct stream *s)
g_memset(ci->name, 0, sizeof(ci->name));
in_uint8a(s, ci->name, 8);
in_uint16_le(s, ci->id);
- /* there might be leftover data from last session after reconnecting
- so free it */
- if (ci->head != 0)
- {
- cod = ci->head;
- while (1)
- {
- free_stream(cod->s);
- old_cod = cod;
- cod = cod->next;
- g_free(old_cod);
- if (ci->tail == old_cod)
- {
- break;
- }
- }
- }
- ci->head = 0;
- ci->tail = 0;
in_uint16_le(s, ci->flags);
LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: chan name '%s' "
"id %d flags %8.8x", ci->name, ci->id, ci->flags));
@@ -556,11 +382,6 @@ process_message_channel_setup(struct stream *s)
g_rail_index = g_num_chan_items;
g_rail_chan_id = ci->id;
}
- else if (g_strcasecmp(ci->name, "drdynvc") == 0)
- {
- g_drdynvc_index = g_num_chan_items; // LK_TODO use this
- g_drdynvc_chan_id = ci->id; // LK_TODO use this
- }
else
{
LOG(10, ("other %s", ci->name));
@@ -569,7 +390,7 @@ process_message_channel_setup(struct stream *s)
g_num_chan_items++;
}
- rv = send_channel_setup_response_message();
+ rv = 0;
if (g_cliprdr_index >= 0)
{
@@ -593,12 +414,6 @@ process_message_channel_setup(struct stream *s)
rail_init();
}
- if (g_drdynvc_index >= 0)
- {
- g_memset(&g_dvc_channels[0], 0, sizeof(g_dvc_channels));
- drdynvc_init();
- }
-
return rv;
}
@@ -607,12 +422,13 @@ process_message_channel_setup(struct stream *s)
static int
process_message_channel_data(struct stream *s)
{
- int chan_id = 0;
- int chan_flags = 0;
- int rv = 0;
- int length = 0;
- int total_length = 0;
+ int chan_id;
+ int chan_flags;
+ int rv;
+ int length;
+ int total_length;
int index;
+ int found;
struct stream *ls;
struct trans *ltran;
struct xrdp_api_data *api_data;
@@ -624,7 +440,7 @@ process_message_channel_data(struct stream *s)
LOGM((LOG_LEVEL_DEBUG, "process_message_channel_data: chan_id %d "
"chan_flags %d", chan_id, chan_flags));
LOG(10, ("process_message_channel_data"));
- rv = send_channel_data_response_message();
+ rv = 0;
if (rv == 0)
{
@@ -644,22 +460,20 @@ process_message_channel_data(struct stream *s)
{
rv = rail_data_in(s, chan_id, chan_flags, length, total_length);
}
- else if (chan_id == g_drdynvc_chan_id)
- {
- rv = drdynvc_data_in(s, chan_id, chan_flags, length, total_length);
- }
- else if (g_api_con_trans_list != 0)
+ else
{
+ found = 0;
for (index = 0; index < g_api_con_trans_list->count; index++)
{
ltran = (struct trans *) list_get_item(g_api_con_trans_list, index);
- if (ltran != 0)
+ if (ltran != NULL)
{
api_data = (struct xrdp_api_data *) (ltran->callback_data);
- if (api_data != 0)
+ if (api_data != NULL)
{
if (api_data->chan_id == chan_id)
{
+ found = 1;
ls = ltran->out_s;
if (chan_flags & 1) /* first */
{
@@ -669,25 +483,333 @@ process_message_channel_data(struct stream *s)
if (chan_flags & 2) /* last */
{
s_mark_end(ls);
- rv = trans_force_write(ltran);
+ rv = trans_write_copy(ltran);
}
break;
}
}
}
}
+ if (found == 0)
+ {
+ LOG(0, ("process_message_channel_data: not found channel %d", chan_id));
+ }
}
+
}
return rv;
}
/*****************************************************************************/
/* returns error */
+/* open response from client */
+static int
+process_message_drdynvc_open_response(struct stream *s)
+{
+ struct chansrv_drdynvc *drdynvc;
+ int chan_id;
+ int creation_status;
+
+ LOG(10, ("process_message_drdynvc_open_response:"));
+ if (!s_check_rem(s, 8))
+ {
+ return 1;
+ }
+ in_uint32_le(s, chan_id);
+ in_uint32_le(s, creation_status);
+ if ((chan_id < 0) || (chan_id > 255))
+ {
+ return 1;
+ }
+ drdynvc = g_drdynvcs + chan_id;
+ if (drdynvc->status != CHANSRV_DRDYNVC_STATUS_OPEN_SENT)
+ {
+ g_writeln("process_message_drdynvc_open_response: status not right");
+ return 1;
+ }
+ if (creation_status == 0)
+ {
+ drdynvc->status = CHANSRV_DRDYNVC_STATUS_OPEN;
+ }
+ else
+ {
+ drdynvc->status = CHANSRV_DRDYNVC_STATUS_CLOSED;
+ }
+ if (drdynvc->open_response != NULL)
+ {
+ if (drdynvc->open_response(chan_id, creation_status) != 0)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* close response from client */
static int
-process_message_channel_data_response(struct stream *s)
+process_message_drdynvc_close_response(struct stream *s)
{
- LOG(10, ("process_message_channel_data_response:"));
- check_chan_items();
+ struct chansrv_drdynvc *drdynvc;
+ int chan_id;
+
+ LOG(10, ("process_message_drdynvc_close_response:"));
+ if (!s_check_rem(s, 4))
+ {
+ return 1;
+ }
+ in_uint32_le(s, chan_id);
+ if ((chan_id < 0) || (chan_id > 255))
+ {
+ return 1;
+ }
+ drdynvc = g_drdynvcs + chan_id;
+ if (drdynvc->status != CHANSRV_DRDYNVC_STATUS_CLOSE_SENT)
+ {
+ g_writeln("process_message_drdynvc_close_response: status not right");
+ return 0;
+ }
+ drdynvc->status = CHANSRV_DRDYNVC_STATUS_CLOSED;
+ if (drdynvc->close_response != NULL)
+ {
+ if (drdynvc->close_response(chan_id) != 0)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* data from client */
+static int
+process_message_drdynvc_data_first(struct stream *s)
+{
+ struct chansrv_drdynvc *drdynvc;
+ int chan_id;
+ int bytes;
+ int total_bytes;
+ char *data;
+
+ LOG(10, ("process_message_drdynvc_data_first:"));
+ if (!s_check_rem(s, 12))
+ {
+ return 1;
+ }
+ in_uint32_le(s, chan_id);
+ in_uint32_le(s, bytes);
+ in_uint32_le(s, total_bytes);
+ if (!s_check_rem(s, bytes))
+ {
+ return 1;
+ }
+ in_uint8p(s, data, bytes);
+ if ((chan_id < 0) || (chan_id > 255))
+ {
+ return 1;
+ }
+ drdynvc = g_drdynvcs + chan_id;
+ if (drdynvc->data_first != NULL)
+ {
+ if (drdynvc->data_first(chan_id, data, bytes, total_bytes) != 0)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* data from client */
+static int
+process_message_drdynvc_data(struct stream *s)
+{
+ struct chansrv_drdynvc *drdynvc;
+ int chan_id;
+ int bytes;
+ char *data;
+
+ LOG(10, ("process_message_drdynvc_data:"));
+ if (!s_check_rem(s, 8))
+ {
+ return 1;
+ }
+ in_uint32_le(s, chan_id);
+ in_uint32_le(s, bytes);
+ if (!s_check_rem(s, bytes))
+ {
+ return 1;
+ }
+ in_uint8p(s, data, bytes);
+ drdynvc = g_drdynvcs + chan_id;
+ if (drdynvc->data != NULL)
+ {
+ if (drdynvc->data(chan_id, data, bytes) != 0)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* open call from chansrv */
+int
+chansrv_drdynvc_open(const char *name, int flags,
+ struct chansrv_drdynvc_procs *procs, int *chan_id)
+{
+ struct stream *s;
+ int name_bytes;
+ int lchan_id;
+ int error;
+
+ lchan_id = 1;
+ while (g_drdynvcs[lchan_id].status != CHANSRV_DRDYNVC_STATUS_CLOSED)
+ {
+ lchan_id++;
+ if (lchan_id > 255)
+ {
+ return 1;
+ }
+ }
+ s = trans_get_out_s(g_con_trans, 8192);
+ if (s == NULL)
+ {
+ return 1;
+ }
+ name_bytes = g_strlen(name);
+ out_uint32_le(s, 0); /* version */
+ out_uint32_le(s, 8 + 8 + 4 + name_bytes + 4 + 4);
+ out_uint32_le(s, 12); /* msg id */
+ out_uint32_le(s, 8 + 4 + name_bytes + 4 + 4);
+ out_uint32_le(s, name_bytes);
+ out_uint8a(s, name, name_bytes);
+ out_uint32_le(s, flags);
+ out_uint32_le(s, lchan_id);
+ s_mark_end(s);
+ error = trans_write_copy(g_con_trans);
+ if (error == 0)
+ {
+ if (chan_id != NULL)
+ {
+ *chan_id = lchan_id;
+ g_drdynvcs[lchan_id].open_response = procs->open_response;
+ g_drdynvcs[lchan_id].close_response = procs->close_response;
+ g_drdynvcs[lchan_id].data_first = procs->data_first;
+ g_drdynvcs[lchan_id].data = procs->data;
+ g_drdynvcs[lchan_id].status = CHANSRV_DRDYNVC_STATUS_OPEN_SENT;
+
+ }
+ }
+ return error;
+}
+
+/*****************************************************************************/
+/* close call from chansrv */
+int
+chansrv_drdynvc_close(int chan_id)
+{
+ struct stream *s;
+ int error;
+
+ s = trans_get_out_s(g_con_trans, 8192);
+ if (s == NULL)
+ {
+ return 1;
+ }
+ out_uint32_le(s, 0); /* version */
+ out_uint32_le(s, 20);
+ out_uint32_le(s, 14); /* msg id */
+ out_uint32_le(s, 12);
+ out_uint32_le(s, chan_id);
+ s_mark_end(s);
+ error = trans_write_copy(g_con_trans);
+ g_drdynvcs[chan_id].status = CHANSRV_DRDYNVC_STATUS_CLOSE_SENT;
+ return error;
+}
+
+/*****************************************************************************/
+int
+chansrv_drdynvc_data_first(int chan_id, const char *data, int data_bytes,
+ int total_data_bytes)
+{
+ struct stream *s;
+ int error;
+
+ //g_writeln("chansrv_drdynvc_data_first: data_bytes %d total_data_bytes %d",
+ // data_bytes, total_data_bytes);
+ s = trans_get_out_s(g_con_trans, 8192);
+ if (s == NULL)
+ {
+ return 1;
+ }
+ out_uint32_le(s, 0); /* version */
+ out_uint32_le(s, 28 + data_bytes);
+ out_uint32_le(s, 16); /* msg id */
+ out_uint32_le(s, 20 + data_bytes);
+ out_uint32_le(s, chan_id);
+ out_uint32_le(s, data_bytes);
+ out_uint32_le(s, total_data_bytes);
+ out_uint8a(s, data, data_bytes);
+ s_mark_end(s);
+ error = trans_write_copy(g_con_trans);
+ return error;
+}
+
+/*****************************************************************************/
+int
+chansrv_drdynvc_data(int chan_id, const char *data, int data_bytes)
+{
+ struct stream *s;
+ int error;
+
+ //g_writeln("chansrv_drdynvc_data: data_bytes %d", data_bytes);
+ s = trans_get_out_s(g_con_trans, 8192);
+ if (s == NULL)
+ {
+ return 1;
+ }
+ out_uint32_le(s, 0); /* version */
+ out_uint32_le(s, 24 + data_bytes);
+ out_uint32_le(s, 18); /* msg id */
+ out_uint32_le(s, 16 + data_bytes);
+ out_uint32_le(s, chan_id);
+ out_uint32_le(s, data_bytes);
+ out_uint8a(s, data, data_bytes);
+ s_mark_end(s);
+ error = trans_write_copy(g_con_trans);
+ return error;
+}
+
+/*****************************************************************************/
+int
+chansrv_drdynvc_send_data(int chan_id, const char *data, int data_bytes)
+{
+ int this_send_bytes;
+
+ //g_writeln("chansrv_drdynvc_send_data: data_bytes %d", data_bytes);
+ if (data_bytes > 1590)
+ {
+ if (chansrv_drdynvc_data_first(chan_id, data, 1590, data_bytes) != 0)
+ {
+ return 1;
+ }
+ data_bytes -= 1590;
+ data += 1590;
+ }
+ while (data_bytes > 0)
+ {
+ this_send_bytes = MIN(1590, data_bytes);
+ if (chansrv_drdynvc_data(chan_id, data, this_send_bytes) != 0)
+ {
+ return 1;
+ }
+ data_bytes -= this_send_bytes;
+ data += this_send_bytes;
+ }
return 0;
}
@@ -725,17 +847,23 @@ process_message(void)
switch (id)
{
- case 1: /* init */
- rv = process_message_init(s);
- break;
case 3: /* channel setup */
rv = process_message_channel_setup(s);
break;
case 5: /* channel data */
rv = process_message_channel_data(s);
break;
- case 7: /* channel data response */
- rv = process_message_channel_data_response(s);
+ case 13: /* drdynvc open response */
+ rv = process_message_drdynvc_open_response(s);
+ break;
+ case 15: /* drdynvc close response */
+ rv = process_message_drdynvc_close_response(s);
+ break;
+ case 17: /* drdynvc data first */
+ rv = process_message_drdynvc_data_first(s);
+ break;
+ case 19: /* drdynvc data */
+ rv = process_message_drdynvc_data(s);
break;
default:
LOGM((LOG_LEVEL_ERROR, "process_message: unknown msg %d", id));
@@ -744,7 +872,8 @@ process_message(void)
if (rv != 0)
{
- break;
+ g_writeln("process_message: error rv %d id %d", rv, id);
+ rv = 0;
}
s->p = next_msg;
@@ -782,11 +911,119 @@ my_trans_data_in(struct trans *trans)
{
/* here, the entire message block is read in, process it */
error = process_message();
+ if (error == 0)
+ {
+ }
+ else
+ {
+ g_writeln("my_trans_data_in: process_message failed");
+ }
+ }
+ else
+ {
+ g_writeln("my_trans_data_in: trans_force_read failed");
}
return error;
}
+/*****************************************************************************/
+struct trans *
+get_api_trans_from_chan_id(int chan_id)
+{
+ return g_drdynvcs[chan_id].xrdp_api_trans;
+}
+
+/*****************************************************************************/
+static int
+my_api_open_response(int chan_id, int creation_status)
+{
+ struct trans *trans;
+ struct stream *s;
+
+ //g_writeln("my_api_open_response: chan_id %d creation_status %d",
+ // chan_id, creation_status);
+ trans = get_api_trans_from_chan_id(chan_id);
+ if (trans == NULL)
+ {
+ return 1;
+ }
+ s = trans_get_out_s(trans, 8192);
+ if (s == NULL)
+ {
+ return 1;
+ }
+ out_uint32_le(s, creation_status);
+ s_mark_end(s);
+ if (trans_write_copy(trans) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+my_api_close_response(int chan_id)
+{
+ //g_writeln("my_api_close_response:");
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+my_api_data_first(int chan_id, char *data, int bytes, int total_bytes)
+{
+ struct trans *trans;
+ struct stream *s;
+
+ //g_writeln("my_api_data_first: bytes %d total_bytes %d", bytes, total_bytes);
+ trans = get_api_trans_from_chan_id(chan_id);
+ if (trans == NULL)
+ {
+ return 1;
+ }
+ s = trans_get_out_s(trans, bytes);
+ if (s == NULL)
+ {
+ return 1;
+ }
+ out_uint8a(s, data, bytes);
+ s_mark_end(s);
+ if (trans_write_copy(trans) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+my_api_data(int chan_id, char *data, int bytes)
+{
+ struct trans *trans;
+ struct stream *s;
+
+ //g_writeln("my_api_data: bytes %d", bytes);
+ trans = get_api_trans_from_chan_id(chan_id);
+ if (trans == NULL)
+ {
+ return 1;
+ }
+ s = trans_get_out_s(trans, bytes);
+ if (s == NULL)
+ {
+ return 1;
+ }
+ out_uint8a(s, data, bytes);
+ s_mark_end(s);
+ if (trans_write_copy(trans) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
/*
* called when WTSVirtualChannelWrite() is invoked in xrdpapi.c
*
@@ -794,94 +1031,130 @@ my_trans_data_in(struct trans *trans)
int
my_api_trans_data_in(struct trans *trans)
{
- struct stream *s;
- int bytes_read;
- int i32;
+ struct stream *s;
+ struct stream *out_s;
struct xrdp_api_data *ad;
+ int index;
+ int rv;
+ int bytes;
+ int ver;
+ int channel_name_bytes;
+ struct chansrv_drdynvc_procs procs;
+ char *chan_name;
- //g_writeln("my_api_trans_data_in:");
-
- LOG(10, ("my_api_trans_data_in:"));
-
- if (trans == 0)
- {
- return 0;
- }
-
- if (g_api_con_trans_list != 0)
+ //g_writeln("my_api_trans_data_in: extra_flags %d", trans->extra_flags);
+ rv = 0;
+ ad = (struct xrdp_api_data *) (trans->callback_data);
+ s = trans_get_in_s(trans);
+ if (trans->extra_flags == 0)
{
- if (list_index_of(g_api_con_trans_list, (tintptr) trans) == -1)
+ in_uint32_le(s, bytes);
+ in_uint32_le(s, ver);
+ //g_writeln("my_api_trans_data_in: bytes %d ver %d", bytes, ver);
+ if (ver != 0)
{
return 1;
}
+ trans->header_size = bytes;
+ trans->extra_flags = 1;
}
-
- LOGM((LOG_LEVEL_DEBUG, "my_api_trans_data_in:"));
-
- s = trans_get_in_s(trans);
- bytes_read = g_tcp_recv(trans->sck, s->data, 16, 0);
- if (bytes_read == 16)
+ else if (trans->extra_flags == 1)
{
- if (g_memcmp(s->data, g_xrdpapi_magic, 12) == 0)
+ rv = 1;
+ in_uint32_le(s, channel_name_bytes);
+ //g_writeln("my_api_trans_data_in: channel_name_bytes %d", channel_name_bytes);
+ chan_name = g_new0(char, channel_name_bytes + 1);
+ if (chan_name == NULL)
{
- in_uint8s(s, 12);
- in_uint32_le(s, bytes_read);
- init_stream(s, bytes_read);
- if (trans_force_read(trans, bytes_read))
- log_message(LOG_LEVEL_ERROR, "chansrv.c: error reading from transport");
+ return 1;
}
- else if (g_tcp_select(trans->sck, 0) & 1)
+ in_uint8a(s, chan_name, channel_name_bytes);
+ in_uint32_le(s, ad->chan_flags);
+ //g_writeln("my_api_trans_data_in: chan_name %s chan_flags 0x%8.8x", chan_name, ad->chan_flags);
+ if (ad->chan_flags == 0)
{
- i32 = bytes_read;
- bytes_read = g_tcp_recv(trans->sck, s->data + bytes_read,
- 8192 * 4 - bytes_read, 0);
- if (bytes_read > 0)
+ /* SVC */
+ for (index = 0; index < g_num_chan_items; index++)
{
- bytes_read += i32;
+ if (g_strcasecmp(g_chan_items[index].name, chan_name) == 0)
+ {
+ ad->chan_id = g_chan_items[index].id;
+ rv = 0;
+ break;
+ }
}
- }
- }
-
- //g_writeln("bytes_read %d", bytes_read);
-
- if (bytes_read > 0)
- {
- LOG(10, ("my_api_trans_data_in: got data %d", bytes_read));
- ad = (struct xrdp_api_data *) trans->callback_data;
-
- if (ad->dvc_chan_id < 0)
- {
- /* writing data to a static virtual channel */
- if (send_channel_data(ad->chan_id, s->data, bytes_read) != 0)
+ if (rv == 0)
+ {
+ /* open ok */
+ out_s = trans_get_out_s(trans, 8192);
+ if (out_s == NULL)
+ {
+ return 1;
+ }
+ out_uint32_le(out_s, 0);
+ s_mark_end(out_s);
+ if (trans_write_copy(trans) != 0)
+ {
+ return 1;
+ }
+ }
+ else
{
- LOG(0, ("my_api_trans_data_in: send_channel_data failed"));
+ /* open failed */
+ out_s = trans_get_out_s(trans, 8192);
+ if (out_s == NULL)
+ {
+ return 1;
+ }
+ out_uint32_le(out_s, 1);
+ s_mark_end(out_s);
+ if (trans_write_copy(trans) != 0)
+ {
+ return 1;
+ }
}
}
else
{
- /* writing data to a dynamic virtual channel */
- drdynvc_write_data(ad->dvc_chan_id, s->data, bytes_read);
+ /* DVS */
+ g_memset(&procs, 0, sizeof(procs));
+ procs.open_response = my_api_open_response;
+ procs.close_response = my_api_close_response;
+ procs.data_first = my_api_data_first;
+ procs.data = my_api_data;
+ rv = chansrv_drdynvc_open(chan_name, ad->chan_flags,
+ &procs, &(ad->chan_id));
+ //g_writeln("my_api_trans_data_in: chansrv_drdynvc_open rv %d "
+ // "chan_id %d", rv, ad->chan_id);
+ g_drdynvcs[ad->chan_id].xrdp_api_trans = trans;
}
+ g_free(chan_name);
+ init_stream(s, 0);
+ trans->extra_flags = 2;
+ trans->header_size = 0;
}
else
{
- ad = (struct xrdp_api_data *) (trans->callback_data);
- if ((ad != NULL) && (ad->dvc_chan_id > 0))
+ bytes = g_sck_recv(trans->sck, s->data, s->size, 0);
+ if (bytes < 1)
+ {
+ //g_writeln("my_api_trans_data_in: disconnect");
+ return 1;
+ }
+ if (ad->chan_flags == 0)
{
- /* WTSVirtualChannelClose() was invoked, or connection dropped */
- LOG(10, ("my_api_trans_data_in: g_tcp_recv failed or disconnected for DVC"));
- ad->transp = NULL;
- ad->is_connected = 0;
- remove_struct_with_chan_id(ad->dvc_chan_id);
+ /* SVC */
+ rv = send_channel_data(ad->chan_id, s->data, bytes);
}
else
{
- LOG(10, ("my_api_trans_data_in: g_tcp_recv failed or disconnected for SVC"));
+ /* DVS */
+ //g_writeln("my_api_trans_data_in: s->size %d bytes %d", s->size, bytes);
+ rv = chansrv_drdynvc_send_data(ad->chan_id, s->data, bytes);
}
- return 1;
+ init_stream(s, 0);
}
-
- return 0;
+ return rv;
}
/*****************************************************************************/
@@ -926,92 +1199,24 @@ int
my_api_trans_conn_in(struct trans *trans, struct trans *new_trans)
{
struct xrdp_api_data *ad;
- struct stream *s;
- int error;
- int index;
- char chan_pri;
- if ((trans == 0) || (trans != g_api_lis_trans) || (new_trans == 0))
+ //g_writeln("my_api_trans_conn_in:");
+ if ((trans == NULL) || (trans != g_api_lis_trans) || (new_trans == NULL))
{
+ g_writeln("my_api_trans_conn_in: error");
return 1;
}
-
- LOGM((LOG_LEVEL_DEBUG, "my_api_trans_conn_in:"));
- LOG(10, ("my_api_trans_conn_in: got incoming"));
-
- s = trans_get_in_s(new_trans);
- s->end = s->data;
-
- error = trans_force_read(new_trans, 64);
-
- if (error != 0)
+ new_trans->trans_data_in = my_api_trans_data_in;
+ new_trans->header_size = 8;
+ new_trans->no_stream_init_on_data_in = 1;
+ ad = g_new0(struct xrdp_api_data, 1);
+ if (ad == NULL)
{
- LOG(0, ("my_api_trans_conn_in: trans_force_read failed"));
- trans_delete(new_trans);
+ g_writeln("my_api_trans_conn_in: error");
return 1;
}
-
- s->end = s->data;
-
- ad = (struct xrdp_api_data *) g_malloc(sizeof(struct xrdp_api_data), 1);
- g_memcpy(ad->header, s->data, 64);
-
- ad->flags = GGET_UINT32(ad->header, 16);
- ad->chan_id = -1;
- ad->dvc_chan_id = -1;
-
- if (ad->flags > 0)
- {
- /* opening a dynamic virtual channel */
-
- if ((index = find_empty_slot_in_dvc_channels()) < 0)
- {
- /* exceeded MAX_DVC_CHANNELS */
- LOG(0, ("my_api_trans_conn_in: MAX_DVC_CHANNELS reached; giving up!"))
- g_free(ad);
- trans_delete(new_trans);
- return 1;
- }
-
- g_dvc_channels[index] = ad;
- chan_pri = 4 - ad->flags;
- ad->dvc_chan_id = g_dvc_chan_id++;
- ad->is_connected = 0;
- ad->transp = new_trans;
- drdynvc_send_open_channel_request(chan_pri, ad->dvc_chan_id, ad->header);
- }
- else
- {
- /* opening a static virtual channel */
-
- for (index = 0; index < g_num_chan_items; index++)
- {
- LOG(10, ("my_api_trans_conn_in: %s %s", ad->header,
- g_chan_items[index].name));
-
- if (g_strcasecmp(ad->header, g_chan_items[index].name) == 0)
- {
- LOG(10, ("my_api_trans_conn_in: found it at %d", index));
- ad->chan_id = g_chan_items[index].id;
- break;
- }
- }
- if (index == g_num_chan_items)
- {
- g_writeln("did not find SVC named %s", ad->header);
- }
- }
-
new_trans->callback_data = ad;
-
- if (g_api_con_trans_list == 0)
- {
- g_api_con_trans_list = list_create();
- }
- new_trans->trans_data_in = my_api_trans_data_in;
- new_trans->header_size = 0;
- list_add_item(g_api_con_trans_list, (tintptr) new_trans);
-
+ list_add_item(g_api_con_trans_list, (intptr_t) new_trans);
return 0;
}
@@ -1077,6 +1282,96 @@ setup_api_listen(void)
}
/*****************************************************************************/
+static int
+api_con_trans_list_get_wait_objs_rw(intptr_t *robjs, int *rcount,
+ intptr_t *wobjs, int *wcount,
+ int *timeout)
+{
+ int api_con_index;
+ struct trans *ltran;
+
+ for (api_con_index = g_api_con_trans_list->count - 1;
+ api_con_index >= 0;
+ api_con_index--)
+ {
+ ltran = (struct trans *)
+ list_get_item(g_api_con_trans_list, api_con_index);
+ if (ltran != NULL)
+ {
+ trans_get_wait_objs_rw(ltran, robjs, rcount, wobjs, wcount,
+ timeout);
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+api_con_trans_list_check_wait_objs(void)
+{
+ int api_con_index;
+ int drdynvc_index;
+ struct trans *ltran;
+ struct xrdp_api_data *ad;
+
+ for (api_con_index = g_api_con_trans_list->count - 1;
+ api_con_index >= 0;
+ api_con_index--)
+ {
+ ltran = (struct trans *)
+ list_get_item(g_api_con_trans_list, api_con_index);
+ if (ltran != NULL)
+ {
+ if (trans_check_wait_objs(ltran) != 0)
+ {
+ /* disconnect */
+ list_remove_item(g_api_con_trans_list, api_con_index);
+ ad = (struct xrdp_api_data *) (ltran->callback_data);
+ if (ad->chan_flags != 0)
+ {
+ chansrv_drdynvc_close(ad->chan_id);
+ }
+ for (drdynvc_index = 0;
+ drdynvc_index < (int) ARRAYSIZE(g_drdynvcs);
+ drdynvc_index++)
+ {
+ if (g_drdynvcs[drdynvc_index].xrdp_api_trans == ltran)
+ {
+ g_drdynvcs[drdynvc_index].xrdp_api_trans = NULL;
+ }
+ }
+ g_free(ad);
+ trans_delete(ltran);
+ }
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+api_con_trans_list_remove_all(void)
+{
+ int api_con_index;
+ struct trans *ltran;
+
+ for (api_con_index = g_api_con_trans_list->count - 1;
+ api_con_index >= 0;
+ api_con_index--)
+ {
+ ltran = (struct trans *)
+ list_get_item(g_api_con_trans_list, api_con_index);
+ if (ltran != NULL)
+ {
+ list_remove_item(g_api_con_trans_list, api_con_index);
+ g_free(ltran->callback_data);
+ trans_delete(ltran);
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
THREAD_RV THREAD_CC
channel_thread_loop(void *in_val)
{
@@ -1086,12 +1381,11 @@ channel_thread_loop(void *in_val)
int num_wobjs;
int timeout;
int error;
- int index;
THREAD_RV rv;
- struct trans *ltran;
LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread start"));
rv = 0;
+ g_api_con_trans_list = list_create();
setup_api_listen();
error = setup_listen();
@@ -1105,6 +1399,7 @@ channel_thread_loop(void *in_val)
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
+ //g_writeln("timeout %d", timeout);
while (g_obj_wait(objs, num_objs, wobjs, num_wobjs, timeout) == 0)
{
check_timeout();
@@ -1157,24 +1452,8 @@ channel_thread_loop(void *in_val)
LOG(0, ("channel_thread_loop: trans_check_wait_objs failed"));
}
}
-
- if (g_api_con_trans_list != 0)
- {
- for (index = g_api_con_trans_list->count - 1; index >= 0; index--)
- {
- ltran = (struct trans *) list_get_item(g_api_con_trans_list, index);
- if (ltran != 0)
- {
- if (trans_check_wait_objs(ltran) != 0)
- {
- list_remove_item(g_api_con_trans_list, index);
- g_free(ltran->callback_data);
- trans_delete(ltran);
- }
- }
- }
- }
-
+ /* check the wait_objs in g_api_con_trans_list */
+ api_con_trans_list_check_wait_objs();
xcommon_check_wait_objs();
sound_check_wait_objs();
dev_redir_check_wait_objs();
@@ -1184,23 +1463,16 @@ channel_thread_loop(void *in_val)
num_wobjs = 0;
objs[num_objs] = g_term_event;
num_objs++;
- trans_get_wait_objs(g_lis_trans, objs, &num_objs);
+ trans_get_wait_objs_rw(g_lis_trans, objs, &num_objs,
+ wobjs, &num_wobjs, &timeout);
trans_get_wait_objs_rw(g_con_trans, objs, &num_objs,
wobjs, &num_wobjs, &timeout);
- trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
-
- if (g_api_con_trans_list != 0)
- {
- for (index = g_api_con_trans_list->count - 1; index >= 0; index--)
- {
- ltran = (struct trans *) list_get_item(g_api_con_trans_list, index);
- if (ltran != 0)
- {
- trans_get_wait_objs(ltran, objs, &num_objs);
- }
- }
- }
-
+ trans_get_wait_objs_rw(g_api_lis_trans, objs, &num_objs,
+ wobjs, &num_wobjs, &timeout);
+ /* get the wait_objs from in g_api_con_trans_list */
+ api_con_trans_list_get_wait_objs_rw(objs, &num_objs,
+ wobjs, &num_wobjs,
+ &timeout);
xcommon_get_wait_objs(objs, &num_objs, &timeout);
sound_get_wait_objs(objs, &num_objs, &timeout);
dev_redir_get_wait_objs(objs, &num_objs, &timeout);
@@ -1215,20 +1487,8 @@ channel_thread_loop(void *in_val)
g_con_trans = 0;
trans_delete(g_api_lis_trans);
g_api_lis_trans = 0;
- if (g_api_con_trans_list != 0)
- {
- for (index = g_api_con_trans_list->count - 1; index >= 0; index--)
- {
- ltran = (struct trans *) list_get_item(g_api_con_trans_list, index);
- if (ltran != 0)
- {
- list_remove_item(g_api_con_trans_list, index);
- g_free(ltran->callback_data);
- trans_delete(ltran);
- }
- }
- list_delete(g_api_con_trans_list);
- }
+ api_con_trans_list_remove_all();
+ list_delete(g_api_con_trans_list);
LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread stop"));
g_set_wait_obj(g_thread_done_event);
return rv;
@@ -1551,6 +1811,8 @@ main(int argc, char **argv)
g_file_delete(log_file);
}
+ g_memset(g_drdynvcs, 0, sizeof(g_drdynvcs));
+
logconfig.log_file = log_file;
logconfig.fd = -1;
logconfig.log_level = log_level;
@@ -1649,66 +1911,3 @@ main(int argc, char **argv)
return 0;
}
-/*
- * return unused slot in dvc_channels[]
- *
- * @return unused slot index on success, -1 on failure
- ******************************************************************************/
-int
-find_empty_slot_in_dvc_channels(void)
-{
- int i;
-
- for (i = 0; i < MAX_DVC_CHANNELS; i++)
- {
- if (g_dvc_channels[i] == NULL)
- {
- return i;
- }
- }
-
- return -1;
-}
-
-/*
- * return struct xrdp_api_data that contains specified dvc_chan_id
- *
- * @param dvc_chan_id channel id to look for
- *
- * @return xrdp_api_data struct containing dvc_chan_id or NULL on failure
- ******************************************************************************/
-struct xrdp_api_data *
-struct_from_dvc_chan_id(tui32 dvc_chan_id)
-{
- int i;
-
- for (i = 0; i < MAX_DVC_CHANNELS; i++)
- {
- if (g_dvc_channels[i] != NULL &&
- g_dvc_channels[i]->dvc_chan_id >= 0 &&
- (tui32) g_dvc_channels[i]->dvc_chan_id == dvc_chan_id)
- {
- return g_dvc_channels[i];
- }
- }
-
- return NULL;
-}
-
-int
-remove_struct_with_chan_id(tui32 dvc_chan_id)
-{
- int i;
-
- for (i = 0; i < MAX_DVC_CHANNELS; i++)
- {
- if (g_dvc_channels[i] != NULL &&
- g_dvc_channels[i]->dvc_chan_id >= 0 &&
- (tui32) g_dvc_channels[i]->dvc_chan_id == dvc_chan_id)
- {
- g_dvc_channels[i] = NULL;
- return 0;
- }
- }
- return -1;
-}
diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h
index e75810c8..e1a0e34f 100644
--- a/sesman/chansrv/chansrv.h
+++ b/sesman/chansrv/chansrv.h
@@ -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
diff --git a/sesman/chansrv/drdynvc.c b/sesman/chansrv/drdynvc.c
deleted file mode 100644
index c02bdadb..00000000
--- a/sesman/chansrv/drdynvc.c
+++ /dev/null
@@ -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;
-}
diff --git a/sesman/chansrv/drdynvc.h b/sesman/chansrv/drdynvc.h
deleted file mode 100644
index cd6a5fca..00000000
--- a/sesman/chansrv/drdynvc.h
+++ /dev/null
@@ -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
diff --git a/sesman/sesman.ini.in b/sesman/sesman.ini.in
index 68ef7795..fb930f6b 100644
--- a/sesman/sesman.ini.in
+++ b/sesman/sesman.ini.in
@@ -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>
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 65e5c4f6..5ed46a3a 100644
--- a/xrdp/xrdp.h
+++ b/xrdp/xrdp.h
@@ -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
diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c
index 4c716d46..7d204b5b 100644
--- a/xrdp/xrdp_mm.c
+++ b/xrdp/xrdp_mm.c
@@ -680,70 +680,27 @@ xrdp_mm_trans_send_channel_setup(struct xrdp_mm *self, struct trans *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);
+ case 8: /* channel data */
+ rv = xrdp_mm_trans_process_channel_data(self, s);
break;
- case 4: /* channel setup response */
+ case 10: /* rail alternate secondary drawing orders */
+ rv = xrdp_mm_process_rail_drawing_orders(self, s);
break;
- case 6: /* channel data response */
+ case 12:
+ rv = xrdp_mm_trans_process_drdynvc_channel_open(self, s);
break;
- case 8: /* channel data */
- rv = xrdp_mm_trans_process_channel_data(self, trans);
+ case 14:
+ rv = xrdp_mm_trans_process_drdynvc_channel_close(self, s);
break;
- case 10: /* rail alternate secondary drawing orders */
- rv = xrdp_mm_process_rail_drawing_orders(self, trans);
+ 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,41 +1380,29 @@ 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
xrdp_mm_connect_chansrv(struct xrdp_mm *self, const char *ip, const char *port)
@@ -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
{
@@ -1228,6 +1482,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)
- {
- /*
- * 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
+ if (wm->mm->usechansrv)
{
- return 1;
+ /*
+ * 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);
}
/*****************************************************************************/
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index e317f584..7e416125 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -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 */
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
index 8b26718d..fd7b13b8 100644
--- a/xrdp/xrdp_wm.c
+++ b/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
+ rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
+ param3, param4);
+ }
+ else
+ {
+ if (self->mm->mod->mod_event != 0)
{
- 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;
}
diff --git a/xrdpapi/xrdpapi.c b/xrdpapi/xrdpapi.c
index 320052ab..a9017aff 100644
--- a/xrdpapi/xrdpapi.c
+++ b/xrdpapi/xrdpapi.c
@@ -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);
}
@@ -454,39 +531,6 @@ can_recv(int sck, int millis)
/*****************************************************************************/
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)
{
int index;
@@ -513,7 +557,6 @@ get_display_num_from_display(char *display_text)
disp[disp_index] = display_text[index];
disp_index++;
}
-
index++;
}