Merge pull request #58 from llyzs/server

Server: add keyboard/mouse input and RemoteFX update processing
This commit is contained in:
Marc-André Moreau 2011-08-23 08:58:25 -07:00
commit 313e1dcfd2
29 changed files with 825 additions and 218 deletions

View File

@ -59,6 +59,9 @@ typedef void (*pcExtendedMouseEvent)(rdpInput* input, uint16 flags, uint16 x, ui
struct rdp_input
{
void* rdp;
void* param1;
void* param2;
pcSynchronizeEvent SynchronizeEvent;
pcKeyboardEvent KeyboardEvent;
pcUnicodeKeyboardEvent UnicodeKeyboardEvent;

View File

@ -25,11 +25,14 @@ typedef struct rdp_freerdp_peer freerdp_peer;
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/settings.h>
#include <freerdp/input.h>
#include <freerdp/update.h>
typedef boolean (*psPeerInitialize)(freerdp_peer* client);
typedef boolean (*psPeerGetFileDescriptor)(freerdp_peer* client, void** rfds, int* rcount);
typedef boolean (*psPeerCheckFileDescriptor)(freerdp_peer* client);
typedef void (*psPeerDisconnect)(freerdp_peer* client);
typedef boolean (*psPeerPostConnect)(freerdp_peer* client);
struct rdp_freerdp_peer
{
@ -39,12 +42,16 @@ struct rdp_freerdp_peer
void* param3;
void* param4;
rdpInput* input;
rdpUpdate* update;
rdpSettings* settings;
psPeerInitialize Initialize;
psPeerGetFileDescriptor GetFileDescriptor;
psPeerCheckFileDescriptor CheckFileDescriptor;
psPeerDisconnect Disconnect;
psPeerPostConnect PostConnect;
};
FREERDP_API freerdp_peer* freerdp_peer_new(int sockfd);

View File

@ -76,6 +76,8 @@ set(LIBFREERDP_CORE_SRCS
tpkt.h
fastpath.c
fastpath.h
surface.c
surface.h
transport.c
transport.h
update.c

View File

@ -34,7 +34,7 @@ void rdp_write_synchronize_pdu(STREAM* s, rdpSettings* settings)
stream_write_uint16(s, settings->pdu_source); /* targetUser (2 bytes) */
}
boolean rdp_read_server_synchronize_pdu(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_server_synchronize_pdu(rdpRdp* rdp, STREAM* s)
{
return True;
}
@ -52,7 +52,7 @@ boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp)
return True;
}
boolean rdp_read_client_synchronize_pdu(STREAM* s)
boolean rdp_recv_client_synchronize_pdu(STREAM* s)
{
uint16 messageType;
@ -78,7 +78,7 @@ boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp)
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id);
}
boolean rdp_read_control_pdu(STREAM* s, uint16* action)
boolean rdp_recv_control_pdu(STREAM* s, uint16* action)
{
if (stream_get_left(s) < 8)
return False;
@ -97,11 +97,11 @@ void rdp_write_client_control_pdu(STREAM* s, uint16 action)
stream_write_uint32(s, 0); /* controlId (4 bytes) */
}
boolean rdp_read_server_control_pdu(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s)
{
uint16 action;
rdp_read_control_pdu(s, &action);
rdp_recv_control_pdu(s, &action);
return True;
}
@ -183,7 +183,7 @@ boolean rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->user_id);
}
boolean rdp_read_client_font_list_pdu(STREAM* s)
boolean rdp_recv_client_font_list_pdu(STREAM* s)
{
if (stream_get_left(s) < 8)
return False;
@ -210,7 +210,7 @@ boolean rdp_send_client_font_list_pdu(rdpRdp* rdp, uint16 flags)
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->user_id);
}
boolean rdp_read_server_font_map_pdu(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_server_font_map_pdu(rdpRdp* rdp, STREAM* s)
{
return True;
}
@ -231,7 +231,7 @@ boolean rdp_send_server_font_map_pdu(rdpRdp* rdp)
return True;
}
boolean rdp_read_deactivate_all(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s)
{
uint16 lengthSourceDescriptor;
@ -250,7 +250,7 @@ boolean rdp_server_accept_client_control_pdu(rdpRdp* rdp, STREAM* s)
{
uint16 action;
if (!rdp_read_control_pdu(s, &action))
if (!rdp_recv_control_pdu(s, &action))
return False;
if (action == CTRLACTION_REQUEST_CONTROL)
{
@ -262,7 +262,7 @@ boolean rdp_server_accept_client_control_pdu(rdpRdp* rdp, STREAM* s)
boolean rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, STREAM* s)
{
if (!rdp_read_client_font_list_pdu(s))
if (!rdp_recv_client_font_list_pdu(s))
return False;
if (!rdp_send_server_font_map_pdu(rdp))
return False;

View File

@ -38,21 +38,21 @@
#define FONTLIST_FIRST 0x0001
#define FONTLIST_LAST 0x0002
boolean rdp_read_deactivate_all(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s);
boolean rdp_read_server_synchronize_pdu(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_server_synchronize_pdu(rdpRdp* rdp, STREAM* s);
boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp);
boolean rdp_read_client_synchronize_pdu(STREAM* s);
boolean rdp_recv_client_synchronize_pdu(STREAM* s);
boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp);
boolean rdp_read_control_pdu(STREAM* s, uint16* action);
boolean rdp_read_server_control_pdu(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_control_pdu(STREAM* s, uint16* action);
boolean rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s);
boolean rdp_send_server_control_cooperate_pdu(rdpRdp* rdp);
boolean rdp_send_server_control_granted_pdu(rdpRdp* rdp);
boolean rdp_send_client_control_pdu(rdpRdp* rdp, uint16 action);
boolean rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp);
boolean rdp_read_client_font_list_pdu(STREAM* s);
boolean rdp_recv_client_font_list_pdu(STREAM* s);
boolean rdp_send_client_font_list_pdu(rdpRdp* rdp, uint16 flags);
boolean rdp_read_server_font_map_pdu(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_server_font_map_pdu(rdpRdp* rdp, STREAM* s);
boolean rdp_send_server_font_map_pdu(rdpRdp* rdp);
boolean rdp_server_accept_client_control_pdu(rdpRdp* rdp, STREAM* s);

View File

@ -1576,7 +1576,7 @@ boolean rdp_read_capability_sets(STREAM* s, rdpSettings* settings, uint16 number
return True;
}
boolean rdp_read_demand_active(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s)
{
uint16 length;
uint16 channelId;
@ -1676,7 +1676,7 @@ boolean rdp_send_demand_active(rdpRdp* rdp)
return True;
}
boolean rdp_read_confirm_active(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_confirm_active(rdpRdp* rdp, STREAM* s)
{
uint16 length;
uint16 channelId;

View File

@ -163,10 +163,10 @@
#define CLW_ENTROPY_RLGR1 0x01
#define CLW_ENTROPY_RLGR3 0x04
boolean rdp_read_demand_active(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s);
void rdp_write_demand_active(STREAM* s, rdpSettings* settings);
boolean rdp_send_demand_active(rdpRdp* rdp);
boolean rdp_read_confirm_active(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_confirm_active(rdpRdp* rdp, STREAM* s);
void rdp_write_confirm_active(STREAM* s, rdpSettings* settings);
boolean rdp_send_confirm_active(rdpRdp* rdp);

View File

@ -106,7 +106,7 @@ boolean rdp_client_connect(rdpRdp* rdp)
boolean rdp_client_connect_mcs_connect_response(rdpRdp* rdp, STREAM* s)
{
if (!mcs_read_connect_response(rdp->mcs, s))
if (!mcs_recv_connect_response(rdp->mcs, s))
return False;
if (!mcs_send_erect_domain_request(rdp->mcs))
@ -121,7 +121,7 @@ boolean rdp_client_connect_mcs_connect_response(rdpRdp* rdp, STREAM* s)
boolean rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, STREAM* s)
{
if (!mcs_read_attach_user_confirm(rdp->mcs, s))
if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
return False;
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->user_id))
@ -138,7 +138,7 @@ boolean rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s)
uint16 channel_id;
boolean all_joined = True;
if (!mcs_read_channel_join_confirm(rdp->mcs, s, &channel_id))
if (!mcs_recv_channel_join_confirm(rdp->mcs, s, &channel_id))
return False;
if (!rdp->mcs->user_channel_joined)
@ -198,7 +198,7 @@ boolean rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s)
boolean rdp_client_connect_license(rdpRdp* rdp, STREAM* s)
{
if (!license_read(rdp->license, s))
if (!license_recv(rdp->license, s))
return False;
if (rdp->license->state == LICENSE_STATE_ABORTED)
@ -219,7 +219,7 @@ boolean rdp_client_connect_license(rdpRdp* rdp, STREAM* s)
boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s)
{
if (!rdp_read_demand_active(rdp, s))
if (!rdp_recv_demand_active(rdp, s))
return False;
if (!rdp_send_confirm_active(rdp))
@ -315,7 +315,7 @@ boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s)
{
int i;
if (!mcs_read_connect_initial(rdp->mcs, s))
if (!mcs_recv_connect_initial(rdp->mcs, s))
return False;
printf("Accepted client: %s\n", rdp->settings->client_hostname);
@ -336,7 +336,7 @@ boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s)
boolean rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, STREAM* s)
{
if (!mcs_read_erect_domain_request(rdp->mcs, s))
if (!mcs_recv_erect_domain_request(rdp->mcs, s))
return False;
rdp->state = CONNECTION_STATE_MCS_ERECT_DOMAIN;
@ -346,7 +346,7 @@ boolean rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, STREAM* s)
boolean rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, STREAM* s)
{
if (!mcs_read_attach_user_request(rdp->mcs, s))
if (!mcs_recv_attach_user_request(rdp->mcs, s))
return False;
if (!mcs_send_attach_user_confirm(rdp->mcs))
@ -363,7 +363,7 @@ boolean rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, STREAM* s)
uint16 channel_id;
boolean all_joined = True;
if (!mcs_read_channel_join_request(rdp->mcs, s, &channel_id))
if (!mcs_recv_channel_join_request(rdp->mcs, s, &channel_id))
return False;
if (!mcs_send_channel_join_confirm(rdp->mcs, channel_id))
@ -391,7 +391,7 @@ boolean rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, STREAM* s)
boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s)
{
if (!rdp_read_client_info(rdp, s))
if (!rdp_recv_client_info(rdp, s))
return False;
if (!license_send_valid_client_error_packet(rdp->license))
@ -407,7 +407,7 @@ boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s)
boolean rdp_server_accept_confirm_active(rdpRdp* rdp, STREAM* s)
{
if (!rdp_read_confirm_active(rdp, s))
if (!rdp_recv_confirm_active(rdp, s))
return False;
rdp->state = CONNECTION_STATE_ACTIVE;

View File

@ -24,6 +24,7 @@
#include "orders.h"
#include "update.h"
#include "surface.h"
#include "fastpath.h"
@ -37,6 +38,8 @@
* two less significant bits of the first byte.
*/
#define FASTPATH_MAX_PACKET_SIZE 0x7FFF
/**
* Read a Fast-Path packet header.\n
* @param s stream
@ -52,7 +55,10 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
stream_read_uint8(s, header);
if (fastpath != NULL)
{
fastpath->encryptionFlags = (header & 0xC0) >> 6;
fastpath->numberEvents = (header & 0x3C) >> 2;
}
stream_read_uint8(s, length); /* length1 */
/* If most significant bit is not set, length2 is not presented. */
@ -67,69 +73,16 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
return length;
}
static int fastpath_recv_update_surfcmd_surface_bits(rdpFastPath* fastpath, STREAM* s)
boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s)
{
rdpUpdate* update = fastpath->rdp->update;
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
int pos;
/* TODO: fipsInformation */
stream_read_uint16(s, cmd->destLeft);
stream_read_uint16(s, cmd->destTop);
stream_read_uint16(s, cmd->destRight);
stream_read_uint16(s, cmd->destBottom);
stream_read_uint8(s, cmd->bpp);
stream_seek(s, 2); /* reserved1, reserved2 */
stream_read_uint8(s, cmd->codecID);
stream_read_uint16(s, cmd->width);
stream_read_uint16(s, cmd->height);
stream_read_uint32(s, cmd->bitmapDataLength);
pos = stream_get_pos(s) + cmd->bitmapDataLength;
cmd->bitmapData = stream_get_tail(s);
IFCALL(update->SurfaceBits, update, cmd);
stream_set_pos(s, pos);
return 20 + cmd->bitmapDataLength;
}
static int fastpath_recv_update_surfcmd_frame_marker(rdpFastPath* fastpath, STREAM* s)
{
uint16 frameAction;
uint32 frameId;
stream_read_uint16(s, frameAction);
stream_read_uint32(s, frameId);
/*printf("frameAction %d frameId %d\n", frameAction, frameId);*/
return 6;
}
static void fastpath_recv_update_surfcmds(rdpFastPath* fastpath, uint16 size, STREAM* s)
{
uint16 cmdType;
while (size > 2)
if ((fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED))
{
stream_read_uint16(s, cmdType);
size -= 2;
switch (cmdType)
{
case CMDTYPE_SET_SURFACE_BITS:
case CMDTYPE_STREAM_SURFACE_BITS:
size -= fastpath_recv_update_surfcmd_surface_bits(fastpath, s);
break;
case CMDTYPE_FRAME_MARKER:
size -= fastpath_recv_update_surfcmd_frame_marker(fastpath, s);
break;
default:
DEBUG_WARN("unknown cmdType 0x%X", cmdType);
return;
}
stream_seek(s, 8); /* dataSignature */
}
return True;
}
static void fastpath_recv_orders(rdpFastPath* fastpath, STREAM* s)
@ -187,7 +140,7 @@ static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint16
break;
case FASTPATH_UPDATETYPE_SURFCMDS:
fastpath_recv_update_surfcmds(fastpath, size, s);
update_recv_surfcmds(fastpath->rdp->update, size, s);
break;
case FASTPATH_UPDATETYPE_PTR_NULL:
@ -278,7 +231,7 @@ static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
stream_set_pos(s, next_pos);
}
void fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s)
boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s)
{
rdpUpdate* update = fastpath->rdp->update;
@ -290,34 +243,288 @@ void fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s)
}
IFCALL(update->EndPaint, update);
return True;
}
STREAM* fastpath_pdu_init(rdpFastPath* fastpath)
static boolean fastpath_read_input_event_header(STREAM* s, uint8* eventFlags, uint8* eventCode)
{
uint8 eventHeader;
if (stream_get_left(s) < 1)
return False;
stream_read_uint8(s, eventHeader); /* eventHeader (1 byte) */
*eventFlags = (eventHeader & 0x1F);
*eventCode = (eventHeader >> 5);
return True;
}
static boolean fastpath_recv_input_event_scancode(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
{
uint16 flags;
uint16 code;
if (stream_get_left(s) < 1)
return False;
stream_read_uint8(s, code); /* keyCode (1 byte) */
flags = 0;
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
flags |= KBD_FLAGS_RELEASE;
else
flags |= KBD_FLAGS_DOWN;
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_EXTENDED))
flags |= KBD_FLAGS_EXTENDED;
IFCALL(fastpath->rdp->input->KeyboardEvent, fastpath->rdp->input, flags, code);
return True;
}
static boolean fastpath_recv_input_event_mouse(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
{
uint16 pointerFlags;
uint16 xPos;
uint16 yPos;
if (stream_get_left(s) < 6)
return False;
stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */
stream_read_uint16(s, xPos); /* xPos (2 bytes) */
stream_read_uint16(s, yPos); /* yPos (2 bytes) */
IFCALL(fastpath->rdp->input->MouseEvent, fastpath->rdp->input, pointerFlags, xPos, yPos);
return True;
}
static boolean fastpath_recv_input_event_mousex(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
{
uint16 pointerFlags;
uint16 xPos;
uint16 yPos;
if (stream_get_left(s) < 6)
return False;
stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */
stream_read_uint16(s, xPos); /* xPos (2 bytes) */
stream_read_uint16(s, yPos); /* yPos (2 bytes) */
IFCALL(fastpath->rdp->input->ExtendedMouseEvent, fastpath->rdp->input, pointerFlags, xPos, yPos);
return True;
}
static boolean fastpath_recv_input_event_sync(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
{
IFCALL(fastpath->rdp->input->SynchronizeEvent, fastpath->rdp->input, eventFlags);
return True;
}
static boolean fastpath_recv_input_event_unicode(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
{
uint16 unicodeCode;
if (stream_get_left(s) < 2)
return False;
stream_read_uint16(s, unicodeCode); /* unicodeCode (2 bytes) */
IFCALL(fastpath->rdp->input->UnicodeKeyboardEvent, fastpath->rdp->input, unicodeCode);
return True;
}
static boolean fastpath_recv_input_event(rdpFastPath* fastpath, STREAM* s)
{
uint8 eventFlags;
uint8 eventCode;
if (!fastpath_read_input_event_header(s, &eventFlags, &eventCode))
return False;
switch (eventCode)
{
case FASTPATH_INPUT_EVENT_SCANCODE:
if (!fastpath_recv_input_event_scancode(fastpath, s, eventFlags))
return False;
break;
case FASTPATH_INPUT_EVENT_MOUSE:
if (!fastpath_recv_input_event_mouse(fastpath, s, eventFlags))
return False;
break;
case FASTPATH_INPUT_EVENT_MOUSEX:
if (!fastpath_recv_input_event_mousex(fastpath, s, eventFlags))
return False;
break;
case FASTPATH_INPUT_EVENT_SYNC:
if (!fastpath_recv_input_event_sync(fastpath, s, eventFlags))
return False;
break;
case FASTPATH_INPUT_EVENT_UNICODE:
if (!fastpath_recv_input_event_unicode(fastpath, s, eventFlags))
return False;
break;
default:
printf("Unknown eventCode %d\n", eventCode);
break;
}
return True;
}
boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
{
uint8 i;
if (fastpath->numberEvents == 0)
{
/**
* If numberEvents is not provided in fpInputHeader, it will be provided
* as onee additional byte here.
*/
if (stream_get_left(s) < 1)
return False;
stream_read_uint8(s, fastpath->numberEvents); /* eventHeader (1 byte) */
}
for (i = 0; i < fastpath->numberEvents; i++)
{
if (!fastpath_recv_input_event(fastpath, s))
return False;
}
return True;
}
STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode)
{
STREAM* s;
s = transport_send_stream_init(fastpath->rdp->transport, 127);
stream_seek(s, 2); /* fpInputHeader and length1 */
/* length2 is not necessary since input PDU should not exceed 127 bytes */
stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */
return s;
}
void fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents)
boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s)
{
int length;
uint16 length;
length = stream_get_length(s);
if (length > 127)
{
printf("Maximum FastPath PDU length is 127\n");
return;
return False;
}
stream_set_pos(s, 0);
stream_write_uint8(s, (numberEvents << 2));
stream_write_uint8(s, (1 << 2));
stream_write_uint8(s, length);
stream_set_pos(s, length);
transport_write(fastpath->rdp->transport, s);
if (transport_write(fastpath->rdp->transport, s) < 0)
return False;
return True;
}
STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath)
{
STREAM* s;
s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE);
stream_seek(s, 3); /* fpOutputHeader, length1 and length2 */
return s;
}
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);
return False;
}
stream_set_pos(s, 0);
stream_write_uint8(s, 0); /* fpOutputHeader (1 byte) */
stream_write_uint8(s, 0x80 | (length >> 8)); /* length1 */
stream_write_uint8(s, length & 0xFF); /* length2 */
stream_set_pos(s, length);
if (transport_write(fastpath->rdp->transport, s) < 0)
return False;
return True;
}
boolean fastpath_send_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd)
{
STREAM* s;
uint16 size;
uint8* bitmapData;
uint32 bitmapDataLength;
uint16 fragment_size;
uint8 fragmentation;
int i;
int bp, ep;
bitmapData = cmd->bitmapData;
bitmapDataLength = cmd->bitmapDataLength;
for (i = 0; bitmapDataLength > 0; i++)
{
s = fastpath_update_pdu_init(fastpath);
bp = stream_get_pos(s);
stream_seek_uint8(s); /* updateHeader (1 byte) */
stream_seek_uint16(s); /* size (2 bytes) */
size = 0;
if (i == 0)
size += update_write_surfcmd_surface_bits_header(s, cmd);
fragment_size = MIN(stream_get_left(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));
stream_write_uint16(s, size);
stream_set_pos(s, ep);
stream_write(s, bitmapData, fragment_size);
bitmapData += fragment_size;
bitmapDataLength -= fragment_size;
if (!fastpath_send_update_pdu(fastpath, s))
return False;
}
return True;
}
rdpFastPath* fastpath_new(rdpRdp* rdp)

