/src/network/C4Network2Res.h

https://bitbucket.org/randrian/openclonk2 · C++ Header · 450 lines · 309 code · 98 blank · 43 comment · 10 complexity · 901bf33f2ab00b8332983c1a5e7a3d30 MD5 · raw file

  1. /*
  2. * OpenClonk, http://www.openclonk.org
  3. *
  4. * Copyright (c) 2004-2007 Peter Wortmann
  5. * Copyright (c) 2005 Sven Eberhardt
  6. * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
  7. *
  8. * Portions might be copyrighted by other authors who have contributed
  9. * to OpenClonk.
  10. *
  11. * Permission to use, copy, modify, and/or distribute this software for any
  12. * purpose with or without fee is hereby granted, provided that the above
  13. * copyright notice and this permission notice appear in all copies.
  14. * See isc_license.txt for full license and disclaimer.
  15. *
  16. * "Clonk" is a registered trademark of Matthes Bender.
  17. * See clonk_trademark_license.txt for full license.
  18. */
  19. // network ressource: data needed for the game (scenario, plr files, definitions...)
  20. #ifndef INC_C4Network2Res
  21. #define INC_C4Network2Res
  22. #include <StdSync.h>
  23. #include <openssl/sha.h>
  24. const uint32_t C4NetResChunkSize = 10U * 1024U;
  25. const int32_t C4NetResDiscoverTimeout = 10, // (s)
  26. C4NetResDiscoverInterval = 1, // (s)
  27. C4NetResStatusInterval = 1, // (s)
  28. C4NetResMaxLoad = 5,
  29. C4NetResLoadTimeout = 60, // (s)
  30. C4NetResDeleteTime = 60, // (s)
  31. C4NetResMaxBigicon = 20; // maximum size, in KB, of bigicon
  32. const int32_t C4NetResIDAnonymous = -2;
  33. enum C4Network2ResType
  34. {
  35. NRT_Null=0,
  36. NRT_Scenario,
  37. NRT_Dynamic,
  38. NRT_Player,
  39. NRT_Definitions,
  40. NRT_System,
  41. NRT_Material,
  42. };
  43. const StdEnumEntry<C4Network2ResType> C4Network2ResType_EnumMap[] =
  44. {
  45. { "Scenario", NRT_Scenario },
  46. { "Dynamic", NRT_Dynamic },
  47. { "Player", NRT_Player },
  48. { "Definitions", NRT_Definitions },
  49. { "System", NRT_System },
  50. { "Material", NRT_Material },
  51. };
  52. // damn circular dependencies
  53. #include "C4PacketBase.h"
  54. #include "C4Network2IO.h"
  55. class C4Network2ResList;
  56. class C4Network2ResChunk;
  57. // classes
  58. class C4Network2ResCore : public C4PacketBase
  59. {
  60. public:
  61. C4Network2ResCore();
  62. protected:
  63. C4Network2ResType eType;
  64. int32_t iID, iDerID;
  65. StdCopyStrBuf FileName, Author;
  66. bool fLoadable;
  67. uint32_t iFileSize, iFileCRC, iContentsCRC;
  68. uint8_t fHasFileSHA;
  69. uint8_t FileSHA[SHA_DIGEST_LENGTH];
  70. uint32_t iChunkSize;
  71. public:
  72. C4Network2ResType getType() const { return eType; }
  73. bool isNull() const { return eType == NRT_Null; }
  74. int32_t getID() const { return iID; }
  75. int32_t getDerID() const { return iDerID; }
  76. bool isLoadable() const { return fLoadable; }
  77. uint32_t getFileSize() const { return iFileSize; }
  78. uint32_t getFileCRC() const { return iFileCRC; }
  79. uint32_t getContentsCRC()const { return iContentsCRC; }
  80. bool hasFileSHA() const { return !!fHasFileSHA; }
  81. const uint8_t*getFileSHA() const { return FileSHA; }
  82. const char * getFileName() const { return FileName.getData(); }
  83. const char * getAuthor() const { return Author.getData(); }
  84. uint32_t getChunkSize() const { return iChunkSize; }
  85. uint32_t getChunkCnt() const { return iFileSize && iChunkSize ? (iFileSize - 1) / iChunkSize + 1 : 0; }
  86. void Set(C4Network2ResType eType, int32_t iResID, const char *strFileName, uint32_t iContentsCRC, const char *szAutor);
  87. void SetID(int32_t inID) { iID = inID; }
  88. void SetDerived(int32_t inDerID) { iDerID = inDerID; }
  89. void SetLoadable(uint32_t iSize, uint32_t iCRC);
  90. void SetFileSHA(BYTE *pSHA) { memcpy(FileSHA, pSHA, SHA_DIGEST_LENGTH); fHasFileSHA = true; }
  91. void Clear();
  92. virtual void CompileFunc(StdCompiler *pComp);
  93. };
  94. class C4Network2ResLoad
  95. {
  96. friend class C4Network2Res;
  97. public:
  98. C4Network2ResLoad(int32_t iChunk, int32_t iByClient);
  99. ~C4Network2ResLoad();
  100. protected:
  101. // chunk download data
  102. int32_t iChunk;
  103. time_t Timestamp;
  104. int32_t iByClient;
  105. // list (C4Network2Res)
  106. C4Network2ResLoad *pNext;
  107. public:
  108. int32_t getChunk() const { return iChunk; }
  109. int32_t getByClient() const { return iByClient; }
  110. C4Network2ResLoad *Next() const { return pNext; }
  111. bool CheckTimeout();
  112. };
  113. class C4Network2ResChunkData : public C4PacketBase
  114. {
  115. public:
  116. C4Network2ResChunkData();
  117. C4Network2ResChunkData(const C4Network2ResChunkData &Data2);
  118. ~C4Network2ResChunkData();
  119. C4Network2ResChunkData &operator =(const C4Network2ResChunkData &Data2);
  120. protected:
  121. int32_t iChunkCnt, iPresentChunkCnt;
  122. // present chunk ranges
  123. struct ChunkRange { int32_t Start, Length; ChunkRange *Next; };
  124. ChunkRange *pChunkRanges;
  125. int32_t iChunkRangeCnt;
  126. public:
  127. int32_t getChunkCnt() const { return iChunkCnt; }
  128. int32_t getPresentChunkCnt() const { return iPresentChunkCnt; }
  129. int32_t getPresentPercent() const { return iPresentChunkCnt * 100 / iChunkCnt; }
  130. bool isComplete() const { return iPresentChunkCnt == iChunkCnt; }
  131. void SetIncomplete(int32_t iChunkCnt);
  132. void SetComplete(int32_t iChunkCnt);
  133. void AddChunk(int32_t iChunk);
  134. void AddChunkRange(int32_t iStart, int32_t iLength);
  135. void Merge(const C4Network2ResChunkData &Data2);
  136. void Clear();
  137. int32_t GetChunkToRetrieve(const C4Network2ResChunkData &Available, int32_t iLoadingCnt, int32_t *pLoading) const;
  138. protected:
  139. // helpers
  140. bool MergeRanges(ChunkRange *pRange);
  141. void GetNegative(C4Network2ResChunkData &Target) const;
  142. int32_t getPresentChunk(int32_t iNr) const;
  143. public:
  144. virtual void CompileFunc(StdCompiler *pComp);
  145. };
  146. class C4Network2Res
  147. {
  148. friend class C4Network2ResList;
  149. friend class C4Network2ResChunk;
  150. public:
  151. // helper for reference-holding
  152. class Ref
  153. {
  154. public:
  155. Ref() : pRes(NULL) { }
  156. Ref(C4Network2Res *pRes) : pRes(pRes) { if(pRes) pRes->AddRef(); }
  157. Ref(const Ref &rCopy) : pRes(rCopy.pRes) { if(pRes) pRes->AddRef(); }
  158. ~Ref() { Clear(); }
  159. Ref &operator = (C4Network2Res *pnRes) { Set(pnRes); return *this; }
  160. Ref &operator = (const Ref &rCopy) { Set(rCopy.pRes); return *this; }
  161. private:
  162. C4Network2Res *pRes;
  163. public:
  164. operator C4Network2Res *() const { return pRes; }
  165. bool operator ! () const { return !pRes; }
  166. C4Network2Res * operator ->() const { return pRes; }
  167. void Clear() { if(pRes) pRes->DelRef(); pRes = NULL; }
  168. void Set(C4Network2Res *pnRes) { if(pRes == pnRes) return; Clear(); pRes = pnRes; if(pRes) pRes->AddRef(); }
  169. };
  170. C4Network2Res(C4Network2ResList *pnParent);
  171. ~C4Network2Res();
  172. protected:
  173. // core, chunk data
  174. C4Network2ResCore Core;
  175. C4Network2ResChunkData Chunks; // (only valid while loading)
  176. bool fDirty;
  177. // local file data
  178. CStdCSec FileCSec;
  179. char szFile[_MAX_PATH + 1], szStandalone[_MAX_PATH + 1];
  180. bool fTempFile, fStandaloneFailed;
  181. // references
  182. long iRefCnt;
  183. bool fRemoved;
  184. // being load?
  185. int32_t iLastReqTime;
  186. // loading
  187. bool fLoading;
  188. struct ClientChunks { C4Network2ResChunkData Chunks; int32_t ClientID; ClientChunks *Next; }
  189. *pCChunks;
  190. time_t iDiscoverStartTime;
  191. C4Network2ResLoad *pLoads;
  192. int32_t iLoadCnt;
  193. // list (C4Network2ResList)
  194. C4Network2Res *pNext;
  195. C4Network2ResList *pParent;
  196. public:
  197. C4Network2ResType getType() const { return Core.getType(); }
  198. const C4Network2ResCore &getCore() const { return Core; }
  199. bool isDirty() const { return fDirty; }
  200. bool isAnonymous() const { return getResID() == C4NetResIDAnonymous; }
  201. int32_t getResID() const { return Core.getID(); }
  202. int32_t getResClient() const { return Core.getID() >> 16; }
  203. const char *getFile() const { return szFile; }
  204. CStdCSec *getFileCSec() { return &FileCSec; }
  205. int32_t getLastReqTime()const { return iLastReqTime; }
  206. bool isRemoved() const { return fRemoved; }
  207. bool isLoading() const { return fLoading; }
  208. bool isComplete() const { return !fLoading; }
  209. int32_t getPresentPercent() const { return fLoading ? Chunks.getPresentPercent() : 100; }
  210. bool SetByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);
  211. bool SetByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);
  212. bool SetByCore(const C4Network2ResCore &nCore, bool fSilent = false, const char *szAsFilename = NULL, int32_t iRecursion=0);
  213. bool SetLoad(const C4Network2ResCore &nCore);
  214. bool SetDerived(const char *strName, const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iDResID);
  215. void ChangeID(int32_t inID);
  216. bool IsBinaryCompatible();
  217. bool GetStandalone(char *pTo, int32_t iMaxL, bool fSetOfficial, bool fAllowUnloadable = false, bool fSilent = false);
  218. bool CalculateSHA();
  219. bool SaveBackFile();
  220. C4Network2Res::Ref Derive();
  221. bool FinishDerive();
  222. bool FinishDerive(const C4Network2ResCore &nCore);
  223. bool SendStatus(C4Network2IOConnection *pTo = NULL);
  224. bool SendChunk(uint32_t iChunk, int32_t iToClient);
  225. // references
  226. void AddRef(); void DelRef();
  227. // events
  228. void OnDiscover(C4Network2IOConnection *pBy);
  229. void OnStatus(const C4Network2ResChunkData &rChunkData, C4Network2IOConnection *pBy);
  230. void OnChunk(const C4Network2ResChunk &rChunk);
  231. bool DoLoad();
  232. bool NeedsDiscover();
  233. C4Group *OpenAsGrp() const;
  234. void Remove();
  235. void Clear();
  236. protected:
  237. int32_t OpenFileRead(); int32_t OpenFileWrite();
  238. void StartNewLoads();
  239. bool StartLoad(int32_t iFromClient, const C4Network2ResChunkData &Chunks);
  240. void EndLoad();
  241. void ClearLoad();
  242. void RemoveLoad(C4Network2ResLoad *pLoad);
  243. void RemoveCChunks(ClientChunks *pChunks);
  244. bool OptimizeStandalone(bool fSilent);
  245. };
  246. class C4Network2ResChunk : public C4PacketBase
  247. {
  248. public:
  249. C4Network2ResChunk();
  250. ~C4Network2ResChunk();
  251. protected:
  252. int32_t iResID;
  253. uint32_t iChunk;
  254. StdBuf Data;
  255. public:
  256. int32_t getResID() const { return iResID; }
  257. uint32_t getChunkNr() const { return iChunk; }
  258. bool Set(C4Network2Res *pRes, uint32_t iChunk);
  259. bool AddTo(C4Network2Res *pRes, C4Network2IO *pIO) const;
  260. virtual void CompileFunc(StdCompiler *pComp);
  261. };
  262. class C4Network2ResList : protected CStdCSecExCallback // run by network thread
  263. {
  264. friend class C4Network2Res;
  265. friend class C4Network2;
  266. public:
  267. C4Network2ResList();
  268. virtual ~C4Network2ResList();
  269. protected:
  270. C4Network2Res *pFirst;
  271. CStdCSecEx ResListCSec;
  272. CStdCSec ResListAddCSec;
  273. int32_t iClientID, iNextResID;
  274. CStdCSec ResIDCSec;
  275. // timings
  276. int32_t iLastDiscover, iLastStatus;
  277. // object used for network i/o
  278. C4Network2IO *pIO;
  279. public:
  280. // initialization
  281. bool Init(int32_t iClientID, C4Network2IO *pIOClass); // by main thread
  282. void SetLocalID(int32_t iClientID); // by both
  283. protected:
  284. int32_t nextResID(); // by main thread
  285. C4Network2Res *getRes(int32_t iResID); // by both
  286. C4Network2Res *getRes(const char *szFile, bool fLocalOnly); // by both
  287. public:
  288. // returns referenced ressource ptrs
  289. C4Network2Res::Ref getRefRes(int32_t iResID); // by both
  290. C4Network2Res::Ref getRefRes(const char *szFile, bool fLocalOnly = false); // by both
  291. C4Network2Res::Ref getRefNextRes(int32_t iResID); // by both
  292. void Add(C4Network2Res *pRes); // by both
  293. C4Network2Res::Ref AddByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID = -1, const char *szResName = NULL, bool fAllowUnloadable = false); // by both
  294. C4Network2Res::Ref AddByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID = -1, const char *szResName = NULL, bool fAllowUnloadable = false); // by both
  295. C4Network2Res::Ref AddByCore(const C4Network2ResCore &Core, bool fLoad = true); // by main thread
  296. C4Network2Res::Ref AddLoad(const C4Network2ResCore &Core); // by main thread
  297. void RemoveAtClient(int32_t iClientID); // by main thread
  298. void Clear(); // by main thread
  299. bool SendDiscover(C4Network2IOConnection *pTo = NULL); // by both
  300. void OnClientConnect(C4Network2IOConnection *pConn); // by main thread
  301. // interface for C4Network2IO
  302. void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn);
  303. void OnTimer();
  304. // CStdCSecExCallback
  305. void OnShareFree(CStdCSecEx *pCSec);
  306. // for C4Network2Res
  307. C4Network2IO *getIOClass() { return pIO; }
  308. protected:
  309. void OnResComplete(C4Network2Res *pRes);
  310. // misc
  311. bool CreateNetworkFolder();
  312. bool FindTempResFileName(const char *szFilename, char *pTarget);
  313. };
  314. // * Packets *
  315. class C4PacketResStatus : public C4PacketBase
  316. {
  317. public:
  318. C4PacketResStatus();
  319. C4PacketResStatus(int32_t iResID, const C4Network2ResChunkData &nChunks);
  320. protected:
  321. int32_t iResID;
  322. C4Network2ResChunkData Chunks;
  323. public:
  324. int32_t getResID() const { return iResID; }
  325. const C4Network2ResChunkData &getChunks() const { return Chunks; }
  326. virtual void CompileFunc(StdCompiler *pComp);
  327. };
  328. class C4PacketResDiscover : public C4PacketBase
  329. {
  330. public:
  331. C4PacketResDiscover();
  332. protected:
  333. int32_t iDisIDs[16], iDisIDCnt;
  334. public:
  335. int32_t getDisIDCnt() const { return iDisIDCnt; }
  336. int32_t getDisID(int32_t i) const { return iDisIDs[i]; }
  337. bool isIDPresent(int32_t iID) const;
  338. bool AddDisID(int32_t iID);
  339. virtual void CompileFunc(StdCompiler *pComp);
  340. };
  341. class C4PacketResRequest : public C4PacketBase
  342. {
  343. public:
  344. C4PacketResRequest(int32_t iID = -1, int32_t iChunk = -1);
  345. protected:
  346. int32_t iReqID, iReqChunk;
  347. public:
  348. int32_t getReqID() const { return iReqID; }
  349. int32_t getReqChunk() const { return iReqChunk; }
  350. virtual void CompileFunc(StdCompiler *pComp);
  351. };
  352. #endif // INC_C4Network2Res