Merge remote-tracking branch 'upstream/master'

This commit is contained in:
qubit 2011-08-28 02:40:34 +05:30
commit e698c91ef1
29 changed files with 855 additions and 69 deletions

3
.gitignore vendored
View File

@ -30,6 +30,9 @@ docs/api
ipch
Debug
# test files
*.pcap
# Binaries
*.a
*.so

View File

@ -17,6 +17,8 @@
* limitations under the License.
*/
#include <freerdp/utils/memory.h>
#include "xf_gdi.h"
static const uint8 xf_rop2_table[] =
@ -186,14 +188,55 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3)
return True;
}
void xf_bitmap_new(xfInfo* xfi, int width, int height, int bpp, uint8* data)
Pixmap xf_bitmap_new(xfInfo* xfi, int width, int height, int bpp, uint8* data)
{
Pixmap bitmap;
uint8* cdata;
XImage* image;
bitmap = XCreatePixmap(xfi->display, xfi->window->handle, width, height, xfi->depth);
cdata = gdi_image_convert(data, NULL, width, height, bpp, xfi->bpp, xfi->clrconv);
image = XCreateImage(xfi->display, xfi->visual, xfi->depth,
ZPixmap, 0, (char *) cdata, width, height, xfi->scanline_pad, 0);
XPutImage(xfi->display, bitmap, xfi->gc, image, 0, 0, 0, 0, width, height);
XFree(image);
if (cdata != data)
xfree(cdata);
return bitmap;
}
void xf_gdi_bitmap_update(rdpUpdate* update, BITMAP_UPDATE* bitmap)
{
int i;
int x, y;
int w, h;
uint8* data;
XImage* image;
BITMAP_DATA* bmp;
xfInfo* xfi = GET_XFI(update);
for (i = 0; i < bitmap->number; i++)
{
bmp = &bitmap->bitmaps[i];
data = gdi_image_convert(bmp->data, NULL, bmp->width, bmp->height, bmp->bpp, xfi->bpp, xfi->clrconv);
image = XCreateImage(xfi->display, xfi->visual, xfi->depth,
ZPixmap, 0, (char*) data, bmp->width, bmp->height, xfi->scanline_pad, 0);
x = bmp->left;
y = bmp->top;
w = bmp->right - bmp->left + 1;
h = bmp->bottom - bmp->top + 1;
XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0, x, y, w, h);
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
}
}
void xf_gdi_palette_update(rdpUpdate* update, PALETTE_UPDATE* palette)
@ -203,12 +246,40 @@ void xf_gdi_palette_update(rdpUpdate* update, PALETTE_UPDATE* palette)
void xf_gdi_set_bounds(rdpUpdate* update, BOUNDS* bounds)
{
XRectangle clip;
xfInfo* xfi = GET_XFI(update);
if (bounds != NULL)
{
clip.x = bounds->left;
clip.y = bounds->top;
clip.width = bounds->right - bounds->left + 1;
clip.height = bounds->bottom - bounds->top + 1;
XSetClipRectangles(xfi->display, xfi->gc, 0, 0, &clip, 1, YXBanded);
}
else
{
XSetClipMask(xfi->display, xfi->gc, None);
}
}
void xf_gdi_dstblt(rdpUpdate* update, DSTBLT_ORDER* dstblt)
{
xfInfo* xfi = GET_XFI(update);
xf_set_rop3(xfi, gdi_rop3_code(dstblt->bRop));
XSetFillStyle(xfi->display, xfi->gc, FillSolid);
XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
dstblt->nLeftRect, dstblt->nTopRect,
dstblt->nWidth, dstblt->nHeight);
if (xfi->drawing == xfi->primary)
{
XFillRectangle(xfi->display, xfi->window->handle, xfi->gc,
dstblt->nLeftRect, dstblt->nTopRect,
dstblt->nWidth, dstblt->nHeight);
}
}
void xf_gdi_patblt(rdpUpdate* update, PATBLT_ORDER* patblt)
@ -218,17 +289,80 @@ void xf_gdi_patblt(rdpUpdate* update, PATBLT_ORDER* patblt)
void xf_gdi_scrblt(rdpUpdate* update, SCRBLT_ORDER* scrblt)
{
xfInfo* xfi = GET_XFI(update);
xf_set_rop3(xfi, gdi_rop3_code(scrblt->bRop));
XCopyArea(xfi->display, xfi->primary, xfi->drawing, xfi->gc, scrblt->nXSrc, scrblt->nYSrc,
scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect);
if (xfi->drawing == xfi->primary)
{
if (xfi->unobscured)
{
XCopyArea(xfi->display, xfi->window->handle, xfi->window->handle, xfi->gc,
scrblt->nXSrc, scrblt->nYSrc, scrblt->nWidth, scrblt->nHeight,
scrblt->nLeftRect, scrblt->nTopRect);
}
else
{
XSetFunction(xfi->display, xfi->gc, GXcopy);
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc,
scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight,
scrblt->nLeftRect, scrblt->nTopRect);
}
}
}
void xf_gdi_opaque_rect(rdpUpdate* update, OPAQUE_RECT_ORDER* opaque_rect)
{
uint32 color;
xfInfo* xfi = GET_XFI(update);
color = gdi_color_convert(opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv);
XSetFunction(xfi->display, xfi->gc, GXcopy);
XSetFillStyle(xfi->display, xfi->gc, FillSolid);
XSetForeground(xfi->display, xfi->gc, color);
XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
opaque_rect->nLeftRect, opaque_rect->nTopRect,
opaque_rect->nWidth, opaque_rect->nHeight);
if (xfi->drawing == xfi->primary)
{
XFillRectangle(xfi->display, xfi->window->handle, xfi->gc,
opaque_rect->nLeftRect, opaque_rect->nTopRect,
opaque_rect->nWidth, opaque_rect->nHeight);
}
}
void xf_gdi_multi_opaque_rect(rdpUpdate* update, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
{
int i;
uint32 color;
DELTA_RECT* rectangle;
xfInfo* xfi = GET_XFI(update);
color = gdi_color_convert(multi_opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv);
XSetFunction(xfi->display, xfi->gc, GXcopy);
XSetFillStyle(xfi->display, xfi->gc, FillSolid);
XSetForeground(xfi->display, xfi->gc, color);
for (i = 1; i < multi_opaque_rect->numRectangles + 1; i++)
{
rectangle = &multi_opaque_rect->rectangles[i];
XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
rectangle->left, rectangle->top,
rectangle->width, rectangle->height);
if (xfi->drawing == xfi->primary)
{
XFillRectangle(xfi->display, xfi->window->handle, xfi->gc,
rectangle->left, rectangle->top,
rectangle->width, rectangle->height);
}
}
}
void xf_gdi_line_to(rdpUpdate* update, LINE_TO_ORDER* line_to)
@ -248,12 +382,28 @@ void xf_gdi_fast_index(rdpUpdate* update, FAST_INDEX_ORDER* fast_index)
void xf_gdi_create_offscreen_bitmap(rdpUpdate* update, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
{
Pixmap surface;
xfInfo* xfi = GET_XFI(update);
surface = xf_bitmap_new(xfi, create_offscreen_bitmap->cx, create_offscreen_bitmap->cy, xfi->bpp, NULL);
offscreen_put(xfi->cache->offscreen, create_offscreen_bitmap->id, (void*) surface);
}
void xf_gdi_switch_surface(rdpUpdate* update, SWITCH_SURFACE_ORDER* switch_surface)
{
Pixmap surface;
xfInfo* xfi = GET_XFI(update);
if (switch_surface->bitmapId == SCREEN_BITMAP_SURFACE)
{
xfi->drawing = xfi->primary;
}
else
{
surface = (Pixmap) offscreen_get(xfi->cache->offscreen, switch_surface->bitmapId);
xfi->drawing = surface;
}
}
void xf_gdi_cache_bitmap_v2(rdpUpdate* update, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)

View File

@ -73,41 +73,44 @@ void xf_end_paint(rdpUpdate* update)
if (xfi->remote_app != True)
{
#if 1
if (gdi->primary->hdc->hwnd->invalid->null)
return;
x = gdi->primary->hdc->hwnd->invalid->x;
y = gdi->primary->hdc->hwnd->invalid->y;
w = gdi->primary->hdc->hwnd->invalid->w;
h = gdi->primary->hdc->hwnd->invalid->h;
XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h);
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
#else
int i;
int ninvalid;
HGDI_RGN* cinvalid;
if (gdi->primary->hdc->hwnd->ninvalid < 1)
return;
ninvalid = gdi->primary->hdc->hwnd->ninvalid;
cinvalid = gdi->primary->hdc->hwnd->cinvalid;
for (i = 0; i < ninvalid; i++)
if (xfi->complex_regions != True)
{
x = cinvalid[i]->x;
y = cinvalid[i]->y;
w = cinvalid[i]->w;
h = cinvalid[i]->h;
if (gdi->primary->hdc->hwnd->invalid->null)
return;
x = gdi->primary->hdc->hwnd->invalid->x;
y = gdi->primary->hdc->hwnd->invalid->y;
w = gdi->primary->hdc->hwnd->invalid->w;
h = gdi->primary->hdc->hwnd->invalid->h;
XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h);
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
}
else
{
int i;
int ninvalid;
HGDI_RGN cinvalid;
XFlush(xfi->display);
#endif
if (gdi->primary->hdc->hwnd->ninvalid < 1)
return;
ninvalid = gdi->primary->hdc->hwnd->ninvalid;
cinvalid = gdi->primary->hdc->hwnd->cinvalid;
for (i = 0; i < ninvalid; i++)
{
x = cinvalid[i].x;
y = cinvalid[i].y;
w = cinvalid[i].w;
h = cinvalid[i].h;
XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h);
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
}
XFlush(xfi->display);
}
}
else
{
@ -293,6 +296,14 @@ boolean xf_pre_connect(freerdp* instance)
xf_kbd_init(xfi);
xfi->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV));
xfi->clrconv->palette = NULL;
xfi->clrconv->alpha = 1;
xfi->clrconv->invert = 0;
xfi->clrconv->rgb555 = 0;
xfi->cache = cache_new(instance->settings);
xfi->xfds = ConnectionNumber(xfi->display);
xfi->screen_number = DefaultScreen(xfi->display);
xfi->screen = ScreenOfDisplay(xfi->display, xfi->screen_number);
@ -300,6 +311,7 @@ boolean xf_pre_connect(freerdp* instance)
xfi->big_endian = (ImageByteOrder(xfi->display) == MSBFirst);
xfi->mouse_motion = False;
xfi->complex_regions = True;
xfi->decoration = settings->decorations;
xfi->remote_app = settings->remote_app;
xfi->fullscreen = settings->fullscreen;
@ -381,7 +393,11 @@ boolean xf_post_connect(freerdp* instance)
gdi_init(instance, CLRCONV_ALPHA | CLRBUF_32BPP);
gdi = GET_GDI(instance->update);
//xf_gdi_register_update_callbacks(instance->update);
if (instance->settings->sw_gdi != True)
{
xfi->srcBpp = instance->settings->color_depth;
xf_gdi_register_update_callbacks(instance->update);
}
if (xfi->fullscreen)
xfi->decoration = False;
@ -423,6 +439,7 @@ boolean xf_post_connect(freerdp* instance)
xfi->gc = XCreateGC(xfi->display, DefaultRootWindow(xfi->display), GCGraphicsExposures, &gcv);
xfi->primary = XCreatePixmap(xfi->display, DefaultRootWindow(xfi->display), xfi->width, xfi->height, xfi->depth);
xfi->drawing = xfi->primary;
XSetForeground(xfi->display, xfi->gc, BlackPixelOfScreen(xfi->screen));
XFillRectangle(xfi->display, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height);
@ -701,6 +718,8 @@ int main(int argc, char* argv[])
chanman = freerdp_chanman_new();
SET_CHANMAN(instance, chanman);
instance->settings->sw_gdi = True;
if (freerdp_parse_args(instance->settings, argc, argv,
xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0)
return 1;

View File

@ -26,6 +26,7 @@
#include <freerdp/chanman/chanman.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/rail/rail.h>
#include <freerdp/cache/cache.h>
typedef struct xf_info xfInfo;
@ -54,9 +55,11 @@ struct xf_info
int depth;
int width;
int height;
int srcBpp;
Screen* screen;
XImage* image;
Pixmap primary;
Pixmap drawing;
Visual* visual;
Display* display;
Colormap colormap;
@ -71,7 +74,9 @@ struct xf_info
xfWorkArea workArea;
int current_desktop;
boolean remote_app;
HCLRCONV clrconv;
rdpRail* rail;
rdpCache* cache;
boolean focused;
boolean mouse_active;
@ -81,6 +86,7 @@ struct xf_info
boolean pressed_keys[256];
XModifierKeymap* modifier_map;
XSetWindowAttributes attribs;
boolean complex_regions;
Atom _NET_WM_ICON;
Atom _MOTIF_WM_HINTS;

View File

@ -44,6 +44,8 @@ add_executable(test_freerdp
test_list.h
test_orders.c
test_orders.h
test_pcap.c
test_pcap.h
test_license.c
test_license.h
test_stream.c

View File

@ -37,6 +37,7 @@
#include "test_librfx.h"
#include "test_freerdp.h"
#include "test_rail.h"
#include "test_pcap.h"
void dump_data(unsigned char * p, int len, int width, char* name)
{
@ -188,6 +189,10 @@ int main(int argc, char* argv[])
{
add_per_suite();
}
else if (strcmp("pcap", argv[*pindex]) == 0)
{
add_pcap_suite();
}
else if (strcmp("ber", argv[*pindex]) == 0)
{
add_ber_suite();

99
cunit/test_pcap.c Normal file
View File

@ -0,0 +1,99 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* pcap File Format Unit Tests
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@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.
*/
#include <freerdp/freerdp.h>
#include <freerdp/utils/hexdump.h>
#include <freerdp/utils/pcap.h>
#include "test_pcap.h"
int init_pcap_suite(void)
{
return 0;
}
int clean_pcap_suite(void)
{
return 0;
}
int add_pcap_suite(void)
{
add_test_suite(pcap);
add_test_function(pcap);
return 0;
}
uint8 test_packet_1[16] =
"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
uint8 test_packet_2[32] =
"\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"
"\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB";
uint8 test_packet_3[64] =
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC";
typedef struct
{
void* data;
uint32 length;
} test_packet;
void test_pcap(void)
{
rdpPcap* pcap;
pcap_record record;
test_packet packets[3];
packets[0].data = test_packet_1;
packets[0].length = sizeof(test_packet_1);
packets[1].data = test_packet_2;
packets[1].length = sizeof(test_packet_2);
packets[2].data = test_packet_3;
packets[2].length = sizeof(test_packet_3);
pcap = pcap_open("/tmp/test.pcap", True);
pcap_add_record(pcap, test_packet_1, sizeof(test_packet_1));
pcap_flush(pcap);
pcap_add_record(pcap, test_packet_2, sizeof(test_packet_2));
pcap_flush(pcap);
pcap_add_record(pcap, test_packet_3, sizeof(test_packet_3));
pcap_close(pcap);
pcap = pcap_open("/tmp/test.pcap", False);
int i = 0;
while (pcap_has_next_record(pcap))
{
pcap_get_next_record(pcap, &record);
CU_ASSERT(record.length == packets[i].length)
i++;
}
CU_ASSERT(i == 3);
pcap_close(pcap);
}

26
cunit/test_pcap.h Normal file
View File

@ -0,0 +1,26 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* pcap File Format Unit Tests
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@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.
*/
#include "test_freerdp.h"
int init_pcap_suite(void);
int clean_pcap_suite(void);
int add_pcap_suite(void);
void test_pcap(void);

View File

@ -193,9 +193,10 @@ typedef GDI_BRUSH* HGDI_BRUSH;
struct _GDI_WND
{
int count;
int ninvalid;
HGDI_RGN invalid;
HGDI_RGN* cinvalid;
HGDI_RGN cinvalid;
};
typedef struct _GDI_WND GDI_WND;
typedef GDI_WND* HGDI_WND;
@ -216,7 +217,6 @@ struct _GDI_DC
int alpha;
int invert;
int rgb555;
int complex;
};
typedef struct _GDI_DC GDI_DC;
typedef GDI_DC* HGDI_DC;

View File

@ -176,6 +176,7 @@ struct rdp_settings
{
uint16 width;
uint16 height;
boolean sw_gdi;
boolean workarea;
boolean fullscreen;
boolean decorations;
@ -296,6 +297,9 @@ struct rdp_settings
uint8 rfx_codec_id;
boolean frame_acknowledge;
boolean dump_rfx;
char* dump_rfx_file;
boolean remote_app;
uint8 num_icon_caches;
uint16 num_icon_cache_entries;

View File

@ -22,6 +22,8 @@
#include <freerdp/rail.h>
#include <freerdp/types.h>
#include <freerdp/utils/pcap.h>
#include <freerdp/utils/stream.h>
/* Common */
@ -1063,6 +1065,7 @@ typedef void (*pcMonitoredDesktop)(rdpUpdate* update, WINDOW_ORDER_INFO* orderIn
typedef void (*pcNonMonitoredDesktop)(rdpUpdate* update, WINDOW_ORDER_INFO* orderInfo);
typedef void (*pcSurfaceBits)(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command);
typedef void (*pcSurfaceCommand)(rdpUpdate* update, STREAM* s);
struct rdp_update
{
@ -1072,6 +1075,9 @@ struct rdp_update
void* param1;
void* param2;
boolean dump_rfx;
rdpPcap* pcap_rfx;
pcBeginPaint BeginPaint;
pcEndPaint EndPaint;
pcSetBounds SetBounds;
@ -1142,6 +1148,7 @@ struct rdp_update
pcNonMonitoredDesktop NonMonitoredDesktop;
pcSurfaceBits SurfaceBits;
pcSurfaceCommand SurfaceCommand;
BITMAP_UPDATE bitmap_update;
PALETTE_UPDATE palette_update;

View File

@ -0,0 +1,83 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* pcap File Format Utils
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@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 __UTILS_PCAP_H
#define __UTILS_PCAP_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/utils/stopwatch.h>
struct _pcap_header
{
uint32 magic_number; /* magic number */
uint16 version_major; /* major version number */
uint16 version_minor; /* minor version number */
sint32 thiszone; /* GMT to local correction */
uint32 sigfigs; /* accuracy of timestamps */
uint32 snaplen; /* max length of captured packets, in octets */
uint32 network; /* data link type */
};
typedef struct _pcap_header pcap_header;
struct _pcap_record_header
{
uint32 ts_sec; /* timestamp seconds */
uint32 ts_usec; /* timestamp microseconds */
uint32 incl_len; /* number of octets of packet saved in file */
uint32 orig_len; /* actual length of packet */
};
typedef struct _pcap_record_header pcap_record_header;
typedef struct _pcap_record pcap_record;
struct _pcap_record
{
pcap_record_header header;
void* data;
uint32 length;
pcap_record* next;
};
struct rdp_pcap
{
FILE* fp;
char* name;
STOPWATCH* sw;
boolean write;
int file_size;
int record_count;
pcap_header header;
pcap_record* head;
pcap_record* tail;
pcap_record* record;
};
typedef struct rdp_pcap rdpPcap;
FREERDP_API rdpPcap* pcap_open(char* name, boolean write);
FREERDP_API void pcap_close(rdpPcap* pcap);
FREERDP_API void pcap_add_record(rdpPcap* pcap, void* data, uint32 length);
FREERDP_API boolean pcap_has_next_record(rdpPcap* pcap);
FREERDP_API boolean pcap_get_next_record(rdpPcap* pcap, pcap_record* record);
FREERDP_API boolean pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record);
FREERDP_API boolean pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record);
FREERDP_API void pcap_flush(rdpPcap* pcap);
#endif /* __UTILS_PCAP_H */

View File

@ -22,6 +22,7 @@
#include <time.h>
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/utils/memory.h>
struct _STOPWATCH
@ -40,6 +41,7 @@ FREERDP_API void stopwatch_start(STOPWATCH* stopwatch);
FREERDP_API void stopwatch_stop(STOPWATCH* stopwatch);
FREERDP_API void stopwatch_reset(STOPWATCH* stopwatch);
double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch);
FREERDP_API double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch);
FREERDP_API void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, uint32* sec, uint32* usec);
#endif /* __UTILS_STOPWATCH_H */

View File

@ -38,7 +38,7 @@
* two less significant bits of the first byte.
*/
#define FASTPATH_MAX_PACKET_SIZE 0x7FFF
#define FASTPATH_MAX_PACKET_SIZE 0x3FFF
/**
* Read a Fast-Path packet header.\n
@ -394,7 +394,7 @@ boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
{
/**
* If numberEvents is not provided in fpInputHeader, it will be provided
* as onee additional byte here.
* as one additional byte here.
*/
if (stream_get_left(s) < 1)
@ -475,6 +475,36 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
return True;
}
boolean fastpath_send_fragmented_update_pdu(rdpFastPath* fastpath, STREAM* s)
{
uint16 length;
uint32 totalLength;
STREAM* update;
totalLength = stream_get_length(s);
update = fastpath_update_pdu_init(fastpath);
if (totalLength <= FASTPATH_MAX_PACKET_SIZE)
{
stream_write_uint8(update, FASTPATH_UPDATETYPE_SURFCMDS | (FASTPATH_FRAGMENT_SINGLE << 4));
stream_write_uint16(update, totalLength);
stream_write(update, s->data, totalLength);
return fastpath_send_update_pdu(fastpath, update);
}
while (totalLength > 0)
{
if (totalLength < FASTPATH_MAX_PACKET_SIZE)
length = totalLength;
else
length = FASTPATH_MAX_PACKET_SIZE;
totalLength -= length;
}
return True;
}
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId)
{
STREAM* s;
@ -519,7 +549,7 @@ boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_C
size += SURFCMD_SURFACE_BITS_HEADER_LENGTH;
}
fragment_size = MIN(stream_get_left(s), bitmapDataLength);
fragment_size = MIN(FASTPATH_MAX_PACKET_SIZE - stream_get_length(s), bitmapDataLength);
if (fragment_size == bitmapDataLength)
{
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST);

