summaryrefslogtreecommitdiff
path: root/src/blu_cat/net/common/connection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/blu_cat/net/common/connection.cpp')
-rw-r--r--src/blu_cat/net/common/connection.cpp136
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();
+}
+
+}