Merge remote-tracking branch 'upstream/master' into rail

This commit is contained in:
roman-b 2011-08-30 23:16:21 +03:00
commit 585b436915
43 changed files with 1665 additions and 155 deletions

3
.gitignore vendored
View File

@ -14,8 +14,9 @@ Makefile
*.cproject
*.settings
# Doxygen
# Documentation
docs/api
client/X11/xfreerdp.1
# Mac OS X
.DS_Store

View File

@ -122,6 +122,8 @@ static void rdpsnd_pulse_stream_success_callback(pa_stream* stream, int success,
static void rdpsnd_pulse_wait_for_operation(rdpsndPulsePlugin* pulse, pa_operation* operation)
{
if (operation == NULL)
return;
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
{
pa_threaded_mainloop_wait(pulse->mainloop);

View File

@ -17,6 +17,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
include(FindXmlto)
include_directories(${X11_INCLUDE_DIRS})
add_executable(xfreerdp
@ -32,26 +33,41 @@ add_executable(xfreerdp
xf_window.h
xfreerdp.c
xfreerdp.h)
if(WITH_MANPAGES)
if(XMLTO_FOUND)
add_custom_command(OUTPUT xfreerdp.1
COMMAND ${XMLTO_EXECUTABLE} man ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp.1.xml
DEPENDS xfreerdp.1.xml)
add_custom_target(xfreerdp.manpage ALL
DEPENDS xfreerdp.1)
install(FILES xfreerdp.1 DESTINATION share/man/man1)
else(XMLTO_FOUND)
message(WARNING "WITH_MANPAGES was set, but xmlto was not found. man-pages will not be installed")
endif(XMLTO_FOUND)
endif(WITH_MANPAGES)
find_package(Xinerama)
if(XINERAMA_FOUND)
add_definitions(-DWITH_XINERAMA)
add_definitions(-DWITH_XINERAMA -DWITH_XEXT)
include_directories(${XINERAMA_INCLUDE_DIRS})
target_link_libraries(xfreerdp ${XINERAMA_LIBRARIES})
endif()
find_package(Xext)
if(Xext_FOUND)
if(XEXT_FOUND)
add_definitions(-DWITH_XEXT)
include_directories(${Xext_INCLUDE_DIRS})
target_link_libraries(xfreerdp ${Xext_LIBRARIES})
include_directories(${XEXT_INCLUDE_DIRS})
target_link_libraries(xfreerdp ${XEXT_LIBRARIES})
endif()
find_package(Xcursor)
if(Xcursor_FOUND)
add_definitions(-DWITH_XCURSOR)
include_directories(${Xcursor_INCLUDE_DIRS})
target_link_libraries(xfreerdp ${Xext_LIBRARIES})
target_link_libraries(xfreerdp ${Xcursor_LIBRARIES})
endif()
target_link_libraries(xfreerdp freerdp-core)
@ -63,3 +79,4 @@ target_link_libraries(xfreerdp freerdp-utils)
target_link_libraries(xfreerdp ${X11_LIBRARIES})
install(TARGETS xfreerdp DESTINATION bin)

View File

@ -343,7 +343,7 @@ boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app)
if (xfi->mouse_active && (app != True))
XGrabKeyboard(xfi->display, xfi->window->handle, True, GrabModeAsync, GrabModeAsync, CurrentTime);
xf_rail_send_activate(xfi, event->xany.window, True);
//xf_rail_send_activate(xfi, event->xany.window, True);
xf_kbd_focus_in(xfi);
return True;
@ -359,7 +359,7 @@ boolean xf_event_FocusOut(xfInfo* xfi, XEvent* event, boolean app)
if (event->xfocus.mode == NotifyWhileGrabbed)
XUngrabKeyboard(xfi->display, CurrentTime);
xf_rail_send_activate(xfi, event->xany.window, False);
//xf_rail_send_activate(xfi, event->xany.window, False);
return True;
}
@ -476,7 +476,7 @@ boolean xf_event_process(freerdp* instance, XEvent* event)
app = True;
}
#if 1
#if 0
if (event->type != MotionNotify)
printf("X11 %s Event: wnd=0x%X\n", X11_EVENT_STRINGS[event->type], (uint32)event->xany.window);
#endif

View File

@ -82,6 +82,7 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
window->windowId, window->ownerWindowId);
xfparent = NULL;
if (window->ownerWindowId != 0)
{
rdpWindow* p = NULL;
@ -89,7 +90,7 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
p = window_list_get_by_id(xfi->rail->list, window->ownerWindowId);
if (p != NULL)
xfparent = (xfWindow *)p->extra;
xfparent = (xfWindow *) p->extra;
}
xfw = xf_CreateWindow((xfInfo*) rail->extra, xfparent,
@ -97,10 +98,10 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
window->windowWidth, window->windowHeight,
window->windowId);
XStoreName(xfi->display, xfw->handle, window->title);
xf_SetWindowStyle(xfi, xfw, window->style, window->extendedStyle);
XStoreName(xfi->display, xfw->handle, window->title);
window->extra = (void*) xfw;
window->extraId = (void*) xfw->handle;
}
@ -165,6 +166,17 @@ void xf_rail_SetWindowRects(rdpRail* rail, rdpWindow* window)
xf_SetWindowRects(xfi, xfw, window->windowRects, window->numWindowRects);
}
void xf_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window)
{
xfInfo* xfi;
xfWindow* xfw;
xfi = (xfInfo*) rail->extra;
xfw = (xfWindow*) window->extra;
xf_SetWindowVisibilityRects(xfi, xfw, window->windowRects, window->numWindowRects);
}
void xf_rail_DestroyWindow(rdpRail* rail, rdpWindow* window)
{
xfWindow* xfw;
@ -181,6 +193,7 @@ void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail)
rail->SetWindowText = xf_rail_SetWindowText;
rail->SetWindowIcon = xf_rail_SetWindowIcon;
rail->SetWindowRects = xf_rail_SetWindowRects;
rail->SetWindowVisibilityRects = xf_rail_SetWindowVisibilityRects;
rail->DestroyWindow = xf_rail_DestroyWindow;
}

View File

