Build without wss support, if OpenSSL is not found

This commit is contained in:
badaix 2025-01-28 17:57:36 +01:00
parent c105fecc5b
commit 2addf7cc3d
16 changed files with 68 additions and 27 deletions

View file

@ -177,8 +177,6 @@ endif()
find_package(Threads REQUIRED)
find_package(OpenSSL REQUIRED)
include(CMakePushCheckState)
include(CheckIncludeFileCXX)
include_directories(${INCLUDE_DIRS})

View file

@ -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)

View file

@ -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

View file

@ -48,8 +48,9 @@ namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
using tcp_socket = boost::asio::ip::tcp::socket;
using ssl_socket = boost::asio::ssl::stream<tcp_socket>;
using tcp_websocket = websocket::stream<tcp_socket>;
#ifdef HAS_OPENSSL
using ssl_websocket = websocket::stream<ssl_socket>;
#endif
class ClientConnection;
@ -244,11 +245,12 @@ private:
std::optional<tcp_websocket> 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

View file

@ -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<ClientConnectionWs>(io_context_, settings_.server);
#ifdef HAS_OPENSSL
else if (settings_.server.protocol == "wss")
clientConnection_ = make_unique<ClientConnectionWss>(io_context_, ssl_context_, settings_.server);
#endif
else
clientConnection_ = make_unique<ClientConnectionTcp>(io_context_, settings_.server);
worker();

View file

@ -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_;

View file

@ -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' = <tcp|ws|wss>://<snapserver host or IP>[:port]\n"
" For example: \"tcp:\\\\192.168.1.1:1704\", or \"wss:\\\\homeserver.local\"\n"
" With 'url' = "
#ifdef HAS_OPENSSL
"<tcp|ws|wss>"
#else
"<tcp|ws>"
#endif
"://<snapserver host or IP>[: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<Switch>("", "help", "Produce help message");
auto groffSwitch = op.add<Switch, Attribute::hidden>("", "groff", "Produce groff message");
@ -335,10 +341,18 @@ int main(int argc, char** argv)
}
catch (...)
{
#ifdef HAS_OPENSSL
throw SnapException("Invalid URI - expected format: \"<scheme>://<host or IP>[:port]\", with 'scheme' on of 'tcp', 'ws' or 'wss'");
#else
throw SnapException("Invalid URI - expected format: \"<scheme>://<host or IP>[: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())

View file

@ -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)

View file

@ -18,7 +18,6 @@
#ifndef NOMINMAX
#define NOMINMAX
#include <optional>
#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;

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -161,12 +161,12 @@ struct ServerSettings
std::string filter{"*:info"};
};
Server server; ///< Server settings
Ssl ssl; ///< SSL settings
std::vector<User> 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<User> 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
};

View file

@ -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})

View file

@ -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"