parent
783807c0b9
commit
81a8ba9d0e
|
@ -34,6 +34,7 @@
|
||||||
#define MAX_ENCODINGS 32
|
#define MAX_ENCODINGS 32
|
||||||
#define MAX_OUTGOING_FRAMES 4
|
#define MAX_OUTGOING_FRAMES 4
|
||||||
#define MSG_BUFFER_SIZE 4096
|
#define MSG_BUFFER_SIZE 4096
|
||||||
|
#define MAX_CUT_TEXT_SIZE 10000000
|
||||||
|
|
||||||
enum nvnc_client_state {
|
enum nvnc_client_state {
|
||||||
VNC_CLIENT_STATE_ERROR = -1,
|
VNC_CLIENT_STATE_ERROR = -1,
|
||||||
|
@ -58,6 +59,12 @@ struct nvnc_common {
|
||||||
void* userdata;
|
void* userdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cut_text {
|
||||||
|
char* buffer;
|
||||||
|
size_t length;
|
||||||
|
size_t index;
|
||||||
|
};
|
||||||
|
|
||||||
struct nvnc_client {
|
struct nvnc_client {
|
||||||
struct nvnc_common common;
|
struct nvnc_common common;
|
||||||
int ref;
|
int ref;
|
||||||
|
@ -80,6 +87,7 @@ struct nvnc_client {
|
||||||
uint8_t msg_buffer[MSG_BUFFER_SIZE];
|
uint8_t msg_buffer[MSG_BUFFER_SIZE];
|
||||||
uint32_t known_width;
|
uint32_t known_width;
|
||||||
uint32_t known_height;
|
uint32_t known_height;
|
||||||
|
struct cut_text cut_text;
|
||||||
};
|
};
|
||||||
|
|
||||||
LIST_HEAD(nvnc_client_list, nvnc_client);
|
LIST_HEAD(nvnc_client_list, nvnc_client);
|
||||||
|
|
84
src/server.c
84
src/server.c
|
@ -92,6 +92,7 @@ static void client_close(struct nvnc_client* client)
|
||||||
tight_encoder_destroy(&client->tight_encoder);
|
tight_encoder_destroy(&client->tight_encoder);
|
||||||
deflateEnd(&client->z_stream);
|
deflateEnd(&client->z_stream);
|
||||||
pixman_region_fini(&client->damage);
|
pixman_region_fini(&client->damage);
|
||||||
|
free(client->cut_text.buffer);
|
||||||
free(client);
|
free(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,31 +603,95 @@ void nvnc_send_cut_text(struct nvnc* server, const char* text, uint32_t len)
|
||||||
static int on_client_cut_text(struct nvnc_client* client)
|
static int on_client_cut_text(struct nvnc_client* client)
|
||||||
{
|
{
|
||||||
struct nvnc* server = client->server;
|
struct nvnc* server = client->server;
|
||||||
|
nvnc_cut_text_fn fn = server->cut_text_fn;
|
||||||
struct rfb_cut_text_msg* msg =
|
struct rfb_cut_text_msg* msg =
|
||||||
(struct rfb_cut_text_msg*)(client->msg_buffer +
|
(struct rfb_cut_text_msg*)(client->msg_buffer +
|
||||||
client->buffer_index);
|
client->buffer_index);
|
||||||
|
|
||||||
if (client->buffer_len - client->buffer_index < sizeof(*msg))
|
size_t left_to_process = client->buffer_len - client->buffer_index;
|
||||||
|
|
||||||
|
if (left_to_process < sizeof(*msg))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t length = ntohl(msg->length);
|
uint32_t length = ntohl(msg->length);
|
||||||
|
uint32_t max_length = MAX_CUT_TEXT_SIZE;
|
||||||
|
|
||||||
/* Messages greater than this size are unsupported */
|
/* Messages greater than this size are unsupported */
|
||||||
if (length > MSG_BUFFER_SIZE - sizeof(*msg)) {
|
if (length > max_length) {
|
||||||
|
log_error("Copied text length (%d) is greater than max supported length (%d)\n",
|
||||||
|
length, max_length);
|
||||||
stream_close(client->net_stream);
|
stream_close(client->net_stream);
|
||||||
client_unref(client);
|
client_unref(client);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->buffer_len - client->buffer_index < sizeof(*msg) + length)
|
size_t msg_size = sizeof(*msg) + length;
|
||||||
return 0;
|
|
||||||
|
|
||||||
nvnc_cut_text_fn fn = server->cut_text_fn;
|
if (msg_size <= left_to_process) {
|
||||||
if (fn) {
|
if (fn)
|
||||||
fn(server, msg->text, length);
|
fn(server, msg->text, length);
|
||||||
|
|
||||||
|
return msg_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sizeof(*msg) + length;
|
assert(!client->cut_text.buffer);
|
||||||
|
|
||||||
|
client->cut_text.buffer = malloc(length);
|
||||||
|
if (!client->cut_text.buffer) {
|
||||||
|
log_error("OOM: %m\n");
|
||||||
|
stream_close(client->net_stream);
|
||||||
|
client_unref(client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t partial_size = left_to_process - sizeof(*msg);
|
||||||
|
|
||||||
|
memcpy(client->cut_text.buffer, msg->text, partial_size);
|
||||||
|
|
||||||
|
client->cut_text.length = length;
|
||||||
|
client->cut_text.index = partial_size;
|
||||||
|
|
||||||
|
return left_to_process;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_big_cut_text(struct nvnc_client* client)
|
||||||
|
{
|
||||||
|
struct nvnc* server = client->server;
|
||||||
|
nvnc_cut_text_fn fn = server->cut_text_fn;
|
||||||
|
|
||||||
|
assert(client->cut_text.length > client->cut_text.index);
|
||||||
|
|
||||||
|
void* start = client->cut_text.buffer + client->cut_text.index;
|
||||||
|
size_t space = client->cut_text.length - client->cut_text.index;
|
||||||
|
|
||||||
|
space = MIN(space, MSG_BUFFER_SIZE);
|
||||||
|
|
||||||
|
ssize_t n_read = stream_read(client->net_stream, start, space);
|
||||||
|
|
||||||
|
if (n_read == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (n_read < 0) {
|
||||||
|
if (errno != EAGAIN) {
|
||||||
|
log_debug("Client connection error: %p (ref %d)\n",
|
||||||
|
client, client->ref);
|
||||||
|
stream_close(client->net_stream);
|
||||||
|
client_unref(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->cut_text.index += n_read;
|
||||||
|
|
||||||
|
if (client->cut_text.index != client->cut_text.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fn)
|
||||||
|
fn(server, client->cut_text.buffer, client->cut_text.length);
|
||||||
|
|
||||||
|
free(client->cut_text.buffer);
|
||||||
|
client->cut_text.buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_client_message(struct nvnc_client* client)
|
static int on_client_message(struct nvnc_client* client)
|
||||||
|
@ -699,6 +764,11 @@ static void on_client_event(struct stream* stream, enum stream_event event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client->cut_text.buffer) {
|
||||||
|
process_big_cut_text(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(client->buffer_index == 0);
|
assert(client->buffer_index == 0);
|
||||||
|
|
||||||
void* start = client->msg_buffer + client->buffer_len;
|
void* start = client->msg_buffer + client->buffer_len;
|
||||||
|
|
Loading…
Reference in New Issue