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 
142  C4Network2ResChunkData &operator =(const C4Network2ResChunkData &Data2);
143 protected:
144  int32_t iChunkCnt{0}, iPresentChunkCnt{0};
145 
146  // present chunk ranges
147  struct ChunkRange { int32_t Start, Length; ChunkRange *Next; };
148  ChunkRange *pChunkRanges{nullptr};
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
215  char szFile[_MAX_PATH + 1], szStandalone[_MAX_PATH + 1];
216  bool fTempFile, fStandaloneFailed;
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;
227  struct ClientChunks { C4Network2ResChunkData Chunks; int32_t ClientID; ClientChunks *Next; }
228  *pCChunks;
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();
267  C4Network2Res::Ref Derive();
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
278  void OnDiscover(C4Network2IOConnection *pBy);
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:
309  ~C4Network2ResChunk() override;
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 
336  C4Network2Res *pFirst{nullptr};
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
C4Network2ResType
Definition: C4Network2Res.h:40
const int32_t C4NetResMaxLoad
Definition: C4Network2Res.h:33
#define SHA_DIGEST_LENGTH
Definition: SHA1.h:42
int32_t iLastReqTime
Definition: StdBuf.h:29
bool isDirty() const
Definition: StdAdaptors.h:780
StdCopyStrBuf FileName
Definition: C4Network2Res.h:76
bool isTempFile() const
uint32_t iContentsCRC
Definition: C4Network2Res.h:78
C4Network2ResType getType() const
Ref(C4Network2Res *pRes)
const int32_t C4NetResStatusInterval
Definition: C4Network2Res.h:32
int32_t getDisID(int32_t i) const
int32_t getReqID() const
const uint8_t * getFileSHA() const
Definition: C4Network2Res.h:93
C4Network2ResType getType() const
Definition: C4Network2Res.h:84
uint8_t BYTE
uint32_t getContentsCRC() const
Definition: C4Network2Res.h:91
C4Network2ResChunkData Chunks
void SetFileSHA(BYTE *pSHA)
bool isComplete() const
uint32_t getChunkCnt() const
Definition: C4Network2Res.h:96
#define _MAX_PATH
CStdCSec ResListAddCSec
bool isRemoved() const
const C4Network2ResChunkData & getChunks() const
Ref(const Ref &rCopy)
time_t iDiscoverStartTime
uint32_t getChunkSize() const
Definition: C4Network2Res.h:95
int32_t getResID() const
const int32_t C4NetResIDAnonymous
Definition: C4Network2Res.h:38
const int32_t C4NetResDiscoverTimeout
Definition: C4Network2Res.h:30
bool hasFileSHA() const
Definition: C4Network2Res.h:92
const C4Network2ResCore & getCore() const
int32_t getChunkCnt() const
C4Network2IO * getIOClass()
bool isNull() const
Definition: C4Network2Res.h:85
int32_t getPresentPercent() const
C4Network2ResCore Core
void Set(C4Network2ResType eType, int32_t iResID, const char *strFileName, uint32_t iContentsCRC)
void CompileFunc(StdCompiler *pComp) override
uint32_t getChunkNr() const
uint32_t getFileSize() const
Definition: C4Network2Res.h:89
void OnClientConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn)
bool isAnonymous() const
int32_t iLoadCnt
uint8_t FileSHA[SHA_DIGEST_LENGTH]
Definition: C4Network2Res.h:80
int32_t getPresentChunkCnt() const
void SetDerived(int32_t inDerID)
int32_t getLastReqTime() const
const char * getData() const
Definition: StdBuf.h:442
int32_t getResID() const
int32_t getChunk() const
void SetLoadable(uint32_t iSize, uint32_t iCRC)
C4Network2ResLoad * pNext
int32_t getResClient() const
C4Network2ResType eType
Definition: C4Network2Res.h:74
C4Network2ResList * pParent
const int32_t C4NetResDeleteTime
Definition: C4Network2Res.h:35
int32_t getResID() const
bool isLoadable() const
Definition: C4Network2Res.h:88
C4Network2ResLoad * Next() const
int32_t getReqChunk() const
uint32_t getFileCRC() const
Definition: C4Network2Res.h:90
const int32_t C4NetResLoadTimeout
Definition: C4Network2Res.h:34
C4Network2ResChunkData Chunks
int32_t getID() const
Definition: C4Network2Res.h:86
const int32_t C4NetResDiscoverInterval
Definition: C4Network2Res.h:31
C4Network2ResLoad * pLoads
void SetID(int32_t inID)
Definition: C4Network2Res.h:99
const char * getFile() const
std::atomic_long iRefCnt
CStdCSecEx ResListCSec
int32_t getDisIDCnt() const
CStdCSec * getFileCSec()
CStdCSec FileCSec
void Set(C4Network2Res *pnRes)
int32_t getDerID() const
Definition: C4Network2Res.h:87
bool isLoading() const
C4Network2Res * pNext
int32_t getByClient() const
const int32_t C4NetResMaxBigicon
Definition: C4Network2Res.h:36
const StdEnumEntry< C4Network2ResType > C4Network2ResType_EnumMap[]
Definition: C4Network2Res.h:51
void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn)
Definition: C4Network2.cpp:878
int32_t getPresentPercent() const
int iSize
Definition: TstC4NetIO.cpp:32
const uint32_t C4NetResChunkSize
Definition: C4Network2Res.h:28
const char * getFileName() const
Definition: C4Network2Res.h:94