From 2addf7cc3dfa27444b79e8805a56849ec03c4f21 Mon Sep 17 00:00:00 2001 From: badaix Date: Tue, 28 Jan 2025 17:57:36 +0100 Subject: [PATCH] Build without wss support, if OpenSSL is not found --- CMakeLists.txt | 2 -- client/CMakeLists.txt | 8 +++++++- client/client_connection.cpp | 3 +++ client/client_connection.hpp | 8 ++++++-- client/controller.cpp | 11 +++++++++-- client/controller.hpp | 2 ++ client/snapclient.cpp | 23 +++++++++++++++++++++-- common/CMakeLists.txt | 4 +--- common/stream_uri.cpp | 3 +-- server/CMakeLists.txt | 3 +++ server/authinfo.cpp | 4 ++-- {common => server}/jwt.cpp | 2 +- {common => server}/jwt.hpp | 2 +- server/server_settings.hpp | 14 +++++++------- test/CMakeLists.txt | 4 +++- test/test_main.cpp | 2 +- 16 files changed, 68 insertions(+), 27 deletions(-) rename {common => server}/jwt.cpp (99%) rename {common => server}/jwt.hpp (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 57380fb3..b680c360 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,8 +177,6 @@ endif() find_package(Threads REQUIRED) -find_package(OpenSSL REQUIRED) - include(CMakePushCheckState) include(CheckIncludeFileCXX) include_directories(${INCLUDE_DIRS}) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 4f6cf54e..a3a44766 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -62,7 +62,13 @@ elseif(NOT ANDROID) endif(PULSE_FOUND) endif(MACOSX) -list(APPEND CLIENT_LIBRARIES OpenSSL::Crypto OpenSSL::SSL) +find_package(OpenSSL) +if(OpenSSL_FOUND) + add_compile_definitions(HAS_OPENSSL) + list(APPEND CLIENT_LIBRARIES OpenSSL::Crypto OpenSSL::SSL) +else() + message(STATUS "OpenSSL not found, building without wss support") +endif() if(ANDROID) list(APPEND CLIENT_LIBRARIES oboe::oboe) diff --git a/client/client_connection.cpp b/client/client_connection.cpp index b8e39a61..73c06d14 100644 --- a/client/client_connection.cpp +++ b/client/client_connection.cpp @@ -517,6 +517,7 @@ void ClientConnectionWs::write(boost::asio::streambuf& buffer, WriteHandler&& wr /////////////////////////////// SSL Websockets //////////////////////////////// +#ifdef HAS_OPENSSL ClientConnectionWss::ClientConnectionWss(boost::asio::io_context& io_context, boost::asio::ssl::context& ssl_context, ClientSettings::Server server) : ClientConnection(io_context, std::move(server)), ssl_context_(ssl_context) @@ -683,3 +684,5 @@ void ClientConnectionWss::write(boost::asio::streambuf& buffer, WriteHandler&& w { getWs().async_write(boost::asio::buffer(buffer.data()), write_handler); } + +#endif // HAS_OPENSSL diff --git a/client/client_connection.hpp b/client/client_connection.hpp index 94393937..4e603f75 100644 --- a/client/client_connection.hpp +++ b/client/client_connection.hpp @@ -48,8 +48,9 @@ namespace websocket = beast::websocket; // from using tcp_socket = boost::asio::ip::tcp::socket; using ssl_socket = boost::asio::ssl::stream; using tcp_websocket = websocket::stream; +#ifdef HAS_OPENSSL using ssl_websocket = websocket::stream; - +#endif class ClientConnection; @@ -244,11 +245,12 @@ private: std::optional tcp_ws_; /// Receive buffer boost::beast::flat_buffer buffer_; - /// protect ssl_ws_ + /// protect tcp_ws_ std::mutex ws_mutex_; }; +#ifdef HAS_OPENSSL /// Websocket connection class ClientConnectionWss : public ClientConnection @@ -279,3 +281,5 @@ private: /// protect ssl_ws_ std::mutex ws_mutex_; }; + +#endif // HAS_OPENSSL diff --git a/client/controller.cpp b/client/controller.cpp index dc81462d..ca7b0acc 100644 --- a/client/controller.cpp +++ b/client/controller.cpp @@ -77,9 +77,13 @@ static constexpr auto LOG_TAG = "Controller"; static constexpr auto TIME_SYNC_INTERVAL = 1s; Controller::Controller(boost::asio::io_context& io_context, const ClientSettings& settings) - : io_context_(io_context), ssl_context_(boost::asio::ssl::context::tlsv12_client), timer_(io_context), settings_(settings), stream_(nullptr), - decoder_(nullptr), player_(nullptr), serverSettings_(nullptr) + : io_context_(io_context), +#ifdef HAS_OPENSSL + ssl_context_(boost::asio::ssl::context::tlsv12_client), +#endif + timer_(io_context), settings_(settings), stream_(nullptr), decoder_(nullptr), player_(nullptr), serverSettings_(nullptr) { +#ifdef HAS_OPENSSL if (settings.server.isSsl()) { boost::system::error_code ec; @@ -118,6 +122,7 @@ Controller::Controller(boost::asio::io_context& io_context, const ClientSettings throw SnapException("Failed to load private key file: " + settings.server.certificate_key.string() + ": " + ec.message()); } } +#endif // HAS_OPENSSL } @@ -401,8 +406,10 @@ void Controller::start() { if (settings_.server.protocol == "ws") clientConnection_ = make_unique(io_context_, settings_.server); +#ifdef HAS_OPENSSL else if (settings_.server.protocol == "wss") clientConnection_ = make_unique(io_context_, ssl_context_, settings_.server); +#endif else clientConnection_ = make_unique(io_context_, settings_.server); worker(); diff --git a/client/controller.hpp b/client/controller.hpp index 48f9b157..59327730 100644 --- a/client/controller.hpp +++ b/client/controller.hpp @@ -64,7 +64,9 @@ private: void sendTimeSyncMessage(int quick_syncs); boost::asio::io_context& io_context_; +#ifdef HAS_OPENSSL boost::asio::ssl::context ssl_context_; +#endif boost::asio::steady_timer timer_; ClientSettings settings_; SampleFormat sampleFormat_; diff --git a/client/snapclient.cpp b/client/snapclient.cpp index a8138da2..0d5657c6 100644 --- a/client/snapclient.cpp +++ b/client/snapclient.cpp @@ -137,8 +137,14 @@ int main(int argc, char** argv) string pcm_device(player::DEFAULT_DEVICE); OptionParser op("Usage: snapclient [options...] [url]\n\n" - " With 'url' = ://[:port]\n" - " For example: \"tcp:\\\\192.168.1.1:1704\", or \"wss:\\\\homeserver.local\"\n" + " With 'url' = " +#ifdef HAS_OPENSSL + "" +#else + "" +#endif + "://[:port]\n" + " For example: \"tcp:\\\\192.168.1.1:1704\", or \"ws:\\\\homeserver.local\"\n" " If 'url' is not configured, snapclient tries to resolve the snapserver IP via mDNS\n"); auto helpSwitch = op.add("", "help", "Produce help message"); auto groffSwitch = op.add("", "groff", "Produce groff message"); @@ -335,10 +341,18 @@ int main(int argc, char** argv) } catch (...) { +#ifdef HAS_OPENSSL throw SnapException("Invalid URI - expected format: \"://[:port]\", with 'scheme' on of 'tcp', 'ws' or 'wss'"); +#else + throw SnapException("Invalid URI - expected format: \"://[:port]\", with 'scheme' on of 'tcp' or 'ws'"); +#endif } if ((uri.scheme != "tcp") && (uri.scheme != "ws") && (uri.scheme != "wss")) +#ifdef HAS_OPENSSL throw SnapException("Protocol must be one of 'tcp', 'ws' or 'wss'"); +#else + throw SnapException("Protocol must be one of 'tcp' or 'ws'"); +#endif settings.server.host = uri.host; settings.server.protocol = uri.scheme; if (uri.port.has_value()) @@ -348,7 +362,12 @@ int main(int argc, char** argv) else if (settings.server.protocol == "ws") settings.server.port = 1780; else if (settings.server.protocol == "wss") + { settings.server.port = 1788; +#ifndef HAS_OPENSSL + throw SnapException("Snapclient is built without wss support"); +#endif + } } if (server_cert_opt->is_set()) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index be24a5ec..d8c18232 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,4 +1,4 @@ -set(SOURCES resampler.cpp sample_format.cpp jwt.cpp base64.cpp stream_uri.cpp +set(SOURCES resampler.cpp sample_format.cpp base64.cpp stream_uri.cpp utils/string_utils.cpp) if(NOT WIN32 AND NOT ANDROID) @@ -18,5 +18,3 @@ if(ANDROID) elseif(SOXR_FOUND) target_link_libraries(common ${SOXR_LIBRARIES}) endif() - -target_link_libraries(common OpenSSL::Crypto OpenSSL::SSL) diff --git a/common/stream_uri.cpp b/common/stream_uri.cpp index 350abf25..a431bdb5 100644 --- a/common/stream_uri.cpp +++ b/common/stream_uri.cpp @@ -18,7 +18,6 @@ #ifndef NOMINMAX #define NOMINMAX -#include #endif // NOMINMAX // prototype/interface header file @@ -88,7 +87,7 @@ void StreamUri::parse(const std::string& stream_uri) host = strutils::uriDecode(strutils::trim_copy(tmp.substr(0, pos))); std::string str_port; host = utils::string::split_left(host, ':', str_port); - port = std::atoi(str_port.c_str()); + port = std::strtol(str_port.c_str(), nullptr, 10); if (port == 0) port = std::nullopt; diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 265825a0..be453da5 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -6,6 +6,7 @@ set(SERVER_SOURCES control_session_tcp.cpp control_session_http.cpp control_session_ws.cpp + jwt.cpp snapserver.cpp server.cpp stream_server.cpp @@ -36,6 +37,8 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/server) include_directories(SYSTEM ${Boost_INCLUDE_DIR}) +find_package(OpenSSL REQUIRED) + if(ANDROID) find_package(vorbis REQUIRED CONFIG) list(APPEND SERVER_LIBRARIES boost::boost) diff --git a/server/authinfo.cpp b/server/authinfo.cpp index c743bb8b..91f15bda 100644 --- a/server/authinfo.cpp +++ b/server/authinfo.cpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl + Copyright (C) 2014-2025 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,8 +22,8 @@ // local headers #include "common/aixlog.hpp" #include "common/base64.h" -#include "common/jwt.hpp" #include "common/utils/string_utils.hpp" +#include "jwt.hpp" // 3rd party headers diff --git a/common/jwt.cpp b/server/jwt.cpp similarity index 99% rename from common/jwt.cpp rename to server/jwt.cpp index 4bec892b..fe5481d1 100644 --- a/common/jwt.cpp +++ b/server/jwt.cpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl + Copyright (C) 2014-2025 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/common/jwt.hpp b/server/jwt.hpp similarity index 99% rename from common/jwt.hpp rename to server/jwt.hpp index bdcfc2a6..17aae26a 100644 --- a/common/jwt.hpp +++ b/server/jwt.hpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl + Copyright (C) 2014-2025 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/server/server_settings.hpp b/server/server_settings.hpp index b660124d..97e27226 100644 --- a/server/server_settings.hpp +++ b/server/server_settings.hpp @@ -161,12 +161,12 @@ struct ServerSettings std::string filter{"*:info"}; }; - Server server; ///< Server settings - Ssl ssl; ///< SSL settings - std::vector users; ///< User settings - Http http; ///< HTTP settings - Tcp tcp; ///< TCP settings - Stream stream; ///< Stream settings + Server server; ///< Server settings + Ssl ssl; ///< SSL settings + std::vector users; ///< User settings + Http http; ///< HTTP settings + Tcp tcp; ///< TCP settings + Stream stream; ///< Stream settings StreamingClient streamingclient; ///< Client settings - Logging logging; ///< Logging settings + Logging logging; ///< Logging settings }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7f21c00a..af9037f8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -16,15 +16,17 @@ endif() # Make test executable set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/test_main.cpp - ${CMAKE_SOURCE_DIR}/common/jwt.cpp ${CMAKE_SOURCE_DIR}/common/stream_uri.cpp ${CMAKE_SOURCE_DIR}/common/base64.cpp ${CMAKE_SOURCE_DIR}/common/utils/string_utils.cpp ${CMAKE_SOURCE_DIR}/server/authinfo.cpp + ${CMAKE_SOURCE_DIR}/server/jwt.cpp ${CMAKE_SOURCE_DIR}/server/streamreader/control_error.cpp ${CMAKE_SOURCE_DIR}/server/streamreader/properties.cpp ${CMAKE_SOURCE_DIR}/server/streamreader/metadata.cpp) +find_package(OpenSSL REQUIRED) + include_directories(SYSTEM ${Boost_INCLUDE_DIR}) add_executable(snapcast_test ${TEST_SOURCES}) diff --git a/test/test_main.cpp b/test/test_main.cpp index 8af0a863..bce2ab0e 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -22,10 +22,10 @@ #include "common/aixlog.hpp" #include "common/base64.h" #include "common/error_code.hpp" -#include "common/jwt.hpp" #include "common/stream_uri.hpp" #include "common/utils/string_utils.hpp" #include "server/authinfo.hpp" +#include "server/jwt.hpp" #include "server/server_settings.hpp" #include "server/streamreader/control_error.hpp" #include "server/streamreader/properties.hpp"