@ -41,9 +41,6 @@ struct _PropMotifWmHints
};
typedef struct _PropMotifWmHints PropMotifWmHints;
void xf_ReferenceWindow(xfInfo* xfi, xfWindow* window);
void xf_DereferenceWindow(xfInfo* xfi, xfWindow* window);
void xf_SendClientMessage(xfInfo* xfi, xfWindow* window, Atom atom, long msg, long d1, long d2, long d3)
{
XEvent xevent;
@ -162,43 +159,38 @@ void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show)
window->decorations = show;
}
void xf_SetWindowUnlisted(xfInfo* xfi, xfWindow* window)
{
Atom window_state[2];
window_state[0] = xfi->_NET_WM_STATE_SKIP_PAGER;
window_state[1] = xfi->_NET_WM_STATE_SKIP_TASKBAR;
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_STATE,
XA_ATOM, 32, PropModeReplace, (uint8*) &window_state, 2);
}
void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style)
{
Atom window_type;
window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
if (((style & WS_POPUP) !=0) ||
((style & WS_DLGFRAME) != 0) ||
((ex_style & WS_EX_DLGMODALFRAME) != 0)
)
if ((style & WS_POPUP) || (style & WS_DLGFRAME) || (ex_style & WS_EX_DLGMODALFRAME))
{
window_type = xfi->_NET_WM_WINDOW_TYPE_DIALOG;
}
else if ((ex_style & WS_EX_TOOLWINDOW) != 0)
if (ex_style & WS_EX_TOOLWINDOW)
{
xf_SetWindowUnlisted(xfi, window);
window_type = xfi->_NET_WM_WINDOW_TYPE_UTILITY;
}
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_WINDOW_TYPE,
xfi->_NET_WM_WINDOW_TYPE, 32, PropModeReplace, (unsigned char*)&window_type, 1);
XA_ATOM, 32, PropModeReplace, (uint8*) &window_type, 1);
}
void xf_SetWindowChildState(xfInfo* xfi, xfWindow* window)
{
Atom window_state[2];
if (window->parent != NULL)
{
window_state[0] = xfi->_NET_WM_STATE_SKIP_PAGER;
window_state[1] = xfi->_NET_WM_STATE_SKIP_TASKBAR;
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_STATE,
xfi->_NET_WM_STATE, 32, PropModeReplace, (unsigned char*)&window_state, 2);
}
}
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height)
{
xfWindow* window;
@ -295,36 +287,18 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width
XGCValues gcv;
int input_mask;
XClassHint* class_hints;
Window parent_handle;
int lx;
int ly;
window->ref_count = 0;
window->decorations = False;
window->fullscreen = False;
window->parent = parent;
lx = x;
ly = y;
parent_handle = RootWindowOfScreen(xfi->screen);
if (window->parent != NULL)
{
lx = x - window->parent->left;
ly = y - window->parent->top;
parent_handle = parent->handle;
}
window->handle = XCreateWindow(xfi->display, parent_handle,
lx, ly, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel, &xfi->attribs);
xf_ReferenceWindow(xfi, window);
xf_ReferenceWindow(xfi, window->parent);
xf_SetWindowDecorations(xfi, window, window->decorations);
xf_SetWindowChildState(xfi, window);
class_hints = XAllocClassHint();
@ -352,10 +326,6 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width
window->gc = XCreateGC(xfi->display, window->handle, GCGraphicsExposures, &gcv);
window->surface = XCreatePixmap(xfi->display, window->handle, window->width, window->height, xfi->depth);
printf("xf_CreateWindow: h=0x%X p=0x%X x=%d y=%d w=%d h=%d\n", (uint32)window->handle,
(window->parent != NULL) ? (uint32)window->parent->handle : 0,
x, y, width, height);
xf_MoveWindow(xfi, window, x, y, width, height);
}
@ -364,37 +334,19 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height)
{
int lx, ly;
Pixmap surface;
if ((width * height) < 1)
return;
printf("xf_MoveWindow: BEFORE correctness h=0x%X x=%d y=%d w=%d h=%d\n",
(uint32) window->handle, x, y, width, height);
xf_FixWindowCoordinates(&x, &y, &width, &height);
if (window->parent != NULL)
{
lx = x - window->parent->left;
ly = y - window->parent->top;
}
else
{
lx = x;
ly = y;
}
printf("xf_MoveWindow: AFTER correctness h=0x%X x=%d y=%d lx=%d ly=%d w=%d h=%d \n",
(uint32) window->handle, x, y, lx, ly, width, height);
if (window->width == width && window->height == height)
XMoveWindow(xfi->display, window->handle, lx, ly);
XMoveWindow(xfi->display, window->handle, x, y);
else if (window->left == x && window->top == y)
XResizeWindow(xfi->display, window->handle, width, height);
else
XMoveResizeWindow(xfi->display, window->handle, lx, ly, width, height);
XMoveResizeWindow(xfi->display, window->handle, x, y, width, height);
surface = XCreatePixmap(xfi->display, window->handle, width, height, xfi->depth);
XCopyArea(xfi->display, surface, window->surface, window->gc, 0, 0, window->width, window->height, 0, 0);
@ -490,42 +442,41 @@ void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int n
xfree(xrects);
}
void xf_ReferenceWindow(xfInfo* xfi, xfWindow* window)
void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects)
{
if (window == NULL) return;
window->ref_count++;
}
int i;
XRectangle* xrects;
void xf_DereferenceWindow(xfInfo* xfi, xfWindow* window)
{
if (window == NULL) return;
xrects = xmalloc(sizeof(XRectangle) * nrects);
window->ref_count--;
if (window->ref_count == 0)
for (i = 0; i < nrects; i++)
{
printf("xf_DerefrenceWindow: destroying h=0x%X p=0x%X\n", (uint32)window->handle,
(window->parent != NULL) ? (uint32)window->parent->handle : 0);
if (window->gc)
XFreeGC(xfi->display, window->gc);
if (window->surface)
XFreePixmap(xfi->display, window->surface);
if (window->handle)
{
XUnmapWindow(xfi->display, window->handle);
XDestroyWindow(xfi->display, window->handle);
}
xfree(window);
xrects[i].x = rects[i].left;
xrects[i].y = rects[i].top;
xrects[i].width = rects[i].right - rects[i].left;
xrects[i].height = rects[i].bottom - rects[i].top;
}
#ifdef WITH_XEXT
XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif
xfree(xrects);
}
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window)
{
xfWindow* parent = window->parent;
if (window->gc)
XFreeGC(xfi->display, window->gc);
printf("xf_DestroyWindow: h=0x%X p=0x%X\n", (uint32)window->handle,
(window->parent != NULL) ? (uint32)window->parent->handle : 0);
if (window->surface)
XFreePixmap(xfi->display, window->surface);
xf_DereferenceWindow(xfi, window);
xf_DereferenceWindow(xfi, parent);
if (window->handle)
{
XUnmapWindow(xfi->display, window->handle);
XDestroyWindow(xfi->display, window->handle);
}
xfree(window);
}