View File

@ -72,18 +72,43 @@ enum FASTPATH_OUTPUT_COMPRESSION
FASTPATH_OUTPUT_COMPRESSION_USED = 0x2
};
/* FastPath Input Events */
enum FASTPATH_INPUT_EVENT_CODE
{
FASTPATH_INPUT_EVENT_SCANCODE = 0x0,
FASTPATH_INPUT_EVENT_MOUSE = 0x1,
FASTPATH_INPUT_EVENT_MOUSEX = 0x2,
FASTPATH_INPUT_EVENT_SYNC = 0x3,
FASTPATH_INPUT_EVENT_UNICODE = 0x4
};
/* FastPath Keyboard Event Flags */
enum FASTPATH_INPUT_KBDFLAGS
{
FASTPATH_INPUT_KBDFLAGS_RELEASE = 0x01,
FASTPATH_INPUT_KBDFLAGS_EXTENDED = 0x02
};
struct rdp_fastpath
{
rdpRdp* rdp;
uint8 encryptionFlags;
uint8 numberEvents;
STREAM* updateData;
};
uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s);
void fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s);
boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s);
boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s);
boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s);
STREAM* fastpath_pdu_init(rdpFastPath* fastpath);
void fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents);
STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode);
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_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd);
rdpFastPath* fastpath_new(rdpRdp* rdp);
void fastpath_free(rdpFastPath* fastpath);