View File

@ -100,6 +100,7 @@ boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s);
STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath);
boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s);
boolean fastpath_send_fragmented_update_pdu(rdpFastPath* fastpath, STREAM* s);
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId);
boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd);

View File

@ -34,9 +34,19 @@ boolean freerdp_connect(freerdp* instance)
rdp = (rdpRdp*) instance->rdp;
IFCALL(instance->PreConnect, instance);
status = rdp_client_connect((rdpRdp*) instance->rdp);
if (status)
{
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);
}
IFCALL(instance->PostConnect, instance);
}
return status;
}

View File

@ -792,6 +792,26 @@ boolean mcs_send_channel_join_confirm(rdpMcs* mcs, uint16 channel_id)
return True;
}
/**
* Send MCS Disconnect Provider Ultimatum PDU.\n
* @param mcs mcs module
*/
boolean mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs)
{
STREAM* s;
uint16 length = 9;
s = transport_send_stream_init(mcs->transport, 9);
mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1);
per_write_enumerated(s, 0, 0); /* reason */
transport_write(mcs->transport, s);
return True;
}
/**
* Instantiate new MCS module.
* @param transport transport

View File

@ -146,6 +146,7 @@ boolean mcs_recv_channel_join_request(rdpMcs* mcs, STREAM* s, uint16* channel_id
boolean mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id);
boolean mcs_recv_channel_join_confirm(rdpMcs* mcs, STREAM* s, uint16* channel_id);
boolean mcs_send_channel_join_confirm(rdpMcs* mcs, uint16 channel_id);
boolean mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs);
boolean mcs_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, uint16* length);
void mcs_write_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU domainMCSPDU, uint16 length, uint8 options);

View File

@ -89,6 +89,10 @@ static boolean peer_recv_data_pdu(rdpPeer* peer, STREAM* s)
}
break;
case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
mcs_send_disconnect_provider_ultimatum(peer->rdp->mcs);
return False;
default:
printf("Data PDU type %d\n", type);
break;

View File

@ -17,12 +17,14 @@
* limitations under the License.
*/
#include <freerdp/utils/pcap.h>
#include "surface.h"
static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s)
{
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
int pos;
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
stream_read_uint16(s, cmd->destLeft);
stream_read_uint16(s, cmd->destTop);
@ -60,6 +62,12 @@ boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
{
uint16 cmdType;
if (update->dump_rfx)
{
pcap_add_record(update->pcap_rfx, s->p, size);
pcap_flush(update->pcap_rfx);
}
while (size > 2)
{
stream_read_uint16(s, cmdType);

View File

@ -124,6 +124,7 @@ boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_fi
boolean tls_disconnect(rdpTls* tls)
{
SSL_shutdown(tls->ssl);
return True;
}

View File

@ -77,8 +77,7 @@ void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data)
dstSize = cbUncompressedSize;
bitmap_data->length = cbCompMainBodySize;
bitmap_data->data = (uint8*) xzalloc(dstSize);
bitmap_data->data = (uint8*) xmalloc(dstSize);
stream_get_mark(s, srcData);
stream_seek(s, bitmap_data->length);
@ -323,10 +322,15 @@ static void update_end_paint(rdpUpdate* update)
{
}
static void update_send_surface_command(rdpUpdate* update, STREAM* s)
{
rdpRdp* rdp = (rdpRdp*) update->rdp;
fastpath_send_fragmented_update_pdu(rdp->fastpath, s);
}
static void update_send_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command)
{
rdpRdp* rdp = (rdpRdp*)update->rdp;
fastpath_send_surfcmd_surface_bits(rdp->fastpath, surface_bits_command);
}
@ -363,6 +367,7 @@ void update_register_server_callbacks(rdpUpdate* update)
update->Synchronize = update_send_synchronize;
update->PointerSystem = update_send_pointer_system;
update->SurfaceBits = update_send_surface_bits;
update->SurfaceCommand = update_send_surface_command;
}
rdpUpdate* update_new(rdpRdp* rdp)