View File

@ -52,6 +52,7 @@ boolean xf_GetWorkArea(xfInfo* xfi);
void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen);
void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show);
void xf_SetWindowUnlisted(xfInfo* xfi, xfWindow* window);
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height);
@ -60,6 +61,7 @@ void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int h
void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state);
void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon);
void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style);
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window);

389
client/X11/xfreerdp.1.xml Normal file
View File

@ -0,0 +1,389 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<refentry>
<refentryinfo>
<date>2011-08-27</date>
<author>
<authorblurb><para>The FreeRDP-Team</para></authorblurb>
</author>
</refentryinfo>
<refmeta>
<refentrytitle>xfreerdp</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="source">freerdp</refmiscinfo>
<refmiscinfo class="manual">xfreerdp</refmiscinfo>
</refmeta>
<refnamediv>
<refname><application>xfreerdp</application></refname>
<refpurpose>X11 frontend to libFreeRDP</refpurpose>
</refnamediv>
<refsynopsisdiv>
<refsynopsisdivinfo>
<date>2011-08-27</date>
</refsynopsisdivinfo>
<para>
<command>xfreerdp</command> [options] server[:port] [[options] server[:port] …]
</para>
</refsynopsisdiv>
<refsect1>
<refsect1info>
<date>2011-08-27</date>
</refsect1info>
<title>DESCRIPTION</title>
<para>
<command>xfreerdp</command> is a frontend to libFreeRDP,
which implements a client to the Remote Desktop Protocol (RDP).
RDP is used in a number of Microsoft products including Microsoft Windows
versions starting from NT Terminal Server. RDP is also implemented by xrdp and VirtualBox.
</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>-0</term>
<listitem>
<para>
Attach to the admin console of the server.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-a <replaceable class="parameter">bpp</replaceable></term>
<listitem>
<para>
Sets the color depth for the connection to <replaceable class="parameter">bpp</replaceable> bits per pixel.
Valid values are 8, 15, 16, 24 and 32. The default value is the color depth of the FreeRDP-window.
</para>
</listitem>
</varlistentry>
<varlistentry id="WorkingDir">
<term>-c <replaceable class="parameter">dir</replaceable></term>
<listitem>
<para>
Sets the working-dir to <replaceable class="parameter">dir</replaceable>.
This parameter is only used when an AlternateShell (<xref linkend="AlternateShell"/>) is requested.
<replaceable class="parameter">dir</replaceable> should contain the executable file specified in the AlternateShell.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-D</term>
<listitem>
<para>
Removes the windows decorations.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d</term>
<listitem>
<para>
Domain used in authentication.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-f</term>
<listitem>
<para>
start in full screen mode. This mode can always be en- and disabled using Ctrl-Alt-Enter.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-g <replaceable class="parameter">geometry</replaceable></term>
<listitem>
<para>
Sets the size of the FreeRDP-window (and of the remote desktop, when establishing a new connection).
<replaceable class="parameter">geometry</replaceable> can have one of the following forms:
<itemizedlist>
<listitem>
<para>
<replaceable class="parameter">W</replaceable>x<replaceable class="parameter">H</replaceable> -
in this case the resulting window will be of
<replaceable class="parameter">W</replaceable>x<replaceable class="parameter">H</replaceable> pixels.
</para>
</listitem>
<listitem>
<para>
<replaceable class="parameter">P</replaceable>% -
in this case the resulting window will be <replaceable class="parameter">P</replaceable>%
of your screen.
</para>
</listitem>
<listitem>
<para>
The special keyword <emphasis>workarea</emphasis> -
in this case the resulting window will be of the same size as your workarea.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-k <replaceable class="parameter">id</replaceable></term>
<listitem>
<para>
Sets the keyboard-layout-id to <replaceable class="parameter">id</replaceable>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-m</term>
<listitem>
<para>
Don't send mouse motion events.
<!-- TODO: what is this good for? -->
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-n <replaceable class="parameter">hostname</replaceable></term>
<listitem>
<para>
Set the reported client hostname to <replaceable class="parameter">hostname</replaceable>.
Default is to automatically detect the hostname.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-o</term>
<listitem>
<para>
Play audio on the console instead of redirecting to the client.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-p <replaceable class="parameter">password</replaceable></term>
<listitem>
<para>
Password used in authentication.
</para>
</listitem>
</varlistentry>
<varlistentry id="AlternateShell">
<term>-s <replaceable class="parameter">shell</replaceable></term>
<listitem>
<para>
Sets the startup-shell to <replaceable class="parameter">shell</replaceable>.
This parameter should contain a complete path to the alternate shell.
If the alternete shell requires a different working directory use <xref linkend="WorkingDir"/>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-t <replaceable class="parameter">port</replaceable></term>
<listitem>
<para>
Connect to <replaceable class="parameter">port</replaceable>, instead of the default 3389.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-u <replaceable class="parameter">username</replaceable></term>
<listitem>
<para>
Username used in authentication.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-x <replaceable class="parameter">flag</replaceable></term>
<listitem>
<para>
Set the experiance performance flags.
<replaceable class="parameter">flag</replaceable> can be one of:
<itemizedlist>
<listitem>
<para>
m - (modem): Equivalent to 15.
</para>
</listitem>
<listitem>
<para>
b - (broadband): Equivalent to 1.
</para>
</listitem>
<listitem>
<para>
l - (lan): Equivalent to 0.
</para>
</listitem>
<listitem>
<para>
<replaceable class="parameter">num</replaceable> - A number that represents a
bit-mask, were numbers mean the following
<footnote><para>Taken from <ulink url="http://msdn.microsoft.com/en-us/library/cc240476%28v=prot.10%29.aspx">
MS-RDPBCGR Scetion 2.2.1.11.1.1.1 - Extended Info Packet</ulink></para></footnote>:
<itemizedlist>
<listitem>
<para>1: Disable desktop wallpaper.</para>
</listitem>
<listitem>
<para>2: Disable full-window drag (only the window outline is displayed when the window is moved).</para>
</listitem>
<listitem>
<para>4: Disable menu animations.</para>
</listitem>
<listitem>
<para>8: Disable user interface themes.</para>
</listitem>
<listitem>
<para>32: Disable mouse cursor shadows.</para>
</listitem>
<listitem>
<para>64: Disable cursor blinking.</para>
</listitem>
<listitem>
<para>128: Enable font smoothing.</para>
</listitem>
<listitem>
<para>256: Enable Desktop Composition.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-z</term>
<listitem>
<para>
Enable compression.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--app</term>
<listitem>
<para>
initialize a RemoteApp connection. This implies -g workarea.
FIXME: How to do RemoteApp
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--ext</term>
<listitem>
<para>
load an extension
FIXME: How to do this
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--no-auth</term>
<listitem>
<para>
Skips authentication. This is useful e.g. for the current FreeRDP server that doesn't yet support server-side authentication.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--no-fastpath</term>
<listitem>
<para>
Disables fast-path. Use slow-path packets instead, which have larger headers.
It might be good for debugging certain issues when you suspect it might be
linked to the parsing of one of the two header types.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--no-osb</term>
<listitem>
<para>
Disable off screen bitmaps.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--plugin</term>
<listitem>
<para>
load a plugin
FIXME: How to do this
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--rfx</term>
<listitem>
<para>
Enable RemoteFX.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--no-rdp</term>
<listitem>
<para>
Disable Standard RDP encryption.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--no-tls</term>
<listitem>
<para>
Disable TLS encryption.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--no-nla</term>
<listitem>
<para>
Disable network level authentication.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--sec <replaceable class="parameter">proto</replaceable></term>
<listitem>
<para>
force protocol security. <replaceable class="parameter">proto</replaceable> can be one of rdp, tls or nla.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--version</term>
<listitem>
<para>
Print version information.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<!-- refsect1>
<title>USAGE</title>
<para>
<command>foo</command> -f foo.conf -d2 foodata.foo
</para>
</refsect1 -->
<!-- refsect1>
<title>CAVEATS</title>
<para>
Other programs named <command>foo</command> may exist and actually
do something!
</para>
</refsect1 -->
<!-- refsect1>
<title>BUGS</title>
<para>
None. Program does nothing.
</para>
</refsect1 -->
<refsect1>
<title>LINKS</title>
<para>
<ulink url="http://www.freerdp.com/">http://www.freerdp.com/</ulink>
</para>
</refsect1>
</refentry>