View File

@ -88,6 +88,8 @@ freerdp* freerdp_new()
instance->GetFileDescriptor = freerdp_get_fds;
instance->CheckFileDescriptor = freerdp_check_fds;
instance->SendChannelData = freerdp_send_channel_data;
input_register_client_callbacks(rdp->input);
}
return instance;

View File

@ -556,7 +556,7 @@ void rdp_write_info_packet(STREAM* s, rdpSettings* settings)
* @param s stream
*/
boolean rdp_read_client_info(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_client_info(rdpRdp* rdp, STREAM* s)
{
uint16 length;
uint16 channelId;
@ -654,7 +654,7 @@ void rdp_recv_logon_info_extended(rdpRdp* rdp, STREAM* s)
stream_seek(s, 570); /* pad */
}
boolean rdp_read_save_session_info(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_save_session_info(rdpRdp* rdp, STREAM* s)
{
uint32 infoType;

View File

@ -83,8 +83,8 @@ boolean rdp_read_extended_info_packet(STREAM* s, rdpSettings* settings);
void rdp_write_extended_info_packet(STREAM* s, rdpSettings* settings);
boolean rdp_read_info_packet(STREAM* s, rdpSettings* settings);
void rdp_write_info_packet(STREAM* s, rdpSettings* settings);
boolean rdp_read_client_info(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_client_info(rdpRdp* rdp, STREAM* s);
boolean rdp_send_client_info(rdpRdp* rdp);
boolean rdp_read_save_session_info(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_save_session_info(rdpRdp* rdp, STREAM* s);
#endif /* __INFO_H */

View File

@ -119,60 +119,79 @@ void input_send_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, ui
rdp_send_client_input_pdu(input->rdp, s);
}
STREAM* rdp_client_fastpath_input_pdu_init(rdpRdp* rdp, uint8 flags, uint8 code)
{
STREAM* s;
s = fastpath_pdu_init(rdp->fastpath);
stream_write_uint8(s, flags | (code << 5)); /* eventHeader */
return s;
}
void rdp_send_client_fastpath_input_pdu(rdpRdp* rdp, STREAM* s)
{
fastpath_send_pdu(rdp->fastpath, s, 1);
}
void input_send_fastpath_synchronize_event(rdpInput* input, uint32 flags)
{
rdpRdp* rdp = (rdpRdp*)input->rdp;
STREAM* s;
/* The FastPath Synchronization eventFlags has identical values as SlowPath */
s = rdp_client_fastpath_input_pdu_init(input->rdp, (uint8)flags, FASTPATH_INPUT_EVENT_SYNC);
rdp_send_client_fastpath_input_pdu(input->rdp, s);
s = fastpath_input_pdu_init(rdp->fastpath, (uint8)flags, FASTPATH_INPUT_EVENT_SYNC);
fastpath_send_input_pdu(rdp->fastpath, s);
}
void input_send_fastpath_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
{
rdpRdp* rdp = (rdpRdp*)input->rdp;
STREAM* s;
uint8 eventFlags = 0;
eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
eventFlags |= (flags & KBD_FLAGS_EXTENDED) ? FASTPATH_INPUT_KBDFLAGS_EXTENDED : 0;
s = rdp_client_fastpath_input_pdu_init(input->rdp, eventFlags, FASTPATH_INPUT_EVENT_SCANCODE);
s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_SCANCODE);
stream_write_uint8(s, code); /* keyCode (1 byte) */
rdp_send_client_fastpath_input_pdu(input->rdp, s);
fastpath_send_input_pdu(rdp->fastpath, s);
}
void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 code)
{
rdpRdp* rdp = (rdpRdp*)input->rdp;
STREAM* s;
s = rdp_client_fastpath_input_pdu_init(input->rdp, 0, FASTPATH_INPUT_EVENT_UNICODE);
s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_UNICODE);
stream_write_uint16(s, code); /* unicodeCode (2 bytes) */
rdp_send_client_fastpath_input_pdu(input->rdp, s);
fastpath_send_input_pdu(rdp->fastpath, s);
}
void input_send_fastpath_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
{
rdpRdp* rdp = (rdpRdp*)input->rdp;
STREAM* s;
s = rdp_client_fastpath_input_pdu_init(input->rdp, 0, FASTPATH_INPUT_EVENT_MOUSE);
s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSE);
input_write_mouse_event(s, flags, x, y);
rdp_send_client_fastpath_input_pdu(input->rdp, s);
fastpath_send_input_pdu(rdp->fastpath, s);
}
void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
{
rdpRdp* rdp = (rdpRdp*)input->rdp;
STREAM* s;
s = rdp_client_fastpath_input_pdu_init(input->rdp, 0, FASTPATH_INPUT_EVENT_MOUSEX);
s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSEX);
input_write_extended_mouse_event(s, flags, x, y);
rdp_send_client_fastpath_input_pdu(input->rdp, s);
fastpath_send_input_pdu(rdp->fastpath, s);
}
void input_register_client_callbacks(rdpInput* input)
{
rdpRdp* rdp = (rdpRdp*)input->rdp;
if (rdp->settings->fastpath_input)
{
input->SynchronizeEvent = input_send_fastpath_synchronize_event;
input->KeyboardEvent = input_send_fastpath_keyboard_event;
input->UnicodeKeyboardEvent = input_send_fastpath_unicode_keyboard_event;
input->MouseEvent = input_send_fastpath_mouse_event;
input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event;
}
else
{
input->SynchronizeEvent = input_send_synchronize_event;
input->KeyboardEvent = input_send_keyboard_event;
input->UnicodeKeyboardEvent = input_send_unicode_keyboard_event;
input->MouseEvent = input_send_mouse_event;
input->ExtendedMouseEvent = input_send_extended_mouse_event;
}
}
rdpInput* input_new(rdpRdp* rdp)
@ -184,22 +203,6 @@ rdpInput* input_new(rdpRdp* rdp)
if (input != NULL)
{
input->rdp = rdp;
if (rdp->settings->fastpath_input)
{
input->SynchronizeEvent = input_send_fastpath_synchronize_event;
input->KeyboardEvent = input_send_fastpath_keyboard_event;
input->UnicodeKeyboardEvent = input_send_fastpath_unicode_keyboard_event;
input->MouseEvent = input_send_fastpath_mouse_event;
input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event;
}
else
{
input->SynchronizeEvent = input_send_synchronize_event;
input->KeyboardEvent = input_send_keyboard_event;
input->UnicodeKeyboardEvent = input_send_unicode_keyboard_event;
input->MouseEvent = input_send_mouse_event;
input->ExtendedMouseEvent = input_send_extended_mouse_event;
}
}
return input;

