From dfd78c722b738e8db4c096393b6ecf0e26435f40 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Sep 2013 12:16:52 -0700 Subject: [PATCH 1/6] chansrv: fix for deadlock --- common/trans.c | 83 ++++++++++++++++++++++++++++++++++++++++ common/trans.h | 3 ++ sesman/chansrv/chansrv.c | 14 ++++++- 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/common/trans.c b/common/trans.c index 8313b606..408b4a7e 100644 --- a/common/trans.c +++ b/common/trans.c @@ -291,6 +291,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) size = (int)(out_s->end - out_s->data); total = 0; + self->in_write = 1; while (total < size) { sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); @@ -308,6 +309,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* term */ self->status = TRANS_STATUS_DOWN; + self->in_write = 0; return 1; } } @@ -317,6 +319,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; + self->in_write = 0; return 1; } } @@ -324,6 +327,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; + self->in_write = 0; return 1; } else @@ -331,6 +335,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) total = total + sent; } } + self->in_write = 0; return 0; } @@ -342,6 +347,84 @@ trans_force_write(struct trans *self) return trans_force_write_s(self, self->out_s); } +/*****************************************************************************/ +int APP_CC +trans_write_check(struct trans* self, int timeout) +{ + int size; + int total; + int sent; + int error; + tbus robjs[1]; + tbus wobjs[1]; + struct stream *out_s; + + if (self->status != TRANS_STATUS_UP) + { + return 1; + } + + out_s = self->out_s; + + size = (int)(out_s->end - out_s->data); + total = 0; + + self->in_write = 1; + while (total < size) + { + robjs[0] = self->sck; + wobjs[0] = self->sck; + error = g_obj_wait(robjs, 1, wobjs, 1, timeout); + if (error != 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + self->in_write = 0; + return 1; + } + + if (!g_tcp_can_send(self->sck, 0)) + { + trans_check_wait_objs(self); + continue; + } + + sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); + + if (sent == -1) + { + if (g_tcp_last_error_would_block(self->sck)) + { + if (!g_tcp_can_send(self->sck, 10)) + { + /* check for term here */ + } + } + else + { + /* error */ + self->status = TRANS_STATUS_DOWN; + self->in_write = 0; + return 1; + } + } + else if (sent == 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + self->in_write = 0; + return 1; + } + else + { + total = total + sent; + } + } + self->in_write = 0; + + return 0; +} + /*****************************************************************************/ int APP_CC trans_connect(struct trans *self, const char *server, const char *port, diff --git a/common/trans.h b/common/trans.h index 4b8e3b42..d9ad6c19 100644 --- a/common/trans.h +++ b/common/trans.h @@ -54,6 +54,7 @@ struct trans struct stream* out_s; char* listen_filename; tis_term is_term; /* used to test for exit */ + int in_write; }; struct trans* APP_CC @@ -73,6 +74,8 @@ trans_force_read(struct trans* self, int size); int APP_CC trans_force_write(struct trans* self); int APP_CC +trans_write_check(struct trans* self, int timeout); +int APP_CC trans_connect(struct trans* self, const char* server, const char* port, int timeout); int APP_CC diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index c3d1aa79..56626c77 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -293,10 +293,20 @@ send_data_from_chan_item(struct chan_item *chan_item) out_uint32_le(s, cod->s->size); out_uint8a(s, cod->s->p, size); s_mark_end(s); - LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- " + LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- " "size %d chan_flags 0x%8.8x", size, chan_flags)); g_sent = 1; - error = trans_force_write(g_con_trans); + if (g_con_trans->in_write) + { + g_writeln("chansrv::send_data_from_chan_item: error, " + "write while in_write"); + error = 1; + } + else + { + /* write but check for read if blocked */ + error = trans_write_check(g_con_trans, -1); + } if (error != 0) { From 3b743f64ebf4c857a5784add1da72ba41fcf7025 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Sep 2013 18:08:22 -0700 Subject: [PATCH 2/6] chansrv: deadlock, add trans copy func --- common/trans.c | 171 ++++++++++++++++++++++++--------------- common/trans.h | 4 +- sesman/chansrv/chansrv.c | 29 +++---- 3 files changed, 122 insertions(+), 82 deletions(-) diff --git a/common/trans.c b/common/trans.c index 408b4a7e..ae150940 100644 --- a/common/trans.c +++ b/common/trans.c @@ -90,6 +90,86 @@ trans_get_wait_objs(struct trans *self, tbus *objs, int *count) return 0; } +/*****************************************************************************/ +int APP_CC +trans_get_wait_objs_rw(struct trans *self, + tbus *robjs, int *rcount, + tbus *wobjs, int *wcount) +{ + if (self == 0) + { + return 1; + } + + if (self->status != TRANS_STATUS_UP) + { + return 1; + } + + robjs[*rcount] = self->sck; + (*rcount)++; + + if (self->wait_s != 0) + { + wobjs[*wcount] = self->sck; + (*wcount)++; + } + + return 0; +} + +/*****************************************************************************/ +int APP_CC +send_waiting(struct trans *self, int block) +{ + struct stream *temp_s; + int bytes; + int sent; + int timeout; + int cont; + + timeout = block ? 100 : 0; + cont = 1; + while (cont) + { + if (self->wait_s != 0) + { + temp_s = self->wait_s; + if (g_tcp_can_send(self->sck, timeout)) + { + bytes = (int) (temp_s->end - temp_s->p); + sent = g_tcp_send(self->sck, temp_s->p, bytes, 0); + if (sent > 0) + { + temp_s->p += sent; + if (temp_s->p >= temp_s->end) + { + self->wait_s = (struct stream *) (temp_s->next_packet); + free_stream(temp_s); + } + } + else if (sent == 0) + { + return 1; + } + else + { + if (!g_tcp_last_error_would_block(self->sck)) + { + return 1; + } + } + } + } + else + { + break; + } + cont = block; + } + return 0; +} + /*****************************************************************************/ int APP_CC trans_check_wait_objs(struct trans *self) @@ -203,6 +283,12 @@ trans_check_wait_objs(struct trans *self) } } } + if (send_waiting(self, 0) != 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + return 1; + } } return rv; @@ -291,7 +377,12 @@ trans_force_write_s(struct trans *self, struct stream *out_s) size = (int)(out_s->end - out_s->data); total = 0; - self->in_write = 1; + if (send_waiting(self, 1) != 0) + { + self->status = TRANS_STATUS_DOWN; + return 1; + } + while (total < size) { sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); @@ -309,7 +400,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* term */ self->status = TRANS_STATUS_DOWN; - self->in_write = 0; return 1; } } @@ -319,7 +409,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; - self->in_write = 0; return 1; } } @@ -327,7 +416,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; - self->in_write = 0; return 1; } else @@ -335,7 +423,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) total = total + sent; } } - self->in_write = 0; return 0; } @@ -349,15 +436,12 @@ trans_force_write(struct trans *self) /*****************************************************************************/ int APP_CC -trans_write_check(struct trans* self, int timeout) +trans_write_copy(struct trans *self) { int size; - int total; - int sent; - int error; - tbus robjs[1]; - tbus wobjs[1]; struct stream *out_s; + struct stream *wait_s; + struct stream *temp_s; if (self->status != TRANS_STATUS_UP) { @@ -365,63 +449,24 @@ trans_write_check(struct trans* self, int timeout) } out_s = self->out_s; - size = (int)(out_s->end - out_s->data); - total = 0; - - self->in_write = 1; - while (total < size) + make_stream(wait_s); + init_stream(wait_s, size); + out_uint8a(wait_s, out_s->data, size); + s_mark_end(wait_s); + if (self->wait_s == 0) { - robjs[0] = self->sck; - wobjs[0] = self->sck; - error = g_obj_wait(robjs, 1, wobjs, 1, timeout); - if (error != 0) - { - /* error */ - self->status = TRANS_STATUS_DOWN; - self->in_write = 0; - return 1; - } - - if (!g_tcp_can_send(self->sck, 0)) - { - trans_check_wait_objs(self); - continue; - } - - sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); - - if (sent == -1) - { - if (g_tcp_last_error_would_block(self->sck)) - { - if (!g_tcp_can_send(self->sck, 10)) - { - /* check for term here */ - } - } - else - { - /* error */ - self->status = TRANS_STATUS_DOWN; - self->in_write = 0; - return 1; - } - } - else if (sent == 0) - { - /* error */ - self->status = TRANS_STATUS_DOWN; - self->in_write = 0; - return 1; - } - else + self->wait_s = wait_s; + } + else + { + temp_s = self->wait_s; + while (temp_s->next_packet != 0) { - total = total + sent; + temp_s = (struct stream *) (temp_s->next_packet); } + temp_s->next_packet = wait_s; } - self->in_write = 0; - return 0; } diff --git a/common/trans.h b/common/trans.h index d9ad6c19..b7b9c20d 100644 --- a/common/trans.h +++ b/common/trans.h @@ -54,7 +54,7 @@ struct trans struct stream* out_s; char* listen_filename; tis_term is_term; /* used to test for exit */ - int in_write; + struct stream* wait_s; }; struct trans* APP_CC @@ -74,7 +74,7 @@ trans_force_read(struct trans* self, int size); int APP_CC trans_force_write(struct trans* self); int APP_CC -trans_write_check(struct trans* self, int timeout); +trans_write_copy(struct trans* self); int APP_CC trans_connect(struct trans* self, const char* server, const char* port, int timeout); diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 56626c77..86c50960 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -296,18 +296,8 @@ send_data_from_chan_item(struct chan_item *chan_item) LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- " "size %d chan_flags 0x%8.8x", size, chan_flags)); g_sent = 1; - if (g_con_trans->in_write) - { - g_writeln("chansrv::send_data_from_chan_item: error, " - "write while in_write"); - error = 1; - } - else - { - /* write but check for read if blocked */ - error = trans_write_check(g_con_trans, -1); - } + error = trans_write_copy(g_con_trans); if (error != 0) { return 1; @@ -402,7 +392,7 @@ send_init_response_message(void) out_uint32_le(s, 2); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); - return trans_force_write(g_con_trans); + return trans_write_copy(g_con_trans); } /*****************************************************************************/ @@ -425,7 +415,7 @@ send_channel_setup_response_message(void) out_uint32_le(s, 4); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); - return trans_force_write(g_con_trans); + return trans_write_copy(g_con_trans); } /*****************************************************************************/ @@ -448,7 +438,7 @@ send_channel_data_response_message(void) out_uint32_le(s, 6); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); - return trans_force_write(g_con_trans); + return trans_write_copy(g_con_trans); } /*****************************************************************************/ @@ -647,7 +637,7 @@ process_message_channel_data(struct stream *s) if (chan_flags & 2) /* last */ { s_mark_end(ls); - trans_force_write(g_api_con_trans); + trans_write_copy(g_api_con_trans); } } } @@ -1051,7 +1041,9 @@ THREAD_RV THREAD_CC channel_thread_loop(void *in_val) { tbus objs[32]; + tbus wobjs[32]; int num_objs; + int num_wobjs; int timeout; int error; THREAD_RV rv; @@ -1065,12 +1057,13 @@ channel_thread_loop(void *in_val) { timeout = -1; num_objs = 0; + 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(g_api_lis_trans, objs, &num_objs); - while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) + while (g_obj_wait(objs, num_objs, wobjs, num_wobjs, timeout) == 0) { check_timeout(); if (g_is_wait_obj_set(g_term_event)) @@ -1145,10 +1138,12 @@ channel_thread_loop(void *in_val) xfuse_check_wait_objs(); timeout = -1; num_objs = 0; + 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(g_con_trans, objs, &num_objs); + trans_get_wait_objs_rw(g_con_trans, objs, &num_objs, + wobjs, &num_wobjs); trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); trans_get_wait_objs(g_api_con_trans, objs, &num_objs); xcommon_get_wait_objs(objs, &num_objs, &timeout); From fc31ae1f48bc2162c49daee8b79f66c67c9cf428 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Sep 2013 19:17:50 -0700 Subject: [PATCH 3/6] trans: reset p when adding to trans list --- common/trans.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/trans.c b/common/trans.c index ae150940..5d5c6125 100644 --- a/common/trans.c +++ b/common/trans.c @@ -454,6 +454,7 @@ trans_write_copy(struct trans *self) init_stream(wait_s, size); out_uint8a(wait_s, out_s->data, size); s_mark_end(wait_s); + wait_s->p = wait_s->data; if (self->wait_s == 0) { self->wait_s = wait_s; From 675e1b86c44d6b75032ec4cb40f4ccfb8cd06358 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 24 Sep 2013 11:17:50 -0700 Subject: [PATCH 4/6] chansrv: work on smartcard --- sesman/chansrv/pcsc/xrdp_pcsc.c | 52 ++++++++++++++++++++++++++---- sesman/chansrv/smartcard.c | 8 ++++- sesman/chansrv/smartcard_pcsc.c | 57 +++++++++++++++++++++++++++++++++ sesman/chansrv/smartcard_pcsc.h | 3 ++ 4 files changed, 112 insertions(+), 8 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 520c9971..b93dba12 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -52,11 +52,22 @@ typedef struct _SCARD_IO_REQUEST #define LLOGLN(_level, _args) \ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0) -#define SCARD_ESTABLISH_CONTEXT 0x01 -#define SCARD_RELEASE_CONTEXT 0x02 -#define SCARD_LIST_READERS 0x03 -#define SCARD_CONNECT 0x04 -#define SCARD_GET_STATUS_CHANGE 0x0C +#define SCARD_ESTABLISH_CONTEXT 0x01 +#define SCARD_RELEASE_CONTEXT 0x02 +#define SCARD_LIST_READERS 0x03 +#define SCARD_CONNECT 0x04 +#define SCARD_RECONNECT 0x05 +#define SCARD_DISCONNECT 0x06 +#define SCARD_BEGIN_TRANSACTION 0x07 +#define SCARD_END_TRANSACTION 0x08 +#define SCARD_TRANSMIT 0x09 +#define SCARD_CONTROL 0x0A +#define SCARD_STATUS 0x0B +#define SCARD_GET_STATUS_CHANGE 0x0C +#define SCARD_CANCEL 0x0D +#define SCARD_CANCEL_TRANSACTION 0x0E +#define SCARD_GET_ATTRIB 0x0F +#define SCARD_SET_ATTRIB 0x10 #define SCARD_S_SUCCESS 0x00000000 #define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) @@ -417,7 +428,7 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } - if (code != SCARD_RELEASE_CONTEXT) + if (code != SCARD_CONNECT) { LLOGLN(0, ("SCardConnect: error, bad code")); pthread_mutex_unlock(&g_mutex); @@ -467,6 +478,11 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard) { + char msg[256]; + int code; + int bytes; + int status; + LLOGLN(0, ("SCardBeginTransaction:")); if (g_sck == -1) { @@ -474,8 +490,30 @@ SCardBeginTransaction(SCARDHANDLE hCard) return SCARD_F_INTERNAL_ERROR; } pthread_mutex_lock(&g_mutex); + SET_UINT32(msg, 0, hCard); + if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4) != 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, send_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4)) + { + LLOGLN(0, ("SCardBeginTransaction: error, bad code")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } pthread_mutex_unlock(&g_mutex); - return SCARD_S_SUCCESS; + status = GET_UINT32(msg, 0); + LLOGLN(10, ("SCardBeginTransaction: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 1a81efea..e4d144bd 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -1163,6 +1163,8 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) /* insert reader name */ num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); + xstream_wr_u32_le(s, 0); + xstream_wr_u32_le(s, 0); xstream_wr_u32_le(s, num_chars); if (wide) { @@ -1178,6 +1180,7 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) xstream_wr_u8(s, w_reader_name[index]); } } + align_s(s, 4); /* insert context */ xstream_wr_u32_le(s, 4); @@ -1670,6 +1673,7 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -1689,7 +1693,9 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_connect_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 7af1871c..4d496c97 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -56,6 +56,7 @@ #define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */ #define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */ #define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */ +#define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */ /* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; @@ -347,6 +348,61 @@ scard_process_connect(struct trans *con, struct stream *in_s) return 0; } +/*****************************************************************************/ +int APP_CC +scard_function_connect_return(struct trans *con, + struct stream *in_s, + int len) +{ + int dwActiveProtocol; + int hCard; + int bytes; + struct stream *out_s; + + g_hexdump(in_s->p, len); + if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0) + { + LLOGLN(0, ("scard_function_connect_return: opps")); + return 1; + } + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C; + in_uint8s(in_s, 36); + in_uint32_le(in_s, dwActiveProtocol); + in_uint8s(in_s, 36); + in_uint32_le(in_s, hCard); + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, hCard); + out_uint32_le(out_s, dwActiveProtocol); + out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + s_mark_end(out_s); + bytes = (int) (out_s->end - out_s->data); + s_pop_layer(out_s, iso_hdr); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x04); /* SCARD_CONNECT 0x04 */ + return trans_force_write(con); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_begin_transaction(struct trans *con, struct stream *in_s) +{ + int hCard; + + LLOGLN(0, ("scard_process_begin_transaction:")); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) + { + LLOGLN(0, ("scard_process_begin_transaction: opps")); + return 1; + } + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_BT; + in_uint32_le(in_s, hCard); + LLOGLN(0, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard)); + scard_send_begin_transaction(con, hCard); + return 0; +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -495,6 +551,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) case 0x07: /* SCARD_BEGIN_TRANSACTION */ LLOGLN(0, ("scard_process_msg: SCARD_BEGIN_TRANSACTION")); + rv = scard_process_begin_transaction(con, in_s); break; case 0x08: /* SCARD_END_TRANSACTION */ diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index 81bf5046..94effea9 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -41,5 +41,8 @@ int APP_CC scard_function_list_readers_return(struct trans *con, int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, int len); +int APP_CC scard_function_connect_return(struct trans *con, + struct stream *in_s, + int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */ From 379685bfcaa4dffd707b932574c99f0bab33b83e Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Tue, 24 Sep 2013 17:19:10 -0700 Subject: [PATCH 5/6] FUSE: we now process only one opendir command at a time --- sesman/chansrv/Makefile.am | 6 +- sesman/chansrv/chansrv_fuse.c | 218 ++++++++++++++++++----------- sesman/chansrv/devredir.c | 10 +- sesman/chansrv/fifo.c | 255 ++++++++++++++++++++++++++++++++++ sesman/chansrv/fifo.h | 35 +++++ sesman/chansrv/mlog.h | 112 +++++++++++++++ 6 files changed, 553 insertions(+), 83 deletions(-) create mode 100644 sesman/chansrv/fifo.c create mode 100644 sesman/chansrv/fifo.h create mode 100644 sesman/chansrv/mlog.h diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 7cecdb1e..29ef902b 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -8,7 +8,8 @@ EXTRA_DIST = \ drdynvc.h \ rail.h \ sound.h \ - xcommon.h + xcommon.h \ + mlog.h EXTRA_DEFINES = EXTRA_INCLUDES = @@ -51,7 +52,8 @@ xrdp_chansrv_SOURCES = \ xcommon.c \ drdynvc.c \ chansrv_fuse.c \ - irp.c + irp.c \ + fifo.c xrdp_chansrv_LDFLAGS = \ $(EXTRA_FLAGS) diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index 572679eb..2eb78ea0 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -102,6 +102,7 @@ void xfuse_devredir_cb_file_close(void *vp) {} #include "os_calls.h" #include "chansrv_fuse.h" #include "list.h" +#include "fifo.h" #define min(x, y) ((x) < (y) ? (x) : (y)) @@ -223,6 +224,16 @@ struct dir_info int index; }; +/* queue FUSE opendir commands so we run only one at a time */ +struct opendir_req +{ + fuse_req_t req; + fuse_ino_t ino; + struct fuse_file_info *fi; +}; + +FIFO g_fifo_opendir; + static struct list *g_req_list = 0; static struct xrdp_fs g_xrdp_fs; /* an inst of xrdp file system */ static char *g_mount_point = 0; /* our FUSE mount point */ @@ -338,19 +349,22 @@ static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent, static void xfuse_cb_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi); -/* clipboard calls */ -int clipboard_request_file_data(int stream_id, int lindex, int offset, - int request_bytes); - static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi); static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); +static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); +/* clipboard calls */ +int clipboard_request_file_data(int stream_id, int lindex, int offset, + int request_bytes); + /* misc calls */ static void xfuse_mark_as_stale(int pinode); static void xfuse_delete_stale_entries(int pinode); @@ -403,6 +417,9 @@ int xfuse_init() if (xfuse_init_xrdp_fs()) return -1; + /* setup FIFOs */ + fifo_init(&g_fifo_opendir, 30); + /* setup FUSE callbacks */ g_memset(&g_xfuse_ops, 0, sizeof(g_xfuse_ops)); g_xfuse_ops.lookup = xfuse_cb_lookup; @@ -424,6 +441,8 @@ int xfuse_init() fuse_opt_add_arg(&args, "xrdp-chansrv"); fuse_opt_add_arg(&args, g_fuse_root_path); + //fuse_opt_add_arg(&args, "-s"); /* single threaded mode */ + //fuse_opt_add_arg(&args, "-d"); /* debug mode */ if (xfuse_init_lib(&args)) { @@ -444,6 +463,7 @@ int xfuse_init() int xfuse_deinit() { xfuse_deinit_xrdp_fs(); + fifo_deinit(&g_fifo_opendir); if (g_ch != 0) { @@ -901,12 +921,11 @@ static int xfuse_deinit_xrdp_fs() static int xfuse_is_inode_valid(int ino) { - /* our lowest ino is FIRST_INODE */ - if (ino < FIRST_INODE) + /* is ino present in our table? */ + if ((ino < FIRST_INODE) || (ino >= g_xrdp_fs.next_node)) return 0; - /* is ino present in our table? */ - if (ino >= g_xrdp_fs.next_node) + if (g_xrdp_fs.inode_table[ino] == NULL) return 0; return 1; @@ -989,6 +1008,11 @@ static void xfuse_dump_fs() log_debug("found %d entries", g_xrdp_fs.num_entries - FIRST_INODE); +#if 0 + log_debug("not dumping xrdp fs"); + return; +#endif + for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++) { if ((xinode = g_xrdp_fs.inode_table[i]) == NULL) @@ -1229,6 +1253,9 @@ static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode) if ((xinode == NULL) || (xinode->mode & S_IFDIR)) return -1; + log_always("deleting: inode=%d name=%s", xinode->inode, xinode->name); + log_debug("deleting: inode=%d name=%s", xinode->inode, xinode->name); + g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--; g_xrdp_fs.inode_table[xinode->inode] = NULL; free(xinode); @@ -1281,6 +1308,12 @@ static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode) if ((xinode == NULL) || (xinode->mode & S_IFREG)) return -1; + log_always("recursively deleting dir with inode=%d name=%s", + xinode->inode, xinode->name); + + log_debug("recursively deleting dir with inode=%d name=%s", + xinode->inode, xinode->name); + for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++) { if ((xip = g_xrdp_fs.inode_table[i]) == NULL) @@ -1342,60 +1375,6 @@ static void xfuse_update_xrdpfs_size() g_xrdp_fs.inode_table = vp; } -/* LK_TODO do we still need this function */ -#if 0 -static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size, - off_t off, struct fuse_file_info *fi) -{ - XRDP_INODE *xinode; - XRDP_INODE *xinode1; - struct dirbuf b; - int first_time = 1; - int i; - - memset(&b, 0, sizeof(struct dirbuf)); - - for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++) - { - if ((xinode = g_xrdp_fs.inode_table[i]) == NULL) - continue; - - /* match parent inode */ - if (xinode->parent_inode != ino) - continue; - - if (first_time) - { - first_time = 0; - if (ino == 1) - { - xfuse_dirbuf_add(req, &b, ".", 1); - xfuse_dirbuf_add(req, &b, "..", 1); - } - else - { - xinode1 = g_xrdp_fs.inode_table[ino]; - xfuse_dirbuf_add(req, &b, ".", ino); - xfuse_dirbuf_add(req, &b, "..", xinode1->parent_inode); - } - } - - xfuse_dirbuf_add(req, &b, xinode->name, xinode->inode); - } - - if (!first_time) - { - if (off < b.size) - fuse_reply_buf(req, b.p + off, min(b.size - off, size)); - else - fuse_reply_buf(req, NULL, 0); - } - - if (b.p) - free(b.p); -} -#endif - /****************************************************************************** ** ** ** callbacks for devredir ** @@ -1464,8 +1443,9 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) { - XFUSE_INFO *fip; - struct dir_info *di; + XFUSE_INFO *fip; + struct dir_info *di; + struct opendir_req *odreq; log_debug("vp=%p IoStatus=0x%x", vp, IoStatus); @@ -1473,7 +1453,7 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) if (fip == NULL) { log_debug("fip is NULL"); - return; + goto done; } if (IoStatus != 0) @@ -1506,6 +1486,22 @@ done: if (fip) free(fip); + + /* remove current request */ + g_free(fifo_remove(&g_fifo_opendir)); + + while (1) + { + /* process next request */ + odreq = fifo_peek(&g_fifo_opendir); + if (!odreq) + return; + + if (xfuse_proc_opendir_req(odreq->req, odreq->ino, odreq->fi)) + g_free(fifo_remove(&g_fifo_opendir)); /* req failed */ + else + break; /* req has been queued */ + } } void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, @@ -1903,15 +1899,19 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino, } xino = g_xrdp_fs.inode_table[ino]; + if (!xino) + { + log_debug("****** invalid ino=%d", (int) ino); + fuse_reply_err(req, EBADF); + return; + } memset(&stbuf, 0, sizeof(stbuf)); stbuf.st_ino = ino; stbuf.st_mode = xino->mode; stbuf.st_nlink = xino->nlink; stbuf.st_size = xino->size; - fuse_reply_attr(req, &stbuf, 1.0); - log_debug("exiting"); } /** @@ -1977,8 +1977,7 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, int i; int first_time; - log_debug("req=%p inode=%d name=%s size=%d offset=%d", req, ino, - g_xrdp_fs.inode_table[ino]->name, size, off); + log_debug("req=%p inode=%d size=%d offset=%d", req, ino, size, off); /* do we have a valid inode? */ if (!xfuse_is_inode_valid(ino)) @@ -2014,6 +2013,12 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, { first_time = 0; ti = g_xrdp_fs.inode_table[ino]; + if (!ti) + { + log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino); + fuse_reply_buf(req, NULL, 0); + return; + } xfuse_dirbuf_add1(req, &b, ".", ino); xfuse_dirbuf_add1(req, &b, "..", ti->parent_inode); } @@ -2451,6 +2456,12 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino, /* if ino points to a dir, fail the open request */ xinode = g_xrdp_fs.inode_table[ino]; + if (!xinode) + { + log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino); + fuse_reply_err(req, EBADF); + return; + } if (xinode->mode & S_IFDIR) { log_debug("reading a dir not allowed!"); @@ -2491,8 +2502,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino, fip->name[1023] = 0; fip->reply_type = RT_FUSE_REPLY_OPEN; - /* LK_TODO need to handle open permissions */ - /* we want path minus 'root node of the share' */ if ((cptr = strchr(full_path, '/')) == NULL) { @@ -2532,6 +2541,12 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct } XRDP_INODE *xinode = g_xrdp_fs.inode_table[ino]; + if (!xinode) + { + log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino); + fuse_reply_err(req, 0); + return; + } if (xinode->is_loc_resource) { /* specified file is a local resource */ @@ -2748,7 +2763,12 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, return; } - xinode = g_xrdp_fs.inode_table[ino]; + if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL) + { + log_debug("g_xrdp_fs.inode_table[%d] is NULL", ino); + fuse_reply_err(req, EBADF); + return; + } if (to_set & FUSE_SET_ATTR_MODE) { @@ -2813,8 +2833,39 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, fuse_reply_attr(req, &st, 1.0); /* LK_TODO just faking for now */ } +/** + * Get dir listing + *****************************************************************************/ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) +{ + struct opendir_req *odreq; + + /* save request */ + odreq = malloc(sizeof(struct opendir_req)); + odreq->req = req; + odreq->ino = ino; + odreq->fi = fi; + + if (fifo_is_empty(&g_fifo_opendir)) + { + fifo_insert(&g_fifo_opendir, odreq); + xfuse_proc_opendir_req(req, ino, fi); + } + else + { + /* place req in FIFO; xfuse_devredir_cb_enum_dir_done() will handle it */ + fifo_insert(&g_fifo_opendir, odreq); + } +} + +/** + * Process the next opendir req + * + * @return 0 of the request was sent for remote lookup, -1 otherwise + *****************************************************************************/ +static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) { struct dir_info *di; XRDP_INODE *xinode; @@ -2823,19 +2874,26 @@ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino, char full_path[4096]; char *cptr; - log_debug("inode=%d name=%s", ino, g_xrdp_fs.inode_table[ino]->name); + log_debug("inode=%d", ino); if (!xfuse_is_inode_valid(ino)) { log_error("inode %d is not valid", ino); fuse_reply_err(req, EBADF); - return; + g_free(fifo_remove(&g_fifo_opendir)); + return -1; } if (ino == 1) goto done; /* special case; enumerate top level dir */ - xinode = g_xrdp_fs.inode_table[ino]; + if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL) + { + log_debug("g_xrdp_fs.inode_table[%d] is NULL", ino); + fuse_reply_err(req, EBADF); + g_free(fifo_remove(&g_fifo_opendir)); + return -1; + } if (xinode->is_loc_resource) goto done; @@ -2846,7 +2904,8 @@ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino, if (xinode->is_synced) { xfuse_enum_dir(req, ino, size, off, fi); - return; + g_free(fifo_remove(&g_fifo_opendir)); + return -1; } else { @@ -2867,7 +2926,8 @@ do_remote_lookup: { log_error("system out of memory"); fuse_reply_err(req, ENOMEM); - return; + g_free(fifo_remove(&g_fifo_opendir)); + return -1; } fip->req = req; @@ -2900,7 +2960,7 @@ do_remote_lookup: } } - return; + return 0; done: @@ -2908,6 +2968,8 @@ done: di->index = FIRST_INODE; fi->fh = (long) di; fuse_reply_open(req, fi); + g_free(fifo_remove(&g_fifo_opendir)); + return -1; } /** diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 418c29e7..1f9eb492 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -68,7 +68,7 @@ #define log_info(_params...) \ { \ - if (LOG_INFO <= LOG_LEVEL) \ + if (LOG_INFO <= LOG_LEVEL) \ { \ g_write("[%10.10u]: DEV_REDIR %s: %d : ", \ g_time3(), __func__, __LINE__); \ @@ -78,7 +78,7 @@ #define log_debug(_params...) \ { \ - if (LOG_DEBUG <= LOG_LEVEL) \ + if (LOG_DEBUG <= LOG_LEVEL) \ { \ g_write("[%10.10u]: DEV_REDIR %s: %d : ", \ g_time3(), __func__, __LINE__); \ @@ -1101,7 +1101,11 @@ dev_redir_file_open(void *fusep, tui32 device_id, char *path, #if 1 /* without the 0x00000010 rdesktop opens files in */ /* O_RDONLY instead of O_RDWR mode */ - DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010; + if (mode & O_RDWR) + DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010; + else + DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE; + CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT; CreateDisposition = CD_FILE_OPEN; // WAS 1 #else diff --git a/sesman/chansrv/fifo.c b/sesman/chansrv/fifo.c new file mode 100644 index 00000000..630df3cd --- /dev/null +++ b/sesman/chansrv/fifo.c @@ -0,0 +1,255 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2013 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. + */ + + /* FIFO implementation to store a pointer to a user struct */ + +/* module based logging */ +#define MODULE_NAME "FIFO " +#define LOCAL_DEBUG + +#include "fifo.h" +#include "mlog.h" + +/** + * Initialize a FIFO that grows as required + * + * @param fp pointer to a FIFO + * @param num_entries initial size + * + * @return 0 on success, -1 on failure + *****************************************************************************/ +int +fifo_init(FIFO* fp, int num_entries) +{ + log_debug_high("entered"); + + /* validate params */ + if (!fp) + { + log_debug_high("invalid parameters"); + return -1; + } + + if (num_entries < 1) + num_entries = 10; + + fp->rd_ptr = 0; + fp->wr_ptr = 0; + fp->user_data = (long *) g_malloc(sizeof(long) * num_entries); + + if (fp->user_data) + { + fp->entries = num_entries; + log_debug_low("FIFO created; rd_ptr=%d wr_ptr=%d entries=%d", + fp->rd_ptr, fp->wr_ptr, fp->entries); + return 0; + } + else + { + log_error("FIFO create error; system out of memory"); + fp->entries = 0; + return -1; + } +} + +/** + * Deinit FIFO and release resources + * + * @param fp FIFO to deinit + * + * @return 0 on success, -1 on error + *****************************************************************************/ +int +fifo_deinit(FIFO* fp) +{ + log_debug_high("entered"); + + if (!fp) + { + log_debug_high("FIFO is null"); + return -1; + } + + if (fp->user_data) + { + g_free(fp->user_data); + fp->user_data = 0; + } + + fp->rd_ptr = 0; + fp->wr_ptr = 0; + fp->entries = 0; +} + +/** + * Check if FIFO is empty + * + * @param fp FIFO + * + * @return 1 if FIFO is empty, 0 otherwise + *****************************************************************************/ +int +fifo_is_empty(FIFO* fp) +{ + log_debug_high("entered"); + + if (!fp) + { + log_debug_high("FIFO is null"); + return 0; + } + + return (fp->rd_ptr == fp->wr_ptr) ? 1 : 0; +} + +/** + * Insert an item at the end + * + * @param fp FIFO + * @param data data to insert into FIFO + * + * @param 0 on success, -1 on error + *****************************************************************************/ + +int +fifo_insert(FIFO* fp, void* data) +{ + long* lp; + int next_val; /* next value for wr_ptr */ + int i; + + log_debug_high("entered"); + + if (!fp) + { + log_debug_high("FIFO is null"); + return -1; + } + + next_val = fp->wr_ptr + 1; + if (next_val >= fp->entries) + next_val = 0; + + if (next_val == fp->rd_ptr) + { + /* FIFO is full, expand it by 10 entries */ + lp = (long *) g_malloc(sizeof(long) * (fp->entries + 10)); + if (!lp) + { + log_debug_low("FIFO full; cannot expand, no memory"); + return -1; + } + + log_debug_low("FIFO full, expanding by 10 entries"); + + /* copy old data new location */ + for (i = 0; i < (fp->entries - 1); i++) + { + lp[i] = fp->user_data[fp->rd_ptr++]; + if (fp->rd_ptr >= fp->entries) + fp->rd_ptr = 0; + } + + /* update pointers */ + fp->rd_ptr = 0; + fp->wr_ptr = fp->entries - 1; + next_val = fp->entries; + fp->entries += 10; + + /* free old data */ + g_free(fp->user_data); + fp->user_data = lp; + } + + log_debug_low("inserting data at index %d", fp->wr_ptr); + + fp->user_data[fp->wr_ptr] = (long) data; + fp->wr_ptr = next_val; + + return 0; +} + +/** + * Remove an item from the head + * + * @param fp FIFO + * + * @param data on success, NULL on error + *****************************************************************************/ +void* +fifo_remove(FIFO* fp) +{ + long data; + + log_debug_high("entered"); + + if (!fp) + { + log_debug_high("FIFO is null"); + return 0; + } + + if (fp->rd_ptr == fp->wr_ptr) + { + log_debug_high("FIFO is empty"); + return 0; + } + + log_debug_low("removing data at index %d", fp->rd_ptr); + + data = fp->user_data[fp->rd_ptr++]; + + if (fp->rd_ptr >= fp->entries) + { + log_debug_high("FIFO rd_ptr wrapped around"); + fp->rd_ptr = 0; + } + + return (void *) data; +} + +/** + * Return item from head, but do not remove it + * + * @param fp FIFO + * + * @param data on success, NULL on error + *****************************************************************************/ +void* +fifo_peek(FIFO* fp) +{ + long data; + + log_debug_high("entered\n"); + + if (!fp) + { + log_debug_high("FIFO is null\n"); + return 0; + } + + if (fp->rd_ptr == fp->wr_ptr) + { + log_debug_high("FIFO is empty\n"); + return 0; + } + + log_debug_low("peeking data at index %d\n", fp->rd_ptr); + + return (void *) fp->user_data[fp->rd_ptr]; +} diff --git a/sesman/chansrv/fifo.h b/sesman/chansrv/fifo.h new file mode 100644 index 00000000..0a23592c --- /dev/null +++ b/sesman/chansrv/fifo.h @@ -0,0 +1,35 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2013 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. + */ + + /* FIFO implementation to store a pointer to a user struct */ + +typedef struct fifo +{ + long* user_data; + int rd_ptr; + int wr_ptr; + int entries; +} FIFO; + +int fifo_init(FIFO* fp, int num_entries); +int fifo_deinit(FIFO* fp); +int fifo_is_empty(FIFO* fp); +int fifo_insert(FIFO* fp, void* data); +void* fifo_remove(FIFO* fp); +void* fifo_peek(FIFO* fp); + diff --git a/sesman/chansrv/mlog.h b/sesman/chansrv/mlog.h new file mode 100644 index 00000000..866c9692 --- /dev/null +++ b/sesman/chansrv/mlog.h @@ -0,0 +1,112 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2013 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. + */ + + /* module based logging */ + +#ifndef _MLOG_H +#define _MLOG_H + +/* + * Note1: to enable debug messages, in your .c file, #define LOCAL_DEBUG + * BEFORE including this file + * + * Note2: in your .c file, #define MODULE_NAME, 8 chars long, to print each + * log entry with your module name + */ + +#define LOG_ERROR 0 +#define LOG_INFO 1 +#define LOG_DEBUG_LOW 2 +#define LOG_DEBUG_HIGH 3 +#define LOG_LEVEL LOG_ERROR + +/* + * print always + */ + +#define log_error(_params...) \ +do \ +{ \ + g_write("[%10.10u]: %s %s: %d: ERROR: ", g_time3(), \ + MODULE_NAME, __func__, __LINE__); \ + g_writeln (_params); \ +} \ +while(0) + +#define log_always(_params...) \ +do \ +{ \ + g_write("[%10.10u]: %s %s: %d: ALWAYS: ", g_time3(), \ + MODULE_NAME, __func__, __LINE__); \ + g_writeln (_params); \ +} \ +while(0) + +/* + * print conditionally + */ + +#ifdef LOCAL_DEBUG +#define log_info(_params...) \ +do \ +{ \ + if (LOG_INFO <= LOG_LEVEL) \ + { \ + g_write("[%10.10u]: %s %s: %d: INFO: ", g_time3(), \ + MODULE_NAME, __func__, __LINE__); \ + g_writeln (_params); \ + } \ +} \ +while(0) +#else +#define log_info(_params...) +#endif + +#ifdef LOCAL_DEBUG +#define log_debug_low(_params...) \ +do \ +{ \ + if (LOG_DEBUG_LOW <= LOG_LEVEL) \ + { \ + g_write("[%10.10u]: %s %s: %d: DEBUG: ", g_time3(), \ + MODULE_NAME, __func__, __LINE__); \ + g_writeln (_params); \ + } \ +} \ +while(0) +#else +#define log_debug_low(_params...) +#endif + +#ifdef LOCAL_DEBUG +#define log_debug_high(_params...) \ +do \ +{ \ + if (LOG_DEBUG_HIGH <= LOG_LEVEL) \ + { \ + g_write("[%10.10u]: %s %s: %d: DEBUG: ", g_time3(), \ + MODULE_NAME, __func__, __LINE__); \ + g_writeln (_params); \ + } \ +} \ +while(0) +#else +#define log_debug_high(_params...) +#endif + +#endif /* #ifndef _MLOG_H */ From 1afb67850157392e2d8c35857388d515ddcdf0b4 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 24 Sep 2013 17:24:46 -0700 Subject: [PATCH 6/6] X11rdp: fixes for off screen bitmap limits --- xorg/X11R7.6/rdp/rdpdraw.c | 10 ++++++---- xorg/X11R7.6/rdp/rdpup.c | 34 ++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/xorg/X11R7.6/rdp/rdpdraw.c b/xorg/X11R7.6/rdp/rdpdraw.c index 2bb6ccc4..b573f1a8 100644 --- a/xorg/X11R7.6/rdp/rdpdraw.c +++ b/xorg/X11R7.6/rdp/rdpdraw.c @@ -769,9 +769,11 @@ rdpDestroyPixmap(PixmapPtr pPixmap) { if (XRDP_IS_OS(priv)) { - rdpup_remove_os_bitmap(priv->rdpindex); - rdpup_delete_os_surface(priv->rdpindex); - draw_item_remove_all(priv); + if (priv->rdpindex >= 0) + { + rdpup_remove_os_bitmap(priv->rdpindex); + rdpup_delete_os_surface(priv->rdpindex); + } } } @@ -1112,7 +1114,7 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) if ((num_clip_rects > 16) && (num_reg_rects > 16)) { box3 = RegionExtents(®); - rdpup_send_area(10, box3->x1 + dx, box3->y1 + dy, + rdpup_send_area(0, box3->x1 + dx, box3->y1 + dy, box3->x2 - box3->x1, box3->y2 - box3->y1); } diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c index 0277fc20..c380f285 100644 --- a/xorg/X11R7.6/rdp/rdpup.c +++ b/xorg/X11R7.6/rdp/rdpup.c @@ -85,6 +85,7 @@ struct rdpup_os_bitmap int stamp; }; +#define USE_MAX_OS_BYTES 1 #define MAX_OS_BYTES (16 * 1024 * 1024) static struct rdpup_os_bitmap *g_os_bitmaps = 0; static int g_max_os_bitmaps = 0; @@ -232,6 +233,7 @@ rdpup_disconnect(void) } /*****************************************************************************/ +/* returns -1 on error */ int rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) { @@ -241,13 +243,16 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) int oldest_index; int this_bytes; + LLOGLN(10, ("rdpup_add_os_bitmap:")); if (!g_connected) { + LLOGLN(10, ("rdpup_add_os_bitmap: test error 1")); return -1; } if (g_os_bitmaps == 0) { + LLOGLN(10, ("rdpup_add_os_bitmap: test error 2")); return -1; } @@ -255,8 +260,8 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) if (this_bytes > MAX_OS_BYTES) { LLOGLN(10, ("rdpup_add_os_bitmap: error, too big this_bytes %d " - "width %d height %d", this_bytes, - pixmap->drawable.height, pixmap->drawable.height)); + "width %d height %d", this_bytes, + pixmap->drawable.height, pixmap->drawable.height)); return -1; } @@ -297,11 +302,14 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) } else { + LLOGLN(10, ("rdpup_add_os_bitmap: too many pixmaps removing " + "oldest_index %d", oldest_index)); rdpup_remove_os_bitmap(oldest_index); - g_os_bitmaps[index].used = 1; - g_os_bitmaps[index].pixmap = pixmap; - g_os_bitmaps[index].priv = priv; - g_os_bitmaps[index].stamp = g_os_bitmap_stamp; + rdpup_delete_os_surface(oldest_index); + g_os_bitmaps[oldest_index].used = 1; + g_os_bitmaps[oldest_index].pixmap = pixmap; + g_os_bitmaps[oldest_index].priv = priv; + g_os_bitmaps[oldest_index].stamp = g_os_bitmap_stamp; g_os_bitmap_stamp++; g_pixmap_num_used++; rv = oldest_index; @@ -310,12 +318,14 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) if (rv < 0) { + LLOGLN(10, ("rdpup_add_os_bitmap: test error 3")); return rv; } g_os_bitmap_alloc_size += this_bytes; LLOGLN(10, ("rdpup_add_os_bitmap: this_bytes %d g_os_bitmap_alloc_size %d", this_bytes, g_os_bitmap_alloc_size)); +#if USE_MAX_OS_BYTES while (g_os_bitmap_alloc_size > MAX_OS_BYTES) { LLOGLN(10, ("rdpup_add_os_bitmap: must delete g_pixmap_num_used %d", @@ -326,7 +336,7 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) index = 0; while (index < g_max_os_bitmaps) { - if (g_os_bitmaps[index].used && g_os_bitmaps[index].stamp < oldest) + if (g_os_bitmaps[index].used && (g_os_bitmaps[index].stamp < oldest)) { oldest = g_os_bitmaps[index].stamp; oldest_index = index; @@ -346,6 +356,7 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) rdpup_remove_os_bitmap(oldest_index); rdpup_delete_os_surface(oldest_index); } +#endif LLOGLN(10, ("rdpup_add_os_bitmap: new bitmap index %d", rv)); LLOGLN(10, ("rdpup_add_os_bitmap: g_pixmap_num_used %d " "g_os_bitmap_stamp 0x%8.8x", g_pixmap_num_used, g_os_bitmap_stamp)); @@ -365,11 +376,13 @@ rdpup_remove_os_bitmap(int rdpindex) if (g_os_bitmaps == 0) { + LLOGLN(10, ("rdpup_remove_os_bitmap: test error 1")); return 1; } if ((rdpindex < 0) && (rdpindex >= g_max_os_bitmaps)) { + LLOGLN(10, ("rdpup_remove_os_bitmap: test error 2")); return 1; } @@ -396,7 +409,8 @@ rdpup_remove_os_bitmap(int rdpindex) LLOGLN(0, ("rdpup_remove_os_bitmap: error")); } - LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used)); + LLOGLN(10, ("rdpup_remove_os_bitmap: g_pixmap_num_used %d", + g_pixmap_num_used)); return 0; } @@ -404,10 +418,6 @@ rdpup_remove_os_bitmap(int rdpindex) int rdpup_update_os_use(int rdpindex) { - PixmapPtr pixmap; - rdpPixmapPtr priv; - int this_bytes; - LLOGLN(10, ("rdpup_update_use: index %d stamp %d", rdpindex, g_os_bitmaps[rdpindex].stamp));