Use client specific pointers in callbacks

tight-png
Andri Yngvason 2019-08-31 23:16:55 +00:00
parent 0a1d47f5f9
commit ed5dadd203
8 changed files with 122 additions and 52 deletions

3
.gitignore vendored
View File

@ -6,3 +6,6 @@ vgcore.*
perf.data perf.data
perf.data.old perf.data.old
zrle-bench zrle-bench
*.so*
examples/draw
examples/png-server

View File

@ -13,10 +13,10 @@ libneatvnc.so.0.0: src/server.o src/util.o src/vec.o src/zrle.o src/pngfb.o \
$(CC) -fPIC -shared $^ $(LDFLAGS) -o $@ $(CC) -fPIC -shared $^ $(LDFLAGS) -o $@
libneatvnc.so.0: libneatvnc.so.0.0 libneatvnc.so.0: libneatvnc.so.0.0
ln -s $^ $@ ln -sf $^ $@
libneatvnc.so: libneatvnc.so.0 libneatvnc.so: libneatvnc.so.0
ln -s $^ $@ ln -sf $^ $@
zrle-bench: bench/zrle-bench.o src/server.o src/util.o src/vec.o src/zrle.o \ zrle-bench: bench/zrle-bench.o src/server.o src/util.o src/vec.o src/zrle.o \
src/pngfb.o src/miniz.o src/pngfb.o src/miniz.o
@ -25,6 +25,9 @@ zrle-bench: bench/zrle-bench.o src/server.o src/util.o src/vec.o src/zrle.o \
examples/png-server: examples/png-server.o src/pngfb.o libneatvnc.so examples/png-server: examples/png-server.o src/pngfb.o libneatvnc.so
$(CC) $^ $(LDFLAGS) -L. -lneatvnc -Wl,-rpath=$(shell pwd) -o $@ $(CC) $^ $(LDFLAGS) -L. -lneatvnc -Wl,-rpath=$(shell pwd) -o $@
examples/draw: examples/draw.o libneatvnc.so
$(CC) $^ $(LDFLAGS) -L. -lneatvnc -Wl,-rpath=$(shell pwd) -o $@
src/%.o: src/%.c src/%.o: src/%.c
$(CC) -c $(CFLAGS) $< -o $@ -MMD -MP -MF $@.deps $(CC) -c $(CFLAGS) $< -o $@ -MMD -MP -MF $@.deps

View File

