diff options
Diffstat (limited to 'src/blu_cat/net/common/connection.cpp')
-rw-r--r-- | src/blu_cat/net/common/connection.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/blu_cat/net/common/connection.cpp b/src/blu_cat/net/common/connection.cpp new file mode 100644 index 0000000..b4e8f1b --- /dev/null +++ b/src/blu_cat/net/common/connection.cpp @@ -0,0 +1,136 @@ +/* + * 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 <iostream> + +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->end_connection(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->end_connection(this->index); + } + }); +} + +bool +Connection::send(const uint32_t id, const std::vector<uint8_t> &msg) +{ + std::vector<uint8_t> *buffered_msg = + new std::vector<uint8_t>(msg.size() + 8); + + { // Create header + std::memcpy(buffered_msg->data(), &id, 4); + + uint32_t size{static_cast<uint32_t>(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->end_connection(this->index); + } + delete buffered_msg; + }); + + return true; +} + +void +Connection::read_messages() +{ + while(this->messages.size() > 0) + this->message_callback->read_message( + std::move(this->messages.pop_back())); +} + +Connection::Connection( + MessageCallback *message_callback, + ConnectionCallback *connection_callback, + asio::io_context &io_context, asio::ip::tcp::socket socket, + unsigned long index): + message_callback{message_callback}, + connection_callback{connection_callback}, + io_context{io_context}, + socket{std::move(socket)}, + index{index} +{ + this->read_header(); +} + +Connection::~Connection() +{ + this->message_callback->disconnect(); + delete message_callback; + this->socket.close(); +} + +} |