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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c072a29 was 870f78c, checked in by Martin Sucha <sucha14@…>, 12 years ago

rfb: Do not hold lock while sending framebuffer update

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