/* * Copyright 2022-2025 Frederico de Oliveira Linhares * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "server.hpp" #include namespace BluCat::NET { void Server::wait_for_client_connections() { acceptor.async_accept( [this](std::error_code error, asio::ip::tcp::socket socket) { if(!error) { std::scoped_lock lock(this->mut); std::cout << "[SERVER] New connection: " << socket.remote_endpoint() << std::endl; if(this->free_connection_slots.size() > 0) { unsigned long pos{this->free_connection_slots.pop_front()}; std::cout << "Working " << pos << std::endl; Connection *new_connection = new Connection( this->callback_instantiator(), this, this->io_context, std::move(socket), pos); this->connections[pos] = new_connection; } else { unsigned long pos{this->connections.size()}; Connection *new_connection = new Connection( this->callback_instantiator(), this, this->io_context, std::move(socket), pos); this->connections.push_back(new_connection); } } else { std::cout << "error connecting to client." << std::endl; } std::cout << "num clients: " << connections.size() << std::endl; this->wait_for_client_connections(); }); } void Server::read_messages() { std::scoped_lock lock(this->mut); for(auto i{0}; i < this->connections.size(); i++) { Connection *c{this->connections[i]}; if(c != nullptr) c->read_messages(); } } void Server::end_connection(unsigned long index) { std::scoped_lock lock(this->mut); delete this->connections[index]; this->connections[index] = nullptr; this->free_connection_slots.push_back(index); } Server::Server(MessageCallback *(*callback_instantiator)(), const uint16_t port): callback_instantiator{callback_instantiator}, acceptor{io_context, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port)} { this->thread_context = std::thread([this](){this->io_context.run();}); this->wait_for_client_connections(); } Server::~Server() { this->connections.clear(); this->io_context.stop(); if(this->thread_context.joinable()) thread_context.join(); } }