#include "message.h" #include #include #include #include namespace scar { constexpr uint8_t PROTOCOL_VERSION = 1; Message::Message(MessageType type) { header_.length = sizeof(MessageHeader); header_.type = type; header_.version = PROTOCOL_VERSION; header_.reserved = 0; } std::vector Message::serialize() const { std::vector buffer; buffer.resize(header_.length); // Copy header std::memcpy(buffer.data(), &header_, sizeof(MessageHeader)); // Copy payload if (!payload_.empty()) { std::memcpy(buffer.data() + sizeof(MessageHeader), payload_.data(), payload_.size()); } return buffer; } void Message::setPayload(const std::vector& data) { payload_ = data; header_.length = sizeof(MessageHeader) + payload_.size(); } std::unique_ptr Message::deserialize(const std::vector& data) { if (data.size() < sizeof(MessageHeader)) { throw std::runtime_error("Invalid message: too short"); } MessageHeader header; std::memcpy(&header, data.data(), sizeof(MessageHeader)); if (header.length != data.size()) { throw std::runtime_error("Invalid message: length mismatch"); } std::vector payload(data.begin() + sizeof(MessageHeader), data.end()); // Dispatch to specific message types switch (header.type) { case MessageType::LOGIN_REQUEST: return LoginRequest::deserialize(payload); case MessageType::LOGIN_RESPONSE: return LoginResponse::deserialize(payload); case MessageType::TEXT_MESSAGE: return TextMessage::deserialize(payload); default: throw std::runtime_error("Unknown message type"); } } // LoginRequest implementation LoginRequest::LoginRequest(const std::string& username, const std::string& password) : Message(MessageType::LOGIN_REQUEST), username_(username), password_(password) { std::cout << "LoginRequest constructor - Username: '" << username << "', Password length: " << password.length() << std::endl; } std::vector LoginRequest::serialize() const { std::cout << "LoginRequest::serialize - Username: '" << username_ << "', Password length: " << password_.length() << std::endl; std::vector payload; // Username length + username uint16_t username_len = username_.size(); std::cout << " Serializing username_len: " << username_len << std::endl; payload.insert(payload.end(), reinterpret_cast(&username_len), reinterpret_cast(&username_len) + sizeof(username_len)); payload.insert(payload.end(), username_.begin(), username_.end()); // Password length + password uint16_t password_len = password_.size(); std::cout << " Serializing password_len: " << password_len << std::endl; payload.insert(payload.end(), reinterpret_cast(&password_len), reinterpret_cast(&password_len) + sizeof(password_len)); payload.insert(payload.end(), password_.begin(), password_.end()); std::cout << " Total payload size: " << payload.size() << std::endl; const_cast(this)->setPayload(payload); return Message::serialize(); } std::unique_ptr LoginRequest::deserialize(const std::vector& payload) { std::cout << "LoginRequest::deserialize - Payload size: " << payload.size() << std::endl; // Debug: print raw bytes std::cout << " Raw payload bytes: "; for (size_t i = 0; i < std::min(payload.size(), size_t(20)); ++i) { std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)payload[i] << " "; } std::cout << std::dec << std::endl; size_t offset = 0; // Read username if (offset + sizeof(uint16_t) > payload.size()) { throw std::runtime_error("Invalid LoginRequest: truncated username length"); } uint16_t username_len; std::memcpy(&username_len, payload.data() + offset, sizeof(username_len)); offset += sizeof(username_len); std::cout << " Username length (raw bytes): " << (int)payload[0] << " " << (int)payload[1] << std::endl; std::cout << " Username length (uint16_t): " << username_len << std::endl; if (offset + username_len > payload.size()) { throw std::runtime_error("Invalid LoginRequest: truncated username"); } std::string username(payload.begin() + offset, payload.begin() + offset + username_len); offset += username_len; std::cout << " Username: '" << username << "'" << std::endl; // Read password if (offset + sizeof(uint16_t) > payload.size()) { throw std::runtime_error("Invalid LoginRequest: truncated password length"); } uint16_t password_len; std::memcpy(&password_len, payload.data() + offset, sizeof(password_len)); offset += sizeof(password_len); std::cout << " Password length: " << password_len << std::endl; if (offset + password_len > payload.size()) { throw std::runtime_error("Invalid LoginRequest: truncated password"); } std::string password(payload.begin() + offset, payload.begin() + offset + password_len); std::cout << " Password: (hidden, length=" << password.length() << ")" << std::endl; return std::make_unique(username, password); } // LoginResponse implementation LoginResponse::LoginResponse(bool success, const std::string& token, ErrorCode error) : Message(MessageType::LOGIN_RESPONSE), success_(success), token_(token), error_(error) {} std::vector LoginResponse::serialize() const { std::vector payload; // Success flag payload.push_back(success_ ? 1 : 0); // Error code uint16_t error_code = static_cast(error_); payload.insert(payload.end(), reinterpret_cast(&error_code), reinterpret_cast(&error_code) + sizeof(error_code)); // Token length + token uint16_t token_len = token_.size(); payload.insert(payload.end(), reinterpret_cast(&token_len), reinterpret_cast(&token_len) + sizeof(token_len)); payload.insert(payload.end(), token_.begin(), token_.end()); const_cast(this)->setPayload(payload); return Message::serialize(); } std::unique_ptr LoginResponse::deserialize(const std::vector& payload) { size_t offset = 0; // Read success flag if (offset >= payload.size()) { throw std::runtime_error("Invalid LoginResponse: missing success flag"); } bool success = payload[offset++] != 0; // Read error code if (offset + sizeof(uint16_t) > payload.size()) { throw std::runtime_error("Invalid LoginResponse: truncated error code"); } uint16_t error_code; std::memcpy(&error_code, payload.data() + offset, sizeof(error_code)); offset += sizeof(error_code); ErrorCode error = static_cast(error_code); // Read token if (offset + sizeof(uint16_t) > payload.size()) { throw std::runtime_error("Invalid LoginResponse: truncated token length"); } uint16_t token_len; std::memcpy(&token_len, payload.data() + offset, sizeof(token_len)); offset += sizeof(token_len); if (offset + token_len > payload.size()) { throw std::runtime_error("Invalid LoginResponse: truncated token"); } std::string token(payload.begin() + offset, payload.begin() + offset + token_len); return std::make_unique(success, token, error); } // TextMessage implementation TextMessage::TextMessage(const std::string& sender, const std::string& content) : Message(MessageType::TEXT_MESSAGE), sender_(sender), content_(content) {} std::vector TextMessage::serialize() const { std::vector payload; // Sender length + sender uint16_t sender_len = sender_.size(); payload.insert(payload.end(), reinterpret_cast(&sender_len), reinterpret_cast(&sender_len) + sizeof(sender_len)); payload.insert(payload.end(), sender_.begin(), sender_.end()); // Content length + content uint16_t content_len = content_.size(); payload.insert(payload.end(), reinterpret_cast(&content_len), reinterpret_cast(&content_len) + sizeof(content_len)); payload.insert(payload.end(), content_.begin(), content_.end()); const_cast(this)->setPayload(payload); return Message::serialize(); } std::unique_ptr TextMessage::deserialize(const std::vector& payload) { size_t offset = 0; // Read sender if (offset + sizeof(uint16_t) > payload.size()) { throw std::runtime_error("Invalid TextMessage: truncated sender length"); } uint16_t sender_len; std::memcpy(&sender_len, payload.data() + offset, sizeof(sender_len)); offset += sizeof(sender_len); if (offset + sender_len > payload.size()) { throw std::runtime_error("Invalid TextMessage: truncated sender"); } std::string sender(payload.begin() + offset, payload.begin() + offset + sender_len); offset += sender_len; // Read content if (offset + sizeof(uint16_t) > payload.size()) { throw std::runtime_error("Invalid TextMessage: truncated content length"); } uint16_t content_len; std::memcpy(&content_len, payload.data() + offset, sizeof(content_len)); offset += sizeof(content_len); if (offset + content_len > payload.size()) { throw std::runtime_error("Invalid TextMessage: truncated content"); } std::string content(payload.begin() + offset, payload.begin() + offset + content_len); return std::make_unique(sender, content); } // ScreenShareStart implementation ScreenShareStart::ScreenShareStart(uint32_t width, uint32_t height) : Message(MessageType::SCREEN_SHARE_START), width_(width), height_(height) { } std::vector ScreenShareStart::serialize() const { std::vector data; data.resize(sizeof(width_) + sizeof(height_)); size_t offset = 0; std::memcpy(data.data() + offset, &width_, sizeof(width_)); offset += sizeof(width_); std::memcpy(data.data() + offset, &height_, sizeof(height_)); const_cast(this)->setPayload(data); return Message::serialize(); } std::unique_ptr ScreenShareStart::deserialize(const std::vector& payload) { if (payload.size() < sizeof(uint32_t) * 2) { throw std::runtime_error("Invalid ScreenShareStart: payload too small"); } uint32_t width, height; size_t offset = 0; std::memcpy(&width, payload.data() + offset, sizeof(width)); offset += sizeof(width); std::memcpy(&height, payload.data() + offset, sizeof(height)); return std::make_unique(width, height); } // ScreenShareData implementation ScreenShareData::ScreenShareData(const std::vector& frameData) : Message(MessageType::SCREEN_SHARE_DATA), frameData_(frameData) { } std::vector ScreenShareData::serialize() const { const_cast(this)->setPayload(frameData_); return Message::serialize(); } std::unique_ptr ScreenShareData::deserialize(const std::vector& payload) { return std::make_unique(payload); } // ScreenShareStop implementation ScreenShareStop::ScreenShareStop() : Message(MessageType::SCREEN_SHARE_STOP) { } std::vector ScreenShareStop::serialize() const { return Message::serialize(); } std::unique_ptr ScreenShareStop::deserialize(const std::vector& payload) { return std::make_unique(); } } // namespace scar