View File

@ -35,17 +35,6 @@
#define INPUT_EVENT_MOUSE 0x8001
#define INPUT_EVENT_MOUSEX 0x8002
/* FastPath Input Events */
#define FASTPATH_INPUT_EVENT_SCANCODE 0x0
#define FASTPATH_INPUT_EVENT_MOUSE 0x1
#define FASTPATH_INPUT_EVENT_MOUSEX 0x2
#define FASTPATH_INPUT_EVENT_SYNC 0x3
#define FASTPATH_INPUT_EVENT_UNICODE 0x4
/* FastPath Keyboard Event Flags */
#define FASTPATH_INPUT_KBDFLAGS_RELEASE 0x01
#define FASTPATH_INPUT_KBDFLAGS_EXTENDED 0x02
#define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4
void input_send_synchronize_event(rdpInput* input, uint32 flags);
@ -60,6 +49,8 @@ void input_send_fastpath_unicode_keyboard_event(rdpInput* input, uint16 code);
void input_send_fastpath_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y);
void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y);
void input_register_client_callbacks(rdpInput* input);
rdpInput* input_new(rdpRdp* rdp);
void input_free(rdpInput* input);

View File

@ -161,7 +161,7 @@ boolean license_send(rdpLicense* license, STREAM* s, uint8 type)
* @param s stream
*/
boolean license_read(rdpLicense* license, STREAM* s)
boolean license_recv(rdpLicense* license, STREAM* s)
{
uint16 length;
uint16 channelId;

View File

@ -156,7 +156,7 @@ struct rdp_license
SCOPE_LIST* scope_list;
};
boolean license_read(rdpLicense* license, STREAM* s);
boolean license_recv(rdpLicense* license, STREAM* s);
boolean license_send(rdpLicense* license, STREAM* s, uint8 type);
STREAM* license_send_stream_init(rdpLicense* license);

