~ubuntu-branches/debian/stretch/assaultcube-data/stretch

« back to all changes in this revision

Viewing changes to source/src/protocol.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gonéri Le Bouder, Ansgar Burchardt, Gonéri Le Bouder
  • Date: 2010-04-02 23:37:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402233755-kf74fxwlu634o6vg
Tags: 1.0.4+repack1-1
[ Ansgar Burchardt ]
* debian/control: fix typo in short description

[ Gonéri Le Bouder ]
* Upgrade to 1.0.4
* bump standards-version to 3.8.4
* Add Depends: ${misc:Depends} just to avoid a lintian warning
* Add a debian/source/format file for the same reason

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// misc useful functions used by the server
 
2
 
 
3
#include "pch.h"
 
4
#include "cube.h"
 
5
#include "hash.h"
 
6
 
 
7
#ifdef _DEBUG
 
8
bool protocoldbg = false;
 
9
void protocoldebug(bool enable) { protocoldbg = enable; }
 
10
#define DEBUGCOND (protocoldbg)
 
11
#endif
 
12
 
 
13
// all network traffic is in 32bit ints, which are then compressed using the following simple scheme (assumes that most values are small).
 
14
 
 
15
void putint(ucharbuf &p, int n)
 
16
{
 
17
    DEBUGVAR(n);
 
18
    if(n<128 && n>-127) p.put(n);
 
19
    else if(n<0x8000 && n>=-0x8000) { p.put(0x80); p.put(n); p.put(n>>8); }
 
20
    else { p.put(0x81); p.put(n); p.put(n>>8); p.put(n>>16); p.put(n>>24); }
 
21
}
 
22
 
 
23
int getint(ucharbuf &p)
 
24
{
 
25
    int c = (char)p.get();
 
26
    if(c==-128) { int n = p.get(); n |= char(p.get())<<8; DEBUGVAR(n); return n; }
 
27
    else if(c==-127) { int n = p.get(); n |= p.get()<<8; n |= p.get()<<16; n |= (p.get()<<24); DEBUGVAR(n); return n; }
 
28
    else
 
29
    {
 
30
        DEBUGVAR(c);
 
31
        return c;
 
32
    }
 
33
}
 
34
 
 
35
// much smaller encoding for unsigned integers up to 28 bits, but can handle signed
 
36
void putuint(ucharbuf &p, int n)
 
37
{
 
38
    DEBUGVAR(n);
 
39
    if(n < 0 || n >= (1<<21))
 
40
    {
 
41
        p.put(0x80 | (n & 0x7F));
 
42
        p.put(0x80 | ((n >> 7) & 0x7F));
 
43
        p.put(0x80 | ((n >> 14) & 0x7F));
 
44
        p.put(n >> 21);
 
45
    }
 
46
    else if(n < (1<<7)) p.put(n);
 
47
    else if(n < (1<<14))
 
48
    {
 
49
        p.put(0x80 | (n & 0x7F));
 
50
        p.put(n >> 7);
 
51
    }
 
52
    else
 
53
    {
 
54
        p.put(0x80 | (n & 0x7F));
 
55
        p.put(0x80 | ((n >> 7) & 0x7F));
 
56
        p.put(n >> 14);
 
57
    }
 
58
}
 
59
 
 
60
int getuint(ucharbuf &p)
 
61
{
 
62
    int n = p.get();
 
63
    if(n & 0x80)
 
64
    {
 
65
        n += (p.get() << 7) - 0x80;
 
66
        if(n & (1<<14)) n += (p.get() << 14) - (1<<14);
 
67
        if(n & (1<<21)) n += (p.get() << 21) - (1<<21);
 
68
        if(n & (1<<28)) n |= 0xF0000000;
 
69
    }
 
70
    DEBUGVAR(n);
 
71
    return n;
 
72
}
 
73
 
 
74
void sendstring(const char *text, ucharbuf &p)
 
75
{
 
76
    const char *t = text;
 
77
    while(*t) putint(p, *t++);
 
78
    putint(p, 0);
 
79
    DEBUGVAR(text);
 
80
}
 
81
 
 
82
void getstring(char *text, ucharbuf &p, int len)
 
83
{
 
84
    char *t = text;
 
85
    do
 
86
    {
 
87
        if(t>=&text[len]) { text[len-1] = 0; return; }
 
88
        if(!p.remaining()) { *t = 0; return; }
 
89
        *t = getint(p);
 
90
    }
 
91
    while(*t++);
 
92
    DEBUGVAR(text);
 
93
}
 
94
 
 
95
void filtertext(char *dst, const char *src, int whitespace, int len)
 
96
{ // whitespace: no whitespace at all (0), blanks only (1), blanks & newline (2)
 
97
    for(int c = *src; c; c = *++src)
 
98
    {
 
99
        c &= 0x7F; // 7-bit ascii
 
100
        switch(c)
 
101
        {
 
102
            case '\f': ++src; continue;
 
103
        }
 
104
        if(isspace(c) ? whitespace && (whitespace>1 || c == ' ') : isprint(c))
 
105
        {
 
106
            *dst++ = c;
 
107
            if(!--len) break;
 
108
        }
 
109
    }
 
110
    *dst = '\0';
 
111
}
 
112
 
 
113
void filterrichtext(char *dst, const char *src, int len)
 
114
{
 
115
    int b, c;
 
116
    unsigned long ul;
 
117
    for(c = *src; c; c = *++src)
 
118
    {
 
119
        c &= 0x7F; // 7-bit ascii
 
120
        if(c == '\\')
 
121
        {
 
122
            b = 0;
 
123
            c = *++src;
 
124
            switch(c)
 
125
            {
 
126
                case '\0': --src; continue;
 
127
                case 'f': c = '\f'; break;
 
128
                case 'n': c = '\n'; break;
 
129
                case 'x':
 
130
                    b = 16;
 
131
                    c = *++src;
 
132
                default:
 
133
                    if(isspace(c)) continue;
 
134
                    if(b == 0 && !isdigit(c)) break;
 
135
                    ul = strtoul(src, (char **) &src, b);
 
136
                    --src;
 
137
                    c = (int) ul;
 
138
                    if(!c) continue; // number conversion failed
 
139
                    break;
 
140
            }
 
141
        }
 
142
        *dst++ = c;
 
143
        if(!--len || !*src) break;
 
144
    }
 
145
    *dst = '\0';
 
146
}
 
147
 
 
148
void filterservdesc(char *dst, const char *src, int len)
 
149
{ // only colors and spaces allowed
 
150
    for(int c = *src; c; c = *++src)
 
151
    {
 
152
        c &= 0x7F; // 7-bit ascii
 
153
        if((!isspace(c) && isprint(c)) || c == ' ' || c == '\f')
 
154
        {
 
155
            *dst++ = c;
 
156
            if(!--len) break;
 
157
        }
 
158
    }
 
159
    *dst = '\0';
 
160
}
 
161
 
 
162
void cutcolorstring(char *text, int len)
 
163
{ // limit string length, ignore color codes
 
164
    while(*text)
 
165
    {
 
166
        if(*text == '\f' && text[1]) text++;
 
167
        else len--;
 
168
        if(len < 0) { *text = '\0'; break; }
 
169
        text++;
 
170
    }
 
171
}
 
172
 
 
173
const char *modefullnames[] =
 
174
{
 
175
    "demo playback",
 
176
    "team deathmatch", "coopedit", "deathmatch", "survivor",
 
177
    "team survivor", "ctf", "pistol frenzy", "bot team deathmatch", "bot deathmatch", "last swiss standing",
 
178
    "one shot, one kill", "team one shot, one kill", "bot one shot, one kill", "hunt the flag", "team keep the flag", "keep the flag"
 
179
};
 
180
 
 
181
const char *modeacronymnames[] =
 
182
{
 
183
    "DEMO",
 
184
    "TDM", "coop", "DM", "SURV", "TSURV", "CTF", "PF", "BTDM", "BDM", "LSS",
 
185
    "OSOK", "TOSOK", "BOSOK", "HTF", "TKTF", "KTF"
 
186
};
 
187
 
 
188
const char *voteerrors[] = { "voting is currently disabled", "there is already a vote pending", "already voted", "can't vote that often", "this vote is not allowed in the current environment (singleplayer/multiplayer)", "no permission", "invalid vote" };
 
189
const char *mmfullnames[] = { "open", "private" };
 
190
 
 
191
const char *fullmodestr(int n) { return (n>=-1 && size_t(n+1) < sizeof(modefullnames)/sizeof(modefullnames[0])) ? modefullnames[n+1] : "unknown"; }
 
192
const char *acronymmodestr(int n) { return (n>=-1 && size_t(n+1) < sizeof(modeacronymnames)/sizeof(modeacronymnames[0])) ? modeacronymnames[n+1] : "n/a"; }
 
