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

# User Rev Content
1 root 1.1 /*
2 root 1.14 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.8 *
4 root 1.12 * 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 pippijn 1.8 *
8 root 1.14 * 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 pippijn 1.8 *
13 root 1.14 * 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 pippijn 1.8 *
18 root 1.14 * 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 root 1.12 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.8 */
23 root 1.1
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 root 1.4 #ifndef NETWORK_H
44     #define NETWORK_H
45    
46     #include <cstdarg>
47 root 1.1
48 root 1.6 /* Maximum size of any packet we expect.
49 root 1.1 *
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 root 1.15 #define NDI_COLOR_MASK 0x1f /* Gives lots of room for expansion - we are */
180 root 1.1 /* using an int anyways, so we have the space */
181     /* to still do all the flags */
182    
183 root 1.15 #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 root 1.1
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 root 1.9 struct ber32
267     {
268 root 1.10 enum { size = 5 }; // maximum length of an encoded ber32
269 root 1.9 uint32 val;
270    
271     ber32 (uint32 val) : val (val) { }
272 root 1.16
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 root 1.9 };
282    
283 root 1.1 /* 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 root 1.5 packet ()
295     {
296     reset ();
297     }
298    
299     packet (const char *name);
300 root 1.1
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 root 1.9 packet &operator <<(const ber32 v);
325    
326 root 1.1 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 root 1.11 packet &operator <<(const std::string &s) { return *this << data (s.data (), s.size ()); }
333 root 1.1
334 root 1.4 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 root 1.1 };
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