View File

@ -319,7 +319,7 @@ void mcs_print_domain_parameters(DomainParameters* domainParameters)
* @param s stream
*/
boolean mcs_read_connect_initial(rdpMcs* mcs, STREAM* s)
boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s)
{
int length;
boolean upwardFlag;
@ -496,7 +496,7 @@ boolean mcs_send_connect_initial(rdpMcs* mcs)
* @param mcs mcs module
*/
boolean mcs_read_connect_response(rdpMcs* mcs, STREAM* s)
boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s)
{
int length;
uint8 result;
@ -571,7 +571,7 @@ boolean mcs_send_connect_response(rdpMcs* mcs)
* @param s stream
*/
boolean mcs_read_erect_domain_request(rdpMcs* mcs, STREAM* s)
boolean mcs_recv_erect_domain_request(rdpMcs* mcs, STREAM* s)
{
uint16 length;
enum DomainMCSPDU MCSPDU;
@ -613,7 +613,7 @@ boolean mcs_send_erect_domain_request(rdpMcs* mcs)
* @param s stream
*/
boolean mcs_read_attach_user_request(rdpMcs* mcs, STREAM* s)
boolean mcs_recv_attach_user_request(rdpMcs* mcs, STREAM* s)
{
uint16 length;
enum DomainMCSPDU MCSPDU;
@ -651,7 +651,7 @@ boolean mcs_send_attach_user_request(rdpMcs* mcs)
* @param mcs mcs module
*/
boolean mcs_read_attach_user_confirm(rdpMcs* mcs, STREAM* s)
boolean mcs_recv_attach_user_confirm(rdpMcs* mcs, STREAM* s)
{
uint16 length;
uint8 result;
@ -698,7 +698,7 @@ boolean mcs_send_attach_user_confirm(rdpMcs* mcs)
* @param s stream
*/
boolean mcs_read_channel_join_request(rdpMcs* mcs, STREAM* s, uint16* channel_id)
boolean mcs_recv_channel_join_request(rdpMcs* mcs, STREAM* s, uint16* channel_id)
{
uint16 length;
enum DomainMCSPDU MCSPDU;
@ -748,7 +748,7 @@ boolean mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id)
* @param mcs mcs module
*/
boolean mcs_read_channel_join_confirm(rdpMcs* mcs, STREAM* s, uint16* channel_id)
boolean mcs_recv_channel_join_confirm(rdpMcs* mcs, STREAM* s, uint16* channel_id)
{
uint16 length;
uint8 result;

View File

@ -132,19 +132,19 @@ typedef struct rdp_mcs rdpMcs;
void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data);
void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data);
boolean mcs_read_connect_initial(rdpMcs* mcs, STREAM* s);
boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s);
boolean mcs_send_connect_initial(rdpMcs* mcs);
boolean mcs_read_connect_response(rdpMcs* mcs, STREAM* s);
boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s);
boolean mcs_send_connect_response(rdpMcs* mcs);
boolean mcs_read_erect_domain_request(rdpMcs* mcs, STREAM* s);
boolean mcs_recv_erect_domain_request(rdpMcs* mcs, STREAM* s);
boolean mcs_send_erect_domain_request(rdpMcs* mcs);
boolean mcs_read_attach_user_request(rdpMcs* mcs, STREAM* s);
boolean mcs_recv_attach_user_request(rdpMcs* mcs, STREAM* s);
boolean mcs_send_attach_user_request(rdpMcs* mcs);
boolean mcs_read_attach_user_confirm(rdpMcs* mcs, STREAM* s);
boolean mcs_recv_attach_user_confirm(rdpMcs* mcs, STREAM* s);
boolean mcs_send_attach_user_confirm(rdpMcs* mcs);
boolean mcs_read_channel_join_request(rdpMcs* mcs, STREAM* s, uint16* channel_id);
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_read_channel_join_confirm(rdpMcs* mcs, STREAM* s, 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_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, uint16* length);
void mcs_write_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU domainMCSPDU, uint16 length, uint8 options);

