diff --git a/CMakeLists.txt b/CMakeLists.txt index 328130f..f2fa0d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,7 @@ add_executable(${PROJECT_NAME} src/gameplay/client_chunk.cpp src/gameplay/server_player.cpp src/gameplay/client_player.cpp + src/gameplay/session.cpp ) if(CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/include/Cubed/gameplay/session.hpp b/include/Cubed/gameplay/session.hpp new file mode 100644 index 0000000..7695062 --- /dev/null +++ b/include/Cubed/gameplay/session.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include +namespace Cubed { +using asio::ip::tcp; + +class Session : public std::enable_shared_from_this { + +public: + Session(tcp::socket socket); + ~Session(); + void start(); + void send(); + void close(); + const std::string& uuid() const; + +private: + static constexpr int HEADER_LEN = 8; + static constexpr uint32_t MAX_PACKET_SIZE = 4 * 1024 * 1024; + tcp::socket m_socket; + std::vector m_read_buffer; + std::deque> m_write_queue; + std::mutex m_write_mutex; + + std::string m_uuid; + + asio::awaitable read(); + asio::awaitable write(); +}; +} // namespace Cubed diff --git a/include/Cubed/tools/uuid.hpp b/include/Cubed/tools/uuid.hpp new file mode 100644 index 0000000..8956586 --- /dev/null +++ b/include/Cubed/tools/uuid.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +namespace Cubed { +inline std::string generate_uuid() { + + static std::mt19937_64 rng( + std::chrono::steady_clock::now().time_since_epoch().count() ^ + (std::random_device{}())); + std::uniform_int_distribution dist(0, UINT64_MAX); + + uint64_t a = dist(rng); + uint64_t b = dist(rng); + + std::array bytes{}; + for (int i = 0; i < 8; ++i) { + bytes[i] = (a >> (56 - 8 * i)) & 0xFF; + bytes[8 + i] = (b >> (56 - 8 * i)) & 0xFF; + } + + bytes[6] = (bytes[6] & 0x0F) | 0x40; + + bytes[8] = (bytes[8] & 0x3F) | 0x80; + + std::ostringstream ss; + ss << std::hex << std::setfill('0'); + for (size_t i = 0; i < bytes.size(); ++i) { + if (i == 4 || i == 6 || i == 8 || i == 10) { + ss << '-'; + } + ss << std::setw(2) << static_cast(bytes[i]); + } + return ss.str(); +} +} // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/session.cpp b/src/gameplay/session.cpp new file mode 100644 index 0000000..b275f80 --- /dev/null +++ b/src/gameplay/session.cpp @@ -0,0 +1,59 @@ +#include "Cubed/gameplay/session.hpp" + +#include "Cubed/tools/log.hpp" +#include "Cubed/tools/uuid.hpp" +using asio::ip::tcp; + +namespace Cubed { +Session::Session(tcp::socket socket) + : m_socket(std::move(socket)), m_uuid(generate_uuid()) {} + +Session::~Session() {} + +void Session::start() { + auto self = shared_from_this(); + asio::co_spawn( + m_socket.get_executor(), + [self]() -> asio::awaitable { co_await self->read(); }, + asio::detached); +} + +const std::string& Session::uuid() const { return m_uuid; } + +asio::awaitable Session::read() { + try { + while (true) { + std::array header; + co_await asio::async_read(m_socket, asio::buffer(header), + asio::use_awaitable); + + uint32_t total_len_net; + std::memcpy(&total_len_net, header.data(), sizeof(total_len_net)); + uint32_t total_len = ntohl(total_len_net); + + uint16_t cmd_id_net; + std::memcpy(&cmd_id_net, header.data() + 4, sizeof(cmd_id_net)); + uint16_t cmd_id = ntohs(cmd_id_net); + if (total_len < HEADER_LEN || total_len > MAX_PACKET_SIZE) { + + throw std::runtime_error("invalid packet length"); + } + uint32_t body_len = total_len - HEADER_LEN; + std::vector body_data(body_len); + if (body_len > 0) { + co_await asio::async_read(m_socket, asio::buffer(body_data), + asio::use_awaitable); + } + + if (cmd_id == 1001) { + } + } + } catch (const asio::system_error& e) { + Logger::warn("Catch Asio Error {}", e.what()); + close(); + } catch (...) { + Logger::error("Unknow Error"); + } +} + +} // namespace Cubed \ No newline at end of file