#include "server.h" #include #include namespace scar { Server::Server(const ServerConfig& config) : ssl_context_(boost::asio::ssl::context::tlsv12_server), acceptor_(io_context_), config_(config) { // Load SSL certificate and key try { std::ifstream cert_file(config_.certPath()); std::ifstream key_file(config_.keyPath()); if (!cert_file.is_open()) { throw std::runtime_error("Cannot open certificate file: " + config_.certPath()); } if (!key_file.is_open()) { throw std::runtime_error("Cannot open key file: " + config_.keyPath()); } ssl_context_.use_certificate_chain_file(config_.certPath()); ssl_context_.use_private_key_file(config_.keyPath(), boost::asio::ssl::context::pem); } catch (const std::exception& e) { std::cerr << "SSL configuration error: " << e.what() << std::endl; throw; } // Initialize database database_ = std::make_shared(config_.dbPath()); if (!database_->initialize()) { throw std::runtime_error("Failed to initialize database"); } // Create authenticator authenticator_ = std::make_shared(database_, config_.jwtSecret()); // Setup acceptor boost::asio::ip::tcp::endpoint endpoint( boost::asio::ip::make_address(config_.host()), config_.port() ); acceptor_.open(endpoint.protocol()); acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); acceptor_.listen(); std::cout << "Server listening on " << config_.host() << ":" << config_.port() << std::endl; } void Server::run() { doAccept(); io_context_.run(); } void Server::stop() { io_context_.stop(); } void Server::doAccept() { acceptor_.async_accept( [this](const boost::system::error_code& error, boost::asio::ip::tcp::socket socket) { if (!error) { std::cout << "New connection from " << socket.remote_endpoint() << std::endl; auto ssl_socket = boost::asio::ssl::stream( std::move(socket), ssl_context_ ); auto session = std::make_shared( std::move(ssl_socket), authenticator_, this ); session->start(); } doAccept(); }); } void Server::addSession(std::shared_ptr session) { std::lock_guard lock(sessions_mutex_); sessions_.insert(session); std::cout << "Session added. Total sessions: " << sessions_.size() << std::endl; } void Server::removeSession(std::shared_ptr session) { std::lock_guard lock(sessions_mutex_); sessions_.erase(session); std::cout << "Session removed. Total sessions: " << sessions_.size() << std::endl; } void Server::broadcastMessage(const TextMessage& message) { std::lock_guard lock(sessions_mutex_); for (auto& session : sessions_) { if (session->isAuthenticated()) { session->send(message); } } } void Server::broadcastToOthers(const Message& message, std::shared_ptr exclude) { std::lock_guard lock(sessions_mutex_); for (auto& session : sessions_) { if (session != exclude && session->isAuthenticated()) { session->send(message); } } } } // namespace scar