From eb8c5c5f811e39b3dcf9251b916778050ab9e1fc Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Tue, 7 Feb 2012 13:38:27 +0100 Subject: [PATCH] Implement server-side support for slow-path Input Event PDU. --- libfreerdp-core/input.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++- libfreerdp-core/input.h | 2 + libfreerdp-core/peer.c | 5 ++ 3 files changed, 169 insertions(+), 1 deletion(-) diff --git a/libfreerdp-core/input.c b/libfreerdp-core/input.c index ae54a1f..29d4d0a 100644 --- a/libfreerdp-core/input.c +++ b/libfreerdp-core/input.c @@ -182,6 +182,168 @@ void input_send_fastpath_extended_mouse_event(rdpInput* input, uint16 flags, uin fastpath_send_input_pdu(rdp->fastpath, s); } +static boolean input_recv_sync_event(rdpInput* input, STREAM* s) +{ + uint32 toggleFlags; + + if (stream_get_left(s) < 6) + return false; + + stream_seek(s, 2); /* pad2Octets (2 bytes) */ + stream_read_uint32(s, toggleFlags); /* toggleFlags (4 bytes) */ + + IFCALL(input->SynchronizeEvent, input, toggleFlags); + + return true; +} + +static boolean input_recv_keyboard_event(rdpInput* input, STREAM* s) +{ + uint16 keyboardFlags, keyCode; + + if (stream_get_left(s) < 6) + return false; + + stream_read_uint16(s, keyboardFlags); /* keyboardFlags (2 bytes) */ + stream_read_uint16(s, keyCode); /* keyCode (2 bytes) */ + stream_seek(s, 2); /* pad2Octets (2 bytes) */ + + IFCALL(input->KeyboardEvent, input, keyboardFlags, keyCode); + + return true; +} + +static boolean input_recv_unicode_keyboard_event(rdpInput* input, STREAM* s) +{ + uint16 keyboardFlags, unicodeCode; + + if (stream_get_left(s) < 6) + return false; + + stream_read_uint16(s, keyboardFlags); /* keyboardFlags (2 bytes) */ + stream_read_uint16(s, unicodeCode); /* unicodeCode (2 bytes) */ + stream_seek(s, 2); /* pad2Octets (2 bytes) */ + + /* + * According to the specification, the slow path Unicode Keyboard Event + * (TS_UNICODE_KEYBOARD_EVENT) contains KBD_FLAGS_RELEASE flag when key + * is released, but contains no flags when it is pressed. + * This is different from the slow path Keyboard Event + * (TS_KEYBOARD_EVENT) which does contain KBD_FLAGS_DOWN flag when the + * key is pressed. + * Set the KBD_FLAGS_DOWN flag if the KBD_FLAGS_RELEASE flag is missing. + */ + + if ((keyboardFlags & KBD_FLAGS_RELEASE) == 0) + keyboardFlags |= KBD_FLAGS_DOWN; + + IFCALL(input->UnicodeKeyboardEvent, input, keyboardFlags, unicodeCode); + + return true; +} + +static boolean input_recv_mouse_event(rdpInput* input, STREAM* s) +{ + uint16 pointerFlags, xPos, 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(input->MouseEvent, input, pointerFlags, xPos, yPos); + + return true; +} + +static boolean input_recv_extended_mouse_event(rdpInput* input, STREAM* s) +{ + uint16 pointerFlags, xPos, 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(input->ExtendedMouseEvent, input, pointerFlags, xPos, yPos); + + return true; +} + +static boolean input_recv_event(rdpInput* input, STREAM* s) +{ + uint16 messageType; + + if (stream_get_left(s) < 4) + return false; + + stream_seek(s, 4); /* eventTime (4 bytes), ignored by the server */ + stream_read_uint16(s, messageType); /* messageType (2 bytes) */ + + switch (messageType) + { + case INPUT_EVENT_SYNC: + if (!input_recv_sync_event(input, s)) + return false; + break; + + case INPUT_EVENT_SCANCODE: + if (!input_recv_keyboard_event(input, s)) + return false; + break; + + case INPUT_EVENT_UNICODE: + if (!input_recv_unicode_keyboard_event(input, s)) + return false; + break; + + case INPUT_EVENT_MOUSE: + if (!input_recv_mouse_event(input, s)) + return false; + break; + + case INPUT_EVENT_MOUSEX: + if (!input_recv_extended_mouse_event(input, s)) + return false; + break; + + default: + printf("Unknown messageType %u\n", messageType); + /* Each input event uses 6 bytes. */ + stream_seek(s, 6); + break; + } + + return true; +} + +boolean input_recv(rdpInput* input, STREAM* s) +{ + uint16 i, numberEvents; + + if (stream_get_left(s) < 4) + return false; + + stream_read_uint16(s, numberEvents); /* numberEvents (2 bytes) */ + stream_seek(s, 2); /* pad2Octets (2 bytes) */ + + /* Each input event uses 6 exactly bytes. */ + if (stream_get_left(s) < 6 * numberEvents) + return false; + + for (i = 0; i < numberEvents; i++) + { + if (!input_recv_event(input, s)) + return false; + } + + return true; +} + void input_register_client_callbacks(rdpInput* input) { rdpRdp* rdp = input->context->rdp; @@ -225,4 +387,3 @@ void input_free(rdpInput* input) xfree(input); } } - diff --git a/libfreerdp-core/input.h b/libfreerdp-core/input.h index a9ad2ba..7fb08dc 100644 --- a/libfreerdp-core/input.h +++ b/libfreerdp-core/input.h @@ -49,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); +boolean input_recv(rdpInput* input, STREAM* s); + void input_register_client_callbacks(rdpInput* input); rdpInput* input_new(rdpRdp* rdp); diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index a7db7c9..01253e5 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -77,6 +77,11 @@ static boolean peer_recv_data_pdu(freerdp_peer* client, STREAM* s) return false; break; + case DATA_PDU_TYPE_INPUT: + if (!input_recv(client->context->rdp->input, s)) + return false; + break; + case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST: /* TODO: notify server bitmap cache data */ break; -- 2.7.4