/* * 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.front()}; this->free_connection_slots.pop(); std::cout << "Working " << pos << std::endl; std::unique_ptr new_connection( std::make_unique( this, this->io_context, std::move(socket), pos)); this->connections[pos] = new_connection.get(); this->get_new_connection(std::move(new_connection)); } else { unsigned long pos{this->connections.size()}; std::unique_ptr new_connection( std::make_unique( this, this->io_context, std::move(socket), pos)); this->connections.push_back(new_connection.get()); this->get_new_connection(std::move(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::disconnect(unsigned long index) { std::scoped_lock lock(this->mut); delete this->connections[index]; this->connections[index] = nullptr; this->free_connection_slots.push(index); } Server::Server(void (*get_new_connection)(std::unique_ptr c), const uint16_t port): get_new_connection{get_new_connection}, 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(); } }