Fix read buffer and drop older outgoing frames

tight-png
Andri Yngvason 2019-12-23 09:33:29 +00:00
parent 80b1f3cb4c
commit 4ebf4623cb
3 changed files with 43 additions and 6 deletions

View File

@ -25,9 +25,13 @@ struct vnc_write_request {
uv_write_t request; uv_write_t request;
uv_write_cb on_done; uv_write_cb on_done;
uv_buf_t buffer; uv_buf_t buffer;
void* userdata;
}; };
int vnc__write(uv_stream_t* stream, const void* payload, size_t size, int vnc__write(uv_stream_t* stream, const void* payload, size_t size,
uv_write_cb on_done); uv_write_cb on_done);
int vnc__write2(uv_stream_t* stream, const void* payload, size_t size,
uv_write_cb on_done, void* userdata);
int rfb_pixfmt_from_fourcc(struct rfb_pixel_format* dst, uint32_t src); int rfb_pixfmt_from_fourcc(struct rfb_pixel_format* dst, uint32_t src);

View File

@ -45,6 +45,7 @@
#define MSG_BUFFER_SIZE 4096 #define MSG_BUFFER_SIZE 4096
#define MAX_ENCODINGS 32 #define MAX_ENCODINGS 32
#define MAX_OUTGOING_FRAMES 4
#define EXPORT __attribute__((visibility("default"))) #define EXPORT __attribute__((visibility("default")))
@ -75,6 +76,7 @@ struct nvnc_client {
LIST_ENTRY(nvnc_client) link; LIST_ENTRY(nvnc_client) link;
struct pixman_region16 damage; struct pixman_region16 damage;
int n_pending_requests; int n_pending_requests;
int n_outgoing_frames;
bool is_updating; bool is_updating;
nvnc_client_fn cleanup_fn; nvnc_client_fn cleanup_fn;
z_stream z_stream; z_stream z_stream;
@ -526,6 +528,10 @@ static int on_client_set_encodings(struct nvnc_client* client)
int n_encodings = MIN(MAX_ENCODINGS, ntohs(msg->n_encodings)); int n_encodings = MIN(MAX_ENCODINGS, ntohs(msg->n_encodings));
int n = 0; int n = 0;
if (client->buffer_len - client->buffer_index <
sizeof(*msg) + n_encodings * 4)
return 0;
for (int i = 0; i < n_encodings; ++i) { for (int i = 0; i < n_encodings; ++i) {
enum rfb_encodings encoding = htonl(msg->encodings[i]); enum rfb_encodings encoding = htonl(msg->encodings[i]);
@ -574,6 +580,9 @@ static int on_client_fb_update_request(struct nvnc_client* client)
(struct rfb_client_fb_update_req_msg*)(client->msg_buffer + (struct rfb_client_fb_update_req_msg*)(client->msg_buffer +
client->buffer_index); client->buffer_index);
if (client->buffer_len - client->buffer_index < sizeof(*msg))
return 0;
int incremental = msg->incremental; int incremental = msg->incremental;
int x = ntohs(msg->x); int x = ntohs(msg->x);
int y = ntohs(msg->y); int y = ntohs(msg->y);
@ -606,6 +615,9 @@ static int on_client_key_event(struct nvnc_client* client)
(struct rfb_client_key_event_msg*)(client->msg_buffer + (struct rfb_client_key_event_msg*)(client->msg_buffer +
client->buffer_index); client->buffer_index);
if (client->buffer_len - client->buffer_index < sizeof(*msg))
return 0;
int down_flag = msg->down_flag; int down_flag = msg->down_flag;
uint32_t keysym = ntohl(msg->key); uint32_t keysym = ntohl(msg->key);
@ -624,6 +636,9 @@ static int on_client_pointer_event(struct nvnc_client* client)
(struct rfb_client_pointer_event_msg*)(client->msg_buffer + (struct rfb_client_pointer_event_msg*)(client->msg_buffer +
client->buffer_index); client->buffer_index);
if (client->buffer_len - client->buffer_index < sizeof(*msg))
return 0;
int button_mask = msg->button_mask; int button_mask = msg->button_mask;
uint16_t x = ntohs(msg->x); uint16_t x = ntohs(msg->x);
uint16_t y = ntohs(msg->y); uint16_t y = ntohs(msg->y);
@ -641,6 +656,9 @@ static int on_client_cut_text(struct nvnc_client* client)
(struct rfb_client_cut_text_msg*)(client->msg_buffer + (struct rfb_client_cut_text_msg*)(client->msg_buffer +
client->buffer_index); client->buffer_index);
if (client->buffer_len - client->buffer_index < sizeof(*msg))
return 0;
uint32_t length = ntohl(msg->length); uint32_t length = ntohl(msg->length);
// TODO // TODO
@ -848,9 +866,11 @@ void nvnc_close(struct nvnc* self)
free(self); free(self);
} }
static void free_write_buffer(uv_write_t* req, int status) static void on_write_frame_done(uv_write_t* req, int status)
{ {
struct vnc_write_request* rq = (struct vnc_write_request*)req; struct vnc_write_request* rq = (struct vnc_write_request*)req;
struct nvnc_client* client = rq->userdata;
client->n_outgoing_frames--;
free(rq->buffer.base); free(rq->buffer.base);
} }
@ -901,9 +921,12 @@ void on_client_update_fb_done(uv_work_t* work, int status)
struct nvnc* server = client->server; struct nvnc* server = client->server;
struct vec* frame = &update->frame; struct vec* frame = &update->frame;
if (!uv_is_closing((uv_handle_t*)&client->stream_handle)) if (client->n_outgoing_frames <= MAX_OUTGOING_FRAMES &&
vnc__write((uv_stream_t*)&client->stream_handle, frame->data, !uv_is_closing((uv_handle_t*)&client->stream_handle))
frame->len, free_write_buffer); vnc__write2((uv_stream_t*)&client->stream_handle, frame->data,
frame->len, on_write_frame_done, client);
else
client->n_outgoing_frames--;
client->is_updating = false; client->is_updating = false;
client->n_pending_requests--; client->n_pending_requests--;
@ -938,6 +961,8 @@ int schedule_client_update_fb(struct nvnc_client* client)
client_ref(client); client_ref(client);
nvnc_fb_ref(fb); nvnc_fb_ref(fb);
client->n_outgoing_frames++;
rc = uv_queue_work(uv_default_loop(), &work->work, do_client_update_fb, rc = uv_queue_work(uv_default_loop(), &work->work, do_client_update_fb,
on_client_update_fb_done); on_client_update_fb_done);
if (rc < 0) if (rc < 0)
@ -946,6 +971,7 @@ int schedule_client_update_fb(struct nvnc_client* client)
return 0; return 0;
queue_failure: queue_failure:
client->n_outgoing_frames--;
nvnc_fb_unref(fb); nvnc_fb_unref(fb);
client_unref(client); client_unref(client);
vec_destroy(&work->frame); vec_destroy(&work->frame);

View File

@ -28,8 +28,8 @@ static void on_write_req_done(uv_write_t* req, int status)
free(self); free(self);
} }
int vnc__write(uv_stream_t* stream, const void* payload, size_t size, int vnc__write2(uv_stream_t* stream, const void* payload, size_t size,
uv_write_cb on_done) uv_write_cb on_done, void* userdata)
{ {
struct vnc_write_request* req = calloc(1, sizeof(*req)); struct vnc_write_request* req = calloc(1, sizeof(*req));
if (!req) if (!req)
@ -38,7 +38,14 @@ int vnc__write(uv_stream_t* stream, const void* payload, size_t size,
req->buffer.base = (char*)payload; req->buffer.base = (char*)payload;
req->buffer.len = size; req->buffer.len = size;
req->on_done = on_done; req->on_done = on_done;
req->userdata = userdata;
return uv_write(&req->request, stream, &req->buffer, 1, return uv_write(&req->request, stream, &req->buffer, 1,
on_write_req_done); on_write_req_done);
} }
int vnc__write(uv_stream_t* stream, const void* payload, size_t size,
uv_write_cb on_done)
{
return vnc__write2(stream, payload, size, on_done, NULL);
}