networkmessage.h

main 179 lines · 4.2 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifndef FS_NETWORKMESSAGE_H_B853CFED58D1413A87ACED07B2926E03
21#define FS_NETWORKMESSAGE_H_B853CFED58D1413A87ACED07B2926E03
22
23#include "const.h"
24#include "enums.h"
25
26class Item;
27class Creature;
28class Player;
29struct Position;
30class RSA;
31
32class NetworkMessage
33{
34 public:
35 using MsgSize_t = uint16_t;
36 // Headers:
37 // 2 bytes for unencrypted message size
38 // 4 bytes for checksum
39 // 2 bytes for encrypted message size
40 static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 8;
41 enum { HEADER_LENGTH = 2 };
42 enum { CHECKSUM_LENGTH = 4 };
43 enum { XTEA_MULTIPLE = 8 };
44 enum { MAX_BODY_LENGTH = NETWORKMESSAGE_MAXSIZE - HEADER_LENGTH - CHECKSUM_LENGTH - XTEA_MULTIPLE };
45 enum { MAX_PROTOCOL_BODY_LENGTH = MAX_BODY_LENGTH - 10 };
46
47 NetworkMessage() = default;
48
49 void reset() {
50 info = {};
51 }
52
53 // simply read functions for incoming message
54 uint8_t getByte() {
55 if (!canRead(1)) {
56 return 0;
57 }
58
59 return buffer[info.position++];
60 }
61
62 uint8_t getPreviousByte() {
63 return buffer[--info.position];
64 }
65
66 template<typename T>
67 T get() {
68 if (!canRead(sizeof(T))) {
69 return 0;
70 }
71
72 T v;
73 memcpy(&v, buffer + info.position, sizeof(T));
74 info.position += sizeof(T);
75 return v;
76 }
77
78 std::string getString(uint16_t stringLen = 0);
79 Position getPosition();
80
81 // skips count unknown/unused bytes in an incoming message
82 void skipBytes(int16_t count) {
83 info.position += count;
84 }
85
86 // simply write functions for outgoing message
87 void addByte(uint8_t value) {
88 if (!canAdd(1)) {
89 return;
90 }
91
92 buffer[info.position++] = value;
93 info.length++;
94 }
95
96 template<typename T>
97 void add(T value) {
98 if (!canAdd(sizeof(T))) {
99 return;
100 }
101
102 memcpy(buffer + info.position, &value, sizeof(T));
103 info.position += sizeof(T);
104 info.length += sizeof(T);
105 }
106
107 void addBytes(const char* bytes, size_t size);
108 void addPaddingBytes(size_t n);
109
110 void addString(const std::string& value);
111
112 void addDouble(double value, uint8_t precision = 2);
113
114 // write functions for complex types
115 void addPosition(const Position& pos);
116 void addItem(uint16_t id, uint8_t count, bool withDescription = false);
117 void addItem(const Item* item, bool withDescription = false);
118 void addItemId(uint16_t itemId);
119 void addOutfit(Outfit_t& outfit);
120
121 MsgSize_t getLength() const {
122 return info.length;
123 }
124
125 void setLength(MsgSize_t newLength) {
126 info.length = newLength;
127 }
128
129 MsgSize_t getBufferPosition() const {
130 return info.position;
131 }
132
133 uint16_t getLengthHeader() const {
134 return static_cast<uint16_t>(buffer[0] | buffer[1] << 8);
135 }
136
137 bool isOverrun() const {
138 return info.overrun;
139 }
140
141 uint8_t* getBuffer() {
142 return buffer;
143 }
144
145 const uint8_t* getBuffer() const {
146 return buffer;
147 }
148
149 uint8_t* getBodyBuffer() {
150 info.position = 2;
151 return buffer + HEADER_LENGTH;
152 }
153
154 protected:
155 struct NetworkMessageInfo {
156 MsgSize_t length = 0;
157 MsgSize_t position = INITIAL_BUFFER_POSITION;
158 bool overrun = false;
159 };
160
161 NetworkMessageInfo info;
162 uint8_t buffer[NETWORKMESSAGE_MAXSIZE];
163
164 private:
165 bool canAdd(size_t size) const {
166 return (size + info.position) < MAX_BODY_LENGTH;
167 }
168
169 bool canRead(int32_t size) {
170 if ((info.position + size) > (info.length + 8) || size >= (NETWORKMESSAGE_MAXSIZE - info.position)) {
171 info.overrun = true;
172 return false;
173 }
174 return true;
175 }
176};
177
178#endif // #ifndef __NETWORK_MESSAGE_H__
179
Top