ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/network.h
Revision: 1.16
Committed: Sun Jul 29 02:24:34 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.15: +9 -0 lines
Log Message:
implement the most elaborate rate limit system to date, from the errors before:

- output-rate is now an upper bound only. its purpose is to give the user
  some control over bandwith use. it should be set too high rather than too low.
- the server will (on linux only, or systems that support tcpi), guess
  how much the kernel is willing to send without delay (this is imperfect as
  we do not know the remote receive window, but we assume its "large enough").
- we accuretyl measure mss and ensure that preferably mss-sized packets
  leave the server, by sending less in some cases and more in others
  to reacht eh desired bandwidth goal
  (e.g. 15000 == http://ue.tst.eu/545350740128735b13aaf541c88bfaf2.txt)

the net effect is that the server will never send (much) more data than the kernel
thinks the network is able to handle. that is, when the connection was idle for a time
and the congestion window is small, we will only start sending small amounts of
data, prompting the kernel to accuratly model the bandwidth.

in essence, this creates a tcp stream that never has more data buffered
than neccessary for in-flight data, ensuring that we can get low-latency
map updates through to the client whole using all excess bandwidth the
network can handle.

I mostly tested with netem, e.g.

   ifconfig lo mtu 1500
   tc qdisc change dev lo root netem delay 190ms 10ms drop 0.1

gave me roughtly 20kb/s throughput even though output-rate was 100kb/s,
without stalling the conenction even when downloading backgorund music and
other large chunks of data.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 /* This file defines various flags that both the new client and
25 * newserver uses. These should never be changed, only expanded.
26 * Changing them will likely cause all old clients to not work properly.
27 * While called newclient, it is really used by both the client and
28 * server to keep some values the same.
29 *
30 * Name format is CS_(command)_(flag)
31 * CS = Client/Server.
32 * (command) is protocol command, ie ITEM
33 * (flag) is the flag name
34 */
35
36 /* It is trivial to keep a link of copy of this file in the client
37 * or server area. But keeping one common file should make things
38 * more reliable, as both the client and server will definately be
39 * talking about the same values.
40 */
41
42
43 #ifndef NETWORK_H
44 #define NETWORK_H
45
46 #include <cstdarg>
47
48 /* Maximum size of any packet we expect.
49 *
50 * The size must be the same in the server and the client (stupid), and its also NOT
51 * the maximum buffer size as one would expect, but the maximum buffer size + 1.
52 */
53 #define MAXSOCKBUF 10240
54
55 #define CS_QUERY_YESNO 0x1 /* Yes/no question */
56 #define CS_QUERY_SINGLECHAR 0x2 /* Single character response expected */
57 #define CS_QUERY_HIDEINPUT 0x4 /* Hide input being entered */
58
59 /* These are multiplication values that should be used when changing
60 * floats to ints, and vice version. MULTI is integer representatin
61 * (float to int), MULTF is float, for going from int to float.
62 */
63 #define FLOAT_MULTI 100000
64 #define FLOAT_MULTF 100000.0
65
66 /* ID's for the various stats that get sent across. */
67
68 #define CS_STAT_HP 1
69 #define CS_STAT_MAXHP 2
70 #define CS_STAT_SP 3
71 #define CS_STAT_MAXSP 4
72 #define CS_STAT_STR 5
73 #define CS_STAT_INT 6
74 #define CS_STAT_WIS 7
75 #define CS_STAT_DEX 8
76 #define CS_STAT_CON 9
77 #define CS_STAT_CHA 10
78 #define CS_STAT_EXP 11
79 #define CS_STAT_LEVEL 12
80 #define CS_STAT_WC 13
81 #define CS_STAT_AC 14
82 #define CS_STAT_DAM 15
83 #define CS_STAT_ARMOUR 16
84 #define CS_STAT_SPEED 17
85 #define CS_STAT_FOOD 18
86 #define CS_STAT_WEAP_SP 19
87 #define CS_STAT_RANGE 20
88 #define CS_STAT_TITLE 21
89 #define CS_STAT_POW 22
90 #define CS_STAT_GRACE 23
91 #define CS_STAT_MAXGRACE 24
92 #define CS_STAT_FLAGS 25
93 #define CS_STAT_WEIGHT_LIM 26
94 #define CS_STAT_EXP64 28
95 #define CS_STAT_SPELL_ATTUNE 29
96 #define CS_STAT_SPELL_REPEL 30
97 #define CS_STAT_SPELL_DENY 31
98
99 /* Start & end of resistances, inclusive. */
100 #define CS_STAT_RESIST_START 100
101 #define CS_STAT_RESIST_END 117
102 #define CS_STAT_RES_PHYS 100
103 #define CS_STAT_RES_MAG 101
104 #define CS_STAT_RES_FIRE 102
105 #define CS_STAT_RES_ELEC 103
106 #define CS_STAT_RES_COLD 104
107 #define CS_STAT_RES_CONF 105
108 #define CS_STAT_RES_ACID 106
109 #define CS_STAT_RES_DRAIN 107
110 #define CS_STAT_RES_GHOSTHIT 108
111 #define CS_STAT_RES_POISON 109
112 #define CS_STAT_RES_SLOW 110
113 #define CS_STAT_RES_PARA 111
114 #define CS_STAT_TURN_UNDEAD 112
115 #define CS_STAT_RES_FEAR 113
116 #define CS_STAT_RES_DEPLETE 114
117 #define CS_STAT_RES_DEATH 115
118 #define CS_STAT_RES_HOLYWORD 116
119 #define CS_STAT_RES_BLIND 117
120
121 /* Start & end of skill experience + skill level, inclusive. */
122 #define CS_STAT_SKILLEXP_START 118
123 #define CS_STAT_SKILLEXP_END 129
124 #define CS_STAT_SKILLEXP_AGILITY 118
125 #define CS_STAT_SKILLEXP_AGLEVEL 119
126 #define CS_STAT_SKILLEXP_PERSONAL 120
127 #define CS_STAT_SKILLEXP_PELEVEL 121
128 #define CS_STAT_SKILLEXP_MENTAL 122
129 #define CS_STAT_SKILLEXP_MELEVEL 123
130 #define CS_STAT_SKILLEXP_PHYSIQUE 124
131 #define CS_STAT_SKILLEXP_PHLEVEL 125
132 #define CS_STAT_SKILLEXP_MAGIC 126
133 #define CS_STAT_SKILLEXP_MALEVEL 127
134 #define CS_STAT_SKILLEXP_WISDOM 128
135 #define CS_STAT_SKILLEXP_WILEVEL 129
136
137 /* CS_STAT_SKILLINFO is used as the starting index point. Skill number->name
138 * map is generated dynamically for the client, so a bunch of entries will
139 * be used here. CS_NUM_SKILLS does not match how many skills there really
140 * are - instead, it is used as a range of values so that the client
141 * can have some idea how many skill categories there may be.
142 */
143 #define CS_STAT_SKILLINFO 140
144 #define CS_NUM_SKILLS 50
145
146 /* These are used with CS_STAT_FLAGS above to communicate S->C what the
147 * server thinks the fireon & runon states are.
148 */
149 #define SF_FIREON 0x01
150 #define SF_RUNON 0x02
151
152 /* The following are the color flags passed to new_draw_info.
153 *
154 * We also set up some control flags
155 *
156 * NDI = New Draw Info
157 */
158
159 /* Color specifications - note these match the order in xutil.c */
160 /* Note 2: Black, the default color, is 0. Thus, it does not need to
161 * be implicitly specified.
162 */
163 #define NDI_BLACK 0
164 #define NDI_WHITE 1
165 #define NDI_NAVY 2
166 #define NDI_RED 3
167 #define NDI_ORANGE 4
168 #define NDI_BLUE 5 /* Actually, it is Dodger Blue */
169 #define NDI_DK_ORANGE 6 /* DarkOrange2 */
170 #define NDI_GREEN 7 /* SeaGreen */
171 #define NDI_LT_GREEN 8 /* DarkSeaGreen, which is actually paler */
172 /* Than seagreen - also background color */
173 #define NDI_GREY 9
174 #define NDI_BROWN 10 /* Sienna */
175 #define NDI_GOLD 11
176 #define NDI_TAN 12 /* Khaki */
177
178 #define NDI_MAX_COLOR 12 /* Last value in */
179 #define NDI_COLOR_MASK 0x1f /* Gives lots of room for expansion - we are */
180 /* using an int anyways, so we have the space */
181 /* to still do all the flags */
182
183 #define NDI_REPLY 0x20 // is a direct reply to a user command
184 #define NDI_NOCREATE 0x40 // do not create a tba if one doesn't exist
185 #define NDI_CLIENT_MASK 0x7f // what the client is allowed to see
186
187 #define NDI_UNIQUE 0x1000 /* Print this out immediately, don't buffer */
188 #define NDI_ALL 0x2000 /* Inform all players of this message */
189 #define NDI_DEF 0x4000 // ignore colour for channel protocol
190
191 /* Flags for the item command */
192 enum {a_none, a_readied, a_wielded, a_worn, a_active, a_applied};
193 #define F_APPLIED 0x000F
194 #define F_LOCATION 0x00F0
195 #define F_UNPAID 0x0200
196 #define F_MAGIC 0x0400
197 #define F_CURSED 0x0800
198 #define F_DAMNED 0x1000
199 #define F_OPEN 0x2000
200 #define F_NOPICK 0x4000
201 #define F_LOCKED 0x8000
202
203 #define CF_FACE_NONE 0
204 #define CF_FACE_BITMAP 1
205 #define CF_FACE_XPM 2
206 #define CF_FACE_PNG 3
207 #define CF_FACE_CACHE 0x10
208
209 /* Used in the new_face structure on the magicmap field. Low bits
210 * are color informatin. For now, only high bit information we need
211 * is floor information.
212 */
213 #define FACE_FLOOR 0x80
214 #define FACE_WALL 0x40 /* Or'd into the color value by the server
215 * right before sending.
216 */
217 #define FACE_COLOR_MASK 0xf
218
219 #define UPD_LOCATION 0x01
220 #define UPD_FLAGS 0x02
221 #define UPD_WEIGHT 0x04
222 #define UPD_FACE 0x08
223 #define UPD_NAME 0x10
224 #define UPD_ANIM 0x20
225 #define UPD_ANIMSPEED 0x40
226 #define UPD_NROF 0x80
227
228 /* The flag values sent by the updspell command */
229 #define UPD_SP_MANA 0x01
230 #define UPD_SP_GRACE 0x02
231 #define UPD_SP_DAMAGE 0x04
232
233 #define SOUND_NORMAL 0
234 #define SOUND_SPELL 1
235
236 struct data
237 {
238 unsigned int len;
239 const void *ptr;
240
241 data (const void *ptr, int len) : len (len), ptr (ptr) { }
242 data (const char *str) : len (strlen (str ? str : 0)), ptr ((void *)str) { }
243 data (const shstr &sh) : len (sh.length ()), ptr ((void *)&sh) { }
244 };
245
246 struct data8
247 {
248 unsigned int len;
249 const void *ptr;
250
251 data8 (const void *ptr, int len) : len (len), ptr (ptr) { }
252 data8 (const char *str) : len (strlen (str ? str : 0)), ptr ((void *)str) { }
253 data8 (const shstr &sh) : len (sh.length ()), ptr ((void *)&sh) { }
254 };
255
256 struct data16
257 {
258 unsigned int len;
259 const void *ptr;
260
261 data16 (const void *ptr, int len) : len (len), ptr (ptr) { }
262 data16 (const char *str) : len (strlen (str ? str : 0)), ptr ((void *)str) { }
263 data16 (const shstr &sh) : len (sh.length ()), ptr ((void *)&sh) { }
264 };
265
266 struct ber32
267 {
268 enum { size = 5 }; // maximum length of an encoded ber32
269 uint32 val;
270
271 ber32 (uint32 val) : val (val) { }
272
273 static int encoded_size (uint32 val)
274 {
275 if (val >= (1 << 7*4)) return 5;
276 if (val >= (1 << 7*3)) return 4;
277 if (val >= (1 << 7*2)) return 3;
278 if (val >= (1 << 7*1)) return 2;
279 return 1;
280 }
281 };
282
283 /* Contains the base information we use to make up a packet we want to send. */
284 struct packet
285 {
286 enum { bufsize = MAXSOCKBUF };
287 enum { hdrlen = 2 }; // keep this many bytes free at the front
288
289 // strategy: only check on variable-length adds
290 // and allow 256 bytes for any headers.
291 uint8 *cur;
292 uint8 buf_ [hdrlen + bufsize + 256];
293
294 packet ()
295 {
296 reset ();
297 }
298
299 packet (const char *name);
300
301 uint8 operator [](unsigned int i) const { return buf_ [i + hdrlen]; }
302 uint8 &operator [](unsigned int i) { return buf_ [i + hdrlen]; }
303
304 uint8 *buf () { return buf_ + hdrlen; }
305 const uint8 *buf () const { return buf_ + hdrlen; }
306
307 void reset (int offset = 0) { cur = buf () + offset; }
308 int length () const { return cur - buf (); }
309 int room () { return bufsize - (cur - buf ()); }
310
311 // unchecked
312 packet &operator <<(uint8 v) { *cur++ = v; return *this; }
313
314 packet &operator <<(uint16 v) { return *this << uint8 (v >> 8) << uint8 (v); }
315 packet &operator <<(uint32 v) { return *this << uint16 (v >> 16) << uint16 (v); }
316 packet &operator <<(uint64 v) { return *this << uint32 (v >> 32) << uint32 (v); }
317
318 packet &operator <<(sint8 v) { return *this << (uint8 )v; }
319 packet &operator <<(sint16 v) { return *this << (uint16)v; }
320 packet &operator <<(sint32 v) { return *this << (uint32)v; }
321 packet &operator <<(sint64 v) { return *this << (uint64)v; }
322
323 // checked
324 packet &operator <<(const ber32 v);
325
326 packet &operator <<(const data &v);
327 packet &operator <<(const data8 &v);
328 packet &operator <<(const data16 &v);
329
330 packet &operator <<(const char *v);
331 packet &operator <<(const shstr &sh) { return *this << data (&sh, sh.length ()); }
332 packet &operator <<(const std::string &s) { return *this << data (s.data (), s.size ()); }
333
334 void vprintf (const char *format, va_list ap);
335
336 void printf (const char *format, ...)
337 {
338 va_list ap;
339 va_start (ap, format);
340 vprintf (format, ap);
341 va_end (ap);
342 }
343 };
344
345 inline uint16 net_uint16 (uint8 *data) { return (data [0] << 8) | data [1]; }
346 inline uint32 net_uint32 (uint8 *data) { return (net_uint16 (data) << 16) | net_uint16 (data + 2); }
347 inline sint16 net_sint16 (uint8 *data) { return sint16 (net_uint16 (data)); }
348 inline sint16 net_sint32 (uint8 *data) { return sint32 (net_uint32 (data)); }
349
350 #endif
351