#include "Session.h" #include "PacketHandler.h" #include "SessionManager.h" #include #include #include Session::Session(tcp::socket socket) : socket_(std::move(socket)) {} Session::~Session() { // 필요한 경우 정리 작업 수행 } void Session::SetNickname(const std::string &nickname) { nickname_ = nickname; } const std::string &Session::GetNickname() const { return nickname_; } void Session::SetGold(uint64_t gold) { gold_ = gold; } uint64_t Session::GetGold() const { return gold_; } void Session::SetSwordLevel(uint32_t level) { swordLevel_ = level; } uint32_t Session::GetSwordLevel() const { return swordLevel_; } void Session::Start() { DoReadHeader(); } void Session::SendPacket(PacketID id) { PacketHeader header; header.id = static_cast(id); header.size = 0; std::vector buffer(sizeof(PacketHeader)); std::memcpy(buffer.data(), &header, sizeof(PacketHeader)); Send(buffer); } void Session::Send(std::span data) { auto self(shared_from_this()); boost::asio::post( socket_.get_executor(), [this, self, msg = std::vector(data.begin(), data.end())]() mutable { bool writeInProgress = !writeQueue_.empty(); writeQueue_.push_back(std::move(msg)); if (!writeInProgress) { DoWrite(); } }); } void Session::DoReadHeader() { auto self(shared_from_this()); boost::asio::async_read( socket_, boost::asio::buffer(&packetHeader_, sizeof(PacketHeader)), [this, self](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { // 바디 크기 결정 // 안전 확인: 메모리 고갈을 방지하기 위해 최대 패킷 크기 제한 if (packetHeader_.size > 1024 * 10) { socket_.close(); return; } packetBody_.resize(packetHeader_.size); DoReadBody(); } else { // 연결 끊김 또는 에러 발생 시 매니저에서 제거 SessionManager::GetInstance().Leave(self); } }); } void Session::DoReadBody() { auto self(shared_from_this()); boost::asio::async_read( socket_, boost::asio::buffer(packetBody_.data(), packetBody_.size()), [this, self](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { Packet packet; packet.header = packetHeader_; packet.payload = packetBody_; // 패킷 핸들러 코루틴 실행 boost::asio::co_spawn( socket_.get_executor(), PacketHandler::HandlePacket(self, std::move(packet)), boost::asio::detached); // 계속해서 읽기 DoReadHeader(); } else { // 에러 발생 시 매니저에서 제거 SessionManager::GetInstance().Leave(self); } }); } void Session::DoWrite() { auto self(shared_from_this()); boost::asio::async_write( socket_, boost::asio::buffer(writeQueue_.front()), [this, self](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { writeQueue_.pop_front(); if (!writeQueue_.empty()) { DoWrite(); } } else { // 에러 발생 시 매니저에서 제거 SessionManager::GetInstance().Leave(self); } }); }