sv_main.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "qwsvdef.h"
  16. quakeparms_t host_parms;
  17. qboolean host_initialized; // true if into command execution (compatability)
  18. double host_frametime;
  19. double realtime; // without any filtering or bounding
  20. int host_hunklevel;
  21. netadr_t master_adr[MAX_MASTERS]; // address of group servers
  22. client_t *host_client; // current client
  23. cvar_t sv_mintic = {"sv_mintic","0.03"}; // bound the size of the
  24. cvar_t sv_maxtic = {"sv_maxtic","0.1"}; // physics time tic
  25. cvar_t developer = {"developer","0"}; // show extra messages
  26. cvar_t timeout = {"timeout","65"}; // seconds without any message
  27. cvar_t zombietime = {"zombietime", "2"}; // seconds to sink messages
  28. // after disconnect
  29. cvar_t rcon_password = {"rcon_password", ""}; // password for remote server commands
  30. cvar_t password = {"password", ""}; // password for entering the game
  31. cvar_t spectator_password = {"spectator_password", ""}; // password for entering as a sepctator
  32. cvar_t allow_download = {"allow_download", "1"};
  33. cvar_t allow_download_skins = {"allow_download_skins", "1"};
  34. cvar_t allow_download_models = {"allow_download_models", "1"};
  35. cvar_t allow_download_sounds = {"allow_download_sounds", "1"};
  36. cvar_t allow_download_maps = {"allow_download_maps", "1"};
  37. cvar_t sv_highchars = {"sv_highchars", "1"};
  38. cvar_t sv_phs = {"sv_phs", "1"};
  39. cvar_t pausable = {"pausable", "1"};
  40. //
  41. // game rules mirrored in svs.info
  42. //
  43. cvar_t fraglimit = {"fraglimit","0",false,true};
  44. cvar_t timelimit = {"timelimit","0",false,true};
  45. cvar_t teamplay = {"teamplay","0",false,true};
  46. cvar_t samelevel = {"samelevel","0", false, true};
  47. cvar_t maxclients = {"maxclients","8", false, true};
  48. cvar_t maxspectators = {"maxspectators","8", false, true};
  49. cvar_t deathmatch = {"deathmatch","1", false, true}; // 0, 1, or 2
  50. cvar_t spawn = {"spawn","0", false, true};
  51. cvar_t watervis = {"watervis", "0", false, true};
  52. cvar_t hostname = {"hostname","unnamed", false, true};
  53. FILE *sv_logfile;
  54. FILE *sv_fraglogfile;
  55. void SV_AcceptClient (netadr_t adr, int userid, char *userinfo);
  56. void Master_Shutdown (void);
  57. //============================================================================
  58. qboolean ServerPaused(void)
  59. {
  60. return sv.paused;
  61. }
  62. /*
  63. ================
  64. SV_Shutdown
  65. Quake calls this before calling Sys_Quit or Sys_Error
  66. ================
  67. */
  68. void SV_Shutdown (void)
  69. {
  70. Master_Shutdown ();
  71. if (sv_logfile)
  72. {
  73. fclose (sv_logfile);
  74. sv_logfile = NULL;
  75. }
  76. if (sv_fraglogfile)
  77. {
  78. fclose (sv_fraglogfile);
  79. sv_logfile = NULL;
  80. }
  81. NET_Shutdown ();
  82. }
  83. /*
  84. ================
  85. SV_Error
  86. Sends a datagram to all the clients informing them of the server crash,
  87. then exits
  88. ================
  89. */
  90. void SV_Error (char *error, ...)
  91. {
  92. va_list argptr;
  93. static char string[1024];
  94. static qboolean inerror = false;
  95. if (inerror)
  96. Sys_Error ("SV_Error: recursively entered (%s)", string);
  97. inerror = true;
  98. va_start (argptr,error);
  99. vsprintf (string,error,argptr);
  100. va_end (argptr);
  101. Con_Printf ("SV_Error: %s\n",string);
  102. SV_FinalMessage (va("server crashed: %s\n", string));
  103. SV_Shutdown ();
  104. Sys_Error ("SV_Error: %s\n",string);
  105. }
  106. /*
  107. ==================
  108. SV_FinalMessage
  109. Used by SV_Error and SV_Quit_f to send a final message to all connected
  110. clients before the server goes down. The messages are sent immediately,
  111. not just stuck on the outgoing message list, because the server is going
  112. to totally exit after returning from this function.
  113. ==================
  114. */
  115. void SV_FinalMessage (char *message)
  116. {
  117. int i;
  118. client_t *cl;
  119. SZ_Clear (&net_message);
  120. MSG_WriteByte (&net_message, svc_print);
  121. MSG_WriteByte (&net_message, PRINT_HIGH);
  122. MSG_WriteString (&net_message, message);
  123. MSG_WriteByte (&net_message, svc_disconnect);
  124. for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
  125. if (cl->state >= cs_spawned)
  126. Netchan_Transmit (&cl->netchan, net_message.cursize
  127. , net_message.data);
  128. }
  129. /*
  130. =====================
  131. SV_DropClient
  132. Called when the player is totally leaving the server, either willingly
  133. or unwillingly. This is NOT called if the entire server is quiting
  134. or crashing.
  135. =====================
  136. */
  137. void SV_DropClient (client_t *drop)
  138. {
  139. // add the disconnect
  140. MSG_WriteByte (&drop->netchan.message, svc_disconnect);
  141. if (drop->state == cs_spawned)
  142. if (!drop->spectator)
  143. {
  144. // call the prog function for removing a client
  145. // this will set the body to a dead frame, among other things
  146. pr_global_struct->self = EDICT_TO_PROG(drop->edict);
  147. PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
  148. }
  149. else if (SpectatorDisconnect)
  150. {
  151. // call the prog function for removing a client
  152. // this will set the body to a dead frame, among other things
  153. pr_global_struct->self = EDICT_TO_PROG(drop->edict);
  154. PR_ExecuteProgram (SpectatorDisconnect);
  155. }
  156. if (drop->spectator)
  157. Con_Printf ("Spectator %s removed\n",drop->name);
  158. else
  159. Con_Printf ("Client %s removed\n",drop->name);
  160. if (drop->download)
  161. {
  162. fclose (drop->download);
  163. drop->download = NULL;
  164. }
  165. if (drop->upload)
  166. {
  167. fclose (drop->upload);
  168. drop->upload = NULL;
  169. }
  170. *drop->uploadfn = 0;
  171. drop->state = cs_zombie; // become free in a few seconds
  172. drop->connection_started = realtime; // for zombie timeout
  173. drop->old_frags = 0;
  174. drop->edict->v.frags = 0;
  175. drop->name[0] = 0;
  176. memset (drop->userinfo, 0, sizeof(drop->userinfo));
  177. // send notification to all remaining clients
  178. SV_FullClientUpdate (drop, &sv.reliable_datagram);
  179. }
  180. //====================================================================
  181. /*
  182. ===================
  183. SV_CalcPing
  184. ===================
  185. */
  186. int SV_CalcPing (client_t *cl)
  187. {
  188. float ping;
  189. int i;
  190. int count;
  191. register client_frame_t *frame;
  192. ping = 0;
  193. count = 0;
  194. for (frame = cl->frames, i=0 ; i<UPDATE_BACKUP ; i++, frame++)
  195. {
  196. if (frame->ping_time > 0)
  197. {
  198. ping += frame->ping_time;
  199. count++;
  200. }
  201. }
  202. if (!count)
  203. return 9999;
  204. ping /= count;
  205. return ping*1000;
  206. }
  207. /*
  208. ===================
  209. SV_FullClientUpdate
  210. Writes all update values to a sizebuf
  211. ===================
  212. */
  213. void SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
  214. {
  215. int i;
  216. char info[MAX_INFO_STRING];
  217. i = client - svs.clients;
  218. //Sys_Printf("SV_FullClientUpdate: Updated frags for client %d\n", i);
  219. MSG_WriteByte (buf, svc_updatefrags);
  220. MSG_WriteByte (buf, i);
  221. MSG_WriteShort (buf, client->old_frags);
  222. MSG_WriteByte (buf, svc_updateping);
  223. MSG_WriteByte (buf, i);
  224. MSG_WriteShort (buf, SV_CalcPing (client));
  225. MSG_WriteByte (buf, svc_updatepl);
  226. MSG_WriteByte (buf, i);
  227. MSG_WriteByte (buf, client->lossage);
  228. MSG_WriteByte (buf, svc_updateentertime);
  229. MSG_WriteByte (buf, i);
  230. MSG_WriteFloat (buf, realtime - client->connection_started);
  231. strcpy (info, client->userinfo);
  232. Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
  233. MSG_WriteByte (buf, svc_updateuserinfo);
  234. MSG_WriteByte (buf, i);
  235. MSG_WriteLong (buf, client->userid);
  236. MSG_WriteString (buf, info);
  237. }
  238. /*
  239. ===================
  240. SV_FullClientUpdateToClient
  241. Writes all update values to a client's reliable stream
  242. ===================
  243. */
  244. void SV_FullClientUpdateToClient (client_t *client, client_t *cl)
  245. {
  246. ClientReliableCheckBlock(cl, 24 + strlen(client->userinfo));
  247. if (cl->num_backbuf) {
  248. SV_FullClientUpdate (client, &cl->backbuf);
  249. ClientReliable_FinishWrite(cl);
  250. } else
  251. SV_FullClientUpdate (client, &cl->netchan.message);
  252. }
  253. /*
  254. ==============================================================================
  255. CONNECTIONLESS COMMANDS
  256. ==============================================================================
  257. */
  258. /*
  259. ================
  260. SVC_Status
  261. Responds with all the info that qplug or qspy can see
  262. This message can be up to around 5k with worst case string lengths.
  263. ================
  264. */
  265. void SVC_Status (void)
  266. {
  267. int i;
  268. client_t *cl;
  269. int ping;
  270. int top, bottom;
  271. Cmd_TokenizeString ("status");
  272. SV_BeginRedirect (RD_PACKET);
  273. Con_Printf ("%s\n", svs.info);
  274. for (i=0 ; i<MAX_CLIENTS ; i++)
  275. {
  276. cl = &svs.clients[i];
  277. if ((cl->state == cs_connected || cl->state == cs_spawned ) && !cl->spectator)
  278. {
  279. top = atoi(Info_ValueForKey (cl->userinfo, "topcolor"));
  280. bottom = atoi(Info_ValueForKey (cl->userinfo, "bottomcolor"));
  281. top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
  282. bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
  283. ping = SV_CalcPing (cl);
  284. Con_Printf ("%i %i %i %i \"%s\" \"%s\" %i %i\n", cl->userid,
  285. cl->old_frags, (int)(realtime - cl->connection_started)/60,
  286. ping, cl->name, Info_ValueForKey (cl->userinfo, "skin"), top, bottom);
  287. }
  288. }
  289. SV_EndRedirect ();
  290. }
  291. /*
  292. ===================
  293. SV_CheckLog
  294. ===================
  295. */
  296. #define LOG_HIGHWATER 4096
  297. #define LOG_FLUSH 10*60
  298. void SV_CheckLog (void)
  299. {
  300. sizebuf_t *sz;
  301. sz = &svs.log[svs.logsequence&1];
  302. // bump sequence if allmost full, or ten minutes have passed and
  303. // there is something still sitting there
  304. if (sz->cursize > LOG_HIGHWATER
  305. || (realtime - svs.logtime > LOG_FLUSH && sz->cursize) )
  306. {
  307. // swap buffers and bump sequence
  308. svs.logtime = realtime;
  309. svs.logsequence++;
  310. sz = &svs.log[svs.logsequence&1];
  311. sz->cursize = 0;
  312. Con_Printf ("beginning fraglog sequence %i\n", svs.logsequence);
  313. }
  314. }
  315. /*
  316. ================
  317. SVC_Log
  318. Responds with all the logged frags for ranking programs.
  319. If a sequence number is passed as a parameter and it is
  320. the same as the current sequence, an A2A_NACK will be returned
  321. instead of the data.
  322. ================
  323. */
  324. void SVC_Log (void)
  325. {
  326. int seq;
  327. char data[MAX_DATAGRAM+64];
  328. if (Cmd_Argc() == 2)
  329. seq = atoi(Cmd_Argv(1));
  330. else
  331. seq = -1;
  332. if (seq == svs.logsequence-1 || !sv_fraglogfile)
  333. { // they allready have this data, or we aren't logging frags
  334. data[0] = A2A_NACK;
  335. NET_SendPacket (1, data, net_from);
  336. return;
  337. }
  338. Con_DPrintf ("sending log %i to %s\n", svs.logsequence-1, NET_AdrToString(net_from));
  339. sprintf (data, "stdlog %i\n", svs.logsequence-1);
  340. strcat (data, (char *)svs.log_buf[((svs.logsequence-1)&1)]);
  341. NET_SendPacket (strlen(data)+1, data, net_from);
  342. }
  343. /*
  344. ================
  345. SVC_Ping
  346. Just responds with an acknowledgement
  347. ================
  348. */
  349. void SVC_Ping (void)
  350. {
  351. char data;
  352. data = A2A_ACK;
  353. NET_SendPacket (1, &data, net_from);
  354. }
  355. /*
  356. =================
  357. SVC_GetChallenge
  358. Returns a challenge number that can be used
  359. in a subsequent client_connect command.
  360. We do this to prevent denial of service attacks that
  361. flood the server with invalid connection IPs. With a
  362. challenge, they must give a valid IP address.
  363. =================
  364. */
  365. void SVC_GetChallenge (void)
  366. {
  367. int i;
  368. int oldest;
  369. int oldestTime;
  370. oldest = 0;
  371. oldestTime = 0x7fffffff;
  372. // see if we already have a challenge for this ip
  373. for (i = 0 ; i < MAX_CHALLENGES ; i++)
  374. {
  375. if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
  376. break;
  377. if (svs.challenges[i].time < oldestTime)
  378. {
  379. oldestTime = svs.challenges[i].time;
  380. oldest = i;
  381. }
  382. }
  383. if (i == MAX_CHALLENGES)
  384. {
  385. // overwrite the oldest
  386. svs.challenges[oldest].challenge = (rand() << 16) ^ rand();
  387. svs.challenges[oldest].adr = net_from;
  388. svs.challenges[oldest].time = realtime;
  389. i = oldest;
  390. }
  391. // send it back
  392. Netchan_OutOfBandPrint (net_from, "%c%i", S2C_CHALLENGE,
  393. svs.challenges[i].challenge);
  394. }
  395. /*
  396. ==================
  397. SVC_DirectConnect
  398. A connection request that did not come from the master
  399. ==================
  400. */
  401. void SVC_DirectConnect (void)
  402. {
  403. char userinfo[1024];
  404. static int userid;
  405. netadr_t adr;
  406. int i;
  407. client_t *cl, *newcl;
  408. client_t temp;
  409. edict_t *ent;
  410. int edictnum;
  411. char *s;
  412. int clients, spectators;
  413. qboolean spectator;
  414. int qport;
  415. int version;
  416. int challenge;
  417. version = atoi(Cmd_Argv(1));
  418. if (version != PROTOCOL_VERSION)
  419. {
  420. Netchan_OutOfBandPrint (net_from, "%c\nServer is version %4.2f.\n", A2C_PRINT, VERSION);
  421. Con_Printf ("* rejected connect from version %i\n", version);
  422. return;
  423. }
  424. qport = atoi(Cmd_Argv(2));
  425. challenge = atoi(Cmd_Argv(3));
  426. // note an extra byte is needed to replace spectator key
  427. strncpy (userinfo, Cmd_Argv(4), sizeof(userinfo)-2);
  428. userinfo[sizeof(userinfo) - 2] = 0;
  429. // see if the challenge is valid
  430. for (i=0 ; i<MAX_CHALLENGES ; i++)
  431. {
  432. if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
  433. {
  434. if (challenge == svs.challenges[i].challenge)
  435. break; // good
  436. Netchan_OutOfBandPrint (net_from, "%c\nBad challenge.\n", A2C_PRINT);
  437. return;
  438. }
  439. }
  440. if (i == MAX_CHALLENGES)
  441. {
  442. Netchan_OutOfBandPrint (net_from, "%c\nNo challenge for address.\n", A2C_PRINT);
  443. return;
  444. }
  445. // check for password or spectator_password
  446. s = Info_ValueForKey (userinfo, "spectator");
  447. if (s[0] && strcmp(s, "0"))
  448. {
  449. if (spectator_password.string[0] &&
  450. stricmp(spectator_password.string, "none") &&
  451. strcmp(spectator_password.string, s) )
  452. { // failed
  453. Con_Printf ("%s:spectator password failed\n", NET_AdrToString (net_from));
  454. Netchan_OutOfBandPrint (net_from, "%c\nrequires a spectator password\n\n", A2C_PRINT);
  455. return;
  456. }
  457. Info_RemoveKey (userinfo, "spectator"); // remove passwd
  458. Info_SetValueForStarKey (userinfo, "*spectator", "1", MAX_INFO_STRING);
  459. spectator = true;
  460. }
  461. else
  462. {
  463. s = Info_ValueForKey (userinfo, "password");
  464. if (password.string[0] &&
  465. stricmp(password.string, "none") &&
  466. strcmp(password.string, s) )
  467. {
  468. Con_Printf ("%s:password failed\n", NET_AdrToString (net_from));
  469. Netchan_OutOfBandPrint (net_from, "%c\nserver requires a password\n\n", A2C_PRINT);
  470. return;
  471. }
  472. spectator = false;
  473. Info_RemoveKey (userinfo, "password"); // remove passwd
  474. }
  475. adr = net_from;
  476. userid++; // so every client gets a unique id
  477. newcl = &temp;
  478. memset (newcl, 0, sizeof(client_t));
  479. newcl->userid = userid;
  480. // works properly
  481. if (!sv_highchars.value) {
  482. byte *p, *q;
  483. for (p = (byte *)newcl->userinfo, q = (byte *)userinfo;
  484. *q && p < (byte *)newcl->userinfo + sizeof(newcl->userinfo)-1; q++)
  485. if (*q > 31 && *q <= 127)
  486. *p++ = *q;
  487. } else
  488. strncpy (newcl->userinfo, userinfo, sizeof(newcl->userinfo)-1);
  489. // if there is allready a slot for this ip, drop it
  490. for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
  491. {
  492. if (cl->state == cs_free)
  493. continue;
  494. if (NET_CompareBaseAdr (adr, cl->netchan.remote_address)
  495. && ( cl->netchan.qport == qport
  496. || adr.port == cl->netchan.remote_address.port ))
  497. {
  498. if (cl->state == cs_connected) {
  499. Con_Printf("%s:dup connect\n", NET_AdrToString (adr));
  500. userid--;
  501. return;
  502. }
  503. Con_Printf ("%s:reconnect\n", NET_AdrToString (adr));
  504. SV_DropClient (cl);
  505. break;
  506. }
  507. }
  508. // count up the clients and spectators
  509. clients = 0;
  510. spectators = 0;
  511. for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
  512. {
  513. if (cl->state == cs_free)
  514. continue;
  515. if (cl->spectator)
  516. spectators++;
  517. else
  518. clients++;
  519. }
  520. // if at server limits, refuse connection
  521. if ( maxclients.value > MAX_CLIENTS )
  522. Cvar_SetValue ("maxclients", MAX_CLIENTS);
  523. if (maxspectators.value > MAX_CLIENTS)
  524. Cvar_SetValue ("maxspectators", MAX_CLIENTS);
  525. if (maxspectators.value + maxclients.value > MAX_CLIENTS)
  526. Cvar_SetValue ("maxspectators", MAX_CLIENTS - maxspectators.value + maxclients.value);
  527. if ( (spectator && spectators >= (int)maxspectators.value)
  528. || (!spectator && clients >= (int)maxclients.value) )
  529. {
  530. Con_Printf ("%s:full connect\n", NET_AdrToString (adr));
  531. Netchan_OutOfBandPrint (adr, "%c\nserver is full\n\n", A2C_PRINT);
  532. return;
  533. }
  534. // find a client slot
  535. newcl = NULL;
  536. for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
  537. {
  538. if (cl->state == cs_free)
  539. {
  540. newcl = cl;
  541. break;
  542. }
  543. }
  544. if (!newcl)
  545. {
  546. Con_Printf ("WARNING: miscounted available clients\n");
  547. return;
  548. }
  549. // build a new connection
  550. // accept the new client
  551. // this is the only place a client_t is ever initialized
  552. *newcl = temp;
  553. Netchan_OutOfBandPrint (adr, "%c", S2C_CONNECTION );
  554. edictnum = (newcl-svs.clients)+1;
  555. Netchan_Setup (&newcl->netchan , adr, qport);
  556. newcl->state = cs_connected;
  557. newcl->datagram.allowoverflow = true;
  558. newcl->datagram.data = newcl->datagram_buf;
  559. newcl->datagram.maxsize = sizeof(newcl->datagram_buf);
  560. // spectator mode can ONLY be set at join time
  561. newcl->spectator = spectator;
  562. ent = EDICT_NUM(edictnum);
  563. newcl->edict = ent;
  564. // parse some info from the info strings
  565. SV_ExtractFromUserinfo (newcl);
  566. // JACK: Init the floodprot stuff.
  567. for (i=0; i<10; i++)
  568. newcl->whensaid[i] = 0.0;
  569. newcl->whensaidhead = 0;
  570. newcl->lockedtill = 0;
  571. // call the progs to get default spawn parms for the new client
  572. PR_ExecuteProgram (pr_global_struct->SetNewParms);
  573. for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
  574. newcl->spawn_parms[i] = (&pr_global_struct->parm1)[i];
  575. if (newcl->spectator)
  576. Con_Printf ("Spectator %s connected\n", newcl->name);
  577. else
  578. Con_DPrintf ("Client %s connected\n", newcl->name);
  579. newcl->sendinfo = true;
  580. }
  581. int Rcon_Validate (void)
  582. {
  583. if (!strlen (rcon_password.string))
  584. return 0;
  585. if (strcmp (Cmd_Argv(1), rcon_password.string) )
  586. return 0;
  587. return 1;
  588. }
  589. /*
  590. ===============
  591. SVC_RemoteCommand
  592. A client issued an rcon command.
  593. Shift down the remaining args
  594. Redirect all printfs
  595. ===============
  596. */
  597. void SVC_RemoteCommand (void)
  598. {
  599. int i;
  600. char remaining[1024];
  601. if (!Rcon_Validate ()) {
  602. Con_Printf ("Bad rcon from %s:\n%s\n"
  603. , NET_AdrToString (net_from), net_message.data+4);
  604. SV_BeginRedirect (RD_PACKET);
  605. Con_Printf ("Bad rcon_password.\n");
  606. } else {
  607. Con_Printf ("Rcon from %s:\n%s\n"
  608. , NET_AdrToString (net_from), net_message.data+4);
  609. SV_BeginRedirect (RD_PACKET);
  610. remaining[0] = 0;
  611. for (i=2 ; i<Cmd_Argc() ; i++)
  612. {
  613. strcat (remaining, Cmd_Argv(i) );
  614. strcat (remaining, " ");
  615. }
  616. Cmd_ExecuteString (remaining);
  617. }
  618. SV_EndRedirect ();
  619. }
  620. /*
  621. =================
  622. SV_ConnectionlessPacket
  623. A connectionless packet has four leading 0xff
  624. characters to distinguish it from a game channel.
  625. Clients that are in the game can still send
  626. connectionless packets.
  627. =================
  628. */
  629. void SV_ConnectionlessPacket (void)
  630. {
  631. char *s;
  632. char *c;
  633. MSG_BeginReading ();
  634. MSG_ReadLong (); // skip the -1 marker
  635. s = MSG_ReadStringLine ();
  636. Cmd_TokenizeString (s);
  637. c = Cmd_Argv(0);
  638. if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) )
  639. {
  640. SVC_Ping ();
  641. return;
  642. }
  643. if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') )
  644. {
  645. Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (net_from));
  646. return;
  647. }
  648. else if (!strcmp(c,"status"))
  649. {
  650. SVC_Status ();
  651. return;
  652. }
  653. else if (!strcmp(c,"log"))
  654. {
  655. SVC_Log ();
  656. return;
  657. }
  658. else if (!strcmp(c,"connect"))
  659. {
  660. SVC_DirectConnect ();
  661. return;
  662. }
  663. else if (!strcmp(c,"getchallenge"))
  664. {
  665. SVC_GetChallenge ();
  666. return;
  667. }
  668. else if (!strcmp(c, "rcon"))
  669. SVC_RemoteCommand ();
  670. else
  671. Con_Printf ("bad connectionless packet from %s:\n%s\n"
  672. , NET_AdrToString (net_from), s);
  673. }
  674. /*
  675. ==============================================================================
  676. PACKET FILTERING
  677. You can add or remove addresses from the filter list with:
  678. addip <ip>
  679. removeip <ip>
  680. The ip address is specified in dot format, and any unspecified digits will match any value, so you can specify an entire class C network with "addip 192.246.40".
  681. Removeip will only remove an address specified exactly the same way. You cannot addip a subnet, then removeip a single host.
  682. listip
  683. Prints the current list of filters.
  684. writeip
  685. Dumps "addip <ip>" commands to listip.cfg so it can be execed at a later date. The filter lists are not saved and restored by default, because I beleive it would cause too much confusion.
  686. filterban <0 or 1>
  687. If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game. This is the default setting.
  688. If 0, then only addresses matching the list will be allowed. This lets you easily set up a private game, or a game that only allows players from your local network.
  689. ==============================================================================
  690. */
  691. typedef struct
  692. {
  693. unsigned mask;
  694. unsigned compare;
  695. } ipfilter_t;
  696. #define MAX_IPFILTERS 1024
  697. ipfilter_t ipfilters[MAX_IPFILTERS];
  698. int numipfilters;
  699. cvar_t filterban = {"filterban", "1"};
  700. /*
  701. =================
  702. StringToFilter
  703. =================
  704. */
  705. qboolean StringToFilter (char *s, ipfilter_t *f)
  706. {
  707. char num[128];
  708. int i, j;
  709. byte b[4];
  710. byte m[4];
  711. for (i=0 ; i<4 ; i++)
  712. {
  713. b[i] = 0;
  714. m[i] = 0;
  715. }
  716. for (i=0 ; i<4 ; i++)
  717. {
  718. if (*s < '0' || *s > '9')
  719. {
  720. Con_Printf ("Bad filter address: %s\n", s);
  721. return false;
  722. }
  723. j = 0;
  724. while (*s >= '0' && *s <= '9')
  725. {
  726. num[j++] = *s++;
  727. }
  728. num[j] = 0;
  729. b[i] = atoi(num);
  730. if (b[i] != 0)
  731. m[i] = 255;
  732. if (!*s)
  733. break;
  734. s++;
  735. }
  736. f->mask = *(unsigned *)m;
  737. f->compare = *(unsigned *)b;
  738. return true;
  739. }
  740. /*
  741. =================
  742. SV_AddIP_f
  743. =================
  744. */
  745. void SV_AddIP_f (void)
  746. {
  747. int i;
  748. for (i=0 ; i<numipfilters ; i++)
  749. if (ipfilters[i].compare == 0xffffffff)
  750. break; // free spot
  751. if (i == numipfilters)
  752. {
  753. if (numipfilters == MAX_IPFILTERS)
  754. {
  755. Con_Printf ("IP filter list is full\n");
  756. return;
  757. }
  758. numipfilters++;
  759. }
  760. if (!StringToFilter (Cmd_Argv(1), &ipfilters[i]))
  761. ipfilters[i].compare = 0xffffffff;
  762. }
  763. /*
  764. =================
  765. SV_RemoveIP_f
  766. =================
  767. */
  768. void SV_RemoveIP_f (void)
  769. {
  770. ipfilter_t f;
  771. int i, j;
  772. if (!StringToFilter (Cmd_Argv(1), &f))
  773. return;
  774. for (i=0 ; i<numipfilters ; i++)
  775. if (ipfilters[i].mask == f.mask
  776. && ipfilters[i].compare == f.compare)
  777. {
  778. for (j=i+1 ; j<numipfilters ; j++)
  779. ipfilters[j-1] = ipfilters[j];
  780. numipfilters--;
  781. Con_Printf ("Removed.\n");
  782. return;
  783. }
  784. Con_Printf ("Didn't find %s.\n", Cmd_Argv(1));
  785. }
  786. /*
  787. =================
  788. SV_ListIP_f
  789. =================
  790. */
  791. void SV_ListIP_f (void)
  792. {
  793. int i;
  794. byte b[4];
  795. Con_Printf ("Filter list:\n");
  796. for (i=0 ; i<numipfilters ; i++)
  797. {
  798. *(unsigned *)b = ipfilters[i].compare;
  799. Con_Printf ("%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]);
  800. }
  801. }
  802. /*
  803. =================
  804. SV_WriteIP_f
  805. =================
  806. */
  807. void SV_WriteIP_f (void)
  808. {
  809. FILE *f;
  810. char name[MAX_OSPATH];
  811. byte b[4];
  812. int i;
  813. sprintf (name, "%s/listip.cfg", com_gamedir);
  814. Con_Printf ("Writing %s.\n", name);
  815. f = fopen (name, "wb");
  816. if (!f)
  817. {
  818. Con_Printf ("Couldn't open %s\n", name);
  819. return;
  820. }
  821. for (i=0 ; i<numipfilters ; i++)
  822. {
  823. *(unsigned *)b = ipfilters[i].compare;
  824. fprintf (f, "addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
  825. }
  826. fclose (f);
  827. }
  828. /*
  829. =================
  830. SV_SendBan
  831. =================
  832. */
  833. void SV_SendBan (void)
  834. {
  835. char data[128];
  836. data[0] = data[1] = data[2] = data[3] = 0xff;
  837. data[4] = A2C_PRINT;
  838. data[5] = 0;
  839. strcat (data, "\nbanned.\n");
  840. NET_SendPacket (strlen(data), data, net_from);
  841. }
  842. /*
  843. =================
  844. SV_FilterPacket
  845. =================
  846. */
  847. qboolean SV_FilterPacket (void)
  848. {
  849. int i;
  850. unsigned in;
  851. in = *(unsigned *)net_from.ip;
  852. for (i=0 ; i<numipfilters ; i++)
  853. if ( (in & ipfilters[i].mask) == ipfilters[i].compare)
  854. return filterban.value;
  855. return !filterban.value;
  856. }
  857. //============================================================================
  858. /*
  859. =================
  860. SV_ReadPackets
  861. =================
  862. */
  863. void SV_ReadPackets (void)
  864. {
  865. int i;
  866. client_t *cl;
  867. qboolean good;
  868. int qport;
  869. good = false;
  870. while (NET_GetPacket ())
  871. {
  872. if (SV_FilterPacket ())
  873. {
  874. SV_SendBan (); // tell them we aren't listening...
  875. continue;
  876. }
  877. // check for connectionless packet (0xffffffff) first
  878. if (*(int *)net_message.data == -1)
  879. {
  880. SV_ConnectionlessPacket ();
  881. continue;
  882. }
  883. // read the qport out of the message so we can fix up
  884. // stupid address translating routers
  885. MSG_BeginReading ();
  886. MSG_ReadLong (); // sequence number
  887. MSG_ReadLong (); // sequence number
  888. qport = MSG_ReadShort () & 0xffff;
  889. // check for packets from connected clients
  890. for (i=0, cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
  891. {
  892. if (cl->state == cs_free)
  893. continue;
  894. if (!NET_CompareBaseAdr (net_from, cl->netchan.remote_address))
  895. continue;
  896. if (cl->netchan.qport != qport)
  897. continue;
  898. if (cl->netchan.remote_address.port != net_from.port)
  899. {
  900. Con_DPrintf ("SV_ReadPackets: fixing up a translated port\n");
  901. cl->netchan.remote_address.port = net_from.port;
  902. }
  903. if (Netchan_Process(&cl->netchan))
  904. { // this is a valid, sequenced packet, so process it
  905. svs.stats.packets++;
  906. good = true;
  907. cl->send_message = true; // reply at end of frame
  908. if (cl->state != cs_zombie)
  909. SV_ExecuteClientMessage (cl);
  910. }
  911. break;
  912. }
  913. if (i != MAX_CLIENTS)
  914. continue;
  915. // packet is not from a known client
  916. // Con_Printf ("%s:sequenced packet without connection\n"
  917. // ,NET_AdrToString(net_from));
  918. }
  919. }
  920. /*
  921. ==================
  922. SV_CheckTimeouts
  923. If a packet has not been received from a client in timeout.value
  924. seconds, drop the conneciton.
  925. When a client is normally dropped, the client_t goes into a zombie state
  926. for a few seconds to make sure any final reliable message gets resent
  927. if necessary
  928. ==================
  929. */
  930. void SV_CheckTimeouts (void)
  931. {
  932. int i;
  933. client_t *cl;
  934. float droptime;
  935. int nclients;
  936. droptime = realtime - timeout.value;
  937. nclients = 0;
  938. for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
  939. {
  940. if (cl->state == cs_connected || cl->state == cs_spawned) {
  941. if (!cl->spectator)
  942. nclients++;
  943. if (cl->netchan.last_received < droptime) {
  944. SV_BroadcastPrintf (PRINT_HIGH, "%s timed out\n", cl->name);
  945. SV_DropClient (cl);
  946. cl->state = cs_free; // don't bother with zombie state
  947. }
  948. }
  949. if (cl->state == cs_zombie &&
  950. realtime - cl->connection_started > zombietime.value)
  951. {
  952. cl->state = cs_free; // can now be reused
  953. }
  954. }
  955. if (sv.paused && !nclients) {
  956. // nobody left, unpause the server
  957. SV_TogglePause("Pause released since no players are left.\n");
  958. }
  959. }
  960. /*
  961. ===================
  962. SV_GetConsoleCommands
  963. Add them exactly as if they had been typed at the console
  964. ===================
  965. */
  966. void SV_GetConsoleCommands (void)
  967. {
  968. char *cmd;
  969. while (1)
  970. {
  971. cmd = Sys_ConsoleInput ();
  972. if (!cmd)
  973. break;
  974. Cbuf_AddText (cmd);
  975. }
  976. }
  977. /*
  978. ===================
  979. SV_CheckVars
  980. ===================
  981. */
  982. void SV_CheckVars (void)
  983. {
  984. static char *pw, *spw;
  985. int v;
  986. if (password.string == pw && spectator_password.string == spw)
  987. return;
  988. pw = password.string;
  989. spw = spectator_password.string;
  990. v = 0;
  991. if (pw && pw[0] && strcmp(pw, "none"))
  992. v |= 1;
  993. if (spw && spw[0] && strcmp(spw, "none"))
  994. v |= 2;
  995. Con_Printf ("Updated needpass.\n");
  996. if (!v)
  997. Info_SetValueForKey (svs.info, "needpass", "", MAX_SERVERINFO_STRING);
  998. else
  999. Info_SetValueForKey (svs.info, "needpass", va("%i",v), MAX_SERVERINFO_STRING);
  1000. }
  1001. /*
  1002. ==================
  1003. SV_Frame
  1004. ==================
  1005. */
  1006. void SV_Frame (float time)
  1007. {
  1008. static double start, end;
  1009. start = Sys_DoubleTime ();
  1010. svs.stats.idle += start - end;
  1011. // keep the random time dependent
  1012. rand ();
  1013. // decide the simulation time
  1014. if (!sv.paused) {
  1015. realtime += time;
  1016. sv.time += time;
  1017. }
  1018. // check timeouts
  1019. SV_CheckTimeouts ();
  1020. // toggle the log buffer if full
  1021. SV_CheckLog ();
  1022. // move autonomous things around if enough time has passed
  1023. if (!sv.paused)
  1024. SV_Physics ();
  1025. // get packets
  1026. SV_ReadPackets ();
  1027. // check for commands typed to the host
  1028. SV_GetConsoleCommands ();
  1029. // process console commands
  1030. Cbuf_Execute ();
  1031. SV_CheckVars ();
  1032. // send messages back to the clients that had packets read this frame
  1033. SV_SendClientMessages ();
  1034. // send a heartbeat to the master if needed
  1035. Master_Heartbeat ();
  1036. // collect timing statistics
  1037. end = Sys_DoubleTime ();
  1038. svs.stats.active += end-start;
  1039. if (++svs.stats.count == STATFRAMES)
  1040. {
  1041. svs.stats.latched_active = svs.stats.active;
  1042. svs.stats.latched_idle = svs.stats.idle;
  1043. svs.stats.latched_packets = svs.stats.packets;
  1044. svs.stats.active = 0;
  1045. svs.stats.idle = 0;
  1046. svs.stats.packets = 0;
  1047. svs.stats.count = 0;
  1048. }
  1049. }
  1050. /*
  1051. ===============
  1052. SV_InitLocal
  1053. ===============
  1054. */
  1055. void SV_InitLocal (void)
  1056. {
  1057. int i;
  1058. extern cvar_t sv_maxvelocity;
  1059. extern cvar_t sv_gravity;
  1060. extern cvar_t sv_aim;
  1061. extern cvar_t sv_stopspeed;
  1062. extern cvar_t sv_spectatormaxspeed;
  1063. extern cvar_t sv_accelerate;
  1064. extern cvar_t sv_airaccelerate;
  1065. extern cvar_t sv_wateraccelerate;
  1066. extern cvar_t sv_friction;
  1067. extern cvar_t sv_waterfriction;
  1068. SV_InitOperatorCommands ();
  1069. SV_UserInit ();
  1070. Cvar_RegisterVariable (&rcon_password);
  1071. Cvar_RegisterVariable (&password);
  1072. Cvar_RegisterVariable (&spectator_password);
  1073. Cvar_RegisterVariable (&sv_mintic);
  1074. Cvar_RegisterVariable (&sv_maxtic);
  1075. Cvar_RegisterVariable (&fraglimit);
  1076. Cvar_RegisterVariable (&timelimit);
  1077. Cvar_RegisterVariable (&teamplay);
  1078. Cvar_RegisterVariable (&samelevel);
  1079. Cvar_RegisterVariable (&maxclients);
  1080. Cvar_RegisterVariable (&maxspectators);
  1081. Cvar_RegisterVariable (&hostname);
  1082. Cvar_RegisterVariable (&deathmatch);
  1083. Cvar_RegisterVariable (&spawn);
  1084. Cvar_RegisterVariable (&watervis);
  1085. Cvar_RegisterVariable (&developer);
  1086. Cvar_RegisterVariable (&timeout);
  1087. Cvar_RegisterVariable (&zombietime);
  1088. Cvar_RegisterVariable (&sv_maxvelocity);
  1089. Cvar_RegisterVariable (&sv_gravity);
  1090. Cvar_RegisterVariable (&sv_stopspeed);
  1091. Cvar_RegisterVariable (&sv_maxspeed);
  1092. Cvar_RegisterVariable (&sv_spectatormaxspeed);
  1093. Cvar_RegisterVariable (&sv_accelerate);
  1094. Cvar_RegisterVariable (&sv_airaccelerate);
  1095. Cvar_RegisterVariable (&sv_wateraccelerate);
  1096. Cvar_RegisterVariable (&sv_friction);
  1097. Cvar_RegisterVariable (&sv_waterfriction);
  1098. Cvar_RegisterVariable (&sv_aim);
  1099. Cvar_RegisterVariable (&filterban);
  1100. Cvar_RegisterVariable (&allow_download);
  1101. Cvar_RegisterVariable (&allow_download_skins);
  1102. Cvar_RegisterVariable (&allow_download_models);
  1103. Cvar_RegisterVariable (&allow_download_sounds);
  1104. Cvar_RegisterVariable (&allow_download_maps);
  1105. Cvar_RegisterVariable (&sv_highchars);
  1106. Cvar_RegisterVariable (&sv_phs);
  1107. Cvar_RegisterVariable (&pausable);
  1108. Cmd_AddCommand ("addip", SV_AddIP_f);
  1109. Cmd_AddCommand ("removeip", SV_RemoveIP_f);
  1110. Cmd_AddCommand ("listip", SV_ListIP_f);
  1111. Cmd_AddCommand ("writeip", SV_WriteIP_f);
  1112. for (i=0 ; i<MAX_MODELS ; i++)
  1113. sprintf (localmodels[i], "*%i", i);
  1114. Info_SetValueForStarKey (svs.info, "*version", va("%4.2f", VERSION), MAX_SERVERINFO_STRING);
  1115. // init fraglog stuff
  1116. svs.logsequence = 1;
  1117. svs.logtime = realtime;
  1118. svs.log[0].data = svs.log_buf[0];
  1119. svs.log[0].maxsize = sizeof(svs.log_buf[0]);
  1120. svs.log[0].cursize = 0;
  1121. svs.log[0].allowoverflow = true;
  1122. svs.log[1].data = svs.log_buf[1];
  1123. svs.log[1].maxsize = sizeof(svs.log_buf[1]);
  1124. svs.log[1].cursize = 0;
  1125. svs.log[1].allowoverflow = true;
  1126. }
  1127. //============================================================================
  1128. /*
  1129. ================
  1130. Master_Heartbeat
  1131. Send a message to the master every few minutes to
  1132. let it know we are alive, and log information
  1133. ================
  1134. */
  1135. #define HEARTBEAT_SECONDS 300
  1136. void Master_Heartbeat (void)
  1137. {
  1138. char string[2048];
  1139. int active;
  1140. int i;
  1141. if (realtime - svs.last_heartbeat < HEARTBEAT_SECONDS)
  1142. return; // not time to send yet
  1143. svs.last_heartbeat = realtime;
  1144. //
  1145. // count active users
  1146. //
  1147. active = 0;
  1148. for (i=0 ; i<MAX_CLIENTS ; i++)
  1149. if (svs.clients[i].state == cs_connected ||
  1150. svs.clients[i].state == cs_spawned )
  1151. active++;
  1152. svs.heartbeat_sequence++;
  1153. sprintf (string, "%c\n%i\n%i\n", S2M_HEARTBEAT,
  1154. svs.heartbeat_sequence, active);
  1155. // send to group master
  1156. for (i=0 ; i<MAX_MASTERS ; i++)
  1157. if (master_adr[i].port)
  1158. {
  1159. Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (master_adr[i]));
  1160. NET_SendPacket (strlen(string), string, master_adr[i]);
  1161. }
  1162. }
  1163. /*
  1164. =================
  1165. Master_Shutdown
  1166. Informs all masters that this server is going down
  1167. =================
  1168. */
  1169. void Master_Shutdown (void)
  1170. {
  1171. char string[2048];
  1172. int i;
  1173. sprintf (string, "%c\n", S2M_SHUTDOWN);
  1174. // send to group master
  1175. for (i=0 ; i<MAX_MASTERS ; i++)
  1176. if (master_adr[i].port)
  1177. {
  1178. Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (master_adr[i]));
  1179. NET_SendPacket (strlen(string), string, master_adr[i]);
  1180. }
  1181. }
  1182. /*
  1183. =================
  1184. SV_ExtractFromUserinfo
  1185. Pull specific info from a newly changed userinfo string
  1186. into a more C freindly form.
  1187. =================
  1188. */
  1189. void SV_ExtractFromUserinfo (client_t *cl)
  1190. {
  1191. char *val, *p, *q;
  1192. int i;
  1193. client_t *client;
  1194. int dupc = 1;
  1195. char newname[80];
  1196. // name for C code
  1197. val = Info_ValueForKey (cl->userinfo, "name");
  1198. // trim user name
  1199. strncpy(newname, val, sizeof(newname) - 1);
  1200. newname[sizeof(newname) - 1] = 0;
  1201. for (p = newname; (*p == ' ' || *p == '\r' || *p == '\n') && *p; p++)
  1202. ;
  1203. if (p != newname && !*p) {
  1204. //white space only
  1205. strcpy(newname, "unnamed");
  1206. p = newname;
  1207. }
  1208. if (p != newname && *p) {
  1209. for (q = newname; *p; *q++ = *p++)
  1210. ;
  1211. *q = 0;
  1212. }
  1213. for (p = newname + strlen(newname) - 1; p != newname && (*p == ' ' || *p == '\r' || *p == '\n') ; p--)
  1214. ;
  1215. p[1] = 0;
  1216. if (strcmp(val, newname)) {
  1217. Info_SetValueForKey (cl->userinfo, "name", newname, MAX_INFO_STRING);
  1218. val = Info_ValueForKey (cl->userinfo, "name");
  1219. }
  1220. if (!val[0] || !stricmp(val, "console")) {
  1221. Info_SetValueForKey (cl->userinfo, "name", "unnamed", MAX_INFO_STRING);
  1222. val = Info_ValueForKey (cl->userinfo, "name");
  1223. }
  1224. // check to see if another user by the same name exists
  1225. while (1) {
  1226. for (i=0, client = svs.clients ; i<MAX_CLIENTS ; i++, client++) {
  1227. if (client->state != cs_spawned || client == cl)
  1228. continue;
  1229. if (!stricmp(client->name, val))
  1230. break;
  1231. }
  1232. if (i != MAX_CLIENTS) { // dup name
  1233. if (strlen(val) > sizeof(cl->name) - 1)
  1234. val[sizeof(cl->name) - 4] = 0;
  1235. p = val;
  1236. if (val[0] == '(')
  1237. if (val[2] == ')')
  1238. p = val + 3;
  1239. else if (val[3] == ')')
  1240. p = val + 4;
  1241. sprintf(newname, "(%d)%-.40s", dupc++, p);
  1242. Info_SetValueForKey (cl->userinfo, "name", newname, MAX_INFO_STRING);
  1243. val = Info_ValueForKey (cl->userinfo, "name");
  1244. } else
  1245. break;
  1246. }
  1247. if (strncmp(val, cl->name, strlen(cl->name))) {
  1248. if (!sv.paused) {
  1249. if (!cl->lastnametime || realtime - cl->lastnametime > 5) {
  1250. cl->lastnamecount = 0;
  1251. cl->lastnametime = realtime;
  1252. } else if (cl->lastnamecount++ > 4) {
  1253. SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked for name spam\n", cl->name);
  1254. SV_ClientPrintf (cl, PRINT_HIGH, "You were kicked from the game for name spamming\n");
  1255. SV_DropClient (cl);
  1256. return;
  1257. }
  1258. }
  1259. if (cl->state >= cs_spawned && !cl->spectator)
  1260. SV_BroadcastPrintf (PRINT_HIGH, "%s changed name to %s\n", cl->name, val);
  1261. }
  1262. strncpy (cl->name, val, sizeof(cl->name)-1);
  1263. // rate command
  1264. val = Info_ValueForKey (cl->userinfo, "rate");
  1265. if (strlen(val))
  1266. {
  1267. i = atoi(val);
  1268. if (i < 500)
  1269. i = 500;
  1270. if (i > 10000)
  1271. i = 10000;
  1272. cl->netchan.rate = 1.0/i;
  1273. }
  1274. // msg command
  1275. val = Info_ValueForKey (cl->userinfo, "msg");
  1276. if (strlen(val))
  1277. {
  1278. cl->messagelevel = atoi(val);
  1279. }
  1280. }
  1281. //============================================================================
  1282. /*
  1283. ====================
  1284. SV_InitNet
  1285. ====================
  1286. */
  1287. void SV_InitNet (void)
  1288. {
  1289. int port;
  1290. int p;
  1291. port = PORT_SERVER;
  1292. p = COM_CheckParm ("-port");
  1293. if (p && p < com_argc)
  1294. {
  1295. port = atoi(com_argv[p+1]);
  1296. Con_Printf ("Port: %i\n", port);
  1297. }
  1298. NET_Init (port);
  1299. Netchan_Init ();
  1300. // heartbeats will allways be sent to the id master
  1301. svs.last_heartbeat = -99999; // send immediately
  1302. // NET_StringToAdr ("192.246.40.70:27000", &idmaster_adr);
  1303. }
  1304. /*
  1305. ====================
  1306. SV_Init
  1307. ====================
  1308. */
  1309. void SV_Init (quakeparms_t *parms)
  1310. {
  1311. COM_InitArgv (parms->argc, parms->argv);
  1312. COM_AddParm ("-game");
  1313. COM_AddParm ("qw");
  1314. if (COM_CheckParm ("-minmemory"))
  1315. parms->memsize = MINIMUM_MEMORY;
  1316. host_parms = *parms;
  1317. if (parms->memsize < MINIMUM_MEMORY)
  1318. SV_Error ("Only %4.1f megs of memory reported, can't execute game", parms->memsize / (float)0x100000);
  1319. Memory_Init (parms->membase, parms->memsize);
  1320. Cbuf_Init ();
  1321. Cmd_Init ();
  1322. COM_Init ();
  1323. PR_Init ();
  1324. Mod_Init ();
  1325. SV_InitNet ();
  1326. SV_InitLocal ();
  1327. Sys_Init ();
  1328. Pmove_Init ();
  1329. Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
  1330. host_hunklevel = Hunk_LowMark ();
  1331. Cbuf_InsertText ("exec server.cfg\n");
  1332. host_initialized = true;
  1333. Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
  1334. Con_Printf ("%4.1f megabyte heap\n",parms->memsize/ (1024*1024.0));
  1335. Con_Printf ("\nServer Version %4.2f (Build %04d)\n\n", VERSION, build_number());
  1336. Con_Printf ("======== QuakeWorld Initialized ========\n");
  1337. // process command line arguments
  1338. Cmd_StuffCmds_f ();
  1339. Cbuf_Execute ();
  1340. // if a map wasn't specified on the command line, spawn start.map
  1341. if (sv.state == ss_dead)
  1342. Cmd_ExecuteString ("map start");
  1343. if (sv.state == ss_dead)
  1344. SV_Error ("Couldn't spawn a server");
  1345. }