View File

@ -54,7 +54,7 @@ static boolean freerdp_peer_check_fds(freerdp_peer* client)
return True;
}
static boolean peer_read_data_pdu(rdpPeer* peer, STREAM* s)
static boolean peer_recv_data_pdu(rdpPeer* peer, STREAM* s)
{
uint8 type;
uint16 length;
@ -66,7 +66,7 @@ static boolean peer_read_data_pdu(rdpPeer* peer, STREAM* s)
switch (type)
{
case DATA_PDU_TYPE_SYNCHRONIZE:
if (!rdp_read_client_synchronize_pdu(s))
if (!rdp_recv_client_synchronize_pdu(s))
return False;
break;
@ -82,6 +82,11 @@ static boolean peer_read_data_pdu(rdpPeer* peer, STREAM* s)
case DATA_PDU_TYPE_FONT_LIST:
if (!rdp_server_accept_client_font_list_pdu(peer->rdp, s))
return False;
if (peer->client->PostConnect)
{
if (!peer->client->PostConnect(peer->client))
return False;
}
break;
default:
@ -92,7 +97,7 @@ static boolean peer_read_data_pdu(rdpPeer* peer, STREAM* s)
return True;
}
static boolean peer_read_tpkt_pdu(rdpPeer* peer, STREAM* s)
static boolean peer_recv_tpkt_pdu(rdpPeer* peer, STREAM* s)
{
uint16 length;
uint16 pduType;
@ -117,7 +122,7 @@ static boolean peer_read_tpkt_pdu(rdpPeer* peer, STREAM* s)
switch (pduType)
{
case PDU_TYPE_DATA:
if (!peer_read_data_pdu(peer, s))
if (!peer_recv_data_pdu(peer, s))
return False;
break;
@ -130,18 +135,29 @@ static boolean peer_read_tpkt_pdu(rdpPeer* peer, STREAM* s)
return True;
}
static boolean peer_read_fastpath_pdu(rdpPeer* peer, STREAM* s)
static boolean peer_recv_fastpath_pdu(rdpPeer* peer, STREAM* s)
{
printf("FastPath Input PDU\n");
return True;
uint16 length;
length = fastpath_read_header(peer->rdp->fastpath, s);
if (length == 0 || length > stream_get_size(s))
{
printf("incorrect FastPath PDU header length %d\n", length);
return False;
}
if (!fastpath_read_security_header(peer->rdp->fastpath, s))
return False;
return fastpath_recv_inputs(peer->rdp->fastpath, s);
}
static boolean peer_read_pdu(rdpPeer* peer, STREAM* s)
static boolean peer_recv_pdu(rdpPeer* peer, STREAM* s)
{
if (tpkt_verify_header(s))
return peer_read_tpkt_pdu(peer, s);
return peer_recv_tpkt_pdu(peer, s);
else
return peer_read_fastpath_pdu(peer, s);
return peer_recv_fastpath_pdu(peer, s);
}
static int peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
@ -186,7 +202,7 @@ static int peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
break;
case CONNECTION_STATE_ACTIVE:
if (!peer_read_pdu(peer, s))
if (!peer_recv_pdu(peer, s))
return -1;
break;
@ -200,6 +216,9 @@ static int peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
static void freerdp_peer_disconnect(freerdp_peer* client)
{
rdpPeer* peer = (rdpPeer*)client->peer;
transport_disconnect(peer->rdp->transport);
}
freerdp_peer* freerdp_peer_new(int sockfd)
@ -220,6 +239,10 @@ freerdp_peer* freerdp_peer_new(int sockfd)
client->peer = (void*)peer;
client->settings = peer->rdp->settings;
client->input = peer->rdp->input;
client->update = peer->rdp->update;
update_register_server_callbacks(client->update);
transport_attach(peer->rdp->transport, sockfd);

View File

@ -288,7 +288,7 @@ boolean rdp_send_data_pdu(rdpRdp* rdp, STREAM* s, uint8 type, uint16 channel_id)
return True;
}
void rdp_read_set_error_info_data_pdu(STREAM* s)
void rdp_recv_set_error_info_data_pdu(STREAM* s)
{
uint32 errorInfo;
@ -298,7 +298,7 @@ void rdp_read_set_error_info_data_pdu(STREAM* s)
rdp_print_errinfo(errorInfo);
}
void rdp_read_data_pdu(rdpRdp* rdp, STREAM* s)
void rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s)
{
uint8 type;
uint16 length;
@ -316,7 +316,7 @@ void rdp_read_data_pdu(rdpRdp* rdp, STREAM* s)
break;
case DATA_PDU_TYPE_CONTROL:
rdp_read_server_control_pdu(rdp, s);
rdp_recv_server_control_pdu(rdp, s);
break;
case DATA_PDU_TYPE_POINTER:
@ -326,7 +326,7 @@ void rdp_read_data_pdu(rdpRdp* rdp, STREAM* s)
break;
case DATA_PDU_TYPE_SYNCHRONIZE:
rdp_read_server_synchronize_pdu(rdp, s);
rdp_recv_server_synchronize_pdu(rdp, s);
break;
case DATA_PDU_TYPE_REFRESH_RECT:
@ -345,14 +345,14 @@ void rdp_read_data_pdu(rdpRdp* rdp, STREAM* s)
break;
case DATA_PDU_TYPE_SAVE_SESSION_INFO:
rdp_read_save_session_info(rdp, s);
rdp_recv_save_session_info(rdp, s);
break;
case DATA_PDU_TYPE_FONT_LIST:
break;
case DATA_PDU_TYPE_FONT_MAP:
rdp_read_server_font_map_pdu(rdp, s);
rdp_recv_server_font_map_pdu(rdp, s);
break;
case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
@ -371,7 +371,7 @@ void rdp_read_data_pdu(rdpRdp* rdp, STREAM* s)
break;
case DATA_PDU_TYPE_SET_ERROR_INFO:
rdp_read_set_error_info_data_pdu(s);
rdp_recv_set_error_info_data_pdu(s);
break;
case DATA_PDU_TYPE_DRAW_NINEGRID_ERROR:
@ -400,7 +400,7 @@ void rdp_read_data_pdu(rdpRdp* rdp, STREAM* s)
* @param s stream
*/
static boolean rdp_read_tpkt_pdu(rdpRdp* rdp, STREAM* s)
static boolean rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
{
uint16 length;
uint16 pduType;
@ -424,16 +424,16 @@ static boolean rdp_read_tpkt_pdu(rdpRdp* rdp, STREAM* s)
switch (pduType)
{
case PDU_TYPE_DATA:
rdp_read_data_pdu(rdp, s);
rdp_recv_data_pdu(rdp, s);
break;
case PDU_TYPE_DEACTIVATE_ALL:
if (!rdp_read_deactivate_all(rdp, s))
if (!rdp_recv_deactivate_all(rdp, s))
return False;
break;
case PDU_TYPE_SERVER_REDIRECTION:
rdp_read_enhanced_security_redirection_packet(rdp, s);
rdp_recv_enhanced_security_redirection_packet(rdp, s);
break;
default:
@ -445,35 +445,29 @@ static boolean rdp_read_tpkt_pdu(rdpRdp* rdp, STREAM* s)
return True;
}
static boolean rdp_read_fastpath_pdu(rdpRdp* rdp, STREAM* s)
static boolean rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s)
{
uint16 length;
length = fastpath_read_header(rdp->fastpath, s);
if (length > stream_get_size(s))
if (length == 0 || length > stream_get_size(s))
{
printf("incorrect FastPath PDU header length %d\n", length);
return False;
}
/* TODO: fipsInformation */
if (!fastpath_read_security_header(rdp->fastpath, s))
return False;
if ((rdp->fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED))
{
stream_seek(s, 8); /* dataSignature */
}
fastpath_recv_updates(rdp->fastpath, s);
return True;
return fastpath_recv_updates(rdp->fastpath, s);
}
static boolean rdp_read_pdu(rdpRdp* rdp, STREAM* s)
static boolean rdp_recv_pdu(rdpRdp* rdp, STREAM* s)
{
if (tpkt_verify_header(s))
return rdp_read_tpkt_pdu(rdp, s);
return rdp_recv_tpkt_pdu(rdp, s);
else
return rdp_read_fastpath_pdu(rdp, s);
return rdp_recv_fastpath_pdu(rdp, s);
}
/**
@ -488,7 +482,7 @@ void rdp_recv(rdpRdp* rdp)
s = transport_recv_stream_init(rdp->transport, 4096);
transport_read(rdp->transport, s);
rdp_read_pdu(rdp, s);
rdp_recv_pdu(rdp, s);
}
static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
@ -523,7 +517,7 @@ static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
break;
case CONNECTION_STATE_ACTIVE:
if (!rdp_read_pdu(rdp, s))
if (!rdp_recv_pdu(rdp, s))
return -1;
break;

View File

@ -27,13 +27,17 @@
* @param sec_flags security flags
*/
void rdp_read_redirection_packet(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_redirection_packet(rdpRdp* rdp, STREAM* s)
{
printf("Redirection Packet\n");
return True;
}
void rdp_read_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s)
boolean rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s)
{
printf("Enhanced Security Redirection Packet\n");
return True;
}

