From ab7a53ea51690e340ea809d3cdecf84591d7d110 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Mon, 22 Aug 2011 23:02:56 +0800 Subject: [PATCH 01/11] server: add PostConnect callback. --- include/freerdp/peer.h | 3 +++ libfreerdp-core/peer.c | 5 +++++ server/test/freerdp_server.c | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/include/freerdp/peer.h b/include/freerdp/peer.h index bbe120cf5..9798b966b 100644 --- a/include/freerdp/peer.h +++ b/include/freerdp/peer.h @@ -30,6 +30,7 @@ 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 { @@ -45,6 +46,8 @@ struct rdp_freerdp_peer psPeerGetFileDescriptor GetFileDescriptor; psPeerCheckFileDescriptor CheckFileDescriptor; psPeerDisconnect Disconnect; + + psPeerPostConnect PostConnect; }; FREERDP_API freerdp_peer* freerdp_peer_new(int sockfd); diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index 36f3952f0..7593bf581 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -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: diff --git a/server/test/freerdp_server.c b/server/test/freerdp_server.c index 5d9e58f74..899fb894f 100644 --- a/server/test/freerdp_server.c +++ b/server/test/freerdp_server.c @@ -26,6 +26,29 @@ #include #include +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"); + + /* Return False here would stop the execution of the peer mainloop. */ + return True; +} + static void* test_peer_mainloop(void* arg) { freerdp_peer* client = (freerdp_peer*)arg; @@ -43,6 +66,8 @@ static void* test_peer_mainloop(void* arg) 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->Initialize(client); while (1) From 57ac9a59ebef757e43d5bc51be52ec27abc766d4 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 11:50:41 +0800 Subject: [PATCH 02/11] server: add input callbacks. --- include/freerdp/input.h | 3 +++ include/freerdp/peer.h | 4 ++++ libfreerdp-core/freerdp.c | 2 ++ libfreerdp-core/input.c | 38 +++++++++++++++++++++--------------- libfreerdp-core/input.h | 2 ++ libfreerdp-core/peer.c | 2 ++ server/test/freerdp_server.c | 34 ++++++++++++++++++++++++++++++++ 7 files changed, 69 insertions(+), 16 deletions(-) diff --git a/include/freerdp/input.h b/include/freerdp/input.h index 469cd1673..393f381b4 100644 --- a/include/freerdp/input.h +++ b/include/freerdp/input.h @@ -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; diff --git a/include/freerdp/peer.h b/include/freerdp/peer.h index 9798b966b..c0dbb1481 100644 --- a/include/freerdp/peer.h +++ b/include/freerdp/peer.h @@ -25,6 +25,8 @@ typedef struct rdp_freerdp_peer freerdp_peer; #include #include #include +#include +#include typedef boolean (*psPeerInitialize)(freerdp_peer* client); typedef boolean (*psPeerGetFileDescriptor)(freerdp_peer* client, void** rfds, int* rcount); @@ -40,6 +42,8 @@ struct rdp_freerdp_peer void* param3; void* param4; + rdpInput* input; + rdpUpdate* update; rdpSettings* settings; psPeerInitialize Initialize; diff --git a/libfreerdp-core/freerdp.c b/libfreerdp-core/freerdp.c index 2f9bc7cb6..90969a78a 100644 --- a/libfreerdp-core/freerdp.c +++ b/libfreerdp-core/freerdp.c @@ -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; diff --git a/libfreerdp-core/input.c b/libfreerdp-core/input.c index fca754f96..777443a83 100644 --- a/libfreerdp-core/input.c +++ b/libfreerdp-core/input.c @@ -175,6 +175,28 @@ void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uin rdp_send_client_fastpath_input_pdu(input->rdp, 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) { rdpInput* input; @@ -184,22 +206,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; diff --git a/libfreerdp-core/input.h b/libfreerdp-core/input.h index a61b0683c..a114350bb 100644 --- a/libfreerdp-core/input.h +++ b/libfreerdp-core/input.h @@ -60,6 +60,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); diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index 7593bf581..2cc3c872d 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -225,6 +225,8 @@ 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; transport_attach(peer->rdp->transport, sockfd); diff --git a/server/test/freerdp_server.c b/server/test/freerdp_server.c index 899fb894f..3546351b6 100644 --- a/server/test/freerdp_server.c +++ b/server/test/freerdp_server.c @@ -49,6 +49,31 @@ boolean test_peer_post_connect(freerdp_peer* client) return True; } +void test_peer_synchronize_event(rdpInput* input, uint32 flags) +{ + printf("Client sent a synchronize event\n"); +} + +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; @@ -63,11 +88,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) From 9880650557a975ca3c03df8ff9b5e4e55aeef0e4 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 12:58:10 +0800 Subject: [PATCH 03/11] Rename functions. --- libfreerdp-core/activation.c | 20 ++++++++-------- libfreerdp-core/activation.h | 14 +++++------ libfreerdp-core/connection.c | 2 +- libfreerdp-core/fastpath.c | 21 ++++++++++++++++- libfreerdp-core/fastpath.h | 4 +++- libfreerdp-core/info.c | 4 ++-- libfreerdp-core/info.h | 4 ++-- libfreerdp-core/peer.c | 19 +++++++-------- libfreerdp-core/rdp.c | 44 ++++++++++++++++------------------- libfreerdp-core/redirection.c | 8 +++++-- libfreerdp-core/redirection.h | 4 ++-- 11 files changed, 82 insertions(+), 62 deletions(-) diff --git a/libfreerdp-core/activation.c b/libfreerdp-core/activation.c index 510f74845..a3b4520d8 100644 --- a/libfreerdp-core/activation.c +++ b/libfreerdp-core/activation.c @@ -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; diff --git a/libfreerdp-core/activation.h b/libfreerdp-core/activation.h index a9035a108..be26d4c55 100644 --- a/libfreerdp-core/activation.h +++ b/libfreerdp-core/activation.h @@ -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); diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index a86418012..3a5dab6ca 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -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)) diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index c06bab440..12b1cecd3 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -67,6 +67,18 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s) return length; } +boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s) +{ + /* TODO: fipsInformation */ + + if ((fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED)) + { + stream_seek(s, 8); /* dataSignature */ + } + + return True; +} + static int fastpath_recv_update_surfcmd_surface_bits(rdpFastPath* fastpath, STREAM* s) { rdpUpdate* update = fastpath->rdp->update; @@ -278,7 +290,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,6 +302,13 @@ void fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s) } IFCALL(update->EndPaint, update); + + return True; +} + +boolean fastpath_recv_input(rdpFastPath* fastpath, STREAM* s) +{ + return True; } STREAM* fastpath_pdu_init(rdpFastPath* fastpath) diff --git a/libfreerdp-core/fastpath.h b/libfreerdp-core/fastpath.h index c1df080d6..bf181ffb9 100644 --- a/libfreerdp-core/fastpath.h +++ b/libfreerdp-core/fastpath.h @@ -80,7 +80,9 @@ struct rdp_fastpath }; 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_input(rdpFastPath* fastpath, STREAM* s); STREAM* fastpath_pdu_init(rdpFastPath* fastpath); void fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents); diff --git a/libfreerdp-core/info.c b/libfreerdp-core/info.c index c97ad0659..61a525d1d 100644 --- a/libfreerdp-core/info.c +++ b/libfreerdp-core/info.c @@ -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; diff --git a/libfreerdp-core/info.h b/libfreerdp-core/info.h index 689f1c19c..199fb0640 100644 --- a/libfreerdp-core/info.h +++ b/libfreerdp-core/info.h @@ -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 */ diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index 2cc3c872d..922a97366 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -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; @@ -97,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; @@ -122,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; @@ -135,18 +135,17 @@ 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; } -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) @@ -191,7 +190,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; diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 4710cc61b..865e28e6a 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -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,31 @@ 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 ((rdp->fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED)) - { - stream_seek(s, 8); /* dataSignature */ - } + if (!fastpath_read_security_header(rdp->fastpath, s)) + return False; fastpath_recv_updates(rdp->fastpath, s); return True; } -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 +484,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 +519,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; diff --git a/libfreerdp-core/redirection.c b/libfreerdp-core/redirection.c index cd4a36b08..a80c55b7f 100644 --- a/libfreerdp-core/redirection.c +++ b/libfreerdp-core/redirection.c @@ -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; } diff --git a/libfreerdp-core/redirection.h b/libfreerdp-core/redirection.h index 78fb9aafd..02c6ddf8c 100644 --- a/libfreerdp-core/redirection.h +++ b/libfreerdp-core/redirection.h @@ -25,7 +25,7 @@ #include #include -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 */ From 3178d278487a4c3cc5d509aec579697e483121fc Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 13:05:58 +0800 Subject: [PATCH 04/11] Rename more functions. --- libfreerdp-core/capabilities.c | 4 ++-- libfreerdp-core/capabilities.h | 4 ++-- libfreerdp-core/connection.c | 20 ++++++++++---------- libfreerdp-core/license.c | 2 +- libfreerdp-core/license.h | 2 +- libfreerdp-core/mcs.c | 14 +++++++------- libfreerdp-core/mcs.h | 14 +++++++------- libfreerdp-core/rdp.c | 4 +--- 8 files changed, 31 insertions(+), 33 deletions(-) diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c index e78bc716b..287974134 100644 --- a/libfreerdp-core/capabilities.c +++ b/libfreerdp-core/capabilities.c @@ -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; diff --git a/libfreerdp-core/capabilities.h b/libfreerdp-core/capabilities.h index 677bed9b9..85460c1fa 100644 --- a/libfreerdp-core/capabilities.h +++ b/libfreerdp-core/capabilities.h @@ -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); diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 3a5dab6ca..0f81a0e8a 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -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)) @@ -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; diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c index 96f0703a2..d9ae8c42b 100644 --- a/libfreerdp-core/license.c +++ b/libfreerdp-core/license.c @@ -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; diff --git a/libfreerdp-core/license.h b/libfreerdp-core/license.h index 54e3105b7..a6d1a5e93 100644 --- a/libfreerdp-core/license.h +++ b/libfreerdp-core/license.h @@ -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); diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index 33315f9bb..f884ba633 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -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; diff --git a/libfreerdp-core/mcs.h b/libfreerdp-core/mcs.h index 66e8b51fa..f7ecc1ea0 100644 --- a/libfreerdp-core/mcs.h +++ b/libfreerdp-core/mcs.h @@ -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); diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 865e28e6a..d1bd26903 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -459,9 +459,7 @@ static boolean rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) if (!fastpath_read_security_header(rdp->fastpath, s)) return False; - fastpath_recv_updates(rdp->fastpath, s); - - return True; + return fastpath_recv_updates(rdp->fastpath, s); } static boolean rdp_recv_pdu(rdpRdp* rdp, STREAM* s) From 719f521a3983f33d26b94fa26336f774834cc7ce Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 15:36:03 +0800 Subject: [PATCH 05/11] libfreerdp-coree/tranport: minimum fastpath packet size is 3. --- libfreerdp-core/transport.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 2d98db9c3..79df17f37 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -293,15 +293,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) { From 2d4f10038ed4a422671b13844b4a4ebbc8089ea0 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 15:51:51 +0800 Subject: [PATCH 06/11] server: process client input events. --- libfreerdp-core/fastpath.c | 187 ++++++++++++++++++++++++++++++++++- libfreerdp-core/fastpath.h | 25 ++++- libfreerdp-core/input.c | 43 ++++---- libfreerdp-core/input.h | 11 --- libfreerdp-core/peer.c | 14 ++- server/test/freerdp_server.c | 5 +- 6 files changed, 243 insertions(+), 42 deletions(-) diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index 12b1cecd3..fd64ec5c7 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -52,7 +52,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. */ @@ -306,8 +309,168 @@ boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s) return True; } -boolean fastpath_recv_input(rdpFastPath* fastpath, STREAM* s) +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; } @@ -320,7 +483,7 @@ STREAM* fastpath_pdu_init(rdpFastPath* fastpath) return s; } -void fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) +boolean fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) { int length; @@ -328,7 +491,7 @@ void fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) if (length > 127) { printf("Maximum FastPath PDU length is 127\n"); - return; + return False; } stream_set_pos(s, 0); @@ -336,7 +499,23 @@ void fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) 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_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode) +{ + STREAM* s; + s = fastpath_pdu_init(fastpath); + stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */ + return s; +} + +boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s) +{ + return fastpath_send_pdu(fastpath, s, 1); } rdpFastPath* fastpath_new(rdpRdp* rdp) diff --git a/libfreerdp-core/fastpath.h b/libfreerdp-core/fastpath.h index bf181ffb9..a047f97e6 100644 --- a/libfreerdp-core/fastpath.h +++ b/libfreerdp-core/fastpath.h @@ -72,20 +72,41 @@ 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); boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s); boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s); -boolean fastpath_recv_input(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); +boolean 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); rdpFastPath* fastpath_new(rdpRdp* rdp); void fastpath_free(rdpFastPath* fastpath); diff --git a/libfreerdp-core/input.c b/libfreerdp-core/input.c index 777443a83..acdc19ddc 100644 --- a/libfreerdp-core/input.c +++ b/libfreerdp-core/input.c @@ -119,60 +119,57 @@ 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) diff --git a/libfreerdp-core/input.h b/libfreerdp-core/input.h index a114350bb..a9ad2baf6 100644 --- a/libfreerdp-core/input.h +++ b/libfreerdp-core/input.h @@ -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); diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index 922a97366..b6048c8ab 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -137,7 +137,19 @@ static boolean peer_recv_tpkt_pdu(rdpPeer* peer, STREAM* s) static boolean peer_recv_fastpath_pdu(rdpPeer* peer, STREAM* s) { - 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_recv_pdu(rdpPeer* peer, STREAM* s) diff --git a/server/test/freerdp_server.c b/server/test/freerdp_server.c index 3546351b6..8bc94663b 100644 --- a/server/test/freerdp_server.c +++ b/server/test/freerdp_server.c @@ -45,13 +45,16 @@ boolean test_peer_post_connect(freerdp_peer* client) } printf("\n"); + printf("Client requested desktop: %dx%dx%d\n", + client->settings->width, client->settings->height, client->settings->color_depth); + /* 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\n"); + printf("Client sent a synchronize event (flags:0x%X)\n", flags); } void test_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code) From ca52da15cdbc899417f4c157bedeb01b7744aec7 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 16:14:32 +0800 Subject: [PATCH 07/11] server: handle disconnection. --- libfreerdp-core/peer.c | 3 +++ libfreerdp-core/transport.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index b6048c8ab..2e122732d 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -216,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) diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 79df17f37..2730ac802 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -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); } @@ -403,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); } From b7ee3be2d9765ed40f10557f62a151e4426f1e3c Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 20:37:08 +0800 Subject: [PATCH 08/11] server: add server update callback registration. --- libfreerdp-core/peer.c | 2 ++ libfreerdp-core/update.c | 15 +++++++++++++++ libfreerdp-core/update.h | 2 ++ 3 files changed, 19 insertions(+) diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index 2e122732d..8493977b1 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -242,6 +242,8 @@ freerdp_peer* freerdp_peer_new(int sockfd) client->input = peer->rdp->input; client->update = peer->rdp->update; + update_register_server_callbacks(client->update); + transport_attach(peer->rdp->transport, sockfd); peer->rdp->transport->recv_callback = peer_recv_callback; diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index e3f9d98a5..54163639b 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -216,6 +216,21 @@ 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) +{ +} + +void update_register_server_callbacks(rdpUpdate* update) +{ + update->BeginPaint = update_begin_paint; + update->EndPaint = update_end_paint; +} + rdpUpdate* update_new(rdpRdp* rdp) { rdpUpdate* update; diff --git a/libfreerdp-core/update.h b/libfreerdp-core/update.h index debe664d2..5ddef6ac4 100644 --- a/libfreerdp-core/update.h +++ b/libfreerdp-core/update.h @@ -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 */ From a5e251a5b26007523502097324123f2b2a9403bc Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 21:01:19 +0800 Subject: [PATCH 09/11] libfreerdp-core/surface: separate surface from fastpath. --- libfreerdp-core/CMakeLists.txt | 2 + libfreerdp-core/fastpath.c | 68 +-------------------------- libfreerdp-core/surface.c | 86 ++++++++++++++++++++++++++++++++++ libfreerdp-core/surface.h | 29 ++++++++++++ 4 files changed, 119 insertions(+), 66 deletions(-) create mode 100644 libfreerdp-core/surface.c create mode 100644 libfreerdp-core/surface.h diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index 208a7aa50..79b423551 100644 --- a/libfreerdp-core/CMakeLists.txt +++ b/libfreerdp-core/CMakeLists.txt @@ -76,6 +76,8 @@ set(LIBFREERDP_CORE_SRCS tpkt.h fastpath.c fastpath.h + surface.c + surface.h transport.c transport.h update.c diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index fd64ec5c7..1a1de6df3 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -24,6 +24,7 @@ #include "orders.h" #include "update.h" +#include "surface.h" #include "fastpath.h" @@ -82,71 +83,6 @@ boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s) return True; } -static int fastpath_recv_update_surfcmd_surface_bits(rdpFastPath* fastpath, STREAM* s) -{ - rdpUpdate* update = fastpath->rdp->update; - 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 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) - { - 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; - } - } -} - static void fastpath_recv_orders(rdpFastPath* fastpath, STREAM* s) { rdpUpdate* update = fastpath->rdp->update; @@ -202,7 +138,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: diff --git a/libfreerdp-core/surface.c b/libfreerdp-core/surface.c new file mode 100644 index 000000000..2e797fce7 --- /dev/null +++ b/libfreerdp-core/surface.c @@ -0,0 +1,86 @@ +/** + * 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; +} + diff --git a/libfreerdp-core/surface.h b/libfreerdp-core/surface.h new file mode 100644 index 000000000..960f5cbbf --- /dev/null +++ b/libfreerdp-core/surface.h @@ -0,0 +1,29 @@ +/** + * 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 + +boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s); + +#endif /* __SURFACE */ + From c79c587ca901e3c1d1ace8ba139c4e47e986808a Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 23:28:28 +0800 Subject: [PATCH 10/11] server: add SurfaceCmds update. --- libfreerdp-core/fastpath.c | 91 ++++++++++++++++++++++++++++++++++---- libfreerdp-core/fastpath.h | 8 ++-- libfreerdp-core/surface.c | 32 ++++++++++++++ libfreerdp-core/surface.h | 3 ++ libfreerdp-core/update.c | 8 ++++ 5 files changed, 130 insertions(+), 12 deletions(-) diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index 1a1de6df3..7dd5a048a 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -38,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 @@ -410,18 +412,19 @@ boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s) return True; } -STREAM* fastpath_pdu_init(rdpFastPath* fastpath) +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; } -boolean 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) @@ -431,7 +434,7 @@ boolean fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) } 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); @@ -441,17 +444,87 @@ boolean fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) return True; } -STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode) +STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath) { STREAM* s; - s = fastpath_pdu_init(fastpath); - stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */ + 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_input_pdu(rdpFastPath* fastpath, STREAM* s) +boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s) { - return fastpath_send_pdu(fastpath, s, 1); + 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) diff --git a/libfreerdp-core/fastpath.h b/libfreerdp-core/fastpath.h index a047f97e6..7f13b7d12 100644 --- a/libfreerdp-core/fastpath.h +++ b/libfreerdp-core/fastpath.h @@ -102,12 +102,14 @@ 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); -boolean 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); diff --git a/libfreerdp-core/surface.c b/libfreerdp-core/surface.c index 2e797fce7..48fa014ed 100644 --- a/libfreerdp-core/surface.c +++ b/libfreerdp-core/surface.c @@ -84,3 +84,35 @@ boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s) 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; +} + diff --git a/libfreerdp-core/surface.h b/libfreerdp-core/surface.h index 960f5cbbf..37a9d069b 100644 --- a/libfreerdp-core/surface.h +++ b/libfreerdp-core/surface.h @@ -25,5 +25,8 @@ 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 */ diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index 54163639b..c8a9bf65c 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -225,10 +225,18 @@ 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) From 52b5aeda9d9ea9e1a7e483016e21c4141b6183b4 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 23:28:54 +0800 Subject: [PATCH 11/11] server: update test server to send the first RemoteFX frame. --- server/test/freerdp_server.c | 93 ++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/server/test/freerdp_server.c b/server/test/freerdp_server.c index 8bc94663b..fe01dcf90 100644 --- a/server/test/freerdp_server.c +++ b/server/test/freerdp_server.c @@ -22,10 +22,100 @@ #include #include #include +#include #include #include +#include #include +/* 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) { /** @@ -48,6 +138,9 @@ boolean test_peer_post_connect(freerdp_peer* client) 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; }