From 29812801f269bf0451beac28fe66bf71c904f701 Mon Sep 17 00:00:00 2001 From: Takeshi Yoshino <4511440+tyoshino@users.noreply.github.com> Date: Mon, 2 Mar 2026 03:30:46 +0000 Subject: [PATCH 1/2] comment --- wish/cpp/src/wish_handler.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wish/cpp/src/wish_handler.h b/wish/cpp/src/wish_handler.h index 4ad6b22..bc09a85 100644 --- a/wish/cpp/src/wish_handler.h +++ b/wish/cpp/src/wish_handler.h @@ -15,6 +15,11 @@ struct wslay_event_context; struct wslay_event_on_msg_recv_arg; } +// WishHandler implements the WiSH Procotol defined at https://datatracker.ietf.org/doc/html/draft-yoshino-wish +// +// It manages the lifecycle of a single WiSH connection, including the initial HTTP handshake and subsequent message framing/parsing. +// +// It uses libevent's bufferevent for async I/O. The underlying transport should be provided through it. class WishHandler { public: using MessageCallback = From 8a9bd568e293086e14a0814af66cbf9e51d44b45 Mon Sep 17 00:00:00 2001 From: Takeshi Yoshino <4511440+tyoshino@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:23:41 +0000 Subject: [PATCH 2/2] split --- wish/cpp/CMakeLists.txt | 15 ++- wish/cpp/README.md | 9 ++ wish/cpp/examples/benchmark_client.cc | 48 ++++++++++ wish/cpp/examples/client.cc | 80 ---------------- wish/cpp/examples/echo_server.cc | 64 +++++++++++++ wish/cpp/examples/hello_client.cc | 50 ++++++++++ wish/cpp/examples/server.cc | 128 -------------------------- wish/cpp/src/tls_client.cc | 107 +++++++++++++++++++++ wish/cpp/src/tls_client.h | 46 +++++++++ wish/cpp/src/tls_server.cc | 105 +++++++++++++++++++++ wish/cpp/src/tls_server.h | 43 +++++++++ wish/cpp/src/wish_handler.cc | 12 ++- wish/cpp/src/wish_handler.h | 8 +- 13 files changed, 498 insertions(+), 217 deletions(-) create mode 100644 wish/cpp/README.md create mode 100644 wish/cpp/examples/benchmark_client.cc delete mode 100644 wish/cpp/examples/client.cc create mode 100644 wish/cpp/examples/echo_server.cc create mode 100644 wish/cpp/examples/hello_client.cc delete mode 100644 wish/cpp/examples/server.cc create mode 100644 wish/cpp/src/tls_client.cc create mode 100644 wish/cpp/src/tls_client.h create mode 100644 wish/cpp/src/tls_server.cc create mode 100644 wish/cpp/src/tls_server.h diff --git a/wish/cpp/CMakeLists.txt b/wish/cpp/CMakeLists.txt index f24890c..2b9861d 100644 --- a/wish/cpp/CMakeLists.txt +++ b/wish/cpp/CMakeLists.txt @@ -51,12 +51,19 @@ add_library(wish_handler ${libevent_SOURCE_DIR}/bufferevent_ssl.c src/tls_context.cc src/tls_context.h + src/tls_server.cc + src/tls_server.h + src/tls_client.cc + src/tls_client.h ) # BoringSSL targets: ssl and crypto target_link_libraries(wish_handler wslay event ssl crypto) -add_executable(wish-server examples/server.cc) -target_link_libraries(wish-server wish_handler) +add_executable(echo_server examples/echo_server.cc) +target_link_libraries(echo_server wish_handler) -add_executable(wish-client examples/client.cc) -target_link_libraries(wish-client wish_handler) +add_executable(hello_client examples/hello_client.cc) +target_link_libraries(hello_client wish_handler) + +add_executable(benchmark_client examples/benchmark_client.cc) +target_link_libraries(benchmark_client wish_handler) diff --git a/wish/cpp/README.md b/wish/cpp/README.md new file mode 100644 index 0000000..00cb9d4 --- /dev/null +++ b/wish/cpp/README.md @@ -0,0 +1,9 @@ +# WiSH C++ Implementation + +This directory contains a C++ implementation of WiSH protocol together with a thin TLS stack enabling mTLS. + +# Development Conventions + +## Coding style + +We basically follow [Google C++ style guide](https://google.github.io/styleguide/cppguide.html). diff --git a/wish/cpp/examples/benchmark_client.cc b/wish/cpp/examples/benchmark_client.cc new file mode 100644 index 0000000..ccf17a4 --- /dev/null +++ b/wish/cpp/examples/benchmark_client.cc @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +#include "../src/tls_client.h" +#include "../src/wish_handler.h" + +int main() { + TlsClient client("../certs/ca.crt", "../certs/client.crt", + "../certs/client.key", "127.0.0.1", 8080); + + if (!client.Init()) { + std::cerr << "Failed to initialize client" << std::endl; + return 1; + } + + const int kTotalMessages = 1000; + int messages_received = 0; + auto start_time = std::chrono::high_resolution_clock::now(); + + client.SetOnOpen([&start_time, kTotalMessages](WishHandler* handler) { + std::cout << "Connected! Starting benchmark..." << std::endl; + + start_time = std::chrono::high_resolution_clock::now(); + + for (int i = 0; i < kTotalMessages; ++i) { + handler->SendText("Benchmark message " + std::to_string(i)); + } + }); + + client.SetOnMessage([&messages_received, kTotalMessages, + &start_time](uint8_t opcode, const std::string& msg) { + messages_received++; + if (messages_received == kTotalMessages) { + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast( + end_time - start_time); + std::cout << "Benchmark complete: Received " << kTotalMessages + << " messages in " << duration.count() << " ms." << std::endl; + exit(0); + } + }); + + client.Run(); + + return 0; +} diff --git a/wish/cpp/examples/client.cc b/wish/cpp/examples/client.cc deleted file mode 100644 index 41ac36e..0000000 --- a/wish/cpp/examples/client.cc +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include - -// To use BoringSSL -#define EVENT__HAVE_OPENSSL 1 -#include -#include -#include -#include -#include - -#include "../src/tls_context.h" -#include "../src/wish_handler.h" - -int main() { - // Initialize BoringSSL - SSL_library_init(); - SSL_load_error_strings(); - - TlsContext tls_ctx; - tls_ctx.set_ca_file("../certs/ca.crt"); - tls_ctx.set_certificate_file("../certs/client.crt"); - tls_ctx.set_private_key_file("../certs/client.key"); - if (!tls_ctx.Init(false)) { - std::cerr << "Failed to init TLS context" << std::endl; - return 1; - } - struct event_base *base = event_base_new(); - if (!base) { - std::cerr << "Could not initialize libevent!" << std::endl; - return 1; - } - - struct evdns_base *dns_base = evdns_base_new(base, 1); - if (!dns_base) { - std::cerr << "Could not initialize dns!" << std::endl; - return 1; - } - - SSL *ssl = SSL_new(tls_ctx.ssl_ctx()); - struct bufferevent *bev = - bufferevent_openssl_socket_new(base, -1, ssl, BUFFEREVENT_SSL_CONNECTING, - BEV_OPT_CLOSE_ON_FREE); - if (!bev) { - std::cerr << "Could not create bufferevent!" << std::endl; - return 1; - } - - if (bufferevent_socket_connect_hostname(bev, dns_base, AF_INET, "127.0.0.1", - 8080) < 0) { - std::cerr << "Could not connect!" << std::endl; - return 1; - } - - // Handler manages its own lifecycle (deletes itself on close) - WishHandler *handler = new WishHandler(bev, false); // is_server = false - - handler->SetOnOpen([handler]() - { - std::cout << "Connected and Handshake Complete!" << std::endl; - - handler->SendText("Hello WiSH Text!"); - handler->SendBinary("Hello WiSH Binary!"); - handler->SendMetadata(true, "Hello WiSH Metadata!"); }); - - handler->SetOnMessage([](uint8_t opcode, const std::string &msg) - { std::cout << "Server says [opcode " << (int)opcode << "]: " << msg - << std::endl; }); - - handler->Start(); - - std::cout << "Client running..." << std::endl; - event_base_dispatch(base); - - evdns_base_free(dns_base, 0); - event_base_free(base); - - return 0; -} diff --git a/wish/cpp/examples/echo_server.cc b/wish/cpp/examples/echo_server.cc new file mode 100644 index 0000000..2d645eb --- /dev/null +++ b/wish/cpp/examples/echo_server.cc @@ -0,0 +1,64 @@ +#include +#include + +#include "../src/tls_server.h" +#include "../src/wish_handler.h" + +int main(int argc, char** argv) { + int port = 8080; + + TlsServer server("../certs/ca.crt", "../certs/server.crt", + "../certs/server.key", port); + + if (!server.Init()) { + std::cerr << "Failed to initialize server" << std::endl; + return 1; + } + + server.SetOnConnection([](struct bufferevent* bev) { + std::cout << "Client connected." << std::endl; + + WishHandler* handler = new WishHandler(bev, true); + + handler->SetOnMessage([handler](uint8_t opcode, const std::string& msg) { + std::string type; + switch (opcode) { + case WISH_OPCODE_TEXT: + type = "TEXT"; + break; + case WISH_OPCODE_BINARY: + type = "BINARY"; + break; + case WISH_OPCODE_TEXT_METADATA: + type = "TEXT_METADATA"; + break; + case WISH_OPCODE_BINARY_METADATA: + type = "BINARY_METADATA"; + break; + default: + type = "UNKNOWN(" + std::to_string(opcode) + ")"; + break; + } + std::cout << "Received [" << type << "]: " << msg << std::endl; + + // Echo back + if (opcode == WISH_OPCODE_TEXT) + handler->SendText(msg); + else if (opcode == WISH_OPCODE_BINARY) + handler->SendBinary(msg); + else if (opcode == WISH_OPCODE_TEXT_METADATA) + handler->SendTextMetadata(msg); + else if (opcode == WISH_OPCODE_BINARY_METADATA) + handler->SendBinaryMetadata(msg); + else { + std::cerr << "Unknown opcode, cannot echo." << std::endl; + } + }); + + handler->Start(); + }); + + server.Run(); + + return 0; +} diff --git a/wish/cpp/examples/hello_client.cc b/wish/cpp/examples/hello_client.cc new file mode 100644 index 0000000..2b9ea94 --- /dev/null +++ b/wish/cpp/examples/hello_client.cc @@ -0,0 +1,50 @@ +#include +#include + +#include "../src/tls_client.h" +#include "../src/wish_handler.h" + +int main() { + TlsClient client("../certs/ca.crt", "../certs/client.crt", + "../certs/client.key", "127.0.0.1", 8080); + + if (!client.Init()) { + std::cerr << "Failed to initialize client" << std::endl; + return 1; + } + + client.SetOnOpen([](WishHandler* handler) { + std::cout << "Connected and Handshake Complete!" << std::endl; + + handler->SendText("Hello WiSH Text!"); + handler->SendBinary("Hello WiSH Binary!"); + handler->SendTextMetadata("Hello WiSH Metadata!"); + handler->SendBinaryMetadata("Hello WiSH Binary Metadata!"); + }); + + client.SetOnMessage([](uint8_t opcode, const std::string& msg) { + std::string type; + switch (opcode) { + case WISH_OPCODE_TEXT: + type = "TEXT"; + break; + case WISH_OPCODE_BINARY: + type = "BINARY"; + break; + case WISH_OPCODE_TEXT_METADATA: + type = "TEXT_METADATA"; + break; + case WISH_OPCODE_BINARY_METADATA: + type = "BINARY_METADATA"; + break; + default: + type = "UNKNOWN(" + std::to_string(opcode) + ")"; + break; + } + std::cout << "Server says [" << type << "]: " << msg << std::endl; + }); + + client.Run(); + + return 0; +} diff --git a/wish/cpp/examples/server.cc b/wish/cpp/examples/server.cc deleted file mode 100644 index 1a9d5f4..0000000 --- a/wish/cpp/examples/server.cc +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include -#include -#include // Added for std::to_string - -// To use BoringSSL -#define EVENT__HAVE_OPENSSL 1 -#include -#include -#include -#include -#include - -#include "../src/tls_context.h" -#include "../src/wish_handler.h" - -void accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, - struct sockaddr *address, int socklen, void *ctx) { - struct event_base *base = evconnlistener_get_base(listener); - TlsContext *tls_ctx = static_cast(ctx); - - SSL *ssl = SSL_new(tls_ctx->ssl_ctx()); - struct bufferevent *bev = - bufferevent_openssl_socket_new(base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, - BEV_OPT_CLOSE_ON_FREE); - - std::cout << "Client connected." << std::endl; - - // Handler manages its own lifecycle (deletes itself on close) - WishHandler *handler = new WishHandler(bev, true); - - handler->SetOnMessage([handler](uint8_t opcode, const std::string &msg) { - std::string type; - switch (opcode) { - case 1: - type = "TEXT"; - break; - case 2: - type = "BINARY"; - break; - case 3: - type = "TEXT_METADATA"; - break; - case 4: - type = "BINARY_METADATA"; - break; - default: - type = "UNKNOWN(" + std::to_string(opcode) + ")"; - break; - } - std::cout << "Received [" << type << "]: " << msg << std::endl; - - // Echo back - int res = 0; - if (opcode == 1) - res = handler->SendText("Echo: " + msg); - else if (opcode == 2) - res = handler->SendBinary("Echo: " + msg); - else if (opcode == 3 || opcode == 4) - res = handler->SendMetadata(opcode == 3, "Echo: " + msg); - - if (res != 0) { - std::cerr << "Failed to send echo." << std::endl; - } - }); - - handler->Start(); -} - -void accept_error_cb(struct evconnlistener *listener, void *ctx) -{ - struct event_base *base = evconnlistener_get_base(listener); - int err = EVUTIL_SOCKET_ERROR(); - std::cerr << "Got an error " << err << " (" - << evutil_socket_error_to_string(err) - << ") on the listener. Shutting down." << std::endl; - event_base_loopexit(base, NULL); -} - -int main(int argc, char **argv) -{ - // Initialize OpenSSL - SSL_library_init(); - SSL_load_error_strings(); - - TlsContext tls_ctx; - tls_ctx.set_ca_file("../certs/ca.crt"); - tls_ctx.set_certificate_file("../certs/server.crt"); - tls_ctx.set_private_key_file("../certs/server.key"); - if (!tls_ctx.Init(true)) { - std::cerr << "Failed to init TLS context" << std::endl; - return 1; - } - - struct event_base *base; - struct evconnlistener *listener; - struct sockaddr_in sin; - int port = 8080; - - base = event_base_new(); - if (!base) { - std::cerr << "Could not initialize libevent!" << std::endl; - return 1; - } - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(0); - sin.sin_port = htons(port); - - listener = evconnlistener_new_bind(base, accept_conn_cb, &tls_ctx, - LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, - -1, (struct sockaddr *)&sin, sizeof(sin)); - - if (!listener){ - std::cerr << "Could not create a listener!" << std::endl; - return 1; - } - - std::cout << "Server listening on port " << port << "..." << std::endl; - event_base_dispatch(base); - - evconnlistener_free(listener); - event_base_free(base); - - return 0; -} diff --git a/wish/cpp/src/tls_client.cc b/wish/cpp/src/tls_client.cc new file mode 100644 index 0000000..4c8250a --- /dev/null +++ b/wish/cpp/src/tls_client.cc @@ -0,0 +1,107 @@ +#include "tls_client.h" + +#include + +// To use BoringSSL +#define EVENT__HAVE_OPENSSL 1 +#include +#include + +TlsClient::TlsClient(const std::string& ca_file, const std::string& cert_file, + const std::string& key_file, const std::string& host, + int port) + : ca_file_(ca_file), + cert_file_(cert_file), + key_file_(key_file), + host_(host), + port_(port), + base_(nullptr), + dns_base_(nullptr), + handler_(nullptr) {} + +TlsClient::~TlsClient() { + if (dns_base_) { + evdns_base_free(dns_base_, 0); + } + if (base_) { + event_base_free(base_); + } + // WishHandler deletes itself when the connection closes + // But if it wasn't started, we might need to delete it. + // Assuming it manages its own lifecycle for now. +} + +bool TlsClient::Init() { + SSL_library_init(); + SSL_load_error_strings(); + + tls_ctx_.set_ca_file(ca_file_); + tls_ctx_.set_certificate_file(cert_file_); + tls_ctx_.set_private_key_file(key_file_); + + if (!tls_ctx_.Init(false)) { + std::cerr << "Failed to init TLS context" << std::endl; + return false; + } + + base_ = event_base_new(); + if (!base_) { + std::cerr << "Could not initialize libevent!" << std::endl; + return false; + } + + dns_base_ = evdns_base_new(base_, 1); + if (!dns_base_) { + std::cerr << "Could not initialize dns!" << std::endl; + return false; + } + + SSL* ssl = SSL_new(tls_ctx_.ssl_ctx()); + struct bufferevent* bev = bufferevent_openssl_socket_new( + base_, -1, ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE); + + if (!bev) { + std::cerr << "Could not create bufferevent!" << std::endl; + return false; + } + + if (bufferevent_socket_connect_hostname(bev, dns_base_, AF_INET, + host_.c_str(), port_) < 0) { + std::cerr << "Could not connect!" << std::endl; + return false; + } + + handler_ = new WishHandler(bev, false); + + if (on_open_) { + handler_->SetOnOpen([this]() { on_open_(handler_); }); + } + + if (on_message_) { + handler_->SetOnMessage(on_message_); + } + + handler_->Start(); + + return true; +} + +void TlsClient::SetOnOpen(OpenCallback cb) { + on_open_ = cb; + if (handler_) { + handler_->SetOnOpen([this]() { on_open_(handler_); }); + } +} + +void TlsClient::SetOnMessage(MessageCallback cb) { + on_message_ = cb; + if (handler_) { + handler_->SetOnMessage(on_message_); + } +} + +void TlsClient::Run() { + std::cout << "Client running..." << std::endl; + + event_base_dispatch(base_); +} diff --git a/wish/cpp/src/tls_client.h b/wish/cpp/src/tls_client.h new file mode 100644 index 0000000..45cf452 --- /dev/null +++ b/wish/cpp/src/tls_client.h @@ -0,0 +1,46 @@ +#ifndef WISH_CPP_SRC_TLS_CLIENT_H_ +#define WISH_CPP_SRC_TLS_CLIENT_H_ + +#include +#include + +#include +#include +#include + +#include "tls_context.h" +#include "wish_handler.h" + +class TlsClient { + public: + using OpenCallback = std::function; + using MessageCallback = std::function; + + TlsClient(const std::string& ca_file, const std::string& cert_file, + const std::string& key_file, const std::string& host, int port); + ~TlsClient(); + + bool Init(); + void SetOnOpen(OpenCallback cb); + void SetOnMessage(MessageCallback cb); + void Run(); + + private: + std::string ca_file_; + std::string cert_file_; + std::string key_file_; + + std::string host_; + int port_; + + TlsContext tls_ctx_; + struct event_base* base_; + struct evdns_base* dns_base_; + + WishHandler* handler_; + + OpenCallback on_open_; + MessageCallback on_message_; +}; + +#endif // WISH_CPP_SRC_TLS_CLIENT_H_ diff --git a/wish/cpp/src/tls_server.cc b/wish/cpp/src/tls_server.cc new file mode 100644 index 0000000..314fafe --- /dev/null +++ b/wish/cpp/src/tls_server.cc @@ -0,0 +1,105 @@ +#include "tls_server.h" + +#include +#include +#include + +// To use BoringSSL +#define EVENT__HAVE_OPENSSL 1 +#include +#include + +TlsServer::TlsServer(const std::string& ca_file, const std::string& cert_file, + const std::string& key_file, int port) + : ca_file_(ca_file), + cert_file_(cert_file), + key_file_(key_file), + port_(port), + base_(nullptr), + listener_(nullptr) {} + +TlsServer::~TlsServer() { + if (listener_) { + evconnlistener_free(listener_); + } + if (base_) { + event_base_free(base_); + } +} + +bool TlsServer::Init() { + SSL_library_init(); + SSL_load_error_strings(); + + tls_ctx_.set_ca_file(ca_file_); + tls_ctx_.set_certificate_file(cert_file_); + tls_ctx_.set_private_key_file(key_file_); + + if (!tls_ctx_.Init(true)) { + std::cerr << "Failed to init TLS context" << std::endl; + return false; + } + + base_ = event_base_new(); + if (!base_) { + std::cerr << "Could not initialize libevent!" << std::endl; + return false; + } + + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(0); + sin.sin_port = htons(port_); + + // passing 'this' instead of &tls_ctx_ because we can pass TlsServer + // and access tls_ctx_ from it + listener_ = evconnlistener_new_bind( + base_, AcceptConnCb, this, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, + (struct sockaddr*)&sin, sizeof(sin)); + + if (!listener_) { + std::cerr << "Could not create a listener!" << std::endl; + return false; + } + + evconnlistener_set_error_cb(listener_, AcceptErrorCb); + + return true; +} + +void TlsServer::Run() { + std::cout << "Server listening on port " << port_ << "..." << std::endl; + event_base_dispatch(base_); +} + +void TlsServer::SetOnConnection(ConnectCallback cb) { + on_connection_ = cb; +} + +void TlsServer::AcceptConnCb(struct evconnlistener* listener, + evutil_socket_t fd, struct sockaddr* address, + int socklen, void* ctx) { + struct event_base* base = evconnlistener_get_base(listener); + TlsServer* server = static_cast(ctx); + + SSL* ssl = SSL_new(server->tls_ctx_.ssl_ctx()); + struct bufferevent* bev = bufferevent_openssl_socket_new( + base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_CLOSE_ON_FREE); + + if (server->on_connection_) { + server->on_connection_(bev); + } else { + std::cerr << "Warning: No connection handler registered." << std::endl; + bufferevent_free(bev); + } +} + +void TlsServer::AcceptErrorCb(struct evconnlistener* listener, void* ctx) { + struct event_base* base = evconnlistener_get_base(listener); + int err = EVUTIL_SOCKET_ERROR(); + std::cerr << "Got an error " << err << " (" + << evutil_socket_error_to_string(err) + << ") on the listener. Shutting down." << std::endl; + event_base_loopexit(base, NULL); +} diff --git a/wish/cpp/src/tls_server.h b/wish/cpp/src/tls_server.h new file mode 100644 index 0000000..a78f730 --- /dev/null +++ b/wish/cpp/src/tls_server.h @@ -0,0 +1,43 @@ +#ifndef WISH_CPP_SRC_TLS_SERVER_H_ +#define WISH_CPP_SRC_TLS_SERVER_H_ + +#include +#include + +#include +#include +#include + +#include "tls_context.h" + +class TlsServer { + public: + using ConnectCallback = std::function; + + TlsServer(const std::string& ca_file, const std::string& cert_file, + const std::string& key_file, int port); + ~TlsServer(); + + bool Init(); + void SetOnConnection(ConnectCallback cb); + void Run(); + + private: + static void AcceptConnCb(struct evconnlistener* listener, evutil_socket_t fd, + struct sockaddr* address, int socklen, void* ctx); + static void AcceptErrorCb(struct evconnlistener* listener, void* ctx); + + std::string ca_file_; + std::string cert_file_; + std::string key_file_; + + int port_; + + TlsContext tls_ctx_; + struct event_base* base_; + struct evconnlistener* listener_; + + ConnectCallback on_connection_; +}; + +#endif // WISH_CPP_SRC_TLS_SERVER_H_ diff --git a/wish/cpp/src/wish_handler.cc b/wish/cpp/src/wish_handler.cc index f9ed132..ff61a1a 100644 --- a/wish/cpp/src/wish_handler.cc +++ b/wish/cpp/src/wish_handler.cc @@ -132,15 +132,19 @@ int WishHandler::SendMessage(uint8_t opcode, const std::string& msg) { } int WishHandler::SendText(const std::string& msg) { - return SendMessage(1, msg); + return SendMessage(WISH_OPCODE_TEXT, msg); } int WishHandler::SendBinary(const std::string& msg) { - return SendMessage(2, msg); + return SendMessage(WISH_OPCODE_BINARY, msg); } -int WishHandler::SendMetadata(bool is_text, const std::string& msg) { - return SendMessage(is_text ? 3 : 4, msg); +int WishHandler::SendTextMetadata(const std::string& msg) { + return SendMessage(WISH_OPCODE_TEXT_METADATA, msg); +} + +int WishHandler::SendBinaryMetadata(const std::string& msg) { + return SendMessage(WISH_OPCODE_BINARY_METADATA, msg); } // ---------------- Handshake Logic ---------------- diff --git a/wish/cpp/src/wish_handler.h b/wish/cpp/src/wish_handler.h index bc09a85..ac787cc 100644 --- a/wish/cpp/src/wish_handler.h +++ b/wish/cpp/src/wish_handler.h @@ -15,6 +15,11 @@ struct wslay_event_context; struct wslay_event_on_msg_recv_arg; } +const uint8_t WISH_OPCODE_TEXT = 1; +const uint8_t WISH_OPCODE_BINARY = 2; +const uint8_t WISH_OPCODE_TEXT_METADATA = 3; +const uint8_t WISH_OPCODE_BINARY_METADATA = 4; + // WishHandler implements the WiSH Procotol defined at https://datatracker.ietf.org/doc/html/draft-yoshino-wish // // It manages the lifecycle of a single WiSH connection, including the initial HTTP handshake and subsequent message framing/parsing. @@ -36,7 +41,8 @@ class WishHandler { // Send methods int SendText(const std::string& msg); int SendBinary(const std::string& msg); - int SendMetadata(bool is_text, const std::string& msg); + int SendTextMetadata(const std::string& msg); + int SendBinaryMetadata(const std::string& msg); void SetOnMessage(MessageCallback cb); void SetOnOpen(OpenCallback cb);