View File

@ -718,7 +718,7 @@ int main(int argc, char* argv[])
chanman = freerdp_chanman_new();
SET_CHANMAN(instance, chanman);
instance->settings->sw_gdi = False;
instance->settings->sw_gdi = True;
if (freerdp_parse_args(instance->settings, argc, argv,
xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0)

View File

@ -9,5 +9,6 @@ option(WITH_DEBUG_CERTIFICATE "Print certificate related debug messages." OFF)
option(WITH_DEBUG_LICENSE "Print license debug messages." OFF)
option(WITH_DEBUG_GDI "Print graphics debug messages." OFF)
option(WITH_DEBUG_RFX "Print RemoteFX debug messages." OFF)
option(WITH_MANPAGES "Generate manpages." ON)
option(WITH_PROFILER "Compile profiler." OFF)
option(WITH_SSE2 "Use SSE2 optimization." OFF)

View File

@ -28,22 +28,22 @@
# limitations under the License.
#=============================================================================
find_path(Xext_INCLUDE_DIR NAMES Xext.h
find_path(XEXT_INCLUDE_DIR NAMES Xext.h
PATH_SUFFIXES X11/extensions
DOC "The Xext include directory"
)
find_library(Xext_LIBRARY NAMES Xext
find_library(XEXT_LIBRARY NAMES Xext
DOC "The Xext library"
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xext DEFAULT_MSG Xext_LIBRARY Xext_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(XEXT DEFAULT_MSG XEXT_LIBRARY XEXT_INCLUDE_DIR)
if(Xext_FOUND)
set( Xext_LIBRARIES ${Xext_LIBRARY} )
set( Xext_INCLUDE_DIRS ${Xext_INCLUDE_DIR} )
if(XEXT_FOUND)
set( XEXT_LIBRARIES ${XEXT_LIBRARY} )
set( XEXT_INCLUDE_DIRS ${XEXT_INCLUDE_DIR} )
endif()
mark_as_advanced(Xext_INCLUDE_DIR Xext_LIBRARY)
mark_as_advanced(XEXT_INCLUDE_DIR XEXT_LIBRARY)

35
cmake/FindXmlto.cmake Normal file
View File

@ -0,0 +1,35 @@
# - Find xmlto
# Find the xmlto docbook xslt frontend
#
# This module defines the following variables:
# XMLTO_FOUND - True if xmlto was found
# XMLTO_EXECUTABLE - Path to xmlto, if xmlto was found
#
#=============================================================================
# Copyright 2011 Nils Andresen <nils@nils-andresen.de>
#
# 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.
#=============================================================================
set(XMLTO_FOUND false)
find_program(XMLTO_EXECUTABLE
NAMES xmlto
DOC "docbook xslt frontend")
if(XMLTO_EXECUTABLE)
set(XMLTO_FOUND true)
message(STATUS "Found XMLTO: ${XMLTO_EXECUTABLE}")
endif()
mark_as_advanced(XMLTO_EXECUTABLE)

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

@ -17,5 +17,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
file(GLOB HEADERS "freerdp/*.h")
file(GLOB HEADERS "freerdp/*")
install_files(/include/freerdp FILES ${HEADERS})

View File

@ -40,6 +40,7 @@ typedef void (*railShowWindow)(rdpRail* rail, rdpWindow* window, uint8 state);
typedef void (*railSetWindowText)(rdpRail* rail, rdpWindow* window);
typedef void (*railSetWindowIcon)(rdpRail* rail, rdpWindow* window, rdpIcon* icon);
typedef void (*railSetWindowRects)(rdpRail* rail, rdpWindow* window);
typedef void (*railSetWindowVisibilityRects)(rdpRail* rail, rdpWindow* window);
struct rdp_rail
{
@ -56,6 +57,7 @@ struct rdp_rail
railSetWindowText SetWindowText;
railSetWindowIcon SetWindowIcon;
railSetWindowRects SetWindowRects;
railSetWindowVisibilityRects SetWindowVisibilityRects;
};
FREERDP_API void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update);

View File

@ -297,6 +297,11 @@ struct rdp_settings
uint8 rfx_codec_id;
boolean frame_acknowledge;
boolean dump_rfx;
boolean play_rfx;
char* dump_rfx_file;
char* play_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,10 @@ struct rdp_update
void* param1;
void* param2;
boolean dump_rfx;
boolean play_rfx;
rdpPcap* pcap_rfx;
pcBeginPaint BeginPaint;
pcEndPaint EndPaint;
pcSetBounds SetBounds;
@ -1142,6 +1149,7 @@ struct rdp_update
pcNonMonitoredDesktop NonMonitoredDesktop;
pcSurfaceBits SurfaceBits;
pcSurfaceCommand SurfaceCommand;
BITMAP_UPDATE bitmap_update;
PALETTE_UPDATE palette_update;

View File

@ -0,0 +1,42 @@
#ifndef __CERTSTORE_UTILS_H
#define __CERTSTORE_UTILS_H
typedef struct rdp_certstore rdpCertstore;
typedef struct rdp_certdata rdpCertdata;
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <freerdp/api.h>
#include <freerdp/freerdp.h>
#include <freerdp/utils/memory.h>
struct rdp_certdata
{
char* thumbprint;
char* hostname;
};
struct rdp_certstore
{
FILE* fp;
char* path;
char* file;
char* home;
int match;
struct rdp_certdata* certdata;
};
void certstore_create(rdpCertstore* certstore);
void certstore_open(rdpCertstore* certstore);
void certstore_load(rdpCertstore* certstore);
void certstore_close(rdpCertstore* certstore);
char* get_local_certloc();
rdpCertdata* certdata_new(char* host_name,char* fingerprint);
void certdata_free(rdpCertdata* certdata);
void certstore_init(rdpCertstore* certstore);
rdpCertstore* certstore_new(rdpCertdata* certdata);
void certstore_free(rdpCertstore* certstore);
int match_certdata(rdpCertstore* certstore);
void print_certdata(rdpCertstore* certstore);
#endif /* __CERTSTORE_UTILS_H */

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

@ -1371,6 +1371,10 @@ void rdp_read_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings)
*/
void rdp_write_rfx_client_capability_container(STREAM* s, rdpSettings* settings)
{
uint16 captureFlags;
captureFlags = settings->dump_rfx ? 0 : CARDP_CAPS_CAPTURE_NON_CAC;
stream_write_uint16(s, 49); /* codecPropertiesLength */
/* TS_RFX_CLNT_CAPS_CONTAINER */

View File

@ -8,7 +8,7 @@
* 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
* 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,
@ -25,7 +25,6 @@
#include "ntlmssp.h"
#include "credssp.h"
/**
* TSRequest ::= SEQUENCE {
* version [0] INTEGER,
@ -109,7 +108,7 @@ int credssp_get_public_key(rdpCredssp* credssp)
{
int ret;
CryptoCert cert;
cert = tls_get_certificate(credssp->transport->tls);
if (cert == NULL)
@ -117,7 +116,8 @@ int credssp_get_public_key(rdpCredssp* credssp)
printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n");
return 0;
}
if(tls_verify_certificate(cert,credssp->transport->settings->hostname))
tls_disconnect(credssp->transport->tls);
ret = crypto_cert_get_public_key(cert, &credssp->public_key);
crypto_cert_free(cert);

View File

@ -8,7 +8,7 @@
* 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
* 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,
@ -189,3 +189,113 @@ void crypto_nonce(uint8* nonce, int size)
{
RAND_bytes((void*) nonce, size);
}
char* crypto_cert_fingerprint(X509* xcert)
{
char* p;
int i = 0;
char* fp_buffer;
unsigned int fp_len;
unsigned char fp[EVP_MAX_MD_SIZE];
X509_digest(xcert, EVP_sha1(), fp, &fp_len);
fp_buffer = xzalloc(3 * fp_len);
p = fp_buffer;
for (i = 0; i < fp_len - 1; i++)
{
sprintf(p, "%02x:", fp[i]);
p = (char*) &fp_buffer[i * 3];
}
sprintf(p, "%02x", fp[i]);
return fp_buffer;
}
boolean x509_verify_cert(CryptoCert cert)
{
char* cert_loc;
X509_STORE_CTX* csc;
boolean status = False;
X509_STORE* cert_ctx = NULL;
X509_LOOKUP* lookup = NULL;
X509* xcert = cert->px509;
cert_ctx = X509_STORE_new();
if (cert_ctx == NULL)
goto end;
OpenSSL_add_all_algorithms();
lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
if (lookup == NULL)
goto end;
lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
if (lookup == NULL)
goto end;
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
cert_loc = get_local_certloc();
if(cert_loc != NULL)
{
X509_LOOKUP_add_dir(lookup, cert_loc, X509_FILETYPE_ASN1);
xfree(cert_loc);
}
csc = X509_STORE_CTX_new();
if (csc == NULL)
goto end;
X509_STORE_set_flags(cert_ctx, 0);
if(!X509_STORE_CTX_init(csc, cert_ctx, xcert, 0))
goto end;
if (X509_verify_cert(csc) == 1)
status = True;
X509_STORE_CTX_free(csc);
X509_STORE_free(cert_ctx);
end:
return status;
}
rdpCertdata* crypto_get_certdata(X509* xcert, char* hostname)
{
char* fp;
rdpCertdata* certdata;
fp = crypto_cert_fingerprint(xcert);
certdata = certdata_new(hostname, fp);
xfree(fp);
return certdata;
}
void crypto_cert_printinfo(X509* xcert)
{
char* fp;
char* issuer;
char* subject;
subject = X509_NAME_oneline(X509_get_subject_name(xcert), NULL, 0);
issuer = X509_NAME_oneline(X509_get_issuer_name(xcert), NULL, 0);
fp = crypto_cert_fingerprint(xcert);
printf("Certificate details:\n");
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fp);
printf("The above X.509 certificate could not be verified, possibly because you do not have "
"the CA certificate in your certificate store, or the certificate has expired."
"Please look at the documentation on how to create local certificate store for a private CA.\n");
xfree(fp);
}

View File

@ -45,6 +45,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/utils/blob.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/certstore.h>
struct crypto_sha1_struct
{
@ -83,8 +84,12 @@ void crypto_rc4_free(CryptoRc4 rc4);
typedef struct crypto_cert_struct* CryptoCert;
CryptoCert crypto_cert_read(uint8* data, uint32 length);
char* cypto_cert_fingerprint(X509* xcert);
void crypto_cert_printinfo(X509* xcert);
void crypto_cert_free(CryptoCert cert);
boolean x509_verify_cert(CryptoCert cert);
boolean crypto_cert_verify(CryptoCert server_cert, CryptoCert cacert);
rdpCertdata* crypto_get_certdata(X509* xcert, char* hostname);
boolean crypto_cert_get_public_key(CryptoCert cert, rdpBlob* public_key);
void crypto_rsa_encrypt(uint8* input, int length, uint32 key_length, uint8* modulus, uint8* exponent, uint8* output);

View File

@ -73,6 +73,26 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
return length;
}
inline void fastpath_read_update_header(STREAM* s, uint8* updateCode, uint8* fragmentation, uint8* compression)
{
uint8 updateHeader;
stream_read_uint8(s, updateHeader);
*updateCode = updateHeader & 0x0F;
*fragmentation = (updateHeader >> 4) & 0x03;
*compression = (updateHeader >> 6) & 0x03;
}
inline void fastpath_write_update_header(STREAM* s, uint8 updateCode, uint8 fragmentation, uint8 compression)
{
uint8 updateHeader = 0;
updateHeader |= updateCode & 0x0F;
updateHeader |= (fragmentation & 0x03) << 4;
updateHeader |= (compression & 0x03) << 6;
stream_write_uint8(s, updateHeader);
}
boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s)
{
/* TODO: fipsInformation */
@ -122,7 +142,7 @@ static void fastpath_recv_update_common(rdpFastPath* fastpath, STREAM* s)
}
}
static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint16 size, STREAM* s)
static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint32 size, STREAM* s)
{
switch (updateCode)
{
@ -175,19 +195,16 @@ static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint16
static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
{
uint8 updateHeader;
uint16 size;
int next_pos;
uint32 totalSize;
uint8 updateCode;
uint8 fragmentation;
uint8 compression;
uint8 compressionFlags;
uint16 size;
STREAM* update_stream;
int next_pos;
stream_read_uint8(s, updateHeader);
updateCode = updateHeader & 0x0F;
fragmentation = (updateHeader >> 4) & 0x03;
compression = (updateHeader >> 6) & 0x03;
fastpath_read_update_header(s, &updateCode, &fragmentation, &compression);
if (compression == FASTPATH_OUTPUT_COMPRESSION_USED)
stream_read_uint8(s, compressionFlags);
@ -207,6 +224,7 @@ static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
update_stream = NULL;
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
{
totalSize = size;
update_stream = s;
}
else
@ -220,13 +238,13 @@ static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
if (fragmentation == FASTPATH_FRAGMENT_LAST)
{
update_stream = fastpath->updateData;
size = stream_get_length(update_stream);
totalSize = stream_get_length(update_stream);
stream_set_pos(update_stream, 0);
}
}
if (update_stream)
fastpath_recv_update(fastpath, updateCode, size, update_stream);
fastpath_recv_update(fastpath, updateCode, totalSize, update_stream);
stream_set_pos(s, next_pos);
}
@ -394,7 +412,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)
@ -457,9 +475,10 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
uint16 length;
length = stream_get_length(s);
if (length > FASTPATH_MAX_PACKET_SIZE)
{
printf("Maximum FastPath Update PDU length is %d\n", FASTPATH_MAX_PACKET_SIZE);
printf("Maximum FastPath Update PDU length is %d (actual:%d)\n", FASTPATH_MAX_PACKET_SIZE, length);
return False;
}
@ -475,6 +494,41 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
return True;
}
boolean fastpath_send_fragmented_update_pdu(rdpFastPath* fastpath, STREAM* s)
{
int fragment;
uint16 length;
uint16 maxLength;
uint32 totalLength;
uint8 fragmentation;
STREAM* update;
maxLength = FASTPATH_MAX_PACKET_SIZE - 6;
totalLength = stream_get_length(s);
stream_set_pos(s, 0);
for (fragment = 0; totalLength > 0; fragment++)
{
update = fastpath_update_pdu_init(fastpath);
length = MIN(maxLength, totalLength);
totalLength -= length;
if (totalLength == 0)
fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST;
else
fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT;
fastpath_write_update_header(update, FASTPATH_UPDATETYPE_SURFCMDS, fragmentation, 0);
stream_write_uint16(update, length);
stream_write(update, s->p, length);
stream_seek(s, length);
fastpath_send_update_pdu(fastpath, update);
}
return True;
}
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId)
{
STREAM* s;
@ -520,19 +574,17 @@ boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_C
}
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);
}
else
{
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT);
}
size += fragment_size;
ep = stream_get_pos(s);
stream_set_pos(s, bp);
stream_write_uint8(s, FASTPATH_UPDATETYPE_SURFCMDS | (fragmentation << 4));
fastpath_write_update_header(s, FASTPATH_UPDATETYPE_SURFCMDS, fragmentation, 0);
stream_write_uint16(s, size);
stream_set_pos(s, ep);

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

