112 std::vector<uint8_t> packet;
115 uint16_t typeValue =
static_cast<uint16_t
>(type);
116 packet.push_back(
static_cast<uint8_t
>(typeValue & 0xFF));
117 packet.push_back(
static_cast<uint8_t
>((typeValue >> 8) & 0xFF));
120 uint32_t length =
static_cast<uint32_t
>(payload.size());
121 packet.push_back(
static_cast<uint8_t
>(length & 0xFF));
122 packet.push_back(
static_cast<uint8_t
>((length >> 8) & 0xFF));
123 packet.push_back(
static_cast<uint8_t
>((length >> 16) & 0xFF));
124 packet.push_back(
static_cast<uint8_t
>((length >> 24) & 0xFF));
127 packet.insert(packet.end(), payload.begin(), payload.end());
138 if (packet.size() < 6) {
143 uint16_t typeValue = packet[0] | (packet[1] << 8);
152 inline std::vector<uint8_t>
getPayload(
const std::vector<uint8_t> &packet) {
153 if (packet.size() < 6) {
158 uint32_t length = packet[2] | (packet[3] << 8) | (packet[4] << 16) | (packet[5] << 24);
161 constexpr uint32_t MAX_PAYLOAD_SIZE = 10 * 1024 * 1024;
162 if (length > MAX_PAYLOAD_SIZE) {
167 if (packet.size() < 6 + length) {
172 if (length > packet.size() - 6) {
176 return std::vector<uint8_t>(packet.begin() + 6, packet.begin() + 6 + length);
187 std::vector<uint8_t> bytes;
188 uint32_t length =
static_cast<uint32_t
>(str.size());
191 bytes.push_back(
static_cast<uint8_t
>(length & 0xFF));
192 bytes.push_back(
static_cast<uint8_t
>((length >> 8) & 0xFF));
193 bytes.push_back(
static_cast<uint8_t
>((length >> 16) & 0xFF));
194 bytes.push_back(
static_cast<uint8_t
>((length >> 24) & 0xFF));
197 bytes.insert(bytes.end(), str.begin(), str.end());
206 if (bytes.size() < offset + 4) {
212 bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24);
215 constexpr uint32_t MAX_STRING_SIZE = 1024 * 1024;
216 if (length > MAX_STRING_SIZE) {
223 if (bytes.size() < offset + length) {
228 if (length > bytes.size() - offset) {
232 std::string result(bytes.begin() + offset, bytes.begin() + offset + length);
250 bool isSpectator =
false) {
254 payload.push_back(isSpectator ? 1 : 0);
278 if (offset < payload.size()) {
279 isSpectator = (payload[offset] != 0);
295 bool isSpectator =
false;
Network protocol with unified message format.
std::vector< uint8_t > createConnectRequest(const std::string &playerName, bool isSpectator=false)
Create HANDSHAKE_REQUEST message.
MessageType
All message types in the R-Type protocol.
@ C2S_UPDATE_AUTO_MM_PREF
@ S2C_MATCHMAKING_STARTED
std::string parseConnectResponse(const std::vector< uint8_t > &packet)
Parse HANDSHAKE_RESPONSE message.
std::string parseConnectRequest(const std::vector< uint8_t > &packet, bool &isSpectator)
Parse HANDSHAKE_REQUEST message.
std::vector< uint8_t > createConnectResponse(const std::string &message)
Create HANDSHAKE_RESPONSE message.
std::string deserializeString(const std::vector< uint8_t > &bytes, size_t &offset)
Deserialize bytes to string.
MessageType getMessageType(const std::vector< uint8_t > &packet)
Get message type from packet.
std::vector< uint8_t > createMessage(MessageType type, const std::vector< uint8_t > &payload)
Create a message with type and payload.
std::vector< uint8_t > serializeString(const std::string &str)
Serialize a string to bytes.
std::vector< uint8_t > getPayload(const std::vector< uint8_t > &packet)
Get payload from packet (without header)