-
Notifications
You must be signed in to change notification settings - Fork 0
/
cs-server-proto.txt
220 lines (165 loc) · 5.52 KB
/
cs-server-proto.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
Game servers will answer the following messages:
Messages are sent to the server by sending 4 consecutive bytes of 255 (32-bit integer -1) and then the string command followed by a zero byte to terminate it
"ping"
Server responds with a single byte code ASCII 'j'
"info"
Server responds with the following packet:
(int32) -1
(byte) ASCII 'C' (info response, S2A_INFO)
(string) net address of server
(string) name of the host / server
(string) name of the map
(string) game directory (i.e. valve/)
(string) Game description (e.g. "half-life multiplay")
(byte) active client count
(byte) maximum clients allowed
(byte) protocol version (currently 7)
"players"
Server responds with the following packet:
(int32) -1
(byte) ASCII 'D' (players response, S2A_PLAYER)
(byte) active client count
for each active client
(byte) client number / index
(string) player name
(int32) client's frag total
(float32) client's total time in-game
"rules"
Server responds with the following packet:
(int32) -1
(byte) ASCII 'E' (rules response, S2A_RULES)
(int16) number of rules
for each rule
(string) rule name
(string) rule value
-------------------
Master server query protocol:
Sent to master:
(byte) ASCII 'c' ( A2M_GET_SERVERS )
Response from master:
(int32) -1
(byte) ASCII 'd' ( M2A_SERVERS )
(byte) unused
// This is followed by as many 6 byte ip addresses as will fit in the message. The master currently feeds about 2K worth of IP address ( 300+ or so ), but we may up that # significantly in the near future.
(4 x byte) ip address
(int16) port #
The old protocol is still valid, but there is a new, extended protocol:
Here are both the old and new protocols ( the new one is the "details" message ):
"info"
Server responds with the following packet:
(int32) -1
(byte) ASCII 'C' (info response, S2A_INFO)
(string) net address of server
(string) name of the host / server
(string) name of the map
(string) game directory (i.e. valve/)
(string) Game description (e.g. "half-life multiplay")
(byte) active client count
(byte) maximum clients allowed
(byte) protocol version (currently 37)
"details"
(int32) -1
(byte) ASCII 'm' ( S2A_INFO_DETAILED )
(string) net address of server
(string) name of the host / server
(string) name of the map
(string) game directory (i.e. valve/)
(string) Game description (e.g. "half-life multiplay")
(byte) active client count
(byte) maximum clients allowed
(byte) protocol version (currently 37)
(byte) type of server == 'l' for listen or 'd' for dedicated
(byte) os of server == 'w' for win32 or 'l' for linux
(byte) password on server == 1 or yes, 0, for no
(byte) is server running a mod? == 1 for yes, 0 for no
IFF the server is running mod byte was 1:
(string) URL for mod's "info" website
(string) URL for mod's download ftp server
(int32) mod version #
(int32) mod download size ( in bytes, approx. )
(byte) is the mod a server side only mod? 1 == yes, 0 == no
(byte) does this server require you to have a custom client side .dll ( client.dll )? 1 == yes, 0 == no.
Here is some code that uses the new protocol. The first function starts the protocol and the second services the message and requests more ip addresses:
/*
==================
Host_GetBatchServerList_f
Request full server list from HL master server.
==================
*/
void Host_GetBatchServerList_f( void )
{
unsigned char c[10];
adrlist_t *p;
int i = 0;
// Request a server list from the master servers.
NET_Config( true ); // Initialize networking
if ( gfNoMasterServer )
return;
if ( !valvemaster_adr )
return;
c[0] = A2M_GET_SERVERS_BATCH; // ascii 'e'
i++;
*(int *)&c[1] = 0; // Request first batch.
i += sizeof( int );
p = valvemaster_adr;
while ( p )
{
// send to valve master
Con_Printf ("Requesting batch server list from %s\n", NET_AdrToString ( p->adr) );
NET_SendPacket (NS_CLIENT, i, c, p->adr );
p = p->next;
}
}
// Upon receiving ( 5 bytes, 4 for the -1 and 1 byte for the 'f' character ):
int32 -1
M2A_SERVER_BATCH // Ascii 'f', the response to the above
void CL_ParseBatchServerList( void )
{
char szAddress[128] = "";
unsigned char cIP[4];
int i;
unsigned short iIPPort;
int nNumAddresses;
int count = 1;
int unique = 0;
MSG_ReadByte(); // Skip \r
unique = MSG_ReadLong();
// So far we have read 6 chars. Remainder of message length is iBytesRead - 6
nNumAddresses = net_message.cursize - sizeof(int) - sizeof(unsigned char) - sizeof(byte);
// Each address is 6 bytes long
//
nNumAddresses /= 6;
while (nNumAddresses-- > 0)
{
memset(szAddress, 0, 128);
for (i = 0; i < 4; i++)
cIP[i] = MSG_ReadByte();
sprintf( szAddress, "%i.%i.%i.%i"
, (int)cIP[0]
, (int)cIP[1]
, (int)cIP[2]
, (int)cIP[3]
);
iIPPort = BigShort((unsigned short)MSG_ReadShort());
//if ( count <= 100 )
// Con_Printf( "%4i: %s:%i\n", count, szAddress, iIPPort );
count++;
}
Con_Printf( "%i servers\n", count );
if ( unique != 0 ) // More servers left, send another request to master
{
unsigned char c[10];
int i = 0;
// Request a server list from the master servers.
NET_Config( true ); // Initialize networking
c[0] = A2M_GET_SERVERS_BATCH;
i++;
*(int *)&c[1] = unique; // Request servers starting after this unique id.
i += sizeof( int );
// send to valve master
Con_DPrintf ("Requesting next batch ( %i ) server list from %s\n", unique, NET_AdrToString ( net_from ) );
NET_SendPacket (NS_CLIENT, i, c, net_from );
}
else
Con_Printf( "Done.\n" );
}