View File

@ -308,7 +308,7 @@ inline uint32 gdi_rop3_code(uint8 code)
inline void gdi_copy_mem(uint8 * d, uint8 * s, int n)
{
memcpy(d, s, n);
memmove(d, s, n);
}
inline void gdi_copy_mem_backwards(uint8 * d, uint8 * s, int n)
@ -949,7 +949,6 @@ int gdi_init(freerdp* instance, uint32 flags)
gdi->hdc->alpha = gdi->clrconv->alpha;
gdi->hdc->invert = gdi->clrconv->invert;
gdi->hdc->rgb555 = gdi->clrconv->rgb555;
gdi->hdc->complex = 1;
gdi->primary = gdi_bitmap_new(gdi, gdi->width, gdi->height, gdi->dstBpp, NULL);
gdi->primary_buffer = gdi->primary->bitmap->data;
@ -958,7 +957,9 @@ int gdi_init(freerdp* instance, uint32 flags)
gdi->primary->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND));
gdi->primary->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0);
gdi->primary->hdc->hwnd->invalid->null = 1;
gdi->primary->hdc->hwnd->cinvalid = NULL;
gdi->primary->hdc->hwnd->count = 32;
gdi->primary->hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * gdi->primary->hdc->hwnd->count);
gdi->primary->hdc->hwnd->ninvalid = 0;
gdi->tile = gdi_bitmap_new(gdi, 64, 64, 32, NULL);

