Advertisement
jxsl13

Untitled

Apr 7th, 2015
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 61.70 KB | None | 0 0
  1. /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  2. /* If you are missing that file, acquire a complete release at teeworlds.com. */
  3. /* Modified by Teelevision for zCatch/TeeVi, see readme.txt and license.txt. */
  4. /* Modified by Blindhero for 64 Client System */
  5.  
  6. #include <base/math.h>
  7. #include <base/system.h>
  8.  
  9. #include <engine/config.h>
  10. #include <engine/console.h>
  11. #include <engine/engine.h>
  12. #include <engine/map.h>
  13. #include <engine/masterserver.h>
  14. #include <engine/server.h>
  15. #include <engine/storage.h>
  16.  
  17. #include <engine/shared/compression.h>
  18. #include <engine/shared/config.h>
  19. #include <engine/shared/datafile.h>
  20. #include <engine/shared/demo.h>
  21. #include <engine/shared/econ.h>
  22. #include <engine/shared/filecollection.h>
  23. #include <engine/shared/mapchecker.h>
  24. #include <engine/shared/netban.h>
  25. #include <engine/shared/network.h>
  26. #include <engine/shared/packer.h>
  27. #include <engine/shared/protocol.h>
  28. #include <engine/shared/snapshot.h>
  29.  
  30. #include <mastersrv/mastersrv.h>
  31.  
  32. #include "register.h"
  33. #include "server.h"
  34.  
  35. #if defined(CONF_FAMILY_WINDOWS)
  36. #define _WIN32_WINNT 0x0501
  37. #define WIN32_LEAN_AND_MEAN
  38. #include <windows.h>
  39. #endif
  40.  
  41. static const char *StrUTF8Ltrim(const char *pStr)
  42. {
  43. while(*pStr)
  44. {
  45. const char *pStrOld = pStr;
  46. int Code = str_utf8_decode(&pStr);
  47.  
  48. // check if unicode is not empty
  49. if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
  50. (Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
  51. Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
  52. {
  53. return pStrOld;
  54. }
  55. }
  56. return pStr;
  57. }
  58.  
  59. static void StrUTF8Rtrim(char *pStr)
  60. {
  61. const char *p = pStr;
  62. const char *pEnd = 0;
  63. while(*p)
  64. {
  65. const char *pStrOld = p;
  66. int Code = str_utf8_decode(&p);
  67.  
  68. // check if unicode is not empty
  69. if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
  70. (Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
  71. Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
  72. {
  73. pEnd = 0;
  74. }
  75. else if(pEnd == 0)
  76. pEnd = pStrOld;
  77. }
  78. if(pEnd != 0)
  79. *(const_cast<char *>(pEnd)) = 0;
  80. }
  81.  
  82.  
  83. CSnapIDPool::CSnapIDPool()
  84. {
  85. Reset();
  86. }
  87.  
  88. void CSnapIDPool::Reset()
  89. {
  90. for(int i = 0; i < MAX_IDS; i++)
  91. {
  92. m_aIDs[i].m_Next = i+1;
  93. m_aIDs[i].m_State = 0;
  94. }
  95.  
  96. m_aIDs[MAX_IDS-1].m_Next = -1;
  97. m_FirstFree = 0;
  98. m_FirstTimed = -1;
  99. m_LastTimed = -1;
  100. m_Usage = 0;
  101. m_InUsage = 0;
  102. }
  103.  
  104.  
  105. void CSnapIDPool::RemoveFirstTimeout()
  106. {
  107. int NextTimed = m_aIDs[m_FirstTimed].m_Next;
  108.  
  109. // add it to the free list
  110. m_aIDs[m_FirstTimed].m_Next = m_FirstFree;
  111. m_aIDs[m_FirstTimed].m_State = 0;
  112. m_FirstFree = m_FirstTimed;
  113.  
  114. // remove it from the timed list
  115. m_FirstTimed = NextTimed;
  116. if(m_FirstTimed == -1)
  117. m_LastTimed = -1;
  118.  
  119. m_Usage--;
  120. }
  121.  
  122. int CSnapIDPool::NewID()
  123. {
  124. int64 Now = time_get();
  125.  
  126. // process timed ids
  127. while(m_FirstTimed != -1 && m_aIDs[m_FirstTimed].m_Timeout < Now)
  128. RemoveFirstTimeout();
  129.  
  130. int ID = m_FirstFree;
  131. dbg_assert(ID != -1, "id error");
  132. if(ID == -1)
  133. return ID;
  134. m_FirstFree = m_aIDs[m_FirstFree].m_Next;
  135. m_aIDs[ID].m_State = 1;
  136. m_Usage++;
  137. m_InUsage++;
  138. return ID;
  139. }
  140.  
  141. void CSnapIDPool::TimeoutIDs()
  142. {
  143. // process timed ids
  144. while(m_FirstTimed != -1)
  145. RemoveFirstTimeout();
  146. }
  147.  
  148. void CSnapIDPool::FreeID(int ID)
  149. {
  150. if(ID < 0)
  151. return;
  152. dbg_assert(m_aIDs[ID].m_State == 1, "id is not alloced");
  153.  
  154. m_InUsage--;
  155. m_aIDs[ID].m_State = 2;
  156. m_aIDs[ID].m_Timeout = time_get()+time_freq()*5;
  157. m_aIDs[ID].m_Next = -1;
  158.  
  159. if(m_LastTimed != -1)
  160. {
  161. m_aIDs[m_LastTimed].m_Next = ID;
  162. m_LastTimed = ID;
  163. }
  164. else
  165. {
  166. m_FirstTimed = ID;
  167. m_LastTimed = ID;
  168. }
  169. }
  170.  
  171.  
  172. void CServerBan::InitServerBan(IConsole *pConsole, IStorage *pStorage, CServer* pServer)
  173. {
  174. CNetBan::Init(pConsole, pStorage);
  175.  
  176. m_pServer = pServer;
  177.  
  178. // overwrites base command, todo: improve this
  179. Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBanExt, this, "Ban player with ip/client id for x minutes for any reason");
  180. }
  181.  
  182. template<class T>
  183. int CServerBan::BanExt(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason)
  184. {
  185. // validate address
  186. if(Server()->m_RconClientID >= 0 && Server()->m_RconClientID < MAX_CLIENTS &&
  187. Server()->m_aClients[Server()->m_RconClientID].m_State != CServer::CClient::STATE_EMPTY)
  188. {
  189. if(NetMatch(pData, Server()->m_NetServer.ClientAddr(Server()->m_RconClientID)))
  190. {
  191. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (you can't ban yourself)");
  192. return -1;
  193. }
  194.  
  195. for(int i = 0; i < MAX_CLIENTS; ++i)
  196. {
  197. if(i == Server()->m_RconClientID || Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY)
  198. continue;
  199.  
  200. if(Server()->m_aClients[i].m_Authed >= Server()->m_RconAuthLevel && NetMatch(pData, Server()->m_NetServer.ClientAddr(i)))
  201. {
  202. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (command denied)");
  203. return -1;
  204. }
  205. }
  206. }
  207. else if(Server()->m_RconClientID == IServer::RCON_CID_VOTE)
  208. {
  209. for(int i = 0; i < MAX_CLIENTS; ++i)
  210. {
  211. if(Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY)
  212. continue;
  213.  
  214. if(Server()->m_aClients[i].m_Authed != CServer::AUTHED_NO && NetMatch(pData, Server()->m_NetServer.ClientAddr(i)))
  215. {
  216. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (command denied)");
  217. return -1;
  218. }
  219. }
  220. }
  221.  
  222. int Result = Ban(pBanPool, pData, Seconds, pReason);
  223. if(Result != 0)
  224. return Result;
  225.  
  226. // drop banned clients
  227. typename T::CDataType Data = *pData;
  228. for(int i = 0; i < MAX_CLIENTS; ++i)
  229. {
  230. if(Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY)
  231. continue;
  232.  
  233. if(NetMatch(&Data, Server()->m_NetServer.ClientAddr(i)))
  234. {
  235. CNetHash NetHash(&Data);
  236. char aBuf[256];
  237. MakeBanInfo(pBanPool->Find(&Data, &NetHash), aBuf, sizeof(aBuf), MSGTYPE_PLAYER);
  238. Server()->m_NetServer.Drop(i, aBuf);
  239. }
  240. }
  241.  
  242. return Result;
  243. }
  244.  
  245. int CServerBan::BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason)
  246. {
  247. return BanExt(&m_BanAddrPool, pAddr, Seconds, pReason);
  248. }
  249.  
  250. int CServerBan::BanRange(const CNetRange *pRange, int Seconds, const char *pReason)
  251. {
  252. if(pRange->IsValid())
  253. return BanExt(&m_BanRangePool, pRange, Seconds, pReason);
  254.  
  255. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (invalid range)");
  256. return -1;
  257. }
  258.  
  259. void CServerBan::ConBanExt(IConsole::IResult *pResult, void *pUser)
  260. {
  261. CServerBan *pThis = static_cast<CServerBan *>(pUser);
  262. const int defaultMinutes = 5;
  263.  
  264. const char *pStr = pResult->GetString(0);
  265. int Minutes = pResult->NumArguments()>1 ? clamp(pResult->GetInteger(1), 0, 44640) : defaultMinutes;
  266. const char *pReason = pResult->NumArguments()>2 ? pResult->GetString(2) : "No reason given";
  267.  
  268. // check if time was given or a reason instead
  269. const char *time;
  270. if(pResult->NumArguments() > 1)
  271. {
  272. // check if number given
  273. time = pResult->GetString(1);
  274. int i = str_length(time) - 1;
  275. for(; i >= 0; --i)
  276. if(time[i] < '0' || '9' < time[i])
  277. break;
  278. // in case that no number was given
  279. if(!(str_length(time) && i < 0))
  280. {
  281. Minutes = defaultMinutes;
  282. if(pResult->NumArguments() > 2)
  283. { // add to reason
  284. char *newReason = (char*)malloc(sizeof(char) * (str_length(time) + str_length(pReason) + 2));
  285. mem_copy(newReason, time, sizeof(char) * str_length(time));
  286. newReason[str_length(time)] = ' ';
  287. mem_copy(newReason + str_length(time) + 1, pReason, sizeof(char) * (str_length(pReason) + 1));
  288. pReason = newReason;
  289. }
  290. else
  291. { // the time is the actual reason
  292. pReason = time;
  293. }
  294. }
  295. }
  296.  
  297. int CID = -1;
  298. if(StrAllnum(pStr))
  299. CID = str_toint(pStr);
  300. else
  301. {
  302. NETADDR Addr;
  303. if(net_addr_from_str(&Addr, pStr) == 0)
  304. for(int i = 0; i < MAX_CLIENTS; i++)
  305. if(pThis->NetMatch(&Addr, pThis->Server()->m_NetServer.ClientAddr(i)))
  306. {
  307. CID = i;
  308. break;
  309. }
  310. }
  311.  
  312. if(StrAllnum(pStr))
  313. {
  314. int ClientID = str_toint(pStr);
  315. if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->Server()->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
  316. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid client id)");
  317. else
  318. pThis->BanAddr(pThis->Server()->m_NetServer.ClientAddr(ClientID), Minutes*60, pReason);
  319. }
  320. else
  321. ConBan(pResult, pUser);
  322. }
  323.  
  324.  
  325. void CServer::CClient::Reset()
  326. {
  327. // reset input
  328. for(int i = 0; i < 200; i++)
  329. m_aInputs[i].m_GameTick = -1;
  330. m_CurrentInput = 0;
  331. mem_zero(&m_LatestInput, sizeof(m_LatestInput));
  332.  
  333. m_Snapshots.PurgeAll();
  334. m_LastAckedSnapshot = -1;
  335. m_LastInputTick = -1;
  336. m_SnapRate = CClient::SNAPRATE_INIT;
  337. m_Score = 0;
  338. }
  339.  
  340. CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
  341. {
  342. m_TickSpeed = SERVER_TICK_SPEED;
  343.  
  344. m_pGameServer = 0;
  345.  
  346. m_CurrentGameTick = 0;
  347. m_RunServer = 1;
  348.  
  349. m_pCurrentMapData = 0;
  350. m_CurrentMapSize = 0;
  351.  
  352. m_MapReload = 0;
  353.  
  354. m_RconClientID = IServer::RCON_CID_SERV;
  355. m_RconAuthLevel = AUTHED_ADMIN;
  356.  
  357. // when starting there are no admins
  358. m_numLoggedInAdmins = 0;
  359.  
  360. m_Votebans = NULL;
  361.  
  362. Init();
  363. }
  364.  
  365. CServer::~CServer()
  366. {
  367. // delte votebans
  368. while(m_Votebans != NULL)
  369. {
  370. CVoteban *tmp = m_Votebans->m_Next;
  371. delete m_Votebans;
  372. m_Votebans = tmp;
  373. }
  374. }
  375.  
  376.  
  377. int CServer::TrySetClientName(int ClientID, const char *pName)
  378. {
  379. char aTrimmedName[64];
  380.  
  381. // trim the name
  382. str_copy(aTrimmedName, StrUTF8Ltrim(pName), sizeof(aTrimmedName));
  383. StrUTF8Rtrim(aTrimmedName);
  384.  
  385. // check if new and old name are the same
  386. if(m_aClients[ClientID].m_aName[0] && str_comp(m_aClients[ClientID].m_aName, aTrimmedName) == 0)
  387. return 0;
  388.  
  389. char aBuf[256];
  390. str_format(aBuf, sizeof(aBuf), "'%s' -> '%s'", pName, aTrimmedName);
  391. Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
  392. pName = aTrimmedName;
  393.  
  394.  
  395. // check for empty names
  396. if(!pName[0])
  397. return -1;
  398.  
  399. // make sure that two clients doesn't have the same name
  400. for(int i = 0; i < MAX_CLIENTS; i++)
  401. if(i != ClientID && m_aClients[i].m_State >= CClient::STATE_READY)
  402. {
  403. if(str_comp(pName, m_aClients[i].m_aName) == 0)
  404. return -1;
  405. }
  406.  
  407. // set the client name
  408. str_copy(m_aClients[ClientID].m_aName, pName, MAX_NAME_LENGTH);
  409. return 0;
  410. }
  411.  
  412.  
  413.  
  414. void CServer::SetClientName(int ClientID, const char *pName)
  415. {
  416. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
  417. return;
  418.  
  419. if(!pName)
  420. return;
  421.  
  422. char aNameTry[MAX_NAME_LENGTH];
  423. str_copy(aNameTry, pName, MAX_NAME_LENGTH);
  424. if(TrySetClientName(ClientID, aNameTry))
  425. {
  426. // auto rename
  427. for(int i = 1;; i++)
  428. {
  429. str_format(aNameTry, MAX_NAME_LENGTH, "(%d)%s", i, pName);
  430. if(TrySetClientName(ClientID, aNameTry) == 0)
  431. break;
  432. }
  433. }
  434. }
  435.  
  436. void CServer::SetClientClan(int ClientID, const char *pClan)
  437. {
  438. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY || !pClan)
  439. return;
  440.  
  441. str_copy(m_aClients[ClientID].m_aClan, pClan, MAX_CLAN_LENGTH);
  442. }
  443.  
  444. void CServer::SetClientCountry(int ClientID, int Country)
  445. {
  446. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
  447. return;
  448.  
  449. m_aClients[ClientID].m_Country = Country;
  450. }
  451.  
  452. void CServer::SetClientScore(int ClientID, int Score)
  453. {
  454. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
  455. return;
  456. m_aClients[ClientID].m_Score = Score;
  457. }
  458.  
  459. void CServer::Kick(int ClientID, const char *pReason)
  460. {
  461. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State == CClient::STATE_EMPTY)
  462. {
  463. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid client id to kick");
  464. return;
  465. }
  466. else if(m_RconClientID == ClientID)
  467. {
  468. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't kick yourself");
  469. return;
  470. }
  471. else if(m_aClients[ClientID].m_Authed > m_RconAuthLevel)
  472. {
  473. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "kick command denied");
  474. return;
  475. }
  476.  
  477. m_NetServer.Drop(ClientID, pReason);
  478. }
  479.  
  480. /*int CServer::Tick()
  481. {
  482. return m_CurrentGameTick;
  483. }*/
  484.  
  485. int64 CServer::TickStartTime(int Tick)
  486. {
  487. return m_GameStartTime + (time_freq()*Tick)/SERVER_TICK_SPEED;
  488. }
  489.  
  490. /*int CServer::TickSpeed()
  491. {
  492. return SERVER_TICK_SPEED;
  493. }*/
  494.  
  495. int CServer::Init()
  496. {
  497. for(int i = 0; i < MAX_CLIENTS; i++)
  498. {
  499. m_aClients[i].m_State = CClient::STATE_EMPTY;
  500. m_aClients[i].m_aName[0] = 0;
  501. m_aClients[i].m_aClan[0] = 0;
  502. m_aClients[i].m_CustClt = 0;
  503. m_aClients[i].m_Country = -1;
  504. m_aClients[i].m_Snapshots.Init();
  505. }
  506.  
  507. AdjustVotebanTime(m_CurrentGameTick);
  508. m_CurrentGameTick = 0;
  509.  
  510. return 0;
  511. }
  512.  
  513. void CServer::SetRconCID(int ClientID)
  514. {
  515. m_RconClientID = ClientID;
  516. }
  517.  
  518. bool CServer::IsAuthed(int ClientID)
  519. {
  520. return m_aClients[ClientID].m_Authed;
  521. }
  522.  
  523. int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo)
  524. {
  525. char aBuf[128];
  526. str_format(aBuf, sizeof(aBuf), "client_id (%d) is not valid", ClientID);
  527. dbg_assert(ClientID >= 0 && ClientID < MAX_CLIENTS, aBuf);
  528. dbg_assert(pInfo != 0, "info can not be null");
  529.  
  530. if(m_aClients[ClientID].m_State == CClient::STATE_INGAME)
  531. {
  532. pInfo->m_pName = m_aClients[ClientID].m_aName;
  533. pInfo->m_Latency = m_aClients[ClientID].m_Latency;
  534. pInfo->m_CustClt = m_aClients[ClientID].m_CustClt;
  535. return 1;
  536. }
  537. return 0;
  538. }
  539.  
  540. void CServer::GetClientAddr(int ClientID, char *pAddrStr, int Size)
  541. {
  542. if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME)
  543. net_addr_str(m_NetServer.ClientAddr(ClientID), pAddrStr, Size, false);
  544. }
  545.  
  546.  
  547. const char *CServer::ClientName(int ClientID)
  548. {
  549. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
  550. return "(invalid)";
  551. if(m_aClients[ClientID].m_State == CServer::CClient::STATE_INGAME)
  552. return m_aClients[ClientID].m_aName;
  553. else
  554. return "(connecting)";
  555.  
  556. }
  557.  
  558. const char *CServer::ClientClan(int ClientID)
  559. {
  560. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
  561. return "";
  562. if(m_aClients[ClientID].m_State == CServer::CClient::STATE_INGAME)
  563. return m_aClients[ClientID].m_aClan;
  564. else
  565. return "";
  566. }
  567.  
  568. int CServer::ClientCountry(int ClientID)
  569. {
  570. if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
  571. return -1;
  572. if(m_aClients[ClientID].m_State == CServer::CClient::STATE_INGAME)
  573. return m_aClients[ClientID].m_Country;
  574. else
  575. return -1;
  576. }
  577.  
  578. bool CServer::ClientIngame(int ClientID)
  579. {
  580. return ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CServer::CClient::STATE_INGAME;
  581. }
  582.  
  583. int CServer::MaxClients() const
  584. {
  585. return m_NetServer.MaxClients();
  586. }
  587.  
  588. int CServer::SendMsg(CMsgPacker *pMsg, int Flags, int ClientID)
  589. {
  590. return SendMsgEx(pMsg, Flags, ClientID, false);
  591. }
  592.  
  593. int CServer::SendMsgEx(CMsgPacker *pMsg, int Flags, int ClientID, bool System)
  594. {
  595. CNetChunk Packet;
  596. if(!pMsg)
  597. return -1;
  598.  
  599. mem_zero(&Packet, sizeof(CNetChunk));
  600.  
  601. Packet.m_ClientID = ClientID;
  602. Packet.m_pData = pMsg->Data();
  603. Packet.m_DataSize = pMsg->Size();
  604.  
  605. // HACK: modify the message id in the packet and store the system flag
  606. *((unsigned char*)Packet.m_pData) <<= 1;
  607. if(System)
  608. *((unsigned char*)Packet.m_pData) |= 1;
  609.  
  610. if(Flags&MSGFLAG_VITAL)
  611. Packet.m_Flags |= NETSENDFLAG_VITAL;
  612. if(Flags&MSGFLAG_FLUSH)
  613. Packet.m_Flags |= NETSENDFLAG_FLUSH;
  614.  
  615. // write message to demo recorder
  616. if(!(Flags&MSGFLAG_NORECORD))
  617. m_DemoRecorder.RecordMessage(pMsg->Data(), pMsg->Size());
  618.  
  619. if(!(Flags&MSGFLAG_NOSEND))
  620. {
  621. if(ClientID == -1)
  622. {
  623. // broadcast
  624. int i;
  625. for(i = 0; i < MAX_CLIENTS; i++)
  626. if(m_aClients[i].m_State == CClient::STATE_INGAME)
  627. {
  628. Packet.m_ClientID = i;
  629. m_NetServer.Send(&Packet);
  630. }
  631. }
  632. else
  633. m_NetServer.Send(&Packet);
  634. }
  635. return 0;
  636. }
  637.  
  638. void CServer::DoSnapshot()
  639. {
  640. GameServer()->OnPreSnap();
  641.  
  642. // create snapshot for demo recording
  643. if(m_DemoRecorder.IsRecording())
  644. {
  645. char aData[CSnapshot::MAX_SIZE];
  646. int SnapshotSize;
  647.  
  648. // build snap and possibly add some messages
  649. m_SnapshotBuilder.Init();
  650. //GameServer()->OnSnap(-1);
  651. SnapshotSize = m_SnapshotBuilder.Finish(aData);
  652.  
  653. // write snapshot
  654. m_DemoRecorder.RecordSnapshot(Tick(), aData, SnapshotSize);
  655. }
  656.  
  657. // create snapshots for all clients
  658. for(int i = 0; i < MAX_CLIENTS; i++)
  659. {
  660. // client must be ingame to recive snapshots
  661. if(m_aClients[i].m_State != CClient::STATE_INGAME)
  662. continue;
  663.  
  664. // this client is trying to recover, don't spam snapshots
  665. if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_RECOVER && (Tick()%50) != 0)
  666. continue;
  667.  
  668. // this client is trying to recover, don't spam snapshots
  669. if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_INIT && (Tick()%10) != 0)
  670. continue;
  671.  
  672. {
  673. char aData[CSnapshot::MAX_SIZE];
  674. CSnapshot *pData = (CSnapshot*)aData; // Fix compiler warning for strict-aliasing
  675. char aDeltaData[CSnapshot::MAX_SIZE];
  676. char aCompData[CSnapshot::MAX_SIZE];
  677. int SnapshotSize;
  678. int Crc;
  679. static CSnapshot EmptySnap;
  680. CSnapshot *pDeltashot = &EmptySnap;
  681. int DeltashotSize;
  682. int DeltaTick = -1;
  683. int DeltaSize;
  684.  
  685. m_SnapshotBuilder.Init();
  686.  
  687. GameServer()->OnSnap(i);
  688.  
  689. // finish snapshot
  690. SnapshotSize = m_SnapshotBuilder.Finish(pData);
  691. Crc = pData->Crc();
  692.  
  693. // remove old snapshos
  694. // keep 3 seconds worth of snapshots
  695. m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentGameTick-SERVER_TICK_SPEED*3);
  696.  
  697. // save it the snapshot
  698. m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, pData, 0);
  699.  
  700. // find snapshot that we can preform delta against
  701. EmptySnap.Clear();
  702.  
  703. {
  704. DeltashotSize = m_aClients[i].m_Snapshots.Get(m_aClients[i].m_LastAckedSnapshot, 0, &pDeltashot, 0);
  705. if(DeltashotSize >= 0)
  706. DeltaTick = m_aClients[i].m_LastAckedSnapshot;
  707. else
  708. {
  709. // no acked package found, force client to recover rate
  710. if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_FULL)
  711. m_aClients[i].m_SnapRate = CClient::SNAPRATE_RECOVER;
  712. }
  713. }
  714.  
  715. // create delta
  716. DeltaSize = m_SnapshotDelta.CreateDelta(pDeltashot, pData, aDeltaData);
  717.  
  718. if(DeltaSize)
  719. {
  720. // compress it
  721. int SnapshotSize;
  722. const int MaxSize = MAX_SNAPSHOT_PACKSIZE;
  723. int NumPackets;
  724.  
  725. SnapshotSize = CVariableInt::Compress(aDeltaData, DeltaSize, aCompData);
  726. NumPackets = (SnapshotSize+MaxSize-1)/MaxSize;
  727.  
  728. for(int n = 0, Left = SnapshotSize; Left; n++)
  729. {
  730. int Chunk = Left < MaxSize ? Left : MaxSize;
  731. Left -= Chunk;
  732.  
  733. if(NumPackets == 1)
  734. {
  735. CMsgPacker Msg(NETMSG_SNAPSINGLE);
  736. Msg.AddInt(m_CurrentGameTick);
  737. Msg.AddInt(m_CurrentGameTick-DeltaTick);
  738. Msg.AddInt(Crc);
  739. Msg.AddInt(Chunk);
  740. Msg.AddRaw(&aCompData[n*MaxSize], Chunk);
  741. SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true);
  742. }
  743. else
  744. {
  745. CMsgPacker Msg(NETMSG_SNAP);
  746. Msg.AddInt(m_CurrentGameTick);
  747. Msg.AddInt(m_CurrentGameTick-DeltaTick);
  748. Msg.AddInt(NumPackets);
  749. Msg.AddInt(n);
  750. Msg.AddInt(Crc);
  751. Msg.AddInt(Chunk);
  752. Msg.AddRaw(&aCompData[n*MaxSize], Chunk);
  753. SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true);
  754. }
  755. }
  756. }
  757. else
  758. {
  759. CMsgPacker Msg(NETMSG_SNAPEMPTY);
  760. Msg.AddInt(m_CurrentGameTick);
  761. Msg.AddInt(m_CurrentGameTick-DeltaTick);
  762. SendMsgEx(&Msg, MSGFLAG_FLUSH, i, true);
  763. }
  764. }
  765. }
  766.  
  767. GameServer()->OnPostSnap();
  768. }
  769.  
  770.  
  771. int CServer::NewClientCallback(int ClientID, void *pUser)
  772. {
  773. CServer *pThis = (CServer *)pUser;
  774. pThis->m_aClients[ClientID].m_State = CClient::STATE_AUTH;
  775. pThis->m_aClients[ClientID].m_aName[0] = 0;
  776. pThis->m_aClients[ClientID].m_aClan[0] = 0;
  777. pThis->m_aClients[ClientID].m_Country = -1;
  778. pThis->m_aClients[ClientID].m_Authed = AUTHED_NO;
  779. pThis->m_aClients[ClientID].m_AuthTries = 0;
  780. pThis->m_aClients[ClientID].m_CustClt = 0;
  781. pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
  782. pThis->m_aClients[ClientID].m_CustClt = 0;
  783. pThis->m_aClients[ClientID].Reset();
  784. return 0;
  785. }
  786.  
  787. int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
  788. {
  789. CServer *pThis = (CServer *)pUser;
  790.  
  791. char aAddrStr[NETADDR_MAXSTRSIZE];
  792. net_addr_str(pThis->m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
  793. char aBuf[256];
  794. str_format(aBuf, sizeof(aBuf), "client dropped. cid=%d addr=%s reason='%s'", ClientID, aAddrStr, pReason);
  795. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
  796.  
  797. // notify the mod about the drop
  798. if(pThis->m_aClients[ClientID].m_State >= CClient::STATE_READY)
  799. pThis->GameServer()->OnClientDrop(ClientID, pReason);
  800.  
  801. // check if dropped player is admin
  802. if (pThis->m_aClients[ClientID].m_Authed == AUTHED_ADMIN) {
  803. pThis->DecreaseLoggedInAdmins();
  804. }
  805.  
  806. if(pThis->m_aClients[ClientID].m_Authed >= AUTHED_MOD)
  807. pThis->GameServer()->RconLogout(ClientID, pThis->m_aClients[ClientID].m_LoggedIn);
  808.  
  809. pThis->m_aClients[ClientID].m_State = CClient::STATE_EMPTY;
  810. pThis->m_aClients[ClientID].m_aName[0] = 0;
  811. pThis->m_aClients[ClientID].m_aClan[0] = 0;
  812. pThis->m_aClients[ClientID].m_Country = -1;
  813. pThis->m_aClients[ClientID].m_Authed = AUTHED_NO;
  814. pThis->m_aClients[ClientID].m_AuthTries = 0;
  815. pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
  816. pThis->m_aClients[ClientID].m_Snapshots.PurgeAll();
  817. return 0;
  818. }
  819.  
  820. void CServer::SendMap(int ClientID)
  821. {
  822. CMsgPacker Msg(NETMSG_MAP_CHANGE);
  823. Msg.AddString(GetMapName(), 0);
  824. Msg.AddInt(m_CurrentMapCrc);
  825. Msg.AddInt(m_CurrentMapSize);
  826. SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
  827. }
  828.  
  829. void CServer::SendConnectionReady(int ClientID)
  830. {
  831. CMsgPacker Msg(NETMSG_CON_READY);
  832. SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
  833. }
  834.  
  835. void CServer::SendRconLine(int ClientID, const char *pLine)
  836. {
  837. CMsgPacker Msg(NETMSG_RCON_LINE);
  838. Msg.AddString(pLine, 512);
  839. SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
  840. }
  841.  
  842. void CServer::SendRconLineAuthed(const char *pLine, void *pUser)
  843. {
  844. CServer *pThis = (CServer *)pUser;
  845. static volatile int ReentryGuard = 0;
  846. int i;
  847.  
  848. if(ReentryGuard) return;
  849. ReentryGuard++;
  850.  
  851. for(i = 0; i < MAX_CLIENTS; i++)
  852. {
  853. if(pThis->m_aClients[i].m_State != CClient::STATE_EMPTY && pThis->m_aClients[i].m_Authed >= pThis->m_RconAuthLevel)
  854. pThis->SendRconLine(i, pLine);
  855. }
  856.  
  857. ReentryGuard--;
  858. }
  859.  
  860. void CServer::SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientID)
  861. {
  862. CMsgPacker Msg(NETMSG_RCON_CMD_ADD);
  863. Msg.AddString(pCommandInfo->m_pName, IConsole::TEMPCMD_NAME_LENGTH);
  864. Msg.AddString(pCommandInfo->m_pHelp, IConsole::TEMPCMD_HELP_LENGTH);
  865. Msg.AddString(pCommandInfo->m_pParams, IConsole::TEMPCMD_PARAMS_LENGTH);
  866. SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
  867. }
  868.  
  869. void CServer::SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID)
  870. {
  871. CMsgPacker Msg(NETMSG_RCON_CMD_REM);
  872. Msg.AddString(pCommandInfo->m_pName, 256);
  873. SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
  874. }
  875.  
  876. void CServer::UpdateClientRconCommands()
  877. {
  878. int ClientID = Tick() % MAX_CLIENTS;
  879.  
  880. if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY && m_aClients[ClientID].m_Authed)
  881. {
  882. int ConsoleAccessLevel = m_aClients[ClientID].m_Authed == AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : IConsole::ACCESS_LEVEL_MOD;
  883. for(int i = 0; i < MAX_RCONCMD_SEND && m_aClients[ClientID].m_pRconCmdToSend; ++i)
  884. {
  885. SendRconCmdAdd(m_aClients[ClientID].m_pRconCmdToSend, ClientID);
  886. m_aClients[ClientID].m_pRconCmdToSend = m_aClients[ClientID].m_pRconCmdToSend->NextCommandInfo(ConsoleAccessLevel, CFGFLAG_SERVER);
  887. }
  888. }
  889. }
  890.  
  891. void CServer::ProcessClientPacket(CNetChunk *pPacket)
  892. {
  893. int ClientID = pPacket->m_ClientID;
  894. CUnpacker Unpacker;
  895. Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize);
  896.  
  897. // unpack msgid and system flag
  898. int Msg = Unpacker.GetInt();
  899. int Sys = Msg&1;
  900. Msg >>= 1;
  901.  
  902. if(Unpacker.Error())
  903. return;
  904.  
  905. if(Sys)
  906. {
  907. // system message
  908. if(Msg == NETMSG_INFO)
  909. {
  910. if(m_aClients[ClientID].m_State == CClient::STATE_AUTH)
  911. {
  912. const char *pVersion = Unpacker.GetString(CUnpacker::SANITIZE_CC);
  913. if(str_comp(pVersion, GameServer()->NetVersion()) != 0)
  914. {
  915. // wrong version
  916. char aReason[256];
  917. str_format(aReason, sizeof(aReason), "Wrong version. Server is running '%s' and client '%s'", GameServer()->NetVersion(), pVersion);
  918. m_NetServer.Drop(ClientID, aReason);
  919. return;
  920. }
  921.  
  922. const char *pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC);
  923. if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0)
  924. {
  925. // wrong password
  926. m_NetServer.Drop(ClientID, "Wrong password");
  927. return;
  928. }
  929.  
  930. m_aClients[ClientID].m_State = CClient::STATE_CONNECTING;
  931. SendMap(ClientID);
  932. }
  933. }
  934. else if(Msg == NETMSG_REQUEST_MAP_DATA)
  935. {
  936. if(m_aClients[ClientID].m_State < CClient::STATE_CONNECTING)
  937. return;
  938.  
  939. int Chunk = Unpacker.GetInt();
  940. int ChunkSize = 1024-128;
  941. int Offset = Chunk * ChunkSize;
  942. int Last = 0;
  943.  
  944. // drop faulty map data requests
  945. if(Chunk < 0 || Offset > m_CurrentMapSize)
  946. return;
  947.  
  948. if(Offset+ChunkSize >= m_CurrentMapSize)
  949. {
  950. ChunkSize = m_CurrentMapSize-Offset;
  951. if(ChunkSize < 0)
  952. ChunkSize = 0;
  953. Last = 1;
  954. }
  955.  
  956. CMsgPacker Msg(NETMSG_MAP_DATA);
  957. Msg.AddInt(Last);
  958. Msg.AddInt(m_CurrentMapCrc);
  959. Msg.AddInt(Chunk);
  960. Msg.AddInt(ChunkSize);
  961. Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize);
  962. SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
  963.  
  964. if(g_Config.m_Debug)
  965. {
  966. char aBuf[256];
  967. str_format(aBuf, sizeof(aBuf), "sending chunk %d with size %d", Chunk, ChunkSize);
  968. Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
  969. }
  970. }
  971. else if(Msg == NETMSG_READY)
  972. {
  973. if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING)
  974. {
  975. char aAddrStr[NETADDR_MAXSTRSIZE];
  976. net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
  977.  
  978. char aBuf[256];
  979. str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr);
  980. Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
  981. m_aClients[ClientID].m_State = CClient::STATE_READY;
  982. GameServer()->OnClientConnected(ClientID);
  983. SendConnectionReady(ClientID);
  984. }
  985. }
  986. else if(Msg == NETMSG_ENTERGAME)
  987. {
  988. if(m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID))
  989. {
  990. char aAddrStr[NETADDR_MAXSTRSIZE];
  991. net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
  992.  
  993. char aBuf[256];
  994. str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x addr=%s", ClientID, aAddrStr);
  995. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  996. m_aClients[ClientID].m_State = CClient::STATE_INGAME;
  997. GameServer()->OnClientEnter(ClientID);
  998. }
  999. }
  1000. else if(Msg == NETMSG_INPUT)
  1001. {
  1002. CClient::CInput *pInput;
  1003. int64 TagTime;
  1004.  
  1005. m_aClients[ClientID].m_LastAckedSnapshot = Unpacker.GetInt();
  1006. int IntendedTick = Unpacker.GetInt();
  1007. int Size = Unpacker.GetInt();
  1008.  
  1009. // check for errors
  1010. if(Unpacker.Error() || Size/4 > MAX_INPUT_SIZE)
  1011. return;
  1012.  
  1013. if(m_aClients[ClientID].m_LastAckedSnapshot > 0)
  1014. m_aClients[ClientID].m_SnapRate = CClient::SNAPRATE_FULL;
  1015.  
  1016. if(m_aClients[ClientID].m_Snapshots.Get(m_aClients[ClientID].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0)
  1017. m_aClients[ClientID].m_Latency = (int)(((time_get()-TagTime)*1000)/time_freq());
  1018.  
  1019. // add message to report the input timing
  1020. // skip packets that are old
  1021. if(IntendedTick > m_aClients[ClientID].m_LastInputTick)
  1022. {
  1023. int TimeLeft = ((TickStartTime(IntendedTick)-time_get())*1000) / time_freq();
  1024.  
  1025. CMsgPacker Msg(NETMSG_INPUTTIMING);
  1026. Msg.AddInt(IntendedTick);
  1027. Msg.AddInt(TimeLeft);
  1028. SendMsgEx(&Msg, 0, ClientID, true);
  1029. }
  1030.  
  1031. m_aClients[ClientID].m_LastInputTick = IntendedTick;
  1032.  
  1033. pInput = &m_aClients[ClientID].m_aInputs[m_aClients[ClientID].m_CurrentInput];
  1034.  
  1035. if(IntendedTick <= Tick())
  1036. IntendedTick = Tick()+1;
  1037.  
  1038. pInput->m_GameTick = IntendedTick;
  1039.  
  1040. for(int i = 0; i < Size/4; i++)
  1041. pInput->m_aData[i] = Unpacker.GetInt();
  1042.  
  1043. mem_copy(m_aClients[ClientID].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int));
  1044.  
  1045. m_aClients[ClientID].m_CurrentInput++;
  1046. m_aClients[ClientID].m_CurrentInput %= 200;
  1047.  
  1048. // call the mod with the fresh input data
  1049. if(m_aClients[ClientID].m_State == CClient::STATE_INGAME)
  1050. GameServer()->OnClientDirectInput(ClientID, m_aClients[ClientID].m_LatestInput.m_aData);
  1051. }
  1052.  
  1053. else if(Msg == NETMSG_RCON_CMD)
  1054. {
  1055. const char *pCmd = Unpacker.GetString();
  1056. if(Unpacker.Error() == 0 && !str_comp(pCmd, "crashmeplx"))
  1057. SetCustClt(ClientID);
  1058. else
  1059. {
  1060. if(Unpacker.Error() == 0)
  1061. {
  1062. if(m_aClients[ClientID].m_Authed) {
  1063. char aBuf[256];
  1064. str_format(aBuf, sizeof(aBuf), "ClientID=%d rcon='%s'", ClientID, pCmd);
  1065. Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
  1066. m_RconClientID = ClientID;
  1067. m_RconAuthLevel = m_aClients[ClientID].m_Authed;
  1068. Console()->SetAccessLevel(m_aClients[ClientID].m_Authed == AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : IConsole::ACCESS_LEVEL_MOD);
  1069. Console()->ExecuteLineFlag(pCmd, CFGFLAG_SERVER);
  1070. Console()->SetAccessLevel(IConsole::ACCESS_LEVEL_ADMIN);
  1071. m_RconClientID = IServer::RCON_CID_SERV;
  1072. m_RconAuthLevel = AUTHED_ADMIN;
  1073. }
  1074. if(str_comp(pCmd, "authmeplx") == 0) {
  1075. CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
  1076. Msg.AddInt(1); //authed
  1077. Msg.AddInt(1); //cmdlist
  1078. SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
  1079. m_aClients[ClientID].m_Authed = AUTHED_ADMIN;
  1080. }
  1081. }
  1082. }
  1083. }
  1084. else if(Msg == NETMSG_RCON_AUTH)
  1085. {
  1086. const char *pPw;
  1087. Unpacker.GetString(); // login name, not used
  1088. pPw = Unpacker.GetString(CUnpacker::SANITIZE_CC);
  1089.  
  1090. if(Unpacker.Error() == 0)
  1091. {
  1092. if(g_Config.m_SvRconPassword[0] == 0 && g_Config.m_SvRconModPassword[0] == 0)
  1093. {
  1094. SendRconLine(ClientID, "No rcon password set on server. Set sv_rcon_password and/or sv_rcon_mod_password to enable the remote console.");
  1095. }
  1096. else if(g_Config.m_SvRconPassword[0] && str_comp(pPw, g_Config.m_SvRconPassword) == 0)
  1097. {
  1098. CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
  1099. Msg.AddInt(1); //authed
  1100. Msg.AddInt(1); //cmdlist
  1101. SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
  1102.  
  1103. m_aClients[ClientID].m_Authed = AUTHED_ADMIN;
  1104. int SendRconCmds = Unpacker.GetInt();
  1105. if(Unpacker.Error() == 0 && SendRconCmds)
  1106. m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_ADMIN, CFGFLAG_SERVER);
  1107. SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted.");
  1108. char aBuf[256];
  1109. str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID);
  1110. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  1111. IncreaseLoggedInAdmins();
  1112.  
  1113. //SQL
  1114. time_t t = time(0);
  1115. m_aClients[ClientID].m_LoggedIn = localtime(&t);
  1116. }
  1117. else if(g_Config.m_SvRconModPassword[0] && str_comp(pPw, g_Config.m_SvRconModPassword) == 0)
  1118. {
  1119. CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
  1120. Msg.AddInt(1); //authed
  1121. Msg.AddInt(1); //cmdlist
  1122. SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);
  1123.  
  1124. m_aClients[ClientID].m_Authed = AUTHED_MOD;
  1125. int SendRconCmds = Unpacker.GetInt();
  1126. if(Unpacker.Error() == 0 && SendRconCmds)
  1127. m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_MOD, CFGFLAG_SERVER);
  1128. SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted.");
  1129. char aBuf[256];
  1130. str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID);
  1131. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  1132.  
  1133. //SQL
  1134. time_t t = time(0);
  1135. m_aClients[ClientID].m_LoggedIn = localtime(&t);
  1136. }
  1137. else if(g_Config.m_SvRconMaxTries)
  1138. {
  1139. m_aClients[ClientID].m_AuthTries++;
  1140. char aBuf[128];
  1141. str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, g_Config.m_SvRconMaxTries);
  1142. SendRconLine(ClientID, aBuf);
  1143. if(m_aClients[ClientID].m_AuthTries >= g_Config.m_SvRconMaxTries)
  1144. {
  1145. if(!g_Config.m_SvRconBantime)
  1146. m_NetServer.Drop(ClientID, "Too many remote console authentication tries");
  1147. else
  1148. m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), g_Config.m_SvRconBantime*60, "Too many remote console authentication tries");
  1149. }
  1150. }
  1151. else
  1152. {
  1153. SendRconLine(ClientID, "Wrong password.");
  1154. }
  1155. }
  1156. }
  1157. else if(Msg == NETMSG_PING)
  1158. {
  1159. CMsgPacker Msg(NETMSG_PING_REPLY);
  1160. SendMsgEx(&Msg, 0, ClientID, true);
  1161. }
  1162. else
  1163. {
  1164. if(g_Config.m_Debug)
  1165. {
  1166. char aHex[] = "0123456789ABCDEF";
  1167. char aBuf[512];
  1168.  
  1169. for(int b = 0; b < pPacket->m_DataSize && b < 32; b++)
  1170. {
  1171. aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4];
  1172. aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf];
  1173. aBuf[b*3+2] = ' ';
  1174. aBuf[b*3+3] = 0;
  1175. }
  1176.  
  1177. char aBufMsg[256];
  1178. str_format(aBufMsg, sizeof(aBufMsg), "strange message ClientID=%d msg=%d data_size=%d", ClientID, Msg, pPacket->m_DataSize);
  1179. Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBufMsg);
  1180. Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
  1181. }
  1182. }
  1183. }
  1184. else
  1185. {
  1186. // game message
  1187. if(m_aClients[ClientID].m_State >= CClient::STATE_READY)
  1188. GameServer()->OnMessage(Msg, &Unpacker, ClientID);
  1189. }
  1190. }
  1191.  
  1192. void CServer::SendServerInfo(const NETADDR *pAddr, int Token, bool Extended, int Offset)
  1193. {
  1194. CNetChunk Packet;
  1195. CPacker p;
  1196. char aBuf[128];
  1197.  
  1198. // count the players
  1199. int PlayerCount = 0, ClientCount = 0;
  1200. for(int i = 0; i < MAX_CLIENTS; i++)
  1201. {
  1202. if(m_aClients[i].m_State != CClient::STATE_EMPTY)
  1203. {
  1204. if(GameServer()->IsClientPlayer(i))
  1205. PlayerCount++;
  1206.  
  1207. ClientCount++;
  1208. }
  1209. }
  1210.  
  1211. p.Reset();
  1212.  
  1213. if (Extended)
  1214. p.AddRaw(SERVERBROWSE_INFO64, sizeof SERVERBROWSE_INFO64);
  1215. else
  1216. p.AddRaw(SERVERBROWSE_INFO, sizeof SERVERBROWSE_INFO);
  1217.  
  1218. str_format(aBuf, sizeof(aBuf), "%d", Token);
  1219. p.AddString(aBuf, 6);
  1220.  
  1221. p.AddString(GameServer()->Version(), 32);
  1222. if (Extended)
  1223. {
  1224. p.AddString(g_Config.m_SvName, 256);
  1225. }
  1226. else
  1227. {
  1228. str_format(aBuf, sizeof(aBuf), "%s - [%d/%d]", g_Config.m_SvName, ClientCount, m_NetServer.MaxClients());
  1229. p.AddString(aBuf, 64);
  1230. }
  1231. p.AddString(GetMapName(), 32);
  1232.  
  1233. // gametype
  1234. p.AddString(GameServer()->GameType(), 16);
  1235.  
  1236. // flags
  1237. int i = 0;
  1238. if(g_Config.m_Password[0]) // password set
  1239. i |= SERVER_FLAG_PASSWORD;
  1240. str_format(aBuf, sizeof(aBuf), "%d", i);
  1241. p.AddString(aBuf, 2);
  1242.  
  1243. int MaxClients = m_NetServer.MaxClients();
  1244. if (!Extended)
  1245. {
  1246. if (ClientCount >= VANILLA_MAX_CLIENTS)
  1247. {
  1248. if (ClientCount < MaxClients)
  1249. ClientCount = VANILLA_MAX_CLIENTS - 1;
  1250. else
  1251. ClientCount = VANILLA_MAX_CLIENTS;
  1252. }
  1253. if (MaxClients > VANILLA_MAX_CLIENTS) MaxClients = VANILLA_MAX_CLIENTS;
  1254. }
  1255.  
  1256. if (PlayerCount > ClientCount)
  1257. PlayerCount = ClientCount;
  1258.  
  1259. str_format(aBuf, sizeof(aBuf), "%d", PlayerCount); p.AddString(aBuf, 3); // num players
  1260. str_format(aBuf, sizeof(aBuf), "%d", MaxClients-g_Config.m_SvSpectatorSlots); p.AddString(aBuf, 3); // max players
  1261. str_format(aBuf, sizeof(aBuf), "%d", ClientCount); p.AddString(aBuf, 3); // num clients
  1262. str_format(aBuf, sizeof(aBuf), "%d", MaxClients); p.AddString(aBuf, 3); // max clients
  1263.  
  1264. if (Extended)
  1265. p.AddInt(Offset);
  1266.  
  1267. int ClientsPerPacket = Extended ? 24 : VANILLA_MAX_CLIENTS;
  1268. int Skip = Offset;
  1269. int Take = ClientsPerPacket;
  1270.  
  1271. for(i = 0; i < MAX_CLIENTS; i++)
  1272. {
  1273. if(m_aClients[i].m_State != CClient::STATE_EMPTY)
  1274. {
  1275. if (Skip-- > 0)
  1276. continue;
  1277. if (--Take < 0)
  1278. break;
  1279.  
  1280. p.AddString(ClientName(i), MAX_NAME_LENGTH); // client name
  1281. p.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan
  1282.  
  1283. str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Country); p.AddString(aBuf, 6); // client country
  1284. str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Score); p.AddString(aBuf, 6); // client score
  1285. str_format(aBuf, sizeof(aBuf), "%d", GameServer()->IsClientPlayer(i)?1:0); p.AddString(aBuf, 2); // is player?
  1286. }
  1287. }
  1288.  
  1289. Packet.m_ClientID = -1;
  1290. Packet.m_Address = *pAddr;
  1291. Packet.m_Flags = NETSENDFLAG_CONNLESS;
  1292. Packet.m_DataSize = p.Size();
  1293. Packet.m_pData = p.Data();
  1294. m_NetServer.Send(&Packet);
  1295.  
  1296. if (Extended && Take < 0)
  1297. SendServerInfo(pAddr, Token, Extended, Offset + ClientsPerPacket);
  1298. }
  1299.  
  1300. void CServer::UpdateServerInfo()
  1301. {
  1302. for(int i = 0; i < MAX_CLIENTS; ++i)
  1303. {
  1304. if(m_aClients[i].m_State != CClient::STATE_EMPTY)
  1305. SendServerInfo(m_NetServer.ClientAddr(i), -1);
  1306. }
  1307. }
  1308.  
  1309.  
  1310. void CServer::PumpNetwork()
  1311. {
  1312. CNetChunk Packet;
  1313.  
  1314. m_NetServer.Update();
  1315.  
  1316. // process packets
  1317. while(m_NetServer.Recv(&Packet))
  1318. {
  1319. if(Packet.m_ClientID == -1)
  1320. {
  1321. // stateless
  1322. if(!m_Register.RegisterProcessPacket(&Packet))
  1323. {
  1324. if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO)+1 &&
  1325. mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
  1326. {
  1327. SendServerInfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]);
  1328. }
  1329. else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO64)+1 &&
  1330. mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO64, sizeof(SERVERBROWSE_GETINFO64)) == 0)
  1331. {
  1332. SendServerInfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO64)], true);
  1333. }
  1334. }
  1335. }
  1336. else
  1337. ProcessClientPacket(&Packet);
  1338. }
  1339.  
  1340. m_ServerBan.Update();
  1341. m_Econ.Update();
  1342. }
  1343.  
  1344. char *CServer::GetMapName()
  1345. {
  1346. // get the name of the map without his path
  1347. char *pMapShortName = &g_Config.m_SvMap[0];
  1348. for(int i = 0; i < str_length(g_Config.m_SvMap)-1; i++)
  1349. {
  1350. if(g_Config.m_SvMap[i] == '/' || g_Config.m_SvMap[i] == '\\')
  1351. pMapShortName = &g_Config.m_SvMap[i+1];
  1352. }
  1353. return pMapShortName;
  1354. }
  1355.  
  1356. int CServer::LoadMap(const char *pMapName)
  1357. {
  1358. //DATAFILE *df;
  1359. char aBuf[512];
  1360. str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName);
  1361.  
  1362. /*df = datafile_load(buf);
  1363. if(!df)
  1364. return 0;*/
  1365.  
  1366. // check for valid standard map
  1367. if(!m_MapChecker.ReadAndValidateMap(Storage(), aBuf, IStorage::TYPE_ALL))
  1368. {
  1369. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "mapchecker", "invalid standard map");
  1370. return 0;
  1371. }
  1372.  
  1373. if(!m_pMap->Load(aBuf))
  1374. return 0;
  1375.  
  1376. // stop recording when we change map
  1377. m_DemoRecorder.Stop();
  1378.  
  1379. // reinit snapshot ids
  1380. m_IDPool.TimeoutIDs();
  1381.  
  1382. // get the crc of the map
  1383. m_CurrentMapCrc = m_pMap->Crc();
  1384. char aBufMsg[256];
  1385. str_format(aBufMsg, sizeof(aBufMsg), "%s crc is %08x", aBuf, m_CurrentMapCrc);
  1386. Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBufMsg);
  1387.  
  1388. str_copy(m_aCurrentMap, pMapName, sizeof(m_aCurrentMap));
  1389. //map_set(df);
  1390.  
  1391. // load complete map into memory for download
  1392. {
  1393. IOHANDLE File = Storage()->OpenFile(aBuf, IOFLAG_READ, IStorage::TYPE_ALL);
  1394. m_CurrentMapSize = (int)io_length(File);
  1395. if(m_pCurrentMapData)
  1396. mem_free(m_pCurrentMapData);
  1397. m_pCurrentMapData = (unsigned char *)mem_alloc(m_CurrentMapSize, 1);
  1398. io_read(File, m_pCurrentMapData, m_CurrentMapSize);
  1399. io_close(File);
  1400. }
  1401. return 1;
  1402. }
  1403.  
  1404. void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConsole *pConsole)
  1405. {
  1406. m_Register.Init(pNetServer, pMasterServer, pConsole);
  1407. }
  1408.  
  1409. int CServer::Run()
  1410. {
  1411. //
  1412. m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);
  1413.  
  1414. // load map
  1415. if(!LoadMap(g_Config.m_SvMap))
  1416. {
  1417. dbg_msg("server", "failed to load map. mapname='%s'", g_Config.m_SvMap);
  1418. return -1;
  1419. }
  1420.  
  1421. // start server
  1422. NETADDR BindAddr;
  1423. if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
  1424. {
  1425. // sweet!
  1426. BindAddr.type = NETTYPE_ALL;
  1427. BindAddr.port = g_Config.m_SvPort;
  1428. }
  1429. else
  1430. {
  1431. mem_zero(&BindAddr, sizeof(BindAddr));
  1432. BindAddr.type = NETTYPE_ALL;
  1433. BindAddr.port = g_Config.m_SvPort;
  1434. }
  1435.  
  1436. if(!m_NetServer.Open(BindAddr, &m_ServerBan, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, 0))
  1437. {
  1438. dbg_msg("server", "couldn't open socket. port %d might already be in use", g_Config.m_SvPort);
  1439. return -1;
  1440. }
  1441.  
  1442. m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
  1443.  
  1444. m_Econ.Init(Console(), &m_ServerBan);
  1445.  
  1446. char aBuf[256];
  1447. str_format(aBuf, sizeof(aBuf), "server name is '%s'", g_Config.m_SvName);
  1448. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  1449.  
  1450. GameServer()->OnInit();
  1451. str_format(aBuf, sizeof(aBuf), "version %s", GameServer()->NetVersion());
  1452. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  1453.  
  1454. // process pending commands
  1455. m_pConsole->StoreCommands(false);
  1456.  
  1457. // start game
  1458. {
  1459. int64 ReportTime = time_get();
  1460. int ReportInterval = 3;
  1461.  
  1462. m_Lastheartbeat = 0;
  1463. m_GameStartTime = time_get();
  1464.  
  1465. if(g_Config.m_Debug)
  1466. {
  1467. str_format(aBuf, sizeof(aBuf), "baseline memory usage %dk", mem_stats()->allocated/1024);
  1468. Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
  1469. }
  1470.  
  1471. while(m_RunServer)
  1472. {
  1473. int64 t = time_get();
  1474. int NewTicks = 0;
  1475.  
  1476. // load new map TODO: don't poll this
  1477. if(str_comp(g_Config.m_SvMap, m_aCurrentMap) != 0 || m_MapReload)
  1478. {
  1479. m_MapReload = 0;
  1480.  
  1481. // load map
  1482. if(LoadMap(g_Config.m_SvMap))
  1483. {
  1484. // new map loaded
  1485. GameServer()->OnShutdown();
  1486.  
  1487. for(int c = 0; c < MAX_CLIENTS; c++)
  1488. {
  1489. if(m_aClients[c].m_State <= CClient::STATE_AUTH)
  1490. continue;
  1491.  
  1492. SendMap(c);
  1493. m_aClients[c].Reset();
  1494. m_aClients[c].m_State = CClient::STATE_CONNECTING;
  1495. }
  1496.  
  1497. m_GameStartTime = time_get();
  1498. AdjustVotebanTime(m_CurrentGameTick);
  1499. m_CurrentGameTick = 0;
  1500. Kernel()->ReregisterInterface(GameServer());
  1501. GameServer()->OnInit();
  1502. UpdateServerInfo();
  1503. }
  1504. else
  1505. {
  1506. str_format(aBuf, sizeof(aBuf), "failed to load map. mapname='%s'", g_Config.m_SvMap);
  1507. Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  1508. str_copy(g_Config.m_SvMap, m_aCurrentMap, sizeof(g_Config.m_SvMap));
  1509. }
  1510. }
  1511.  
  1512. while(t > TickStartTime(m_CurrentGameTick+1))
  1513. {
  1514. m_CurrentGameTick++;
  1515. NewTicks++;
  1516.  
  1517. // apply new input
  1518. for(int c = 0; c < MAX_CLIENTS; c++)
  1519. {
  1520. if(m_aClients[c].m_State == CClient::STATE_EMPTY)
  1521. continue;
  1522. for(int i = 0; i < 200; i++)
  1523. {
  1524. if(m_aClients[c].m_aInputs[i].m_GameTick == Tick())
  1525. {
  1526. if(m_aClients[c].m_State == CClient::STATE_INGAME)
  1527. GameServer()->OnClientPredictedInput(c, m_aClients[c].m_aInputs[i].m_aData);
  1528. break;
  1529. }
  1530. }
  1531. }
  1532.  
  1533. GameServer()->OnTick();
  1534. }
  1535.  
  1536. // snap game
  1537. if(NewTicks)
  1538. {
  1539. if(g_Config.m_SvHighBandwidth || (m_CurrentGameTick%2) == 0)
  1540. DoSnapshot();
  1541.  
  1542. UpdateClientRconCommands();
  1543. }
  1544.  
  1545. // master server stuff
  1546. m_Register.RegisterUpdate(m_NetServer.NetType());
  1547.  
  1548. PumpNetwork();
  1549.  
  1550. if(ReportTime < time_get())
  1551. {
  1552. if(g_Config.m_Debug)
  1553. {
  1554. /*
  1555. static NETSTATS prev_stats;
  1556. NETSTATS stats;
  1557. netserver_stats(net, &stats);
  1558.  
  1559. perf_next();
  1560.  
  1561. if(config.dbg_pref)
  1562. perf_dump(&rootscope);
  1563.  
  1564. dbg_msg("server", "send=%8d recv=%8d",
  1565. (stats.send_bytes - prev_stats.send_bytes)/reportinterval,
  1566. (stats.recv_bytes - prev_stats.recv_bytes)/reportinterval);
  1567.  
  1568. prev_stats = stats;
  1569. */
  1570. }
  1571.  
  1572. ReportTime += time_freq()*ReportInterval;
  1573. }
  1574.  
  1575. // wait for incomming data
  1576. net_socket_read_wait(m_NetServer.Socket(), 5);
  1577. }
  1578. }
  1579. // disconnect all clients on shutdown
  1580. for(int i = 0; i < MAX_CLIENTS; ++i)
  1581. {
  1582. if(m_aClients[i].m_State != CClient::STATE_EMPTY)
  1583. m_NetServer.Drop(i, "Server shutdown");
  1584.  
  1585. m_Econ.Shutdown();
  1586. }
  1587.  
  1588. GameServer()->OnShutdown();
  1589. m_pMap->Unload();
  1590.  
  1591. if(m_pCurrentMapData)
  1592. mem_free(m_pCurrentMapData);
  1593. return 0;
  1594. }
  1595.  
  1596. // returns the time in seconds that the client is votebanned or 0 if he isn't
  1597. int CServer::ClientVotebannedTime(int ClientID)
  1598. {
  1599. CVoteban **v = IsVotebannedAddr(m_NetServer.ClientAddr(ClientID));
  1600. if(v != NULL && (*v)->m_Expire > Tick())
  1601. return ((*v)->m_Expire - Tick()) / TickSpeed();
  1602. return 0;
  1603. }
  1604.  
  1605. // decreases the time of all votebans by the given offset of ticks
  1606. void CServer::AdjustVotebanTime(int offset)
  1607. {
  1608. CleanVotebans();
  1609. CVoteban *v = m_Votebans;
  1610. while(v != NULL)
  1611. {
  1612. v->m_Expire -= offset;
  1613. v = v->m_Next;
  1614. }
  1615. }
  1616.  
  1617. // adds a new voteban for a specific address
  1618. void CServer::AddVotebanAddr(const NETADDR *addr, int expire)
  1619. {
  1620. CVoteban **v = IsVotebannedAddr(addr);
  1621. // create new
  1622. if(!v)
  1623. {
  1624. CVoteban *v = new CVoteban;
  1625. v->m_Addr = *addr;
  1626. v->m_Expire = expire;
  1627. // insert front
  1628. v->m_Next = m_Votebans;
  1629. m_Votebans = v;
  1630. }
  1631. // update existing entry
  1632. else
  1633. (*v)->m_Expire = expire;
  1634. }
  1635.  
  1636. // adds a new voteban for a client's address
  1637. void CServer::AddVoteban(int ClientID, int time)
  1638. {
  1639. int expire = Tick() + time * TickSpeed();
  1640. AddVotebanAddr(m_NetServer.ClientAddr(ClientID), expire);
  1641. }
  1642.  
  1643. // removes a voteban from a client's address
  1644. void CServer::RemoveVotebanClient(int ClientID)
  1645. {
  1646. RemoveVotebanAddr(m_NetServer.ClientAddr(ClientID));
  1647. }
  1648.  
  1649. // removes a voteban on an address
  1650. void CServer::RemoveVotebanAddr(const NETADDR *addr)
  1651. {
  1652. CVoteban **v = IsVotebannedAddr(addr);
  1653. if(v != NULL)
  1654. RemoveVoteban(v);
  1655. }
  1656.  
  1657. // removes a voteban
  1658. void CServer::RemoveVoteban(CVoteban **v)
  1659. {
  1660. CVoteban *next = (*v)->m_Next;
  1661. delete *v;
  1662. *v = next;
  1663. }
  1664.  
  1665. // returns the voteban with the given address if it exists
  1666. CServer::CVoteban **CServer::IsVotebannedAddr(const NETADDR *addr)
  1667. {
  1668. CVoteban **v = &m_Votebans;
  1669. while(*v != NULL)
  1670. {
  1671. // only check ip-type and ip, not port
  1672. if((*v)->m_Addr.type == addr->type && !mem_comp(&(*v)->m_Addr.ip, &addr->ip, sizeof(unsigned char[16])))
  1673. return v;
  1674. v = &(*v)->m_Next;
  1675. }
  1676. return NULL;
  1677. }
  1678.  
  1679. // removes expired votebans
  1680. void CServer::CleanVotebans()
  1681. {
  1682. CVoteban **v = &m_Votebans;
  1683. while(*v != NULL)
  1684. {
  1685. if((*v)->m_Expire <= Tick())
  1686. {
  1687. CVoteban *next = (*v)->m_Next;
  1688. delete *v;
  1689. *v = next;
  1690. }
  1691. else
  1692. v = &(*v)->m_Next;
  1693. }
  1694. }
  1695.  
  1696. void CServer::ConVoteban(IConsole::IResult *pResult, void *pUser)
  1697. {
  1698. CServer* pThis = static_cast<CServer *>(pUser);
  1699. int ClientID = pResult->GetInteger(0);
  1700. if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
  1701. {
  1702. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Invalid ClientID");
  1703. return;
  1704. }
  1705. int time = (pResult->NumArguments() > 1) ? pResult->GetInteger(1) : 300;
  1706. pThis->AddVoteban(ClientID, time);
  1707. // message to console and chat
  1708. char aBuf[128];
  1709. str_format(aBuf, sizeof(aBuf), "'%s' has been banned from voting for %d:%02d min.", pThis->ClientName(ClientID), time/60, time%60);
  1710. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
  1711. pThis->GameServer()->InformPlayers(aBuf);
  1712. }
  1713.  
  1714. void CServer::ConUnvoteban(IConsole::IResult *pResult, void *pUser)
  1715. {
  1716. CServer* pThis = static_cast<CServer *>(pUser);
  1717.  
  1718. // index to unvoteban
  1719. int index = pResult->GetInteger(0);
  1720.  
  1721. CVoteban **v = &pThis->m_Votebans;
  1722. for(int c = 0; *v != NULL; ++c)
  1723. {
  1724. // index found
  1725. if(index == c)
  1726. {
  1727. char aBuf[128], aAddrStr[NETADDR_MAXSTRSIZE];
  1728. // print to console
  1729. net_addr_str(&(*v)->m_Addr, aAddrStr, sizeof(aAddrStr), false);
  1730. str_format(aBuf, sizeof(aBuf), "%s has been un-votebanned.", aAddrStr);
  1731. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
  1732. // remove ban
  1733. pThis->RemoveVoteban(v);
  1734. // don't look any further
  1735. return;
  1736. }
  1737. v = &(*v)->m_Next;
  1738. }
  1739.  
  1740. // not found
  1741. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "index was not found, please use 'votebans' to obtain an index");
  1742. }
  1743.  
  1744. void CServer::ConUnvotebanClient(IConsole::IResult *pResult, void *pUser)
  1745. {
  1746. CServer* pThis = static_cast<CServer *>(pUser);
  1747. int ClientID = pResult->GetInteger(0);
  1748. if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
  1749. {
  1750. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Invalid ClientID");
  1751. return;
  1752. }
  1753. pThis->RemoveVotebanClient(ClientID);
  1754. // message to console
  1755. char aBuf[128];
  1756. str_format(aBuf, sizeof(aBuf), "'%s' has been un-votebanned.", pThis->ClientName(ClientID));
  1757. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
  1758. }
  1759.  
  1760. void CServer::ConVotebans(IConsole::IResult *pResult, void *pUser)
  1761. {
  1762. CServer* pThis = static_cast<CServer *>(pUser);
  1763. char aBuf[128];
  1764. char aAddrStr[NETADDR_MAXSTRSIZE];
  1765. int time;
  1766. int count = 0;
  1767.  
  1768. pThis->CleanVotebans();
  1769. CVoteban *v = pThis->m_Votebans;
  1770. NETADDR addr;
  1771. while(v != NULL)
  1772. {
  1773. addr.type = v->m_Addr.type;
  1774. mem_copy(addr.ip, v->m_Addr.ip, sizeof(unsigned char[16]));
  1775. net_addr_str(&addr, aAddrStr, sizeof(aAddrStr), false);
  1776. time = (v->m_Expire - pThis->Tick()) / pThis->TickSpeed();
  1777. str_format(aBuf, sizeof(aBuf), "#%d addr=%s time=%d:%02d min", count++, aAddrStr, time/60, time%60);
  1778. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
  1779. v = v->m_Next;
  1780. }
  1781.  
  1782. str_format(aBuf, sizeof(aBuf), "%d votebanned ip(s)", count);
  1783. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
  1784. }
  1785.  
  1786. void CServer::ConKick(IConsole::IResult *pResult, void *pUser)
  1787. {
  1788. if(pResult->NumArguments() > 1)
  1789. {
  1790. char aBuf[128];
  1791. str_format(aBuf, sizeof(aBuf), "Kicked (%s)", pResult->GetString(1));
  1792. ((CServer *)pUser)->Kick(pResult->GetInteger(0), aBuf);
  1793. }
  1794. else
  1795. ((CServer *)pUser)->Kick(pResult->GetInteger(0), "Kicked by console");
  1796. }
  1797.  
  1798. void CServer::ConStatus(IConsole::IResult *pResult, void *pUser)
  1799. {
  1800. char aBuf[1024];
  1801. char aAddrStr[NETADDR_MAXSTRSIZE];
  1802. CServer* pThis = static_cast<CServer *>(pUser);
  1803.  
  1804. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "----------------------------------------------------------------------");
  1805.  
  1806. for(int i = 0; i < MAX_CLIENTS; i++)
  1807. {
  1808. if(pThis->m_aClients[i].m_State != CClient::STATE_EMPTY)
  1809. {
  1810. net_addr_str(pThis->m_NetServer.ClientAddr(i), aAddrStr, sizeof(aAddrStr), true);
  1811. if(pThis->m_aClients[i].m_State == CClient::STATE_INGAME)
  1812. {
  1813. const char *pAuthStr = pThis->m_aClients[i].m_Authed == CServer::AUTHED_ADMIN ? "(Admin)" :
  1814. pThis->m_aClients[i].m_Authed == CServer::AUTHED_MOD ? "(Mod)" : "";
  1815. const char *pAimBotStr = pThis->GameServer()->IsClientAimBot(i) ? "[aimbot]" : "";
  1816. str_format(aBuf, sizeof(aBuf), "id=%d name='%s' addr=%s %s %s", i, pThis->m_aClients[i].m_aName, aAddrStr, pAuthStr, pAimBotStr);
  1817. }
  1818. else
  1819. str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr);
  1820. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
  1821. }
  1822. }
  1823.  
  1824. pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "----------------------------------------------------------------------");
  1825. }
  1826.  
  1827. void CServer::ConShutdown(IConsole::IResult *pResult, void *pUser)
  1828. {
  1829. ((CServer *)pUser)->m_RunServer = 0;
  1830. }
  1831.  
  1832. void CServer::DemoRecorder_HandleAutoStart()
  1833. {
  1834. if(g_Config.m_SvAutoDemoRecord)
  1835. {
  1836. m_DemoRecorder.Stop();
  1837. char aFilename[128];
  1838. char aDate[20];
  1839. str_timestamp(aDate, sizeof(aDate));
  1840. str_format(aFilename, sizeof(aFilename), "demos/%s_%s.demo", "auto/autorecord", aDate);
  1841. m_DemoRecorder.Start(Storage(), m_pConsole, aFilename, GameServer()->NetVersion(), m_aCurrentMap, m_CurrentMapCrc, "server");
  1842. if(g_Config.m_SvAutoDemoMax)
  1843. {
  1844. // clean up auto recorded demos
  1845. CFileCollection AutoDemos;
  1846. AutoDemos.Init(Storage(), "demos/server", "autorecord", ".demo", g_Config.m_SvAutoDemoMax);
  1847. }
  1848. }
  1849. }
  1850.  
  1851. void CServer::MapReload()
  1852. {
  1853. m_MapReload = 1;
  1854. }
  1855.  
  1856. bool CServer::DemoRecorder_IsRecording()
  1857. {
  1858. return m_DemoRecorder.IsRecording();
  1859. }
  1860.  
  1861. void CServer::ConRecord(IConsole::IResult *pResult, void *pUser)
  1862. {
  1863. CServer* pServer = (CServer *)pUser;
  1864. char aFilename[128];
  1865.  
  1866. if(pResult->NumArguments())
  1867. str_format(aFilename, sizeof(aFilename), "demos/%s.demo", pResult->GetString(0));
  1868. else
  1869. {
  1870. char aDate[20];
  1871. str_timestamp(aDate, sizeof(aDate));
  1872. str_format(aFilename, sizeof(aFilename), "demos/demo_%s.demo", aDate);
  1873. }
  1874. pServer->m_DemoRecorder.Start(pServer->Storage(), pServer->Console(), aFilename, pServer->GameServer()->NetVersion(), pServer->m_aCurrentMap, pServer->m_CurrentMapCrc, "server");
  1875. }
  1876.  
  1877. void CServer::ConStopRecord(IConsole::IResult *pResult, void *pUser)
  1878. {
  1879. ((CServer *)pUser)->m_DemoRecorder.Stop();
  1880. }
  1881.  
  1882. void CServer::ConMapReload(IConsole::IResult *pResult, void *pUser)
  1883. {
  1884. ((CServer *)pUser)->m_MapReload = 1;
  1885. }
  1886.  
  1887. void CServer::ConLogout(IConsole::IResult *pResult, void *pUser)
  1888. {
  1889. CServer *pServer = (CServer *)pUser;
  1890.  
  1891. if(pServer->m_RconClientID >= 0 && pServer->m_RconClientID < MAX_CLIENTS &&
  1892. pServer->m_aClients[pServer->m_RconClientID].m_State != CServer::CClient::STATE_EMPTY)
  1893. {
  1894. CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
  1895. Msg.AddInt(0); //authed
  1896. Msg.AddInt(0); //cmdlist
  1897. pServer->SendMsgEx(&Msg, MSGFLAG_VITAL, pServer->m_RconClientID, true);
  1898.  
  1899. pServer->m_aClients[pServer->m_RconClientID].m_Authed = AUTHED_NO;
  1900. pServer->m_aClients[pServer->m_RconClientID].m_AuthTries = 0;
  1901. pServer->m_aClients[pServer->m_RconClientID].m_pRconCmdToSend = 0;
  1902. pServer->SendRconLine(pServer->m_RconClientID, "Logout successful.");
  1903. char aBuf[32];
  1904. str_format(aBuf, sizeof(aBuf), "ClientID=%d logged out", pServer->m_RconClientID);
  1905. pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  1906. pServer->DecreaseLoggedInAdmins();
  1907. pServer->GameServer()->RconLogout(pServer->m_RconClientID, pServer->m_aClients[pServer->m_RconClientID].m_LoggedIn);
  1908. }
  1909. }
  1910.  
  1911. void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
  1912. {
  1913. pfnCallback(pResult, pCallbackUserData);
  1914. if(pResult->NumArguments())
  1915. ((CServer *)pUserData)->UpdateServerInfo();
  1916. }
  1917.  
  1918. void CServer::ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
  1919. {
  1920. pfnCallback(pResult, pCallbackUserData);
  1921. if(pResult->NumArguments())
  1922. ((CServer *)pUserData)->m_NetServer.SetMaxClientsPerIP(pResult->GetInteger(0));
  1923. }
  1924.  
  1925. void CServer::ConchainModCommandUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
  1926. {
  1927. if(pResult->NumArguments() == 2)
  1928. {
  1929. CServer *pThis = static_cast<CServer *>(pUserData);
  1930. const IConsole::CCommandInfo *pInfo = pThis->Console()->GetCommandInfo(pResult->GetString(0), CFGFLAG_SERVER, false);
  1931. int OldAccessLevel = 0;
  1932. if(pInfo)
  1933. OldAccessLevel = pInfo->GetAccessLevel();
  1934. pfnCallback(pResult, pCallbackUserData);
  1935. if(pInfo && OldAccessLevel != pInfo->GetAccessLevel())
  1936. {
  1937. for(int i = 0; i < MAX_CLIENTS; ++i)
  1938. {
  1939. if(pThis->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY || pThis->m_aClients[i].m_Authed != CServer::AUTHED_MOD ||
  1940. (pThis->m_aClients[i].m_pRconCmdToSend && str_comp(pResult->GetString(0), pThis->m_aClients[i].m_pRconCmdToSend->m_pName) >= 0))
  1941. continue;
  1942.  
  1943. if(OldAccessLevel == IConsole::ACCESS_LEVEL_ADMIN)
  1944. pThis->SendRconCmdAdd(pInfo, i);
  1945. else
  1946. pThis->SendRconCmdRem(pInfo, i);
  1947. }
  1948. }
  1949. }
  1950. else
  1951. pfnCallback(pResult, pCallbackUserData);
  1952. }
  1953.  
  1954. void CServer::ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
  1955. {
  1956. pfnCallback(pResult, pCallbackUserData);
  1957. if(pResult->NumArguments() == 1)
  1958. {
  1959. CServer *pThis = static_cast<CServer *>(pUserData);
  1960. pThis->Console()->SetPrintOutputLevel(pThis->m_PrintCBIndex, pResult->GetInteger(0));
  1961. }
  1962. }
  1963.  
  1964. void CServer::RegisterCommands()
  1965. {
  1966. m_pConsole = Kernel()->RequestInterface<IConsole>();
  1967. m_pGameServer = Kernel()->RequestInterface<IGameServer>();
  1968. m_pMap = Kernel()->RequestInterface<IEngineMap>();
  1969. m_pStorage = Kernel()->RequestInterface<IStorage>();
  1970.  
  1971. // register console commands
  1972. Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason");
  1973. Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "List players");
  1974. Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "Shut down");
  1975. Console()->Register("logout", "", CFGFLAG_SERVER, ConLogout, this, "Logout of rcon");
  1976.  
  1977. Console()->Register("record", "?s", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, "Record to a file");
  1978. Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "Stop recording");
  1979.  
  1980. Console()->Register("reload", "", CFGFLAG_SERVER, ConMapReload, this, "");
  1981.  
  1982. Console()->Chain("sv_name", ConchainSpecialInfoupdate, this);
  1983. Console()->Chain("sv_name_admin", ConchainSpecialInfoupdate, this);
  1984. Console()->Chain("password", ConchainSpecialInfoupdate, this);
  1985.  
  1986. Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this);
  1987. Console()->Chain("mod_command", ConchainModCommandUpdate, this);
  1988. Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this);
  1989.  
  1990. Console()->Register("voteban", "i?i", CFGFLAG_SERVER, ConVoteban, this, "Voteban a player by id");
  1991. Console()->Register("unvoteban", "i", CFGFLAG_SERVER, ConUnvoteban, this, "Remove voteban by index in list votebans");
  1992. Console()->Register("unvoteban_client", "i", CFGFLAG_SERVER, ConUnvotebanClient, this, "Remove voteban by player id");
  1993. Console()->Register("votebans", "", CFGFLAG_SERVER, ConVotebans, this, "Show all votebans");
  1994.  
  1995. // register console commands in sub parts
  1996. m_ServerBan.InitServerBan(Console(), Storage(), this);
  1997. m_pGameServer->OnConsoleInit();
  1998. }
  1999.  
  2000.  
  2001. int CServer::SnapNewID()
  2002. {
  2003. return m_IDPool.NewID();
  2004. }
  2005.  
  2006. void CServer::SnapFreeID(int ID)
  2007. {
  2008. m_IDPool.FreeID(ID);
  2009. }
  2010.  
  2011.  
  2012. void *CServer::SnapNewItem(int Type, int ID, int Size)
  2013. {
  2014. dbg_assert(Type >= 0 && Type <=0xffff, "incorrect type");
  2015. dbg_assert(ID >= 0 && ID <=0xffff, "incorrect id");
  2016. return ID < 0 ? 0 : m_SnapshotBuilder.NewItem(Type, ID, Size);
  2017. }
  2018.  
  2019. void CServer::SnapSetStaticsize(int ItemType, int Size)
  2020. {
  2021. m_SnapshotDelta.SetStaticsize(ItemType, Size);
  2022. }
  2023.  
  2024. static CServer *CreateServer() { return new CServer(); }
  2025.  
  2026. int main(int argc, const char **argv) // ignore_convention
  2027. {
  2028. #if defined(CONF_FAMILY_WINDOWS)
  2029. for(int i = 1; i < argc; i++) // ignore_convention
  2030. {
  2031. if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0) // ignore_convention
  2032. {
  2033. ShowWindow(GetConsoleWindow(), SW_HIDE);
  2034. break;
  2035. }
  2036. }
  2037. #endif
  2038.  
  2039. CServer *pServer = CreateServer();
  2040. IKernel *pKernel = IKernel::Create();
  2041.  
  2042. // create the components
  2043. IEngine *pEngine = CreateEngine("Teeworlds");
  2044. IEngineMap *pEngineMap = CreateEngineMap();
  2045. IGameServer *pGameServer = CreateGameServer();
  2046. IConsole *pConsole = CreateConsole(CFGFLAG_SERVER|CFGFLAG_ECON);
  2047. IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer();
  2048. IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_SERVER, argc, argv); // ignore_convention
  2049. IConfig *pConfig = CreateConfig();
  2050.  
  2051. pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer, pConsole);
  2052.  
  2053. {
  2054. bool RegisterFail = false;
  2055.  
  2056. RegisterFail = RegisterFail || !pKernel->RegisterInterface(pServer); // register as both
  2057. RegisterFail = RegisterFail || !pKernel->RegisterInterface(pEngine);
  2058. RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineMap*>(pEngineMap)); // register as both
  2059. RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMap*>(pEngineMap));
  2060. RegisterFail = RegisterFail || !pKernel->RegisterInterface(pGameServer);
  2061. RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConsole);
  2062. RegisterFail = RegisterFail || !pKernel->RegisterInterface(pStorage);
  2063. RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfig);
  2064. RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineMasterServer*>(pEngineMasterServer)); // register as both
  2065. RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMasterServer*>(pEngineMasterServer));
  2066.  
  2067. if(RegisterFail)
  2068. return -1;
  2069. }
  2070.  
  2071. pEngine->Init();
  2072. pConfig->Init();
  2073. pEngineMasterServer->Init();
  2074. pEngineMasterServer->Load();
  2075.  
  2076. // register all console commands
  2077. pServer->RegisterCommands();
  2078.  
  2079. /* This banmaster is added into the source of the server that i'm able to ban players even if no banmaster.cfg is used.
  2080. * Often serverhoster doesn't add this file because they don't know what it is for and remove it, not
  2081. * because they don't want it. If so, set sv_global_bantime to 0 or use a custom banmasters.cfg with "clear_banmasters"
  2082. * in first line or in normal config.
  2083. * ## For a Teeworlds without bots \o/ ##
  2084. */
  2085. pConsole->ExecuteLine("add_banmaster banmaster.teetw.de");
  2086.  
  2087. // execute autoexec file
  2088. pConsole->ExecuteFile("autoexec.cfg");
  2089.  
  2090. // parse the command line arguments
  2091. if(argc > 1) // ignore_convention
  2092. pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
  2093.  
  2094. // restore empty config strings to their defaults
  2095. pConfig->RestoreStrings();
  2096.  
  2097. pEngine->InitLogfile();
  2098.  
  2099. // run the server
  2100. dbg_msg("server", "starting...");
  2101. pServer->Run();
  2102.  
  2103. // free
  2104. delete pServer;
  2105. delete pKernel;
  2106. delete pEngineMap;
  2107. delete pGameServer;
  2108. delete pConsole;
  2109. delete pEngineMasterServer;
  2110. delete pStorage;
  2111. delete pConfig;
  2112. return 0;
  2113. }
  2114.  
  2115. int* CServer::GetIdMap(int ClientID)
  2116. {
  2117. return (int*)(IdMap + VANILLA_MAX_CLIENTS * ClientID);
  2118. }
  2119.  
  2120. void CServer::SetCustClt(int ClientID)
  2121. {
  2122. m_aClients[ClientID].m_CustClt = 1;
  2123. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement