AsyncServer.cpp 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "AsyncNetwork.h"
  23. #include "../Session_local.h"
  24. const int MIN_RECONNECT_TIME = 2000;
  25. const int EMPTY_RESEND_TIME = 500;
  26. const int PING_RESEND_TIME = 500;
  27. const int NOINPUT_IDLE_TIME = 30000;
  28. const int HEARTBEAT_MSEC = 5*60*1000;
  29. // must be kept in sync with authReplyMsg_t
  30. const char* authReplyMsg[] = {
  31. // "Waiting for authorization",
  32. "#str_07204",
  33. // "Client unknown to auth",
  34. "#str_07205",
  35. // "Access denied - CD Key in use",
  36. "#str_07206",
  37. // "Auth custom message", // placeholder - we propagate a message from the master
  38. "#str_07207",
  39. // "Authorize Server - Waiting for client"
  40. "#str_07208"
  41. };
  42. const char* authReplyStr[] = {
  43. "AUTH_NONE",
  44. "AUTH_OK",
  45. "AUTH_WAIT",
  46. "AUTH_DENY"
  47. };
  48. /*
  49. ==================
  50. idAsyncServer::idAsyncServer
  51. ==================
  52. */
  53. idAsyncServer::idAsyncServer( void ) {
  54. int i;
  55. active = false;
  56. realTime = 0;
  57. serverTime = 0;
  58. serverId = 0;
  59. serverDataChecksum = 0;
  60. localClientNum = -1;
  61. gameInitId = 0;
  62. gameFrame = 0;
  63. gameTime = 0;
  64. gameTimeResidual = 0;
  65. memset( challenges, 0, sizeof( challenges ) );
  66. memset( userCmds, 0, sizeof( userCmds ) );
  67. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  68. ClearClient( i );
  69. }
  70. serverReloadingEngine = false;
  71. nextHeartbeatTime = 0;
  72. nextAsyncStatsTime = 0;
  73. noRconOutput = true;
  74. lastAuthTime = 0;
  75. memset( stats_outrate, 0, sizeof( stats_outrate ) );
  76. stats_current = 0;
  77. stats_average_sum = 0;
  78. stats_max = 0;
  79. stats_max_index = 0;
  80. }
  81. /*
  82. ==================
  83. idAsyncServer::InitPort
  84. ==================
  85. */
  86. bool idAsyncServer::InitPort( void ) {
  87. int lastPort;
  88. // if this is the first time we have spawned a server, open the UDP port
  89. if ( !serverPort.GetPort() ) {
  90. if ( cvarSystem->GetCVarInteger( "net_port" ) != 0 ) {
  91. if ( !serverPort.InitForPort( cvarSystem->GetCVarInteger( "net_port" ) ) ) {
  92. common->Printf( "Unable to open server on port %d (net_port)\n", cvarSystem->GetCVarInteger( "net_port" ) );
  93. return false;
  94. }
  95. } else {
  96. // scan for multiple ports, in case other servers are running on this IP already
  97. for ( lastPort = 0; lastPort < NUM_SERVER_PORTS; lastPort++ ) {
  98. if ( serverPort.InitForPort( PORT_SERVER + lastPort ) ) {
  99. break;
  100. }
  101. }
  102. if ( lastPort >= NUM_SERVER_PORTS ) {
  103. common->Printf( "Unable to open server network port.\n" );
  104. return false;
  105. }
  106. }
  107. }
  108. return true;
  109. }
  110. /*
  111. ==================
  112. idAsyncServer::ClosePort
  113. ==================
  114. */
  115. void idAsyncServer::ClosePort( void ) {
  116. int i;
  117. serverPort.Close();
  118. for ( i = 0; i < MAX_CHALLENGES; i++ ) {
  119. challenges[ i ].authReplyPrint.Clear();
  120. }
  121. }
  122. /*
  123. ==================
  124. idAsyncServer::Spawn
  125. ==================
  126. */
  127. void idAsyncServer::Spawn( void ) {
  128. int i, size;
  129. byte msgBuf[MAX_MESSAGE_SIZE];
  130. netadr_t from;
  131. // shutdown any current game
  132. session->Stop();
  133. if ( active ) {
  134. return;
  135. }
  136. if ( !InitPort() ) {
  137. return;
  138. }
  139. // trash any currently pending packets
  140. while( serverPort.GetPacket( from, msgBuf, size, sizeof( msgBuf ) ) ) {
  141. }
  142. // reset cheats cvars
  143. if ( !idAsyncNetwork::allowCheats.GetBool() ) {
  144. cvarSystem->ResetFlaggedVariables( CVAR_CHEAT );
  145. }
  146. memset( challenges, 0, sizeof( challenges ) );
  147. memset( userCmds, 0, sizeof( userCmds ) );
  148. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  149. ClearClient( i );
  150. }
  151. common->Printf( "Server spawned on port %i.\n", serverPort.GetPort() );
  152. // calculate a checksum on some of the essential data used
  153. serverDataChecksum = declManager->GetChecksum();
  154. // get a pseudo random server id, but don't use the id which is reserved for connectionless packets
  155. serverId = Sys_Milliseconds() & CONNECTIONLESS_MESSAGE_ID_MASK;
  156. active = true;
  157. nextHeartbeatTime = 0;
  158. nextAsyncStatsTime = 0;
  159. ExecuteMapChange();
  160. }
  161. /*
  162. ==================
  163. idAsyncServer::Kill
  164. ==================
  165. */
  166. void idAsyncServer::Kill( void ) {
  167. int i, j;
  168. if ( !active ) {
  169. return;
  170. }
  171. // drop all clients
  172. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  173. DropClient( i, "#str_07135" );
  174. }
  175. // send some empty messages to the zombie clients to make sure they disconnect
  176. for ( j = 0; j < 4; j++ ) {
  177. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  178. if ( clients[i].clientState == SCS_ZOMBIE ) {
  179. if ( clients[i].channel.UnsentFragmentsLeft() ) {
  180. clients[i].channel.SendNextFragment( serverPort, serverTime );
  181. } else {
  182. SendEmptyToClient( i, true );
  183. }
  184. }
  185. }
  186. Sys_Sleep( 10 );
  187. }
  188. // reset any pureness
  189. fileSystem->ClearPureChecksums();
  190. active = false;
  191. // shutdown any current game
  192. session->Stop();
  193. }
  194. /*
  195. ==================
  196. idAsyncServer::ExecuteMapChange
  197. ==================
  198. */
  199. void idAsyncServer::ExecuteMapChange( void ) {
  200. int i;
  201. idBitMsg msg;
  202. byte msgBuf[MAX_MESSAGE_SIZE];
  203. idStr mapName;
  204. findFile_t ff;
  205. bool addonReload = false;
  206. char bestGameType[ MAX_STRING_CHARS ];
  207. assert( active );
  208. // reset any pureness
  209. fileSystem->ClearPureChecksums();
  210. // make sure the map/gametype combo is good
  211. game->GetBestGameType( cvarSystem->GetCVarString("si_map"), cvarSystem->GetCVarString("si_gametype"), bestGameType );
  212. cvarSystem->SetCVarString("si_gametype", bestGameType );
  213. // initialize map settings
  214. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "rescanSI" );
  215. sprintf( mapName, "maps/%s", sessLocal.mapSpawnData.serverInfo.GetString( "si_map" ) );
  216. mapName.SetFileExtension( ".map" );
  217. ff = fileSystem->FindFile( mapName, !serverReloadingEngine );
  218. switch( ff ) {
  219. case FIND_NO:
  220. common->Printf( "Can't find map %s\n", mapName.c_str() );
  221. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "disconnect\n" );
  222. return;
  223. case FIND_ADDON:
  224. // NOTE: we have no problem with addon dependencies here because if the map is in
  225. // an addon pack that's already on search list, then all it's deps are assumed to be on search as well
  226. common->Printf( "map %s is in an addon pak - reloading\n", mapName.c_str() );
  227. addonReload = true;
  228. break;
  229. default:
  230. break;
  231. }
  232. // if we are asked to do a full reload, the strategy is completely different
  233. if ( !serverReloadingEngine && ( addonReload || idAsyncNetwork::serverReloadEngine.GetInteger() != 0 ) ) {
  234. if ( idAsyncNetwork::serverReloadEngine.GetInteger() != 0 ) {
  235. common->Printf( "net_serverReloadEngine enabled - doing a full reload\n" );
  236. }
  237. // tell the clients to reconnect
  238. // FIXME: shouldn't they wait for the new pure list, then reload?
  239. // in a lot of cases this is going to trigger two reloadEngines for the clients
  240. // one to restart, the other one to set paks right ( with addon for instance )
  241. // can fix by reconnecting without reloading and waiting for the server to tell..
  242. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  243. if ( clients[ i ].clientState >= SCS_PUREWAIT && i != localClientNum ) {
  244. msg.Init( msgBuf, sizeof( msgBuf ) );
  245. msg.WriteByte( SERVER_RELIABLE_MESSAGE_RELOAD );
  246. SendReliableMessage( i, msg );
  247. clients[ i ].clientState = SCS_ZOMBIE; // so we don't bother sending a disconnect
  248. }
  249. }
  250. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "reloadEngine" );
  251. serverReloadingEngine = true; // don't get caught in endless loop
  252. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "spawnServer\n" );
  253. // decrease feature
  254. if ( idAsyncNetwork::serverReloadEngine.GetInteger() > 0 ) {
  255. idAsyncNetwork::serverReloadEngine.SetInteger( idAsyncNetwork::serverReloadEngine.GetInteger() - 1 );
  256. }
  257. return;
  258. }
  259. serverReloadingEngine = false;
  260. serverTime = 0;
  261. // initialize game id and time
  262. gameInitId ^= Sys_Milliseconds(); // NOTE: make sure the gameInitId is always a positive number because negative numbers have special meaning
  263. gameFrame = 0;
  264. gameTime = 0;
  265. gameTimeResidual = 0;
  266. memset( userCmds, 0, sizeof( userCmds ) );
  267. if ( idAsyncNetwork::serverDedicated.GetInteger() == 0 ) {
  268. InitLocalClient( 0 );
  269. } else {
  270. localClientNum = -1;
  271. }
  272. // re-initialize all connected clients for the new map
  273. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  274. if ( clients[i].clientState >= SCS_PUREWAIT && i != localClientNum ) {
  275. InitClient( i, clients[i].clientId, clients[i].clientRate );
  276. SendGameInitToClient( i );
  277. if ( sessLocal.mapSpawnData.serverInfo.GetBool( "si_pure" ) ) {
  278. clients[ i ].clientState = SCS_PUREWAIT;
  279. }
  280. }
  281. }
  282. // setup the game pak checksums
  283. // since this is not dependant on si_pure we catch anything bad before loading map
  284. if ( sessLocal.mapSpawnData.serverInfo.GetInt( "si_pure" ) ) {
  285. if ( !fileSystem->UpdateGamePakChecksums( ) ) {
  286. session->MessageBox( MSG_OK, common->GetLanguageDict()->GetString ( "#str_04337" ), common->GetLanguageDict()->GetString ( "#str_04338" ), true );
  287. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "disconnect\n" );
  288. return;
  289. }
  290. }
  291. // load map
  292. sessLocal.ExecuteMapChange();
  293. if ( localClientNum >= 0 ) {
  294. BeginLocalClient();
  295. } else {
  296. game->SetLocalClient( -1 );
  297. }
  298. if ( sessLocal.mapSpawnData.serverInfo.GetInt( "si_pure" ) ) {
  299. // lock down the pak list
  300. fileSystem->UpdatePureServerChecksums( );
  301. // tell the clients so they can work out their pure lists
  302. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  303. if ( clients[ i ].clientState == SCS_PUREWAIT ) {
  304. if ( !SendReliablePureToClient( i ) ) {
  305. clients[ i ].clientState = SCS_CONNECTED;
  306. }
  307. }
  308. }
  309. }
  310. // serverTime gets reset, force a heartbeat so timings restart
  311. MasterHeartbeat( true );
  312. }
  313. /*
  314. ==================
  315. idAsyncServer::GetPort
  316. ==================
  317. */
  318. int idAsyncServer::GetPort( void ) const {
  319. return serverPort.GetPort();
  320. }
  321. /*
  322. ===============
  323. idAsyncServer::GetBoundAdr
  324. ===============
  325. */
  326. netadr_t idAsyncServer::GetBoundAdr( void ) const {
  327. return serverPort.GetAdr();
  328. }
  329. /*
  330. ==================
  331. idAsyncServer::GetOutgoingRate
  332. ==================
  333. */
  334. int idAsyncServer::GetOutgoingRate( void ) const {
  335. int i, rate;
  336. rate = 0;
  337. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  338. const serverClient_t &client = clients[i];
  339. if ( client.clientState >= SCS_CONNECTED ) {
  340. rate += client.channel.GetOutgoingRate();
  341. }
  342. }
  343. return rate;
  344. }
  345. /*
  346. ==================
  347. idAsyncServer::GetIncomingRate
  348. ==================
  349. */
  350. int idAsyncServer::GetIncomingRate( void ) const {
  351. int i, rate;
  352. rate = 0;
  353. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  354. const serverClient_t &client = clients[i];
  355. if ( client.clientState >= SCS_CONNECTED ) {
  356. rate += client.channel.GetIncomingRate();
  357. }
  358. }
  359. return rate;
  360. }
  361. /*
  362. ==================
  363. idAsyncServer::IsClientInGame
  364. ==================
  365. */
  366. bool idAsyncServer::IsClientInGame( int clientNum ) const {
  367. return ( clients[clientNum].clientState >= SCS_INGAME );
  368. }
  369. /*
  370. ==================
  371. idAsyncServer::GetClientPing
  372. ==================
  373. */
  374. int idAsyncServer::GetClientPing( int clientNum ) const {
  375. const serverClient_t &client = clients[clientNum];
  376. if ( client.clientState < SCS_CONNECTED ) {
  377. return 99999;
  378. } else {
  379. return client.clientPing;
  380. }
  381. }
  382. /*
  383. ==================
  384. idAsyncServer::GetClientPrediction
  385. ==================
  386. */
  387. int idAsyncServer::GetClientPrediction( int clientNum ) const {
  388. const serverClient_t &client = clients[clientNum];
  389. if ( client.clientState < SCS_CONNECTED ) {
  390. return 99999;
  391. } else {
  392. return client.clientPrediction;
  393. }
  394. }
  395. /*
  396. ==================
  397. idAsyncServer::GetClientTimeSinceLastPacket
  398. ==================
  399. */
  400. int idAsyncServer::GetClientTimeSinceLastPacket( int clientNum ) const {
  401. const serverClient_t &client = clients[clientNum];
  402. if ( client.clientState < SCS_CONNECTED ) {
  403. return 99999;
  404. } else {
  405. return serverTime - client.lastPacketTime;
  406. }
  407. }
  408. /*
  409. ==================
  410. idAsyncServer::GetClientTimeSinceLastInput
  411. ==================
  412. */
  413. int idAsyncServer::GetClientTimeSinceLastInput( int clientNum ) const {
  414. const serverClient_t &client = clients[clientNum];
  415. if ( client.clientState < SCS_CONNECTED ) {
  416. return 99999;
  417. } else {
  418. return serverTime - client.lastInputTime;
  419. }
  420. }
  421. /*
  422. ==================
  423. idAsyncServer::GetClientOutgoingRate
  424. ==================
  425. */
  426. int idAsyncServer::GetClientOutgoingRate( int clientNum ) const {
  427. const serverClient_t &client = clients[clientNum];
  428. if ( client.clientState < SCS_CONNECTED ) {
  429. return -1;
  430. } else {
  431. return client.channel.GetOutgoingRate();
  432. }
  433. }
  434. /*
  435. ==================
  436. idAsyncServer::GetClientIncomingRate
  437. ==================
  438. */
  439. int idAsyncServer::GetClientIncomingRate( int clientNum ) const {
  440. const serverClient_t &client = clients[clientNum];
  441. if ( client.clientState < SCS_CONNECTED ) {
  442. return -1;
  443. } else {
  444. return client.channel.GetIncomingRate();
  445. }
  446. }
  447. /*
  448. ==================
  449. idAsyncServer::GetClientOutgoingCompression
  450. ==================
  451. */
  452. float idAsyncServer::GetClientOutgoingCompression( int clientNum ) const {
  453. const serverClient_t &client = clients[clientNum];
  454. if ( client.clientState < SCS_CONNECTED ) {
  455. return 0.0f;
  456. } else {
  457. return client.channel.GetOutgoingCompression();
  458. }
  459. }
  460. /*
  461. ==================
  462. idAsyncServer::GetClientIncomingCompression
  463. ==================
  464. */
  465. float idAsyncServer::GetClientIncomingCompression( int clientNum ) const {
  466. const serverClient_t &client = clients[clientNum];
  467. if ( client.clientState < SCS_CONNECTED ) {
  468. return 0.0f;
  469. } else {
  470. return client.channel.GetIncomingCompression();
  471. }
  472. }
  473. /*
  474. ==================
  475. idAsyncServer::GetClientIncomingPacketLoss
  476. ==================
  477. */
  478. float idAsyncServer::GetClientIncomingPacketLoss( int clientNum ) const {
  479. const serverClient_t &client = clients[clientNum];
  480. if ( client.clientState < SCS_CONNECTED ) {
  481. return 0.0f;
  482. } else {
  483. return client.channel.GetIncomingPacketLoss();
  484. }
  485. }
  486. /*
  487. ==================
  488. idAsyncServer::GetNumClients
  489. ==================
  490. */
  491. int idAsyncServer::GetNumClients( void ) const {
  492. int ret = 0;
  493. for ( int i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  494. if ( clients[ i ].clientState >= SCS_CONNECTED ) {
  495. ret++;
  496. }
  497. }
  498. return ret;
  499. }
  500. /*
  501. ==================
  502. idAsyncServer::GetNumIdleClients
  503. ==================
  504. */
  505. int idAsyncServer::GetNumIdleClients( void ) const {
  506. int ret = 0;
  507. for ( int i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  508. if ( clients[ i ].clientState >= SCS_CONNECTED ) {
  509. if ( serverTime - clients[ i ].lastInputTime > NOINPUT_IDLE_TIME ) {
  510. ret++;
  511. }
  512. }
  513. }
  514. return ret;
  515. }
  516. /*
  517. ==================
  518. idAsyncServer::DuplicateUsercmds
  519. ==================
  520. */
  521. void idAsyncServer::DuplicateUsercmds( int frame, int time ) {
  522. int i, previousIndex, currentIndex;
  523. previousIndex = ( frame - 1 ) & ( MAX_USERCMD_BACKUP - 1 );
  524. currentIndex = frame & ( MAX_USERCMD_BACKUP - 1 );
  525. // duplicate previous user commands if no new commands are available for a client
  526. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  527. if ( clients[i].clientState == SCS_FREE ) {
  528. continue;
  529. }
  530. if ( idAsyncNetwork::DuplicateUsercmd( userCmds[previousIndex][i], userCmds[currentIndex][i], frame, time ) ) {
  531. clients[i].numDuplicatedUsercmds++;
  532. }
  533. }
  534. }
  535. /*
  536. ==================
  537. idAsyncServer::ClearClient
  538. ==================
  539. */
  540. void idAsyncServer::ClearClient( int clientNum ) {
  541. serverClient_t &client = clients[clientNum];
  542. client.clientId = 0;
  543. client.clientState = SCS_FREE;
  544. client.clientPrediction = 0;
  545. client.clientAheadTime = 0;
  546. client.clientRate = 0;
  547. client.clientPing = 0;
  548. client.gameInitSequence = 0;
  549. client.gameFrame = 0;
  550. client.gameTime = 0;
  551. client.channel.Shutdown();
  552. client.lastConnectTime = 0;
  553. client.lastEmptyTime = 0;
  554. client.lastPingTime = 0;
  555. client.lastSnapshotTime = 0;
  556. client.lastPacketTime = 0;
  557. client.lastInputTime = 0;
  558. client.snapshotSequence = 0;
  559. client.acknowledgeSnapshotSequence = 0;
  560. client.numDuplicatedUsercmds = 0;
  561. }
  562. /*
  563. ==================
  564. idAsyncServer::InitClient
  565. ==================
  566. */
  567. void idAsyncServer::InitClient( int clientNum, int clientId, int clientRate ) {
  568. int i;
  569. // clear the user info
  570. sessLocal.mapSpawnData.userInfo[ clientNum ].Clear(); // always start with a clean base
  571. // clear the server client
  572. serverClient_t &client = clients[clientNum];
  573. client.clientId = clientId;
  574. client.clientState = SCS_CONNECTED;
  575. client.clientPrediction = 0;
  576. client.clientAheadTime = 0;
  577. client.gameInitSequence = -1;
  578. client.gameFrame = 0;
  579. client.gameTime = 0;
  580. client.channel.ResetRate();
  581. client.clientRate = clientRate ? clientRate : idAsyncNetwork::serverMaxClientRate.GetInteger();
  582. client.channel.SetMaxOutgoingRate( Min( idAsyncNetwork::serverMaxClientRate.GetInteger(), client.clientRate ) );
  583. client.clientPing = 0;
  584. client.lastConnectTime = serverTime;
  585. client.lastEmptyTime = serverTime;
  586. client.lastPingTime = serverTime;
  587. client.lastSnapshotTime = serverTime;
  588. client.lastPacketTime = serverTime;
  589. client.lastInputTime = serverTime;
  590. client.acknowledgeSnapshotSequence = 0;
  591. client.numDuplicatedUsercmds = 0;
  592. // clear the user commands
  593. for ( i = 0; i < MAX_USERCMD_BACKUP; i++ ) {
  594. memset( &userCmds[i][clientNum], 0, sizeof( userCmds[i][clientNum] ) );
  595. }
  596. // let the game know a player connected
  597. game->ServerClientConnect( clientNum, client.guid );
  598. }
  599. /*
  600. ==================
  601. idAsyncServer::InitLocalClient
  602. ==================
  603. */
  604. void idAsyncServer::InitLocalClient( int clientNum ) {
  605. netadr_t badAddress;
  606. localClientNum = clientNum;
  607. InitClient( clientNum, 0, 0 );
  608. memset( &badAddress, 0, sizeof( badAddress ) );
  609. badAddress.type = NA_BAD;
  610. clients[clientNum].channel.Init( badAddress, serverId );
  611. clients[clientNum].clientState = SCS_INGAME;
  612. sessLocal.mapSpawnData.userInfo[clientNum] = *cvarSystem->MoveCVarsToDict( CVAR_USERINFO );
  613. }
  614. /*
  615. ==================
  616. idAsyncServer::BeginLocalClient
  617. ==================
  618. */
  619. void idAsyncServer::BeginLocalClient( void ) {
  620. game->SetLocalClient( localClientNum );
  621. game->SetUserInfo( localClientNum, sessLocal.mapSpawnData.userInfo[localClientNum], false, false );
  622. game->ServerClientBegin( localClientNum );
  623. }
  624. /*
  625. ==================
  626. idAsyncServer::LocalClientInput
  627. ==================
  628. */
  629. void idAsyncServer::LocalClientInput( void ) {
  630. int index;
  631. if ( localClientNum < 0 ) {
  632. return;
  633. }
  634. index = gameFrame & ( MAX_USERCMD_BACKUP - 1 );
  635. userCmds[index][localClientNum] = usercmdGen->GetDirectUsercmd();
  636. userCmds[index][localClientNum].gameFrame = gameFrame;
  637. userCmds[index][localClientNum].gameTime = gameTime;
  638. if ( idAsyncNetwork::UsercmdInputChanged( userCmds[( gameFrame - 1 ) & ( MAX_USERCMD_BACKUP - 1 )][localClientNum], userCmds[index][localClientNum] ) ) {
  639. clients[localClientNum].lastInputTime = serverTime;
  640. }
  641. clients[localClientNum].gameFrame = gameFrame;
  642. clients[localClientNum].gameTime = gameTime;
  643. clients[localClientNum].lastPacketTime = serverTime;
  644. }
  645. /*
  646. ==================
  647. idAsyncServer::DropClient
  648. ==================
  649. */
  650. void idAsyncServer::DropClient( int clientNum, const char *reason ) {
  651. int i;
  652. idBitMsg msg;
  653. byte msgBuf[MAX_MESSAGE_SIZE];
  654. serverClient_t &client = clients[clientNum];
  655. if ( client.clientState <= SCS_ZOMBIE ) {
  656. return;
  657. }
  658. if ( client.clientState >= SCS_PUREWAIT && clientNum != localClientNum ) {
  659. msg.Init( msgBuf, sizeof( msgBuf ) );
  660. msg.WriteByte( SERVER_RELIABLE_MESSAGE_DISCONNECT );
  661. msg.WriteLong( clientNum );
  662. msg.WriteString( reason );
  663. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  664. // clientNum so SCS_PUREWAIT client gets it's own disconnect msg
  665. if ( i == clientNum || clients[i].clientState >= SCS_CONNECTED ) {
  666. SendReliableMessage( i, msg );
  667. }
  668. }
  669. }
  670. reason = common->GetLanguageDict()->GetString( reason );
  671. common->Printf( "client %d %s\n", clientNum, reason );
  672. cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "addChatLine \"%s^0 %s\"", sessLocal.mapSpawnData.userInfo[ clientNum ].GetString( "ui_name" ), reason ) );
  673. // remove the player from the game
  674. game->ServerClientDisconnect( clientNum );
  675. client.clientState = SCS_ZOMBIE;
  676. }
  677. /*
  678. ==================
  679. idAsyncServer::SendReliableMessage
  680. ==================
  681. */
  682. void idAsyncServer::SendReliableMessage( int clientNum, const idBitMsg &msg ) {
  683. if ( clientNum == localClientNum ) {
  684. return;
  685. }
  686. if ( !clients[ clientNum ].channel.SendReliableMessage( msg ) ) {
  687. clients[ clientNum ].channel.ClearReliableMessages();
  688. DropClient( clientNum, "#str_07136" );
  689. }
  690. }
  691. /*
  692. ==================
  693. idAsyncServer::CheckClientTimeouts
  694. ==================
  695. */
  696. void idAsyncServer::CheckClientTimeouts( void ) {
  697. int i, zombieTimeout, clientTimeout;
  698. zombieTimeout = serverTime - idAsyncNetwork::serverZombieTimeout.GetInteger() * 1000;
  699. clientTimeout = serverTime - idAsyncNetwork::serverClientTimeout.GetInteger() * 1000;
  700. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  701. serverClient_t &client = clients[i];
  702. if ( i == localClientNum ) {
  703. continue;
  704. }
  705. if ( client.lastPacketTime > serverTime ) {
  706. client.lastPacketTime = serverTime;
  707. continue;
  708. }
  709. if ( client.clientState == SCS_ZOMBIE && client.lastPacketTime < zombieTimeout ) {
  710. client.channel.Shutdown();
  711. client.clientState = SCS_FREE;
  712. continue;
  713. }
  714. if ( client.clientState >= SCS_PUREWAIT && client.lastPacketTime < clientTimeout ) {
  715. DropClient( i, "#str_07137" );
  716. continue;
  717. }
  718. }
  719. }
  720. /*
  721. ==================
  722. idAsyncServer::SendPrintBroadcast
  723. ==================
  724. */
  725. void idAsyncServer::SendPrintBroadcast( const char *string ) {
  726. int i;
  727. idBitMsg msg;
  728. byte msgBuf[MAX_MESSAGE_SIZE];
  729. msg.Init( msgBuf, sizeof( msgBuf ) );
  730. msg.WriteByte( SERVER_RELIABLE_MESSAGE_PRINT );
  731. msg.WriteString( string );
  732. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  733. if ( clients[i].clientState >= SCS_CONNECTED ) {
  734. SendReliableMessage( i, msg );
  735. }
  736. }
  737. }
  738. /*
  739. ==================
  740. idAsyncServer::SendPrintToClient
  741. ==================
  742. */
  743. void idAsyncServer::SendPrintToClient( int clientNum, const char *string ) {
  744. idBitMsg msg;
  745. byte msgBuf[MAX_MESSAGE_SIZE];
  746. serverClient_t &client = clients[clientNum];
  747. if ( client.clientState < SCS_CONNECTED ) {
  748. return;
  749. }
  750. msg.Init( msgBuf, sizeof( msgBuf ) );
  751. msg.WriteByte( SERVER_RELIABLE_MESSAGE_PRINT );
  752. msg.WriteString( string );
  753. SendReliableMessage( clientNum, msg );
  754. }
  755. /*
  756. ==================
  757. idAsyncServer::SendUserInfoBroadcast
  758. ==================
  759. */
  760. void idAsyncServer::SendUserInfoBroadcast( int userInfoNum, const idDict &info, bool sendToAll ) {
  761. idBitMsg msg;
  762. byte msgBuf[MAX_MESSAGE_SIZE];
  763. const idDict *gameInfo;
  764. bool gameModifiedInfo;
  765. gameInfo = game->SetUserInfo( userInfoNum, info, false, true );
  766. if ( gameInfo ) {
  767. gameModifiedInfo = true;
  768. } else {
  769. gameModifiedInfo = false;
  770. gameInfo = &info;
  771. }
  772. if ( userInfoNum == localClientNum ) {
  773. common->DPrintf( "local user info modified by server\n" );
  774. cvarSystem->SetCVarsFromDict( *gameInfo );
  775. cvarSystem->ClearModifiedFlags( CVAR_USERINFO ); // don't emit back
  776. }
  777. msg.Init( msgBuf, sizeof( msgBuf ) );
  778. msg.WriteByte( SERVER_RELIABLE_MESSAGE_CLIENTINFO );
  779. msg.WriteByte( userInfoNum );
  780. if ( gameModifiedInfo || sendToAll ) {
  781. msg.WriteBits( 0, 1 );
  782. } else {
  783. msg.WriteBits( 1, 1 );
  784. }
  785. #if ID_CLIENTINFO_TAGS
  786. msg.WriteLong( sessLocal.mapSpawnData.userInfo[userInfoNum].Checksum() );
  787. common->DPrintf( "broadcast for client %d: 0x%x\n", userInfoNum, sessLocal.mapSpawnData.userInfo[userInfoNum].Checksum() );
  788. sessLocal.mapSpawnData.userInfo[userInfoNum].Print();
  789. #endif
  790. if ( gameModifiedInfo || sendToAll ) {
  791. msg.WriteDeltaDict( *gameInfo, NULL );
  792. } else {
  793. msg.WriteDeltaDict( *gameInfo, &sessLocal.mapSpawnData.userInfo[userInfoNum] );
  794. }
  795. for ( int i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  796. if ( clients[i].clientState >= SCS_CONNECTED && ( sendToAll || i != userInfoNum || gameModifiedInfo ) ) {
  797. SendReliableMessage( i, msg );
  798. }
  799. }
  800. sessLocal.mapSpawnData.userInfo[userInfoNum] = *gameInfo;
  801. }
  802. /*
  803. ==================
  804. idAsyncServer::UpdateUI
  805. if the game modifies userInfo, it will call this through command system
  806. we then need to get the info from the game, and broadcast to clients
  807. ( using DeltaDict and our current mapSpawnData as a base )
  808. ==================
  809. */
  810. void idAsyncServer::UpdateUI( int clientNum ) {
  811. const idDict *info = game->GetUserInfo( clientNum );
  812. if ( !info ) {
  813. common->Warning( "idAsyncServer::UpdateUI: no info from game\n" );
  814. return;
  815. }
  816. SendUserInfoBroadcast( clientNum, *info, true );
  817. }
  818. /*
  819. ==================
  820. idAsyncServer::SendUserInfoToClient
  821. ==================
  822. */
  823. void idAsyncServer::SendUserInfoToClient( int clientNum, int userInfoNum, const idDict &info ) {
  824. idBitMsg msg;
  825. byte msgBuf[MAX_MESSAGE_SIZE];
  826. if ( clients[clientNum].clientState < SCS_CONNECTED ) {
  827. return;
  828. }
  829. msg.Init( msgBuf, sizeof( msgBuf ) );
  830. msg.WriteByte( SERVER_RELIABLE_MESSAGE_CLIENTINFO );
  831. msg.WriteByte( userInfoNum );
  832. msg.WriteBits( 0, 1 );
  833. #if ID_CLIENTINFO_TAGS
  834. msg.WriteLong( 0 );
  835. common->DPrintf( "user info %d to client %d: NULL base\n", userInfoNum, clientNum );
  836. #endif
  837. msg.WriteDeltaDict( info, NULL );
  838. SendReliableMessage( clientNum, msg );
  839. }
  840. /*
  841. ==================
  842. idAsyncServer::SendSyncedCvarsBroadcast
  843. ==================
  844. */
  845. void idAsyncServer::SendSyncedCvarsBroadcast( const idDict &cvars ) {
  846. idBitMsg msg;
  847. byte msgBuf[MAX_MESSAGE_SIZE];
  848. int i;
  849. msg.Init( msgBuf, sizeof( msgBuf ) );
  850. msg.WriteByte( SERVER_RELIABLE_MESSAGE_SYNCEDCVARS );
  851. msg.WriteDeltaDict( cvars, &sessLocal.mapSpawnData.syncedCVars );
  852. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  853. if ( clients[i].clientState >= SCS_CONNECTED ) {
  854. SendReliableMessage( i, msg );
  855. }
  856. }
  857. sessLocal.mapSpawnData.syncedCVars = cvars;
  858. }
  859. /*
  860. ==================
  861. idAsyncServer::SendSyncedCvarsToClient
  862. ==================
  863. */
  864. void idAsyncServer::SendSyncedCvarsToClient( int clientNum, const idDict &cvars ) {
  865. idBitMsg msg;
  866. byte msgBuf[MAX_MESSAGE_SIZE];
  867. if ( clients[clientNum].clientState < SCS_CONNECTED ) {
  868. return;
  869. }
  870. msg.Init( msgBuf, sizeof( msgBuf ) );
  871. msg.WriteByte( SERVER_RELIABLE_MESSAGE_SYNCEDCVARS );
  872. msg.WriteDeltaDict( cvars, NULL );
  873. SendReliableMessage( clientNum, msg );
  874. }
  875. /*
  876. ==================
  877. idAsyncServer::SendApplySnapshotToClient
  878. ==================
  879. */
  880. void idAsyncServer::SendApplySnapshotToClient( int clientNum, int sequence ) {
  881. idBitMsg msg;
  882. byte msgBuf[MAX_MESSAGE_SIZE];
  883. msg.Init( msgBuf, sizeof( msgBuf ) );
  884. msg.WriteByte( SERVER_RELIABLE_MESSAGE_APPLYSNAPSHOT );
  885. msg.WriteLong( sequence );
  886. SendReliableMessage( clientNum, msg );
  887. }
  888. /*
  889. ==================
  890. idAsyncServer::SendEmptyToClient
  891. ==================
  892. */
  893. bool idAsyncServer::SendEmptyToClient( int clientNum, bool force ) {
  894. idBitMsg msg;
  895. byte msgBuf[MAX_MESSAGE_SIZE];
  896. serverClient_t &client = clients[clientNum];
  897. if ( client.lastEmptyTime > realTime ) {
  898. client.lastEmptyTime = realTime;
  899. }
  900. if ( !force && ( realTime - client.lastEmptyTime < EMPTY_RESEND_TIME ) ) {
  901. return false;
  902. }
  903. if ( idAsyncNetwork::verbose.GetInteger() ) {
  904. common->Printf( "sending empty to client %d: gameInitId = %d, gameFrame = %d, gameTime = %d\n", clientNum, gameInitId, gameFrame, gameTime );
  905. }
  906. msg.Init( msgBuf, sizeof( msgBuf ) );
  907. msg.WriteLong( gameInitId );
  908. msg.WriteByte( SERVER_UNRELIABLE_MESSAGE_EMPTY );
  909. client.channel.SendMessage( serverPort, serverTime, msg );
  910. client.lastEmptyTime = realTime;
  911. return true;
  912. }
  913. /*
  914. ==================
  915. idAsyncServer::SendPingToClient
  916. ==================
  917. */
  918. bool idAsyncServer::SendPingToClient( int clientNum ) {
  919. idBitMsg msg;
  920. byte msgBuf[MAX_MESSAGE_SIZE];
  921. serverClient_t &client = clients[clientNum];
  922. if ( client.lastPingTime > realTime ) {
  923. client.lastPingTime = realTime;
  924. }
  925. if ( realTime - client.lastPingTime < PING_RESEND_TIME ) {
  926. return false;
  927. }
  928. if ( idAsyncNetwork::verbose.GetInteger() == 2 ) {
  929. common->Printf( "pinging client %d: gameInitId = %d, gameFrame = %d, gameTime = %d\n", clientNum, gameInitId, gameFrame, gameTime );
  930. }
  931. msg.Init( msgBuf, sizeof( msgBuf ) );
  932. msg.WriteLong( gameInitId );
  933. msg.WriteByte( SERVER_UNRELIABLE_MESSAGE_PING );
  934. msg.WriteLong( realTime );
  935. client.channel.SendMessage( serverPort, serverTime, msg );
  936. client.lastPingTime = realTime;
  937. return true;
  938. }
  939. /*
  940. ==================
  941. idAsyncServer::SendGameInitToClient
  942. ==================
  943. */
  944. void idAsyncServer::SendGameInitToClient( int clientNum ) {
  945. idBitMsg msg;
  946. byte msgBuf[MAX_MESSAGE_SIZE];
  947. if ( idAsyncNetwork::verbose.GetInteger() ) {
  948. common->Printf( "sending gameinit to client %d: gameInitId = %d, gameFrame = %d, gameTime = %d\n", clientNum, gameInitId, gameFrame, gameTime );
  949. }
  950. serverClient_t &client = clients[clientNum];
  951. // clear the unsent fragments. might flood winsock but that's ok
  952. while( client.channel.UnsentFragmentsLeft() ) {
  953. client.channel.SendNextFragment( serverPort, serverTime );
  954. }
  955. msg.Init( msgBuf, sizeof( msgBuf ) );
  956. msg.WriteLong( gameInitId );
  957. msg.WriteByte( SERVER_UNRELIABLE_MESSAGE_GAMEINIT );
  958. msg.WriteLong( gameFrame );
  959. msg.WriteLong( gameTime );
  960. msg.WriteDeltaDict( sessLocal.mapSpawnData.serverInfo, NULL );
  961. client.gameInitSequence = client.channel.SendMessage( serverPort, serverTime, msg );
  962. }
  963. /*
  964. ==================
  965. idAsyncServer::SendSnapshotToClient
  966. ==================
  967. */
  968. bool idAsyncServer::SendSnapshotToClient( int clientNum ) {
  969. int i, j, index, numUsercmds;
  970. idBitMsg msg;
  971. byte msgBuf[MAX_MESSAGE_SIZE];
  972. usercmd_t * last;
  973. byte clientInPVS[MAX_ASYNC_CLIENTS >> 3];
  974. serverClient_t &client = clients[clientNum];
  975. if ( serverTime - client.lastSnapshotTime < idAsyncNetwork::serverSnapshotDelay.GetInteger() ) {
  976. return false;
  977. }
  978. if ( idAsyncNetwork::verbose.GetInteger() == 2 ) {
  979. common->Printf( "sending snapshot to client %d: gameInitId = %d, gameFrame = %d, gameTime = %d\n", clientNum, gameInitId, gameFrame, gameTime );
  980. }
  981. // how far is the client ahead of the server minus the packet delay
  982. client.clientAheadTime = client.gameTime - ( gameTime + gameTimeResidual );
  983. // write the snapshot
  984. msg.Init( msgBuf, sizeof( msgBuf ) );
  985. msg.WriteLong( gameInitId );
  986. msg.WriteByte( SERVER_UNRELIABLE_MESSAGE_SNAPSHOT );
  987. msg.WriteLong( client.snapshotSequence );
  988. msg.WriteLong( gameFrame );
  989. msg.WriteLong( gameTime );
  990. msg.WriteByte( idMath::ClampChar( client.numDuplicatedUsercmds ) );
  991. msg.WriteShort( idMath::ClampShort( client.clientAheadTime ) );
  992. // write the game snapshot
  993. game->ServerWriteSnapshot( clientNum, client.snapshotSequence, msg, clientInPVS, MAX_ASYNC_CLIENTS );
  994. // write the latest user commands from the other clients in the PVS to the snapshot
  995. for ( last = NULL, i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  996. serverClient_t &client = clients[i];
  997. if ( client.clientState == SCS_FREE || i == clientNum ) {
  998. continue;
  999. }
  1000. // if the client is not in the PVS
  1001. if ( !( clientInPVS[i >> 3] & ( 1 << ( i & 7 ) ) ) ) {
  1002. continue;
  1003. }
  1004. int maxRelay = idMath::ClampInt( 1, MAX_USERCMD_RELAY, idAsyncNetwork::serverMaxUsercmdRelay.GetInteger() );
  1005. // Max( 1, to always send at least one cmd, which we know we have because we call DuplicateUsercmds in RunFrame
  1006. numUsercmds = Max( 1, Min( client.gameFrame, gameFrame + maxRelay ) - gameFrame );
  1007. msg.WriteByte( i );
  1008. msg.WriteByte( numUsercmds );
  1009. for ( j = 0; j < numUsercmds; j++ ) {
  1010. index = ( gameFrame + j ) & ( MAX_USERCMD_BACKUP - 1 );
  1011. idAsyncNetwork::WriteUserCmdDelta( msg, userCmds[index][i], last );
  1012. last = &userCmds[index][i];
  1013. }
  1014. }
  1015. msg.WriteByte( MAX_ASYNC_CLIENTS );
  1016. client.channel.SendMessage( serverPort, serverTime, msg );
  1017. client.lastSnapshotTime = serverTime;
  1018. client.snapshotSequence++;
  1019. client.numDuplicatedUsercmds = 0;
  1020. return true;
  1021. }
  1022. /*
  1023. ==================
  1024. idAsyncServer::ProcessUnreliableClientMessage
  1025. ==================
  1026. */
  1027. void idAsyncServer::ProcessUnreliableClientMessage( int clientNum, const idBitMsg &msg ) {
  1028. int i, id, acknowledgeSequence, clientGameInitId, clientGameFrame, numUsercmds, index;
  1029. usercmd_t *last;
  1030. serverClient_t &client = clients[clientNum];
  1031. if ( client.clientState == SCS_ZOMBIE ) {
  1032. return;
  1033. }
  1034. acknowledgeSequence = msg.ReadLong();
  1035. clientGameInitId = msg.ReadLong();
  1036. // while loading a map the client may send empty messages to keep the connection alive
  1037. if ( clientGameInitId == GAME_INIT_ID_MAP_LOAD ) {
  1038. if ( idAsyncNetwork::verbose.GetInteger() ) {
  1039. common->Printf( "ignore unreliable msg from client %d, gameInitId == ID_MAP_LOAD\n", clientNum );
  1040. }
  1041. return;
  1042. }
  1043. // check if the client is in the right game
  1044. if ( clientGameInitId != gameInitId ) {
  1045. if ( acknowledgeSequence > client.gameInitSequence ) {
  1046. // the client is connected but not in the right game
  1047. client.clientState = SCS_CONNECTED;
  1048. // send game init to client
  1049. SendGameInitToClient( clientNum );
  1050. if ( sessLocal.mapSpawnData.serverInfo.GetBool( "si_pure" ) ) {
  1051. client.clientState = SCS_PUREWAIT;
  1052. if ( !SendReliablePureToClient( clientNum ) ) {
  1053. client.clientState = SCS_CONNECTED;
  1054. }
  1055. }
  1056. } else if ( idAsyncNetwork::verbose.GetInteger() ) {
  1057. common->Printf( "ignore unreliable msg from client %d, wrong gameInit, old sequence\n", clientNum );
  1058. }
  1059. return;
  1060. }
  1061. client.acknowledgeSnapshotSequence = msg.ReadLong();
  1062. if ( client.clientState == SCS_CONNECTED ) {
  1063. // the client is in the right game
  1064. client.clientState = SCS_INGAME;
  1065. // send the user info of other clients
  1066. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1067. if ( clients[i].clientState >= SCS_CONNECTED && i != clientNum ) {
  1068. SendUserInfoToClient( clientNum, i, sessLocal.mapSpawnData.userInfo[i] );
  1069. }
  1070. }
  1071. // send synchronized cvars to client
  1072. SendSyncedCvarsToClient( clientNum, sessLocal.mapSpawnData.syncedCVars );
  1073. SendEnterGameToClient( clientNum );
  1074. // get the client running in the game
  1075. game->ServerClientBegin( clientNum );
  1076. // write any reliable messages to initialize the client game state
  1077. game->ServerWriteInitialReliableMessages( clientNum );
  1078. } else if ( client.clientState == SCS_INGAME ) {
  1079. // apply the last snapshot the client received
  1080. if ( game->ServerApplySnapshot( clientNum, client.acknowledgeSnapshotSequence ) ) {
  1081. SendApplySnapshotToClient( clientNum, client.acknowledgeSnapshotSequence );
  1082. }
  1083. }
  1084. // process the unreliable message
  1085. id = msg.ReadByte();
  1086. switch( id ) {
  1087. case CLIENT_UNRELIABLE_MESSAGE_EMPTY: {
  1088. if ( idAsyncNetwork::verbose.GetInteger() ) {
  1089. common->Printf( "received empty message for client %d\n", clientNum );
  1090. }
  1091. break;
  1092. }
  1093. case CLIENT_UNRELIABLE_MESSAGE_PINGRESPONSE: {
  1094. client.clientPing = realTime - msg.ReadLong();
  1095. break;
  1096. }
  1097. case CLIENT_UNRELIABLE_MESSAGE_USERCMD: {
  1098. client.clientPrediction = msg.ReadShort();
  1099. // read user commands
  1100. clientGameFrame = msg.ReadLong();
  1101. numUsercmds = msg.ReadByte();
  1102. for ( last = NULL, i = clientGameFrame - numUsercmds + 1; i <= clientGameFrame; i++ ) {
  1103. index = i & ( MAX_USERCMD_BACKUP - 1 );
  1104. idAsyncNetwork::ReadUserCmdDelta( msg, userCmds[index][clientNum], last );
  1105. userCmds[index][clientNum].gameFrame = i;
  1106. userCmds[index][clientNum].duplicateCount = 0;
  1107. if ( idAsyncNetwork::UsercmdInputChanged( userCmds[( i - 1 ) & ( MAX_USERCMD_BACKUP - 1 )][clientNum], userCmds[index][clientNum] ) ) {
  1108. client.lastInputTime = serverTime;
  1109. }
  1110. last = &userCmds[index][clientNum];
  1111. }
  1112. if ( last ) {
  1113. client.gameFrame = last->gameFrame;
  1114. client.gameTime = last->gameTime;
  1115. }
  1116. if ( idAsyncNetwork::verbose.GetInteger() == 2 ) {
  1117. common->Printf( "received user command for client %d, gameInitId = %d, gameFrame, %d gameTime %d\n", clientNum, clientGameInitId, client.gameFrame, client.gameTime );
  1118. }
  1119. break;
  1120. }
  1121. default: {
  1122. common->Printf( "unknown unreliable message %d from client %d\n", id, clientNum );
  1123. break;
  1124. }
  1125. }
  1126. }
  1127. /*
  1128. ==================
  1129. idAsyncServer::ProcessReliableClientMessages
  1130. ==================
  1131. */
  1132. void idAsyncServer::ProcessReliableClientMessages( int clientNum ) {
  1133. idBitMsg msg;
  1134. byte msgBuf[MAX_MESSAGE_SIZE];
  1135. byte id;
  1136. serverClient_t &client = clients[clientNum];
  1137. msg.Init( msgBuf, sizeof( msgBuf ) );
  1138. while ( client.channel.GetReliableMessage( msg ) ) {
  1139. id = msg.ReadByte();
  1140. switch( id ) {
  1141. case CLIENT_RELIABLE_MESSAGE_CLIENTINFO: {
  1142. idDict info;
  1143. msg.ReadDeltaDict( info, &sessLocal.mapSpawnData.userInfo[clientNum] );
  1144. SendUserInfoBroadcast( clientNum, info );
  1145. break;
  1146. }
  1147. case CLIENT_RELIABLE_MESSAGE_PRINT: {
  1148. char string[MAX_STRING_CHARS];
  1149. msg.ReadString( string, sizeof( string ) );
  1150. common->Printf( "%s\n", string );
  1151. break;
  1152. }
  1153. case CLIENT_RELIABLE_MESSAGE_DISCONNECT: {
  1154. DropClient( clientNum, "#str_07138" );
  1155. break;
  1156. }
  1157. case CLIENT_RELIABLE_MESSAGE_PURE: {
  1158. // we get this message once the client has successfully updated it's pure list
  1159. ProcessReliablePure( clientNum, msg );
  1160. break;
  1161. }
  1162. default: {
  1163. // pass reliable message on to game code
  1164. game->ServerProcessReliableMessage( clientNum, msg );
  1165. break;
  1166. }
  1167. }
  1168. }
  1169. }
  1170. /*
  1171. ==================
  1172. idAsyncServer::ProcessAuthMessage
  1173. ==================
  1174. */
  1175. void idAsyncServer::ProcessAuthMessage( const idBitMsg &msg ) {
  1176. netadr_t client_from;
  1177. char client_guid[ 12 ], string[ MAX_STRING_CHARS ];
  1178. int i, clientId;
  1179. authReply_t reply;
  1180. authReplyMsg_t replyMsg = AUTH_REPLY_WAITING;
  1181. idStr replyPrintMsg;
  1182. reply = (authReply_t)msg.ReadByte();
  1183. if ( reply <= 0 || reply >= AUTH_MAXSTATES ) {
  1184. common->DPrintf( "auth: invalid reply %d\n", reply );
  1185. return;
  1186. }
  1187. clientId = msg.ReadShort( );
  1188. msg.ReadNetadr( &client_from );
  1189. msg.ReadString( client_guid, sizeof( client_guid ) );
  1190. if ( reply != AUTH_OK ) {
  1191. replyMsg = (authReplyMsg_t)msg.ReadByte();
  1192. if ( replyMsg <= 0 || replyMsg >= AUTH_REPLY_MAXSTATES ) {
  1193. common->DPrintf( "auth: invalid reply msg %d\n", replyMsg );
  1194. return;
  1195. }
  1196. if ( replyMsg == AUTH_REPLY_PRINT ) {
  1197. msg.ReadString( string, MAX_STRING_CHARS );
  1198. replyPrintMsg = string;
  1199. }
  1200. }
  1201. lastAuthTime = serverTime;
  1202. // no message parsing below
  1203. for ( i = 0; i < MAX_CHALLENGES; i++ ) {
  1204. if ( !challenges[i].connected && challenges[ i ].clientId == clientId ) {
  1205. // return if something is wrong
  1206. // break if we have found a valid auth
  1207. if ( !strlen( challenges[ i ].guid ) ) {
  1208. common->DPrintf( "auth: client %s has no guid yet\n", Sys_NetAdrToString( challenges[ i ].address ) );
  1209. return;
  1210. }
  1211. if ( idStr::Cmp( challenges[ i ].guid, client_guid ) ) {
  1212. common->DPrintf( "auth: client %s %s not matched, auth server says guid %s\n", Sys_NetAdrToString( challenges[ i ].address ), challenges[i].guid, client_guid );
  1213. return;
  1214. }
  1215. if ( !Sys_CompareNetAdrBase( client_from, challenges[i].address ) ) {
  1216. // let auth work when server and master don't see the same IP
  1217. common->DPrintf( "auth: matched guid '%s' for != IPs %s and %s\n", client_guid, Sys_NetAdrToString( client_from ), Sys_NetAdrToString( challenges[i].address ) );
  1218. }
  1219. break;
  1220. }
  1221. }
  1222. if ( i >= MAX_CHALLENGES ) {
  1223. common->DPrintf( "auth: failed client lookup %s %s\n", Sys_NetAdrToString( client_from ), client_guid );
  1224. return;
  1225. }
  1226. if ( challenges[ i ].authState != CDK_WAIT ) {
  1227. common->DWarning( "auth: challenge 0x%x %s authState %d != CDK_WAIT", challenges[ i ].challenge, Sys_NetAdrToString( challenges[ i ].address ), challenges[ i ].authState );
  1228. return;
  1229. }
  1230. idStr::snPrintf( challenges[ i ].guid, 12, client_guid );
  1231. if ( reply == AUTH_OK ) {
  1232. challenges[ i ].authState = CDK_OK;
  1233. common->Printf( "client %s %s is authed\n", Sys_NetAdrToString( client_from ), client_guid );
  1234. } else {
  1235. const char *msg;
  1236. if ( replyMsg != AUTH_REPLY_PRINT ) {
  1237. msg = authReplyMsg[ replyMsg ];
  1238. } else {
  1239. msg = replyPrintMsg.c_str();
  1240. }
  1241. // maybe localize it
  1242. const char *l_msg = common->GetLanguageDict()->GetString( msg );
  1243. common->DPrintf( "auth: client %s %s - %s %s\n", Sys_NetAdrToString( client_from ), client_guid, authReplyStr[ reply ], l_msg );
  1244. challenges[ i ].authReply = reply;
  1245. challenges[ i ].authReplyMsg = replyMsg;
  1246. challenges[ i ].authReplyPrint = replyPrintMsg;
  1247. }
  1248. }
  1249. /*
  1250. ==================
  1251. idAsyncServer::ProcessChallengeMessage
  1252. ==================
  1253. */
  1254. void idAsyncServer::ProcessChallengeMessage( const netadr_t from, const idBitMsg &msg ) {
  1255. int i, clientId, oldest, oldestTime;
  1256. idBitMsg outMsg;
  1257. byte msgBuf[MAX_MESSAGE_SIZE];
  1258. clientId = msg.ReadLong();
  1259. oldest = 0;
  1260. oldestTime = 0x7fffffff;
  1261. // see if we already have a challenge for this ip
  1262. for ( i = 0; i < MAX_CHALLENGES; i++ ) {
  1263. if ( !challenges[i].connected && Sys_CompareNetAdrBase( from, challenges[i].address ) && clientId == challenges[i].clientId ) {
  1264. break;
  1265. }
  1266. if ( challenges[i].time < oldestTime ) {
  1267. oldestTime = challenges[i].time;
  1268. oldest = i;
  1269. }
  1270. }
  1271. if ( i >= MAX_CHALLENGES ) {
  1272. // this is the first time this client has asked for a challenge
  1273. i = oldest;
  1274. challenges[i].address = from;
  1275. challenges[i].clientId = clientId;
  1276. challenges[i].challenge = ( (rand() << 16) ^ rand() ) ^ serverTime;
  1277. challenges[i].time = serverTime;
  1278. challenges[i].connected = false;
  1279. challenges[i].authState = CDK_WAIT;
  1280. challenges[i].authReply = AUTH_NONE;
  1281. challenges[i].authReplyMsg = AUTH_REPLY_WAITING;
  1282. challenges[i].authReplyPrint = "";
  1283. challenges[i].guid[0] = '\0';
  1284. }
  1285. challenges[i].pingTime = serverTime;
  1286. common->Printf( "sending challenge 0x%x to %s\n", challenges[i].challenge, Sys_NetAdrToString( from ) );
  1287. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1288. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1289. outMsg.WriteString( "challengeResponse" );
  1290. outMsg.WriteLong( challenges[i].challenge );
  1291. outMsg.WriteShort( serverId );
  1292. outMsg.WriteString( cvarSystem->GetCVarString( "fs_game_base" ) );
  1293. outMsg.WriteString( cvarSystem->GetCVarString( "fs_game" ) );
  1294. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  1295. if ( Sys_IsLANAddress( from ) ) {
  1296. // no CD Key check for LAN clients
  1297. challenges[i].authState = CDK_OK;
  1298. } else {
  1299. if ( idAsyncNetwork::LANServer.GetBool() ) {
  1300. common->Printf( "net_LANServer is enabled. Client %s is not a LAN address, will be rejected\n", Sys_NetAdrToString( from ) );
  1301. challenges[ i ].authState = CDK_ONLYLAN;
  1302. } else {
  1303. // emit a cd key confirmation request
  1304. outMsg.BeginWriting();
  1305. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1306. outMsg.WriteString( "srvAuth" );
  1307. outMsg.WriteLong( ASYNC_PROTOCOL_VERSION );
  1308. outMsg.WriteNetadr( from );
  1309. outMsg.WriteLong( -1 ); // this identifies "challenge" auth vs "connect" auth
  1310. // protocol 1.37 addition
  1311. outMsg.WriteByte( fileSystem->RunningD3XP() );
  1312. serverPort.SendPacket( idAsyncNetwork::GetMasterAddress(), outMsg.GetData(), outMsg.GetSize() );
  1313. }
  1314. }
  1315. }
  1316. /*
  1317. ==================
  1318. idAsyncServer::SendPureServerMessage
  1319. ==================
  1320. */
  1321. bool idAsyncServer::SendPureServerMessage( const netadr_t to, int OS ) {
  1322. idBitMsg outMsg;
  1323. byte msgBuf[ MAX_MESSAGE_SIZE ];
  1324. int serverChecksums[ MAX_PURE_PAKS ];
  1325. int gamePakChecksum;
  1326. int i;
  1327. fileSystem->GetPureServerChecksums( serverChecksums, OS, &gamePakChecksum );
  1328. if ( !serverChecksums[ 0 ] ) {
  1329. // happens if you run fully expanded assets with si_pure 1
  1330. common->Warning( "pure server has no pak files referenced" );
  1331. return false;
  1332. }
  1333. common->DPrintf( "client %s: sending pure pak list\n", Sys_NetAdrToString( to ) );
  1334. // send our list of required paks
  1335. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1336. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1337. outMsg.WriteString( "pureServer" );
  1338. i = 0;
  1339. while ( serverChecksums[ i ] ) {
  1340. outMsg.WriteLong( serverChecksums[ i++ ] );
  1341. }
  1342. outMsg.WriteLong( 0 );
  1343. // write the pak checksum for game code
  1344. outMsg.WriteLong( gamePakChecksum );
  1345. serverPort.SendPacket( to, outMsg.GetData(), outMsg.GetSize() );
  1346. return true;
  1347. }
  1348. /*
  1349. ==================
  1350. idAsyncServer::SendReliablePureToClient
  1351. ==================
  1352. */
  1353. bool idAsyncServer::SendReliablePureToClient( int clientNum ) {
  1354. idBitMsg msg;
  1355. byte msgBuf[ MAX_MESSAGE_SIZE ];
  1356. int serverChecksums[ MAX_PURE_PAKS ];
  1357. int i;
  1358. int gamePakChecksum;
  1359. fileSystem->GetPureServerChecksums( serverChecksums, clients[ clientNum ].OS, &gamePakChecksum );
  1360. if ( !serverChecksums[ 0 ] ) {
  1361. // happens if you run fully expanded assets with si_pure 1
  1362. common->Warning( "pure server has no pak files referenced" );
  1363. return false;
  1364. }
  1365. common->DPrintf( "client %d: sending pure pak list (reliable channel) @ gameInitId %d\n", clientNum, gameInitId );
  1366. msg.Init( msgBuf, sizeof( msgBuf ) );
  1367. msg.WriteByte( SERVER_RELIABLE_MESSAGE_PURE );
  1368. msg.WriteLong( gameInitId );
  1369. i = 0;
  1370. while ( serverChecksums[ i ] ) {
  1371. msg.WriteLong( serverChecksums[ i++ ] );
  1372. }
  1373. msg.WriteLong( 0 );
  1374. msg.WriteLong( gamePakChecksum );
  1375. SendReliableMessage( clientNum, msg );
  1376. return true;
  1377. }
  1378. /*
  1379. ==================
  1380. idAsyncServer::ValidateChallenge
  1381. ==================
  1382. */
  1383. int idAsyncServer::ValidateChallenge( const netadr_t from, int challenge, int clientId ) {
  1384. int i;
  1385. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1386. const serverClient_t &client = clients[i];
  1387. if ( client.clientState == SCS_FREE ) {
  1388. continue;
  1389. }
  1390. if ( Sys_CompareNetAdrBase( from, client.channel.GetRemoteAddress() ) &&
  1391. ( clientId == client.clientId || from.port == client.channel.GetRemoteAddress().port ) ) {
  1392. if ( serverTime - client.lastConnectTime < MIN_RECONNECT_TIME ) {
  1393. common->Printf( "%s: reconnect rejected : too soon\n", Sys_NetAdrToString( from ) );
  1394. return -1;
  1395. }
  1396. break;
  1397. }
  1398. }
  1399. for ( i = 0; i < MAX_CHALLENGES; i++ ) {
  1400. if ( Sys_CompareNetAdrBase( from, challenges[i].address ) && from.port == challenges[i].address.port ) {
  1401. if ( challenge == challenges[i].challenge ) {
  1402. break;
  1403. }
  1404. }
  1405. }
  1406. if ( i == MAX_CHALLENGES ) {
  1407. PrintOOB( from, SERVER_PRINT_BADCHALLENGE, "#str_04840" );
  1408. return -1;
  1409. }
  1410. return i;
  1411. }
  1412. /*
  1413. ==================
  1414. idAsyncServer::ProcessConnectMessage
  1415. ==================
  1416. */
  1417. void idAsyncServer::ProcessConnectMessage( const netadr_t from, const idBitMsg &msg ) {
  1418. int clientNum, protocol, clientDataChecksum, challenge, clientId, ping, clientRate;
  1419. idBitMsg outMsg;
  1420. byte msgBuf[ MAX_MESSAGE_SIZE ];
  1421. char guid[ 12 ];
  1422. char password[ 17 ];
  1423. int i, ichallenge, islot, OS, numClients;
  1424. protocol = msg.ReadLong();
  1425. OS = msg.ReadShort();
  1426. // check the protocol version
  1427. if ( protocol != ASYNC_PROTOCOL_VERSION ) {
  1428. // that's a msg back to a client, we don't know about it's localization, so send english
  1429. PrintOOB( from, SERVER_PRINT_BADPROTOCOL, va( "server uses protocol %d.%d\n", ASYNC_PROTOCOL_MAJOR, ASYNC_PROTOCOL_MINOR ) );
  1430. return;
  1431. }
  1432. clientDataChecksum = msg.ReadLong();
  1433. challenge = msg.ReadLong();
  1434. clientId = msg.ReadShort();
  1435. clientRate = msg.ReadLong();
  1436. // check the client data - only for non pure servers
  1437. if ( !sessLocal.mapSpawnData.serverInfo.GetInt( "si_pure" ) && clientDataChecksum != serverDataChecksum ) {
  1438. PrintOOB( from, SERVER_PRINT_MISC, "#str_04842" );
  1439. return;
  1440. }
  1441. if ( ( ichallenge = ValidateChallenge( from, challenge, clientId ) ) == -1 ) {
  1442. return;
  1443. }
  1444. challenges[ ichallenge ].OS = OS;
  1445. msg.ReadString( guid, sizeof( guid ) );
  1446. switch ( challenges[ ichallenge ].authState ) {
  1447. case CDK_PUREWAIT:
  1448. SendPureServerMessage( from, OS );
  1449. return;
  1450. case CDK_ONLYLAN:
  1451. common->DPrintf( "%s: not a lan client\n", Sys_NetAdrToString( from ) );
  1452. PrintOOB( from, SERVER_PRINT_MISC, "#str_04843" );
  1453. return;
  1454. case CDK_WAIT:
  1455. if ( challenges[ ichallenge ].authReply == AUTH_NONE && Min( serverTime - lastAuthTime, serverTime - challenges[ ichallenge ].time ) > AUTHORIZE_TIMEOUT ) {
  1456. common->DPrintf( "%s: Authorize server timed out\n", Sys_NetAdrToString( from ) );
  1457. break; // will continue with the connecting process
  1458. }
  1459. const char *msg, *l_msg;
  1460. if ( challenges[ ichallenge ].authReplyMsg != AUTH_REPLY_PRINT ) {
  1461. msg = authReplyMsg[ challenges[ ichallenge ].authReplyMsg ];
  1462. } else {
  1463. msg = challenges[ ichallenge ].authReplyPrint.c_str();
  1464. }
  1465. l_msg = common->GetLanguageDict()->GetString( msg );
  1466. common->DPrintf( "%s: %s\n", Sys_NetAdrToString( from ), l_msg );
  1467. if ( challenges[ ichallenge ].authReplyMsg == AUTH_REPLY_UNKNOWN || challenges[ ichallenge ].authReplyMsg == AUTH_REPLY_WAITING ) {
  1468. // the client may be trying to connect to us in LAN mode, and the server disagrees
  1469. // let the client know so it would switch to authed connection
  1470. idBitMsg outMsg;
  1471. byte msgBuf[ MAX_MESSAGE_SIZE ];
  1472. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1473. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1474. outMsg.WriteString( "authrequired" );
  1475. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  1476. }
  1477. PrintOOB( from, SERVER_PRINT_MISC, msg );
  1478. // update the guid in the challenges
  1479. idStr::snPrintf( challenges[ ichallenge ].guid, sizeof( challenges[ ichallenge ].guid ), guid );
  1480. // once auth replied denied, stop sending further requests
  1481. if ( challenges[ ichallenge ].authReply != AUTH_DENY ) {
  1482. // emit a cd key confirmation request
  1483. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1484. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1485. outMsg.WriteString( "srvAuth" );
  1486. outMsg.WriteLong( ASYNC_PROTOCOL_VERSION );
  1487. outMsg.WriteNetadr( from );
  1488. outMsg.WriteLong( clientId );
  1489. outMsg.WriteString( guid );
  1490. // protocol 1.37 addition
  1491. outMsg.WriteByte( fileSystem->RunningD3XP() );
  1492. serverPort.SendPacket( idAsyncNetwork::GetMasterAddress(), outMsg.GetData(), outMsg.GetSize() );
  1493. }
  1494. return;
  1495. default:
  1496. assert( challenges[ ichallenge ].authState == CDK_OK || challenges[ ichallenge ].authState == CDK_PUREOK );
  1497. }
  1498. numClients = 0;
  1499. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1500. serverClient_t &client = clients[ i ];
  1501. if ( client.clientState >= SCS_PUREWAIT ) {
  1502. numClients++;
  1503. }
  1504. }
  1505. // game may be passworded, client banned by IP or GUID
  1506. // if authState == CDK_PUREOK, the check was already performed once before entering pure checks
  1507. // but meanwhile, the max players may have been reached
  1508. msg.ReadString( password, sizeof( password ) );
  1509. char reason[MAX_STRING_CHARS];
  1510. allowReply_t reply = game->ServerAllowClient( numClients, Sys_NetAdrToString( from ), guid, password, reason );
  1511. if ( reply != ALLOW_YES ) {
  1512. common->DPrintf( "game denied connection for %s\n", Sys_NetAdrToString( from ) );
  1513. // SERVER_PRINT_GAMEDENY passes the game opcode through. Don't use PrintOOB
  1514. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1515. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1516. outMsg.WriteString( "print" );
  1517. outMsg.WriteLong( SERVER_PRINT_GAMEDENY );
  1518. outMsg.WriteLong( reply );
  1519. outMsg.WriteString( reason );
  1520. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  1521. return;
  1522. }
  1523. // enter pure checks if necessary
  1524. if ( sessLocal.mapSpawnData.serverInfo.GetInt( "si_pure" ) && challenges[ ichallenge ].authState != CDK_PUREOK ) {
  1525. if ( SendPureServerMessage( from, OS ) ) {
  1526. challenges[ ichallenge ].authState = CDK_PUREWAIT;
  1527. return;
  1528. }
  1529. }
  1530. // push back decl checksum here when running pure. just an additional safe check
  1531. if ( sessLocal.mapSpawnData.serverInfo.GetInt( "si_pure" ) && clientDataChecksum != serverDataChecksum ) {
  1532. PrintOOB( from, SERVER_PRINT_MISC, "#str_04844" );
  1533. return;
  1534. }
  1535. ping = serverTime - challenges[ ichallenge ].pingTime;
  1536. common->Printf( "challenge from %s connecting with %d ping\n", Sys_NetAdrToString( from ), ping );
  1537. challenges[ ichallenge ].connected = true;
  1538. // find a slot for the client
  1539. for ( islot = 0; islot < 3; islot++ ) {
  1540. for ( clientNum = 0; clientNum < MAX_ASYNC_CLIENTS; clientNum++ ) {
  1541. serverClient_t &client = clients[ clientNum ];
  1542. if ( islot == 0 ) {
  1543. // if this slot uses the same IP and port
  1544. if ( Sys_CompareNetAdrBase( from, client.channel.GetRemoteAddress() ) &&
  1545. ( clientId == client.clientId || from.port == client.channel.GetRemoteAddress().port ) ) {
  1546. break;
  1547. }
  1548. } else if ( islot == 1 ) {
  1549. // if this client is not connected and the slot uses the same IP
  1550. if ( client.clientState >= SCS_PUREWAIT ) {
  1551. continue;
  1552. }
  1553. if ( Sys_CompareNetAdrBase( from, client.channel.GetRemoteAddress() ) ) {
  1554. break;
  1555. }
  1556. } else if ( islot == 2 ) {
  1557. // if this slot is free
  1558. if ( client.clientState == SCS_FREE ) {
  1559. break;
  1560. }
  1561. }
  1562. }
  1563. if ( clientNum < MAX_ASYNC_CLIENTS ) {
  1564. // initialize
  1565. clients[ clientNum ].channel.Init( from, serverId );
  1566. clients[ clientNum ].OS = OS;
  1567. strncpy( clients[ clientNum ].guid, guid, 12 );
  1568. clients[ clientNum ].guid[11] = 0;
  1569. break;
  1570. }
  1571. }
  1572. // if no free spots available
  1573. if ( clientNum >= MAX_ASYNC_CLIENTS ) {
  1574. PrintOOB( from, SERVER_PRINT_MISC, "#str_04845" );
  1575. return;
  1576. }
  1577. common->Printf( "sending connect response to %s\n", Sys_NetAdrToString( from ) );
  1578. // send connect response message
  1579. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1580. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1581. outMsg.WriteString( "connectResponse" );
  1582. outMsg.WriteLong( clientNum );
  1583. outMsg.WriteLong( gameInitId );
  1584. outMsg.WriteLong( gameFrame );
  1585. outMsg.WriteLong( gameTime );
  1586. outMsg.WriteDeltaDict( sessLocal.mapSpawnData.serverInfo, NULL );
  1587. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  1588. InitClient( clientNum, clientId, clientRate );
  1589. clients[clientNum].gameInitSequence = 1;
  1590. clients[clientNum].snapshotSequence = 1;
  1591. // clear the challenge struct so a reconnect from this client IP starts clean
  1592. memset( &challenges[ ichallenge ], 0, sizeof( challenge_t ) );
  1593. }
  1594. /*
  1595. ==================
  1596. idAsyncServer::VerifyChecksumMessage
  1597. ==================
  1598. */
  1599. bool idAsyncServer::VerifyChecksumMessage( int clientNum, const netadr_t *from, const idBitMsg &msg, idStr &reply, int OS ) {
  1600. int i, numChecksums;
  1601. int checksums[ MAX_PURE_PAKS ];
  1602. int gamePakChecksum;
  1603. int serverChecksums[ MAX_PURE_PAKS ];
  1604. int serverGamePakChecksum;
  1605. // pak checksums, in a 0-terminated list
  1606. numChecksums = 0;
  1607. do {
  1608. i = msg.ReadLong( );
  1609. checksums[ numChecksums++ ] = i;
  1610. // just to make sure a broken client doesn't crash us
  1611. if ( numChecksums >= MAX_PURE_PAKS ) {
  1612. common->Warning( "MAX_PURE_PAKS ( %d ) exceeded in idAsyncServer::ProcessPureMessage\n", MAX_PURE_PAKS );
  1613. sprintf( reply, "#str_07144" );
  1614. return false;
  1615. }
  1616. } while ( i );
  1617. numChecksums--;
  1618. // code pak checksum
  1619. gamePakChecksum = msg.ReadLong( );
  1620. fileSystem->GetPureServerChecksums( serverChecksums, OS, &serverGamePakChecksum );
  1621. assert( serverChecksums[ 0 ] );
  1622. // compare the lists
  1623. if ( serverGamePakChecksum != gamePakChecksum ) {
  1624. common->Printf( "client %s: invalid game code pak ( 0x%x )\n", from ? Sys_NetAdrToString( *from ) : va( "%d", clientNum ), gamePakChecksum );
  1625. sprintf( reply, "#str_07145" );
  1626. return false;
  1627. }
  1628. for ( i = 0; serverChecksums[ i ] != 0; i++ ) {
  1629. if ( checksums[ i ] != serverChecksums[ i ] ) {
  1630. common->DPrintf( "client %s: pak missing ( 0x%x )\n", from ? Sys_NetAdrToString( *from ) : va( "%d", clientNum ), serverChecksums[ i ] );
  1631. sprintf( reply, "pak missing ( 0x%x )\n", serverChecksums[ i ] );
  1632. return false;
  1633. }
  1634. }
  1635. if ( checksums[ i ] != 0 ) {
  1636. common->DPrintf( "client %s: extra pak file referenced ( 0x%x )\n", from ? Sys_NetAdrToString( *from ) : va( "%d", clientNum ), checksums[ i ] );
  1637. sprintf( reply, "extra pak file referenced ( 0x%x )\n", checksums[ i ] );
  1638. return false;
  1639. }
  1640. return true;
  1641. }
  1642. /*
  1643. ==================
  1644. idAsyncServer::ProcessPureMessage
  1645. ==================
  1646. */
  1647. void idAsyncServer::ProcessPureMessage( const netadr_t from, const idBitMsg &msg ) {
  1648. int iclient, challenge, clientId;
  1649. idStr reply;
  1650. challenge = msg.ReadLong();
  1651. clientId = msg.ReadShort();
  1652. if ( ( iclient = ValidateChallenge( from, challenge, clientId ) ) == -1 ) {
  1653. return;
  1654. }
  1655. if ( challenges[ iclient ].authState != CDK_PUREWAIT ) {
  1656. common->DPrintf( "client %s: got pure message, not in CDK_PUREWAIT\n", Sys_NetAdrToString( from ) );
  1657. return;
  1658. }
  1659. if ( !VerifyChecksumMessage( iclient, &from, msg, reply, challenges[ iclient ].OS ) ) {
  1660. PrintOOB( from, SERVER_PRINT_MISC, reply );
  1661. return;
  1662. }
  1663. common->DPrintf( "client %s: passed pure checks\n", Sys_NetAdrToString( from ) );
  1664. challenges[ iclient ].authState = CDK_PUREOK; // next connect message will get the client through completely
  1665. }
  1666. /*
  1667. ==================
  1668. idAsyncServer::ProcessReliablePure
  1669. ==================
  1670. */
  1671. void idAsyncServer::ProcessReliablePure( int clientNum, const idBitMsg &msg ) {
  1672. idStr reply;
  1673. idBitMsg outMsg;
  1674. byte msgBuf[MAX_MESSAGE_SIZE];
  1675. int clientGameInitId;
  1676. clientGameInitId = msg.ReadLong();
  1677. if ( clientGameInitId != gameInitId ) {
  1678. common->DPrintf( "client %d: ignoring reliable pure from an old gameInit (%d)\n", clientNum, clientGameInitId );
  1679. return;
  1680. }
  1681. if ( clients[ clientNum ].clientState != SCS_PUREWAIT ) {
  1682. // should not happen unless something is very wrong. still, don't let this crash us, just get rid of the client
  1683. common->DPrintf( "client %d: got reliable pure while != SCS_PUREWAIT, sending a reload\n", clientNum );
  1684. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1685. outMsg.WriteByte( SERVER_RELIABLE_MESSAGE_RELOAD );
  1686. SendReliableMessage( clientNum, msg );
  1687. // go back to SCS_CONNECTED to sleep on the client until it goes away for a reconnect
  1688. clients[ clientNum ].clientState = SCS_CONNECTED;
  1689. return;
  1690. }
  1691. if ( !VerifyChecksumMessage( clientNum, NULL, msg, reply, clients[ clientNum ].OS ) ) {
  1692. DropClient( clientNum, reply );
  1693. return;
  1694. }
  1695. common->DPrintf( "client %d: passed pure checks (reliable channel)\n", clientNum );
  1696. clients[ clientNum ].clientState = SCS_CONNECTED;
  1697. }
  1698. /*
  1699. ==================
  1700. idAsyncServer::RemoteConsoleOutput
  1701. ==================
  1702. */
  1703. void idAsyncServer::RemoteConsoleOutput( const char *string ) {
  1704. noRconOutput = false;
  1705. PrintOOB( rconAddress, SERVER_PRINT_RCON, string );
  1706. }
  1707. /*
  1708. ==================
  1709. RConRedirect
  1710. ==================
  1711. */
  1712. void RConRedirect( const char *string ) {
  1713. idAsyncNetwork::server.RemoteConsoleOutput( string );
  1714. }
  1715. /*
  1716. ==================
  1717. idAsyncServer::ProcessRemoteConsoleMessage
  1718. ==================
  1719. */
  1720. void idAsyncServer::ProcessRemoteConsoleMessage( const netadr_t from, const idBitMsg &msg ) {
  1721. idBitMsg outMsg;
  1722. byte msgBuf[952];
  1723. char string[MAX_STRING_CHARS];
  1724. if ( idAsyncNetwork::serverRemoteConsolePassword.GetString()[0] == '\0' ) {
  1725. PrintOOB( from, SERVER_PRINT_MISC, "#str_04846" );
  1726. return;
  1727. }
  1728. msg.ReadString( string, sizeof( string ) );
  1729. if ( idStr::Icmp( string, idAsyncNetwork::serverRemoteConsolePassword.GetString() ) != 0 ) {
  1730. PrintOOB( from, SERVER_PRINT_MISC, "#str_04847" );
  1731. return;
  1732. }
  1733. msg.ReadString( string, sizeof( string ) );
  1734. common->Printf( "rcon from %s: %s\n", Sys_NetAdrToString( from ), string );
  1735. rconAddress = from;
  1736. noRconOutput = true;
  1737. common->BeginRedirect( (char *)msgBuf, sizeof( msgBuf ), RConRedirect );
  1738. cmdSystem->BufferCommandText( CMD_EXEC_NOW, string );
  1739. common->EndRedirect();
  1740. if ( noRconOutput ) {
  1741. PrintOOB( rconAddress, SERVER_PRINT_RCON, "#str_04848" );
  1742. }
  1743. }
  1744. /*
  1745. ==================
  1746. idAsyncServer::ProcessGetInfoMessage
  1747. ==================
  1748. */
  1749. void idAsyncServer::ProcessGetInfoMessage( const netadr_t from, const idBitMsg &msg ) {
  1750. int i, challenge;
  1751. idBitMsg outMsg;
  1752. byte msgBuf[MAX_MESSAGE_SIZE];
  1753. if ( !IsActive() ) {
  1754. return;
  1755. }
  1756. common->DPrintf( "Sending info response to %s\n", Sys_NetAdrToString( from ) );
  1757. challenge = msg.ReadLong();
  1758. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1759. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1760. outMsg.WriteString( "infoResponse" );
  1761. outMsg.WriteLong( challenge );
  1762. outMsg.WriteLong( ASYNC_PROTOCOL_VERSION );
  1763. outMsg.WriteDeltaDict( sessLocal.mapSpawnData.serverInfo, NULL );
  1764. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1765. serverClient_t &client = clients[i];
  1766. if ( client.clientState < SCS_CONNECTED ) {
  1767. continue;
  1768. }
  1769. outMsg.WriteByte( i );
  1770. outMsg.WriteShort( client.clientPing );
  1771. outMsg.WriteLong( client.channel.GetMaxOutgoingRate() );
  1772. outMsg.WriteString( sessLocal.mapSpawnData.userInfo[i].GetString( "ui_name", "Player" ) );
  1773. }
  1774. outMsg.WriteByte( MAX_ASYNC_CLIENTS );
  1775. outMsg.WriteLong( fileSystem->GetOSMask() );
  1776. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  1777. }
  1778. /*
  1779. ===============
  1780. idAsyncServer::PrintLocalServerInfo
  1781. see (client) "getInfo" -> (server) "infoResponse" -> (client)ProcessGetInfoMessage
  1782. ===============
  1783. */
  1784. void idAsyncServer::PrintLocalServerInfo( void ) {
  1785. int i;
  1786. common->Printf( "server '%s' IP = %s\nprotocol %d.%d OS mask 0x%x\n",
  1787. sessLocal.mapSpawnData.serverInfo.GetString( "si_name" ),
  1788. Sys_NetAdrToString( serverPort.GetAdr() ),
  1789. ASYNC_PROTOCOL_MAJOR,
  1790. ASYNC_PROTOCOL_MINOR,
  1791. fileSystem->GetOSMask() );
  1792. sessLocal.mapSpawnData.serverInfo.Print();
  1793. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1794. serverClient_t &client = clients[i];
  1795. if ( client.clientState < SCS_CONNECTED ) {
  1796. continue;
  1797. }
  1798. common->Printf( "client %2d: %s, ping = %d, rate = %d\n", i,
  1799. sessLocal.mapSpawnData.userInfo[i].GetString( "ui_name", "Player" ),
  1800. client.clientPing, client.channel.GetMaxOutgoingRate() );
  1801. }
  1802. }
  1803. /*
  1804. ==================
  1805. idAsyncServer::ConnectionlessMessage
  1806. ==================
  1807. */
  1808. bool idAsyncServer::ConnectionlessMessage( const netadr_t from, const idBitMsg &msg ) {
  1809. char string[MAX_STRING_CHARS*2]; // M. Quinn - Even Balance - PB Packets need more than 1024
  1810. msg.ReadString( string, sizeof( string ) );
  1811. // info request
  1812. if ( idStr::Icmp( string, "getInfo" ) == 0 ) {
  1813. ProcessGetInfoMessage( from, msg );
  1814. return false;
  1815. }
  1816. // remote console
  1817. if ( idStr::Icmp( string, "rcon" ) == 0 ) {
  1818. ProcessRemoteConsoleMessage( from, msg );
  1819. return true;
  1820. }
  1821. if ( !active ) {
  1822. PrintOOB( from, SERVER_PRINT_MISC, "#str_04849" );
  1823. return false;
  1824. }
  1825. // challenge from a client
  1826. if ( idStr::Icmp( string, "challenge" ) == 0 ) {
  1827. ProcessChallengeMessage( from, msg );
  1828. return false;
  1829. }
  1830. // connect from a client
  1831. if ( idStr::Icmp( string, "connect" ) == 0 ) {
  1832. ProcessConnectMessage( from, msg );
  1833. return false;
  1834. }
  1835. // pure mesasge from a client
  1836. if ( idStr::Icmp( string, "pureClient" ) == 0 ) {
  1837. ProcessPureMessage( from, msg );
  1838. return false;
  1839. }
  1840. // download request
  1841. if ( idStr::Icmp( string, "downloadRequest" ) == 0 ) {
  1842. ProcessDownloadRequestMessage( from, msg );
  1843. }
  1844. // auth server
  1845. if ( idStr::Icmp( string, "auth" ) == 0 ) {
  1846. if ( !Sys_CompareNetAdrBase( from, idAsyncNetwork::GetMasterAddress() ) ) {
  1847. common->Printf( "auth: bad source %s\n", Sys_NetAdrToString( from ) );
  1848. return false;
  1849. }
  1850. if ( idAsyncNetwork::LANServer.GetBool() ) {
  1851. common->Printf( "auth message from master. net_LANServer is enabled, ignored.\n" );
  1852. }
  1853. ProcessAuthMessage( msg );
  1854. return false;
  1855. }
  1856. return false;
  1857. }
  1858. /*
  1859. ==================
  1860. idAsyncServer::ProcessMessage
  1861. ==================
  1862. */
  1863. bool idAsyncServer::ProcessMessage( const netadr_t from, idBitMsg &msg ) {
  1864. int i, id, sequence;
  1865. idBitMsg outMsg;
  1866. byte msgBuf[MAX_MESSAGE_SIZE];
  1867. id = msg.ReadShort();
  1868. // check for a connectionless message
  1869. if ( id == CONNECTIONLESS_MESSAGE_ID ) {
  1870. return ConnectionlessMessage( from, msg );
  1871. }
  1872. if ( msg.GetRemaingData() < 4 ) {
  1873. common->DPrintf( "%s: tiny packet\n", Sys_NetAdrToString( from ) );
  1874. return false;
  1875. }
  1876. // find out which client the message is from
  1877. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1878. serverClient_t &client = clients[i];
  1879. if ( client.clientState == SCS_FREE ) {
  1880. continue;
  1881. }
  1882. // This does not compare the UDP port, because some address translating
  1883. // routers will change that at arbitrary times.
  1884. if ( !Sys_CompareNetAdrBase( from, client.channel.GetRemoteAddress() ) || id != client.clientId ) {
  1885. continue;
  1886. }
  1887. // make sure it is a valid, in sequence packet
  1888. if ( !client.channel.Process( from, serverTime, msg, sequence ) ) {
  1889. return false; // out of order, duplicated, fragment, etc.
  1890. }
  1891. // zombie clients still need to do the channel processing to make sure they don't
  1892. // need to retransmit the final reliable message, but they don't do any other processing
  1893. if ( client.clientState == SCS_ZOMBIE ) {
  1894. return false;
  1895. }
  1896. client.lastPacketTime = serverTime;
  1897. ProcessReliableClientMessages( i );
  1898. ProcessUnreliableClientMessage( i, msg );
  1899. return false;
  1900. }
  1901. // if we received a sequenced packet from an address we don't recognize,
  1902. // send an out of band disconnect packet to it
  1903. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1904. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  1905. outMsg.WriteString( "disconnect" );
  1906. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  1907. return false;
  1908. }
  1909. /*
  1910. ==================
  1911. idAsyncServer::SendReliableGameMessage
  1912. ==================
  1913. */
  1914. void idAsyncServer::SendReliableGameMessage( int clientNum, const idBitMsg &msg ) {
  1915. int i;
  1916. idBitMsg outMsg;
  1917. byte msgBuf[MAX_MESSAGE_SIZE];
  1918. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1919. outMsg.WriteByte( SERVER_RELIABLE_MESSAGE_GAME );
  1920. outMsg.WriteData( msg.GetData(), msg.GetSize() );
  1921. if ( clientNum >= 0 && clientNum < MAX_ASYNC_CLIENTS ) {
  1922. if ( clients[clientNum].clientState == SCS_INGAME ) {
  1923. SendReliableMessage( clientNum, outMsg );
  1924. }
  1925. return;
  1926. }
  1927. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1928. if ( clients[i].clientState != SCS_INGAME ) {
  1929. continue;
  1930. }
  1931. SendReliableMessage( i, outMsg );
  1932. }
  1933. }
  1934. /*
  1935. ==================
  1936. idAsyncServer::LocalClientSendReliableMessageExcluding
  1937. ==================
  1938. */
  1939. void idAsyncServer::SendReliableGameMessageExcluding( int clientNum, const idBitMsg &msg ) {
  1940. int i;
  1941. idBitMsg outMsg;
  1942. byte msgBuf[MAX_MESSAGE_SIZE];
  1943. assert( clientNum >= 0 && clientNum < MAX_ASYNC_CLIENTS );
  1944. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  1945. outMsg.WriteByte( SERVER_RELIABLE_MESSAGE_GAME );
  1946. outMsg.WriteData( msg.GetData(), msg.GetSize() );
  1947. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  1948. if ( i == clientNum ) {
  1949. continue;
  1950. }
  1951. if ( clients[i].clientState != SCS_INGAME ) {
  1952. continue;
  1953. }
  1954. SendReliableMessage( i, outMsg );
  1955. }
  1956. }
  1957. /*
  1958. ==================
  1959. idAsyncServer::LocalClientSendReliableMessage
  1960. ==================
  1961. */
  1962. void idAsyncServer::LocalClientSendReliableMessage( const idBitMsg &msg ) {
  1963. if ( localClientNum < 0 ) {
  1964. common->Printf( "LocalClientSendReliableMessage: no local client\n" );
  1965. return;
  1966. }
  1967. game->ServerProcessReliableMessage( localClientNum, msg );
  1968. }
  1969. /*
  1970. ==================
  1971. idAsyncServer::ProcessConnectionLessMessages
  1972. ==================
  1973. */
  1974. void idAsyncServer::ProcessConnectionLessMessages( void ) {
  1975. int size, id;
  1976. idBitMsg msg;
  1977. byte msgBuf[MAX_MESSAGE_SIZE];
  1978. netadr_t from;
  1979. if ( !serverPort.GetPort() ) {
  1980. return;
  1981. }
  1982. while( serverPort.GetPacket( from, msgBuf, size, sizeof( msgBuf ) ) ) {
  1983. msg.Init( msgBuf, sizeof( msgBuf ) );
  1984. msg.SetSize( size );
  1985. msg.BeginReading();
  1986. id = msg.ReadShort();
  1987. if ( id == CONNECTIONLESS_MESSAGE_ID ) {
  1988. ConnectionlessMessage( from, msg );
  1989. }
  1990. }
  1991. }
  1992. /*
  1993. ==================
  1994. idAsyncServer::UpdateTime
  1995. ==================
  1996. */
  1997. int idAsyncServer::UpdateTime( int clamp ) {
  1998. int time, msec;
  1999. time = Sys_Milliseconds();
  2000. msec = idMath::ClampInt( 0, clamp, time - realTime );
  2001. realTime = time;
  2002. serverTime += msec;
  2003. return msec;
  2004. }
  2005. /*
  2006. ==================
  2007. idAsyncServer::RunFrame
  2008. ==================
  2009. */
  2010. void idAsyncServer::RunFrame( void ) {
  2011. int i, msec, size;
  2012. bool newPacket;
  2013. idBitMsg msg;
  2014. byte msgBuf[MAX_MESSAGE_SIZE];
  2015. netadr_t from;
  2016. int outgoingRate, incomingRate;
  2017. float outgoingCompression, incomingCompression;
  2018. msec = UpdateTime( 100 );
  2019. if ( !serverPort.GetPort() ) {
  2020. return;
  2021. }
  2022. if ( !active ) {
  2023. ProcessConnectionLessMessages();
  2024. return;
  2025. }
  2026. gameTimeResidual += msec;
  2027. // spin in place processing incoming packets until enough time lapsed to run a new game frame
  2028. do {
  2029. do {
  2030. // blocking read with game time residual timeout
  2031. newPacket = serverPort.GetPacketBlocking( from, msgBuf, size, sizeof( msgBuf ), USERCMD_MSEC - gameTimeResidual - 1 );
  2032. if ( newPacket ) {
  2033. msg.Init( msgBuf, sizeof( msgBuf ) );
  2034. msg.SetSize( size );
  2035. msg.BeginReading();
  2036. if ( ProcessMessage( from, msg ) ) {
  2037. return; // return because rcon was used
  2038. }
  2039. }
  2040. msec = UpdateTime( 100 );
  2041. gameTimeResidual += msec;
  2042. } while( newPacket );
  2043. } while( gameTimeResidual < USERCMD_MSEC );
  2044. // send heart beat to master servers
  2045. MasterHeartbeat();
  2046. // check for clients that timed out
  2047. CheckClientTimeouts();
  2048. if ( idAsyncNetwork::idleServer.GetBool() == ( !GetNumClients() || GetNumIdleClients() != GetNumClients() ) ) {
  2049. idAsyncNetwork::idleServer.SetBool( !idAsyncNetwork::idleServer.GetBool() );
  2050. // the need to propagate right away, only this
  2051. sessLocal.mapSpawnData.serverInfo.Set( "si_idleServer", idAsyncNetwork::idleServer.GetString() );
  2052. game->SetServerInfo( sessLocal.mapSpawnData.serverInfo );
  2053. }
  2054. // make sure the time doesn't wrap
  2055. if ( serverTime > 0x70000000 ) {
  2056. ExecuteMapChange();
  2057. return;
  2058. }
  2059. // check for synchronized cvar changes
  2060. if ( cvarSystem->GetModifiedFlags() & CVAR_NETWORKSYNC ) {
  2061. idDict newCvars;
  2062. newCvars = *cvarSystem->MoveCVarsToDict( CVAR_NETWORKSYNC );
  2063. SendSyncedCvarsBroadcast( newCvars );
  2064. cvarSystem->ClearModifiedFlags( CVAR_NETWORKSYNC );
  2065. }
  2066. // check for user info changes of the local client
  2067. if ( cvarSystem->GetModifiedFlags() & CVAR_USERINFO ) {
  2068. if ( localClientNum >= 0 ) {
  2069. idDict newInfo;
  2070. game->ThrottleUserInfo( );
  2071. newInfo = *cvarSystem->MoveCVarsToDict( CVAR_USERINFO );
  2072. SendUserInfoBroadcast( localClientNum, newInfo );
  2073. }
  2074. cvarSystem->ClearModifiedFlags( CVAR_USERINFO );
  2075. }
  2076. // advance the server game
  2077. while( gameTimeResidual >= USERCMD_MSEC ) {
  2078. // sample input for the local client
  2079. LocalClientInput();
  2080. // duplicate usercmds for clients if no new ones are available
  2081. DuplicateUsercmds( gameFrame, gameTime );
  2082. // advance game
  2083. gameReturn_t ret = game->RunFrame( userCmds[gameFrame & ( MAX_USERCMD_BACKUP - 1 ) ] );
  2084. idAsyncNetwork::ExecuteSessionCommand( ret.sessionCommand );
  2085. // update time
  2086. gameFrame++;
  2087. gameTime += USERCMD_MSEC;
  2088. gameTimeResidual -= USERCMD_MSEC;
  2089. }
  2090. // duplicate usercmds so there is always at least one available to send with snapshots
  2091. DuplicateUsercmds( gameFrame, gameTime );
  2092. // send snapshots to connected clients
  2093. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  2094. serverClient_t &client = clients[i];
  2095. if ( client.clientState == SCS_FREE || i == localClientNum ) {
  2096. continue;
  2097. }
  2098. // modify maximum rate if necesary
  2099. if ( idAsyncNetwork::serverMaxClientRate.IsModified() ) {
  2100. client.channel.SetMaxOutgoingRate( Min( client.clientRate, idAsyncNetwork::serverMaxClientRate.GetInteger() ) );
  2101. }
  2102. // if the channel is not yet ready to send new data
  2103. if ( !client.channel.ReadyToSend( serverTime ) ) {
  2104. continue;
  2105. }
  2106. // send additional message fragments if the last message was too large to send at once
  2107. if ( client.channel.UnsentFragmentsLeft() ) {
  2108. client.channel.SendNextFragment( serverPort, serverTime );
  2109. continue;
  2110. }
  2111. if ( client.clientState == SCS_INGAME ) {
  2112. if ( !SendSnapshotToClient( i ) ) {
  2113. SendPingToClient( i );
  2114. }
  2115. } else {
  2116. SendEmptyToClient( i );
  2117. }
  2118. }
  2119. if ( com_showAsyncStats.GetBool() ) {
  2120. UpdateAsyncStatsAvg();
  2121. // dedicated will verbose to console
  2122. if ( idAsyncNetwork::serverDedicated.GetBool() && serverTime >= nextAsyncStatsTime ) {
  2123. common->Printf( "delay = %d msec, total outgoing rate = %d KB/s, total incoming rate = %d KB/s\n", GetDelay(),
  2124. GetOutgoingRate() >> 10, GetIncomingRate() >> 10 );
  2125. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  2126. outgoingRate = GetClientOutgoingRate( i );
  2127. incomingRate = GetClientIncomingRate( i );
  2128. outgoingCompression = GetClientOutgoingCompression( i );
  2129. incomingCompression = GetClientIncomingCompression( i );
  2130. if ( outgoingRate != -1 && incomingRate != -1 ) {
  2131. common->Printf( "client %d: out rate = %d B/s (% -2.1f%%), in rate = %d B/s (% -2.1f%%)\n",
  2132. i, outgoingRate, outgoingCompression, incomingRate, incomingCompression );
  2133. }
  2134. }
  2135. idStr msg;
  2136. GetAsyncStatsAvgMsg( msg );
  2137. common->Printf( va( "%s\n", msg.c_str() ) );
  2138. nextAsyncStatsTime = serverTime + 1000;
  2139. }
  2140. }
  2141. idAsyncNetwork::serverMaxClientRate.ClearModified();
  2142. }
  2143. /*
  2144. ==================
  2145. idAsyncServer::PacifierUpdate
  2146. ==================
  2147. */
  2148. void idAsyncServer::PacifierUpdate( void ) {
  2149. int i;
  2150. if ( !IsActive() ) {
  2151. return;
  2152. }
  2153. realTime = Sys_Milliseconds();
  2154. ProcessConnectionLessMessages();
  2155. for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
  2156. if ( clients[i].clientState >= SCS_PUREWAIT ) {
  2157. if ( clients[i].channel.UnsentFragmentsLeft() ) {
  2158. clients[i].channel.SendNextFragment( serverPort, serverTime );
  2159. } else {
  2160. SendEmptyToClient( i );
  2161. }
  2162. }
  2163. }
  2164. }
  2165. /*
  2166. ==================
  2167. idAsyncServer::PrintOOB
  2168. ==================
  2169. */
  2170. void idAsyncServer::PrintOOB( const netadr_t to, int opcode, const char *string ) {
  2171. idBitMsg outMsg;
  2172. byte msgBuf[ MAX_MESSAGE_SIZE ];
  2173. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  2174. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  2175. outMsg.WriteString( "print" );
  2176. outMsg.WriteLong( opcode );
  2177. outMsg.WriteString( string );
  2178. serverPort.SendPacket( to, outMsg.GetData(), outMsg.GetSize() );
  2179. }
  2180. /*
  2181. ==================
  2182. idAsyncServer::MasterHeartbeat
  2183. ==================
  2184. */
  2185. void idAsyncServer::MasterHeartbeat( bool force ) {
  2186. if ( idAsyncNetwork::LANServer.GetBool() ) {
  2187. if ( force ) {
  2188. common->Printf( "net_LANServer is enabled. Not sending heartbeats\n" );
  2189. }
  2190. return;
  2191. }
  2192. if ( force ) {
  2193. nextHeartbeatTime = 0;
  2194. }
  2195. // not yet
  2196. if ( serverTime < nextHeartbeatTime ) {
  2197. return;
  2198. }
  2199. nextHeartbeatTime = serverTime + HEARTBEAT_MSEC;
  2200. for ( int i = 0 ; i < MAX_MASTER_SERVERS ; i++ ) {
  2201. netadr_t adr;
  2202. if ( idAsyncNetwork::GetMasterAddress( i, adr ) ) {
  2203. common->Printf( "Sending heartbeat to %s\n", Sys_NetAdrToString( adr ) );
  2204. idBitMsg outMsg;
  2205. byte msgBuf[ MAX_MESSAGE_SIZE ];
  2206. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  2207. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  2208. outMsg.WriteString( "heartbeat" );
  2209. serverPort.SendPacket( adr, outMsg.GetData(), outMsg.GetSize() );
  2210. }
  2211. }
  2212. }
  2213. /*
  2214. ===============
  2215. idAsyncServer::SendEnterGameToClient
  2216. ===============
  2217. */
  2218. void idAsyncServer::SendEnterGameToClient( int clientNum ) {
  2219. idBitMsg msg;
  2220. byte msgBuf[ MAX_MESSAGE_SIZE ];
  2221. msg.Init( msgBuf, sizeof( msgBuf ) );
  2222. msg.WriteByte( SERVER_RELIABLE_MESSAGE_ENTERGAME );
  2223. SendReliableMessage( clientNum, msg );
  2224. }
  2225. /*
  2226. ===============
  2227. idAsyncServer::UpdateAsyncStatsAvg
  2228. ===============
  2229. */
  2230. void idAsyncServer::UpdateAsyncStatsAvg( void ) {
  2231. stats_average_sum -= stats_outrate[ stats_current ];
  2232. stats_outrate[ stats_current ] = idAsyncNetwork::server.GetOutgoingRate();
  2233. if ( stats_outrate[ stats_current ] > stats_max ) {
  2234. stats_max = stats_outrate[ stats_current ];
  2235. stats_max_index = stats_current;
  2236. } else if ( stats_current == stats_max_index ) {
  2237. // find the new max
  2238. int i;
  2239. stats_max = 0;
  2240. for ( i = 0; i < stats_numsamples ; i++ ) {
  2241. if ( stats_outrate[ i ] > stats_max ) {
  2242. stats_max = stats_outrate[ i ];
  2243. stats_max_index = i;
  2244. }
  2245. }
  2246. }
  2247. stats_average_sum += stats_outrate[ stats_current ];
  2248. stats_current++; stats_current %= stats_numsamples;
  2249. }
  2250. /*
  2251. ===============
  2252. idAsyncServer::GetAsyncStatsAvgMsg
  2253. ===============
  2254. */
  2255. void idAsyncServer::GetAsyncStatsAvgMsg( idStr &msg ) {
  2256. sprintf( msg, "avrg out: %d B/s - max %d B/s ( over %d ms )", stats_average_sum / stats_numsamples, stats_max, idAsyncNetwork::serverSnapshotDelay.GetInteger() * stats_numsamples );
  2257. }
  2258. /*
  2259. ===============
  2260. idAsyncServer::ProcessDownloadRequestMessage
  2261. ===============
  2262. */
  2263. void idAsyncServer::ProcessDownloadRequestMessage( const netadr_t from, const idBitMsg &msg ) {
  2264. int challenge, clientId, iclient, numPaks, i;
  2265. int dlGamePak;
  2266. int dlPakChecksum;
  2267. int dlSize[ MAX_PURE_PAKS ]; // sizes
  2268. idStrList pakNames; // relative path
  2269. idStrList pakURLs; // game URLs
  2270. char pakbuf[ MAX_STRING_CHARS ];
  2271. idStr paklist;
  2272. byte msgBuf[ MAX_MESSAGE_SIZE ];
  2273. byte tmpBuf[ MAX_MESSAGE_SIZE ];
  2274. idBitMsg outMsg, tmpMsg;
  2275. int dlRequest;
  2276. int voidSlots = 0; // to count and verbose the right number of paks requested for downloads
  2277. challenge = msg.ReadLong();
  2278. clientId = msg.ReadShort();
  2279. dlRequest = msg.ReadLong();
  2280. if ( ( iclient = ValidateChallenge( from, challenge, clientId ) ) == -1 ) {
  2281. return;
  2282. }
  2283. if ( challenges[ iclient ].authState != CDK_PUREWAIT ) {
  2284. common->DPrintf( "client %s: got download request message, not in CDK_PUREWAIT\n", Sys_NetAdrToString( from ) );
  2285. return;
  2286. }
  2287. // the first token of the pak names list passed to the game will be empty if no game pak is requested
  2288. dlGamePak = msg.ReadLong();
  2289. if ( dlGamePak ) {
  2290. if ( !( dlSize[ 0 ] = fileSystem->ValidateDownloadPakForChecksum( dlGamePak, pakbuf, true ) ) ) {
  2291. common->Warning( "client requested unknown game pak 0x%x", dlGamePak );
  2292. pakbuf[ 0 ] = '\0';
  2293. voidSlots++;
  2294. }
  2295. } else {
  2296. pakbuf[ 0 ] = '\0';
  2297. voidSlots++;
  2298. }
  2299. pakNames.Append( pakbuf );
  2300. numPaks = 1;
  2301. // read the checksums, build path names and pass that to the game code
  2302. dlPakChecksum = msg.ReadLong();
  2303. while ( dlPakChecksum ) {
  2304. if ( !( dlSize[ numPaks ] = fileSystem->ValidateDownloadPakForChecksum( dlPakChecksum, pakbuf, false ) ) ) {
  2305. // we pass an empty token to the game so our list doesn't get offset
  2306. common->Warning( "client requested an unknown pak 0x%x", dlPakChecksum );
  2307. pakbuf[ 0 ] = '\0';
  2308. voidSlots++;
  2309. }
  2310. pakNames.Append( pakbuf );
  2311. numPaks++;
  2312. dlPakChecksum = msg.ReadLong();
  2313. }
  2314. for ( i = 0; i < pakNames.Num(); i++ ) {
  2315. if ( i > 0 ) {
  2316. paklist += ";";
  2317. }
  2318. paklist += pakNames[ i ].c_str();
  2319. }
  2320. // read the message and pass it to the game code
  2321. common->DPrintf( "got download request for %d paks - %s\n", numPaks - voidSlots, paklist.c_str() );
  2322. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  2323. outMsg.WriteShort( CONNECTIONLESS_MESSAGE_ID );
  2324. outMsg.WriteString( "downloadInfo" );
  2325. outMsg.WriteLong( dlRequest );
  2326. if ( !game->DownloadRequest( Sys_NetAdrToString( from ), challenges[ iclient ].guid, paklist.c_str(), pakbuf ) ) {
  2327. common->DPrintf( "game: no downloads\n" );
  2328. outMsg.WriteByte( SERVER_DL_NONE );
  2329. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  2330. return;
  2331. }
  2332. char *token, *next;
  2333. int type = 0;
  2334. token = pakbuf;
  2335. next = strchr( token, ';' );
  2336. while ( token ) {
  2337. if ( next ) {
  2338. *next = '\0';
  2339. }
  2340. if ( type == 0 ) {
  2341. type = atoi( token );
  2342. } else if ( type == SERVER_DL_REDIRECT ) {
  2343. common->DPrintf( "download request: redirect to URL %s\n", token );
  2344. outMsg.WriteByte( SERVER_DL_REDIRECT );
  2345. outMsg.WriteString( token );
  2346. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  2347. return;
  2348. } else if ( type == SERVER_DL_LIST ) {
  2349. pakURLs.Append( token );
  2350. } else {
  2351. common->DPrintf( "wrong op type %d\n", type );
  2352. next = token = NULL;
  2353. }
  2354. if ( next ) {
  2355. token = next + 1;
  2356. next = strchr( token, ';' );
  2357. } else {
  2358. token = NULL;
  2359. }
  2360. }
  2361. if ( type == SERVER_DL_LIST ) {
  2362. int totalDlSize = 0;
  2363. int numActualPaks = 0;
  2364. // put the answer packet together
  2365. outMsg.WriteByte( SERVER_DL_LIST );
  2366. tmpMsg.Init( tmpBuf, MAX_MESSAGE_SIZE );
  2367. for ( i = 0; i < pakURLs.Num(); i++ ) {
  2368. tmpMsg.BeginWriting();
  2369. if ( !dlSize[ i ] || !pakURLs[ i ].Length() ) {
  2370. // still send the relative path so the client knows what it missed
  2371. tmpMsg.WriteByte( SERVER_PAK_NO );
  2372. tmpMsg.WriteString( pakNames[ i ] );
  2373. } else {
  2374. totalDlSize += dlSize[ i ];
  2375. numActualPaks++;
  2376. tmpMsg.WriteByte( SERVER_PAK_YES );
  2377. tmpMsg.WriteString( pakNames[ i ] );
  2378. tmpMsg.WriteString( pakURLs[ i ] );
  2379. tmpMsg.WriteLong( dlSize[ i ] );
  2380. }
  2381. // keep last 5 bytes for an 'end of message' - SERVER_PAK_END and the totalDlSize long
  2382. if ( outMsg.GetRemainingSpace() - tmpMsg.GetSize() > 5 ) {
  2383. outMsg.WriteData( tmpMsg.GetData(), tmpMsg.GetSize() );
  2384. } else {
  2385. outMsg.WriteByte( SERVER_PAK_END );
  2386. break;
  2387. }
  2388. }
  2389. if ( i == pakURLs.Num() ) {
  2390. // put a closure even if size not exceeded
  2391. outMsg.WriteByte( SERVER_PAK_END );
  2392. }
  2393. common->DPrintf( "download request: download %d paks, %d bytes\n", numActualPaks, totalDlSize );
  2394. serverPort.SendPacket( from, outMsg.GetData(), outMsg.GetSize() );
  2395. }
  2396. }