Fix some issues

tight-png
Andri Yngvason 2019-08-12 22:11:41 +00:00 committed by Andri Yngvason
parent ab9c7456e7
commit 0b0baae302
2 changed files with 57 additions and 22 deletions

View File

@ -13,18 +13,18 @@
int send_to_client(void *client, const void *payload, size_t size); int send_to_client(void *client, const void *payload, size_t size);
int receive_from_client(void *client, void *result, size_t size); int receive_from_client(void *client, void *result, size_t size);
enum rfb_security_type : uint8_t { enum rfb_security_type {
RFB_SECURITY_TYPE_INVALID = 0, RFB_SECURITY_TYPE_INVALID = 0,
RFB_SECURITY_TYPE_NONE = 1, RFB_SECURITY_TYPE_NONE = 1,
RFB_SECURITY_TYPE_VNC_AUTH = 2, RFB_SECURITY_TYPE_VNC_AUTH = 2,
}; };
enum rfb_security_handshake_result : uint32_t { enum rfb_security_handshake_result {
RFB_SECURITY_HANDSHAKE_OK = 0, RFB_SECURITY_HANDSHAKE_OK = 0,
RFB_SECURITY_HANDSHAKE_FAILED = 1, RFB_SECURITY_HANDSHAKE_FAILED = 1,
}; };
enum rfb_client_to_server_msg_type : uint8_t { enum rfb_client_to_server_msg_type {
RFB_CLIENT_TO_SERVER_SET_PIXEL_FORMAT = 0, RFB_CLIENT_TO_SERVER_SET_PIXEL_FORMAT = 0,
RFB_CLIENT_TO_SERVER_SET_ENCODINGS = 2, RFB_CLIENT_TO_SERVER_SET_ENCODINGS = 2,
RFB_CLIENT_TO_SERVER_FRAMEBUFFER_UPDATE_REQUEST = 3, RFB_CLIENT_TO_SERVER_FRAMEBUFFER_UPDATE_REQUEST = 3,
@ -35,7 +35,7 @@ enum rfb_client_to_server_msg_type : uint8_t {
struct rfb_security_types_msg { struct rfb_security_types_msg {
uint8_t n; uint8_t n;
enum rfb_security_type types[1]; uint8_t types[1];
} RFB_PACKED; } RFB_PACKED;
struct rfb_error_reason { struct rfb_error_reason {

View File

@ -21,7 +21,7 @@ enum vnc_client_state {
struct vnc_server; struct vnc_server;
struct vnc_client { struct vnc_client {
uv_stream_t stream_handle; uv_tcp_t stream_handle;
struct vnc_server *server; struct vnc_server *server;
enum vnc_client_state state; enum vnc_client_state state;
uint32_t pixfmt; uint32_t pixfmt;
@ -52,6 +52,19 @@ struct vnc_server {
struct vnc_display display; struct vnc_display display;
}; };
static const char* fourcc_to_string(uint32_t fourcc)
{
static char buffer[5];
buffer[0] = (fourcc >> 0) & 0xff;
buffer[1] = (fourcc >> 8) & 0xff;
buffer[2] = (fourcc >> 16) & 0xff;
buffer[3] = (fourcc >> 24) & 0xff;
buffer[4] = '\0';
return buffer;
}
static void on_write_req_done(uv_write_t *req, int status) static void on_write_req_done(uv_write_t *req, int status)
{ {
struct vnc_write_request *self = (struct vnc_write_request*)req; struct vnc_write_request *self = (struct vnc_write_request*)req;
@ -112,7 +125,7 @@ static int handle_unsupported_version(struct vnc_client *client)
reason->length = htonl(strlen(reason_string)); reason->length = htonl(strlen(reason_string));
(void)strcmp(reason->message, reason_string); (void)strcmp(reason->message, reason_string);
vnc__write(&client->stream_handle, buffer, vnc__write((uv_stream_t*)&client->stream_handle, buffer,
1 + sizeof(*reason) + strlen(reason_string), 1 + sizeof(*reason) + strlen(reason_string),
close_after_write); close_after_write);
@ -138,7 +151,7 @@ static int on_version_message(struct vnc_client *client)
}, },
}; };
vnc__write(&client->stream_handle, &security, sizeof(security), NULL); vnc__write((uv_stream_t*)&client->stream_handle, &security, sizeof(security), NULL);
client->state = VNC_CLIENT_STATE_WAITING_FOR_SECURITY; client->state = VNC_CLIENT_STATE_WAITING_FOR_SECURITY;
return 12; return 12;
@ -150,8 +163,7 @@ static int handle_invalid_security_type(struct vnc_client *client)
client->state = VNC_CLIENT_STATE_ERROR; client->state = VNC_CLIENT_STATE_ERROR;
enum rfb_security_handshake_result *result = uint8_t *result = (uint8_t*)buffer;
(enum rfb_security_handshake_result*)buffer;
struct rfb_error_reason *reason = struct rfb_error_reason *reason =
(struct rfb_error_reason*)(buffer + sizeof(*result)); (struct rfb_error_reason*)(buffer + sizeof(*result));
@ -162,7 +174,7 @@ static int handle_invalid_security_type(struct vnc_client *client)
reason->length = htonl(strlen(reason_string)); reason->length = htonl(strlen(reason_string));
(void)strcmp(reason->message, reason_string); (void)strcmp(reason->message, reason_string);
vnc__write(&client->stream_handle, buffer, vnc__write((uv_stream_t*)&client->stream_handle, buffer,
sizeof(*result) + sizeof(*reason) + strlen(reason_string), sizeof(*result) + sizeof(*reason) + strlen(reason_string),
close_after_write); close_after_write);
@ -182,7 +194,7 @@ static int on_security_message(struct vnc_client *client)
enum rfb_security_handshake_result result enum rfb_security_handshake_result result
= htonl(RFB_SECURITY_HANDSHAKE_OK); = htonl(RFB_SECURITY_HANDSHAKE_OK);
vnc__write(&client->stream_handle, &result, sizeof(result), NULL); vnc__write((uv_stream_t*)&client->stream_handle, &result, sizeof(result), NULL);
client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT; client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT;
return sizeof(type); return sizeof(type);
@ -276,7 +288,7 @@ static int max_values_to_depth(int r, int g, int b)
return -1; return -1;
} }
static uint32_t shift_values_to_fourcc(int r, int b, int g, int bpp) static uint32_t shift_values_to_fourcc(int r, int g, int b, int bpp)
{ {
#define RGBEQ(rv, gv, bv) (r == (rv) && g == (gv) && b == (bv)) #define RGBEQ(rv, gv, bv) (r == (rv) && g == (gv) && b == (bv))
if (bpp == 32 && RGBEQ(24, 16, 8)) return DRM_FORMAT_RGBX8888; if (bpp == 32 && RGBEQ(24, 16, 8)) return DRM_FORMAT_RGBX8888;
@ -319,7 +331,8 @@ int get_fourcc_depth(uint32_t fourcc)
case DRM_FORMAT_BGR233: case DRM_FORMAT_BGR233:
return 8; return 8;
default: default:
return (fourcc & 0xffff) - (('0' << 8) | '0'); return (((fourcc >> 24) & 0xff) - '0') +
(((fourcc >> 16) & 0xff) - '0') * 10;
} }
} }
@ -329,10 +342,9 @@ uint32_t rfb_pixfmt_to_fourcc(const struct rfb_pixel_format *fmt)
if (!fmt->true_colour_flag) if (!fmt->true_colour_flag)
return DRM_FORMAT_INVALID; return DRM_FORMAT_INVALID;
uint16_t red_max = ntohs(fmt->red_max);
uint16_t red_max = ntohl(fmt->red_max); uint16_t green_max = ntohs(fmt->green_max);
uint16_t green_max = ntohl(fmt->green_max); uint16_t blue_max = ntohs(fmt->blue_max);
uint16_t blue_max = ntohl(fmt->blue_max);
/* Note: The depth value given by the client is ignored */ /* Note: The depth value given by the client is ignored */
int depth = max_values_to_depth(red_max, green_max, blue_max); int depth = max_values_to_depth(red_max, green_max, blue_max);
@ -340,7 +352,7 @@ uint32_t rfb_pixfmt_to_fourcc(const struct rfb_pixel_format *fmt)
return DRM_FORMAT_INVALID; return DRM_FORMAT_INVALID;
uint32_t fourcc = uint32_t fourcc =
shift_values_to_fourcc(fmt->red_shift, fmt->green_max, shift_values_to_fourcc(fmt->red_shift, fmt->green_shift,
fmt->blue_shift, fmt->bits_per_pixel); fmt->blue_shift, fmt->bits_per_pixel);
if (fourcc == DRM_FORMAT_INVALID) if (fourcc == DRM_FORMAT_INVALID)
@ -370,11 +382,11 @@ static void send_server_init_message(struct vnc_client *client)
msg->width = htons(display->width), msg->width = htons(display->width),
msg->height = htons(display->height), msg->height = htons(display->height),
msg->name_length = htons(name_len), msg->name_length = htonl(name_len),
memcpy(msg->name_string, display->name, name_len); memcpy(msg->name_string, display->name, name_len);
rfb_pixfmt_from_fourcc(&msg->pixel_format, display->pixfmt); rfb_pixfmt_from_fourcc(&msg->pixel_format, display->pixfmt);
vnc__write(&client->stream_handle, msg, size, NULL); vnc__write((uv_stream_t*)&client->stream_handle, msg, size, NULL);
free(msg); free(msg);
} }
@ -412,6 +424,8 @@ static int on_client_set_pixel_format(struct vnc_client *client)
client->pixfmt = rfb_pixfmt_to_fourcc(fmt); client->pixfmt = rfb_pixfmt_to_fourcc(fmt);
printf("SetPixelFormat: %x\n", client->pixfmt);
return 4 + sizeof(struct rfb_pixel_format); return 4 + sizeof(struct rfb_pixel_format);
} }
@ -425,6 +439,7 @@ static int on_client_message(struct vnc_client *client)
switch (type) { switch (type) {
case RFB_CLIENT_TO_SERVER_SET_PIXEL_FORMAT: case RFB_CLIENT_TO_SERVER_SET_PIXEL_FORMAT:
return on_client_set_pixel_format(client);
case RFB_CLIENT_TO_SERVER_SET_ENCODINGS: case RFB_CLIENT_TO_SERVER_SET_ENCODINGS:
case RFB_CLIENT_TO_SERVER_FRAMEBUFFER_UPDATE_REQUEST: case RFB_CLIENT_TO_SERVER_FRAMEBUFFER_UPDATE_REQUEST:
case RFB_CLIENT_TO_SERVER_KEY_EVENT: case RFB_CLIENT_TO_SERVER_KEY_EVENT:
@ -439,6 +454,7 @@ static int on_client_message(struct vnc_client *client)
static int try_read_client_message(struct vnc_client *client) static int try_read_client_message(struct vnc_client *client)
{ {
printf("Client state: %d\n", client->state);
switch (client->state) { switch (client->state) {
case VNC_CLIENT_STATE_ERROR: case VNC_CLIENT_STATE_ERROR:
uv_close((uv_handle_t*)&client->stream_handle, cleanup_client); uv_close((uv_handle_t*)&client->stream_handle, cleanup_client);
@ -467,6 +483,9 @@ static void on_client_read(uv_stream_t *stream, ssize_t n_read,
return; return;
} }
if (n_read < 0)
return;
struct vnc_client *client = (struct vnc_client*)stream; struct vnc_client *client = (struct vnc_client*)stream;
assert(client->buffer_index == 0); assert(client->buffer_index == 0);
@ -489,7 +508,7 @@ static void on_client_read(uv_stream_t *stream, ssize_t n_read,
client->buffer_index += rc; client->buffer_index += rc;
} }
assert(client->buffer_index < client->buffer_len); assert(client->buffer_index <= client->buffer_len);
memmove(client->msg_buffer, client->msg_buffer + client->buffer_index, memmove(client->msg_buffer, client->msg_buffer + client->buffer_index,
client->buffer_index); client->buffer_index);
@ -507,7 +526,10 @@ static void on_connection(uv_stream_t *server_stream, int status)
client->server = server; client->server = server;
uv_accept((uv_stream_t*)&server->tcp_handle, &client->stream_handle); uv_tcp_init(uv_default_loop(), &client->stream_handle);
uv_accept((uv_stream_t*)&server->tcp_handle,
(uv_stream_t*)&client->stream_handle);
uv_read_start((uv_stream_t*)&client->stream_handle, uv_read_start((uv_stream_t*)&client->stream_handle,
allocate_read_buffer, on_client_read); allocate_read_buffer, on_client_read);
@ -543,3 +565,16 @@ failure:
uv_unref((uv_handle_t*)&self->tcp_handle); uv_unref((uv_handle_t*)&self->tcp_handle);
return -1; return -1;
} }
int main()
{
struct vnc_server server = { 0 };
server.display.pixfmt = DRM_FORMAT_RGBX8888;
server.display.width = 1024;
server.display.height = 768;
server.display.name = "Silly VNC";
vnc_server_init(&server, "127.0.0.1", 5900);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}