@ -20,6 +20,7 @@
#include "rdp.h"
#include "input.h"
#include "update.h"
#include "surface.h"
#include "transport.h"
#include "connection.h"
@ -34,10 +35,51 @@ 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);
if (instance->settings->play_rfx)
{
STREAM* s;
rdpUpdate* update;
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);
update = instance->update;
while (pcap_has_next_record(update->pcap_rfx))
{
pcap_get_next_record_header(update->pcap_rfx, &record);
s->data = xrealloc(s->data, record.length);
record.data = s->data;
s->size = record.length;
pcap_get_next_record_content(update->pcap_rfx, &record);
stream_set_pos(s, 0);
update->BeginPaint(update);
update_recv_surfcmds(update, s->size, s);
update->EndPaint(update);
}
xfree(s->data);
return True;
}
}
return status;
}

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);
@ -56,12 +58,16 @@ static int update_recv_surfcmd_frame_marker(rdpUpdate* update, STREAM* s)
return 6;
}
boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
boolean update_recv_surfcmds(rdpUpdate* update, uint32 size, STREAM* s)
{
uint8* mark;
uint16 cmdType;
uint32 cmdLength;
while (size > 2)
{
stream_get_mark(s, mark);
stream_read_uint16(s, cmdType);
size -= 2;
@ -69,17 +75,25 @@ boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
{
case CMDTYPE_SET_SURFACE_BITS:
case CMDTYPE_STREAM_SURFACE_BITS:
size -= update_recv_surfcmd_surface_bits(update, s);
cmdLength = update_recv_surfcmd_surface_bits(update, s);
break;
case CMDTYPE_FRAME_MARKER:
size -= update_recv_surfcmd_frame_marker(update, s);
cmdLength = update_recv_surfcmd_frame_marker(update, s);
break;
default:
DEBUG_WARN("unknown cmdType 0x%X", cmdType);
return False;
}
size -= cmdLength;
if (update->dump_rfx)
{
pcap_add_record(update->pcap_rfx, mark, cmdLength + 2);
pcap_flush(update->pcap_rfx);
}
}
return True;
}

