/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
- /*
- * OpenClonk, http://www.openclonk.org
- *
- * Copyright (c) 2004-2007 Peter Wortmann
- * Copyright (c) 2005 Sven Eberhardt
- * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
- *
- * Portions might be copyrighted by other authors who have contributed
- * to OpenClonk.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- * See isc_license.txt for full license and disclaimer.
- *
- * "Clonk" is a registered trademark of Matthes Bender.
- * See clonk_trademark_license.txt for full license.
- */
- // network ressource: data needed for the game (scenario, plr files, definitions...)
- #ifndef INC_C4Network2Res
- #define INC_C4Network2Res
- #include <StdSync.h>
- #include <openssl/sha.h>
- const uint32_t C4NetResChunkSize = 10U * 1024U;
- const int32_t C4NetResDiscoverTimeout = 10, // (s)
- C4NetResDiscoverInterval = 1, // (s)
- C4NetResStatusInterval = 1, // (s)
- C4NetResMaxLoad = 5,
- C4NetResLoadTimeout = 60, // (s)
- C4NetResDeleteTime = 60, // (s)
- C4NetResMaxBigicon = 20; // maximum size, in KB, of bigicon
- const int32_t C4NetResIDAnonymous = -2;
- enum C4Network2ResType
- {
- NRT_Null=0,
- NRT_Scenario,
- NRT_Dynamic,
- NRT_Player,
- NRT_Definitions,
- NRT_System,
- NRT_Material,
- };
- const StdEnumEntry<C4Network2ResType> C4Network2ResType_EnumMap[] =
- {
- { "Scenario", NRT_Scenario },
- { "Dynamic", NRT_Dynamic },
- { "Player", NRT_Player },
- { "Definitions", NRT_Definitions },
- { "System", NRT_System },
- { "Material", NRT_Material },
- };
- // damn circular dependencies
- #include "C4PacketBase.h"
- #include "C4Network2IO.h"
- class C4Network2ResList;
- class C4Network2ResChunk;
- // classes
- class C4Network2ResCore : public C4PacketBase
- {
- public:
- C4Network2ResCore();
- protected:
- C4Network2ResType eType;
- int32_t iID, iDerID;
- StdCopyStrBuf FileName, Author;
- bool fLoadable;
- uint32_t iFileSize, iFileCRC, iContentsCRC;
- uint8_t fHasFileSHA;
- uint8_t FileSHA[SHA_DIGEST_LENGTH];
- uint32_t iChunkSize;
- public:
- C4Network2ResType getType() const { return eType; }
- bool isNull() const { return eType == NRT_Null; }
- int32_t getID() const { return iID; }
- int32_t getDerID() const { return iDerID; }
- bool isLoadable() const { return fLoadable; }
- uint32_t getFileSize() const { return iFileSize; }
- uint32_t getFileCRC() const { return iFileCRC; }
- uint32_t getContentsCRC()const { return iContentsCRC; }
- bool hasFileSHA() const { return !!fHasFileSHA; }
- const uint8_t*getFileSHA() const { return FileSHA; }
- const char * getFileName() const { return FileName.getData(); }
- const char * getAuthor() const { return Author.getData(); }
- uint32_t getChunkSize() const { return iChunkSize; }
- uint32_t getChunkCnt() const { return iFileSize && iChunkSize ? (iFileSize - 1) / iChunkSize + 1 : 0; }
- void Set(C4Network2ResType eType, int32_t iResID, const char *strFileName, uint32_t iContentsCRC, const char *szAutor);
- void SetID(int32_t inID) { iID = inID; }
- void SetDerived(int32_t inDerID) { iDerID = inDerID; }
- void SetLoadable(uint32_t iSize, uint32_t iCRC);
- void SetFileSHA(BYTE *pSHA) { memcpy(FileSHA, pSHA, SHA_DIGEST_LENGTH); fHasFileSHA = true; }
- void Clear();
- virtual void CompileFunc(StdCompiler *pComp);
- };
- class C4Network2ResLoad
- {
- friend class C4Network2Res;
- public:
- C4Network2ResLoad(int32_t iChunk, int32_t iByClient);
- ~C4Network2ResLoad();
- protected:
- // chunk download data
- int32_t iChunk;
- time_t Timestamp;
- int32_t iByClient;
- // list (C4Network2Res)
- C4Network2ResLoad *pNext;
- public:
- int32_t getChunk() const { return iChunk; }
- int32_t getByClient() const { return iByClient; }
- C4Network2ResLoad *Next() const { return pNext; }
- bool CheckTimeout();
- };
- class C4Network2ResChunkData : public C4PacketBase
- {
- public:
- C4Network2ResChunkData();
- C4Network2ResChunkData(const C4Network2ResChunkData &Data2);
- ~C4Network2ResChunkData();
- C4Network2ResChunkData &operator =(const C4Network2ResChunkData &Data2);
- protected:
- int32_t iChunkCnt, iPresentChunkCnt;
- // present chunk ranges
- struct ChunkRange { int32_t Start, Length; ChunkRange *Next; };
- ChunkRange *pChunkRanges;
- int32_t iChunkRangeCnt;
- public:
- int32_t getChunkCnt() const { return iChunkCnt; }
- int32_t getPresentChunkCnt() const { return iPresentChunkCnt; }
- int32_t getPresentPercent() const { return iPresentChunkCnt * 100 / iChunkCnt; }
- bool isComplete() const { return iPresentChunkCnt == iChunkCnt; }
- void SetIncomplete(int32_t iChunkCnt);
- void SetComplete(int32_t iChunkCnt);
- void AddChunk(int32_t iChunk);
- void AddChunkRange(int32_t iStart, int32_t iLength);
- void Merge(const C4Network2ResChunkData &Data2);
- void Clear();
- int32_t GetChunkToRetrieve(const C4Network2ResChunkData &Available, int32_t iLoadingCnt, int32_t *pLoading) const;
- protected:
- // helpers
- bool MergeRanges(ChunkRange *pRange);
- void GetNegative(C4Network2ResChunkData &Target) const;
- int32_t getPresentChunk(int32_t iNr) const;
- public:
- virtual void CompileFunc(StdCompiler *pComp);
- };
- class C4Network2Res
- {
- friend class C4Network2ResList;
- friend class C4Network2ResChunk;
- public:
- // helper for reference-holding
- class Ref
- {
- public:
- Ref() : pRes(NULL) { }
- Ref(C4Network2Res *pRes) : pRes(pRes) { if(pRes) pRes->AddRef(); }
- Ref(const Ref &rCopy) : pRes(rCopy.pRes) { if(pRes) pRes->AddRef(); }
- ~Ref() { Clear(); }
- Ref &operator = (C4Network2Res *pnRes) { Set(pnRes); return *this; }
- Ref &operator = (const Ref &rCopy) { Set(rCopy.pRes); return *this; }
- private:
- C4Network2Res *pRes;
- public:
- operator C4Network2Res *() const { return pRes; }
- bool operator ! () const { return !pRes; }
- C4Network2Res * operator ->() const { return pRes; }
- void Clear() { if(pRes) pRes->DelRef(); pRes = NULL; }
- void Set(C4Network2Res *pnRes) { if(pRes == pnRes) return; Clear(); pRes = pnRes; if(pRes) pRes->AddRef(); }
- };
- C4Network2Res(C4Network2ResList *pnParent);
- ~C4Network2Res();
- protected:
- // core, chunk data
- C4Network2ResCore Core;
- C4Network2ResChunkData Chunks; // (only valid while loading)
- bool fDirty;
- // local file data
- CStdCSec FileCSec;
- char szFile[_MAX_PATH + 1], szStandalone[_MAX_PATH + 1];
- bool fTempFile, fStandaloneFailed;
- // references
- long iRefCnt;
- bool fRemoved;
- // being load?
- int32_t iLastReqTime;
- // loading
- bool fLoading;
- struct ClientChunks { C4Network2ResChunkData Chunks; int32_t ClientID; ClientChunks *Next; }
- *pCChunks;
- time_t iDiscoverStartTime;
- C4Network2ResLoad *pLoads;
- int32_t iLoadCnt;
- // list (C4Network2ResList)
- C4Network2Res *pNext;
- C4Network2ResList *pParent;
- public:
- C4Network2ResType getType() const { return Core.getType(); }
- const C4Network2ResCore &getCore() const { return Core; }
- bool isDirty() const { return fDirty; }
- bool isAnonymous() const { return getResID() == C4NetResIDAnonymous; }
- int32_t getResID() const { return Core.getID(); }
- int32_t getResClient() const { return Core.getID() >> 16; }
- const char *getFile() const { return szFile; }
- CStdCSec *getFileCSec() { return &FileCSec; }
- int32_t getLastReqTime()const { return iLastReqTime; }
- bool isRemoved() const { return fRemoved; }
- bool isLoading() const { return fLoading; }
- bool isComplete() const { return !fLoading; }
- int32_t getPresentPercent() const { return fLoading ? Chunks.getPresentPercent() : 100; }
- bool SetByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);
- bool SetByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);
- bool SetByCore(const C4Network2ResCore &nCore, bool fSilent = false, const char *szAsFilename = NULL, int32_t iRecursion=0);
- bool SetLoad(const C4Network2ResCore &nCore);
- bool SetDerived(const char *strName, const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iDResID);
- void ChangeID(int32_t inID);
- bool IsBinaryCompatible();
- bool GetStandalone(char *pTo, int32_t iMaxL, bool fSetOfficial, bool fAllowUnloadable = false, bool fSilent = false);
- bool CalculateSHA();
- bool SaveBackFile();
- C4Network2Res::Ref Derive();
- bool FinishDerive();
- bool FinishDerive(const C4Network2ResCore &nCore);
- bool SendStatus(C4Network2IOConnection *pTo = NULL);
- bool SendChunk(uint32_t iChunk, int32_t iToClient);
- // references
- void AddRef(); void DelRef();
- // events
- void OnDiscover(C4Network2IOConnection *pBy);
- void OnStatus(const C4Network2ResChunkData &rChunkData, C4Network2IOConnection *pBy);
- void OnChunk(const C4Network2ResChunk &rChunk);
- bool DoLoad();
- bool NeedsDiscover();
- C4Group *OpenAsGrp() const;
- void Remove();
- void Clear();
- protected:
- int32_t OpenFileRead(); int32_t OpenFileWrite();
- void StartNewLoads();
- bool StartLoad(int32_t iFromClient, const C4Network2ResChunkData &Chunks);
- void EndLoad();
- void ClearLoad();
- void RemoveLoad(C4Network2ResLoad *pLoad);
- void RemoveCChunks(ClientChunks *pChunks);
- bool OptimizeStandalone(bool fSilent);
- };
- class C4Network2ResChunk : public C4PacketBase
- {
- public:
- C4Network2ResChunk();
- ~C4Network2ResChunk();
- protected:
- int32_t iResID;
- uint32_t iChunk;
- StdBuf Data;
- public:
- int32_t getResID() const { return iResID; }
- uint32_t getChunkNr() const { return iChunk; }
- bool Set(C4Network2Res *pRes, uint32_t iChunk);
- bool AddTo(C4Network2Res *pRes, C4Network2IO *pIO) const;
- virtual void CompileFunc(StdCompiler *pComp);
- };
- class C4Network2ResList : protected CStdCSecExCallback // run by network thread
- {
- friend class C4Network2Res;
- friend class C4Network2;
- public:
- C4Network2ResList();
- virtual ~C4Network2ResList();
- protected:
- C4Network2Res *pFirst;
- CStdCSecEx ResListCSec;
- CStdCSec ResListAddCSec;
- int32_t iClientID, iNextResID;
- CStdCSec ResIDCSec;
- // timings
- int32_t iLastDiscover, iLastStatus;
- // object used for network i/o
- C4Network2IO *pIO;
- public:
- // initialization
- bool Init(int32_t iClientID, C4Network2IO *pIOClass); // by main thread
- void SetLocalID(int32_t iClientID); // by both
- protected:
- int32_t nextResID(); // by main thread
- C4Network2Res *getRes(int32_t iResID); // by both
- C4Network2Res *getRes(const char *szFile, bool fLocalOnly); // by both
- public:
- // returns referenced ressource ptrs
- C4Network2Res::Ref getRefRes(int32_t iResID); // by both
- C4Network2Res::Ref getRefRes(const char *szFile, bool fLocalOnly = false); // by both
- C4Network2Res::Ref getRefNextRes(int32_t iResID); // by both
- void Add(C4Network2Res *pRes); // by both
- C4Network2Res::Ref AddByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID = -1, const char *szResName = NULL, bool fAllowUnloadable = false); // by both
- C4Network2Res::Ref AddByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID = -1, const char *szResName = NULL, bool fAllowUnloadable = false); // by both
- C4Network2Res::Ref AddByCore(const C4Network2ResCore &Core, bool fLoad = true); // by main thread
- C4Network2Res::Ref AddLoad(const C4Network2ResCore &Core); // by main thread
- void RemoveAtClient(int32_t iClientID); // by main thread
- void Clear(); // by main thread
- bool SendDiscover(C4Network2IOConnection *pTo = NULL); // by both
- void OnClientConnect(C4Network2IOConnection *pConn); // by main thread
- // interface for C4Network2IO
- void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn);
- void OnTimer();
- // CStdCSecExCallback
- void OnShareFree(CStdCSecEx *pCSec);
- // for C4Network2Res
- C4Network2IO *getIOClass() { return pIO; }
- protected:
- void OnResComplete(C4Network2Res *pRes);
- // misc
- bool CreateNetworkFolder();
- bool FindTempResFileName(const char *szFilename, char *pTarget);
- };
- // * Packets *
- class C4PacketResStatus : public C4PacketBase
- {
- public:
- C4PacketResStatus();
- C4PacketResStatus(int32_t iResID, const C4Network2ResChunkData &nChunks);
- protected:
- int32_t iResID;
- C4Network2ResChunkData Chunks;
- public:
- int32_t getResID() const { return iResID; }
- const C4Network2ResChunkData &getChunks() const { return Chunks; }
- virtual void CompileFunc(StdCompiler *pComp);
- };
- class C4PacketResDiscover : public C4PacketBase
- {
- public:
- C4PacketResDiscover();
- protected:
- int32_t iDisIDs[16], iDisIDCnt;
- public:
- int32_t getDisIDCnt() const { return iDisIDCnt; }
- int32_t getDisID(int32_t i) const { return iDisIDs[i]; }
- bool isIDPresent(int32_t iID) const;
- bool AddDisID(int32_t iID);
- virtual void CompileFunc(StdCompiler *pComp);
- };
- class C4PacketResRequest : public C4PacketBase
- {
- public:
- C4PacketResRequest(int32_t iID = -1, int32_t iChunk = -1);
- protected:
- int32_t iReqID, iReqChunk;
- public:
- int32_t getReqID() const { return iReqID; }
- int32_t getReqChunk() const { return iReqChunk; }
- virtual void CompileFunc(StdCompiler *pComp);
- };
- #endif // INC_C4Network2Res