#pragma once #include #include #include #include #include "Address.hpp" #include "Messenger.hpp" #include "NetworkError.hpp" #include "TcpStream.hpp" #include "packets/Packet.hpp" #include "packets/LoginPacket.hpp" #include "protocol/quicr/QuicrConnection.hpp" namespace tw::net { /** * Contains handlers for each message type. Calls this handler when message comes in. */ class MessageHandler { private: // std::optional> m_quicr_messenger; // Messenger m_server_messenger; std::unique_ptr m_quicr_endpoint; quicr::QuicrConnection* m_quicr_connection; std::vector(std::span)>> m_handlers; std::unique_ptr create_endpoint() { auto endpoint_r = quicr::QuicrEndpoint::create(); if(!endpoint_r) { spdlog::error("Failed to create QuicrEndpoint: {}", endpoint_r.error().message()); throw std::runtime_error("Failed to create QuicrEndpoint"); } return std::make_unique(std::move(endpoint_r.value())); } public: const bool is_connected() const { return m_quicr_connection->state() == quicr::QuicrConnectionState::Established; } MessageHandler(MessageHandler&& m) // : m_server_messenger{std::move(m.m_server_messenger)}, : m_handlers(std::move(m.m_handlers)), m_quicr_endpoint(std::move(m.m_quicr_endpoint)), m_quicr_connection(m.m_quicr_connection) { } MessageHandler(Address address) : m_quicr_endpoint(create_endpoint()), m_quicr_connection(m_quicr_endpoint->connect(address).value()), m_handlers(100) { spdlog::info("Connected to server at {}", address.to_string()); } // MessageHandler(Messenger&& server_messenger) : // // m_server_messenger{std::move(server_messenger)}, // m_quicr_connection(std::move(server_messenger.connection())), // m_handlers(100) { // } template constexpr void set_handler(const std::function handler) { PacketType type = Message::value; m_handlers[type] = [handler, this](std::span data) -> tl::expected { T result = {}; result.ParseFromArray(data.data(), data.size()); // spdlog::info("Deserialized message [{}]: {}", (int32_t)Message::value, result.DebugString()); handler(&result); // if(m_server_messenger.peek().has_value() && m_server_messenger.peek().value() == Message::value) { // tl::expected mesg = m_server_messenger.pop(nullptr); // if(!mesg.has_value()) { // return tl::make_unexpected(mesg.error()); // } // handler(&mesg.value()); // } return {}; }; } constexpr void set_raw_handler(uint32_t type, const std::function(std::span)> handler) { m_handlers[type] = handler; } void update() { m_quicr_endpoint->poll(); while(true) { std::vector buffer(64 * 1024); auto read_r = m_quicr_connection->read_into(buffer); if(!read_r) { spdlog::error("Failed to read from QUICr stream: {}", read_r.error().message()); break; } if(*read_r == 0) { break; } uint32_t type = reinterpret_cast(buffer.data())[0]; if(m_handlers[type] == nullptr) { spdlog::warn("Unknown message type: {}", type); throw std::runtime_error("Unknown message type: {}"); break; } auto handler_r = m_handlers[type](std::span(buffer.data(), *read_r).subspan(sizeof(uint32_t))); if(!handler_r) { spdlog::error("Handler error"); break; } } // while(m_server_messenger.peek().has_value() && m_server_messenger.peek().value().has_value()) { // std::optional type = m_server_messenger.peek().value(); // if(type >= m_handlers.size() || m_handlers[type.value()] == nullptr) { // spdlog::warn("Unknown message type: {}", (int)type.value()); // break; // } // auto r = m_handlers[type.value()](); // if(!r) { // spdlog::error("Failed to handle message: {}", r.error().message()); // } // } } template T> tl::expected send(T& mesg) { std::string payload; if(!mesg.SerializeToString(&payload)) { spdlog::error("Failed to serialize message"); return 0; } int32_t length = payload.length(); if(length == 0) { return 0; } std::vector bytes(length + sizeof(uint32_t)); uint32_t type = Message::value; auto payload_bytes = std::as_writable_bytes(std::span(payload)); memcpy(bytes.data(), &type, sizeof(type)); memcpy(bytes.data() + sizeof(uint32_t), payload_bytes.data(), payload_bytes.size()); auto send_r = m_quicr_connection->send_message(bytes, false); if(!send_r) { spdlog::error("Failed to send message: {}", send_r.error().message()); return 0; } return payload_bytes.size(); } }; }