mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 22:48:19 +00:00
Revert "server: add websockets support via libwebsockets"
This reverts commit 63bb37276e.
This commit is contained in:
parent
b7bdd28343
commit
4e7d25a7ac
16
configure.ac
16
configure.ac
@ -160,14 +160,6 @@ AC_ARG_ENABLE(automated_tests,
|
||||
AS_IF([test x"$enable_automated_tests" != "xno"], [enable_automated_tests="yes"])
|
||||
AM_CONDITIONAL(SUPPORT_AUTOMATED_TESTS, test "x$enable_automated_tests" != "xno")
|
||||
|
||||
AC_ARG_ENABLE(libwebsockets,
|
||||
[ --enable-libwebsockets Enable websockets server support (no need for proxy)],,
|
||||
[enable_libwebsockets="no"])
|
||||
AS_IF([test x"enable_libwebsockets" != "xyes"], [enable_websockets="no"])
|
||||
AM_CONDITIONAL(SUPPORT_LIBWEBSOCKETS, test "x$enable_websockets" = "xyes")
|
||||
if test "x$enable_libwebsockets" = "xyes"; then
|
||||
AC_DEFINE([USE_LIBWEBSOCKETS], [1], [Define if supporting websocket connections])
|
||||
fi
|
||||
|
||||
dnl =========================================================================
|
||||
dnl Check deps
|
||||
@ -245,12 +237,6 @@ if test "x$enable_smartcard" = "xyes"; then
|
||||
SPICE_REQUIRES+=" libcacard >= 0.1.2"
|
||||
fi
|
||||
|
||||
if test "x$enable_libwebsockets" = "xyes"; then
|
||||
PKG_CHECK_MODULES(LIBWEBSOCKETS, libwebsockets >= 0.0.3)
|
||||
AC_SUBST(LIBWEBSOCKETS_LIBS)
|
||||
AC_SUBST(LIBWEBSOCKETS_CFLAGS)
|
||||
SPICE_REQUIRES+=" libwebsockets >= 0.0.3"
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.17.7)
|
||||
AC_SUBST(PIXMAN_CFLAGS)
|
||||
@ -550,8 +536,6 @@ echo "
|
||||
SASL support: ${enable_sasl}
|
||||
|
||||
Automated tests: ${enable_automated_tests}
|
||||
|
||||
libwebsockets: ${enable_libwebsockets}
|
||||
"
|
||||
|
||||
if test $os_win32 == "yes" ; then
|
||||
|
||||
@ -10,7 +10,6 @@ AM_CPPFLAGS = \
|
||||
$(SLIRP_CFLAGS) \
|
||||
$(SMARTCARD_CFLAGS) \
|
||||
$(SSL_CFLAGS) \
|
||||
$(LIBWEBSOCKETS_CFLAGS) \
|
||||
$(VISIBILITY_HIDDEN_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(NULL)
|
||||
@ -39,7 +38,6 @@ libspice_server_la_LIBADD = \
|
||||
$(SLIRP_LIBS) \
|
||||
$(SSL_LIBS) \
|
||||
$(Z_LIBS) \
|
||||
$(LIBWEBSOCKETS_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
libspice_server_la_SOURCES = \
|
||||
@ -95,13 +93,6 @@ libspice_server_la_SOURCES = \
|
||||
zlib_encoder.h \
|
||||
$(NULL)
|
||||
|
||||
if SUPPORT_WEBSOCKETS
|
||||
libspice_server_la_SOURCES += \
|
||||
reds_websockets.c \
|
||||
reds_websockets.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if SUPPORT_TUNNEL
|
||||
libspice_server_la_SOURCES += \
|
||||
red_tunnel_worker.c \
|
||||
|
||||
@ -4,16 +4,6 @@
|
||||
#include <time.h>
|
||||
|
||||
#include <spice/protocol.h>
|
||||
#include <spice/stats.h>
|
||||
|
||||
#if USE_LIBWEBSOCKETS
|
||||
#include <libwebsockets.h>
|
||||
#endif
|
||||
|
||||
#include "reds.h"
|
||||
#include "char_device.h"
|
||||
#include "agent-msg-filter.h"
|
||||
#include "main_channel.h"
|
||||
|
||||
#define MIGRATE_TIMEOUT (1000 * 10) /* 10sec */
|
||||
#define MM_TIMER_GRANULARITY_MS (1000 / 30)
|
||||
@ -44,6 +34,10 @@ typedef struct VDIReadBuf {
|
||||
uint8_t data[SPICE_AGENT_MAX_DATA_SIZE];
|
||||
} VDIReadBuf;
|
||||
|
||||
static VDIReadBuf *vdi_port_read_buf_get(void);
|
||||
static VDIReadBuf *vdi_port_read_buf_ref(VDIReadBuf *buf);
|
||||
static void vdi_port_read_buf_unref(VDIReadBuf *buf);
|
||||
|
||||
enum {
|
||||
VDI_PORT_READ_STATE_READ_HEADER,
|
||||
VDI_PORT_READ_STATE_GET_BUFF,
|
||||
@ -131,19 +125,9 @@ typedef struct RedsClientMonitorsConfig {
|
||||
int buffer_pos;
|
||||
} RedsClientMonitorsConfig;
|
||||
|
||||
#ifdef USE_LIBWEBSOCKETS
|
||||
#define REDS_MAX_WEBSOCKETS 32
|
||||
#endif
|
||||
|
||||
typedef struct RedsState {
|
||||
int listen_socket;
|
||||
int secure_listen_socket;
|
||||
#ifdef USE_LIBWEBSOCKETS
|
||||
struct libwebsocket_context *ws_context;
|
||||
RedsWebSocket ws[REDS_MAX_WEBSOCKETS];
|
||||
int ws_in_service_fd;
|
||||
int ws_count;
|
||||
#endif
|
||||
SpiceWatch *listen_watch;
|
||||
SpiceWatch *secure_listen_watch;
|
||||
VDIPortState agent_state;
|
||||
@ -195,27 +179,4 @@ typedef struct RedsState {
|
||||
RedsClientMonitorsConfig client_monitors_config;
|
||||
} RedsState;
|
||||
|
||||
typedef struct AsyncRead {
|
||||
RedsStream *stream;
|
||||
void *opaque;
|
||||
uint8_t *now;
|
||||
uint8_t *end;
|
||||
void (*done)(void *opaque);
|
||||
void (*error)(void *opaque, int err);
|
||||
} AsyncRead;
|
||||
|
||||
typedef struct RedLinkInfo {
|
||||
RedsStream *stream;
|
||||
AsyncRead asyc_read;
|
||||
SpiceLinkHeader link_header;
|
||||
SpiceLinkMess *link_mess;
|
||||
int mess_pos;
|
||||
TicketInfo tiTicketing;
|
||||
SpiceLinkAuthMechanism auth_mechanism;
|
||||
int skip_auth;
|
||||
} RedLinkInfo;
|
||||
|
||||
RedLinkInfo *spice_server_add_client_create_link(SpiceServer *s, int socket, int skip_auth);
|
||||
void reds_handle_new_link(RedLinkInfo *link);
|
||||
|
||||
#endif
|
||||
|
||||
@ -74,16 +74,9 @@
|
||||
#ifdef USE_SMARTCARD
|
||||
#include "smartcard.h"
|
||||
#endif
|
||||
#if USE_LIBWEBSOCKETS
|
||||
#include "reds_websockets.h"
|
||||
#endif
|
||||
|
||||
#include "reds-private.h"
|
||||
|
||||
static VDIReadBuf *vdi_port_read_buf_get(void);
|
||||
static VDIReadBuf *vdi_port_read_buf_ref(VDIReadBuf *buf);
|
||||
static void vdi_port_read_buf_unref(VDIReadBuf *buf);
|
||||
|
||||
SpiceCoreInterface *core = NULL;
|
||||
static SpiceCharDeviceInstance *vdagent = NULL;
|
||||
static SpiceMigrateInstance *migration_interface = NULL;
|
||||
@ -106,10 +99,6 @@ static TicketAuthentication taTicket;
|
||||
|
||||
static int spice_port = -1;
|
||||
static int spice_secure_port = -1;
|
||||
#if USE_LIBWEBSOCKETS
|
||||
static int spice_ws_port = -1;
|
||||
static int spice_wss_port = -1;
|
||||
#endif
|
||||
static int spice_listen_socket_fd = -1;
|
||||
static char spice_addr[256];
|
||||
static int spice_family = PF_UNSPEC;
|
||||
@ -138,6 +127,26 @@ static bool exit_on_disconnect = FALSE;
|
||||
|
||||
static RedsState *reds = NULL;
|
||||
|
||||
typedef struct AsyncRead {
|
||||
RedsStream *stream;
|
||||
void *opaque;
|
||||
uint8_t *now;
|
||||
uint8_t *end;
|
||||
void (*done)(void *opaque);
|
||||
void (*error)(void *opaque, int err);
|
||||
} AsyncRead;
|
||||
|
||||
typedef struct RedLinkInfo {
|
||||
RedsStream *stream;
|
||||
AsyncRead asyc_read;
|
||||
SpiceLinkHeader link_header;
|
||||
SpiceLinkMess *link_mess;
|
||||
int mess_pos;
|
||||
TicketInfo tiTicketing;
|
||||
SpiceLinkAuthMechanism auth_mechanism;
|
||||
int skip_auth;
|
||||
} RedLinkInfo;
|
||||
|
||||
typedef struct RedSSLParameters {
|
||||
char keyfile_password[256];
|
||||
char certs_file[256];
|
||||
@ -2709,7 +2718,7 @@ static void reds_handle_read_header_done(void *opaque)
|
||||
async_read_handler(0, 0, &link->asyc_read);
|
||||
}
|
||||
|
||||
void reds_handle_new_link(RedLinkInfo *link)
|
||||
static void reds_handle_new_link(RedLinkInfo *link)
|
||||
{
|
||||
AsyncRead *obj = &link->asyc_read;
|
||||
obj->opaque = link;
|
||||
@ -2873,6 +2882,7 @@ static void reds_accept_ssl_connection(int fd, int event, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reds_accept(int fd, int event, void *data)
|
||||
{
|
||||
int socket;
|
||||
@ -2886,33 +2896,25 @@ static void reds_accept(int fd, int event, void *data)
|
||||
close(socket);
|
||||
}
|
||||
|
||||
RedLinkInfo *spice_server_add_client_create_link(SpiceServer *s, int socket, int skip_auth)
|
||||
{
|
||||
RedLinkInfo *link;
|
||||
|
||||
spice_assert(reds == s);
|
||||
if (!(link = reds_init_client_connection(socket))) {
|
||||
spice_warning("accept failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
link->skip_auth = skip_auth;
|
||||
return link;
|
||||
}
|
||||
|
||||
SPICE_GNUC_VISIBLE int spice_server_add_client(SpiceServer *s, int socket, int skip_auth)
|
||||
{
|
||||
RedLinkInfo *link;
|
||||
RedsStream *stream;
|
||||
|
||||
link = spice_server_add_client_create_link(s, socket, skip_auth);
|
||||
if (!link) {
|
||||
spice_assert(reds == s);
|
||||
if (!(link = reds_init_client_connection(socket))) {
|
||||
spice_warning("accept failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
link->skip_auth = skip_auth;
|
||||
|
||||
stream = link->stream;
|
||||
stream->read = stream_read_cb;
|
||||
stream->write = stream_write_cb;
|
||||
stream->writev = stream_writev_cb;
|
||||
|
||||
reds_handle_new_link(link);
|
||||
return 0;
|
||||
}
|
||||
@ -3031,12 +3033,6 @@ static int reds_init_net(void)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_LIBWEBSOCKETS
|
||||
if (spice_ws_port != -1 || spice_wss_port != -1) {
|
||||
reds_init_websocket(reds, spice_addr, spice_ws_port, spice_wss_port);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3953,27 +3949,6 @@ SPICE_GNUC_VISIBLE int spice_server_set_port(SpiceServer *s, int port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SPICE_GNUC_VISIBLE int spice_server_set_ws_ports(SpiceServer *s, int ws_port, int wss_port)
|
||||
{
|
||||
#if USE_LIBWEBSOCKETS
|
||||
spice_assert(reds == s);
|
||||
if ((ws_port < 1 || ws_port > 0xffff) && (wss_port < 1 || wss_port > 0xffff)) {
|
||||
return -1;
|
||||
}
|
||||
if (ws_port > 0 && ws_port < 0xffff) {
|
||||
spice_ws_port = ws_port;
|
||||
}
|
||||
if (wss_port > 0 && wss_port < 0xffff) {
|
||||
spice_wss_port = wss_port;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
fprintf(stderr, "libwebsockets is unsupported in this spice build\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
SPICE_GNUC_VISIBLE void spice_server_set_addr(SpiceServer *s, const char *addr, int flags)
|
||||
{
|
||||
spice_assert(reds == s);
|
||||
|
||||
@ -65,20 +65,6 @@ typedef struct RedsSASL {
|
||||
} RedsSASL;
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBWEBSOCKETS
|
||||
typedef struct RedsWebSocket {
|
||||
struct libwebsocket_context *context;
|
||||
struct libwebsocket *wsi;
|
||||
SpiceWatch *watch;
|
||||
int fd;
|
||||
unsigned events;
|
||||
/* buffer of available data to read, always starts at offset 0 to data_avail - 1. */
|
||||
unsigned char *data;
|
||||
unsigned data_len;
|
||||
unsigned data_avail;
|
||||
} RedsWebSocket;
|
||||
#endif
|
||||
|
||||
struct RedsStream {
|
||||
int socket;
|
||||
SpiceWatch *watch;
|
||||
@ -87,9 +73,6 @@ struct RedsStream {
|
||||
receive may return data afterward. check the flag before calling receive*/
|
||||
int shutdown;
|
||||
SSL *ssl;
|
||||
#ifdef USE_LIBWEBSOCKETS
|
||||
RedsWebSocket *ws;
|
||||
#endif
|
||||
|
||||
#if HAVE_SASL
|
||||
RedsSASL sasl;
|
||||
|
||||
@ -1,310 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include "spice.h"
|
||||
#include "reds.h"
|
||||
#include "reds-private.h"
|
||||
#include "reds_websockets.h"
|
||||
|
||||
static ssize_t stream_write_ws_cb(RedsStream *s, const void *buf, size_t size)
|
||||
{
|
||||
/* TODO: better way to handle the requirement of libwebsocket, perhaps
|
||||
* we should make a writev version for libwebsocket. Assuming writev doesn't
|
||||
* cause a linearlizing copy itself. */
|
||||
ssize_t ret;
|
||||
unsigned char *padded_buf = spice_malloc(size + LWS_SEND_BUFFER_PRE_PADDING +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
spice_assert(s && s->ws);
|
||||
memcpy(padded_buf + LWS_SEND_BUFFER_PRE_PADDING, buf, size);
|
||||
ret = libwebsocket_write(s->ws->wsi, &padded_buf[LWS_SEND_BUFFER_PRE_PADDING], size,
|
||||
LWS_WRITE_BINARY);
|
||||
free(padded_buf);
|
||||
return ret == 0 ? size : -1; /* XXX exact bytes required? if not this is
|
||||
good enough, else need to change
|
||||
libwebsocket */
|
||||
}
|
||||
|
||||
static void reds_websocket_append_data(RedsWebSocket *ws, unsigned char *buf,
|
||||
size_t size)
|
||||
{
|
||||
if (!ws->data) {
|
||||
ws->data = spice_malloc(size);
|
||||
ws->data_len = size;
|
||||
ws->data_avail = 0;
|
||||
}
|
||||
if (ws->data_len < size + ws->data_avail) {
|
||||
ws->data_len = size + ws->data_avail;
|
||||
ws->data = spice_realloc(ws->data, ws->data_len);
|
||||
}
|
||||
memcpy(ws->data + ws->data_avail, buf, size);
|
||||
ws->data_avail += size;
|
||||
}
|
||||
|
||||
static ssize_t reds_websocket_read_data(RedsWebSocket *ws, unsigned char *buf,
|
||||
size_t size)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
ret = ws->data_avail > size ? size : ws->data_avail;
|
||||
if (ret > 0) {
|
||||
memcpy(buf, ws->data, ret);
|
||||
}
|
||||
if (ret > 0 && ret < ws->data_avail) {
|
||||
memmove(ws->data, ws->data + ret, ws->data_avail - ret);
|
||||
}
|
||||
ws->data_avail -= ret;
|
||||
if (ws->data_avail == 0 && ret == size) {
|
||||
free(ws->data);
|
||||
ws->data = NULL;
|
||||
ws->data_len = ws->data_avail = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int reds_libwebsocket_service_fd(RedsState *s, struct pollfd *pfd)
|
||||
{
|
||||
int ret;
|
||||
if (s->ws_in_service_fd) {
|
||||
return 0;
|
||||
}
|
||||
s->ws_in_service_fd = 1;
|
||||
ret = libwebsocket_service_fd(s->ws_context, pfd);
|
||||
s->ws_in_service_fd = 0;
|
||||
if (ret != 0) {
|
||||
if (errno == EAGAIN) {
|
||||
spice_debug("libwebsocket_servide_fd EAGAIN, pfd->revents = %d",
|
||||
pfd->revents);
|
||||
return 0;
|
||||
}
|
||||
/* since read is the last systemcall, errno should be set correctly */
|
||||
spice_debug("libwebsocket_service_fd errored; (%d) %s",
|
||||
errno, sys_errlist[errno]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t stream_read_ws_cb(RedsStream *s, void *buf, size_t size)
|
||||
{
|
||||
RedsWebSocket *ws;
|
||||
struct pollfd pfd;
|
||||
RedsState *reds_state;
|
||||
|
||||
/* TODO: perhaps change libwebsocket to allow a socket like read. Then
|
||||
* we can avoid the whole RedsWebSocket->data{,_len,_avail}. */
|
||||
spice_assert(s && s->ws);
|
||||
ws = s->ws;
|
||||
reds_state = libwebsocket_context_user(ws->context);
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
spice_debug("%p %d / %d", ws->data, ws->data_avail, ws->data_len);
|
||||
if (ws->data_avail < size && !reds_state->ws_in_service_fd) {
|
||||
pfd.fd = ws->fd;
|
||||
pfd.events = ws->events;
|
||||
pfd.revents = POLLIN;
|
||||
if (reds_libwebsocket_service_fd(reds_state, &pfd)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ws->data_avail == 0) {
|
||||
errno = EAGAIN; /* force a reset of the watch on the fd, so that
|
||||
libwebsocket_service_fd has a chance to run */
|
||||
return -1;
|
||||
}
|
||||
return reds_websocket_read_data(ws, buf, size);
|
||||
}
|
||||
|
||||
static RedsWebSocket *reds_ws_from_fd(RedsState *s, int fd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < s->ws_count ; ++i) {
|
||||
if (s->ws[i].fd == fd) {
|
||||
return &s->ws[i];
|
||||
}
|
||||
}
|
||||
spice_error("%s: no match for %d (%d ws sockets)\n", __func__,
|
||||
fd, s->ws_count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int callback_http(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
const char *message = "TODO: serve spice-html5";
|
||||
char buf[512];
|
||||
int n;
|
||||
|
||||
n = snprintf(buf, sizeof(buf),
|
||||
"HTTP/1.0 200 OK\x0d\x0a"
|
||||
"Server: spice\x0d\x0a"
|
||||
"Content-Type: text/html\x0d\x0a"
|
||||
"Content-Length: %zu\x0d\x0a"
|
||||
"\x0d\x0a"
|
||||
"%s", strlen(message), message);
|
||||
libwebsocket_write(wsi, (unsigned char *)buf, n, LWS_WRITE_HTTP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spice_server_add_ws_client(SpiceServer *s, int socket, int skip_auth,
|
||||
RedsWebSocket *ws)
|
||||
{
|
||||
RedLinkInfo *link;
|
||||
RedsStream *stream;
|
||||
|
||||
link = spice_server_add_client_create_link(s, socket, skip_auth);
|
||||
if (!link) {
|
||||
return -1;
|
||||
}
|
||||
stream = link->stream;
|
||||
stream->read = stream_read_ws_cb;
|
||||
stream->write = stream_write_ws_cb;
|
||||
stream->writev = NULL; /* falls back to write iteration */
|
||||
stream->ws = ws;
|
||||
reds_handle_new_link(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void watch_ws(int fd, int event, void *data)
|
||||
{
|
||||
struct libwebsocket_context *context = data;
|
||||
RedsState *s = libwebsocket_context_user(context);
|
||||
struct pollfd pfd = {
|
||||
.fd = fd,
|
||||
.events = reds_ws_from_fd(s, fd)->events,
|
||||
.revents = (event & SPICE_WATCH_EVENT_READ ? POLLIN : 0) |
|
||||
(event & SPICE_WATCH_EVENT_WRITE ? POLLOUT : 0)
|
||||
};
|
||||
|
||||
reds_libwebsocket_service_fd(s, &pfd);
|
||||
}
|
||||
|
||||
static int callback_ws(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
{
|
||||
int fd;
|
||||
RedsState *s = libwebsocket_context_user(context);
|
||||
int n;
|
||||
RedsWebSocket *ws;
|
||||
int events;
|
||||
|
||||
spice_debug("%s: reason %d user %lu len %zd \n", __func__, reason,
|
||||
(unsigned long)user, len);
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_HTTP:
|
||||
return callback_http(context, wsi, user, in, len);
|
||||
|
||||
case LWS_CALLBACK_ADD_POLL_FD:
|
||||
if (s->ws_count >= REDS_MAX_WEBSOCKETS) {
|
||||
spice_warning("exceeded websockets maximum watches");
|
||||
return 1; /* close connection */
|
||||
}
|
||||
spice_debug("adding ws for fd %d", (int)(long)user);
|
||||
events = (int)(long)len;
|
||||
ws = &s->ws[s->ws_count];
|
||||
ws->watch = core->watch_add((int)(long)user,
|
||||
(events & POLLIN ? SPICE_WATCH_EVENT_READ: 0) |
|
||||
(events & POLLOUT ? SPICE_WATCH_EVENT_WRITE : 0),
|
||||
watch_ws, (void *)context);
|
||||
ws->fd = (int)(long)user;
|
||||
ws->events = events;
|
||||
s->ws_count++;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_DEL_POLL_FD:
|
||||
spice_debug("removing ws for fd %d", (int)(long)user);
|
||||
for (n = 0; n < s->ws_count; n++) {
|
||||
if (s->ws[n].fd == (int)(long)user) {
|
||||
s->ws[n] = s->ws[s->ws_count - 1];
|
||||
}
|
||||
s->ws_count--;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SET_MODE_POLL_FD:
|
||||
reds_ws_from_fd(s, (int)(long)user)->events |= (int)(long)len;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLEAR_MODE_POLL_FD:
|
||||
reds_ws_from_fd(s, (int)(long)user)->events &= (int)(long)len;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
fd = libwebsocket_get_socket_fd(wsi);
|
||||
ws = reds_ws_from_fd(s, fd);
|
||||
*(RedsWebSocket **)user = ws;
|
||||
ws->wsi = wsi;
|
||||
ws->context = context;
|
||||
ws->data_avail = 0;
|
||||
spice_debug("LWS_CALLBACK_ESTABLISHED\n");
|
||||
spice_server_add_ws_client(s, fd, 0, ws);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
spice_debug("LWS_CALLBACK_CLIENT_RECEIVE\n");
|
||||
spice_assert(user != NULL);
|
||||
ws = *(RedsWebSocket **)user;
|
||||
spice_assert(ws != NULL);
|
||||
reds_websocket_append_data(ws, in, len);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
case LWS_CALLBACK_BROADCAST:
|
||||
case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
|
||||
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
||||
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
|
||||
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS:
|
||||
case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
|
||||
case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
|
||||
case LWS_CALLBACK_CONFIRM_EXTENSION_OKAY:
|
||||
case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct libwebsocket_protocols ws_protocols[] = {
|
||||
/* first protocol must always be HTTP handler */
|
||||
|
||||
{
|
||||
"binary", /* name - based on spice-html5 :) */
|
||||
callback_ws, /* callback */
|
||||
sizeof(void*), /* per_session_data_size */
|
||||
/* below initializing library used values to avoid warning */
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
},
|
||||
{
|
||||
NULL, NULL, 0, NULL, 0, 0, 0 /* End of list */
|
||||
}
|
||||
};
|
||||
|
||||
void reds_init_websocket(RedsState *s, const char *addr,
|
||||
int ws_port, int wss_port)
|
||||
{
|
||||
if (ws_port != -1) {
|
||||
s->ws_context = libwebsocket_create_context(ws_port,
|
||||
strlen(addr) ? addr : NULL,
|
||||
ws_protocols, libwebsocket_internal_extensions,
|
||||
NULL /*cert_path*/, NULL /*key_path*/, -1, -1, 0 /*opts*/,
|
||||
s);
|
||||
}
|
||||
if (wss_port != -1) {
|
||||
spice_error("TODO: secure websocket not supported");
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
#ifndef REDS_WEBSOCKETS_H
|
||||
#define REDS_WEBSOCKETS_H
|
||||
|
||||
#include "reds-private.h"
|
||||
|
||||
void reds_init_websocket(RedsState *s, const char *addr,
|
||||
int ws_port, int wss_port);
|
||||
|
||||
#endif
|
||||
@ -130,8 +130,3 @@ SPICE_SERVER_0.11.4 {
|
||||
global:
|
||||
spice_server_set_exit_on_disconnect;
|
||||
} SPICE_SERVER_0.11.2;
|
||||
|
||||
SPICE_SERVER_0.12.1 {
|
||||
global:
|
||||
spice_server_set_ws_ports;
|
||||
} SPICE_SERVER_0.11.4;
|
||||
|
||||
@ -434,13 +434,6 @@ void spice_server_destroy(SpiceServer *s);
|
||||
int spice_server_set_compat_version(SpiceServer *s,
|
||||
spice_compat_version_t version);
|
||||
int spice_server_set_port(SpiceServer *s, int port);
|
||||
|
||||
/* @ws_port: -1 for don't set, otherwise in [1,65535] port to listen
|
||||
* for unencrypted websocket connections.
|
||||
* @wss_port: -1 for don't set, otherwise in [1,65535] port to listen
|
||||
* for encrypted websocket connections.
|
||||
*/
|
||||
int spice_server_set_ws_ports(SpiceServer *s, int ws_port, int wss_port);
|
||||
void spice_server_set_addr(SpiceServer *s, const char *addr, int flags);
|
||||
int spice_server_set_listen_socket_fd(SpiceServer *s, int listen_fd);
|
||||
int spice_server_set_exit_on_disconnect(SpiceServer *s, int flag);
|
||||
|
||||
@ -701,14 +701,13 @@ static int flush_resources(QXLInstance *qin)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int client_monitors_config(QXLInstance *qin, VDAgentMonitorsConfig *monitors_config)
|
||||
static void client_monitors_config(QXLInstance *qin, VDAgentMonitorsConfig *monitors_config)
|
||||
{
|
||||
if (!monitors_config) {
|
||||
printf("%s: NULL monitors_config\n", __func__);
|
||||
} else {
|
||||
printf("%s: %d\n", __func__, monitors_config->num_of_monitors);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QXLInterface display_sif = {
|
||||
@ -816,7 +815,6 @@ Test *test_new(SpiceCoreInterface *core)
|
||||
printf("TESTER: listening on port %d (unsecure)\n", port);
|
||||
spice_server_set_port(server, port);
|
||||
spice_server_set_noauth(server);
|
||||
spice_server_set_ws_ports(test->server, 5959, -1);
|
||||
spice_server_init(server, core);
|
||||
|
||||
cursor_init();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user