From 0388459bd0c5c5671daf3b27cadf3f53b82dd942 Mon Sep 17 00:00:00 2001 From: Benjamin Sergeant Date: Sat, 25 Jul 2020 11:26:06 -0700 Subject: [PATCH] (ixwebsocket) add WebSocketProxyServer, from ws. Still need to make the interface better. --- CMakeLists.txt | 2 + docs/CHANGELOG.md | 4 + ixwebsocket/IXWebSocketProxyServer.cpp | 117 ++++++++++++++++ ixwebsocket/IXWebSocketProxyServer.h | 20 +++ ixwebsocket/IXWebSocketVersion.h | 2 +- ws/CMakeLists.txt | 1 - ws/ws.cpp | 3 +- ws/ws.h | 6 - ws/ws_proxy_server.cpp | 176 ------------------------- 9 files changed, 146 insertions(+), 185 deletions(-) create mode 100644 ixwebsocket/IXWebSocketProxyServer.cpp create mode 100644 ixwebsocket/IXWebSocketProxyServer.h delete mode 100644 ws/ws_proxy_server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b19b0ef9..2c8dc896 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ set( IXWEBSOCKET_SOURCES ixwebsocket/IXWebSocketPerMessageDeflate.cpp ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp + ixwebsocket/IXWebSocketProxyServer.cpp ixwebsocket/IXWebSocketServer.cpp ixwebsocket/IXWebSocketTransport.cpp ) @@ -96,6 +97,7 @@ set( IXWEBSOCKET_HEADERS ixwebsocket/IXWebSocketPerMessageDeflate.h ixwebsocket/IXWebSocketPerMessageDeflateCodec.h ixwebsocket/IXWebSocketPerMessageDeflateOptions.h + ixwebsocket/IXWebSocketProxyServer.h ixwebsocket/IXWebSocketSendInfo.h ixwebsocket/IXWebSocketServer.h ixwebsocket/IXWebSocketTransport.h diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 58445903..892d3fe4 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog All changes to this project will be documented in this file. +## [9.10.7] - 2020-07-25 + +(ixwebsocket) add WebSocketProxyServer, from ws. Still need to make the interface better. + ## [9.10.6] - 2020-07-24 (ws) port broadcast_server sub-command to the new server API diff --git a/ixwebsocket/IXWebSocketProxyServer.cpp b/ixwebsocket/IXWebSocketProxyServer.cpp new file mode 100644 index 00000000..61603aad --- /dev/null +++ b/ixwebsocket/IXWebSocketProxyServer.cpp @@ -0,0 +1,117 @@ +/* + * IXWebSocketProxyServer.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketProxyServer.h" + +#include "IXWebSocketServer.h" +#include + +namespace ix +{ + class ProxyConnectionState : public ix::ConnectionState + { + public: + ProxyConnectionState() + : _connected(false) + { + } + + ix::WebSocket& webSocket() + { + return _serverWebSocket; + } + + bool isConnected() + { + return _connected; + } + + void setConnected() + { + _connected = true; + } + + private: + ix::WebSocket _serverWebSocket; + bool _connected; + }; + + int websocket_proxy_server_main(int port, + const std::string& hostname, + const ix::SocketTLSOptions& tlsOptions, + const std::string& remoteUrl, + bool verbose) + { + ix::WebSocketServer server(port, hostname); + server.setTLSOptions(tlsOptions); + + auto factory = []() -> std::shared_ptr { + return std::make_shared(); + }; + server.setConnectionStateFactory(factory); + + server.setOnConnectionCallback( + [remoteUrl, verbose](std::shared_ptr webSocket, + std::shared_ptr connectionState, + std::unique_ptr connectionInfo) { + auto state = std::dynamic_pointer_cast(connectionState); + auto remoteIp = connectionInfo->remoteIp; + + // Server connection + state->webSocket().setOnMessageCallback( + [webSocket, state, remoteIp, verbose](const WebSocketMessagePtr& msg) { + if (msg->type == ix::WebSocketMessageType::Close) + { + state->setTerminated(); + } + else if (msg->type == ix::WebSocketMessageType::Message) + { + webSocket->send(msg->str, msg->binary); + } + }); + + // Client connection + webSocket->setOnMessageCallback( + [state, remoteUrl, verbose](const WebSocketMessagePtr& msg) { + if (msg->type == ix::WebSocketMessageType::Open) + { + // Connect to the 'real' server + std::string url(remoteUrl); + url += msg->openInfo.uri; + state->webSocket().setUrl(url); + state->webSocket().disableAutomaticReconnection(); + state->webSocket().start(); + + // we should sleep here for a bit until we've established the + // connection with the remote server + while (state->webSocket().getReadyState() != ReadyState::Open) + { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + else if (msg->type == ix::WebSocketMessageType::Close) + { + state->webSocket().close(msg->closeInfo.code, msg->closeInfo.reason); + } + else if (msg->type == ix::WebSocketMessageType::Message) + { + state->webSocket().send(msg->str, msg->binary); + } + }); + }); + + auto res = server.listen(); + if (!res.first) + { + return 1; + } + + server.start(); + server.wait(); + + return 0; + } +} // namespace ix diff --git a/ixwebsocket/IXWebSocketProxyServer.h b/ixwebsocket/IXWebSocketProxyServer.h new file mode 100644 index 00000000..268ab4cd --- /dev/null +++ b/ixwebsocket/IXWebSocketProxyServer.h @@ -0,0 +1,20 @@ +/* + * IXWebSocketProxyServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved. + */ +#pragma once + +#include "IXSocketTLSOptions.h" +#include +#include +#include + +namespace ix +{ + int websocket_proxy_server_main(int port, + const std::string& hostname, + const ix::SocketTLSOptions& tlsOptions, + const std::string& remoteUrl, + bool verbose); +} // namespace ix diff --git a/ixwebsocket/IXWebSocketVersion.h b/ixwebsocket/IXWebSocketVersion.h index 76415b07..a516a1a6 100644 --- a/ixwebsocket/IXWebSocketVersion.h +++ b/ixwebsocket/IXWebSocketVersion.h @@ -6,4 +6,4 @@ #pragma once -#define IX_WEBSOCKET_VERSION "9.10.6" +#define IX_WEBSOCKET_VERSION "9.10.7" diff --git a/ws/CMakeLists.txt b/ws/CMakeLists.txt index cd477eb7..2485bf99 100644 --- a/ws/CMakeLists.txt +++ b/ws/CMakeLists.txt @@ -66,7 +66,6 @@ add_executable(ws ws_cobra_publish.cpp ws_httpd.cpp ws_autobahn.cpp - ws_proxy_server.cpp ws_sentry_minidump_upload.cpp ws_dns_lookup.cpp ws.cpp) diff --git a/ws/ws.cpp b/ws/ws.cpp index 430af64c..a79736de 100644 --- a/ws/ws.cpp +++ b/ws/ws.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -657,7 +658,7 @@ int main(int argc, char** argv) } else if (app.got_subcommand("proxy_server")) { - ret = ix::ws_proxy_server_main(port, hostname, tlsOptions, remoteHost, verbose); + ret = ix::websocket_proxy_server_main(port, hostname, tlsOptions, remoteHost, verbose); } else if (app.got_subcommand("upload_minidump")) { diff --git a/ws/ws.h b/ws/ws.h index d5837b18..4ac56f0f 100644 --- a/ws/ws.h +++ b/ws/ws.h @@ -116,12 +116,6 @@ namespace ix int ws_redis_server_main(int port, const std::string& hostname); - int ws_proxy_server_main(int port, - const std::string& hostname, - const ix::SocketTLSOptions& tlsOptions, - const std::string& remoteHost, - bool verbose); - int ws_sentry_minidump_upload(const std::string& metadataPath, const std::string& minidump, const std::string& project, diff --git a/ws/ws_proxy_server.cpp b/ws/ws_proxy_server.cpp deleted file mode 100644 index 6676fb7a..00000000 --- a/ws/ws_proxy_server.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * ws_proxy_server.cpp - * Author: Benjamin Sergeant - * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. - */ - -#include -#include -#include - -namespace ix -{ - class ProxyConnectionState : public ix::ConnectionState - { - public: - ProxyConnectionState() - : _connected(false) - { - } - - ix::WebSocket& webSocket() - { - return _serverWebSocket; - } - - bool isConnected() - { - return _connected; - } - - void setConnected() - { - _connected = true; - } - - private: - ix::WebSocket _serverWebSocket; - bool _connected; - }; - - int ws_proxy_server_main(int port, - const std::string& hostname, - const ix::SocketTLSOptions& tlsOptions, - const std::string& remoteUrl, - bool verbose) - { - spdlog::info("Listening on {}:{}", hostname, port); - - ix::WebSocketServer server(port, hostname); - server.setTLSOptions(tlsOptions); - - auto factory = []() -> std::shared_ptr { - return std::make_shared(); - }; - server.setConnectionStateFactory(factory); - - server.setOnConnectionCallback([remoteUrl, - verbose](std::shared_ptr webSocket, - std::shared_ptr connectionState, - std::unique_ptr connectionInfo) { - auto state = std::dynamic_pointer_cast(connectionState); - auto remoteIp = connectionInfo->remoteIp; - - // Server connection - state->webSocket().setOnMessageCallback([webSocket, state, remoteIp, verbose]( - const WebSocketMessagePtr& msg) { - if (msg->type == ix::WebSocketMessageType::Open) - { - spdlog::info("New connection to remote server"); - spdlog::info("remote ip: {}", remoteIp); - spdlog::info("id: {}", state->getId()); - spdlog::info("Uri: {}", msg->openInfo.uri); - spdlog::info("Headers:"); - for (auto it : msg->openInfo.headers) - { - spdlog::info("{}: {}", it.first, it.second); - } - } - else if (msg->type == ix::WebSocketMessageType::Close) - { - spdlog::info("Closed remote server connection: client id {} code {} reason {}", - state->getId(), - msg->closeInfo.code, - msg->closeInfo.reason); - state->setTerminated(); - } - else if (msg->type == ix::WebSocketMessageType::Error) - { - spdlog::error("Connection error: {}", msg->errorInfo.reason); - spdlog::error("#retries: {}", msg->errorInfo.retries); - spdlog::error("Wait time(ms): {}", msg->errorInfo.wait_time); - spdlog::error("HTTP Status: {}", msg->errorInfo.http_status); - } - else if (msg->type == ix::WebSocketMessageType::Message) - { - spdlog::info("Received {} bytes from server", msg->wireSize); - if (verbose) - { - spdlog::info("payload {}", msg->str); - } - - webSocket->send(msg->str, msg->binary); - } - }); - - // Client connection - webSocket->setOnMessageCallback( - [state, remoteUrl, verbose](const WebSocketMessagePtr& msg) { - if (msg->type == ix::WebSocketMessageType::Open) - { - spdlog::info("New connection from client"); - spdlog::info("id: {}", state->getId()); - spdlog::info("Uri: {}", msg->openInfo.uri); - spdlog::info("Headers:"); - for (auto it : msg->openInfo.headers) - { - spdlog::info("{}: {}", it.first, it.second); - } - - // Connect to the 'real' server - std::string url(remoteUrl); - url += msg->openInfo.uri; - state->webSocket().setUrl(url); - state->webSocket().disableAutomaticReconnection(); - state->webSocket().start(); - - // we should sleep here for a bit until we've established the - // connection with the remote server - while (state->webSocket().getReadyState() != ReadyState::Open) - { - spdlog::info("waiting for server connection establishment"); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - spdlog::info("server connection established"); - } - else if (msg->type == ix::WebSocketMessageType::Close) - { - spdlog::info("Closed client connection: client id {} code {} reason {}", - state->getId(), - msg->closeInfo.code, - msg->closeInfo.reason); - state->webSocket().close(msg->closeInfo.code, msg->closeInfo.reason); - } - else if (msg->type == ix::WebSocketMessageType::Error) - { - spdlog::error("Connection error: {}", msg->errorInfo.reason); - spdlog::error("#retries: {}", msg->errorInfo.retries); - spdlog::error("Wait time(ms): {}", msg->errorInfo.wait_time); - spdlog::error("HTTP Status: {}", msg->errorInfo.http_status); - } - else if (msg->type == ix::WebSocketMessageType::Message) - { - spdlog::info("Received {} bytes from client", msg->wireSize); - if (verbose) - { - spdlog::info("payload {}", msg->str); - } - - state->webSocket().send(msg->str, msg->binary); - } - }); - }); - - auto res = server.listen(); - if (!res.first) - { - spdlog::info(res.second); - return 1; - } - - server.start(); - server.wait(); - - return 0; - } -} // namespace ix