source: mainline/uspace/srv/hid/rfb/rfb.c@ 2d78d88

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2d78d88 was 7c3fb9b, checked in by Jiri Svoboda <jiri@…>, 8 years ago

Fix block comment formatting (ccheck).

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