source: mainline/uspace/srv/hid/rfb/rfb.c@ 1569a9b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1569a9b was 1569a9b, checked in by GitHub <noreply@…>, 8 years ago

The "not-so-obvious" error handling tweaks. (#9)

Some more changes to enable type-checking with errno_t. Some of the "fixes" here don't quite feel right, but a proper solution would be a more elaborate refactoring of the surrounding code.

  • 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 int recv_char(tcp_conn_t *conn, char *c)
65{
66 size_t nrecv;
67 int 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 int recv_chars(tcp_conn_t *conn, char *c, size_t count)
86{
87 for (size_t i = 0; i < count; i++) {
88 int rc = recv_char(conn, c);
89 if (rc != EOK)
90 return rc;
91 c++;
92 }
93 return EOK;
94}
95
96static int recv_skip_chars(tcp_conn_t *conn, size_t count)
97{
98 for (size_t i = 0; i < count; i++) {
99 char c;
100 int 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
175int 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
198int 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 int 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 int 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 int 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 int 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 int rc = tcp_conn_send(conn, send_palette, send_palette_size);
559 if (rc != EOK) {
560 free(buf);
561 return rc;
562 }
563 }
564
565 int rc = tcp_conn_send(conn, buf, buf_size);
566 free(buf);
567
568 return rc;
569}
570
571static int 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 int 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
761int 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 int 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.