View File

@ -374,35 +374,25 @@ inline int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h)
GDI_RECT inv;
GDI_RECT rgn;
HGDI_RGN invalid;
HGDI_RGN cinvalid;
if (hdc->hwnd == NULL)
return 0;
if (hdc->complex)
{
HGDI_RGN* cinvalid;
cinvalid = hdc->hwnd->cinvalid;
if (hdc->hwnd->ninvalid <= 0)
{
hdc->hwnd->ninvalid = 0;
cinvalid = (HGDI_RGN*) malloc(sizeof(HGDI_RGN));
}
else
{
cinvalid = (HGDI_RGN*) realloc(cinvalid, sizeof(HGDI_RGN) * (hdc->hwnd->ninvalid + 1));
}
invalid = gdi_CreateRectRgn(x, y, x + w - 1, y + h - 1);
cinvalid[hdc->hwnd->ninvalid] = invalid;
hdc->hwnd->cinvalid = cinvalid;
hdc->hwnd->ninvalid++;
}
if (hdc->hwnd->invalid == NULL)
return 0;
cinvalid = hdc->hwnd->cinvalid;
if (hdc->hwnd->ninvalid + 1 > hdc->hwnd->count)
{
hdc->hwnd->count *= 2;
cinvalid = (HGDI_RGN) realloc(cinvalid, sizeof(GDI_RGN) * (hdc->hwnd->count));
}
gdi_SetRgn(&cinvalid[hdc->hwnd->ninvalid++], x, y, w, h);
hdc->hwnd->cinvalid = cinvalid;
invalid = hdc->hwnd->invalid;
if (invalid->null)

