Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / fastpath.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * Fast Path
4  *
5  * Copyright 2011 Vic Lee
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <freerdp/api.h>
24 #include <freerdp/utils/stream.h>
25
26 #include "orders.h"
27 #include "per.h"
28 #include "update.h"
29 #include "surface.h"
30
31 #include "fastpath.h"
32
33 /**
34  * Fast-Path packet format is defined in [MS-RDPBCGR] 2.2.9.1.2, which revises
35  * server output packets from the first byte with the goal of improving
36  * bandwidth.
37  * 
38  * Slow-Path packet always starts with TPKT header, which has the first
39  * byte 0x03, while Fast-Path packet starts with 2 zero bits in the first
40  * two less significant bits of the first byte.
41  */
42
43 #define FASTPATH_MAX_PACKET_SIZE 0x3FFF
44
45 /*
46  * The fastpath header may be two or three bytes long.
47  * This function assumes that at least two bytes are available in the stream
48  * and doesn't touch third byte.
49  */
50 uint16 fastpath_header_length(STREAM* s)
51 {
52         uint8 length1;
53
54         stream_seek_uint8(s);
55         stream_read_uint8(s, length1);
56         stream_rewind(s, 2);
57
58         return ((length1 & 0x80) != 0 ? 3 : 2);
59 }
60
61 /**
62  * Read a Fast-Path packet header.\n
63  * @param s stream
64  * @param encryptionFlags
65  * @return length
66  */
67 uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
68 {
69         uint8 header;
70         uint16 length;
71
72         stream_read_uint8(s, header);
73
74         if (fastpath != NULL)
75         {
76                 fastpath->encryptionFlags = (header & 0xC0) >> 6;
77                 fastpath->numberEvents = (header & 0x3C) >> 2;
78         }
79
80         per_read_length(s, &length);
81
82         return length;
83 }
84
85 INLINE void fastpath_read_update_header(STREAM* s, uint8* updateCode, uint8* fragmentation, uint8* compression)
86 {
87         uint8 updateHeader;
88
89         stream_read_uint8(s, updateHeader);
90         *updateCode = updateHeader & 0x0F;
91         *fragmentation = (updateHeader >> 4) & 0x03;
92         *compression = (updateHeader >> 6) & 0x03;
93 }
94
95 INLINE void fastpath_write_update_header(STREAM* s, uint8 updateCode, uint8 fragmentation, uint8 compression)
96 {
97         uint8 updateHeader = 0;
98
99         updateHeader |= updateCode & 0x0F;
100         updateHeader |= (fragmentation & 0x03) << 4;
101         updateHeader |= (compression & 0x03) << 6;
102         stream_write_uint8(s, updateHeader);
103 }
104
105 uint16 fastpath_read_header_rdp(rdpFastPath* fastpath, STREAM* s)
106 {
107         uint8 header;
108         uint16 length;
109
110         stream_read_uint8(s, header);
111
112         if (fastpath != NULL)
113         {
114                 fastpath->encryptionFlags = (header & 0xC0) >> 6;
115                 fastpath->numberEvents = (header & 0x3C) >> 2;
116         }
117
118         per_read_length(s, &length);
119
120         return length - stream_get_length(s);
121 }
122
123 static void fastpath_recv_orders(rdpFastPath* fastpath, STREAM* s)
124 {
125         rdpUpdate* update = fastpath->rdp->update;
126         uint16 numberOrders;
127
128         stream_read_uint16(s, numberOrders); /* numberOrders (2 bytes) */
129
130         while (numberOrders > 0)
131         {
132                 update_recv_order(update, s);
133                 numberOrders--;
134         }
135 }
136
137 static void fastpath_recv_update_common(rdpFastPath* fastpath, STREAM* s)
138 {
139         uint16 updateType;
140         rdpUpdate* update = fastpath->rdp->update;
141         rdpContext* context = update->context;
142
143         stream_read_uint16(s, updateType); /* updateType (2 bytes) */
144
145         switch (updateType)
146         {
147                 case UPDATE_TYPE_BITMAP:
148                         update_read_bitmap(update, s, &update->bitmap_update);
149                         IFCALL(update->BitmapUpdate, context, &update->bitmap_update);
150                         break;
151
152                 case UPDATE_TYPE_PALETTE:
153                         update_read_palette(update, s, &update->palette_update);
154                         IFCALL(update->Palette, context, &update->palette_update);
155                         break;
156         }
157 }
158
159 static void fastpath_recv_update_synchronize(rdpFastPath* fastpath, STREAM* s)
160 {
161         stream_seek_uint16(s); /* size (2 bytes), must be set to zero */
162 }
163
164 static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint32 size, STREAM* s)
165 {
166         rdpUpdate* update = fastpath->rdp->update;
167         rdpContext* context = fastpath->rdp->update->context;
168         rdpPointerUpdate* pointer = update->pointer;
169
170         switch (updateCode)
171         {
172                 case FASTPATH_UPDATETYPE_ORDERS:
173                         fastpath_recv_orders(fastpath, s);
174                         break;
175
176                 case FASTPATH_UPDATETYPE_BITMAP:
177                 case FASTPATH_UPDATETYPE_PALETTE:
178                         fastpath_recv_update_common(fastpath, s);
179                         break;
180
181                 case FASTPATH_UPDATETYPE_SYNCHRONIZE:
182                         fastpath_recv_update_synchronize(fastpath, s);
183                         IFCALL(update->Synchronize, context);
184                         break;
185
186                 case FASTPATH_UPDATETYPE_SURFCMDS:
187                         update_recv_surfcmds(update, size, s);
188                         break;
189
190                 case FASTPATH_UPDATETYPE_PTR_NULL:
191                         pointer->pointer_system.type = SYSPTR_NULL;
192                         IFCALL(pointer->PointerSystem, context, &pointer->pointer_system);
193                         break;
194
195                 case FASTPATH_UPDATETYPE_PTR_DEFAULT:
196                         update->pointer->pointer_system.type = SYSPTR_DEFAULT;
197                         IFCALL(pointer->PointerSystem, context, &pointer->pointer_system);
198                         break;
199
200                 case FASTPATH_UPDATETYPE_PTR_POSITION:
201                         update_read_pointer_position(s, &pointer->pointer_position);
202                         IFCALL(pointer->PointerPosition, context, &pointer->pointer_position);
203                         break;
204
205                 case FASTPATH_UPDATETYPE_COLOR:
206                         update_read_pointer_color(s, &pointer->pointer_color);
207                         IFCALL(pointer->PointerColor, context, &pointer->pointer_color);
208                         break;
209
210                 case FASTPATH_UPDATETYPE_CACHED:
211                         update_read_pointer_cached(s, &pointer->pointer_cached);
212                         IFCALL(pointer->PointerCached, context, &pointer->pointer_cached);
213                         break;
214
215                 case FASTPATH_UPDATETYPE_POINTER:
216                         update_read_pointer_new(s, &pointer->pointer_new);
217                         IFCALL(pointer->PointerNew, context, &pointer->pointer_new);
218                         break;
219
220                 default:
221                         DEBUG_WARN("unknown updateCode 0x%X", updateCode);
222                         break;
223         }
224 }
225
226 static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
227 {
228         uint16 size;
229         int next_pos;
230         uint32 totalSize;
231         uint8 updateCode;
232         uint8 fragmentation;
233         uint8 compression;
234         uint8 compressionFlags;
235         STREAM* update_stream;
236         STREAM* comp_stream;
237         rdpRdp  *rdp;
238         uint32 roff;
239         uint32 rlen;
240
241         rdp = fastpath->rdp;
242
243         fastpath_read_update_header(s, &updateCode, &fragmentation, &compression);
244
245         if (compression == FASTPATH_OUTPUT_COMPRESSION_USED)
246                 stream_read_uint8(s, compressionFlags);
247         else
248                 compressionFlags = 0;
249
250         stream_read_uint16(s, size);
251         next_pos = stream_get_pos(s) + size;
252         comp_stream = s;
253
254         if (compressionFlags & PACKET_COMPRESSED)
255         {
256                 if (decompress_rdp(rdp, s->p, size, compressionFlags, &roff, &rlen))
257                 {
258                         comp_stream = stream_new(0);
259                         comp_stream->data = rdp->mppc->history_buf + roff;
260                         comp_stream->p = comp_stream->data;
261                         comp_stream->size = rlen;
262                         size = comp_stream->size;
263                 }
264                 else
265                 {
266                         printf("decompress_rdp() failed\n");
267                         stream_seek(s, size);
268                 }
269         }
270
271         update_stream = NULL;
272         if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
273         {
274                 totalSize = size;
275                 update_stream = comp_stream;
276         }
277         else
278         {
279                 if (fragmentation == FASTPATH_FRAGMENT_FIRST)
280                         stream_set_pos(fastpath->updateData, 0);
281
282                 stream_check_size(fastpath->updateData, size);
283                 stream_copy(fastpath->updateData, comp_stream, size);
284
285                 if (fragmentation == FASTPATH_FRAGMENT_LAST)
286                 {
287                         update_stream = fastpath->updateData;
288                         totalSize = stream_get_length(update_stream);
289                         stream_set_pos(update_stream, 0);
290                 }
291         }
292
293         if (update_stream)
294                 fastpath_recv_update(fastpath, updateCode, totalSize, update_stream);
295
296         stream_set_pos(s, next_pos);
297
298         if (comp_stream != s)
299                 xfree(comp_stream);
300 }
301
302 boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s)
303 {
304         rdpUpdate* update = fastpath->rdp->update;
305
306         IFCALL(update->BeginPaint, update->context);
307
308         while (stream_get_left(s) >= 3)
309         {
310                 fastpath_recv_update_data(fastpath, s);
311         }
312
313         IFCALL(update->EndPaint, update->context);
314
315         return true;
316 }
317
318 static boolean fastpath_read_input_event_header(STREAM* s, uint8* eventFlags, uint8* eventCode)
319 {
320         uint8 eventHeader;
321
322         if (stream_get_left(s) < 1)
323                 return false;
324
325         stream_read_uint8(s, eventHeader); /* eventHeader (1 byte) */
326
327         *eventFlags = (eventHeader & 0x1F);
328         *eventCode = (eventHeader >> 5);
329
330         return true;
331 }
332
333 static boolean fastpath_recv_input_event_scancode(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
334 {
335         uint16 flags;
336         uint16 code;
337
338         if (stream_get_left(s) < 1)
339                 return false;
340
341         stream_read_uint8(s, code); /* keyCode (1 byte) */
342
343         flags = 0;
344         if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
345                 flags |= KBD_FLAGS_RELEASE;
346         else
347                 flags |= KBD_FLAGS_DOWN;
348
349         if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_EXTENDED))
350                 flags |= KBD_FLAGS_EXTENDED;
351
352         IFCALL(fastpath->rdp->input->KeyboardEvent, fastpath->rdp->input, flags, code);
353
354         return true;
355 }
356
357 static boolean fastpath_recv_input_event_mouse(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
358 {
359         uint16 pointerFlags;
360         uint16 xPos;
361         uint16 yPos;
362
363         if (stream_get_left(s) < 6)
364                 return false;
365
366         stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */
367         stream_read_uint16(s, xPos); /* xPos (2 bytes) */
368         stream_read_uint16(s, yPos); /* yPos (2 bytes) */
369
370         IFCALL(fastpath->rdp->input->MouseEvent, fastpath->rdp->input, pointerFlags, xPos, yPos);
371
372         return true;
373 }
374
375 static boolean fastpath_recv_input_event_mousex(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
376 {
377         uint16 pointerFlags;
378         uint16 xPos;
379         uint16 yPos;
380
381         if (stream_get_left(s) < 6)
382                 return false;
383
384         stream_read_uint16(s, pointerFlags); /* pointerFlags (2 bytes) */
385         stream_read_uint16(s, xPos); /* xPos (2 bytes) */
386         stream_read_uint16(s, yPos); /* yPos (2 bytes) */
387
388         IFCALL(fastpath->rdp->input->ExtendedMouseEvent, fastpath->rdp->input, pointerFlags, xPos, yPos);
389
390         return true;
391 }
392
393 static boolean fastpath_recv_input_event_sync(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
394 {
395         IFCALL(fastpath->rdp->input->SynchronizeEvent, fastpath->rdp->input, eventFlags);
396
397         return true;
398 }
399
400 static boolean fastpath_recv_input_event_unicode(rdpFastPath* fastpath, STREAM* s, uint8 eventFlags)
401 {
402         uint16 unicodeCode;
403         uint16 flags;
404
405         if (stream_get_left(s) < 2)
406                 return false;
407
408         stream_read_uint16(s, unicodeCode); /* unicodeCode (2 bytes) */
409
410         flags = 0;
411         if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
412                 flags |= KBD_FLAGS_RELEASE;
413         else
414                 flags |= KBD_FLAGS_DOWN;
415
416         IFCALL(fastpath->rdp->input->UnicodeKeyboardEvent, fastpath->rdp->input, flags, unicodeCode);
417
418         return true;
419 }
420
421 static boolean fastpath_recv_input_event(rdpFastPath* fastpath, STREAM* s)
422 {
423         uint8 eventFlags;
424         uint8 eventCode;
425
426         if (!fastpath_read_input_event_header(s, &eventFlags, &eventCode))
427                 return false;
428
429         switch (eventCode)
430         {
431                 case FASTPATH_INPUT_EVENT_SCANCODE:
432                         if (!fastpath_recv_input_event_scancode(fastpath, s, eventFlags))
433                                 return false;
434                         break;
435
436                 case FASTPATH_INPUT_EVENT_MOUSE:
437                         if (!fastpath_recv_input_event_mouse(fastpath, s, eventFlags))
438                                 return false;
439                         break;
440
441                 case FASTPATH_INPUT_EVENT_MOUSEX:
442                         if (!fastpath_recv_input_event_mousex(fastpath, s, eventFlags))
443                                 return false;
444                         break;
445
446                 case FASTPATH_INPUT_EVENT_SYNC:
447                         if (!fastpath_recv_input_event_sync(fastpath, s, eventFlags))
448                                 return false;
449                         break;
450
451                 case FASTPATH_INPUT_EVENT_UNICODE:
452                         if (!fastpath_recv_input_event_unicode(fastpath, s, eventFlags))
453                                 return false;
454                         break;
455
456                 default:
457                         printf("Unknown eventCode %d\n", eventCode);
458                         break;
459         }
460
461         return true;
462 }
463
464 boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
465 {
466         uint8 i;
467
468         if (fastpath->numberEvents == 0)
469         {
470                 /**
471                  * If numberEvents is not provided in fpInputHeader, it will be provided
472                  * as one additional byte here.
473                  */
474
475                 if (stream_get_left(s) < 1)
476                         return false;
477
478                 stream_read_uint8(s, fastpath->numberEvents); /* eventHeader (1 byte) */
479         }
480
481         for (i = 0; i < fastpath->numberEvents; i++)
482         {
483                 if (!fastpath_recv_input_event(fastpath, s))
484                         return false;
485         }
486
487         return true;
488 }
489
490 static uint32 fastpath_get_sec_bytes(rdpRdp* rdp)
491 {
492         uint32 sec_bytes;
493
494         if (rdp->do_crypt)
495         {
496                 sec_bytes = 8;
497                 if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS)
498                         sec_bytes += 4;
499         }
500         else
501                 sec_bytes = 0;
502         return sec_bytes;
503 }
504
505 STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode)
506 {
507         rdpRdp *rdp;
508         STREAM* s;
509
510         rdp = fastpath->rdp;
511
512         s = transport_send_stream_init(rdp->transport, 256);
513         stream_seek(s, 3); /* fpInputHeader, length1 and length2 */
514         if (rdp->do_crypt) {
515                 rdp->sec_flags |= SEC_ENCRYPT;
516                 if (rdp->do_secure_checksum)
517                         rdp->sec_flags |= SEC_SECURE_CHECKSUM;
518         }
519         stream_seek(s, fastpath_get_sec_bytes(rdp));
520         stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */
521         return s;
522 }
523
524 boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s)
525 {
526         rdpRdp *rdp;
527         uint16 length;
528         uint8 eventHeader;
529         int sec_bytes;
530
531         rdp = fastpath->rdp;
532
533         length = stream_get_length(s);
534         if (length > 127)
535         {
536                 printf("Maximum FastPath PDU length is 127\n");
537                 return false;
538         }
539
540         eventHeader = FASTPATH_INPUT_ACTION_FASTPATH;
541         eventHeader |= (1 << 2); /* numberEvents */
542         if (rdp->sec_flags & SEC_ENCRYPT)
543                 eventHeader |= (FASTPATH_INPUT_ENCRYPTED << 6);
544         if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
545                 eventHeader |= (FASTPATH_INPUT_SECURE_CHECKSUM << 6);
546
547         stream_set_pos(s, 0);
548         stream_write_uint8(s, eventHeader);
549         sec_bytes = fastpath_get_sec_bytes(fastpath->rdp);
550         /*
551          * We always encode length in two bytes, eventhough we could use
552          * only one byte if length <= 0x7F. It is just easier that way,
553          * because we can leave room for fixed-length header, store all
554          * the data first and then store the header.
555          */
556         stream_write_uint16_be(s, 0x8000 | (length + sec_bytes));
557
558         if (sec_bytes > 0)
559         {
560                 uint8* ptr;
561
562                 ptr = stream_get_tail(s) + sec_bytes;
563                 if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
564                         security_salted_mac_signature(rdp, ptr, length - 3, true, stream_get_tail(s));
565                 else
566                         security_mac_signature(rdp, ptr, length - 3, stream_get_tail(s));
567                 security_encrypt(ptr, length - 3, rdp);
568         }
569
570         rdp->sec_flags = 0;
571
572         stream_set_pos(s, length + sec_bytes);
573         if (transport_write(fastpath->rdp->transport, s) < 0)
574                 return false;
575
576         return true;
577 }
578
579 STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath)
580 {
581         STREAM* s;
582         s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE);
583         stream_seek(s, 3); /* fpOutputHeader, length1 and length2 */
584         stream_seek(s, fastpath_get_sec_bytes(fastpath->rdp));
585         stream_seek(s, 3); /* updateHeader, size */
586         return s;
587 }
588
589 boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM* s)
590 {
591         rdpRdp *rdp;
592         uint8* bm;
593         uint8* ptr;
594         int fragment;
595         int sec_bytes;
596         uint16 length;
597         boolean result;
598         uint16 pduLength;
599         uint16 maxLength;
600         uint32 totalLength;
601         uint8 fragmentation;
602         uint8 header;
603         STREAM* update;
604
605         result = true;
606
607         rdp = fastpath->rdp;
608         sec_bytes = fastpath_get_sec_bytes(rdp);
609         maxLength = FASTPATH_MAX_PACKET_SIZE - 6 - sec_bytes;
610         totalLength = stream_get_length(s) - 6 - sec_bytes;
611         stream_set_pos(s, 0);
612         update = stream_new(0);
613
614         for (fragment = 0; totalLength > 0; fragment++)
615         {
616                 length = MIN(maxLength, totalLength);
617                 totalLength -= length;
618                 pduLength = length + 6 + sec_bytes;
619
620                 if (totalLength == 0)
621                         fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST;
622                 else
623                         fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT;
624
625                 stream_get_mark(s, bm);
626                 header = 0;
627                 if (sec_bytes > 0)
628                         header |= (FASTPATH_OUTPUT_ENCRYPTED << 6);
629                 stream_write_uint8(s, header); /* fpOutputHeader (1 byte) */
630                 stream_write_uint8(s, 0x80 | (pduLength >> 8)); /* length1 */
631                 stream_write_uint8(s, pduLength & 0xFF); /* length2 */
632                 if (sec_bytes > 0)
633                         stream_seek(s, sec_bytes);
634                 fastpath_write_update_header(s, updateCode, fragmentation, 0);
635                 stream_write_uint16(s, length);
636
637                 stream_attach(update, bm, pduLength);
638                 stream_seek(update, pduLength);
639                 if (sec_bytes > 0)
640                 {
641                         ptr = bm + 3 + sec_bytes;
642                         if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
643                                 security_salted_mac_signature(rdp, ptr, length + 3, true, bm + 3);
644                         else
645                                 security_mac_signature(rdp, ptr, length + 3, bm + 3);
646                         security_encrypt(ptr, length + 3, rdp);
647                 }
648                 if (transport_write(fastpath->rdp->transport, update) < 0)
649                 {
650                         stream_detach(update);
651                         result = false;
652                         break;
653                 }
654                 stream_detach(update);
655
656                 /* Reserve 6+sec_bytes bytes for the next fragment header, if any. */
657                 stream_seek(s, length - 6 - sec_bytes);
658         }
659
660         stream_free(update);
661
662         return result;
663 }
664
665 rdpFastPath* fastpath_new(rdpRdp* rdp)
666 {
667         rdpFastPath* fastpath;
668
669         fastpath = xnew(rdpFastPath);
670         fastpath->rdp = rdp;
671         fastpath->updateData = stream_new(4096);
672
673         return fastpath;
674 }
675
676 void fastpath_free(rdpFastPath* fastpath)
677 {
678         stream_free(fastpath->updateData);
679         xfree(fastpath);
680 }