/* * 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 "connection.hpp" #include namespace BluCat::NET { void Connection::read_header() { asio::async_read( this->socket, asio::buffer( &this->reading_message.header, sizeof(MessageHeader)), [this](std::error_code error, std::size_t length) { if(!error) { if(this->reading_message.header.size > 0) { this->reading_message.body.resize(this->reading_message.header.size); this->read_body(); } else { this->reading_message.body.resize(0); this->messages.push_back(this->reading_message); this->read_header(); } } else { std::cout << "Failed to read header: " << error.message() << std::endl; this->connection_callback->disconnect(this->index); } }); } void Connection::read_body() { asio::async_read( this->socket, asio::buffer( this->reading_message.body.data(), this->reading_message.body.size()), [this](std::error_code error, std::size_t length) { if(!error) { this->messages.push_back(this->reading_message); this->read_header(); } else { std::cout << "Failed to read body." << std::endl; this->connection_callback->disconnect(this->index); } }); } bool Connection::send(const uint32_t id, const std::vector &msg) { std::vector *buffered_msg = new std::vector(msg.size() + 8); { // Create header std::memcpy(buffered_msg->data(), &id, 4); uint32_t size{static_cast(msg.size())}; std::memcpy(buffered_msg->data() + 4, &size, 4); } // Append string to buffer. copy(msg.begin(), msg.end(), buffered_msg->begin() + 8); asio::async_write( this->socket, asio::buffer(buffered_msg->data(), buffered_msg->size()), [this, buffered_msg](std::error_code error, std::size_t length) { if(error) { std::cout << "Failed to send message: " << error.message() << std::endl; this->connection_callback->disconnect(this->index); } delete buffered_msg; }); return true; } bool Connection::read_message(Message *m) { if(this->messages.size() <= 0) return false; *m = std::move(this->messages.pop_back()); return true; } Connection::Connection( ConnectionCallback *connection_callback, asio::io_context &io_context, asio::ip::tcp::socket socket, unsigned long index): connection_callback{connection_callback}, io_context{io_context}, socket{std::move(socket)}, index{index} { this->read_header(); } Connection::~Connection() { this->socket.close(); } }