View File

@ -30,6 +30,7 @@ set(FREERDP_UTILS_SRCS
load_plugin.c
memory.c
mutex.c
pcap.c
profiler.c
rail.c
registry.c

View File

@ -51,7 +51,47 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
while (index < argc)
{
if (strcmp("-a", argv[index]) == 0)
if ((strcmp("-h", argv[index]) == 0 ) || (strcmp("--help", argv[index]) == 0 ))
{
printf("\n"
"FreeRDP - A Free Remote Desktop Protocol Client\n"
"See http://www.freerdp.com for more information\n"
"\n"
"Usage: %s [options] server:port\n"
" -0: connect to console session\n"
" -a: set color depth in bit, default is 16\n"
" -c: initial working directory\n"
" -D: hide window decorations\n"
" -d: domain\n"
" -f: fullscreen mode\n"
" -g: set geometry, using format WxH or X%% or 'workarea', default is 1024x768\n"
" -h: print this help\n"
" -k: set keyboard layout ID\n"
" -m: don't send mouse motion events\n"
" -n: hostname\n"
" -o: console audio\n"
" -p: password\n"
" -s: set startup-shell\n"
" -t: alternative port number, default is 3389\n"
" -u: username\n"
" -x: performance flags (m[odem], b[roadband] or l[an])\n"
" -z: enable compression\n"
" --app: RemoteApp connection. This implies -g workarea\n"
" --ext: load an extension\n"
" --no-auth: disable authentication\n"
" --no-fastpath: disable fast-path\n"
" --no-osb: disable off screen bitmaps, default on\n"
" --plugin: load a virtual channel plugin\n"
" --rfx: enable RemoteFX\n"
" --no-rdp: disable Standard RDP encryption\n"
" --no-tls: disable TLS encryption\n"
" --no-nla: disable network level authentication\n"
" --sec: force protocol security (rdp, tls or nla)\n"
" --version: print version information\n"
"\n", argv[0]);
return -1; //TODO: What is the correct return
}
else if (strcmp("-a", argv[index]) == 0)
{
index++;
if (index == argc)
@ -211,6 +251,28 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
settings->fastpath_input = False;
settings->fastpath_output = False;
}
else if (strcmp("--gdi", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing GDI backend\n");
return -1;
}
if (strncmp("sw", argv[index], 1) == 0) /* software */
{
settings->sw_gdi = True;
}
else if (strncmp("hw", argv[index], 1) == 0) /* hardware */
{
settings->sw_gdi = False;
}
else
{
printf("unknown GDI backend\n");
return -1;
}
}
else if (strcmp("--rfx", argv[index]) == 0)
{
settings->rfx_codec = True;
@ -220,6 +282,17 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
settings->performance_flags = PERF_FLAG_NONE;
settings->large_pointer = True;
}
else if (strcmp("--dump-rfx", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing file name\n");
return -1;
}
settings->dump_rfx_file = xstrdup(argv[index]);
settings->dump_rfx = True;
}
else if (strcmp("-m", argv[index]) == 0)
{
settings->mouse_motion = 0;

193
libfreerdp-utils/pcap.c Normal file
View File

@ -0,0 +1,193 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* pcap File Format Utils
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@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.
*/
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <freerdp/types.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/pcap.h>
#define PCAP_MAGIC 0xA1B2C3D4
void pcap_read_header(rdpPcap* pcap, pcap_header* header)
{
fread((void*) header, sizeof(pcap_header), 1, pcap->fp);
}
void pcap_write_header(rdpPcap* pcap, pcap_header* header)
{
fwrite((void*) header, sizeof(pcap_header), 1, pcap->fp);
}
void pcap_read_record_header(rdpPcap* pcap, pcap_record_header* record)
{
fread((void*) record, sizeof(pcap_record_header), 1, pcap->fp);
}
void pcap_write_record_header(rdpPcap* pcap, pcap_record_header* record)
{
fwrite((void*) record, sizeof(pcap_record_header), 1, pcap->fp);
}
void pcap_read_record(rdpPcap* pcap, pcap_record* record)
{
pcap_read_record_header(pcap, &record->header);
record->length = record->header.incl_len;
record->data = xmalloc(record->length);
fread(record->data, record->length, 1, pcap->fp);
}
void pcap_write_record(rdpPcap* pcap, pcap_record* record)
{
pcap_write_record_header(pcap, &record->header);
fwrite(record->data, record->length, 1, pcap->fp);
}
void pcap_add_record(rdpPcap* pcap, void* data, uint32 length)
{
pcap_record* record;
if (pcap->tail == NULL)
{
pcap->tail = (pcap_record*) xzalloc(sizeof(pcap_record));
pcap->head = pcap->tail;
pcap->record = pcap->head;
record = pcap->tail;
}
else
{
record = (pcap_record*) xzalloc(sizeof(pcap_record));
pcap->tail->next = record;
pcap->tail = record;
}
if (pcap->record == NULL)
pcap->record = record;
record->data = data;
record->length = length;
record->header.incl_len = length;
record->header.orig_len = length;
stopwatch_stop(pcap->sw);
stopwatch_get_elapsed_time_in_useconds(pcap->sw, &record->header.ts_sec, &record->header.ts_usec);
stopwatch_start(pcap->sw);
}
boolean pcap_has_next_record(rdpPcap* pcap)
{
if (pcap->file_size - (ftell(pcap->fp)) <= 16)
return False;
return True;
}
boolean pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record)
{
if (pcap_has_next_record(pcap) != True)
return False;
pcap_read_record_header(pcap, &record->header);
record->length = record->header.incl_len;
record->data = xmalloc(record->length);
return True;
}
boolean pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record)
{
fread(record->data, record->length, 1, pcap->fp);
return True;
}
boolean pcap_get_next_record(rdpPcap* pcap, pcap_record* record)
{
if (pcap_has_next_record(pcap) != True)
return False;
pcap_read_record(pcap, record);
return True;
}
rdpPcap* pcap_open(char* name, boolean write)
{
rdpPcap* pcap;
pcap = (rdpPcap*) xzalloc(sizeof(rdpPcap));
if (pcap != NULL)
{
pcap->name = name;
pcap->write = write;
pcap->record_count = 0;
if (write)
{
pcap->fp = fopen(name, "w+");
pcap->header.magic_number = 0xA1B2C3D4;
pcap->header.version_major = 2;
pcap->header.version_minor = 4;
pcap->header.thiszone = 0;
pcap->header.sigfigs = 0;
pcap->header.snaplen = 65535;
pcap->header.network = 0;
pcap_write_header(pcap, &pcap->header);
}
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);
pcap_read_header(pcap, &pcap->header);
}
pcap->sw = stopwatch_create();
stopwatch_start(pcap->sw);
}
return pcap;
}
void pcap_flush(rdpPcap* pcap)
{
while (pcap->record != NULL)
{
pcap_write_record(pcap, pcap->record);
pcap->record = pcap->record->next;
}
if (pcap->fp != NULL)
fflush(pcap->fp);
}
void pcap_close(rdpPcap* pcap)
{
pcap_flush(pcap);
if (pcap->fp != NULL)
fclose(pcap->fp);
stopwatch_stop(pcap->sw);
stopwatch_free(pcap->sw);
}

