Implement server-side support for slow-path Input Event PDU.
authorPawel Jakub Dawidek <pawel@dawidek.net>
Tue, 7 Feb 2012 12:38:27 +0000 (13:38 +0100)
committerPawel Jakub Dawidek <pawel@dawidek.net>
Tue, 7 Feb 2012 12:53:00 +0000 (13:53 +0100)
libfreerdp-core/input.c
libfreerdp-core/input.h
libfreerdp-core/peer.c

index ae54a1f..29d4d0a 100644 (file)
@@ -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);
        }
 }
-
index a9ad2ba..7fb08dc 100644 (file)
@@ -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);
index a7db7c9..01253e5 100644 (file)
@@ -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;