View File

@ -39,7 +39,7 @@ enum SURFCMD_FRAMEACTION
SURFACECMD_FRAMEACTION_END = 0x0001
};
boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s);
boolean update_recv_surfcmds(rdpUpdate* update, uint32 size, STREAM* s);
void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd);
void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId);

View File

@ -8,7 +8,7 @@
* 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
* 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,
@ -240,7 +240,7 @@ rdpTls* tls_new()
tls->connect = tls_connect;
tls->accept = tls_accept;
tls->disconnect = tls_disconnect;
SSL_load_error_strings();
SSL_library_init();
}
@ -248,6 +248,69 @@ rdpTls* tls_new()
return tls;
}
int tls_verify_certificate(CryptoCert cert, char* hostname)
{
boolean ret;
ret = x509_verify_cert(cert);
if (!ret)
{
rdpCertdata* certdata;
certdata = crypto_get_certdata(cert->px509, hostname);
rdpCertstore* certstore = certstore_new(certdata);
if (match_certdata(certstore) == 0)
goto end;
if (certstore->match == 1)
{
char answer;
crypto_cert_printinfo(cert->px509);
while(1)
{
printf("Do you trust the above certificate? (Y/N) ");
answer=fgetc(stdin);
if(answer=='y' || answer =='Y')
{
print_certdata(certstore);
break;
}
else if(answer=='n' || answer=='N')
{
certstore_free(certstore);
return 1;
}
}
}
else if (certstore->match == -1)
{
tls_print_cert_error();
certstore_free(certstore);
return 1;
}
end:
certstore_free(certstore);
}
return 0;
}
void tls_print_cert_error()
{
printf("#####################################\n");
printf("##############WARNING################\n");
printf("#####################################\n");
printf("The thumbprint of certificate received\n");
printf("did not match the stored thumbprint.You\n");
printf("might be a victim of MAN in the MIDDLE\n");
printf("ATTACK.It is also possible that server's\n");
printf("certificate have been changed.In that case\n");
printf("contact your server administrator\n");
}
void tls_free(rdpTls* tls)
{
if (tls != NULL)

View File

@ -49,8 +49,9 @@ boolean tls_disconnect(rdpTls* tls);
int tls_read(rdpTls* tls, uint8* data, int length);
int tls_write(rdpTls* tls, uint8* data, int length);
CryptoCert tls_get_certificate(rdpTls* tls);
int tls_verify_certificate(CryptoCert cert,char* hostname);
void tls_print_cert_error();
boolean tls_print_error(char* func, SSL* connection, int value);
rdpTls* tls_new();
void tls_free(rdpTls* tls);

View File

@ -322,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);
}
@ -362,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

