109 lines
3.3 KiB
C++
109 lines
3.3 KiB
C++
|
|
#include "server.h"
|
||
|
|
#include <iostream>
|
||
|
|
#include <fstream>
|
||
|
|
|
||
|
|
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<Database>(config_.dbPath());
|
||
|
|
if (!database_->initialize()) {
|
||
|
|
throw std::runtime_error("Failed to initialize database");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create authenticator
|
||
|
|
authenticator_ = std::make_shared<Authenticator>(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<boost::asio::ip::tcp::socket>(
|
||
|
|
std::move(socket), ssl_context_
|
||
|
|
);
|
||
|
|
|
||
|
|
auto session = std::make_shared<Session>(
|
||
|
|
std::move(ssl_socket),
|
||
|
|
authenticator_,
|
||
|
|
this
|
||
|
|
);
|
||
|
|
|
||
|
|
session->start();
|
||
|
|
}
|
||
|
|
|
||
|
|
doAccept();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::addSession(std::shared_ptr<Session> session) {
|
||
|
|
std::lock_guard<std::mutex> lock(sessions_mutex_);
|
||
|
|
sessions_.insert(session);
|
||
|
|
std::cout << "Session added. Total sessions: " << sessions_.size() << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::removeSession(std::shared_ptr<Session> session) {
|
||
|
|
std::lock_guard<std::mutex> 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<std::mutex> lock(sessions_mutex_);
|
||
|
|
|
||
|
|
for (auto& session : sessions_) {
|
||
|
|
if (session->isAuthenticated()) {
|
||
|
|
session->send(message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace scar
|