From 08bb4aa5c1392e4b0567eaf8025a78c252e3da80 Mon Sep 17 00:00:00 2001 From: Martin Fleisz Date: Thu, 20 Oct 2011 03:50:12 -0700 Subject: [PATCH 1/2] transport: Leaking socket on disconnect when using TLS transport layer --- libfreerdp-core/transport.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 32a915311..c0c9ad11f 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -71,9 +71,8 @@ void transport_attach(rdpTransport* transport, int sockfd) boolean transport_disconnect(rdpTransport* transport) { if (transport->layer == TRANSPORT_LAYER_TLS) - return tls_disconnect(transport->tls); - else - return tcp_disconnect(transport->tcp); + tls_disconnect(transport->tls); + return tcp_disconnect(transport->tcp); } boolean transport_connect_rdp(rdpTransport* transport) From 12245abfc88c07059db349cdf86a4031713e590f Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Thu, 20 Oct 2011 14:25:25 +0200 Subject: [PATCH 2/2] pcap: fix several segfaults with NULL pcap file handle - pcap_open did not return NULL if fopen failed - libfreerdp-core, tfreerdp-serer and xfreerdp-server did not check the pcap_open result - also fixed the sleep calculation in the xfreerdp-server --- libfreerdp-core/freerdp.c | 8 +++-- libfreerdp-utils/pcap.c | 10 ++++-- server/X11/xf_peer.c | 67 +++++++++++++++++++++++++++++---------- server/X11/xfreerdp.c | 4 +++ server/test/tfreerdp.c | 3 ++ 5 files changed, 70 insertions(+), 22 deletions(-) diff --git a/libfreerdp-core/freerdp.c b/libfreerdp-core/freerdp.c index a23da105a..b9f8ca153 100644 --- a/libfreerdp-core/freerdp.c +++ b/libfreerdp-core/freerdp.c @@ -42,8 +42,9 @@ boolean freerdp_connect(freerdp* instance) { if (instance->settings->dump_rfx) { - instance->update->dump_rfx = instance->settings->dump_rfx; instance->update->pcap_rfx = pcap_open(instance->settings->dump_rfx_file, True); + if (instance->update->pcap_rfx) + instance->update->dump_rfx = True; } IFCALL(instance->PostConnect, instance); @@ -55,11 +56,12 @@ boolean freerdp_connect(freerdp* instance) pcap_record record; s = stream_new(1024); - instance->update->play_rfx = instance->settings->play_rfx; instance->update->pcap_rfx = pcap_open(instance->settings->play_rfx_file, False); + if (instance->update->pcap_rfx) + instance->update->play_rfx = True; update = instance->update; - while (pcap_has_next_record(update->pcap_rfx)) + while (instance->update->play_rfx && pcap_has_next_record(update->pcap_rfx)) { pcap_get_next_record_header(update->pcap_rfx, &record); diff --git a/libfreerdp-utils/pcap.c b/libfreerdp-utils/pcap.c index 132a0cd00..96a43495c 100644 --- a/libfreerdp-utils/pcap.c +++ b/libfreerdp-utils/pcap.c @@ -134,6 +134,13 @@ rdpPcap* pcap_open(char* name, boolean write) { rdpPcap* pcap; + FILE *pcap_fp = fopen(name, write ? "w+" : "r"); + if (pcap_fp == NULL) + { + perror("opening pcap dump"); + return NULL; + } + pcap = (rdpPcap*) xzalloc(sizeof(rdpPcap)); if (pcap != NULL) @@ -141,10 +148,10 @@ rdpPcap* pcap_open(char* name, boolean write) pcap->name = name; pcap->write = write; pcap->record_count = 0; + pcap->fp = pcap_fp; if (write) { - pcap->fp = fopen(name, "w+"); pcap->header.magic_number = 0xA1B2C3D4; pcap->header.version_major = 2; pcap->header.version_minor = 4; @@ -156,7 +163,6 @@ rdpPcap* pcap_open(char* name, boolean write) } else { - pcap->fp = fopen(name, "r"); fseek(pcap->fp, 0, SEEK_END); pcap->file_size = (int) ftell(pcap->fp); fseek(pcap->fp, 0, SEEK_SET); diff --git a/server/X11/xf_peer.c b/server/X11/xf_peer.c index 8b40cdb50..7f7ea4501 100644 --- a/server/X11/xf_peer.c +++ b/server/X11/xf_peer.c @@ -27,6 +27,7 @@ #include extern char* xf_pcap_file; +extern boolean xf_pcap_dump_realtime; #include "xf_encode.h" @@ -49,7 +50,10 @@ xfInfo* xf_info_init() xfi->display = XOpenDisplay(NULL); if (xfi->display == NULL) + { printf("failed to open display: %s\n", XDisplayName(NULL)); + exit(1); + } xfi->number = DefaultScreen(xfi->display); xfi->screen = ScreenOfDisplay(xfi->display, xfi->number); @@ -227,12 +231,49 @@ void xf_peer_live_rfx(freerdp_peer* client) } } +static boolean xf_peer_sleep_tsdiff(uint32 *old_sec, uint32 *old_usec, uint32 new_sec, uint32 new_usec) +{ + sint32 sec, usec; + + if (*old_sec==0 && *old_usec==0) + { + *old_sec = new_sec; + *old_usec = new_usec; + return True; + } + + sec = new_sec - *old_sec; + usec = new_usec - *old_usec; + + if (sec<0 || (sec==0 && usec<0)) + { + printf("Invalid time stamp detected.\n"); + return False; + } + + *old_sec = new_sec; + *old_usec = new_usec; + + while (usec < 0) + { + usec += 1000000; + sec--; + } + + if (sec > 0) + freerdp_sleep(sec); + + if (usec > 0) + freerdp_usleep(usec); + + return True; +} + void xf_peer_dump_rfx(freerdp_peer* client) { STREAM* s; - double ttime; - uint32 seconds; - uint32 useconds; + uint32 prev_seconds; + uint32 prev_useconds; rdpUpdate* update; rdpPcap* pcap_rfx; pcap_record record; @@ -242,7 +283,10 @@ void xf_peer_dump_rfx(freerdp_peer* client) client->update->pcap_rfx = pcap_open(xf_pcap_file, False); pcap_rfx = client->update->pcap_rfx; - seconds = useconds = 0; + if (pcap_rfx == NULL) + return; + + prev_seconds = prev_useconds = 0; while (pcap_has_next_record(pcap_rfx)) { @@ -255,19 +299,8 @@ void xf_peer_dump_rfx(freerdp_peer* client) pcap_get_next_record_content(pcap_rfx, &record); s->p = s->data + s->size; - seconds = record.header.ts_sec - seconds; - useconds = record.header.ts_usec - useconds; - - ttime = ((double) seconds * 1000000) + (double) useconds; - - seconds = (uint32) (ttime / 1000000); - useconds = (uint32) (ttime - (((double) seconds) * 1000000)); - - if (seconds > 0) - freerdp_sleep(seconds); - - if (useconds > 0) - freerdp_usleep(useconds); + if (xf_pcap_dump_realtime && xf_peer_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == False) + break; update->SurfaceCommand(update, s); } diff --git a/server/X11/xfreerdp.c b/server/X11/xfreerdp.c index 78bc6cbfb..09954786b 100644 --- a/server/X11/xfreerdp.c +++ b/server/X11/xfreerdp.c @@ -26,6 +26,7 @@ #include "xfreerdp.h" char* xf_pcap_file = NULL; +boolean xf_pcap_dump_realtime = True; void xf_server_main_loop(freerdp_listener* instance) { @@ -100,6 +101,9 @@ int main(int argc, char* argv[]) if (argc > 1) xf_pcap_file = argv[1]; + if (argc > 2 && !strcmp(argv[2], "--fast")) + xf_pcap_dump_realtime = False; + /* Open the server socket and start listening. */ if (instance->Open(instance, NULL, 3389)) { diff --git a/server/test/tfreerdp.c b/server/test/tfreerdp.c index d3fd11355..ba16f8f26 100644 --- a/server/test/tfreerdp.c +++ b/server/test/tfreerdp.c @@ -299,6 +299,9 @@ void tf_peer_dump_rfx(freerdp_peer* client) client->update->pcap_rfx = pcap_open(test_pcap_file, False); pcap_rfx = client->update->pcap_rfx; + if (pcap_rfx == NULL) + return; + prev_seconds = prev_useconds = 0; while (pcap_has_next_record(pcap_rfx))