Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
e698c91ef1
3
.gitignore
vendored
3
.gitignore
vendored
@ -30,6 +30,9 @@ docs/api
|
||||
ipch
|
||||
Debug
|
||||
|
||||
# test files
|
||||
*.pcap
|
||||
|
||||
# Binaries
|
||||
*.a
|
||||
*.so
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
99
cunit/test_pcap.c
Normal 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
26
cunit/test_pcap.h
Normal 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);
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
83
include/freerdp/utils/pcap.h
Normal file
83
include/freerdp/utils/pcap.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -30,6 +30,7 @@ set(FREERDP_UTILS_SRCS
|
||||
load_plugin.c
|
||||
memory.c
|
||||
mutex.c
|
||||
pcap.c
|
||||
profiler.c
|
||||
rail.c
|
||||
registry.c
|
||||
|
@ -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
193
libfreerdp-utils/pcap.c
Normal 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);
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user