mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-13 18:16:35 +01:00
Clean up and prepare for HTTP
This commit is contained in:
parent
3da0cf2a31
commit
40520a6dc6
5 changed files with 163 additions and 56 deletions
|
|
@ -35,7 +35,7 @@ using namespace ArdourSurface;
|
||||||
#include "pbd/abstract_ui.cc" // instantiate template
|
#include "pbd/abstract_ui.cc" // instantiate template
|
||||||
|
|
||||||
ArdourWebsockets::ArdourWebsockets (Session& s)
|
ArdourWebsockets::ArdourWebsockets (Session& s)
|
||||||
: ControlProtocol (s, X_ (SURFACE_NAME))
|
: ControlProtocol (s, X_ (surface_name))
|
||||||
, AbstractUI<ArdourWebsocketsUIRequest> (name ())
|
, AbstractUI<ArdourWebsocketsUIRequest> (name ())
|
||||||
, _strips (*this)
|
, _strips (*this)
|
||||||
, _globals (*this)
|
, _globals (*this)
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,11 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "strips.h"
|
#include "strips.h"
|
||||||
|
|
||||||
#define SURFACE_NAME "WebSockets Server (Experimental)"
|
|
||||||
#define SURFACE_ID "uri://ardour.org/surfaces/ardour_websockets:0"
|
|
||||||
|
|
||||||
namespace ArdourSurface
|
namespace ArdourSurface
|
||||||
{
|
{
|
||||||
|
const char * const surface_name = "WebSockets Server (Experimental)";
|
||||||
|
const char * const surface_id = "uri://ardour.org/surfaces/ardour_websockets:0";
|
||||||
|
|
||||||
struct ArdourWebsocketsUIRequest : public BaseUI::BaseRequestObject {
|
struct ArdourWebsocketsUIRequest : public BaseUI::BaseRequestObject {
|
||||||
public:
|
public:
|
||||||
ArdourWebsocketsUIRequest () {}
|
ArdourWebsocketsUIRequest () {}
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ ardour_websockets_request_buffer_factory (uint32_t num_requests)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ControlProtocolDescriptor ardour_websockets_descriptor = {
|
static ControlProtocolDescriptor ardour_websockets_descriptor = {
|
||||||
/*name : */ SURFACE_NAME,
|
/*name : */ surface_name,
|
||||||
/*id : */ SURFACE_ID,
|
/*id : */ surface_id,
|
||||||
/*ptr : */ 0,
|
/*ptr : */ 0,
|
||||||
/*module : */ 0,
|
/*module : */ 0,
|
||||||
/*mandatory : */ 0,
|
/*mandatory : */ 0,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_INDEX_SIZE 65536
|
||||||
|
|
||||||
using namespace Glib;
|
using namespace Glib;
|
||||||
|
|
||||||
WebsocketsServer::WebsocketsServer (ArdourSurface::ArdourWebsockets& surface)
|
WebsocketsServer::WebsocketsServer (ArdourSurface::ArdourWebsockets& surface)
|
||||||
|
|
@ -49,7 +51,6 @@ WebsocketsServer::WebsocketsServer (ArdourSurface::ArdourWebsockets& surface)
|
||||||
memset (&proto, 0, sizeof (lws_protocols));
|
memset (&proto, 0, sizeof (lws_protocols));
|
||||||
proto.name = "lws-ardour";
|
proto.name = "lws-ardour";
|
||||||
proto.callback = WebsocketsServer::lws_callback;
|
proto.callback = WebsocketsServer::lws_callback;
|
||||||
proto.per_session_data_size = 0;
|
|
||||||
proto.rx_buffer_size = 0;
|
proto.rx_buffer_size = 0;
|
||||||
proto.id = 0;
|
proto.id = 0;
|
||||||
proto.user = 0;
|
proto.user = 0;
|
||||||
|
|
@ -59,9 +60,29 @@ WebsocketsServer::WebsocketsServer (ArdourSurface::ArdourWebsockets& surface)
|
||||||
_lws_proto[0] = proto;
|
_lws_proto[0] = proto;
|
||||||
memset (&_lws_proto[1], 0, sizeof (lws_protocols));
|
memset (&_lws_proto[1], 0, sizeof (lws_protocols));
|
||||||
|
|
||||||
|
// '/' is served by a static index.html file in the surface data directory
|
||||||
|
// inside it there is a 'builtin' subdirectory that contains all built-in
|
||||||
|
// surfaces so there is no need to create a dedicated mount point for them
|
||||||
|
// list of surfaces is available as a dynamically generated json file
|
||||||
|
memset (&_lws_mnt_index, 0, sizeof (lws_http_mount));
|
||||||
|
_lws_mnt_index.mountpoint = "/";
|
||||||
|
_lws_mnt_index.mountpoint_len = strlen (_lws_mnt_index.mountpoint);
|
||||||
|
_lws_mnt_index.origin_protocol = LWSMPRO_FILE;
|
||||||
|
_lws_mnt_index.origin = _resources.index_dir ().c_str ();
|
||||||
|
|
||||||
|
// user defined surfaces in the user config directory
|
||||||
|
memset (&_lws_mnt_user, 0, sizeof (lws_http_mount));
|
||||||
|
_lws_mnt_user.mountpoint = "/user";
|
||||||
|
_lws_mnt_user.mountpoint_len = strlen (_lws_mnt_user.mountpoint);
|
||||||
|
_lws_mnt_user.origin_protocol = LWSMPRO_FILE;
|
||||||
|
_lws_mnt_user.origin = _resources.user_dir ().c_str ();
|
||||||
|
|
||||||
|
_lws_mnt_index.mount_next = &_lws_mnt_user;
|
||||||
|
|
||||||
memset (&_lws_info, 0, sizeof (lws_context_creation_info));
|
memset (&_lws_info, 0, sizeof (lws_context_creation_info));
|
||||||
_lws_info.port = WEBSOCKET_LISTEN_PORT;
|
_lws_info.port = WEBSOCKET_LISTEN_PORT;
|
||||||
_lws_info.protocols = _lws_proto;
|
_lws_info.protocols = _lws_proto;
|
||||||
|
_lws_info.mounts = &_lws_mnt_index;
|
||||||
_lws_info.uid = -1;
|
_lws_info.uid = -1;
|
||||||
_lws_info.gid = -1;
|
_lws_info.gid = -1;
|
||||||
_lws_info.user = this;
|
_lws_info.user = this;
|
||||||
|
|
@ -141,7 +162,7 @@ WebsocketsServer::update_all_clients (const NodeState& state, bool force)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::add_poll_fd (struct lws_pollargs* pa)
|
WebsocketsServer::add_poll_fd (struct lws_pollargs* pa)
|
||||||
{
|
{
|
||||||
/* fd can be SOCKET or int depending platform */
|
/* fd can be SOCKET or int depending platform */
|
||||||
|
|
@ -168,14 +189,16 @@ WebsocketsServer::add_poll_fd (struct lws_pollargs* pa)
|
||||||
ctx.wg_iosrc = Glib::RefPtr<Glib::IOSource> (0);
|
ctx.wg_iosrc = Glib::RefPtr<Glib::IOSource> (0);
|
||||||
|
|
||||||
_fd_ctx[fd] = ctx;
|
_fd_ctx[fd] = ctx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::mod_poll_fd (struct lws_pollargs* pa)
|
WebsocketsServer::mod_poll_fd (struct lws_pollargs* pa)
|
||||||
{
|
{
|
||||||
LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd);
|
LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd);
|
||||||
if (it == _fd_ctx.end ()) {
|
if (it == _fd_ctx.end ()) {
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->second.lws_pfd.events = pa->events;
|
it->second.lws_pfd.events = pa->events;
|
||||||
|
|
@ -189,7 +212,7 @@ WebsocketsServer::mod_poll_fd (struct lws_pollargs* pa)
|
||||||
|
|
||||||
if (it->second.wg_iosrc) {
|
if (it->second.wg_iosrc) {
|
||||||
/* already polling for write */
|
/* already polling for write */
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<IOSource> wg_iosrc = it->second.g_channel->create_watch (Glib::IO_OUT);
|
RefPtr<IOSource> wg_iosrc = it->second.g_channel->create_watch (Glib::IO_OUT);
|
||||||
|
|
@ -202,14 +225,16 @@ WebsocketsServer::mod_poll_fd (struct lws_pollargs* pa)
|
||||||
it->second.wg_iosrc = Glib::RefPtr<Glib::IOSource> (0);
|
it->second.wg_iosrc = Glib::RefPtr<Glib::IOSource> (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::del_poll_fd (struct lws_pollargs* pa)
|
WebsocketsServer::del_poll_fd (struct lws_pollargs* pa)
|
||||||
{
|
{
|
||||||
LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd);
|
LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd);
|
||||||
if (it == _fd_ctx.end ()) {
|
if (it == _fd_ctx.end ()) {
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->second.rg_iosrc->destroy ();
|
it->second.rg_iosrc->destroy ();
|
||||||
|
|
@ -219,30 +244,36 @@ WebsocketsServer::del_poll_fd (struct lws_pollargs* pa)
|
||||||
}
|
}
|
||||||
|
|
||||||
_fd_ctx.erase (it);
|
_fd_ctx.erase (it);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::add_client (Client wsi)
|
WebsocketsServer::add_client (Client wsi)
|
||||||
{
|
{
|
||||||
_client_ctx.emplace (wsi, ClientContext (wsi));
|
_client_ctx.emplace (wsi, ClientContext (wsi));
|
||||||
dispatcher ().update_all_nodes (wsi); // send all state
|
dispatcher ().update_all_nodes (wsi); // send all state
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::del_client (Client wsi)
|
WebsocketsServer::del_client (Client wsi)
|
||||||
{
|
{
|
||||||
ClientContextMap::iterator it = _client_ctx.find (wsi);
|
ClientContextMap::iterator it = _client_ctx.find (wsi);
|
||||||
|
|
||||||
if (it != _client_ctx.end ()) {
|
if (it != _client_ctx.end ()) {
|
||||||
_client_ctx.erase (it);
|
_client_ctx.erase (it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::recv_client (Client wsi, void* buf, size_t len)
|
WebsocketsServer::recv_client (Client wsi, void* buf, size_t len)
|
||||||
{
|
{
|
||||||
NodeStateMessage msg (buf, len);
|
NodeStateMessage msg (buf, len);
|
||||||
if (!msg.is_valid ()) {
|
if (!msg.is_valid ()) {
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
@ -251,26 +282,28 @@ WebsocketsServer::recv_client (Client wsi, void* buf, size_t len)
|
||||||
|
|
||||||
ClientContextMap::iterator it = _client_ctx.find (wsi);
|
ClientContextMap::iterator it = _client_ctx.find (wsi);
|
||||||
if (it == _client_ctx.end ()) {
|
if (it == _client_ctx.end ()) {
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* avoid echo */
|
/* avoid echo */
|
||||||
it->second.update_state (msg.state ());
|
it->second.update_state (msg.state ());
|
||||||
|
|
||||||
dispatcher ().dispatch (wsi, msg);
|
dispatcher ().dispatch (wsi, msg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::write_client (Client wsi)
|
WebsocketsServer::write_client (Client wsi)
|
||||||
{
|
{
|
||||||
ClientContextMap::iterator it = _client_ctx.find (wsi);
|
ClientContextMap::iterator it = _client_ctx.find (wsi);
|
||||||
if (it == _client_ctx.end ()) {
|
if (it == _client_ctx.end ()) {
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientOutputBuffer& pending = it->second.output_buf ();
|
ClientOutputBuffer& pending = it->second.output_buf ();
|
||||||
if (pending.empty ()) {
|
if (pending.empty ()) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* one lws_write() call per LWS_CALLBACK_SERVER_WRITEABLE callback */
|
/* one lws_write() call per LWS_CALLBACK_SERVER_WRITEABLE callback */
|
||||||
|
|
@ -279,13 +312,15 @@ WebsocketsServer::write_client (Client wsi)
|
||||||
pending.pop_front ();
|
pending.pop_front ();
|
||||||
|
|
||||||
unsigned char out_buf[1024];
|
unsigned char out_buf[1024];
|
||||||
size_t len = msg.serialize (out_buf + LWS_PRE, 1024 - LWS_PRE);
|
int len = msg.serialize (out_buf + LWS_PRE, 1024 - LWS_PRE);
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
std::cerr << "TX " << msg.state ().debug_str () << std::endl;
|
std::cerr << "TX " << msg.state ().debug_str () << std::endl;
|
||||||
#endif
|
#endif
|
||||||
lws_write (wsi, out_buf + LWS_PRE, len, LWS_WRITE_TEXT);
|
if (lws_write (wsi, out_buf + LWS_PRE, len, LWS_WRITE_TEXT) != len) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
PBD::error << "ArdourWebsockets: cannot serialize message" << endmsg;
|
PBD::error << "ArdourWebsockets: cannot serialize message" << endmsg;
|
||||||
}
|
}
|
||||||
|
|
@ -293,21 +328,84 @@ WebsocketsServer::write_client (Client wsi)
|
||||||
if (!pending.empty ()) {
|
if (!pending.empty ()) {
|
||||||
lws_callback_on_writable (wsi);
|
lws_callback_on_writable (wsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
WebsocketsServer::reject_http_client (Client wsi)
|
WebsocketsServer::send_index_hdr (Client wsi)
|
||||||
{
|
{
|
||||||
const char *html_body = "<p>This URL is not meant to be accessed via HTTP; for example using"
|
char url[1024];
|
||||||
" a web browser. Refer to Ardour documentation for further information.</p>";
|
|
||||||
lws_return_http_status (wsi, 404, html_body);
|
if (lws_hdr_copy (wsi, url, 1024, WSI_TOKEN_GET_URI) < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (url, "/index.json") != 0) {
|
||||||
|
lws_return_http_status (wsi, 404, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char out_buf[1024],
|
||||||
|
*start = out_buf,
|
||||||
|
*p = start,
|
||||||
|
*end = &out_buf[sizeof(out_buf) - 1];
|
||||||
|
|
||||||
|
#if LWS_LIBRARY_VERSION_MAJOR >= 3
|
||||||
|
lws_add_http_common_headers (wsi, HTTP_STATUS_OK, "application/json",
|
||||||
|
LWS_ILLEGAL_HTTP_CONTENT_LEN, &p, end);
|
||||||
|
lws_add_http_header_by_token (wsi, WSI_TOKEN_HTTP_CACHE_CONTROL,
|
||||||
|
reinterpret_cast<const unsigned char*> ("no-store"), 8, &p, end);
|
||||||
|
|
||||||
|
if (lws_finalize_write_http_header (wsi, start, &p, end) != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
lws_add_http_header_status (wsi, HTTP_STATUS_OK, &p, end);
|
||||||
|
lws_add_http_header_by_token (wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||||
|
reinterpret_cast<const unsigned char*> ("application/json"), 16, &p, end);
|
||||||
|
lws_add_http_header_by_token (wsi, WSI_TOKEN_CONNECTION,
|
||||||
|
reinterpret_cast<const unsigned char*> ("close"), 5, &p, end);
|
||||||
|
lws_add_http_header_by_token (wsi, WSI_TOKEN_HTTP_CACHE_CONTROL,
|
||||||
|
reinterpret_cast<const unsigned char*> ("no-store"), 8, &p, end);
|
||||||
|
lws_finalize_http_header (wsi, &p, end);
|
||||||
|
|
||||||
|
int len = p - start;
|
||||||
|
|
||||||
|
if (lws_write (wsi, start, len, LWS_WRITE_HTTP_HEADERS) != len) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lws_callback_on_writable (wsi);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
WebsocketsServer::send_index_body (Client wsi)
|
||||||
|
{
|
||||||
|
std::string index = _resources.scan ();
|
||||||
|
|
||||||
|
char body[MAX_INDEX_SIZE];
|
||||||
|
//lws_strncpy (body, index.c_str (), sizeof(body));
|
||||||
|
memset (body, 0, sizeof (body));
|
||||||
|
strncpy (body, index.c_str (), sizeof(body) - 1);
|
||||||
|
int len = strlen (body);
|
||||||
|
|
||||||
|
if (lws_write (wsi, reinterpret_cast<unsigned char*> (body), len, LWS_WRITE_HTTP) != len) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lws_http_transaction_completed (wsi);
|
||||||
|
|
||||||
|
return -1; // end connection
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WebsocketsServer::io_handler (Glib::IOCondition ioc, lws_sockfd_type fd)
|
WebsocketsServer::io_handler (Glib::IOCondition ioc, lws_sockfd_type fd)
|
||||||
{
|
{
|
||||||
/* IO_IN=1, IO_PRI=2, IO_ERR=8, IO_HUP=16 */
|
/* IO_IN=1, IO_PRI=2, IO_OUT=4, IO_ERR=8, IO_HUP=16 */
|
||||||
//printf ("io_handler ioc = %d\n", ioc);
|
|
||||||
|
|
||||||
LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (fd);
|
LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (fd);
|
||||||
if (it == _fd_ctx.end ()) {
|
if (it == _fd_ctx.end ()) {
|
||||||
|
|
@ -317,9 +415,7 @@ WebsocketsServer::io_handler (Glib::IOCondition ioc, lws_sockfd_type fd)
|
||||||
struct lws_pollfd* lws_pfd = &it->second.lws_pfd;
|
struct lws_pollfd* lws_pfd = &it->second.lws_pfd;
|
||||||
lws_pfd->revents = ioc_to_events (ioc);
|
lws_pfd->revents = ioc_to_events (ioc);
|
||||||
|
|
||||||
if (lws_service_fd (_lws_context, lws_pfd) < 0) {
|
lws_service_fd (_lws_context, lws_pfd);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ioc & (Glib::IO_IN | Glib::IO_OUT);
|
return ioc & (Glib::IO_IN | Glib::IO_OUT);
|
||||||
}
|
}
|
||||||
|
|
@ -368,41 +464,48 @@ WebsocketsServer::lws_callback (struct lws* wsi, enum lws_callback_reasons reaso
|
||||||
{
|
{
|
||||||
void* ctx_userdata = lws_context_user (lws_get_context (wsi));
|
void* ctx_userdata = lws_context_user (lws_get_context (wsi));
|
||||||
WebsocketsServer* server = static_cast<WebsocketsServer*> (ctx_userdata);
|
WebsocketsServer* server = static_cast<WebsocketsServer*> (ctx_userdata);
|
||||||
|
int rc;
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case LWS_CALLBACK_ADD_POLL_FD:
|
case LWS_CALLBACK_ADD_POLL_FD:
|
||||||
server->add_poll_fd (static_cast<struct lws_pollargs*> (in));
|
rc = server->add_poll_fd (static_cast<struct lws_pollargs*> (in));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
|
case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
|
||||||
server->mod_poll_fd (static_cast<struct lws_pollargs*> (in));
|
rc = server->mod_poll_fd (static_cast<struct lws_pollargs*> (in));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_DEL_POLL_FD:
|
case LWS_CALLBACK_DEL_POLL_FD:
|
||||||
server->del_poll_fd (static_cast<struct lws_pollargs*> (in));
|
rc = server->del_poll_fd (static_cast<struct lws_pollargs*> (in));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_ESTABLISHED:
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
server->add_client (wsi);
|
rc = server->add_client (wsi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_CLOSED:
|
case LWS_CALLBACK_CLOSED:
|
||||||
server->del_client (wsi);
|
rc = server->del_client (wsi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
server->recv_client (wsi, in, len);
|
rc = server->recv_client (wsi, in, len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||||
server->write_client (wsi);
|
rc = server->write_client (wsi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* will be called only if the requested url is not fulfilled
|
||||||
|
by the any of the mount configurations (index, builtin, user) */
|
||||||
case LWS_CALLBACK_HTTP:
|
case LWS_CALLBACK_HTTP:
|
||||||
server->reject_http_client (wsi);
|
rc = server->send_index_hdr (wsi);
|
||||||
return 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||||
|
rc = server->send_index_body (wsi);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_CLOSED_HTTP:
|
||||||
case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
|
case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
|
||||||
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
||||||
case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
|
case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
|
||||||
|
|
@ -421,20 +524,18 @@ WebsocketsServer::lws_callback (struct lws* wsi, enum lws_callback_reasons reaso
|
||||||
case LWS_CALLBACK_HTTP_CONFIRM_UPGRADE:
|
case LWS_CALLBACK_HTTP_CONFIRM_UPGRADE:
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
/* do nothing but keep connection alive */
|
||||||
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* TODO: handle HTTP connections.
|
|
||||||
* Serve static ctrl-surface pages, JS, CSS etc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/* see libwebsockets.h lws_callback_reasons */
|
/* see libwebsockets.h lws_callback_reasons */
|
||||||
std::cerr << "LWS: unhandled callback " << reason << std::endl;
|
std::cerr << "LWS: unhandled callback " << reason << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
rc = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#include "component.h"
|
#include "component.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
|
#include "resources.h"
|
||||||
|
|
||||||
#define WEBSOCKET_LISTEN_PORT 9000
|
#define WEBSOCKET_LISTEN_PORT 9000
|
||||||
|
|
||||||
|
|
@ -62,6 +63,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct lws_protocols _lws_proto[2];
|
struct lws_protocols _lws_proto[2];
|
||||||
|
struct lws_http_mount _lws_mnt_index;
|
||||||
|
struct lws_http_mount _lws_mnt_user;
|
||||||
struct lws_context_creation_info _lws_info;
|
struct lws_context_creation_info _lws_info;
|
||||||
struct lws_context* _lws_context;
|
struct lws_context* _lws_context;
|
||||||
|
|
||||||
|
|
@ -73,15 +76,18 @@ private:
|
||||||
typedef boost::unordered_map<Client, ClientContext> ClientContextMap;
|
typedef boost::unordered_map<Client, ClientContext> ClientContextMap;
|
||||||
ClientContextMap _client_ctx;
|
ClientContextMap _client_ctx;
|
||||||
|
|
||||||
void add_poll_fd (struct lws_pollargs*);
|
ServerResources _resources;
|
||||||
void mod_poll_fd (struct lws_pollargs*);
|
|
||||||
void del_poll_fd (struct lws_pollargs*);
|
|
||||||
|
|
||||||
void add_client (Client);
|
int add_poll_fd (struct lws_pollargs*);
|
||||||
void del_client (Client);
|
int mod_poll_fd (struct lws_pollargs*);
|
||||||
void recv_client (Client, void* buf, size_t len);
|
int del_poll_fd (struct lws_pollargs*);
|
||||||
void write_client (Client);
|
|
||||||
void reject_http_client (Client);
|
int add_client (Client);
|
||||||
|
int del_client (Client);
|
||||||
|
int recv_client (Client, void*, size_t);
|
||||||
|
int write_client (Client);
|
||||||
|
int send_index_hdr (Client);
|
||||||
|
int send_index_body (Client);
|
||||||
|
|
||||||
bool io_handler (Glib::IOCondition, lws_sockfd_type);
|
bool io_handler (Glib::IOCondition, lws_sockfd_type);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue