OpenClonk
C4Network2Res.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2013-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // network resource: data needed for the game (scenario, plr files, definitions...)
17 
18 #ifndef INC_C4Network2Res
19 #define INC_C4Network2Res
20 
21 #include "lib/StdAdaptors.h"
22 #include "platform/StdSync.h"
23 
24 #include "lib/SHA1.h"
25 
26 #include <atomic>
27 
28 const uint32_t C4NetResChunkSize = 10U * 1024U;
29 
30 const int32_t C4NetResDiscoverTimeout = 10, // (s)
34  C4NetResLoadTimeout = 60, // (s)
35  C4NetResDeleteTime = 60, // (s)
36  C4NetResMaxBigicon = 20; // maximum size, in KB, of bigicon
37 
38 const int32_t C4NetResIDAnonymous = -2;
39 
41 {
49 };
50 
52 {
53  { "Scenario", NRT_Scenario },
54  { "Dynamic", NRT_Dynamic },
55  { "Player", NRT_Player },
56  { "Definitions", NRT_Definitions },
57  { "System", NRT_System },
58  { "Material", NRT_Material },
59 };
60 
61 // damn circular dependencies
62 #include "network/C4PacketBase.h"
63 #include "network/C4Network2IO.h"
64 class C4Network2ResList;
65 class C4Network2ResChunk;
66 
67 // classes
69 {
70 public:
72 
73 protected:
75  int32_t iID{-1}, iDerID{-1};
77  bool fLoadable{false};
79  uint8_t fHasFileSHA{false};
81  uint32_t iChunkSize;
82 
83 public:
84  C4Network2ResType getType() const { return eType; }
85  bool isNull() const { return eType == NRT_Null; }
86  int32_t getID() const { return iID; }
87  int32_t getDerID() const { return iDerID; }
88  bool isLoadable() const { return fLoadable; }
89  uint32_t getFileSize() const { return iFileSize; }
90  uint32_t getFileCRC() const { return iFileCRC; }
91  uint32_t getContentsCRC()const { return iContentsCRC; }
92  bool hasFileSHA() const { return !!fHasFileSHA; }
93  const uint8_t*getFileSHA() const { return FileSHA; }
94  const char * getFileName() const { return FileName.getData(); }
95  uint32_t getChunkSize() const { return iChunkSize; }
96  uint32_t getChunkCnt() const { return iFileSize && iChunkSize ? (iFileSize - 1) / iChunkSize + 1 : 0; }
97 
98  void Set(C4Network2ResType eType, int32_t iResID, const char *strFileName, uint32_t iContentsCRC);
99  void SetID(int32_t inID) { iID = inID; }
100  void SetDerived(int32_t inDerID) { iDerID = inDerID; }
101  void SetLoadable(uint32_t iSize, uint32_t iCRC);
102  void SetFileSHA(BYTE *pSHA) { memcpy(FileSHA, pSHA, SHA_DIGEST_LENGTH); fHasFileSHA = true; }
103  void Clear();
104 
105  void CompileFunc(StdCompiler *pComp) override;
106 
107 };
108 
110 {
111  friend class C4Network2Res;
112 public:
113  C4Network2ResLoad(int32_t iChunk, int32_t iByClient);
115 
116 protected:
117  // chunk download data
118  int32_t iChunk;
119  time_t Timestamp;
120  int32_t iByClient;
121 
122  // list (C4Network2Res)
124 
125 public:
126  int32_t getChunk() const { return iChunk; }
127  int32_t getByClient() const { return iByClient; }
128 
129  C4Network2ResLoad *Next() const { return pNext; }
130 
131  bool CheckTimeout();
132 
133 };
134 
136 {
137 public:
140  ~C4Network2ResChunkData() override;
141 
143 protected:
144  int32_t iChunkCnt{0}, iPresentChunkCnt{0};
145 
146  // present chunk ranges
147  struct ChunkRange { int32_t Start, Length; ChunkRange *Next; };
149  int32_t iChunkRangeCnt{0};
150 
151 public:
152  int32_t getChunkCnt() const { return iChunkCnt; }
153  int32_t getPresentChunkCnt() const { return iPresentChunkCnt; }
154  int32_t getPresentPercent() const { return iPresentChunkCnt * 100 / iChunkCnt; }
155  bool isComplete() const { return iPresentChunkCnt == iChunkCnt; }
156 
157  void SetIncomplete(int32_t iChunkCnt);
158  void SetComplete(int32_t iChunkCnt);
159 
160  void AddChunk(int32_t iChunk);
161  void AddChunkRange(int32_t iStart, int32_t iLength);
162  void Merge(const C4Network2ResChunkData &Data2);
163 
164  void Clear();
165 
166  int32_t GetChunkToRetrieve(const C4Network2ResChunkData &Available, int32_t iLoadingCnt, int32_t *pLoading) const;
167 
168 protected:
169  // helpers
170  bool MergeRanges(ChunkRange *pRange);
171  void GetNegative(C4Network2ResChunkData &Target) const;
172  int32_t getPresentChunk(int32_t iNr) const;
173 
174 public:
175  void CompileFunc(StdCompiler *pComp) override;
176 };
177 
179 {
180  friend class C4Network2ResList;
181  friend class C4Network2ResChunk;
182 public:
183 
184  // helper for reference-holding
185  class Ref
186  {
187  public:
188  Ref() = default;
189  Ref(C4Network2Res *pRes) : pRes(pRes) { if (pRes) pRes->AddRef(); }
190  Ref(const Ref &rCopy) : pRes(rCopy.pRes) { if (pRes) pRes->AddRef(); }
191  ~Ref() { Clear(); }
192  Ref &operator = (C4Network2Res *pnRes) { Set(pnRes); return *this; }
193  Ref &operator = (const Ref &rCopy) { Set(rCopy.pRes); return *this; }
194  private:
195  C4Network2Res *pRes{nullptr};
196  public:
197  operator C4Network2Res *() const { return pRes; }
198  bool operator ! () const { return !pRes; }
199  C4Network2Res * operator ->() const { return pRes; }
200  void Clear() { if (pRes) pRes->DelRef(); pRes = nullptr; }
201  void Set(C4Network2Res *pnRes) { if (pRes == pnRes) return; Clear(); pRes = pnRes; if (pRes) pRes->AddRef(); }
202  };
203 
204  C4Network2Res(C4Network2ResList *pnParent);
205  ~C4Network2Res();
206 
207 protected:
208  // core, chunk data
210  C4Network2ResChunkData Chunks; // (only valid while loading)
211  bool fDirty;
212 
213  // local file data
217 
218  // references
219  std::atomic_long iRefCnt;
220  bool fRemoved;
221 
222  // being load?
223  int32_t iLastReqTime;
224 
225  // loading
226  bool fLoading;
231  int32_t iLoadCnt;
232 
233  // list (C4Network2ResList)
236 
237 public:
238  C4Network2ResType getType() const { return Core.getType(); }
239  const C4Network2ResCore &getCore() const { return Core; }
240  bool isDirty() const { return fDirty; }
241  bool isAnonymous() const { return getResID() == C4NetResIDAnonymous; }
242  int32_t getResID() const { return Core.getID(); }
243  int32_t getResClient() const { return Core.getID() >> 16; }
244  const char *getFile() const { return szFile; }
245  CStdCSec *getFileCSec() { return &FileCSec; }
246  int32_t getLastReqTime()const { return iLastReqTime; }
247  bool isRemoved() const { return fRemoved; }
248  bool isLoading() const { return fLoading; }
249  bool isComplete() const { return !fLoading; }
250  int32_t getPresentPercent() const { return fLoading ? Chunks.getPresentPercent() : 100; }
251  bool isTempFile() const { return fTempFile; }
252 
253  bool SetByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = nullptr, bool fSilent = false);
254  bool SetByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = nullptr, bool fSilent = false);
255  bool SetByCore(const C4Network2ResCore &nCore, bool fSilent = false, const char *szAsFilename = nullptr, int32_t iRecursion=0);
256  bool SetLoad(const C4Network2ResCore &nCore);
257 
258  bool SetDerived(const char *strName, const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iDResID);
259 
260  void ChangeID(int32_t inID);
261 
262  bool IsBinaryCompatible();
263  bool GetStandalone(char *pTo, int32_t iMaxL, bool fSetOfficial, bool fAllowUnloadable = false, bool fSilent = false);
264  bool CalculateSHA();
265 
266  bool SaveBackFile();
268  bool FinishDerive();
269  bool FinishDerive(const C4Network2ResCore &nCore);
270 
271  bool SendStatus(C4Network2IOConnection *pTo = nullptr);
272  bool SendChunk(uint32_t iChunk, int32_t iToClient);
273 
274  // references
275  void AddRef(); void DelRef();
276 
277  // events
279  void OnStatus(const C4Network2ResChunkData &rChunkData, C4Network2IOConnection *pBy);
280  void OnChunk(const C4Network2ResChunk &rChunk);
281  bool DoLoad();
282 
283  bool NeedsDiscover();
284 
285  C4Group *OpenAsGrp() const;
286 
287  void Remove();
288  void Clear();
289 
290 protected:
291  int32_t OpenFileRead(); int32_t OpenFileWrite();
292 
293  void StartNewLoads();
294  bool StartLoad(int32_t iFromClient, const C4Network2ResChunkData &Chunks);
295  void EndLoad();
296  void ClearLoad();
297 
298  void RemoveLoad(C4Network2ResLoad *pLoad);
299  void RemoveCChunks(ClientChunks *pChunks);
300 
301  bool OptimizeStandalone(bool fSilent);
302 
303 };
304 
306 {
307 public:
310 
311 protected:
312  int32_t iResID;
313  uint32_t iChunk;
315 
316 public:
317  int32_t getResID() const { return iResID; }
318  uint32_t getChunkNr() const { return iChunk; }
319 
320  bool Set(C4Network2Res *pRes, uint32_t iChunk);
321  bool AddTo(C4Network2Res *pRes, C4Network2IO *pIO) const;
322 
323  void CompileFunc(StdCompiler *pComp) override;
324 };
325 
326 class C4Network2ResList : protected CStdCSecExCallback // run by network thread
327 {
328  friend class C4Network2Res;
329  friend class C4Network2;
330 public:
332  ~C4Network2ResList() override;
333 
334 protected:
335 
339 
340  int32_t iClientID{-1}, iNextResID;
342 
343  // timings
344  int32_t iLastDiscover{0}, iLastStatus{0};
345 
346  // object used for network i/o
347  C4Network2IO *pIO{nullptr};
348 
349 public:
350 
351  // initialization
352  bool Init(int32_t iClientID, C4Network2IO *pIOClass); // by main thread
353  void SetLocalID(int32_t iClientID); // by both
354 
355 protected:
356  int32_t nextResID(); // by main thread
357 
358  C4Network2Res *getRes(int32_t iResID); // by both
359  C4Network2Res *getRes(const char *szFile, bool fLocalOnly); // by both
360 
361 public:
362  // returns referenced resource ptrs
363  C4Network2Res::Ref getRefRes(int32_t iResID); // by both
364  C4Network2Res::Ref getRefRes(const char *szFile, bool fLocalOnly = false); // by both
365  C4Network2Res::Ref getRefNextRes(int32_t iResID); // by both
366 
367  void Add(C4Network2Res *pRes); // by both
368  C4Network2Res::Ref AddByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID = -1, const char *szResName = nullptr, bool fAllowUnloadable = false); // by both
369  C4Network2Res::Ref AddByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID = -1, const char *szResName = nullptr, bool fAllowUnloadable = false); // by both
370  C4Network2Res::Ref AddByCore(const C4Network2ResCore &Core, bool fLoad = true); // by main thread
371  C4Network2Res::Ref AddLoad(const C4Network2ResCore &Core); // by main thread
372 
373  void RemoveAtClient(int32_t iClientID); // by main thread
374  void Clear(); // by main thread
375 
376  bool SendDiscover(C4Network2IOConnection *pTo = nullptr); // by both
377  void OnClientConnect(C4Network2IOConnection *pConn); // by main thread
378 
379  // interface for C4Network2IO
380  void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn);
381  void OnTimer();
382 
383  // CStdCSecExCallback
384  void OnShareFree(CStdCSecEx *pCSec) override;
385 
386  // for C4Network2Res
387  C4Network2IO *getIOClass() { return pIO; }
388 
389 protected:
390  void OnResComplete(C4Network2Res *pRes);
391 
392  // misc
393  bool CreateNetworkFolder();
394  bool FindTempResFileName(const char *szFilename, char *pTarget);
395 
396 };
397 
398 // * Packets *
399 
401 {
402 public:
404  C4PacketResStatus(int32_t iResID, const C4Network2ResChunkData &nChunks);
405 
406 protected:
407  int32_t iResID;
409 
410 public:
411  int32_t getResID() const { return iResID; }
412  const C4Network2ResChunkData &getChunks() const { return Chunks; }
413 
414  void CompileFunc(StdCompiler *pComp) override;
415 };
416 
418 {
419 public:
421 
422 protected:
423  int32_t iDisIDs[16], iDisIDCnt{0};
424 
425 public:
426  int32_t getDisIDCnt() const { return iDisIDCnt; }
427  int32_t getDisID(int32_t i) const { return iDisIDs[i]; }
428  bool isIDPresent(int32_t iID) const;
429 
430  bool AddDisID(int32_t iID);
431 
432  void CompileFunc(StdCompiler *pComp) override;
433 };
434 
436 {
437 public:
438  C4PacketResRequest(int32_t iID = -1, int32_t iChunk = -1);
439 
440 protected:
441  int32_t iReqID, iReqChunk;
442 
443 public:
444  int32_t getReqID() const { return iReqID; }
445  int32_t getReqChunk() const { return iReqChunk; }
446 
447  void CompileFunc(StdCompiler *pComp) override;
448 };
449 
450 #endif // INC_C4Network2Res
const int32_t C4NetResStatusInterval
Definition: C4Network2Res.h:32
const int32_t C4NetResDiscoverInterval
Definition: C4Network2Res.h:31
const int32_t C4NetResIDAnonymous
Definition: C4Network2Res.h:38
const int32_t C4NetResLoadTimeout
Definition: C4Network2Res.h:34
const int32_t C4NetResMaxLoad
Definition: C4Network2Res.h:33
const int32_t C4NetResDeleteTime
Definition: C4Network2Res.h:35
C4Network2ResType
Definition: C4Network2Res.h:41
@ NRT_Player
Definition: C4Network2Res.h:45
@ NRT_Definitions
Definition: C4Network2Res.h:46
@ NRT_Material
Definition: C4Network2Res.h:48
@ NRT_Dynamic
Definition: C4Network2Res.h:44
@ NRT_Scenario
Definition: C4Network2Res.h:43
@ NRT_Null
Definition: C4Network2Res.h:42
@ NRT_System
Definition: C4Network2Res.h:47
const int32_t C4NetResDiscoverTimeout
Definition: C4Network2Res.h:30
const StdEnumEntry< C4Network2ResType > C4Network2ResType_EnumMap[]
Definition: C4Network2Res.h:51
const uint32_t C4NetResChunkSize
Definition: C4Network2Res.h:28
const int32_t C4NetResMaxBigicon
Definition: C4Network2Res.h:36
#define _MAX_PATH_LEN
uint8_t BYTE
#define SHA_DIGEST_LENGTH
Definition: SHA1.h:42
Definition: StdAdaptors.h:795
int iSize
Definition: TstC4NetIO.cpp:32
void Set(C4Network2Res *pnRes)
bool operator!() const
Ref & operator=(C4Network2Res *pnRes)
C4Network2Res * operator->() const
Ref(C4Network2Res *pRes)
Ref(const Ref &rCopy)
int32_t getPresentChunkCnt() const
void GetNegative(C4Network2ResChunkData &Target) const
int32_t getPresentPercent() const
int32_t GetChunkToRetrieve(const C4Network2ResChunkData &Available, int32_t iLoadingCnt, int32_t *pLoading) const
C4Network2ResChunkData & operator=(const C4Network2ResChunkData &Data2)
ChunkRange * pChunkRanges
void AddChunk(int32_t iChunk)
bool MergeRanges(ChunkRange *pRange)
~C4Network2ResChunkData() override
int32_t getChunkCnt() const
void Merge(const C4Network2ResChunkData &Data2)
void SetIncomplete(int32_t iChunkCnt)
int32_t getPresentChunk(int32_t iNr) const
void AddChunkRange(int32_t iStart, int32_t iLength)
void SetComplete(int32_t iChunkCnt)
void CompileFunc(StdCompiler *pComp) override
void CompileFunc(StdCompiler *pComp) override
~C4Network2ResChunk() override
bool Set(C4Network2Res *pRes, uint32_t iChunk)
uint32_t getChunkNr() const
bool AddTo(C4Network2Res *pRes, C4Network2IO *pIO) const
int32_t getResID() const
void SetDerived(int32_t inDerID)
void SetFileSHA(BYTE *pSHA)
uint32_t getChunkSize() const
Definition: C4Network2Res.h:95
StdCopyStrBuf FileName
Definition: C4Network2Res.h:76
int32_t getDerID() const
Definition: C4Network2Res.h:87
void Set(C4Network2ResType eType, int32_t iResID, const char *strFileName, uint32_t iContentsCRC)
C4Network2ResType eType
Definition: C4Network2Res.h:74
uint8_t FileSHA[SHA_DIGEST_LENGTH]
Definition: C4Network2Res.h:80
uint32_t getContentsCRC() const
Definition: C4Network2Res.h:91
bool isNull() const
Definition: C4Network2Res.h:85
const char * getFileName() const
Definition: C4Network2Res.h:94
void CompileFunc(StdCompiler *pComp) override
void SetLoadable(uint32_t iSize, uint32_t iCRC)
uint32_t getFileCRC() const
Definition: C4Network2Res.h:90
void SetID(int32_t inID)
Definition: C4Network2Res.h:99
bool hasFileSHA() const
Definition: C4Network2Res.h:92
int32_t getID() const
Definition: C4Network2Res.h:86
uint32_t getChunkCnt() const
Definition: C4Network2Res.h:96
uint32_t getFileSize() const
Definition: C4Network2Res.h:89
bool isLoadable() const
Definition: C4Network2Res.h:88
C4Network2ResType getType() const
Definition: C4Network2Res.h:84
const uint8_t * getFileSHA() const
Definition: C4Network2Res.h:93
uint32_t iContentsCRC
Definition: C4Network2Res.h:78
void OnStatus(const C4Network2ResChunkData &rChunkData, C4Network2IOConnection *pBy)
int32_t iLoadCnt
std::atomic_long iRefCnt
CStdCSec FileCSec
time_t iDiscoverStartTime
C4Network2Res(C4Network2ResList *pnParent)
const char * getFile() const
C4Group * OpenAsGrp() const
int32_t getResID() const
int32_t getResClient() const
C4Network2ResList * pParent
const C4Network2ResCore & getCore() const
int32_t getPresentPercent() const
C4Network2ResType getType() const
int32_t getLastReqTime() const
bool isComplete() const
C4Network2ResChunkData Chunks
void RemoveCChunks(ClientChunks *pChunks)
void OnChunk(const C4Network2ResChunk &rChunk)
int32_t OpenFileWrite()
C4Network2Res::Ref Derive()
int32_t OpenFileRead()
bool fStandaloneFailed
C4Network2Res * pNext
bool SetLoad(const C4Network2ResCore &nCore)
C4Network2ResChunkData Chunks
void ChangeID(int32_t inID)
bool isTempFile() const
char szFile[_MAX_PATH_LEN]
bool SetByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName=nullptr, bool fSilent=false)
bool isLoading() const
int32_t iLastReqTime
bool SendChunk(uint32_t iChunk, int32_t iToClient)
bool SetDerived(const char *strName, const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iDResID)
bool isDirty() const
char szStandalone[_MAX_PATH_LEN]
CStdCSec * getFileCSec()
bool isAnonymous() const
bool SaveBackFile()
bool SendStatus(C4Network2IOConnection *pTo=nullptr)
bool IsBinaryCompatible()
struct C4Network2Res::ClientChunks * pCChunks
bool GetStandalone(char *pTo, int32_t iMaxL, bool fSetOfficial, bool fAllowUnloadable=false, bool fSilent=false)
void RemoveLoad(C4Network2ResLoad *pLoad)
bool SetByCore(const C4Network2ResCore &nCore, bool fSilent=false, const char *szAsFilename=nullptr, int32_t iRecursion=0)
bool SetByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName=nullptr, bool fSilent=false)
C4Network2ResLoad * pLoads
C4Network2ResCore Core
bool isRemoved() const
bool OptimizeStandalone(bool fSilent)
void OnDiscover(C4Network2IOConnection *pBy)
bool StartLoad(int32_t iFromClient, const C4Network2ResChunkData &Chunks)
C4Network2IO * pIO
C4Network2Res::Ref getRefRes(int32_t iResID)
void RemoveAtClient(int32_t iClientID)
bool FindTempResFileName(const char *szFilename, char *pTarget)
C4Network2Res::Ref AddByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID=-1, const char *szResName=nullptr, bool fAllowUnloadable=false)
void Add(C4Network2Res *pRes)
void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn)
C4Network2Res::Ref AddByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID=-1, const char *szResName=nullptr, bool fAllowUnloadable=false)
C4Network2Res * getRes(int32_t iResID)
C4Network2Res * pFirst
void OnResComplete(C4Network2Res *pRes)
C4Network2IO * getIOClass()
~C4Network2ResList() override
bool Init(int32_t iClientID, C4Network2IO *pIOClass)
void SetLocalID(int32_t iClientID)
C4Network2Res::Ref AddByCore(const C4Network2ResCore &Core, bool fLoad=true)
void OnClientConnect(C4Network2IOConnection *pConn)
bool SendDiscover(C4Network2IOConnection *pTo=nullptr)
C4Network2Res::Ref getRefNextRes(int32_t iResID)
void OnShareFree(CStdCSecEx *pCSec) override
CStdCSecEx ResListCSec
CStdCSec ResListAddCSec
C4Network2Res::Ref AddLoad(const C4Network2ResCore &Core)
int32_t getChunk() const
int32_t getByClient() const
C4Network2ResLoad * pNext
C4Network2ResLoad * Next() const
C4Network2ResLoad(int32_t iChunk, int32_t iByClient)
bool AddDisID(int32_t iID)
Definition: C4Packet2.cpp:540
int32_t getDisID(int32_t i) const
void CompileFunc(StdCompiler *pComp) override
Definition: C4Packet2.cpp:548
bool isIDPresent(int32_t iID) const
Definition: C4Packet2.cpp:532
int32_t getDisIDCnt() const
C4PacketResRequest(int32_t iID=-1, int32_t iChunk=-1)
Definition: C4Packet2.cpp:556
int32_t getReqChunk() const
void CompileFunc(StdCompiler *pComp) override
Definition: C4Packet2.cpp:562
int32_t getReqID() const
const C4Network2ResChunkData & getChunks() const
void CompileFunc(StdCompiler *pComp) override
Definition: C4Packet2.cpp:522
int32_t getResID() const
C4Network2ResChunkData Chunks
Definition: StdBuf.h:30
const char * getData() const
Definition: StdBuf.h:442