PageRenderTime 45ms CodeModel.GetById 19ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/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
Possible License(s): WTFPL, 0BSD, LGPL-2.1, CC-BY-3.0
  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
 21#ifndef INC_C4Network2Res
 22#define INC_C4Network2Res
 23
 24#include <StdSync.h>
 25
 26#include <openssl/sha.h>
 27
 28const uint32_t C4NetResChunkSize = 10U * 1024U;
 29
 30const int32_t C4NetResDiscoverTimeout = 10, // (s)
 31							C4NetResDiscoverInterval = 1, // (s)
 32							C4NetResStatusInterval = 1, // (s)
 33							C4NetResMaxLoad = 5,
 34							C4NetResLoadTimeout = 60, // (s)
 35							C4NetResDeleteTime = 60, // (s)
 36							C4NetResMaxBigicon = 20; // maximum size, in KB, of bigicon
 37
 38const int32_t C4NetResIDAnonymous = -2;
 39
 40enum C4Network2ResType
 41{
 42	NRT_Null=0,
 43	NRT_Scenario,
 44	NRT_Dynamic,
 45	NRT_Player,
 46	NRT_Definitions,
 47	NRT_System,
 48	NRT_Material,
 49};
 50
 51const StdEnumEntry<C4Network2ResType> C4Network2ResType_EnumMap[] =
 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 "C4PacketBase.h"
 63#include "C4Network2IO.h"
 64class C4Network2ResList;
 65class C4Network2ResChunk;
 66
 67// classes
 68class C4Network2ResCore : public C4PacketBase
 69{
 70public:
 71	C4Network2ResCore();
 72
 73protected:
 74	C4Network2ResType eType;
 75	int32_t iID, iDerID;
 76	StdCopyStrBuf FileName, Author;
 77	bool fLoadable;
 78	uint32_t iFileSize, iFileCRC, iContentsCRC;
 79	uint8_t fHasFileSHA;
 80	uint8_t FileSHA[SHA_DIGEST_LENGTH];
 81	uint32_t iChunkSize;
 82
 83public:
 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	const char *	getAuthor()			const { return Author.getData(); }
 96	uint32_t			getChunkSize()	const { return iChunkSize; }
 97	uint32_t			getChunkCnt()		const { return iFileSize && iChunkSize ? (iFileSize - 1) / iChunkSize + 1 : 0; }
 98
 99	void Set(C4Network2ResType eType, int32_t iResID, const char *strFileName, uint32_t iContentsCRC, const char *szAutor);
100	void SetID(int32_t inID)						{ iID = inID; }
101  void SetDerived(int32_t inDerID)    { iDerID = inDerID; }
102	void SetLoadable(uint32_t iSize, uint32_t iCRC);
103	void SetFileSHA(BYTE *pSHA)					{ memcpy(FileSHA, pSHA, SHA_DIGEST_LENGTH); fHasFileSHA = true; }
104	void Clear();
105
106	virtual void CompileFunc(StdCompiler *pComp);
107
108};
109
110class C4Network2ResLoad
111{
112	friend class C4Network2Res;
113public:
114	C4Network2ResLoad(int32_t iChunk, int32_t iByClient);
115	~C4Network2ResLoad();
116
117protected:
118	// chunk download data
119	int32_t iChunk;
120	time_t Timestamp;
121	int32_t iByClient;
122
123	// list (C4Network2Res)
124	C4Network2ResLoad *pNext;
125
126public:
127	int32_t			getChunk()				const { return iChunk; }
128	int32_t			getByClient()			const { return iByClient; }
129
130	C4Network2ResLoad *Next()	const { return pNext; }
131
132	bool CheckTimeout();
133
134};
135
136class C4Network2ResChunkData : public C4PacketBase
137{
138public:
139	C4Network2ResChunkData();
140	C4Network2ResChunkData(const C4Network2ResChunkData &Data2);
141	~C4Network2ResChunkData();
142
143	C4Network2ResChunkData &operator =(const C4Network2ResChunkData &Data2);
144protected:
145	int32_t iChunkCnt, iPresentChunkCnt;
146
147	// present chunk ranges
148	struct ChunkRange { int32_t Start, Length; ChunkRange *Next; };
149	ChunkRange *pChunkRanges;
150	int32_t iChunkRangeCnt;
151
152public:
153	int32_t getChunkCnt()					const { return iChunkCnt; }
154	int32_t getPresentChunkCnt()	const { return iPresentChunkCnt; }
155	int32_t getPresentPercent()		const { return iPresentChunkCnt * 100 / iChunkCnt; }
156	bool isComplete()					const { return iPresentChunkCnt == iChunkCnt; }
157
158	void SetIncomplete(int32_t iChunkCnt);
159	void SetComplete(int32_t iChunkCnt);
160
161	void AddChunk(int32_t iChunk);
162	void AddChunkRange(int32_t iStart, int32_t iLength);
163	void Merge(const C4Network2ResChunkData &Data2);
164
165	void Clear();
166
167	int32_t GetChunkToRetrieve(const C4Network2ResChunkData &Available, int32_t iLoadingCnt, int32_t *pLoading) const;
168
169protected:
170	// helpers
171	bool MergeRanges(ChunkRange *pRange);
172	void GetNegative(C4Network2ResChunkData &Target) const;
173	int32_t getPresentChunk(int32_t iNr) const;
174
175public:
176	virtual void CompileFunc(StdCompiler *pComp);
177};
178
179class C4Network2Res
180{
181	friend class C4Network2ResList;
182	friend class C4Network2ResChunk;
183public:
184
185	// helper for reference-holding
186	class Ref
187	{
188	public:
189		Ref() : pRes(NULL) { }
190		Ref(C4Network2Res *pRes) : pRes(pRes) { if(pRes) pRes->AddRef(); }
191		Ref(const Ref &rCopy) : pRes(rCopy.pRes) { if(pRes) pRes->AddRef(); }
192		~Ref() { Clear(); }
193		Ref &operator = (C4Network2Res *pnRes) { Set(pnRes); return *this; }
194		Ref &operator = (const Ref &rCopy) { Set(rCopy.pRes); return *this; }
195	private:
196		C4Network2Res *pRes;
197	public:
198		operator C4Network2Res *() const { return pRes; }
199		bool operator ! () const { return !pRes; }
200		C4Network2Res * operator ->() const { return pRes; }
201		void Clear() { if(pRes) pRes->DelRef(); pRes = NULL; }
202		void Set(C4Network2Res *pnRes) { if(pRes == pnRes) return; Clear(); pRes = pnRes; if(pRes) pRes->AddRef(); }
203	};
204
205	C4Network2Res(C4Network2ResList *pnParent);
206	~C4Network2Res();
207
208protected:
209	// core, chunk data
210	C4Network2ResCore Core;
211	C4Network2ResChunkData Chunks; // (only valid while loading)
212	bool fDirty;
213
214	// local file data
215  CStdCSec FileCSec;
216	char szFile[_MAX_PATH + 1], szStandalone[_MAX_PATH + 1];
217	bool fTempFile, fStandaloneFailed;
218
219	// references
220	long iRefCnt;
221	bool fRemoved;
222
223	// being load?
224	int32_t iLastReqTime;
225
226	// loading
227	bool fLoading;
228	struct ClientChunks { C4Network2ResChunkData Chunks; int32_t ClientID; ClientChunks *Next; }
229		*pCChunks;
230	time_t iDiscoverStartTime;
231	C4Network2ResLoad *pLoads;
232	int32_t iLoadCnt;
233
234	// list (C4Network2ResList)
235	C4Network2Res *pNext;
236	C4Network2ResList *pParent;
237
238public:
239	C4Network2ResType getType() const { return Core.getType(); }
240	const C4Network2ResCore &getCore() const { return Core; }
241	bool				isDirty()				const { return fDirty; }
242	bool				isAnonymous()		const { return getResID() == C4NetResIDAnonymous; }
243	int32_t			getResID()			const { return Core.getID(); }
244	int32_t			getResClient()	const { return Core.getID() >> 16; }
245	const char *getFile()				const { return szFile; }
246  CStdCSec   *getFileCSec()         { return &FileCSec; }
247	int32_t			getLastReqTime()const { return iLastReqTime; }
248	bool				isRemoved()			const { return fRemoved; }
249	bool				isLoading()			const { return fLoading; }
250	bool				isComplete()		const { return !fLoading; }
251  int32_t			getPresentPercent() const { return fLoading ? Chunks.getPresentPercent() : 100; }
252
253	bool SetByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);
254	bool SetByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);
255	bool SetByCore(const C4Network2ResCore &nCore, bool fSilent = false, const char *szAsFilename = NULL, 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 = NULL);
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
290protected:
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
305class C4Network2ResChunk : public C4PacketBase
306{
307public:
308	C4Network2ResChunk();
309	~C4Network2ResChunk();
310
311protected:
312	int32_t iResID;
313	uint32_t iChunk;
314	StdBuf Data;
315
316public:
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	virtual void CompileFunc(StdCompiler *pComp);
324};
325
326class C4Network2ResList : protected CStdCSecExCallback // run by network thread
327{
328	friend class C4Network2Res;
329	friend class C4Network2;
330public:
331	C4Network2ResList();
332	virtual ~C4Network2ResList();
333
334protected:
335
336	C4Network2Res *pFirst;
337	CStdCSecEx ResListCSec;
338	CStdCSec ResListAddCSec;
339
340	int32_t iClientID, iNextResID;
341	CStdCSec ResIDCSec;
342
343	// timings
344	int32_t iLastDiscover, iLastStatus;
345
346	// object used for network i/o
347	C4Network2IO *pIO;
348
349public:
350
351	// initialization
352	bool Init(int32_t iClientID, C4Network2IO *pIOClass); // by main thread
353	void SetLocalID(int32_t iClientID); // by both
354
355protected:
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
361public:
362	// returns referenced ressource 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 = NULL, bool fAllowUnloadable = false); // by both
369	C4Network2Res::Ref AddByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID = -1, const char *szResName = NULL, 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 = NULL); // 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);
385
386	// for C4Network2Res
387	C4Network2IO *getIOClass() { return pIO; }
388
389protected:
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
400class C4PacketResStatus : public C4PacketBase
401{
402public:
403	C4PacketResStatus();
404	C4PacketResStatus(int32_t iResID, const C4Network2ResChunkData &nChunks);
405
406protected:
407	int32_t iResID;
408	C4Network2ResChunkData Chunks;
409
410public:
411	int32_t	getResID() const { return iResID; }
412	const C4Network2ResChunkData &getChunks() const { return Chunks; }
413
414	virtual void CompileFunc(StdCompiler *pComp);
415};
416
417class C4PacketResDiscover : public C4PacketBase
418{
419public:
420	C4PacketResDiscover();
421
422protected:
423	int32_t iDisIDs[16], iDisIDCnt;
424
425public:
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	virtual void CompileFunc(StdCompiler *pComp);
433};
434
435class C4PacketResRequest : public C4PacketBase
436{
437public:
438	C4PacketResRequest(int32_t iID = -1, int32_t iChunk = -1);
439
440protected:
441	int32_t iReqID, iReqChunk;
442
443public:
444	int32_t getReqID()		const { return iReqID; }
445	int32_t getReqChunk() const { return iReqChunk; }
446
447	virtual void CompileFunc(StdCompiler *pComp);
448};
449
450#endif // INC_C4Network2Res