@ -12,29 +12,35 @@ struct draw {
struct nvnc_fb fb; struct nvnc_fb fb;
}; };
void on_fb_req(struct nvnc *nvnc, bool incremental, uint16_t x, uint16_t y, void on_fb_req(struct nvnc_client *client, bool incremental, uint16_t x, uint16_t y,
uint16_t width, uint16_t height) uint16_t width, uint16_t height)
{ {
if (incremental) if (incremental)
return; return;
struct draw *draw = nvnc_get_userdata(nvnc); struct nvnc* server = nvnc_get_server(client);
assert(server);
struct draw *draw = nvnc_get_userdata(server);
assert(draw); assert(draw);
struct pixman_region16 region; struct pixman_region16 region;
pixman_region_init_rect(&region, 0, 0, draw->fb.width, pixman_region_init_rect(&region, 0, 0, draw->fb.width,
draw->fb.height); draw->fb.height);
nvnc_update_fb(nvnc, &draw->fb, &region); nvnc_update_fb(server, &draw->fb, &region);
pixman_region_fini(&region); pixman_region_fini(&region);
} }
void on_pointer_event(struct nvnc *nvnc, uint16_t x, uint16_t y, void on_pointer_event(struct nvnc_client *client, uint16_t x, uint16_t y,
enum nvnc_button_mask buttons) enum nvnc_button_mask buttons)
{ {
if (!(buttons & NVNC_BUTTON_LEFT)) if (!(buttons & NVNC_BUTTON_LEFT))
return; return;
struct draw *draw = nvnc_get_userdata(nvnc); struct nvnc *server = nvnc_get_server(client);
assert(server);
struct draw *draw = nvnc_get_userdata(server);
assert(draw); assert(draw);
uint32_t *image = draw->fb.addr; uint32_t *image = draw->fb.addr;
@ -45,7 +51,7 @@ void on_pointer_event(struct nvnc *nvnc, uint16_t x, uint16_t y,
pixman_region_init_rect(&region, 0, 0, draw->fb.width, pixman_region_init_rect(&region, 0, 0, draw->fb.width,
draw->fb.height); draw->fb.height);
// pixman_region_init_rect(&region, x, y, 1, 1); // pixman_region_init_rect(&region, x, y, 1, 1);
nvnc_update_fb(nvnc, &draw->fb, &region); nvnc_update_fb(server, &draw->fb, &region);
pixman_region_fini(&region); pixman_region_fini(&region);
} }

View File

@ -7,18 +7,21 @@
int read_png_file(struct nvnc_fb* fb, const char *filename); int read_png_file(struct nvnc_fb* fb, const char *filename);
void on_fb_req(struct nvnc *nvnc, bool incremental, uint16_t x, uint16_t y, void on_fb_req(struct nvnc_client *client, bool incremental,
uint16_t width, uint16_t height) uint16_t x, uint16_t y, uint16_t width, uint16_t height)
{ {
if (incremental) if (incremental)
return; return;
struct nvnc_fb *fb = nvnc_get_userdata(nvnc); struct nvnc *server = nvnc_get_server(client);
assert(server);
struct nvnc_fb *fb = nvnc_get_userdata(server);
assert(fb); assert(fb);
struct pixman_region16 region; struct pixman_region16 region;
pixman_region_init_rect(&region, 0, 0, fb->width, fb->height); pixman_region_init_rect(&region, 0, 0, fb->width, fb->height);
nvnc_update_fb(nvnc, fb, &region); nvnc_update_fb(server, fb, &region);
pixman_region_fini(&region); pixman_region_fini(&region);
} }

View File

@ -4,6 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
struct nvnc; struct nvnc;
struct nvnc_client;
struct pixman_region16; struct pixman_region16;
enum nvnc_button_mask { enum nvnc_button_mask {
@ -23,18 +24,20 @@ struct nvnc_fb {
uint64_t fourcc_modifier; uint64_t fourcc_modifier;
}; };
typedef void (*nvnc_key_fn)(struct nvnc*, uint32_t keysym, bool is_pressed); typedef void (*nvnc_key_fn)(struct nvnc_client*, uint32_t keysym, bool is_pressed);
typedef void (*nvnc_pointer_fn)(struct nvnc*, uint16_t x, uint16_t y, typedef void (*nvnc_pointer_fn)(struct nvnc_client*, uint16_t x, uint16_t y,
enum nvnc_button_mask); enum nvnc_button_mask);
typedef void (*nvnc_fb_req_fn)(struct nvnc*, bool is_incremental, typedef void (*nvnc_fb_req_fn)(struct nvnc_client*, bool is_incremental,
uint16_t x, uint16_t y, uint16_t x, uint16_t y,
uint16_t width, uint16_t height); uint16_t width, uint16_t height);
struct nvnc *nvnc_open(const char *addr, uint16_t port); struct nvnc *nvnc_open(const char *addr, uint16_t port);
void nvnc_close(struct nvnc *self); void nvnc_close(struct nvnc *self);
void nvnc_set_userdata(struct nvnc *self, void* userdata); void nvnc_set_userdata(void *self, void* userdata);
void* nvnc_get_userdata(const struct nvnc *self); void* nvnc_get_userdata(const void *self);
struct nvnc *nvnc_get_server(const struct nvnc_client *client);
void nvnc_set_dimensions(struct nvnc *self, uint16_t width, uint16_t height, void nvnc_set_dimensions(struct nvnc *self, uint16_t width, uint16_t height,
uint32_t fourcc_format); uint32_t fourcc_format);
@ -45,5 +48,10 @@ void nvnc_set_key_fn(struct nvnc *self, nvnc_key_fn);
void nvnc_set_pointer_fn(struct nvnc *self, nvnc_pointer_fn); void nvnc_set_pointer_fn(struct nvnc *self, nvnc_pointer_fn);
void nvnc_set_fb_req_fn(struct nvnc *self, nvnc_fb_req_fn); void nvnc_set_fb_req_fn(struct nvnc *self, nvnc_fb_req_fn);
/*
* Send an updated framebuffer to all clients with pending update requests.
*
* Only the region specified by the region argument is updated.
*/
int nvnc_update_fb(struct nvnc *self, const struct nvnc_fb* fb, int nvnc_update_fb(struct nvnc *self, const struct nvnc_fb* fb,
const struct pixman_region16* region); const struct pixman_region16* region);

27
inc/type-macros.h 100644
View File

@ -0,0 +1,27 @@
/* Copyright (c) 2014-2016, Marel
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef TYPE_MACROS_H_
#define TYPE_MACROS_H_
#include <stddef.h>
#define container_of(ptr, type, member) \
({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) ); \
})
#endif /* TYPE_MACROS_H_ */

View File

@ -2,6 +2,7 @@
#include "util.h" #include "util.h"
#include "zrle.h" #include "zrle.h"
#include "vec.h" #include "vec.h"
#include "type-macros.h"
#include "neatvnc.h" #include "neatvnc.h"
#include <stdlib.h> #include <stdlib.h>
@ -29,7 +30,7 @@ enum vnc_encodings {
VNC_ENCODING_DESKTOPSIZE = 1 << 7, VNC_ENCODING_DESKTOPSIZE = 1 << 7,
}; };
enum vnc_client_state { enum nvnc_client_state {
VNC_CLIENT_STATE_ERROR = -1, VNC_CLIENT_STATE_ERROR = -1,
VNC_CLIENT_STATE_WAITING_FOR_VERSION = 0, VNC_CLIENT_STATE_WAITING_FOR_VERSION = 0,
VNC_CLIENT_STATE_WAITING_FOR_SECURITY, VNC_CLIENT_STATE_WAITING_FOR_SECURITY,
@ -39,21 +40,26 @@ enum vnc_client_state {
struct nvnc; struct nvnc;
struct vnc_client { struct nvnc_common {
void* userdata;
};
struct nvnc_client {
struct nvnc_common common;
uv_tcp_t stream_handle; uv_tcp_t stream_handle;
struct nvnc *server; struct nvnc *server;
enum vnc_client_state state; enum nvnc_client_state state;
uint32_t fourcc; uint32_t fourcc;
struct rfb_pixel_format pixfmt; struct rfb_pixel_format pixfmt;
enum vnc_encodings encodings; enum vnc_encodings encodings;
LIST_ENTRY(vnc_client) link; LIST_ENTRY(nvnc_client) link;
struct pixman_region16 requested_region; struct pixman_region16 requested_region;
size_t buffer_index; size_t buffer_index;
size_t buffer_len; size_t buffer_len;
uint8_t msg_buffer[MSG_BUFFER_SIZE]; uint8_t msg_buffer[MSG_BUFFER_SIZE];
}; };
LIST_HEAD(vnc_client_list, vnc_client); LIST_HEAD(nvnc_client_list, nvnc_client);
struct vnc_display { struct vnc_display {
uint16_t width; uint16_t width;
@ -63,8 +69,9 @@ struct vnc_display {
}; };
struct nvnc { struct nvnc {
struct nvnc_common common;
uv_tcp_t tcp_handle; uv_tcp_t tcp_handle;
struct vnc_client_list clients; struct nvnc_client_list clients;
struct vnc_display display; struct vnc_display display;
void *userdata; void *userdata;
nvnc_key_fn key_fn; nvnc_key_fn key_fn;
@ -96,7 +103,9 @@ static void allocate_read_buffer(uv_handle_t *handle, size_t suggested_size,
static void cleanup_client(uv_handle_t* handle) static void cleanup_client(uv_handle_t* handle)
{ {
struct vnc_client *client = (struct vnc_client*)handle; struct nvnc_client *client =
container_of((uv_tcp_t*)handle, struct nvnc_client,
stream_handle);
LIST_REMOVE(client, link); LIST_REMOVE(client, link);
pixman_region_fini(&client->requested_region); pixman_region_fini(&client->requested_region);
@ -108,7 +117,7 @@ static void close_after_write(uv_write_t *req, int status)
uv_close((uv_handle_t*)req->handle, cleanup_client); uv_close((uv_handle_t*)req->handle, cleanup_client);
} }
static int handle_unsupported_version(struct vnc_client *client) static int handle_unsupported_version(struct nvnc_client *client)
{ {
char buffer[256]; char buffer[256];
@ -130,7 +139,7 @@ static int handle_unsupported_version(struct vnc_client *client)
return 0; return 0;
} }
static int on_version_message(struct vnc_client *client) static int on_version_message(struct nvnc_client *client)
{ {
if (client->buffer_len - client->buffer_index < 12) if (client->buffer_len - client->buffer_index < 12)
return 0; return 0;
@ -155,7 +164,7 @@ static int on_version_message(struct vnc_client *client)
return 12; return 12;
} }
static int handle_invalid_security_type(struct vnc_client *client) static int handle_invalid_security_type(struct nvnc_client *client)
{ {
char buffer[256]; char buffer[256];
@ -179,7 +188,7 @@ static int handle_invalid_security_type(struct vnc_client *client)
return 0; return 0;
} }
static int on_security_message(struct vnc_client *client) static int on_security_message(struct nvnc_client *client)
{ {
if (client->buffer_len - client->buffer_index < 1) if (client->buffer_len - client->buffer_index < 1)
return 0; return 0;
@ -198,7 +207,7 @@ static int on_security_message(struct vnc_client *client)
return sizeof(type); return sizeof(type);
} }
static void disconnect_all_other_clients(struct vnc_client *client) static void disconnect_all_other_clients(struct nvnc_client *client)
{ {
// TODO // TODO
} }
@ -360,7 +369,7 @@ uint32_t rfb_pixfmt_to_fourcc(const struct rfb_pixel_format *fmt)
return fourcc; return fourcc;
} }
static void send_server_init_message(struct vnc_client *client) static void send_server_init_message(struct nvnc_client *client)
{ {
struct nvnc *server = client->server; struct nvnc *server = client->server;
struct vnc_display *display = &server->display; struct vnc_display *display = &server->display;
@ -389,7 +398,7 @@ static void send_server_init_message(struct vnc_client *client)
free(msg); free(msg);
} }
static int on_init_message(struct vnc_client *client) static int on_init_message(struct nvnc_client *client)
{ {
if (client->buffer_len - client->buffer_index < 1) if (client->buffer_len - client->buffer_index < 1)
return 0; return 0;
@ -404,7 +413,7 @@ static int on_init_message(struct vnc_client *client)
return sizeof(shared_flag); return sizeof(shared_flag);
} }
static int on_client_set_pixel_format(struct vnc_client *client) static int on_client_set_pixel_format(struct nvnc_client *client)
{ {
if (client->buffer_len - client->buffer_index if (client->buffer_len - client->buffer_index
< 4 + sizeof(struct rfb_pixel_format)) < 4 + sizeof(struct rfb_pixel_format))
@ -431,7 +440,7 @@ static int on_client_set_pixel_format(struct vnc_client *client)
return 4 + sizeof(struct rfb_pixel_format); return 4 + sizeof(struct rfb_pixel_format);
} }
static int on_client_set_encodings(struct vnc_client *client) static int on_client_set_encodings(struct nvnc_client *client)
{ {
struct rfb_client_set_encodings_msg *msg = struct rfb_client_set_encodings_msg *msg =
(struct rfb_client_set_encodings_msg*)(client->msg_buffer + (struct rfb_client_set_encodings_msg*)(client->msg_buffer +
@ -458,7 +467,7 @@ static int on_client_set_encodings(struct vnc_client *client)
return sizeof(*msg) + 4 * n_encodings; return sizeof(*msg) + 4 * n_encodings;
} }
static int on_client_fb_update_request(struct vnc_client *client) static int on_client_fb_update_request(struct nvnc_client *client)
{ {
struct nvnc *server = client->server; struct nvnc *server = client->server;
@ -478,12 +487,12 @@ static int on_client_fb_update_request(struct vnc_client *client)
nvnc_fb_req_fn fn = server->fb_req_fn; nvnc_fb_req_fn fn = server->fb_req_fn;
if (fn) if (fn)
fn(server, incremental, x, y, width, height); fn(client, incremental, x, y, width, height);
return sizeof(*msg); return sizeof(*msg);
} }
static int on_client_key_event(struct vnc_client *client) static int on_client_key_event(struct nvnc_client *client)
{ {
struct nvnc *server = client->server; struct nvnc *server = client->server;
@ -496,12 +505,12 @@ static int on_client_key_event(struct vnc_client *client)
nvnc_key_fn fn = server->key_fn; nvnc_key_fn fn = server->key_fn;
if (fn) if (fn)
fn(server, keysym, !!down_flag); fn(client, keysym, !!down_flag);
return sizeof(*msg); return sizeof(*msg);
} }
static int on_client_pointer_event(struct vnc_client *client) static int on_client_pointer_event(struct nvnc_client *client)
{ {
struct nvnc *server = client->server; struct nvnc *server = client->server;
@ -515,12 +524,12 @@ static int on_client_pointer_event(struct vnc_client *client)
nvnc_pointer_fn fn = server->pointer_fn; nvnc_pointer_fn fn = server->pointer_fn;
if (fn) if (fn)
fn(server, x, y, button_mask); fn(client, x, y, button_mask);
return sizeof(*msg); return sizeof(*msg);
} }
static int on_client_cut_text(struct vnc_client *client) static int on_client_cut_text(struct nvnc_client *client)
{ {
struct rfb_client_cut_text_msg *msg = struct rfb_client_cut_text_msg *msg =
(struct rfb_client_cut_text_msg*)(client->msg_buffer + (struct rfb_client_cut_text_msg*)(client->msg_buffer +
@ -533,7 +542,7 @@ static int on_client_cut_text(struct vnc_client *client)
return sizeof(*msg) + length; return sizeof(*msg) + length;
} }
static int on_client_message(struct vnc_client *client) static int on_client_message(struct nvnc_client *client)
{ {
if (client->buffer_len - client->buffer_index < 1) if (client->buffer_len - client->buffer_index < 1)
return 0; return 0;
@ -560,7 +569,7 @@ static int on_client_message(struct vnc_client *client)
return 0; return 0;
} }
static int try_read_client_message(struct vnc_client *client) static int try_read_client_message(struct nvnc_client *client)
{ {
switch (client->state) { switch (client->state) {
case VNC_CLIENT_STATE_ERROR: case VNC_CLIENT_STATE_ERROR:
@ -593,7 +602,9 @@ static void on_client_read(uv_stream_t *stream, ssize_t n_read,
if (n_read < 0) if (n_read < 0)
return; return;
struct vnc_client *client = (struct vnc_client*)stream; struct nvnc_client *client =
container_of((uv_tcp_t*)stream, struct nvnc_client,
stream_handle);
assert(client->buffer_index == 0); assert(client->buffer_index == 0);
@ -625,9 +636,10 @@ static void on_client_read(uv_stream_t *stream, ssize_t n_read,
static void on_connection(uv_stream_t *server_stream, int status) static void on_connection(uv_stream_t *server_stream, int status)
{ {
struct nvnc *server = (struct nvnc*)server_stream; struct nvnc *server = container_of((uv_tcp_t*)server_stream,
struct nvnc, tcp_handle);
struct vnc_client *client = calloc(1, sizeof(*client)); struct nvnc_client *client = calloc(1, sizeof(*client));
if (!client) if (!client)
return; return;
@ -708,7 +720,7 @@ failure:
EXPORT EXPORT
void nvnc_close(struct nvnc *self) void nvnc_close(struct nvnc *self)
{ {
struct vnc_client *client; struct nvnc_client *client;
LIST_FOREACH(client, &self->clients, link) LIST_FOREACH(client, &self->clients, link)
uv_close((uv_handle_t*)&client->stream_handle, cleanup_client); uv_close((uv_handle_t*)&client->stream_handle, cleanup_client);
@ -742,7 +754,7 @@ int nvnc_update_fb(struct nvnc *self, const struct nvnc_fb *fb,
if (rc < 0) if (rc < 0)
goto failure; goto failure;
struct vnc_client *client; struct nvnc_client *client;
LIST_FOREACH(client, &self->clients, link) { LIST_FOREACH(client, &self->clients, link) {
struct pixman_region16* cregion = &client->requested_region; struct pixman_region16* cregion = &client->requested_region;
@ -765,15 +777,17 @@ failure:
} }
EXPORT EXPORT
void nvnc_set_userdata(struct nvnc *self, void *userdata) void nvnc_set_userdata(void *self, void *userdata)
{ {
self->userdata = userdata; struct nvnc_common *common = self;
common->userdata = userdata;
} }
EXPORT EXPORT
void* nvnc_get_userdata(const struct nvnc *self) void* nvnc_get_userdata(const void *self)
{ {
return self->userdata; const struct nvnc_common *common = self;
return common->userdata;
} }
EXPORT EXPORT
@ -803,6 +817,12 @@ void nvnc_set_dimensions(struct nvnc *self, uint16_t width, uint16_t height,
self->display.pixfmt = fourcc_format; self->display.pixfmt = fourcc_format;
} }
EXPORT
struct nvnc *nvnc_get_server(const struct nvnc_client *client)
{
return client->server;
}
EXPORT EXPORT
void nvnc_set_name(struct nvnc *self, const char *name) void nvnc_set_name(struct nvnc *self, const char *name)
{ {

View File

@ -183,7 +183,7 @@ int zrle_deflate(struct vec* dst, const struct vec* src, z_stream* zs,
r = deflate(zs, flush ? Z_FINISH : Z_NO_FLUSH); r = deflate(zs, flush ? Z_FINISH : Z_NO_FLUSH);
assert(r != Z_STREAM_ERROR); assert(r != Z_STREAM_ERROR);
dst->len = dst->cap - zs->avail_out; dst->len = zs->next_out - (Bytef*)dst->data;
} while (zs->avail_out == 0); } while (zs->avail_out == 0);
assert(zs->avail_in == 0); assert(zs->avail_in == 0);