#if RTC_ENABLE_WEBSOCKET
#include "websocketserver.hpp"
#include "common.hpp"
#include "internals.hpp"
#include "threadpool.hpp"
#include "utils.hpp"
namespace rtc::impl {
using namespace std::placeholders;
const string PemBeginCertificateTag = "-----BEGIN CERTIFICATE-----";
WebSocketServer::WebSocketServer(Configuration config_)
: config(std::move(config_)), mStopped(false) {
PLOG_VERBOSE << "Creating WebSocketServer";
if (config.enableTls) {
if (config.certificatePemFile && config.keyPemFile) {
mCertificate = std::make_shared<Certificate>(
config.certificatePemFile->find(PemBeginCertificateTag) != string::npos
? Certificate::FromString(*config.certificatePemFile, *config.keyPemFile)
: Certificate::FromFile(*config.certificatePemFile, *config.keyPemFile,
config.keyPemPass.value_or("")));
} else if (!config.certificatePemFile && !config.keyPemFile) {
mCertificate = std::make_shared<Certificate>(
Certificate::Generate(CertificateType::Default, "localhost"));
} else {
throw std::invalid_argument(
"Either none or both certificate and key PEM files must be specified");
}
}
const char *bindAddress = nullptr;
if (config.bindAddress) {
bindAddress = config.bindAddress->c_str();
}
tcpServer = std::make_unique<TcpServer>(config.port, bindAddress);
mThread = std::thread(&WebSocketServer::runLoop, this);
}
WebSocketServer::~WebSocketServer() {
PLOG_VERBOSE << "Destroying WebSocketServer";
stop();
}
void WebSocketServer::stop() {
if (mStopped.exchange(true))
return;
PLOG_DEBUG << "Stopping WebSocketServer thread";
tcpServer->close();
mThread.join();
}
void WebSocketServer::runLoop() {
utils::this_thread::set_name("RTC server");
PLOG_INFO << "Starting WebSocketServer";
try {
while (auto incoming = tcpServer->accept()) {
try {
if (!clientCallback)
continue;
WebSocket::Configuration clientConfig;
clientConfig.connectionTimeout = config.connectionTimeout;
clientConfig.maxMessageSize = config.maxMessageSize;
auto impl = std::make_shared<WebSocket>(std::move(clientConfig), mCertificate);
impl->changeState(WebSocket::State::Connecting);
impl->setTcpTransport(incoming);
clientCallback(std::make_shared<rtc::WebSocket>(impl));
} catch (const std::exception &e) {
PLOG_ERROR << "WebSocketServer: " << e.what();
}
}
} catch (const std::exception &e) {
PLOG_FATAL << "WebSocketServer: " << e.what();
}
PLOG_INFO << "Stopped WebSocketServer";
}
}
#endif