Add custom formatter for regen text
[ryzomcore.git] / ryzom / client / src / login_patch.h
blobdfd46b49c50c7b09182df9527b435415b2ad7143
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef CL_PATCH_H
18 #define CL_PATCH_H
20 #include <string>
22 #include "nel/misc/types_nl.h"
23 #include "nel/misc/config_file.h"
24 #include "nel/misc/thread.h"
25 #include "nel/misc/progress_callback.h"
27 #include "game_share/bnp_patch.h"
29 #include "login_xdelta.h"
31 extern NLMISC::CConfigFile ConfigFile;
33 class CPatchThread;
34 class CCheckThread;
35 class CScanDataThread;
36 class CInstallThread;
37 class CDownloadThread;
40 // Useful for using an external downloader (BitTorrent) use of interface with CGameDownloader from client_background_rd.exe using as install program
41 // Forward all messages to CRyzomControl that will forward to CGameDownloader (The engine of the install software)
42 class IAsyncDownloader
44 public:
45 virtual ~IAsyncDownloader(){}
46 virtual void addToDownloadList(const std::string &/* patchName */, const std::string &/* sourceName */, uint32 /* timestamp */, const std::string& /* extractPath */, uint32 /* sevenZipSize */, uint32 /* size */){}
47 virtual void onFileInstall(const std::string& /* filename */, uint32 /* index */, uint32 /* filecount */){}
48 virtual void onFileInstallFinished(){}
49 virtual void onFileDownloading(const std::string& /* sourceName */, uint32 /* rate */, uint32 /* fileIndex */, uint32 /* fileCount */, uint64 /* fileSize */, uint64 /* fullSize */){}
50 virtual void onFileInstalling(const std::string& /* sourceName */, uint32 /* rate */, uint32 /* fileIndex */, uint32 /* fileCount */, uint64 /* fileSize */, uint64 /* fullSize */){}
51 virtual void onFileDownloadFinished(){}
52 virtual void fatalError(const std::string& /* errorId */, const std::string& /* param1 */, const std::string& /* param2 */){}
55 // To define alternate log
56 class IPatchManagerStateListener
58 public:
59 virtual void setState (bool /* bOutputToLog */, const std::string &/* ucsNewState */){}
62 // Get Info of file to install
63 class CInstallThreadEntry
65 public:
66 CInstallThreadEntry(){ Timestamp = 0; }
67 CInstallThreadEntry(const char* patchName, const char* sourceName, uint32 timestamp, const char* extractPath, uint32 size, uint32 sZipFileSize)
68 :PatchName(patchName), SourceName(sourceName), Timestamp(timestamp),Size(size),SZipFileSize(sZipFileSize),ExtractPath(extractPath) {}
69 std::string PatchName;
70 std::string SourceName;
71 uint32 Timestamp;
72 uint32 Size;
73 uint32 SZipFileSize;
74 std::string ExtractPath;
78 /**
79 * class managing the patch system
80 * \author Matthieu 'TrapII' Besson
81 * \author Vianney 'Ace' Lecroart
82 * \author Nevrax France
83 * \date July 2004
85 class CPatchManager
88 public:
90 struct SFileToPatch
92 std::string FileName; // Dest file for the patch
93 std::string SrcFileName; // Optional src file to which apply patch (empty unless some version of the file, possibly with
94 // all patchs applied, was found in the /unpack directory due to a download by the background downloader)
95 std::vector<uint32> Patches;
96 std::vector<uint32> PatcheSizes;
97 uint32 LastFileDate; // Used during patching to set the date of the file to the Date of the last patch
98 bool LocalFileToDelete; // Used during patching to know if we have to delete local file prior to apply patches
99 bool LocalFileExists;
100 bool Incremental; // Used during patching to know if we have to xdelta against a ref file
101 std::string ExtractPath; // Used during patching to extract a bnp file to a specific directory
102 uint32 FinalFileSize; // just for info, the final size after patch
103 uint32 SZFileSize; // Size of the SZ file
106 struct SPatchInfo
108 struct SCat
110 std::string Name;
111 uint32 Size; // Patch size for this category (all files to patch)
112 sint32 Req; // -1 or a value in Required cat (used only for optcat)
113 uint32 SZipSize; // SevenZipSize
114 uint32 FinalFileSize; // uncompressed SevenZipSize
115 SCat() { Size = 0; Req = -1; SZipSize = 0; FinalFileSize=0;}
118 std::vector<SCat> NonOptCat;
119 std::vector<SCat> ReqCat;
120 std::vector<SCat> OptCat;
123 void clear()
125 NonOptCat.clear();
126 ReqCat.clear();
127 OptCat.clear();
130 // return bitfield of available patchs, indexed by BGDownloader::TDownloadID
131 uint32 getAvailablePatchsBitfield() const;
134 public:
136 /// Singleton method : Get the unique patch manager instance
137 static CPatchManager* getInstance()
139 if (_Instance == NULL)
140 _Instance = new CPatchManager();
141 return _Instance;
144 // serverPath is the name where to find all patches, files description and so on
145 // serverVersion is a string describing the version of the description file
146 void init(const std::vector<std::string>& patchURIs, const std::string &serverPath, const std::string &serverVersion);
148 /// Get the version with the Description file (must be done after init)
149 std::string getClientVersion ();
151 bool isVerboseLog() { return VerboseLog; }
153 void setVerboseLog(bool b) { VerboseLog = b; }
155 // Get the string information about what the threads are doing
156 // Return true if the state has changed
157 bool getThreadState (std::string &state, std::vector<std::string> &stateLog);
159 /** Get the error message (filled after a patch of check)
160 * May be empty if the cause of error is unknown or unhandled
162 const std::string &getLastErrorMessage() { return _ErrorMessage; }
164 // ---------------------
165 // First Part : Checking
166 // ---------------------
168 // start the check of bnp (download description file DescFilename, look at the version of bnps)
169 // init must have been done
170 void startCheckThread(bool includeBackgroundPatch);
172 // if the checkThread ended and is ok then the getDesc* methods can be called
173 bool isCheckThreadEnded(bool &ok);
175 // Get all the optional categories to display for patching
176 void getInfoToDisp(SPatchInfo &piOut);
178 void forceStopCheckThread();
179 // Used by installation software
180 void startInstallThread(const std::vector<CInstallThreadEntry>& entries);
181 // Used by installation software
182 void startDownloadThread(const std::vector<CInstallThreadEntry>& entries);
183 // ----------------------------------------------
184 // Second Part : Downloading and Applying patches
185 // ----------------------------------------------
187 /** start to patch with a set of files
188 * \param commitPatch When true, the patched version of the file will replace the original file, else the patched version
189 * will be left in the /unpack directory and the previous version in /data will remain unchanged.
190 * The background downloader should set this to false.
193 void startPatchThread(const std::vector<std::string> &CategoriesSelected, bool commitPatch);
195 // Return true if patch has ended
196 // Ok is set to true if the patch is ended and the patch process is ok (if the patch is already ended ok is false)
197 bool isPatchThreadEnded (bool &ok);
200 void forceStopPatchThread();
202 bool mustLaunchBatFile() const { return MustLaunchBatFile; }
203 void createBatchFile(CProductDescriptionForClient &descFile, bool wantRyzomRestart = true, bool useBatchFile = true);
204 void executeBatchFile();
205 void deleteBatchFile();
206 void reboot();
208 // TODO : modify it for the second part ...
209 // Maybe we can't get patchs size ... currently, it only returns 1!
211 int getTotalFilesToGet();
212 int getCurrentFilesToGet();
213 int getPatchingSize();
215 // Return % of current file that has been downloaded/patched so far
216 float getCurrentFileProgress() const;
218 bool isDownloadInProgress() { return DownloadInProgress; }
220 // ----------------------------------------------
221 // ScanData Part : optional task which verify all data
222 // ----------------------------------------------
224 // start the full check of BNP
225 void startScanDataThread();
227 // if the scan data thread has ended
228 bool isScanDataThreadEnded(bool &ok);
230 // ask to stop the Scan Data thread. NB: for security, the thread will continue to the current scanned file,
231 // then stop. Hence, you must still wait isScanDataThreadEnded() return true
232 void askForStopScanDataThread();
234 // If the scan thread is not running, touch the files with error, and return the number of corrupted files
235 uint applyScanDataResult();
237 // get the current info Log for data Scan (true if some change from last get, else text is not filled)
238 bool getDataScanLog(std::string &text);
240 CProductDescriptionForClient &getDescFile() { return DescFile; }
242 NLMISC::IThread *getCurrThread() const { return Thread; }
243 // set an external state listener (enable to log) infos
244 void setStateListener(IPatchManagerStateListener* stateListener);
246 // set an external downloader (useful for installer using BitTorrent protocole)
247 void setAsyncDownloader(IAsyncDownloader* asyncDownloader);
248 // get the external downloader (useful for installer using BitTorrent protocole or NULL)
249 IAsyncDownloader* getAsyncDownloader() const;
251 // By default the name used is the name of the current executable.
252 // But for external torrent downloader we must set "client_ryzom_rd.exe"
253 void setRyzomFilename(const std::string& ryzomFilename) { RyzomFilename = ryzomFilename; }
255 // Used when client data is not located in current directory
256 void setClientRootPath(const std::string& clientRootPath);
258 // Used by installation software to download a file only if necessary
259 static bool download(const std::string& patchPath, const std::string& sourcePath,
260 const std::string& tmpDirectory, uint32 timestamp);
261 // Used by installation software to create install.bat file (not used)
262 static bool extract(const std::string& patchPath,
263 const std::vector<std::string>& sourceFilename,
264 const std::vector<std::string>& extractPath,
265 const std::string& updateBatchFilename,
266 const std::string& exectName,
267 void (*stopFun)() );
268 // Installation software must be able to indicate if ryzom must be stated at end of installation
269 void setStartRyzomAtEnd(bool startAtEnd){ _StartRyzomAtEnd = startAtEnd; }
270 // Forward message to installation software if needed
271 void fatalError(const std::string& errorId, const std::string& param1, const std::string& param2);
273 const std::string & getServerVersion () { return ServerVersion; }
274 private:
276 // Methods used by patch & check threads
277 // -------------------------------------
279 friend class CCheckThread;
280 friend class CPatchThread;
281 friend class CScanDataThread;
282 friend class CInstallThread;
283 friend class CDownloadThread;
284 friend class CPatchThreadDownloadProgress;
286 // Set the thread state (called by threads to let us know what they are doing)
287 void setState (bool bOutputToLog, const std::string &ucsState);
288 void touchState();
290 /// Get the version of the server given during init()
293 /// Read the description file (throw exception if it doesn't exist)
294 void readDescFile(sint32 nVersion);
296 /// Read the description of the highest client version file found
297 void readClientVersionAndDescFile();
299 void setRWAccess (const std::string &filename, bool bThrowException=true);
301 std::string deleteFile (const std::string &filename, bool bThrowException=true, bool bWarning=true);
303 // Rename src to dst throw an exception if we cant
304 void renameFile (const std::string &src, const std::string &dst);
306 // Accessors used by the patch thread
307 const std::string &getDescFilename() { return DescFilename; }
308 const std::string &getUpdateBatchFilename() { return UpdateBatchFilename; }
309 const std::string &getRyzomFilename() { return RyzomFilename; }
311 CPatchThread *getPatchThread() { return PatchThread; }
313 // Get a file from the server and decompress it if zipped
314 void getServerFile (const std::string &name, bool bZipped = false, const std::string& destName="", NLMISC::IProgressCallback *progress = NULL);
315 void downloadFileWithCurl (const std::string &source, const std::string &dest, NLMISC::IProgressCallback *progress = NULL);
316 void downloadFile (const std::string &source, const std::string &dest, NLMISC::IProgressCallback *progress = NULL);
317 // Decompress zipped file override destination file
318 void decompressFile (const std::string &filename);
319 void applyDate (const std::string &sFilename, uint32 nDate);
321 void getPatchFromDesc(SFileToPatch &ftpOut, const CBNPFile &fIn, bool forceCheckSumTest);
323 bool bnpUnpack(const std::string &srcBigfile, const std::string &dstPath, std::vector<std::string> &vFilenames);
325 // stop the threads (called when knowing the thread ended)
326 void stopCheckThread();
327 void stopPatchThread();
328 void stopScanDataThread();
330 // add a file to the scan data log
331 void addDataScanLogCorruptedFile(const SFileToPatch &ftp);
332 void clearDataScanLog();
333 static void getCorruptedFileInfo(const SFileToPatch &ftp, std::string &sTranslate);
335 static bool downloadAndUnpack(const std::string& patchPath, const std::string& sourceFilename, const std::string& extractPath, const std::string& tmpDirectory, uint32 timestamp);
336 // Forward message to Installation Software
337 void onFileInstallFinished();
338 void onFileDownloadFinished();
339 void onFileDownloading(const std::string& sourceName, uint32 rate, uint32 fileIndex, uint32 fileCount, uint64 fileSize, uint64 fullSize);
340 void onFileInstalling(const std::string& sourceName, uint32 rate, uint32 fileIndex, uint32 fileCount, uint64 fileSize, uint64 fullSize);
342 private:
344 static int downloadProgressFunc(void *foo, double t, double d, double ultotal, double ulnow);
345 static int validateProgress(void *foo, double t, double d, double ultotal, double ulnow);
347 class MyPatchingCB : public CXDeltaPatch::ICallBack
349 public:
350 std::string patchFilename;
351 std::string srcFilename;
353 virtual void progress(float f);
355 friend class CPatchManager::MyPatchingCB;
357 private:
359 /// Constructor
360 CPatchManager();
362 /// The singleton's instance
363 static CPatchManager* _Instance;
365 class CPatchServer
367 public:
369 CPatchServer(const std::string& serverPath)
371 ServerPath = serverPath;
372 Available = true;
374 if (!ServerPath.empty() && ServerPath[ServerPath.size()-1] != '/')
375 ServerPath += '/';
377 std::string::size_type pos = ServerPath.find ("@");
378 if (pos != std::string::npos)
379 DisplayedServerPath = "http://" + ServerPath.substr (pos+1);
380 else
381 DisplayedServerPath = ServerPath;
384 std::string ServerPath;
385 std::string DisplayedServerPath;
386 bool Available;
389 // Patch Servers
390 std::vector<CPatchServer> PatchServers;
391 sint UsedServer;
393 // Server desc
394 std::string ServerPath;
395 std::string DisplayedServerPath;
396 std::string ServerVersion;
398 bool DownloadInProgress;
400 /// Description file
401 std::string DescFilename;
402 bool ValidDescFile;
403 CProductDescriptionForClient DescFile;
404 std::vector<SFileToPatch> FilesToPatch;
405 std::vector<std::string> OptionalCat;
407 std::string _ErrorMessage;
409 // Threads
410 CPatchThread *PatchThread;
411 CCheckThread *CheckThread;
412 CScanDataThread *ScanDataThread;
413 CInstallThread *InstallThread;
414 CDownloadThread *DownloadThread;
415 NLMISC::IThread *Thread;
417 // State
418 struct CState
420 std::string State;
421 std::vector<std::string> StateLog;
422 bool StateChanged;
423 CState()
425 StateChanged= false;
428 NLMISC::CSynchronized<CState> State;
429 std::string LogSeparator;
430 std::string CurrentFile;
433 // Useful pathes and names
435 /// Now deprecated : the launcher is the client ryzom
436 std::string RyzomFilename;
437 std::string UpdateBatchFilename;
438 std::string UpgradeBatchFilename;
440 // Where the client get all delta and desc file
441 std::string ClientPatchPath; // Temporary path
442 std::string ReadableClientDataPath; // Where original data can be found
443 std::string WritableClientDataPath; // Where data can be written
445 /// Output useful information for debugging in the log file
446 bool VerboseLog;
448 bool MustLaunchBatFile; // And then relaunch ryzom
450 // For Data Scan, list of files with checksum error => should delete them
451 struct CDataScanState
453 std::vector<SFileToPatch> FilesWithScanDataError;
454 bool Changed;
455 CDataScanState()
457 Changed= false;
460 typedef NLMISC::CSynchronized<CDataScanState> TSyncDataScanState;
461 TSyncDataScanState DataScanState;
462 // The date to apply when file is buggy: use default of year 2001, just to have a coherent date
463 enum {DefaultResetDate= 31 * 366 * 24 * 3600};
464 // The file size of a an empty BNP
465 // If the BNP Header format change, please modify 'EmptyBnpFileSize' as needed
466 enum {EmptyBnpFileSize= 8};
467 // Use an external downloader: (BitTorrent)
468 IAsyncDownloader* _AsyncDownloader;
469 IPatchManagerStateListener* _StateListener;// Alternate log
470 bool _StartRyzomAtEnd;
471 public:
472 // used by threads to signal error at the end of execution
473 void setErrorMessage(const std::string &message);
478 * \author Matthieu 'TrapII' Besson
479 * \author Vianney 'Ace' Lecroart
480 * \author Nevrax France
481 * \date July 2004
483 class CCheckThread : public NLMISC::IRunnable
486 public:
488 CCheckThread(bool includeBackgroundPatch);
490 public:
492 bool Ended; // true if the thread have ended
493 bool CheckOk; // true if the check is good
494 bool StopAsked;
496 int TotalFileToCheck;
497 int CurrentFileChecked;
498 bool IncludeBackgroundPatch;
500 private:
502 void run();
507 * class managing the patch getting files from server and applying patches
508 * \author Matthieu 'TrapII' Besson
509 * \author Vianney 'Ace' Lecroart
510 * \author Nevrax France
511 * \date July 2004
513 class CPatchThread : public NLMISC::IRunnable
516 public:
518 bool Ended; // true if the thread have ended the patch
519 bool PatchOk; // true if the patch was good
520 bool StopAsked;
522 public:
524 CPatchThread(bool commitPatch);
526 // Clear the list of files to patch
527 void clear();
529 // Add files to be patched (avoid multiple time the same file)
530 void add(const CPatchManager::SFileToPatch &ftp);
532 int getNbFileToPatch() { return (int)AllFilesToPatch.size(); }
533 int getCurrentFilePatched() { return (int) floorf(CurrentFilePatched); }
534 int getPatchingSize() { return PatchSizeProgress; }
535 float getCurrentFileProgress() const { return fmodf(CurrentFilePatched, 1.f); }
537 private:
539 std::vector<CPatchManager::SFileToPatch> AllFilesToPatch;
540 float CurrentFilePatched;
541 int PatchSizeProgress;
542 bool _CommitPatch;
545 friend class CPatchThreadDownloadProgress;
546 private:
548 void run();
549 void processFile (CPatchManager::SFileToPatch &rFTP);
550 void xDeltaPatch(const std::string &patch, const std::string &src, const std::string &out);
554 * This thread peforms the installation of file that have been downloaded via asynchrous download (BitTorrent)
555 * It unzip, delete obsolete file, extract file from bnp
559 class CInstallThread : public NLMISC::IRunnable
561 public:
562 CInstallThread(const std::vector<CInstallThreadEntry> entries):_Entries(entries){}
563 void run();
564 std::vector<CInstallThreadEntry> _Entries;
567 class CDownloadThread : public NLMISC::IRunnable
569 public:
570 CDownloadThread(const std::vector<CInstallThreadEntry> entries):_Entries(entries){}
571 void run();
572 std::vector<CInstallThreadEntry> _Entries;
576 * This thread perform a checksum check on all existing files registered in the local .idx
577 * \author Lionel Berenguier
578 * \author Nevrax France
579 * \date July 2004
581 class CScanDataThread : public NLMISC::IRunnable
584 public:
586 CScanDataThread();
588 public:
590 // Written by MainThread, read by thread
591 bool AskForCancel; // true if the main thread ask to cancel the task
593 // Written by thread, read by Main Thread
594 bool Ended; // true if the thread have ended
595 bool CheckOk; // true if the check is good
596 int TotalFileToScan;
597 int CurrentFileScanned;
599 private:
601 void run();
606 #endif // CL_PATCH_H
608 /* End of login_patch.h */