View File

@ -56,5 +56,15 @@ void stopwatch_reset(STOPWATCH* stopwatch)
double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch)
{
return ((double)stopwatch->elapsed) / CLOCKS_PER_SEC;
return ((double) stopwatch->elapsed) / CLOCKS_PER_SEC;
}
void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, uint32* sec, uint32* usec)
{
double uelapsed;
*sec = ((uint32) stopwatch->elapsed) / CLOCKS_PER_SEC;
uelapsed = stopwatch->elapsed - ((double)(*sec) * CLOCKS_PER_SEC);
*usec = (uelapsed / (CLOCKS_PER_SEC / 1000000));
}

View File

@ -183,7 +183,7 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
RFX_RECT rect;
STREAM* s;
if (!client->settings->rfx_codec)
if (!client->settings->rfx_codec || !info)
return;
if (info->icon_width < 1)
return;
@ -232,6 +232,33 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
info->icon_y = y;
}
void test_peer_dump_rfx(freerdp_peer* client)
{
STREAM* s;
rdpUpdate* update;
rdpPcap* pcap_rfx;
pcap_record record;
s = stream_new(512);
update = client->update;
client->update->pcap_rfx = pcap_open("rfx_test.pcap", False);
pcap_rfx = client->update->pcap_rfx;
while (pcap_has_next_record(pcap_rfx))
{
pcap_get_next_record_header(pcap_rfx, &record);
s->data = xrealloc(s->data, record.length);
record.data = s->data;
s->size = record.length;
pcap_get_next_record_content(pcap_rfx, &record);
s->p = s->data + s->size;
update->SurfaceCommand(update, s);
}
}
boolean test_peer_post_connect(freerdp_peer* client)
{
/**
@ -259,6 +286,11 @@ boolean test_peer_post_connect(freerdp_peer* client)
test_peer_draw_background(client);
test_peer_load_icon(client);
if (client->update->dump_rfx)
{
test_peer_dump_rfx(client);
}
/* Return False here would stop the execution of the peer mainloop. */
return True;
}