193
const char *modestr(int n, bool acronyms) { return acronyms ? acronymmodestr (n) : fullmodestr(n); }
 
194
const char *voteerrorstr(int n) { return (n>=0 && (size_t)n < sizeof(voteerrors)/sizeof(voteerrors[0])) ? voteerrors[n] : "unknown"; }
 
195
const char *mmfullname(int n) { return (n>=0 && n < MM_NUM) ? mmfullnames[n] : "unknown"; }
 
196
 
 
197
char msgsizesl[] =               // size inclusive message token, 0 for variable or not-checked sizes
 
198
{
 
199
    SV_INITS2C, 5, SV_WELCOME, 2, SV_INITC2S, 0, SV_POS, 0, SV_TEXT, 0, SV_TEAMTEXT, 0, SV_SOUND, 2, SV_VOICECOM, 2, SV_VOICECOMTEAM, 2, SV_CDIS, 2,
 
200
    SV_SHOOT, 0, SV_EXPLODE, 0, SV_SUICIDE, 1, SV_AKIMBO, 2, SV_RELOAD, 3,
 
201
    SV_GIBDIED, 4, SV_DIED, 4, SV_GIBDAMAGE, 6, SV_DAMAGE, 6, SV_HITPUSH, 6, SV_SHOTFX, 9, SV_THROWNADE, 8,
 
202
    SV_TRYSPAWN, 1, SV_SPAWNSTATE, 23, SV_SPAWN, 3, SV_FORCEDEATH, 2, SV_RESUME, 0,
 
203
    SV_TIMEUP, 2, SV_EDITENT, 10, SV_MAPRELOAD, 2, SV_NEXTMAP, 0, SV_ITEMACC, 2,
 
204
    SV_MAPCHANGE, 0, SV_ITEMSPAWN, 2, SV_ITEMPICKUP, 2,
 
205
    SV_PING, 2, SV_PONG, 2, SV_CLIENTPING, 2, SV_GAMEMODE, 2,
 
206
    SV_EDITMODE, 2, SV_EDITH, 7, SV_EDITT, 7, SV_EDITS, 6, SV_EDITD, 6, SV_EDITE, 6, SV_NEWMAP, 2,
 
207
    SV_SENDMAP, 0, SV_RECVMAP, 1, SV_SERVMSG, 0, SV_ITEMLIST, 0, SV_WEAPCHANGE, 2, SV_PRIMARYWEAP, 2,
 
208
    SV_MODELSKIN, 2,
 
209
    SV_FLAGACTION, 3, SV_FLAGINFO, 0, SV_FLAGMSG, 0, SV_FLAGCNT, 3,
 
210
    SV_ARENAWIN, 2,
 
211
    SV_SETADMIN, 0, SV_SERVOPINFO, 3,
 
212
    SV_CALLVOTE, 0, SV_CALLVOTESUC, 1, SV_CALLVOTEERR, 2, SV_VOTE, 2, SV_VOTERESULT, 2,
 
213
    SV_FORCETEAM, 3, SV_AUTOTEAM, 2, SV_CHANGETEAM, 1,
 
214
    SV_WHOIS, 2, SV_WHOISINFO, 3,
 
215
    SV_LISTDEMOS, 1, SV_SENDDEMOLIST, 0, SV_GETDEMO, 2, SV_SENDDEMO, 0, SV_DEMOPLAYBACK, 3,
 
216
    SV_CONNECT, 0,
 
217
    SV_CLIENT, 0,
 
218
    SV_EXTENSION, 0,
 
219
    SV_SPAWNLIST, 0, SV_FORCENOTIFY, 3,
 
220
    -1
 
221
};
 
222
 
 
223
char msgsizelookup(int msg)
 
224
{
 
225
    for(char *p = msgsizesl; *p>=0; p += 2) if(*p==msg) return p[1];
 
226
    return -1;
 
227
}
 
228
 
 
229
const char *genpwdhash(const char *name, const char *pwd, int salt)
 
230
{
 
231
    static string temp;
 
232
    s_sprintf(temp)("%s %d %s %s %d", pwd, salt, name, pwd, abs(PROTOCOL_VERSION));
 
233
    tiger::hashval hash;
 
234
    tiger::hash((uchar *)temp, (int)strlen(temp), hash);
 
235
    s_sprintf(temp)("%llx %llx %llx", hash.chunks[0], hash.chunks[1], hash.chunks[2]);
 
236
    return temp;
 
237
}
 
238
 
 
239