Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NetServerConfig.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Stars
6  FILE: NetServerConfig.cpp
7  AUTHOR: John DiCamillo
8 
9 */
10 
11 #include "MemDebug.h"
12 #include "NetServerConfig.h"
13 #include "NetUser.h"
14 
15 #include "NetLayer.h"
16 #include "NetAddr.h"
17 #include "NetGame.h"
18 #include "NetHost.h"
19 #include "NetServer.h"
20 #include "HttpServer.h"
21 #include "HttpServletExec.h"
22 #include "NetLobbyServer.h"
23 #include "NetAuth.h"
24 
25 #include "token.h"
26 #include "Game.h"
27 #include "DataLoader.h"
28 #include "ParseUtil.h"
29 #include "Resource.h"
30 
31 // +--------------------------------------------------------------------+
32 
33 NetServerConfig* NetServerConfig::instance = 0;
34 extern const char* versionInfo;
35 
36 // +--------------------------------------------------------------------+
37 
39 {
40  instance = this;
41 
42  name = "Starshatter ";
43  admin_name = "system";
44  admin_pass = "manager";
45  admin_port = 11111;
46  lobby_port = 11100;
47  game_port = 11101;
48  game_type = NET_GAME_PUBLIC;
49  auth_level = NetAuth::NET_AUTH_STANDARD;
50  poolsize = 8;
51  session_timeout = 300;
52 
53  name += versionInfo;
54 
55  Load();
56 }
57 
59 {
60  instance = 0;
61 
62  banned_addrs.destroy();
63  banned_names.destroy();
64 }
65 
66 // +--------------------------------------------------------------------+
67 
68 void
70 {
71  if (!instance)
72  instance = new(__FILE__,__LINE__) NetServerConfig();
73 }
74 
75 void
77 {
78  delete instance;
79  instance = 0;
80 }
81 
82 // +--------------------------------------------------------------------+
83 
84 void
86 {
87  // read the config file:
88  BYTE* block = 0;
89  int blocklen = 0;
90  int port = 0;
91 
92  char filename[64];
93  strcpy_s(filename, "server.cfg");
94 
95  FILE* f;
96  ::fopen_s(&f, filename, "rb");
97 
98  if (f) {
99  ::fseek(f, 0, SEEK_END);
100  blocklen = ftell(f);
101  ::fseek(f, 0, SEEK_SET);
102 
103  block = new(__FILE__,__LINE__) BYTE[blocklen+1];
104  block[blocklen] = 0;
105 
106  ::fread(block, blocklen, 1, f);
107  ::fclose(f);
108  }
109 
110  if (blocklen == 0) {
111  delete [] block;
112  return;
113  }
114 
115  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block, blocklen));
116  Term* term = parser.ParseTerm();
117 
118  if (!term) {
119  Print("ERROR: could not parse '%s'.\n", filename);
120  delete [] block;
121  return;
122  }
123  else {
124  TermText* file_type = term->isText();
125  if (!file_type || file_type->value() != "SERVER_CONFIG") {
126  Print("WARNING: invalid '%s' file. Using defaults\n", filename);
127  delete [] block;
128  return;
129  }
130  }
131 
132  do {
133  delete term;
134 
135  term = parser.ParseTerm();
136 
137  if (term) {
138  TermDef* def = term->isDef();
139  if (def) {
140  if (def->name()->value() == "name") {
141  GetDefText(instance->name, def, filename);
142  }
143 
144  else if (def->name()->value() == "admin_name") {
145  GetDefText(instance->admin_name, def, filename);
146  }
147 
148  else if (def->name()->value() == "admin_pass") {
149  GetDefText(instance->admin_pass, def, filename);
150  }
151 
152  else if (def->name()->value() == "game_pass") {
153  GetDefText(instance->game_pass, def, filename);
154  }
155 
156  else if (def->name()->value() == "mission") {
157  GetDefText(instance->mission, def, filename);
158  }
159 
160  else if (def->name()->value() == "auth_level") {
161  Text level;
162 
163  if (def->term() && def->term()->isText()) {
164  GetDefText(level, def, filename);
165 
166  level.toLower();
167 
168  if (level.indexOf("min") == 0)
169  instance->auth_level = NetAuth::NET_AUTH_MINIMAL;
170 
171  else if (level == "standard" || level == "std")
172  instance->auth_level = NetAuth::NET_AUTH_STANDARD;
173 
174  else if (level == "secure")
175  instance->auth_level = NetAuth::NET_AUTH_SECURE;
176  }
177 
178  else {
179  GetDefNumber(instance->auth_level, def, filename);
180  }
181  }
182 
183  else if (def->name()->value() == "admin_port") {
184  GetDefNumber(port, def, filename);
185  if (port > 1024 && port < 48000)
186  instance->admin_port = (WORD) port;
187  }
188 
189  else if (def->name()->value() == "lobby_port") {
190  GetDefNumber(port, def, filename);
191  if (port > 1024 && port < 48000)
192  instance->lobby_port = (WORD) port;
193  }
194 
195  else if (def->name()->value() == "game_port") {
196  GetDefNumber(port, def, filename);
197  if (port > 1024 && port < 48000)
198  instance->game_port = (WORD) port;
199  }
200 
201  else if (def->name()->value() == "game_type") {
202  Text type;
203  GetDefText(type, def, filename);
204  type.setSensitive(false);
205 
206  if (type == "LAN")
207  instance->game_type = NET_GAME_LAN;
208 
209  else if (type == "private")
210  instance->game_type = NET_GAME_PRIVATE;
211 
212  else
213  instance->game_type = NET_GAME_PUBLIC;
214  }
215 
216  else if (def->name()->value() == "poolsize") {
217  GetDefNumber(instance->poolsize, def, filename);
218  }
219 
220  else if (def->name()->value() == "session_timeout") {
221  GetDefNumber(instance->session_timeout, def, filename);
222  }
223 
224  else
225  Print("WARNING: unknown label '%s' in '%s'\n",
226  def->name()->value().data(), filename);
227  }
228  else {
229  Print("WARNING: term ignored in '%s'\n", filename);
230  term->print();
231  }
232  }
233  }
234  while (term);
235 
236  delete [] block;
237 
238  LoadBanList();
239 }
240 
241 // +--------------------------------------------------------------------+
242 
243 void
245 {
246  FILE* f;
247  fopen_s(&f, "server.cfg", "w");
248  if (f) {
249  fprintf(f, "SERVER_CONFIG\n\n");
250  fprintf(f, "name: \"%s\"\n", instance->name.data());
251  fprintf(f, "admin_name: \"%s\"\n", instance->admin_name.data());
252  fprintf(f, "admin_pass: \"%s\"\n", instance->admin_pass.data());
253  fprintf(f, "game_pass: \"%s\"\n", instance->game_pass.data());
254  fprintf(f, "\n");
255  fprintf(f, "admin_port: %d\n", instance->admin_port);
256  fprintf(f, "lobby_port: %d\n", instance->lobby_port);
257  fprintf(f, "game_port: %d\n", instance->game_port);
258 
259  switch (instance->game_type) {
260  case NET_GAME_LAN:
261  fprintf(f, "game_type: LAN\n");
262  break;
263 
264  case NET_GAME_PRIVATE:
265  fprintf(f, "game_type: private\n");
266  break;
267 
268  case NET_GAME_PUBLIC:
269  default:
270  fprintf(f, "game_type: public\n");
271  break;
272  }
273 
274  switch (instance->auth_level) {
276  fprintf(f, "auth_level: minimal\n");
277  break;
278 
280  default:
281  fprintf(f, "auth_level: standard\n");
282  break;
283 
285  fprintf(f, "auth_level: secure\n");
286  break;
287  }
288 
289  fprintf(f, "\n");
290  fprintf(f, "poolsize: %d\n", instance->poolsize);
291  fprintf(f, "session_timeout: %d\n", instance->session_timeout);
292 
293  if (mission.length() > 0) {
294  fprintf(f, "\nmission: \"%s\"\n", instance->mission.data());
295  }
296 
297  fclose(f);
298  }
299 }
300 
301 // +--------------------------------------------------------------------+
302 
303 Text
304 NetServerConfig::Clean(const char* s)
305 {
306  if (!s || !*s) return Text();
307 
308  int len = strlen(s);
309  char* buff = new(__FILE__,__LINE__) char[len+1];
310  ZeroMemory(buff, len+1);
311 
312  char* p = buff;
313 
314  for (int i = 0; i < len; i++) {
315  char c = s[i];
316 
317  if (c >= 32 && c < 127)
318  *p++ = c;
319  }
320 
321  Text result(buff);
322  delete [] buff;
323 
324  return result;
325 }
326 
327 // +--------------------------------------------------------------------+
328 
329 void
330 NetServerConfig::LoadBanList()
331 {
332  // read the config file:
333  BYTE* block = 0;
334  int blocklen = 0;
335  int port = 0;
336 
337  char filename[64];
338  strcpy_s(filename, "banned.cfg");
339 
340  FILE* f;
341  ::fopen_s(&f, filename, "rb");
342 
343  if (f) {
344  ::fseek(f, 0, SEEK_END);
345  blocklen = ftell(f);
346  ::fseek(f, 0, SEEK_SET);
347 
348  block = new(__FILE__,__LINE__) BYTE[blocklen+1];
349  block[blocklen] = 0;
350 
351  ::fread(block, blocklen, 1, f);
352  ::fclose(f);
353  }
354 
355  if (blocklen == 0) {
356  delete [] block;
357  return;
358  }
359 
360  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block, blocklen));
361  Term* term = parser.ParseTerm();
362 
363  if (!term) {
364  Print("ERROR: could not parse '%s'.\n", filename);
365  delete [] block;
366  return;
367  }
368  else {
369  TermText* file_type = term->isText();
370  if (!file_type || file_type->value() != "BANNED_CONFIG") {
371  Print("WARNING: invalid '%s' file.\n", filename);
372  delete [] block;
373  return;
374  }
375  }
376 
377  banned_addrs.destroy();
378  banned_names.destroy();
379 
380  do {
381  delete term;
382 
383  term = parser.ParseTerm();
384 
385  if (term) {
386  TermDef* def = term->isDef();
387  if (def) {
388  if (def->name()->value() == "name") {
389  Text name;
390  GetDefText(name, def, filename);
391  banned_names.append(new(__FILE__,__LINE__) Text(name));
392  }
393 
394  else if (def->name()->value() == "addr") {
395  DWORD addr;
396  GetDefNumber(addr, def, filename);
397  banned_addrs.append(new(__FILE__,__LINE__) NetAddr(addr));
398  }
399  }
400 
401  else {
402  Print("WARNING: term ignored in '%s'\n", filename);
403  term->print();
404  }
405  }
406  }
407  while (term);
408 
409  delete [] block;
410 }
411 
412 void
414 {
415  if (!user || IsUserBanned(user))
416  return;
417 
418  NetAddr* user_addr = new(__FILE__,__LINE__) NetAddr(user->GetAddress().IPAddr());
419  Text* user_name = new(__FILE__,__LINE__) Text(user->Name());
420 
421  banned_addrs.append(user_addr);
422  banned_names.append(user_name);
423 
424  FILE* f;
425  fopen_s(&f, "banned.cfg", "w");
426  if (f) {
427  fprintf(f, "BANNED_CONFIG\n\n");
428 
429  ListIter<NetAddr> a_iter = banned_addrs;
430  while (++a_iter) {
431  NetAddr* addr = a_iter.value();
432  fprintf(f, "addr: 0x%08x // %d.%d.%d.%d\n",
433  addr->IPAddr(),
434  addr->B1(),
435  addr->B2(),
436  addr->B3(),
437  addr->B4());
438  }
439 
440  fprintf(f, "\n");
441 
442  ListIter<Text> n_iter = banned_names;
443  while (++n_iter) {
444  Text* name = n_iter.value();
445  fprintf(f, "name: \"%s\"\n", name->data());
446  }
447 
448  fclose(f);
449  }
450 }
451 
452 bool
454 {
455  if (user) {
456  NetAddr user_addr = user->GetAddress();
457  Text user_name = user->Name();
458 
459  user_addr.SetPort(0);
460 
461  return banned_addrs.contains(&user_addr) ||
462  banned_names.contains(&user_name);
463  }
464 
465  return false;
466 }
467