View File

@ -25,7 +25,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/utils/stream.h>
void rdp_read_redirection_packet(rdpRdp* rdp, STREAM* s);
void rdp_read_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_redirection_packet(rdpRdp* rdp, STREAM* s);
boolean rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s);
#endif /* __REDIRECTION_H */

118
libfreerdp-core/surface.c Normal file
View File

@ -0,0 +1,118 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Surface Commands
*
* Copyright 2011 Vic Lee
*
* 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 "surface.h"
static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s)
{
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
int pos;
stream_read_uint16(s, cmd->destLeft);
stream_read_uint16(s, cmd->destTop);
stream_read_uint16(s, cmd->destRight);
stream_read_uint16(s, cmd->destBottom);
stream_read_uint8(s, cmd->bpp);
stream_seek(s, 2); /* reserved1, reserved2 */
stream_read_uint8(s, cmd->codecID);
stream_read_uint16(s, cmd->width);
stream_read_uint16(s, cmd->height);
stream_read_uint32(s, cmd->bitmapDataLength);
pos = stream_get_pos(s) + cmd->bitmapDataLength;
cmd->bitmapData = stream_get_tail(s);
IFCALL(update->SurfaceBits, update, cmd);
stream_set_pos(s, pos);
return 20 + cmd->bitmapDataLength;
}
static int update_recv_surfcmd_frame_marker(rdpUpdate* update, STREAM* s)
{
uint16 frameAction;
uint32 frameId;
stream_read_uint16(s, frameAction);
stream_read_uint32(s, frameId);
/*printf("frameAction %d frameId %d\n", frameAction, frameId);*/
return 6;
}
boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
{
uint16 cmdType;
while (size > 2)
{
stream_read_uint16(s, cmdType);
size -= 2;
switch (cmdType)
{
case CMDTYPE_SET_SURFACE_BITS:
case CMDTYPE_STREAM_SURFACE_BITS:
size -= update_recv_surfcmd_surface_bits(update, s);
break;
case CMDTYPE_FRAME_MARKER:
size -= update_recv_surfcmd_frame_marker(update, s);
break;
default:
DEBUG_WARN("unknown cmdType 0x%X", cmdType);
return False;
}
}
return True;
}
int update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd)
{
stream_check_size(s, 22);
stream_write_uint16(s, CMDTYPE_STREAM_SURFACE_BITS);
stream_write_uint16(s, cmd->destLeft);
stream_write_uint16(s, cmd->destTop);
stream_write_uint16(s, cmd->destRight);
stream_write_uint16(s, cmd->destBottom);
stream_write_uint8(s, cmd->bpp);
stream_write_uint16(s, 0); /* reserved1, reserved2 */
stream_write_uint8(s, cmd->codecID);
stream_write_uint16(s, cmd->width);
stream_write_uint16(s, cmd->height);
stream_write_uint32(s, cmd->bitmapDataLength);
return 22;
}
int update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId)
{
stream_check_size(s, 8);
stream_write_uint16(s, CMDTYPE_FRAME_MARKER);
stream_write_uint16(s, frameAction);
stream_write_uint32(s, frameId);
return 8;
}

32
libfreerdp-core/surface.h Normal file
View File

