CPP_SRCS = $(shell find src -name \*.cpp)
CPP_DEPS = $(shell find src -name \*.h)
-LIBS = cairo freetype2 libavformat libavcodec libavutil libswresample libswscale
+LIBS = cairo freetype2 jsoncpp libavformat libavcodec libavutil libswresample libswscale libuv libwebsockets
main: $(CPP_SRCS) $(CPP_DEPS)
clang++ -g $(shell pkg-config --cflags --libs $(LIBS)) $(CPP_SRCS) -o $@
, surface(plane, linesize, CAIRO_FORMAT_ARGB32, width, height)
, ctx(surface.CreateContext())
, width(width)
- , height(height) {
+ , height(height)
+ , text("Hello") {
}
~Renderer() {
}
ctx.SetFontFace(font);
ctx.SetFontSize(16);
ctx.SetSourceRGB(1, 1, 1);
- ctx.ShowText("Hello");
+ ctx.ShowText(text.c_str());
surface.Flush();
}
+ void SetText(const std::string &t) {
+ text = t;
+ }
+
private:
freetype::Library ft;
int width;
int height;
+ std::string text;
+
};
}
namespace cairo {
+using TextExtends = cairo_text_extents_t;
+
class Context {
public:
cairo_fill(ctx);
}
+ void GetTextExtends(const char *text, TextExtends &extends) {
+ cairo_text_extents(ctx, text, &extends);
+ }
+
void MoveTo(double x, double y) {
cairo_move_to(ctx, x, y);
}
#include <cstdint>
#include <iostream>
#include <thread>
+#include <json/json.h>
extern "C" {
#include <libavcodec/codec_id.h>
#include "app/Renderer.h"
#include "app/Stream.h"
+#include "uv/Loop.h"
+#include "ws/Connection.h"
+#include "ws/Context.h"
namespace {
running = false;
}
+void ws_handler(void *user, const Json::Value &json) {
+ const std::string data_string = json["data"].asString();
+ Json::Value data;
+ Json::Reader json_reader;
+ json_reader.parse(data_string, data);
+ app::Renderer *renderer = static_cast<app::Renderer *>(user);
+ renderer->SetText(data["model"]["text"].asString());
+}
+
}
const int FPS = 60;
const char *URL = "rtmp://localhost/localhorsttv";
+ uv::Loop loop;
+
+ ws::Context wsctx(loop);
+ ws::Connection wsconn(wsctx.GetContext());
+
app::Stream stream(URL, WIDTH, HEIGHT, FPS);
running = true;
app::Renderer renderer(plane, linesize, WIDTH, HEIGHT);
+ wsconn.Subscribe("ChatBotLog", &ws_handler, &renderer);
+
stream.Start();
std::cout << std::endl;
while (running) {
+ loop.TryStep();
+
const int64_t target = stream.VideoElapsedMS();
const int64_t elapsed = stream.TimeElapsedMS();
const int64_t difference = target - elapsed;
stream.PrepareVideoFrame();
if (stream.GetVideoFrameCounter() > 0 && difference < 0) {
- std::cout << (difference / 1000.0) << "s behind schedule, dropping frame" << std::endl;
+ std::cout << (difference / -1000.0) << "s behind schedule, dropping frame" << std::endl;
} else {
renderer.RenderVideoFrame(stream.GetVideoFrameCounter(), target);
}
stream.PushAudioFrame();
}
- if (stream.GetVideoFrameCounter() % 60 == 59) {
- std::cout << "rendered: " << (target / 1000.0) << "s, elapsed: " << (elapsed / 1000.0) << "s, difference: " << (difference / 1000.0) << 's' << std::endl;
- }
+ //if (stream.GetVideoFrameCounter() % 60 == 59) {
+ // std::cout << "rendered: " << (target / 1000.0) << "s, elapsed: " << (elapsed / 1000.0) << "s, difference: " << (difference / 1000.0) << 's' << std::endl;
+ //}
if (difference > 3000) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::cout << std::endl;
+ wsctx.Shutdown();
stream.Finish();
return 0;
--- /dev/null
+#ifndef TEST_UV_ERROR_H_
+#define TEST_UV_ERROR_H_
+
+#include <stdexcept>
+#include <string>
+
+#include <uv.h>
+
+namespace {
+std::string uv_make_message(const std::string &msg, int status) {
+ return msg + ": " + std::string(uv_strerror(status));
+}
+}
+
+namespace uv {
+
+class Error: public std::runtime_error {
+
+public:
+ Error(const std::string &msg, int status): std::runtime_error(uv_make_message(msg, status)) {
+ }
+ ~Error() {
+ }
+
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef TEST_UV_LOOP_H_
+#define TEST_UV_LOOP_H_
+
+#include <uv.h>
+
+#include "Error.h"
+
+namespace uv {
+
+class Loop {
+
+public:
+ Loop() {
+ int res = uv_loop_init(&loop);
+ if (res < 0) {
+ throw Error("failed to initialize loop", res);
+ }
+ }
+ ~Loop() {
+ uv_loop_close(&loop);
+ }
+
+ Loop(const Loop &) = delete;
+ Loop &operator =(const Loop &) = delete;
+
+public:
+ uv_loop_t *GetLoop() {
+ return &loop;
+ }
+
+public:
+ void Run() {
+ uv_run(&loop, UV_RUN_DEFAULT);
+ }
+ void Step() {
+ uv_run(&loop, UV_RUN_ONCE);
+ }
+ void TryStep() {
+ uv_run(&loop, UV_RUN_NOWAIT);
+ }
+
+private:
+ uv_loop_t loop;
+
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef TEST_UV_LOOP_H_
+#define TEST_UV_LOOP_H_
+
+#include <uv.h>
+
+#include "Error.h"
+
+namespace uv {
+
+class Signal {
+
+public:
+ Signal(uv_loop_t &loop, int sig, void *data, void (*handler)(void *, int)): handler(handler), data(data) {
+ int res = uv_signal_init(&loop, &signal);
+ if (res < 0) {
+ throw Error("failed to initialize loop", res);
+ }
+ res = uv_signal_start(&signal, &signal_handler, sig);
+ if (res < 0) {
+ throw Error("failed to install signal handler", res);
+ }
+ signal.data = this;
+ }
+ ~Signal() {
+ uv_signal_stop(&signal);
+ }
+
+ Signal(const Signal &) = delete;
+ Signal &operator =(const Signal &) = delete;
+
+private:
+ static void signal_handler(uv_signal_t *sig, int signum) {
+ Signal *signal = static_cast<Signal *>(sig->data);
+ signal->handler(signal->data, signum);
+ }
+
+private:
+ uv_signal_t signal;
+ void (*handler)(void *, int);
+ void *data;
+
+};
+
+}
+
+#endif
--- /dev/null
+#include "Connection.h"
+
+#include <iostream>
+#include <libwebsockets.h>
+#include <stdexcept>
+
+#include "io.h"
+
+namespace ws {
+
+Connection::Connection(lws_context *ctx)
+: info{0}, wsi(nullptr), connected(false) {
+ info.context = ctx;
+ info.opaque_user_data = this;
+ // wss://alttp.localhorst.tv/app/nkmbiabdrtqnd8t19txs?protocol=7&client=js&version=8.3.0&flash=false
+ info.address = "alttp.localhorst.tv";
+ info.port = 443;
+ info.ssl_connection = 1;
+ info.path = "/app/nkmbiabdrtqnd8t19txs?protocol=7&client=js&version=8.3.0&flash=false";
+ info.host = "alttp.localhorst.tv";
+ info.origin = "test";
+ info.protocol = "pusher";
+ info.ietf_version_or_minus_one = -1;
+ info.userdata = this;
+ info.pwsi = &wsi;
+ wsi = lws_client_connect_via_info(&info);
+ if (!wsi) {
+ throw std::runtime_error("failed to connect client");
+ }
+ lws_set_timer_usecs(wsi, 30000000);
+ out_buffer.insert(0, LWS_PRE, '\0');
+}
+
+int Connection::ProtoCallback(lws_callback_reasons reason, void *in, size_t len) {
+ switch (reason) {
+ case LWS_CALLBACK_CLIENT_ESTABLISHED:
+ connected = true;
+ if (out_buffer.length() > LWS_PRE) {
+ lws_callback_on_writable(wsi);
+ }
+ break;
+ case LWS_CALLBACK_CLIENT_CLOSED:
+ connected = false;
+ break;
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ if (lws_is_first_fragment(wsi)) {
+ in_buffer.clear();
+ }
+ in_buffer.append(static_cast<const char *>(in), len);
+ if (lws_is_final_fragment(wsi)) {
+ HandleMessage(in_buffer);
+ }
+ break;
+ case LWS_CALLBACK_CLIENT_WRITEABLE:
+ if (out_buffer.length() > LWS_PRE) {
+ int res = lws_write(wsi, reinterpret_cast<unsigned char *>(&out_buffer[0]) + LWS_PRE, out_buffer.length() - LWS_PRE, LWS_WRITE_TEXT);
+ if (res > 0) {
+ out_buffer.erase(LWS_PRE, res);
+ }
+ break;
+ }
+ case LWS_CALLBACK_TIMER:
+ Ping();
+ lws_set_timer_usecs(wsi, 30000000);
+ break;
+ case LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL:
+ case LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL:
+ case LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL:
+ case LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL:
+ case LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION:
+ case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
+ case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
+ case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
+ case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
+ case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
+ case LWS_CALLBACK_WSI_CREATE:
+ break;
+ default:
+ std::cout << "unhandled connection proto callback, reason: " << reason << ", in: " << in << ", len: " << len << std::endl;
+ if (in && len) {
+ std::cout << " DATA: \"" << std::string(static_cast<const char *>(in), len) << '"' << std::endl;
+ }
+ break;
+ }
+ return 0;
+}
+
+}
--- /dev/null
+#ifndef TEST_WS_CONNECTION_H_
+#define TEST_WS_CONNECTION_H_
+
+#include "json/reader.h"
+#include "json/value.h"
+#include "json/writer.h"
+#include <cstring>
+#include <map>
+#include <string>
+
+#include <json/json.h>
+#include <libwebsockets.h>
+#include <vector>
+
+namespace ws {
+
+class Connection {
+
+public:
+ explicit Connection(lws_context *ctx);
+ ~Connection() {
+ }
+
+ Connection(const Connection &) = delete;
+ Connection &operator =(const Connection &) = delete;
+
+private:
+ struct Callback {
+ void *user;
+ void (*callback)(void *, const Json::Value &);
+ void Call(const Json::Value &val) const {
+ (*callback)(user, val);
+ }
+ };
+
+public:
+ void Ping() {
+ SendMessage("{\"event\":\"pusher:ping\"}");
+ }
+
+ void Subscribe(const std::string &chan, void (*callback)(void *, const Json::Value &), void *user = nullptr) {
+ callbacks[chan].push_back({ user, callback });
+ Json::Value json;
+ json["event"] = "pusher:subscribe";
+ json["data"]["channel"] = chan;
+ SendMessage(json);
+ }
+
+ void SendMessage(const Json::Value &json) {
+ SendMessage(json_writer.write(json));
+ }
+
+ void SendMessage(const std::string &msg) {
+ out_buffer.append(msg);
+ lws_callback_on_writable(wsi);
+ }
+
+ void SendMessage(const char *msg) {
+ out_buffer.append(msg);
+ lws_callback_on_writable(wsi);
+ }
+
+public:
+ int ProtoCallback(lws_callback_reasons reason, void *in, size_t len);
+
+ void HandleMessage(const std::string &msg) {
+ Json::Value json;
+ json_reader.parse(msg, json);
+ const std::string channel = json["channel"].asString();
+ for (const Callback &callback : callbacks[channel]) {
+ callback.Call(json);
+ }
+ }
+
+private:
+ lws_client_connect_info info;
+ lws *wsi;
+ bool connected;
+
+ std::string in_buffer;
+ std::string out_buffer;
+
+ Json::Reader json_reader;
+ Json::FastWriter json_writer;
+ std::map<std::string, std::vector<Callback>> callbacks;
+
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef TEST_WS_CONTEXT_H_
+#define TEST_WS_CONTEXT_H_
+
+#include <cstdio>
+#include <iostream>
+#include <stdexcept>
+#include <string>
+
+#include <libwebsockets.h>
+
+#include "Connection.h"
+#include "io.h"
+#include "../uv/Loop.h"
+
+namespace ws {
+
+class Context {
+
+public:
+ explicit Context(uv::Loop &loop): info{0}, ctx(nullptr), proto{0}, protos{0}, loops{0} {
+ //lws_set_log_level(LLL_USER|LLL_ERR|LLL_WARN|LLL_NOTICE|LLL_INFO|LLL_DEBUG, nullptr);
+ proto.name = "pusher";
+ proto.callback = &proto_callback;
+ proto.user = this;
+ proto.rx_buffer_size = BUFSIZ;
+ proto.tx_packet_size = BUFSIZ;
+ protos[0] = &proto;
+ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_LIBUV;
+ info.port = CONTEXT_PORT_NO_LISTEN;
+ info.pprotocols = protos;
+ loops[0] = loop.GetLoop();
+ info.foreign_loops = loops;
+ ctx = lws_create_context(&info);
+ if (!ctx) {
+ throw std::runtime_error("failed to create context");
+ }
+ }
+ ~Context() {
+ lws_context_destroy(ctx);
+ }
+
+ Context(const Context &) = delete;
+ Context &operator =(const Context &) = delete;
+
+public:
+ lws_context *GetContext() {
+ return ctx;
+ }
+
+ void Shutdown() {
+ lws_context_deprecate(ctx, nullptr);
+ }
+
+private:
+ static int proto_callback(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len) {
+ void *user_data = lws_wsi_user(wsi);
+ if (user_data) {
+ Connection *conn = static_cast<Connection *>(user_data);
+ return conn->ProtoCallback(reason, in, len);
+ }
+ Context *c = static_cast<Context *>(user);
+ return c->ProtoCallback(reason, in, len);
+ }
+
+ int ProtoCallback(lws_callback_reasons reason, void *in, size_t len) {
+ switch (reason) {
+ case LWS_CALLBACK_PROTOCOL_INIT:
+ case LWS_CALLBACK_PROTOCOL_DESTROY:
+ case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
+ break;
+ default:
+ std::cout << "unhandled generic proto callback, reason: " << reason << ", in: " << in << ", len: " << len << std::endl;
+ if (in && len) {
+ std::cout << " DATA: \"" << std::string(static_cast<const char *>(in), len) << '"' << std::endl;
+ }
+ break;
+ }
+ return 0;
+ }
+
+private:
+ lws_context_creation_info info;
+ lws_protocols proto;
+ const lws_protocols *protos[2];
+ void *loops[2];
+ lws_context *ctx;
+
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef TEST_WS_IO_H_
+#define TEST_WS_IO_H_
+
+#include <ostream>
+
+extern "C" {
+#include <libwebsockets.h>
+}
+
+namespace std {
+inline std::ostream &operator <<(std::ostream &out, lws_callback_reasons r) {
+ switch (r) {
+ case LWS_CALLBACK_PROTOCOL_INIT:
+ out << "protocol init";
+ break;
+ case LWS_CALLBACK_PROTOCOL_DESTROY:
+ out << "protocol destroy";
+ break;
+ case LWS_CALLBACK_WSI_CREATE:
+ out << "wsi create";
+ break;
+ case LWS_CALLBACK_WSI_DESTROY:
+ out << "wsi destroy";
+ break;
+ case LWS_CALLBACK_WSI_TX_CREDIT_GET:
+ out << "wsi tx credit get";
+ break;
+
+ case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
+ out << "load extra client certs";
+ break;
+ case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS:
+ out << "load extra server certs";
+ break;
+ case LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION:
+ out << "perform server cert verify";
+ break;
+ case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
+ out << "perform client cert verify";
+ break;
+ case LWS_CALLBACK_SSL_INFO:
+ out << "ssl info";
+ break;
+
+ case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
+ out << "new client instance";
+ break;
+ case LWS_CALLBACK_HTTP:
+ out << "http request";
+ break;
+ case LWS_CALLBACK_HTTP_BODY:
+ out << "http body";
+ break;
+ case LWS_CALLBACK_HTTP_BODY_COMPLETION:
+ out << "http body complete";
+ break;
+ case LWS_CALLBACK_HTTP_FILE_COMPLETION:
+ out << "http file complete";
+ break;
+ case LWS_CALLBACK_HTTP_WRITEABLE:
+ out << "http writable";
+ break;
+ case LWS_CALLBACK_CLOSED_HTTP:
+ out << "http closed";
+ break;
+ case LWS_CALLBACK_FILTER_HTTP_CONNECTION:
+ out << "filter http connection";
+ break;
+ case LWS_CALLBACK_ADD_HEADERS:
+ out << "add headers";
+ break;
+ case LWS_CALLBACK_VERIFY_BASIC_AUTHORIZATION:
+ out << "verify basic auth";
+ break;
+ case LWS_CALLBACK_CHECK_ACCESS_RIGHTS:
+ out << "check access rights";
+ break;
+ case LWS_CALLBACK_PROCESS_HTML:
+ out << "process html";
+ break;
+ case LWS_CALLBACK_HTTP_BIND_PROTOCOL:
+ out << "http bind protocol";
+ break;
+ case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
+ out << "http drop protocol";
+ break;
+ case LWS_CALLBACK_HTTP_CONFIRM_UPGRADE:
+ out << "http confirm upgrade";
+ break;
+
+ case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
+ out << "http client connection established";
+ break;
+ case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
+ out << "http client connection closed";
+ break;
+ case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
+ out << "http client read";
+ break;
+ case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
+ out << "http client completed";
+ break;
+ case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
+ out << "http client writable";
+ break;
+ case LWS_CALLBACK_CLIENT_HTTP_REDIRECT:
+ out << "http client redirect";
+ break;
+ case LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL:
+ out << "http client bind protocol";
+ break;
+ case LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL:
+ out << "http client drop protocol";
+ break;
+
+ case LWS_CALLBACK_ESTABLISHED:
+ out << "connection established";
+ break;
+ case LWS_CALLBACK_CLOSED:
+ out << "connection closed";
+ break;
+ case LWS_CALLBACK_SERVER_WRITEABLE:
+ out << "server writable";
+ break;
+ case LWS_CALLBACK_RECEIVE:
+ out << "receive";
+ break;
+ case LWS_CALLBACK_RECEIVE_PONG:
+ out << "receive pong";
+ break;
+ case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
+ out << "peer initiated close";
+ break;
+ case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
+ out << "filter protocol connection";
+ break;
+ case LWS_CALLBACK_CONFIRM_EXTENSION_OKAY:
+ out << "confirm extension ok";
+ break;
+ case LWS_CALLBACK_WS_SERVER_BIND_PROTOCOL:
+ out << "ws server bind protocol";
+ break;
+ case LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL:
+ out << "ws server drop protocol";
+ break;
+
+ case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
+ out << "client connection error";
+ break;
+ case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
+ out << "client filter pre establish";
+ break;
+ case LWS_CALLBACK_CLIENT_ESTABLISHED:
+ out << "client connection established";
+ break;
+ case LWS_CALLBACK_CLIENT_CLOSED:
+ out << "client connection closed";
+ break;
+ case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
+ out << "client append handshake header";
+ break;
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ out << "client receive";
+ break;
+ case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
+ out << "client receive pong";
+ break;
+ case LWS_CALLBACK_CLIENT_WRITEABLE:
+ out << "client writable";
+ break;
+ case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
+ out << "client confirm extension suppported";
+ break;
+ case LWS_CALLBACK_WS_EXT_DEFAULTS:
+ out << "ws ext defaults";
+ break;
+ case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
+ out << "filter network connection";
+ break;
+ case LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL:
+ out << "ws client bind protocol";
+ break;
+ case LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL:
+ out << "ws client drop protocol";
+ break;
+
+ case LWS_CALLBACK_GET_THREAD_ID:
+ out << "get thread id";
+ break;
+ case LWS_CALLBACK_ADD_POLL_FD:
+ out << "add poll fd";
+ break;
+ case LWS_CALLBACK_DEL_POLL_FD:
+ out << "del poll fd";
+ break;
+ case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
+ out << "change mode poll fd";
+ break;
+ case LWS_CALLBACK_LOCK_POLL:
+ out << "lock poll";
+ break;
+ case LWS_CALLBACK_UNLOCK_POLL:
+ out << "unlock poll";
+ break;
+
+ case LWS_CALLBACK_CGI:
+ out << "cgi";
+ break;
+ case LWS_CALLBACK_CGI_TERMINATED:
+ out << "cgi terminated";
+ break;
+ case LWS_CALLBACK_CGI_STDIN_DATA:
+ out << "cgi stdin data";
+ break;
+ case LWS_CALLBACK_CGI_STDIN_COMPLETED:
+ out << "cgi stdin completed";
+ break;
+ case LWS_CALLBACK_CGI_PROCESS_ATTACH:
+ out << "cgi process attach";
+ break;
+
+ case LWS_CALLBACK_SESSION_INFO:
+ out << "session info";
+ break;
+ case LWS_CALLBACK_GS_EVENT:
+ out << "gs event";
+ break;
+ case LWS_CALLBACK_HTTP_PMO:
+ out << "http pmo";
+ break;
+
+ case LWS_CALLBACK_RAW_PROXY_CLI_RX:
+ out << "raw proxy cli rx";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_SRV_RX:
+ out << "raw proxy srv rx";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_CLI_CLOSE:
+ out << "raw proxy cli close";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_SRV_CLOSE:
+ out << "raw proxy srv close";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_CLI_WRITEABLE:
+ out << "raw proxy cli writable";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_SRV_WRITEABLE:
+ out << "raw proxy srv writable";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_CLI_ADOPT:
+ out << "raw proxy cli adopt";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_SRV_ADOPT:
+ out << "raw proxy srv adopt";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_CLI_BIND_PROTOCOL:
+ out << "raw proxy cli bind protocol";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_SRV_BIND_PROTOCOL:
+ out << "raw proxy srv bind protocol";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_CLI_DROP_PROTOCOL:
+ out << "raw proxy cli drop protocol";
+ break;
+ case LWS_CALLBACK_RAW_PROXY_SRV_DROP_PROTOCOL:
+ out << "raw proxy srv drop protocol";
+ break;
+
+ case LWS_CALLBACK_RAW_RX:
+ out << "raw rx";
+ break;
+ case LWS_CALLBACK_RAW_CLOSE:
+ out << "raw close";
+ break;
+ case LWS_CALLBACK_RAW_WRITEABLE:
+ out << "raw writable";
+ break;
+ case LWS_CALLBACK_RAW_ADOPT:
+ out << "raw adopt";
+ break;
+ case LWS_CALLBACK_RAW_CONNECTED:
+ out << "raw connected";
+ break;
+ case LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL:
+ out << "raw skt bind protocol";
+ break;
+ case LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL:
+ out << "raw skt drop protocol";
+ break;
+
+ case LWS_CALLBACK_RAW_ADOPT_FILE:
+ out << "raw adopt file";
+ break;
+ case LWS_CALLBACK_RAW_RX_FILE:
+ out << "raw rx file";
+ break;
+ case LWS_CALLBACK_RAW_WRITEABLE_FILE:
+ out << "raw writable file";
+ break;
+ case LWS_CALLBACK_RAW_CLOSE_FILE:
+ out << "raw close file";
+ break;
+ case LWS_CALLBACK_RAW_FILE_BIND_PROTOCOL:
+ out << "raw file bind protocol";
+ break;
+ case LWS_CALLBACK_RAW_FILE_DROP_PROTOCOL:
+ out << "raw file drop protocol";
+ break;
+
+ case LWS_CALLBACK_TIMER:
+ out << "timer";
+ break;
+ case LWS_CALLBACK_EVENT_WAIT_CANCELLED:
+ out << "event wait cancelled";
+ break;
+ case LWS_CALLBACK_CHILD_CLOSING:
+ out << "child closing";
+ break;
+
+ case LWS_CALLBACK_VHOST_CERT_AGING:
+ out << "vhost cert aging";
+ break;
+ case LWS_CALLBACK_VHOST_CERT_UPDATE:
+ out << "vhost cert update";
+ break;
+
+ case LWS_CALLBACK_MQTT_NEW_CLIENT_INSTANTIATED:
+ out << "mqtt new client instantiated";
+ break;
+ case LWS_CALLBACK_MQTT_IDLE:
+ out << "mqtt idle";
+ break;
+ case LWS_CALLBACK_MQTT_CLIENT_ESTABLISHED:
+ out << "mqtt client established";
+ break;
+ case LWS_CALLBACK_MQTT_SUBSCRIBED:
+ out << "mqtt subscribed";
+ break;
+ case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE:
+ out << "mqtt client writable";
+ break;
+ case LWS_CALLBACK_MQTT_CLIENT_RX:
+ out << "mqtt client rx";
+ break;
+ case LWS_CALLBACK_MQTT_UNSUBSCRIBED:
+ out << "mqtt unsubscribed";
+ break;
+ case LWS_CALLBACK_MQTT_DROP_PROTOCOL:
+ out << "mqtt drop protocol";
+ break;
+ case LWS_CALLBACK_MQTT_CLIENT_CLOSED:
+ out << "mqtt client closed";
+ break;
+ case LWS_CALLBACK_MQTT_ACK:
+ out << "mqtt ack";
+ break;
+ case LWS_CALLBACK_MQTT_RESEND:
+ out << "mqtt resend";
+ break;
+
+ default:
+ out << "unknown reason";
+ break;
+ }
+ out << " (" << int(r) << ')';
+ return out;
+}
+}
+
+#endif