@ -284,6 +284,10 @@ void rail_CreateWindow(rdpRail* rail, rdpWindow* window)
{
IFCALL(rail->SetWindowRects, rail, window);
}
if (window->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
{
IFCALL(rail->SetWindowVisibilityRects, rail, window);
}
}
void rail_UpdateWindow(rdpRail* rail, rdpWindow* window)
@ -356,7 +360,7 @@ void rail_UpdateWindow(rdpRail* rail, rdpWindow* window)
if (window->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
{
IFCALL(rail->SetWindowVisibilityRects, rail, window);
}
}

View File

@ -30,9 +30,11 @@ set(FREERDP_UTILS_SRCS
load_plugin.c
memory.c
mutex.c
pcap.c
profiler.c
rail.c
registry.c
certstore.c
semaphore.c
sleep.c
stopwatch.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)
@ -242,6 +282,28 @@ 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("--play-rfx", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing file name\n");
return -1;
}
settings->play_rfx_file = xstrdup(argv[index]);
settings->play_rfx = True;
}
else if (strcmp("-m", argv[index]) == 0)
{
settings->mouse_motion = True;

View File

@ -0,0 +1,213 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* certstore Utils
*
* Copyright 2011 Jiten Pathy
*
* 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/utils/certstore.h>
#ifdef _WIN32
#include <windows.h>
#endif
static char cert_dir[] = "freerdp";
static char cert_loc[] = "cacert";
static char certstore_file[] = "known_hosts";
void certstore_create(rdpCertstore* certstore)
{
certstore->fp = fopen((char*)certstore->file, "w+");
if (certstore->fp == NULL)
{
printf("certstore_create: error opening [%s] for writing\n", certstore->file);
return;
}
fflush(certstore->fp);
}
void certstore_load(rdpCertstore* certstore)
{
certstore->fp = fopen((char*)certstore->file, "r+");
}
void certstore_open(rdpCertstore* certstore)
{
struct stat stat_info;
if (stat((char*)certstore->file, &stat_info) != 0)
certstore_create(certstore);
else
certstore_load(certstore);
}
void certstore_close(rdpCertstore* certstore)
{
if (certstore->fp != NULL)
fclose(certstore->fp);
}
char* get_local_certloc()
{
char *home_path;
char *certloc;
struct stat stat_info;
home_path=getenv("HOME");
certloc=(char*)xmalloc(strlen(home_path)+strlen("/.")+strlen(cert_dir)+strlen("/")+strlen(cert_loc)+1);
sprintf(certloc,"%s/.%s/%s",home_path,cert_dir,cert_loc);
if(stat((char*)certloc, &stat_info) != 0)
mkdir(certloc, S_IRUSR | S_IWUSR | S_IXUSR);
return certloc;
}
void certstore_init(rdpCertstore* certstore)
{
int length;
char* home_path;
struct stat stat_info;
certstore->match=1;
home_path = getenv("HOME");
if (home_path == NULL)
{
printf("could not get home path\n");
return;
}
certstore->home = (char*) xstrdup(home_path);
printf("home path: %s\n", certstore->home);
certstore->path = (char*) xmalloc(strlen(certstore->home) + strlen("/.") + strlen(cert_dir) + 1);
sprintf(certstore->path, "%s/.%s", certstore->home, cert_dir);
printf("certstore path: %s\n", certstore->path);
if (stat(certstore->path, &stat_info) != 0)
{
#ifndef _WIN32
mkdir(certstore->path, S_IRUSR | S_IWUSR | S_IXUSR);
#else
CreateDirectory(certstore->path, 0);
#endif
printf("creating directory %s\n", certstore->path);
}
length = strlen(certstore->path);
certstore->file = (char*) xmalloc(strlen(certstore->path) + strlen("/") + strlen(certstore_file) + 1);
sprintf(certstore->file, "%s/%s", certstore->path, certstore_file);
printf("certstore file: %s\n", certstore->file);
certstore_open(certstore);
}
rdpCertdata* certdata_new(char* host_name,char* fingerprint)
{
rdpCertdata* certdata=(rdpCertdata*)xzalloc(sizeof(rdpCertdata));
if(certdata !=NULL)
{
certdata->hostname=xzalloc(strlen(host_name)+1);
certdata->thumbprint=xzalloc(strlen(fingerprint)+1);
sprintf(certdata->hostname,"%s",host_name);
sprintf(certdata->thumbprint,"%s",fingerprint);
}
return certdata;
}
void certdata_free(rdpCertdata* certdata)
{
if(certdata != NULL)
{
xfree(certdata->hostname);
xfree(certdata->thumbprint);
xfree(certdata);
}
}
rdpCertstore* certstore_new(rdpCertdata* certdata)
{
rdpCertstore* certstore = (rdpCertstore*) xzalloc(sizeof(rdpCertstore));
if (certstore != NULL)
{
certstore->certdata = certdata;
certstore_init(certstore);
}
return certstore;
}
void certstore_free(rdpCertstore* certstore)
{
if (certstore != NULL)
{
certstore_close(certstore);
xfree(certstore->path);
xfree(certstore->file);
xfree(certstore->home);
certdata_free(certstore->certdata);
xfree(certstore);
}
}
int match_certdata(rdpCertstore* certstore)
{
char *host;
char *p;
char *thumb_print;
int length;
unsigned char c;
FILE* cfp;
cfp=certstore->fp;
rdpCertdata* cert_data=certstore->certdata;
length=strlen(cert_data->thumbprint);
host=xzalloc(strlen(cert_data->hostname)+1);
for(;;)
{
if((int)fread(host,sizeof(char),strlen(cert_data->hostname),cfp) < strlen(cert_data->hostname))
break;
if((!strcmp(host,cert_data->hostname)) && ((c=fgetc(cfp))==' ' || c=='\t') )
{
ungetc(c,cfp);
while((c=fgetc(cfp))==' ' || c=='\t');
if(c==EOF)
break;
ungetc(c,cfp);
thumb_print=xzalloc(length+1);
p=thumb_print;
while((p-thumb_print) < length && (*p=fgetc(cfp))!=EOF && *p!='\n' && *p==*(cert_data->thumbprint+(p-thumb_print)))
p++;
if(p-thumb_print==length)
certstore->match=0;
else
certstore->match=-1;
break;
}
else
{
while(c!='\n' && c!=EOF)
c=fgetc(cfp);
if(c==EOF)
break;
}
}
xfree(host);
return certstore->match;
}
void print_certdata(rdpCertstore* certstore)
{
fseek(certstore->fp,0,SEEK_END);
fprintf(certstore->fp,"%s %s\n",certstore->certdata->hostname,certstore->certdata->thumbprint);
}

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 = 0xFFFFFFFF;
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

@ -30,6 +30,8 @@
#include <freerdp/rfx/rfx.h>
#include <freerdp/listener.h>
static char* test_pcap_file = NULL;
/* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */
static const unsigned int test_quantization_values[] =
{
@ -183,6 +185,8 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
RFX_RECT rect;
STREAM* s;
if (client->update->dump_rfx)
return;
if (!client->settings->rfx_codec || !info)
return;
if (info->icon_width < 1)
@ -232,6 +236,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(test_pcap_file, 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)
{
/**
@ -256,9 +287,18 @@ boolean test_peer_post_connect(freerdp_peer* client)
/* A real server should tag the peer as activated here and start sending updates in mainloop. */
test_peer_init(client);
test_peer_draw_background(client);
test_peer_load_icon(client);
if (test_pcap_file != NULL)
{
client->update->dump_rfx = True;
test_peer_dump_rfx(client);
}
else
{
test_peer_draw_background(client);
}
/* Return False here would stop the execution of the peer mainloop. */
return True;
}
@ -292,13 +332,13 @@ void test_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uin
static void* test_peer_mainloop(void* arg)
{
freerdp_peer* client = (freerdp_peer*)arg;
int i;
int fds;
int max_fds;
int rcount;
void* rfds[32];
fd_set rfds_set;
freerdp_peer* client = (freerdp_peer*) arg;
memset(rfds, 0, sizeof(rfds));
@ -452,8 +492,11 @@ int main(int argc, char* argv[])
instance->PeerAccepted = test_peer_accepted;
if (argc > 1)
test_pcap_file = argv[1];
/* Open the server socket and start listening. */
if (instance->Open(instance, (argc > 1 ? argv[1] : NULL), 3389))
if (instance->Open(instance, NULL, 3389))
{
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
test_server_mainloop(instance);

BIN
server/test/rfx_test.pcap Normal file

Binary file not shown.