@ -0,0 +1,32 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Surface Commands
*
* Copyright 2011 Vic Lee
*
* 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 __SURFACE
#define __SURFACE
#include "rdp.h"
#include <freerdp/utils/stream.h>
boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s);
int update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd);
int update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId);
#endif /* __SURFACE */

View File

@ -70,6 +70,8 @@ void transport_attach(rdpTransport* transport, int sockfd)
boolean transport_disconnect(rdpTransport* transport)
{
if (transport->tls)
IFCALL(transport->tls->disconnect, transport->tls);
return transport->tcp->disconnect(transport->tcp);
}
@ -293,15 +295,27 @@ int transport_check_fds(rdpTransport* transport)
while ((pos = stream_get_pos(transport->recv_buffer)) > 0)
{
/* Ensure the TPKT or Fast Path header is available. */
if (pos <= 4)
return 0;
stream_set_pos(transport->recv_buffer, 0);
if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */
{
/* Ensure the TPKT header is available. */
if (pos <= 4)
{
stream_set_pos(transport->recv_buffer, pos);
return 0;
}
length = tpkt_read_header(transport->recv_buffer);
}
else /* Fast Path */
{
/* Ensure the Fast Path header is available. */
if (pos <= 2)
{
stream_set_pos(transport->recv_buffer, pos);
return 0;
}
length = fastpath_read_header(NULL, transport->recv_buffer);
}
if (length == 0)
{
@ -391,6 +405,8 @@ void transport_free(rdpTransport* transport)
stream_free(transport->recv_stream);
stream_free(transport->send_stream);
wait_obj_free(transport->recv_event);
if (transport->tls)
tls_free(transport->tls);
tcp_free(transport->tcp);
xfree(transport);
}

View File

@ -216,6 +216,29 @@ void update_reset_state(rdpUpdate* update)
update->order_info.orderType = ORDER_TYPE_PATBLT;
}
static void update_begin_paint(rdpUpdate* update)
{
update_reset_state(update);
}
static void update_end_paint(rdpUpdate* update)
{
}
static void update_send_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command)
{
rdpRdp* rdp = (rdpRdp*)update->rdp;
fastpath_send_surface_bits(rdp->fastpath, surface_bits_command);
}
void update_register_server_callbacks(rdpUpdate* update)
{
update->BeginPaint = update_begin_paint;
update->EndPaint = update_end_paint;
update->SurfaceBits = update_send_surface_bits;
}
rdpUpdate* update_new(rdpRdp* rdp)
{
rdpUpdate* update;

View File

@ -43,4 +43,6 @@ void update_read_bitmap(rdpUpdate* update, STREAM* s, BITMAP_UPDATE* bitmap_upda
void update_read_palette(rdpUpdate* update, STREAM* s, PALETTE_UPDATE* palette_update);
void update_recv(rdpUpdate* update, STREAM* s);
void update_register_server_callbacks(rdpUpdate* update);
#endif /* __UPDATE_H */

View File

@ -22,10 +22,154 @@
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <freerdp/constants.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/thread.h>
#include <freerdp/rfx/rfx.h>
#include <freerdp/listener.h>
/* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */
static const unsigned int test_quantization_values[] =
{
6, 6, 6, 6, 7, 7, 8, 8, 8, 9
};
static const uint8 rgb_scanline_data[] =
{
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF
};
void test_peer_init_desktop(freerdp_peer* client)
{
rdpUpdate* update = client->update;
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
RFX_CONTEXT* context;
uint8* rgb_data;
STREAM* s;
int i;
RFX_RECT rect = {0, 0, 100, 80};
rgb_data = (uint8*) xmalloc(100 * 80 * 3);
for (i = 0; i < 80; i++)
memcpy(rgb_data + i * 100 * 3, rgb_scanline_data, 100 * 3);
s = stream_new(65536);
stream_clear(s);
context = rfx_context_new();
context->mode = RLGR3;
context->width = 800;
context->height = 600;
rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB);
/* In Video mode, the RemoteFX header should only be sent once */
rfx_compose_message_header(context, s);
rfx_compose_message_data(context, s,
&rect, 1, rgb_data, 100, 80, 100 * 3);
cmd->destLeft = 0;
cmd->destTop = 0;
cmd->destRight = 100;
cmd->destBottom = 80;
cmd->bpp = 32;
cmd->codecID = CODEC_ID_REMOTEFX;
cmd->width = 100;
cmd->height = 80;
cmd->bitmapDataLength = stream_get_length(s);
cmd->bitmapData = stream_get_head(s);
update->SurfaceBits(update, cmd);
stream_free(s);
rfx_context_free(context);
xfree(rgb_data);
}
boolean test_peer_post_connect(freerdp_peer* client)
{
/**
* This callback is called when the entire connection sequence is done, i.e. we've received the
* Font List PDU from the client and sent out the Font Map PDU.
* The server may start sending graphics output and receiving keyboard/mouse input after this
* callback returns.
*/
printf("Client %s is activated", client->settings->hostname);
if (client->settings->autologon)
{
printf(" and wants to login automatically as %s\\%s",
client->settings->domain ? client->settings->domain : "",
client->settings->username);
/* A real server may perform OS login here if NLA is not executed previously. */
}
printf("\n");
printf("Client requested desktop: %dx%dx%d\n",
client->settings->width, client->settings->height, client->settings->color_depth);
/* A real server should tag the peer as activated here and start sending updates in mainloop. */
test_peer_init_desktop(client);
/* Return False here would stop the execution of the peer mainloop. */
return True;
}
void test_peer_synchronize_event(rdpInput* input, uint32 flags)
{
printf("Client sent a synchronize event (flags:0x%X)\n", flags);
}
void test_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
{
printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code);
}
void test_peer_unicode_keyboard_event(rdpInput* input, uint16 code)
{
printf("Client sent a unicode keyboard event (code:0x%X)\n", code);
}
void test_peer_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
{
printf("Client sent a mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y);
}
void test_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
{
printf("Client sent an extended mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y);
}
static void* test_peer_mainloop(void* arg)
{
freerdp_peer* client = (freerdp_peer*)arg;
@ -40,9 +184,20 @@ static void* test_peer_mainloop(void* arg)
printf("We've got a client %s\n", client->settings->hostname);
/* Initialize the real server settings here */
client->settings->cert_file = xstrdup("server.crt");
client->settings->privatekey_file = xstrdup("server.key");
client->settings->nla_security = False;
client->PostConnect = test_peer_post_connect;
client->input->param1 = client;
client->input->SynchronizeEvent = test_peer_synchronize_event;
client->input->KeyboardEvent = test_peer_keyboard_event;
client->input->UnicodeKeyboardEvent = test_peer_unicode_keyboard_event;
client->input->MouseEvent = test_peer_mouse_event;
client->input->ExtendedMouseEvent = test_peer_extended_mouse_event;
client->Initialize(client);
while (1)