Fix some issues
parent
ab9c7456e7
commit
0b0baae302
|
@ -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 {
|
||||||
|
|
71
server.c
71
server.c
|
@ -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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue