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

Last change on this file was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 21.8 KB
RevLine 
[bd0e6a1]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>
[fab2746]33#include <inet/addr.h>
34#include <inet/endpoint.h>
35#include <inet/tcp.h>
[bd0e6a1]36#include <inttypes.h>
37#include <str.h>
38#include <str_error.h>
39#include <byteorder.h>
[2c9f6dd3]40#include <macros.h>
[47b27b40]41#include <io/log.h>
[bd0e6a1]42
43#include "rfb.h"
44
[fab2746]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
[bd0e6a1]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/** Receive one character (with buffering) */
[b7fd2a0]63static errno_t recv_char(tcp_conn_t *conn, char *c)
[bd0e6a1]64{
[fab2746]65 size_t nrecv;
[b7fd2a0]66 errno_t rc;
[fab2746]67
[bd0e6a1]68 if (rbuf_out == rbuf_in) {
69 rbuf_out = 0;
70 rbuf_in = 0;
[a35b458]71
[fab2746]72 rc = tcp_conn_recv_wait(conn, rbuf, BUFFER_SIZE, &nrecv);
73 if (rc != EOK)
[bd0e6a1]74 return rc;
[a35b458]75
[fab2746]76 rbuf_in = nrecv;
[bd0e6a1]77 }
[a35b458]78
[bd0e6a1]79 *c = rbuf[rbuf_out++];
80 return EOK;
81}
82
83/** Receive count characters (with buffering) */
[18b6a88]84static errno_t __attribute__((warn_unused_result))
85recv_chars(tcp_conn_t *conn, char *c, size_t count)
[bd0e6a1]86{
87 for (size_t i = 0; i < count; i++) {
[b7fd2a0]88 errno_t rc = recv_char(conn, c);
[bd0e6a1]89 if (rc != EOK)
90 return rc;
91 c++;
92 }
93 return EOK;
94}
95
[b7fd2a0]96static errno_t recv_skip_chars(tcp_conn_t *conn, size_t count)
[bd0e6a1]97{
98 for (size_t i = 0; i < count; i++) {
99 char c;
[b7fd2a0]100 errno_t rc = recv_char(conn, &c);
[bd0e6a1]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
[b7fd2a0]175errno_t rfb_init(rfb_t *rfb, uint16_t width, uint16_t height, const char *name)
[bd0e6a1]176{
177 memset(rfb, 0, sizeof(rfb_t));
178 fibril_mutex_initialize(&rfb->lock);
[a35b458]179
[bd0e6a1]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;
[a35b458]191
[0d23cc0]192 rfb->name = str_dup(name);
[38c822e]193 rfb->supports_trle = false;
[a35b458]194
[bd0e6a1]195 return rfb_set_size(rfb, width, height);
196}
197
[b7fd2a0]198errno_t rfb_set_size(rfb_t *rfb, uint16_t width, uint16_t height)
[bd0e6a1]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;
[a35b458]211
[bd0e6a1]212 /* Fill with white */
213 memset(rfb->framebuffer.data, 255, new_size);
[a35b458]214
[bd0e6a1]215 return EOK;
216}
217
[18b6a88]218static errno_t __attribute__((warn_unused_result))
219recv_message(tcp_conn_t *conn, char type, void *buf, size_t size)
[bd0e6a1]220{
221 memcpy(buf, &type, 1);
[18b6a88]222 return recv_chars(conn, ((char *) buf) + 1, size - 1);
[bd0e6a1]223}
224
225static uint32_t rfb_scale_channel(uint8_t val, uint32_t max)
226{
227 return val * max / 255;
228}
229
[2c9f6dd3]230static void rfb_encode_index(rfb_t *rfb, uint8_t *buf, pixel_t pixel)
231{
232 int first_free_index = -1;
233 for (size_t i = 0; i < 256; i++) {
234 bool free = ALPHA(rfb->palette[i]) == 0;
235 if (free && first_free_index == -1) {
236 first_free_index = i;
[18b6a88]237 } else if (!free && RED(rfb->palette[i]) == RED(pixel) &&
[2c9f6dd3]238 GREEN(rfb->palette[i]) == GREEN(pixel) &&
239 BLUE(rfb->palette[i]) == BLUE(pixel)) {
240 *buf = i;
241 return;
242 }
243 }
[a35b458]244
[2c9f6dd3]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 }
[a35b458]252
[2c9f6dd3]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)
[bd0e6a1]259{
260 uint32_t pix = 0;
[2c9f6dd3]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;
[a35b458]264
[bd0e6a1]265 if (pf->bpp == 8) {
266 uint8_t pix8 = pix;
267 memcpy(buf, &pix8, 1);
[18b6a88]268 } else if (pf->bpp == 16) {
[bd0e6a1]269 uint16_t pix16 = pix;
270 if (pf->big_endian) {
271 pix16 = host2uint16_t_be(pix16);
[18b6a88]272 } else {
[bd0e6a1]273 pix16 = host2uint16_t_le(pix16);
274 }
275 memcpy(buf, &pix16, 2);
[18b6a88]276 } else if (pf->bpp == 32) {
[bd0e6a1]277 if (pf->big_endian) {
278 pix = host2uint32_t_be(pix);
[18b6a88]279 } else {
[bd0e6a1]280 pix = host2uint32_t_le(pix);
281 }
282 memcpy(buf, &pix, 4);
283 }
284}
285
[2c9f6dd3]286static void rfb_encode_pixel(rfb_t *rfb, void *buf, pixel_t pixel)
287{
288 if (rfb->pixel_format.true_color) {
289 rfb_encode_true_color(&rfb->pixel_format, buf, pixel);
[18b6a88]290 } else {
[2c9f6dd3]291 rfb_encode_index(rfb, buf, pixel);
292 }
293}
294
295static void rfb_set_color_map_entries_to_be(rfb_set_color_map_entries_t *src,
296 rfb_set_color_map_entries_t *dst)
297{
298 dst->first_color = host2uint16_t_be(src->first_color);
299 dst->color_count = host2uint16_t_be(src->color_count);
300}
301
302static void rfb_color_map_entry_to_be(rfb_color_map_entry_t *src,
303 rfb_color_map_entry_t *dst)
304{
305 dst->red = host2uint16_t_be(src->red);
306 dst->green = host2uint16_t_be(src->green);
307 dst->blue = host2uint16_t_be(src->blue);
308}
309
[870f78c]310static void *rfb_send_palette_message(rfb_t *rfb, size_t *psize)
[2c9f6dd3]311{
312 size_t size = sizeof(rfb_set_color_map_entries_t) +
313 rfb->palette_used * sizeof(rfb_color_map_entry_t);
[a35b458]314
[2c9f6dd3]315 void *buf = malloc(size);
316 if (buf == NULL)
[870f78c]317 return NULL;
[a35b458]318
[2c9f6dd3]319 void *pos = buf;
[a35b458]320
[2c9f6dd3]321 rfb_set_color_map_entries_t *scme = pos;
322 scme->message_type = RFB_SMSG_SET_COLOR_MAP_ENTRIES;
323 scme->first_color = 0;
324 scme->color_count = rfb->palette_used;
325 rfb_set_color_map_entries_to_be(scme, scme);
326 pos += sizeof(rfb_set_color_map_entries_t);
[a35b458]327
[2c9f6dd3]328 rfb_color_map_entry_t *entries = pos;
329 for (unsigned i = 0; i < rfb->palette_used; i++) {
330 entries[i].red = 65535 * RED(rfb->palette[i]) / 255;
331 entries[i].green = 65535 * GREEN(rfb->palette[i]) / 255;
332 entries[i].blue = 65535 * BLUE(rfb->palette[i]) / 255;
333 rfb_color_map_entry_to_be(&entries[i], &entries[i]);
334 }
[a35b458]335
[870f78c]336 *psize = size;
337 return buf;
[2c9f6dd3]338}
339
[38c822e]340static size_t rfb_rect_encode_raw(rfb_t *rfb, rfb_rectangle_t *rect, void *buf)
341{
342 size_t pixel_size = rfb->pixel_format.bpp / 8;
343 size_t size = (rect->width * rect->height * pixel_size);
[a35b458]344
[38c822e]345 if (buf == NULL)
346 return size;
[a35b458]347
[38c822e]348 for (uint16_t y = 0; y < rect->height; y++) {
349 for (uint16_t x = 0; x < rect->width; x++) {
350 pixel_t pixel = pixelmap_get_pixel(&rfb->framebuffer,
351 x + rect->x, y + rect->y);
352 rfb_encode_pixel(rfb, buf, pixel);
353 buf += pixel_size;
354 }
355 }
[a35b458]356
[38c822e]357 return size;
358}
359
360typedef enum {
[18b6a88]361 COMP_NONE,
362 COMP_SKIP_START,
363 COMP_SKIP_END
[38c822e]364} cpixel_compress_type_t;
365
366typedef struct {
367 size_t size;
368 cpixel_compress_type_t compress_type;
369} cpixel_ctx_t;
370
371static void cpixel_context_init(cpixel_ctx_t *ctx, rfb_pixel_format_t *pixel_format)
372{
373 ctx->size = pixel_format->bpp / 8;
374 ctx->compress_type = COMP_NONE;
[a35b458]375
[38c822e]376 if (pixel_format->bpp == 32 && pixel_format->depth <= 24) {
377 uint32_t mask = 0;
378 mask |= pixel_format->r_max << pixel_format->r_shift;
379 mask |= pixel_format->g_max << pixel_format->g_shift;
380 mask |= pixel_format->b_max << pixel_format->b_shift;
[a35b458]381
[38c822e]382 if (pixel_format->big_endian) {
383 mask = host2uint32_t_be(mask);
[18b6a88]384 } else {
[38c822e]385 mask = host2uint32_t_le(mask);
386 }
[a35b458]387
[38c822e]388 uint8_t *mask_data = (uint8_t *) &mask;
389 if (mask_data[0] == 0) {
390 ctx->compress_type = COMP_SKIP_START;
391 ctx->size = 3;
[18b6a88]392 } else if (mask_data[3] == 0) {
[38c822e]393 ctx->compress_type = COMP_SKIP_END;
394 ctx->size = 3;
395 }
396 }
397}
398
399static void cpixel_encode(rfb_t *rfb, cpixel_ctx_t *cpixel, void *buf,
400 pixel_t pixel)
401{
402 uint8_t data[4];
403 rfb_encode_pixel(rfb, data, pixel);
[a35b458]404
[38c822e]405 switch (cpixel->compress_type) {
406 case COMP_NONE:
407 case COMP_SKIP_END:
408 memcpy(buf, data, cpixel->size);
409 break;
410 case COMP_SKIP_START:
411 memcpy(buf, data + 1, cpixel->size);
412 }
413}
414
[bde5c04]415static size_t rfb_tile_encode_raw(rfb_t *rfb, cpixel_ctx_t *cpixel,
[38c822e]416 rfb_rectangle_t *tile, void *buf)
417{
[bde5c04]418 size_t size = tile->width * tile->height * cpixel->size;
[38c822e]419 if (buf == NULL)
420 return size;
[a35b458]421
[38c822e]422 for (uint16_t y = tile->y; y < tile->y + tile->height; y++) {
423 for (uint16_t x = tile->x; x < tile->x + tile->width; x++) {
424 pixel_t pixel = pixelmap_get_pixel(&rfb->framebuffer, x, y);
425 cpixel_encode(rfb, cpixel, buf, pixel);
426 }
427 }
[a35b458]428
[38c822e]429 return size;
430}
431
[b7fd2a0]432static errno_t rfb_tile_encode_solid(rfb_t *rfb, cpixel_ctx_t *cpixel,
[bde5c04]433 rfb_rectangle_t *tile, void *buf, size_t *size)
[38c822e]434{
435 /* Check if it is single color */
436 pixel_t the_color = pixelmap_get_pixel(&rfb->framebuffer, tile->x, tile->y);
437 for (uint16_t y = tile->y; y < tile->y + tile->height; y++) {
438 for (uint16_t x = tile->x; x < tile->x + tile->width; x++) {
439 if (pixelmap_get_pixel(&rfb->framebuffer, x, y) != the_color)
[bde5c04]440 return EINVAL;
[38c822e]441 }
442 }
[a35b458]443
[38c822e]444 /* OK, encode it */
445 if (buf)
446 cpixel_encode(rfb, cpixel, buf, the_color);
[bde5c04]447 *size = cpixel->size;
448 return EOK;
[38c822e]449}
450
451static size_t rfb_rect_encode_trle(rfb_t *rfb, rfb_rectangle_t *rect, void *buf)
452{
453 cpixel_ctx_t cpixel;
454 cpixel_context_init(&cpixel, &rfb->pixel_format);
[a35b458]455
[38c822e]456 size_t size = 0;
457 for (uint16_t y = 0; y < rect->height; y += 16) {
458 for (uint16_t x = 0; x < rect->width; x += 16) {
459 rfb_rectangle_t tile = {
460 .x = x,
461 .y = y,
462 .width = (x + 16 <= rect->width ? 16 : rect->width - x),
463 .height = (y + 16 <= rect->height ? 16 : rect->height - y)
464 };
[a35b458]465
[38c822e]466 size += 1;
467 uint8_t *tile_enctype_ptr = buf;
468 if (buf)
469 buf += 1;
[a35b458]470
[38c822e]471 uint8_t tile_enctype = RFB_TILE_ENCODING_SOLID;
[bde5c04]472 size_t tile_size;
[b7fd2a0]473 errno_t rc = rfb_tile_encode_solid(rfb, &cpixel, &tile, buf,
[bde5c04]474 &tile_size);
475 if (rc != EOK) {
[38c822e]476 tile_size = rfb_tile_encode_raw(rfb, &cpixel, &tile, buf);
477 tile_enctype = RFB_TILE_ENCODING_RAW;
478 }
[a35b458]479
[38c822e]480 if (buf) {
481 *tile_enctype_ptr = tile_enctype;
482 buf += tile_size;
483 }
484 }
485 }
486 return size;
487}
488
[b7fd2a0]489static errno_t rfb_send_framebuffer_update(rfb_t *rfb, tcp_conn_t *conn,
[fab2746]490 bool incremental)
[bd0e6a1]491{
[870f78c]492 fibril_mutex_lock(&rfb->lock);
[bd0e6a1]493 if (!incremental || !rfb->damage_valid) {
494 rfb->damage_rect.x = 0;
495 rfb->damage_rect.y = 0;
496 rfb->damage_rect.width = rfb->width;
497 rfb->damage_rect.height = rfb->height;
498 }
[a35b458]499
[bd0e6a1]500 /* We send only single raw rectangle right now */
501 size_t buf_size = sizeof(rfb_framebuffer_update_t) +
502 sizeof(rfb_rectangle_t) * 1 +
[18b6a88]503 rfb_rect_encode_raw(rfb, &rfb->damage_rect, NULL);
[a35b458]504
[bd0e6a1]505 void *buf = malloc(buf_size);
[870f78c]506 if (buf == NULL) {
507 fibril_mutex_unlock(&rfb->lock);
[bd0e6a1]508 return ENOMEM;
[870f78c]509 }
[bd0e6a1]510 memset(buf, 0, buf_size);
[a35b458]511
[bd0e6a1]512 void *pos = buf;
513 rfb_framebuffer_update_t *fbu = buf;
514 fbu->message_type = RFB_SMSG_FRAMEBUFFER_UPDATE;
515 fbu->rect_count = 1;
516 rfb_framebuffer_update_to_be(fbu, fbu);
517 pos += sizeof(rfb_framebuffer_update_t);
[a35b458]518
[bd0e6a1]519 rfb_rectangle_t *rect = pos;
520 pos += sizeof(rfb_rectangle_t);
[a35b458]521
[38c822e]522 *rect = rfb->damage_rect;
[a35b458]523
[38c822e]524 if (rfb->supports_trle) {
525 rect->enctype = RFB_ENCODING_TRLE;
526 pos += rfb_rect_encode_trle(rfb, rect, pos);
[18b6a88]527 } else {
[38c822e]528 rect->enctype = RFB_ENCODING_RAW;
529 pos += rfb_rect_encode_raw(rfb, rect, pos);
530 }
531 rfb_rectangle_to_be(rect, rect);
[a35b458]532
[870f78c]533 rfb->damage_valid = false;
[a35b458]534
[870f78c]535 size_t send_palette_size = 0;
536 void *send_palette = NULL;
[a35b458]537
[2c9f6dd3]538 if (!rfb->pixel_format.true_color) {
[870f78c]539 send_palette = rfb_send_palette_message(rfb, &send_palette_size);
540 if (send_palette == NULL) {
541 free(buf);
542 fibril_mutex_unlock(&rfb->lock);
543 return ENOMEM;
544 }
545 }
[a35b458]546
[870f78c]547 fibril_mutex_unlock(&rfb->lock);
[a35b458]548
[870f78c]549 if (!rfb->pixel_format.true_color) {
[b7fd2a0]550 errno_t rc = tcp_conn_send(conn, send_palette, send_palette_size);
[2c9f6dd3]551 if (rc != EOK) {
552 free(buf);
553 return rc;
554 }
555 }
[a35b458]556
[b7fd2a0]557 errno_t rc = tcp_conn_send(conn, buf, buf_size);
[bd0e6a1]558 free(buf);
[a35b458]559
[bd0e6a1]560 return rc;
561}
562
[b7fd2a0]563static errno_t rfb_set_pixel_format(rfb_t *rfb, rfb_pixel_format_t *pixel_format)
[2c9f6dd3]564{
565 rfb->pixel_format = *pixel_format;
566 if (rfb->pixel_format.true_color) {
567 free(rfb->palette);
568 rfb->palette = NULL;
569 rfb->palette_used = 0;
[47b27b40]570 log_msg(LOG_DEFAULT, LVL_DEBUG,
571 "changed pixel format to %d-bit true color (%x<<%d, %x<<%d, %x<<%d)",
572 pixel_format->depth, pixel_format->r_max, pixel_format->r_shift,
573 pixel_format->g_max, pixel_format->g_shift, pixel_format->b_max,
574 pixel_format->b_shift);
[18b6a88]575 } else {
[2c9f6dd3]576 if (rfb->palette == NULL) {
577 rfb->palette = malloc(sizeof(pixel_t) * 256);
578 if (rfb->palette == NULL)
579 return ENOMEM;
580 memset(rfb->palette, 0, sizeof(pixel_t) * 256);
581 rfb->palette_used = 0;
582 }
[47b27b40]583 log_msg(LOG_DEFAULT, LVL_DEBUG, "changed pixel format to %d-bit palette",
584 pixel_format->depth);
[2c9f6dd3]585 }
586 return EOK;
587}
588
[fab2746]589static void rfb_socket_connection(rfb_t *rfb, tcp_conn_t *conn)
[bd0e6a1]590{
591 /* Version handshake */
[b7fd2a0]592 errno_t rc = tcp_conn_send(conn, "RFB 003.008\n", 12);
[47b27b40]593 if (rc != EOK) {
[dd8ab1c]594 log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server version: %s",
595 str_error(rc));
[bd0e6a1]596 return;
[47b27b40]597 }
[a35b458]598
[bd0e6a1]599 char client_version[12];
[fab2746]600 rc = recv_chars(conn, client_version, 12);
[47b27b40]601 if (rc != EOK) {
[dd8ab1c]602 log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client version: %s",
603 str_error(rc));
[bd0e6a1]604 return;
[47b27b40]605 }
[a35b458]606
[47b27b40]607 if (memcmp(client_version, "RFB 003.008\n", 12) != 0) {
608 log_msg(LOG_DEFAULT, LVL_WARN, "Client version is not RFB 3.8");
[bd0e6a1]609 return;
[47b27b40]610 }
[a35b458]611
[7c3fb9b]612 /*
613 * Security handshake
[bd0e6a1]614 * 1 security type supported, which is 1 - None
615 */
616 char sec_types[2];
617 sec_types[0] = 1; /* length */
618 sec_types[1] = RFB_SECURITY_NONE;
[fab2746]619 rc = tcp_conn_send(conn, sec_types, 2);
[47b27b40]620 if (rc != EOK) {
621 log_msg(LOG_DEFAULT, LVL_WARN,
[dd8ab1c]622 "Failed sending security handshake: %s", str_error(rc));
[bd0e6a1]623 return;
[47b27b40]624 }
[a35b458]625
[bd0e6a1]626 char selected_sec_type = 0;
[fab2746]627 rc = recv_char(conn, &selected_sec_type);
[47b27b40]628 if (rc != EOK) {
[dd8ab1c]629 log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving security type: %s",
630 str_error(rc));
[bd0e6a1]631 return;
[47b27b40]632 }
633 if (selected_sec_type != RFB_SECURITY_NONE) {
634 log_msg(LOG_DEFAULT, LVL_WARN,
635 "Client selected security type other than none");
[bd0e6a1]636 return;
[47b27b40]637 }
[bd0e6a1]638 uint32_t security_result = RFB_SECURITY_HANDSHAKE_OK;
[fab2746]639 rc = tcp_conn_send(conn, &security_result, sizeof(uint32_t));
[47b27b40]640 if (rc != EOK) {
[dd8ab1c]641 log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending security result: %s",
642 str_error(rc));
[bd0e6a1]643 return;
[47b27b40]644 }
[a35b458]645
[bd0e6a1]646 /* Client init */
647 char shared_flag;
[fab2746]648 rc = recv_char(conn, &shared_flag);
[47b27b40]649 if (rc != EOK) {
[dd8ab1c]650 log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client init: %s",
651 str_error(rc));
[bd0e6a1]652 return;
[47b27b40]653 }
[a35b458]654
[bd0e6a1]655 /* Server init */
656 fibril_mutex_lock(&rfb->lock);
657 size_t name_length = str_length(rfb->name);
658 size_t msg_length = sizeof(rfb_server_init_t) + name_length;
659 rfb_server_init_t *server_init = malloc(msg_length);
660 if (server_init == NULL) {
[47b27b40]661 log_msg(LOG_DEFAULT, LVL_WARN, "Cannot allocate memory for server init");
[bd0e6a1]662 fibril_mutex_unlock(&rfb->lock);
663 return;
664 }
665 server_init->width = rfb->width;
666 server_init->height = rfb->height;
[18b6a88]667 server_init->pixel_format = rfb->pixel_format;
[bd0e6a1]668 server_init->name_length = name_length;
669 rfb_server_init_to_be(server_init, server_init);
670 memcpy(server_init->name, rfb->name, name_length);
671 fibril_mutex_unlock(&rfb->lock);
[fab2746]672 rc = tcp_conn_send(conn, server_init, msg_length);
[47b27b40]673 if (rc != EOK) {
[dd8ab1c]674 log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server init: %s",
675 str_error(rc));
[bd0e6a1]676 return;
[47b27b40]677 }
[a35b458]678
[bd0e6a1]679 while (true) {
680 char message_type = 0;
[fab2746]681 rc = recv_char(conn, &message_type);
[47b27b40]682 if (rc != EOK) {
683 log_msg(LOG_DEFAULT, LVL_WARN,
[ad0d1f5]684 "Failed receiving client message type: %s",
685 str_error(rc));
[bd0e6a1]686 return;
[47b27b40]687 }
[a35b458]688
[bd0e6a1]689 rfb_set_pixel_format_t spf;
690 rfb_set_encodings_t se;
691 rfb_framebuffer_update_request_t fbur;
692 rfb_key_event_t ke;
693 rfb_pointer_event_t pe;
694 rfb_client_cut_text_t cct;
695 switch (message_type) {
696 case RFB_CMSG_SET_PIXEL_FORMAT:
[ad0d1f5]697 rc = recv_message(conn, message_type, &spf, sizeof(spf));
698 if (rc != EOK) {
699 log_msg(LOG_DEFAULT, LVL_WARN,
700 "Failed receiving client message: %s",
701 str_error(rc));
702 return;
703 }
[bd0e6a1]704 rfb_pixel_format_to_host(&spf.pixel_format, &spf.pixel_format);
[47b27b40]705 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received SetPixelFormat message");
[bd0e6a1]706 fibril_mutex_lock(&rfb->lock);
[2c9f6dd3]707 rc = rfb_set_pixel_format(rfb, &spf.pixel_format);
[bd0e6a1]708 fibril_mutex_unlock(&rfb->lock);
[2c9f6dd3]709 if (rc != EOK)
710 return;
[bd0e6a1]711 break;
712 case RFB_CMSG_SET_ENCODINGS:
[ad0d1f5]713 rc = recv_message(conn, message_type, &se, sizeof(se));
714 if (rc != EOK) {
715 log_msg(LOG_DEFAULT, LVL_WARN,
716 "Failed receiving client message: %s",
717 str_error(rc));
718 return;
719 }
[bd0e6a1]720 rfb_set_encodings_to_host(&se, &se);
[47b27b40]721 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received SetEncodings message");
[bd0e6a1]722 for (uint16_t i = 0; i < se.count; i++) {
723 int32_t encoding = 0;
[fab2746]724 rc = recv_chars(conn, (char *) &encoding, sizeof(int32_t));
[bd0e6a1]725 if (rc != EOK)
726 return;
727 encoding = uint32_t_be2host(encoding);
[47b27b40]728 if (encoding == RFB_ENCODING_TRLE) {
729 log_msg(LOG_DEFAULT, LVL_DEBUG,
730 "Client supports TRLE encoding");
[38c822e]731 rfb->supports_trle = true;
[47b27b40]732 }
[bd0e6a1]733 }
734 break;
735 case RFB_CMSG_FRAMEBUFFER_UPDATE_REQUEST:
[ad0d1f5]736 rc = recv_message(conn, message_type, &fbur, sizeof(fbur));
737 if (rc != EOK) {
738 log_msg(LOG_DEFAULT, LVL_WARN,
739 "Failed receiving client message: %s",
740 str_error(rc));
741 return;
742 }
[bd0e6a1]743 rfb_framebuffer_update_request_to_host(&fbur, &fbur);
[47b27b40]744 log_msg(LOG_DEFAULT, LVL_DEBUG2,
745 "Received FramebufferUpdateRequest message");
[fab2746]746 rfb_send_framebuffer_update(rfb, conn, fbur.incremental);
[bd0e6a1]747 break;
748 case RFB_CMSG_KEY_EVENT:
[ad0d1f5]749 rc = recv_message(conn, message_type, &ke, sizeof(ke));
750 if (rc != EOK) {
751 log_msg(LOG_DEFAULT, LVL_WARN,
752 "Failed receiving client message: %s",
753 str_error(rc));
754 return;
755 }
[bd0e6a1]756 rfb_key_event_to_host(&ke, &ke);
[47b27b40]757 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received KeyEvent message");
[bd0e6a1]758 break;
759 case RFB_CMSG_POINTER_EVENT:
[ad0d1f5]760 rc = recv_message(conn, message_type, &pe, sizeof(pe));
761 if (rc != EOK) {
762 log_msg(LOG_DEFAULT, LVL_WARN,
763 "Failed receiving client message: %s",
764 str_error(rc));
765 return;
766 }
[bd0e6a1]767 rfb_pointer_event_to_host(&pe, &pe);
[47b27b40]768 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received PointerEvent message");
[bd0e6a1]769 break;
770 case RFB_CMSG_CLIENT_CUT_TEXT:
[ad0d1f5]771 rc = recv_message(conn, message_type, &cct, sizeof(cct));
772 if (rc != EOK) {
773 log_msg(LOG_DEFAULT, LVL_WARN,
774 "Failed receiving client message: %s",
775 str_error(rc));
776 return;
777 }
[bd0e6a1]778 rfb_client_cut_text_to_host(&cct, &cct);
[47b27b40]779 log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received ClientCutText message");
[fab2746]780 recv_skip_chars(conn, cct.length);
[bd0e6a1]781 break;
782 default:
[47b27b40]783 log_msg(LOG_DEFAULT, LVL_WARN,
784 "Invalid client message type encountered");
[bd0e6a1]785 return;
786 }
787 }
788}
789
[b7fd2a0]790errno_t rfb_listen(rfb_t *rfb, uint16_t port)
[fab2746]791{
792 tcp_t *tcp = NULL;
793 tcp_listener_t *lst = NULL;
794 inet_ep_t ep;
[b7fd2a0]795 errno_t rc;
[a35b458]796
[d6ff08a0]797 rc = tcp_create(&tcp);
798 if (rc != EOK) {
799 log_msg(LOG_DEFAULT, LVL_ERROR, "Error initializing TCP.");
800 goto error;
801 }
[a35b458]802
[fab2746]803 inet_ep_init(&ep);
804 ep.port = port;
[a35b458]805
[fab2746]806 rc = tcp_listener_create(tcp, &ep, &listen_cb, rfb, &conn_cb, rfb,
807 &lst);
[bd0e6a1]808 if (rc != EOK) {
[d6ff08a0]809 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating listener.");
[fab2746]810 goto error;
[bd0e6a1]811 }
[a35b458]812
[fab2746]813 rfb->tcp = tcp;
814 rfb->lst = lst;
[a35b458]815
[bd0e6a1]816 return EOK;
[fab2746]817error:
818 tcp_listener_destroy(lst);
819 tcp_destroy(tcp);
820 return rc;
[bd0e6a1]821}
822
[fab2746]823static void rfb_new_conn(tcp_listener_t *lst, tcp_conn_t *conn)
[bd0e6a1]824{
[fab2746]825 rfb_t *rfb = (rfb_t *)tcp_listener_userptr(lst);
826 log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection accepted");
827
828 rbuf_out = 0;
829 rbuf_in = 0;
830
831 rfb_socket_connection(rfb, conn);
[bd0e6a1]832}
Note: See TracBrowser for help on using the repository browser.