source: mainline/uspace/srv/hid/rfb/rfb.c@ a35b458

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 20.9 KB
Line 
1/*
2 * Copyright (c) 2013 Martin Sucha
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <errno.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <fibril_synch.h>
33#include <inet/addr.h>
34#include <inet/endpoint.h>
35#include <inet/tcp.h>
36#include <inttypes.h>
37#include <str.h>
38#include <str_error.h>
39#include <byteorder.h>
40#include <macros.h>
41#include <io/log.h>
42
43#include "rfb.h"
44
45static void rfb_new_conn(tcp_listener_t *, tcp_conn_t *);
46
47static tcp_listen_cb_t listen_cb = {
48 .new_conn = rfb_new_conn
49};
50
51static tcp_cb_t conn_cb = {
52 .connected = NULL
53};
54
55/** Buffer for receiving the request. */
56#define BUFFER_SIZE 1024
57
58static char rbuf[BUFFER_SIZE];
59static size_t rbuf_out;
60static size_t rbuf_in;
61
62
63/** Receive one character (with buffering) */
64static errno_t recv_char(tcp_conn_t *conn, char *c)
65{
66 size_t nrecv;
67 errno_t rc;
68
69 if (rbuf_out == rbuf_in) {
70 rbuf_out = 0;
71 rbuf_in = 0;
72
73 rc = tcp_conn_recv_wait(conn, rbuf, BUFFER_SIZE, &nrecv);
74 if (rc != EOK)
75 return rc;
76
77 rbuf_in = nrecv;
78 }
79
80 *c = rbuf[rbuf_out++];
81 return EOK;
82}
83
84/** Receive count characters (with buffering) */
85static errno_t recv_chars(tcp_conn_t *conn, char *c, size_t count)
86{
87 for (size_t i = 0; i < count; i++) {
88 errno_t rc = recv_char(conn, c);
89 if (rc != EOK)
90 return rc;
91 c++;
92 }
93 return EOK;
94}
95
96static errno_t recv_skip_chars(tcp_conn_t *conn, size_t count)
97{
98 for (size_t i = 0; i < count; i++) {
99 char c;
100 errno_t rc = recv_char(conn, &c);
101 if (rc != EOK)
102 return rc;
103 }
104 return EOK;
105}
106
107static void rfb_pixel_format_to_be(rfb_pixel_format_t *src, rfb_pixel_format_t *dst)
108{
109 dst->r_max = host2uint16_t_be(src->r_max);
110 dst->g_max = host2uint16_t_be(src->g_max);
111 dst->b_max = host2uint16_t_be(src->b_max);
112}
113
114static void rfb_pixel_format_to_host(rfb_pixel_format_t *src, rfb_pixel_format_t *dst)
115{
116 dst->r_max = uint16_t_be2host(src->r_max);
117 dst->g_max = uint16_t_be2host(src->g_max);
118 dst->b_max = uint16_t_be2host(src->b_max);
119}
120
121static void rfb_server_init_to_be(rfb_server_init_t *src, rfb_server_init_t *dst)
122{
123 dst->width = host2uint16_t_be(src->width);
124 dst->height = host2uint16_t_be(src->height);
125 rfb_pixel_format_to_be(&src->pixel_format, &dst->pixel_format);
126 dst->name_length = host2uint32_t_be(src->name_length);
127}
128
129static void rfb_set_encodings_to_host(rfb_set_encodings_t *src, rfb_set_encodings_t *dst)
130{
131 dst->count = uint16_t_be2host(src->count);
132}
133
134static void rfb_framebuffer_update_request_to_host(rfb_framebuffer_update_request_t *src,
135 rfb_framebuffer_update_request_t *dst)
136{
137 dst->x = uint16_t_be2host(src->x);
138 dst->y = uint16_t_be2host(src->x);
139 dst->width = uint16_t_be2host(src->width);
140 dst->height = uint16_t_be2host(src->height);
141}
142
143static void rfb_framebuffer_update_to_be(rfb_framebuffer_update_t *src,
144 rfb_framebuffer_update_t *dst)
145{
146 dst->rect_count = host2uint16_t_be(src->rect_count);
147}
148
149static void rfb_rectangle_to_be(rfb_rectangle_t *src, rfb_rectangle_t *dst)
150{
151 dst->x = host2uint16_t_be(src->x);
152 dst->y = host2uint16_t_be(src->y);
153 dst->width = host2uint16_t_be(src->width);
154 dst->height = host2uint16_t_be(src->height);
155 dst->enctype = host2uint32_t_be(src->enctype);
156}
157
158static void rfb_key_event_to_host(rfb_key_event_t *src, rfb_key_event_t *dst)
159{
160 dst->key = uint32_t_be2host(src->key);
161}
162
163static void rfb_pointer_event_to_host(rfb_pointer_event_t *src, rfb_pointer_event_t *dst)
164{
165 dst->x = uint16_t_be2host(src->x);
166 dst->y = uint16_t_be2host(src->y);
167}
168
169static void rfb_client_cut_text_to_host(rfb_client_cut_text_t *src,
170 rfb_client_cut_text_t *dst)
171{
172 dst->length = uint32_t_be2host(src->length);
173}
174
175errno_t rfb_init(rfb_t *rfb, uint16_t width, uint16_t height, const char *name)
176{
177 memset(rfb, 0, sizeof(rfb_t));
178 fibril_mutex_initialize(&rfb->lock);
179
180 rfb_pixel_format_t *pf = &rfb->pixel_format;
181 pf->bpp = 32;
182 pf->depth = 24;
183 pf->big_endian = 1;
184 pf->true_color = 1;
185 pf->r_max = 255;
186 pf->g_max = 255;
187 pf->b_max = 255;
188 pf->r_shift = 0;
189 pf->g_shift = 8;
190 pf->b_shift = 16;
191
192 rfb->name = str_dup(name);
193 rfb->supports_trle = false;
194
195 return rfb_set_size(rfb, width, height);
196}
197
198errno_t rfb_set_size(rfb_t *rfb, uint16_t width, uint16_t height)
199{
200 size_t new_size = width * height * sizeof(pixel_t);
201 void *pixbuf = malloc(new_size);
202 if (pixbuf == NULL)
203 return ENOMEM;
204
205 free(rfb->framebuffer.data);
206 rfb->framebuffer.data = pixbuf;
207 rfb->framebuffer.width = width;
208 rfb->framebuffer.height = height;
209 rfb->width = width;
210 rfb->height = height;
211
212 /* Fill with white */
213 memset(rfb->framebuffer.data, 255, new_size);
214
215 return EOK;
216}
217
218static errno_t recv_message(tcp_conn_t *conn, char type, void *buf, size_t size)
219{
220 memcpy(buf, &type, 1);
221 return recv_chars(conn, ((char *) buf) + 1, size -1);
222}
223
224static uint32_t rfb_scale_channel(uint8_t val, uint32_t max)
225{
226 return val * max / 255;
227}
228
229static void rfb_encode_index(rfb_t *rfb, uint8_t *buf, pixel_t pixel)
230{
231 int first_free_index = -1;
232 for (size_t i = 0; i < 256; i++) {
233 bool free = ALPHA(rfb->palette[i]) == 0;
234 if (free && first_free_index == -1) {
235 first_free_index = i;
236 }
237 else if (!free && RED(rfb->palette[i]) == RED(pixel) &&
238 GREEN(rfb->palette[i]) == GREEN(pixel) &&
239 BLUE(rfb->palette[i]) == BLUE(pixel)) {
240 *buf = i;
241 return;
242 }
243 }
244
245 if (first_free_index != -1) {
246 rfb->palette[first_free_index] = PIXEL(255, RED(pixel), GREEN(pixel),
247 BLUE(pixel));
248 rfb->palette_used = max(rfb->palette_used, (unsigned) first_free_index + 1);
249 *buf = first_free_index;
250 return;
251 }
252
253 /* TODO find nearest color index. We are lazy so return index 0 for now */
254 *buf = 0;
255}
256
257static void rfb_encode_true_color(rfb_pixel_format_t *pf, void *buf,
258 pixel_t pixel)
259{
260 uint32_t pix = 0;
261 pix |= rfb_scale_channel(RED(pixel), pf->r_max) << pf->r_shift;
262 pix |= rfb_scale_channel(GREEN(pixel), pf->g_max) << pf->g_shift;
263 pix |= rfb_scale_channel(BLUE(pixel), pf->b_max) << pf->b_shift;
264
265 if (pf->bpp == 8) {
266 uint8_t pix8 = pix;
267 memcpy(buf, &pix8, 1);
268 }
269 else if (pf->bpp == 16) {
270 uint16_t pix16 = pix;
271 if (pf->big_endian) {
272 pix16 = host2uint16_t_be(pix16);
273 }
274 else {
275 pix16 = host2uint16_t_le(pix16);
276 }
277 memcpy(buf, &pix16, 2);
278 }
279 else if (pf->bpp == 32) {
280 if (pf->big_endian) {
281 pix = host2uint32_t_be(pix);
282 }
283 else {
284 pix = host2uint32_t_le(pix);
285 }
286 memcpy(buf, &pix, 4);
287 }
288}
289
290static void rfb_encode_pixel(rfb_t *rfb, void *buf, pixel_t pixel)
291{
292 if (rfb->pixel_format.true_color) {
293 rfb_encode_true_color(&rfb->pixel_format, buf, pixel);
294 }
295 else {
296 rfb_encode_index(rfb, buf, pixel);
297 }
298}
299
300static void rfb_set_color_map_entries_to_be(rfb_set_color_map_entries_t *src,
301 rfb_set_color_map_entries_t *dst)
302{
303 dst->first_color = host2uint16_t_be(src->first_color);
304 dst->color_count = host2uint16_t_be(src->color_count);
305}
306
307static void rfb_color_map_entry_to_be(rfb_color_map_entry_t *src,
308 rfb_color_map_entry_t *dst)
309{
310 dst->red = host2uint16_t_be(src->red);
311 dst->green = host2uint16_t_be(src->green);
312 dst->blue = host2uint16_t_be(src->blue);
313}
314
315static void *rfb_send_palette_message(rfb_t *rfb, size_t *psize)
316{
317 size_t size = sizeof(rfb_set_color_map_entries_t) +
318 rfb->palette_used * sizeof(rfb_color_map_entry_t);
319
320 void *buf = malloc(size);
321 if (buf == NULL)
322 return NULL;
323
324 void *pos = buf;
325
326 rfb_set_color_map_entries_t *scme = pos;
327 scme->message_type = RFB_SMSG_SET_COLOR_MAP_ENTRIES;
328 scme->first_color = 0;
329 scme->color_count = rfb->palette_used;
330 rfb_set_color_map_entries_to_be(scme, scme);
331 pos += sizeof(rfb_set_color_map_entries_t);
332
333 rfb_color_map_entry_t *entries = pos;
334 for (unsigned i = 0; i < rfb->palette_used; i++) {
335 entries[i].red = 65535 * RED(rfb->palette[i]) / 255;
336 entries[i].green = 65535 * GREEN(rfb->palette[i]) / 255;
337 entries[i].blue = 65535 * BLUE(rfb->palette[i]) / 255;
338 rfb_color_map_entry_to_be(&entries[i], &entries[i]);
339 }
340
341 *psize = size;
342 return buf;
343}
344
345static size_t rfb_rect_encode_raw(rfb_t *rfb, rfb_rectangle_t *rect, void *buf)
346{
347 size_t pixel_size = rfb->pixel_format.bpp / 8;
348 size_t size = (rect->width * rect->height * pixel_size);
349
350 if (buf == NULL)
351 return size;
352
353 for (uint16_t y = 0; y < rect->height; y++) {
354 for (uint16_t x = 0; x < rect->width; x++) {
355 pixel_t pixel = pixelmap_get_pixel(&rfb->framebuffer,
356 x + rect->x, y + rect->y);
357 rfb_encode_pixel(rfb, buf, pixel);
358 buf += pixel_size;
359 }
360 }
361
362 return size;
363}
364
365typedef enum {
366 COMP_NONE, COMP_SKIP_START, COMP_SKIP_END
367} cpixel_compress_type_t;
368
369typedef struct {
370 size_t size;
371 cpixel_compress_type_t compress_type;
372} cpixel_ctx_t;
373
374static void cpixel_context_init(cpixel_ctx_t *ctx, rfb_pixel_format_t *pixel_format)
375{
376 ctx->size = pixel_format->bpp / 8;
377 ctx->compress_type = COMP_NONE;
378
379 if (pixel_format->bpp == 32 && pixel_format->depth <= 24) {
380 uint32_t mask = 0;
381 mask |= pixel_format->r_max << pixel_format->r_shift;
382 mask |= pixel_format->g_max << pixel_format->g_shift;
383 mask |= pixel_format->b_max << pixel_format->b_shift;
384
385 if (pixel_format->big_endian) {
386 mask = host2uint32_t_be(mask);
387 }
388 else {
389 mask = host2uint32_t_le(mask);
390 }
391
392 uint8_t *mask_data = (uint8_t *) &mask;
393 if (mask_data[0] == 0) {
394 ctx->compress_type = COMP_SKIP_START;
395 ctx->size = 3;
396 }
397 else if (mask_data[3] == 0) {
398 ctx->compress_type = COMP_SKIP_END;
399 ctx->size = 3;
400 }
401 }
402}
403
404static void cpixel_encode(rfb_t *rfb, cpixel_ctx_t *cpixel, void *buf,
405 pixel_t pixel)
406{
407 uint8_t data[4];
408 rfb_encode_pixel(rfb, data, pixel);
409
410 switch (cpixel->compress_type) {
411 case COMP_NONE:
412 case COMP_SKIP_END:
413 memcpy(buf, data, cpixel->size);
414 break;
415 case COMP_SKIP_START:
416 memcpy(buf, data + 1, cpixel->size);
417 }
418}
419
420static size_t rfb_tile_encode_raw(rfb_t *rfb, cpixel_ctx_t *cpixel,
421 rfb_rectangle_t *tile, void *buf)
422{
423 size_t size = tile->width * tile->height * cpixel->size;
424 if (buf == NULL)
425 return size;
426
427 for (uint16_t y = tile->y; y < tile->y + tile->height; y++) {
428 for (uint16_t x = tile->x; x < tile->x + tile->width; x++) {
429 pixel_t pixel = pixelmap_get_pixel(&rfb->framebuffer, x, y);
430 cpixel_encode(rfb, cpixel, buf, pixel);
431 }
432 }
433
434 return size;
435}
436
437static errno_t rfb_tile_encode_solid(rfb_t *rfb, cpixel_ctx_t *cpixel,
438 rfb_rectangle_t *tile, void *buf, size_t *size)
439{
440 /* Check if it is single color */
441 pixel_t the_color = pixelmap_get_pixel(&rfb->framebuffer, tile->x, tile->y);
442 for (uint16_t y = tile->y; y < tile->y + tile->height; y++) {
443 for (uint16_t x = tile->x; x < tile->x + tile->width; x++) {
444 if (pixelmap_get_pixel(&rfb->framebuffer, x, y) != the_color)
445 return EINVAL;
446 }
447 }
448
449 /* OK, encode it */
450 if (buf)
451 cpixel_encode(rfb, cpixel, buf, the_color);
452 *size = cpixel->size;
453 return EOK;
454}
455
456static size_t rfb_rect_encode_trle(rfb_t *rfb, rfb_rectangle_t *rect, void *buf)
457{
458 cpixel_ctx_t cpixel;
459 cpixel_context_init(&cpixel, &rfb->pixel_format);
460
461 size_t size = 0;
462 for (uint16_t y = 0; y < rect->height; y += 16) {
463 for (uint16_t x = 0; x < rect->width; x += 16) {
464 rfb_rectangle_t tile = {
465 .x = x,
466 .y = y,
467 .width = (x + 16 <= rect->width ? 16 : rect->width - x),
468 .height = (y + 16 <= rect->height ? 16 : rect->height - y)
469 };
470
471 size += 1;
472 uint8_t *tile_enctype_ptr = buf;
473 if (buf)
474 buf += 1;
475
476 uint8_t tile_enctype = RFB_TILE_ENCODING_SOLID;
477 size_t tile_size;
478 errno_t rc = rfb_tile_encode_solid(rfb, &cpixel, &tile, buf,
479 &tile_size);
480 if (rc != EOK) {
481 tile_size = rfb_tile_encode_raw(rfb, &cpixel, &tile, buf);
482 tile_enctype = RFB_TILE_ENCODING_RAW;
483 }
484
485 if (buf) {
486 *tile_enctype_ptr = tile_enctype;
487 buf += tile_size;
488 }
489 }
490 }
491 return size;
492}
493
494static errno_t rfb_send_framebuffer_update(rfb_t *rfb, tcp_conn_t *conn,
495 bool incremental)
496{
497 fibril_mutex_lock(&rfb->lock);
498 if (!incremental || !rfb->damage_valid) {
499 rfb->damage_rect.x = 0;
500 rfb->damage_rect.y = 0;
501 rfb->damage_rect.width = rfb->width;
502 rfb->damage_rect.height = rfb->height;
503 }
504
505
506 /* We send only single raw rectangle right now */
507 size_t buf_size = sizeof(rfb_framebuffer_update_t) +
508 sizeof(rfb_rectangle_t) * 1 +
509 rfb_rect_encode_raw(rfb, &rfb->damage_rect, NULL)
510 ;
511
512 void *buf = malloc(buf_size);
513 if (buf == NULL) {
514 fibril_mutex_unlock(&rfb->lock);
515 return ENOMEM;
516 }
517 memset(buf, 0, buf_size);
518
519 void *pos = buf;
520 rfb_framebuffer_update_t *fbu = buf;
521 fbu->message_type = RFB_SMSG_FRAMEBUFFER_UPDATE;
522 fbu->rect_count = 1;
523 rfb_framebuffer_update_to_be(fbu, fbu);
524 pos += sizeof(rfb_framebuffer_update_t);
525
526 rfb_rectangle_t *rect = pos;
527 pos += sizeof(rfb_rectangle_t);
528
529 *rect = rfb->damage_rect;
530
531 if (rfb->supports_trle) {
532 rect->enctype = RFB_ENCODING_TRLE;
533 pos += rfb_rect_encode_trle(rfb, rect, pos);
534 }
535 else {
536 rect->enctype = RFB_ENCODING_RAW;
537 pos += rfb_rect_encode_raw(rfb, rect, pos);
538 }
539 rfb_rectangle_to_be(rect, rect);
540
541 rfb->damage_valid = false;
542
543 size_t send_palette_size = 0;
544 void *send_palette = NULL;
545
546 if (!rfb->pixel_format.true_color) {
547 send_palette = rfb_send_palette_message(rfb, &send_palette_size);
548 if (send_palette == NULL) {
549 free(buf);
550 fibril_mutex_unlock(&rfb->lock);
551 return ENOMEM;
552 }
553 }
554
555 fibril_mutex_unlock(&rfb->lock);
556
557 if (!rfb->pixel_format.true_color) {
558 errno_t rc = tcp_conn_send(conn, send_palette, send_palette_size);
559 if (rc != EOK) {
560 free(buf);
561 return rc;
562 }
563 }
564
565 errno_t rc = tcp_conn_send(conn, buf, buf_size);
566 free(buf);
567
568 return rc;
569}
570
571static errno_t rfb_set_pixel_format(rfb_t *rfb, rfb_pixel_format_t *pixel_format)
572{
573 rfb->pixel_format = *pixel_format;
574 if (rfb->pixel_format.true_color) {
575 free(rfb->palette);
576 rfb->palette = NULL;
577 rfb->palette_used = 0;
578 log_msg(LOG_DEFAULT, LVL_DEBUG,
579 "changed pixel format to %d-bit true color (%x<<%d, %x<<%d, %x<<%d)",
580 pixel_format->depth, pixel_format->r_max, pixel_format->r_shift,
581 pixel_format->g_max, pixel_format->g_shift, pixel_format->b_max,
582 pixel_format->b_shift);
583 }
584 else {
585 if (rfb->palette == NULL) {
586 rfb->palette = malloc(sizeof(pixel_t) * 256);
587 if (rfb->palette == NULL)
588 return ENOMEM;
589 memset(rfb->palette, 0, sizeof(pixel_t) * 256);
590 rfb->palette_used = 0;
591 }
592 log_msg(LOG_DEFAULT, LVL_DEBUG, "changed pixel format to %d-bit palette",
593 pixel_format->depth);
594 }
595 return EOK;
596}
597
598static void rfb_socket_connection(rfb_t *rfb, tcp_conn_t *conn)
599{
600 /* Version handshake */
601 errno_t rc = tcp_conn_send(conn, "RFB 003.008\n", 12);
602 if (rc != EOK) {
603 log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server version: %s",
604 str_error(rc));
605 return;
606 }
607
608 char client_version[12];
609 rc = recv_chars(conn, client_version, 12);
610 if (rc != EOK) {
611 log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client version: %s",
612 str_error(rc));
613 return;
614 }
615
616 if (memcmp(client_version, "RFB 003.008\n", 12) != 0) {
617 log_msg(LOG_DEFAULT, LVL_WARN, "Client version is not RFB 3.8");
618 return;
619 }
620
621 /* Security handshake
622 * 1 security type supported, which is 1 - None
623 */
624 char sec_types[2];
625 sec_types[0] = 1; /* length */
626 sec_types[1] = RFB_SECURITY_NONE;
627 rc = tcp_conn_send(conn, sec_types, 2);
628 if (rc != EOK) {
629 log_msg(LOG_DEFAULT, LVL_WARN,
630 "Failed sending security handshake: %s", str_error(rc));
631 return;
632 }
633
634 char selected_sec_type = 0;
635 rc = recv_char(conn, &selected_sec_type);
636 if (rc != EOK) {
637 log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving security type: %s",
638 str_error(rc));
639 return;
640 }
641 if (selected_sec_type != RFB_SECURITY_NONE) {
642 log_msg(LOG_DEFAULT, LVL_WARN,
643 "Client selected security type other than none");
644 return;
645 }
646 uint32_t security_result = RFB_SECURITY_HANDSHAKE_OK;
647 rc = tcp_conn_send(conn, &security_result, sizeof(uint32_t));
648 if (rc != EOK) {
649 log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending security result: %s",
650 str_error(rc));
651 return;
652 }
653
654 /* Client init */
655 char shared_flag;
656 rc = recv_char(conn, &shared_flag);
657 if (rc != EOK) {
658 log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client init: %s",
659 str_error(rc));
660 return;
661 }
662
663 /* Server init */
664 fibril_mutex_lock(&rfb->lock);
665 size_t name_length = str_length(rfb->name);
666 size_t msg_length = sizeof(rfb_server_init_t) + name_length;
667 rfb_server_init_t *server_init = malloc(msg_length);
668 if (server_init == NULL) {
669 log_msg(LOG_DEFAULT, LVL_WARN, "Cannot allocate memory for server init");
670 fibril_mutex_unlock(&rfb->lock);
671 return;
672 }
673 server_init->width = rfb->width;
674 server_init->height = rfb->height;
675 server_init->pixel_format = rfb->pixel_format,
676 server_init->name_length = name_length;
677 rfb_server_init_to_be(server_init, server_init);
678 memcpy(server_init->name, rfb->name, name_length);
679 fibril_mutex_unlock(&rfb->lock);
680 rc = tcp_conn_send(conn, server_init, msg_length);
681 if (rc != EOK) {
682 log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server init: %s",
683 str_error(rc));
684 return;
685 }
686
687 while (true) {
688 char message_type = 0;
689 rc = recv_char(conn, &message_type);
690 if (rc != EOK) {
691 log_msg(LOG_DEFAULT, LVL_WARN,
692 "Failed receiving client message type");
693 return;
694 }
695
696 rfb_set_pixel_format_t spf;
697 rfb_set_encodings_t se;
698 rfb_framebuffer_update_request_t fbur;
699 rfb_key_event_t ke;
700 rfb_pointer_event_t pe;
701 rfb_client_cut_text_t cct;
702 switch (message_type) {
703 case RFB_CMSG_SET_PIXEL_FORMAT:
704 recv_message(conn, message_type, &spf, sizeof(spf));
705 rfb_pixel_format_to_host(&spf.pixel_format, &spf.pixel_format);
706 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received SetPixelFormat message");
707 fibril_mutex_lock(&rfb->lock);
708 rc = rfb_set_pixel_format(rfb, &spf.pixel_format);
709 fibril_mutex_unlock(&rfb->lock);
710 if (rc != EOK)
711 return;
712 break;
713 case RFB_CMSG_SET_ENCODINGS:
714 recv_message(conn, message_type, &se, sizeof(se));
715 rfb_set_encodings_to_host(&se, &se);
716 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received SetEncodings message");
717 for (uint16_t i = 0; i < se.count; i++) {
718 int32_t encoding = 0;
719 rc = recv_chars(conn, (char *) &encoding, sizeof(int32_t));
720 if (rc != EOK)
721 return;
722 encoding = uint32_t_be2host(encoding);
723 if (encoding == RFB_ENCODING_TRLE) {
724 log_msg(LOG_DEFAULT, LVL_DEBUG,
725 "Client supports TRLE encoding");
726 rfb->supports_trle = true;
727 }
728 }
729 break;
730 case RFB_CMSG_FRAMEBUFFER_UPDATE_REQUEST:
731 recv_message(conn, message_type, &fbur, sizeof(fbur));
732 rfb_framebuffer_update_request_to_host(&fbur, &fbur);
733 log_msg(LOG_DEFAULT, LVL_DEBUG2,
734 "Received FramebufferUpdateRequest message");
735 rfb_send_framebuffer_update(rfb, conn, fbur.incremental);
736 break;
737 case RFB_CMSG_KEY_EVENT:
738 recv_message(conn, message_type, &ke, sizeof(ke));
739 rfb_key_event_to_host(&ke, &ke);
740 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received KeyEvent message");
741 break;
742 case RFB_CMSG_POINTER_EVENT:
743 recv_message(conn, message_type, &pe, sizeof(pe));
744 rfb_pointer_event_to_host(&pe, &pe);
745 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received PointerEvent message");
746 break;
747 case RFB_CMSG_CLIENT_CUT_TEXT:
748 recv_message(conn, message_type, &cct, sizeof(cct));
749 rfb_client_cut_text_to_host(&cct, &cct);
750 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received ClientCutText message");
751 recv_skip_chars(conn, cct.length);
752 break;
753 default:
754 log_msg(LOG_DEFAULT, LVL_WARN,
755 "Invalid client message type encountered");
756 return;
757 }
758 }
759}
760
761errno_t rfb_listen(rfb_t *rfb, uint16_t port)
762{
763 tcp_t *tcp = NULL;
764 tcp_listener_t *lst = NULL;
765 inet_ep_t ep;
766 errno_t rc;
767
768 rc = tcp_create(&tcp);
769 if (rc != EOK) {
770 log_msg(LOG_DEFAULT, LVL_ERROR, "Error initializing TCP.");
771 goto error;
772 }
773
774 inet_ep_init(&ep);
775 ep.port = port;
776
777 rc = tcp_listener_create(tcp, &ep, &listen_cb, rfb, &conn_cb, rfb,
778 &lst);
779 if (rc != EOK) {
780 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating listener.");
781 goto error;
782 }
783
784 rfb->tcp = tcp;
785 rfb->lst = lst;
786
787 return EOK;
788error:
789 tcp_listener_destroy(lst);
790 tcp_destroy(tcp);
791 return rc;
792}
793
794static void rfb_new_conn(tcp_listener_t *lst, tcp_conn_t *conn)
795{
796 rfb_t *rfb = (rfb_t *)tcp_listener_userptr(lst);
797 log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection accepted");
798
799 rbuf_out = 0;
800 rbuf_in = 0;
801
802 rfb_socket_connection(rfb, conn);
803}
Note: See TracBrowser for help on using the repository browser.