diff --git a/source/glest_game/menu/menu_state_connected_game.cpp b/source/glest_game/menu/menu_state_connected_game.cpp index 930e80b1..3a4757b0 100644 --- a/source/glest_game/menu/menu_state_connected_game.cpp +++ b/source/glest_game/menu/menu_state_connected_game.cpp @@ -384,7 +384,9 @@ MenuStateConnectedGame::MenuStateConnectedGame(Program *program, MainMenu *mainM GraphicComponent::applyAllCustomProperties(containerName); //tileset listBox - findDirs(config.getPathListForType(ptTilesets), tileSets); + findDirs(config.getPathListForType(ptTilesets), tilesetFiles); + + findDirs(config.getPathListForType(ptTechs), techTreeFiles); if(config.getBool("EnableFTPXfer","true") == true) { @@ -412,12 +414,22 @@ MenuStateConnectedGame::MenuStateConnectedGame(Program *program, MainMenu *mainM } } + std::pair techtreesPath; + vector techtreesList = Config::getInstance().getPathListForType(ptTechs); + if(techtreesList.size() > 0) { + techtreesPath.first = techtreesList[0]; + if(techtreesList.size() > 1) { + techtreesPath.second = techtreesList[1]; + } + } + string fileArchiveExtension = config.getString("FileArchiveExtension",""); string fileArchiveExtractCommand = config.getString("FileArchiveExtractCommand",""); string fileArchiveExtractCommandParameters = config.getString("FileArchiveExtractCommandParameters",""); - ftpClientThread = new FTPClientThread(portNumber,serverUrl,mapsPath, - tilesetsPath,this,fileArchiveExtension,fileArchiveExtractCommand, + ftpClientThread = new FTPClientThread(portNumber,serverUrl, + mapsPath,tilesetsPath,techtreesPath, + this,fileArchiveExtension,fileArchiveExtractCommand, fileArchiveExtractCommandParameters); ftpClientThread->start(); } @@ -493,6 +505,24 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){ ftpClientThread->addTilesetToRequests(getMissingTilesetFromFTPServer); MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); fileFTPProgressList[getMissingTilesetFromFTPServer] = pair(0,""); + } + } + else if(ftpMissingDataType == ftpmsg_MissingTechtree) { + getMissingTechtreeFromFTPServerInProgress = true; + + char szMsg[1024]=""; + if(lang.hasString("DataMissingTechtreeNowDownloading") == true) { + sprintf(szMsg,lang.get("DataMissingTechtreeNowDownloading").c_str(),getHumanPlayerName().c_str(),getMissingTechtreeFromFTPServer.c_str()); + } + else { + sprintf(szMsg,"Player: %s is attempting to download the techtree: %s",getHumanPlayerName().c_str(),getMissingTechtreeFromFTPServer.c_str()); + } + clientInterface->sendTextMessage(szMsg,-1, true); + + if(ftpClientThread != NULL) { + ftpClientThread->addTechtreeToRequests(getMissingTechtreeFromFTPServer); + MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); + fileFTPProgressList[getMissingTechtreeFromFTPServer] = pair(0,""); } } } @@ -890,7 +920,8 @@ void MenuStateConnectedGame::update() { // Test data synch //tilesetCRC++; - //int32 techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,""), "/" + gameSettings->getTech() + "/*", ".xml", NULL); + int32 techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,""), string("/") + gameSettings->getTech() + string("/*"), ".xml", NULL); + Checksum checksum; string file = Map::getMapPath(gameSettings->getMap(),"",false); checksum.addFile(file); @@ -900,9 +931,10 @@ void MenuStateConnectedGame::update() { safeMutexFTPProgress.ReleaseLock(); bool dataSynchMismatch = ((mapCRC != 0 && mapCRC != gameSettings->getMapCRC()) || - (tilesetCRC != 0 && tilesetCRC != gameSettings->getTilesetCRC())); + (tilesetCRC != 0 && tilesetCRC != gameSettings->getTilesetCRC()) || + (techCRC != 0 && techCRC != gameSettings->getTechCRC())); - //printf("\nmapCRC [%d] gameSettings->getMapCRC() [%d] tilesetCRC [%d] gameSettings->getTilesetCRC() [%d]\n",mapCRC,gameSettings->getMapCRC(),tilesetCRC,gameSettings->getTilesetCRC()); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nmapCRC [%d] gameSettings->getMapCRC() [%d]\ntilesetCRC [%d] gameSettings->getTilesetCRC() [%d]\ntechCRC [%d] gameSettings->getTechCRC() [%d]\n",mapCRC,gameSettings->getMapCRC(),tilesetCRC,gameSettings->getTilesetCRC(),techCRC,gameSettings->getTechCRC()); if(dataSynchMismatch == true) { string labelSynch = lang.get("DataNotSynchedTitle"); @@ -926,6 +958,15 @@ void MenuStateConnectedGame::update() { } } + if(techCRC != 0 && techCRC != gameSettings->getTechCRC()) { + labelSynch = labelSynch + " " + lang.get("TechTree"); + if(updateDataSynchDetailText == true && + lastTechtreeDataSynchError != lang.get("DataNotSynchedTechtree") + " " + listBoxTechTree.getSelectedItem()) { + lastTechtreeDataSynchError = lang.get("DataNotSynchedTechtree") + " " + listBoxTechTree.getSelectedItem(); + clientInterface->sendTextMessage(lastTechtreeDataSynchError,-1,true); + } + } + /* if(clientInterface->getNetworkGameDataSynchCheckOkTech() == false) { labelSynch = labelSynch + " techtree"; @@ -1111,13 +1152,13 @@ void MenuStateConnectedGame::update() { if(getMissingTilesetFromFTPServerInProgress == false) { // tileset - if(std::find(this->tileSets.begin(),this->tileSets.end(),gameSettings->getTileset()) != this->tileSets.end()) { + if(std::find(tilesetFiles.begin(),tilesetFiles.end(),gameSettings->getTileset()) != tilesetFiles.end()) { lastMissingTileSet = ""; tilesets.push_back(formatString(gameSettings->getTileset())); } else { - // try to get the map via ftp + // try to get the tileset via ftp if(ftpClientThread != NULL && getMissingTilesetFromFTPServer != gameSettings->getTileset()) { if(ftpMessageBox.getEnabled() == false) { getMissingTilesetFromFTPServer = gameSettings->getTileset(); @@ -1155,9 +1196,55 @@ void MenuStateConnectedGame::update() { listBoxTileset.setItems(tilesets); } - // techtree - techtree.push_back(formatString(gameSettings->getTech())); - listBoxTechTree.setItems(techtree); + if(getMissingTechtreeFromFTPServerInProgress == false) { + // techtree + if(std::find(techTreeFiles.begin(),techTreeFiles.end(),gameSettings->getTech()) != techTreeFiles.end()) { + lastMissingTechtree = ""; + + techtree.push_back(formatString(gameSettings->getTech())); + } + else { + // try to get the tileset via ftp + if(ftpClientThread != NULL && getMissingTechtreeFromFTPServer != gameSettings->getTech()) { + if(ftpMessageBox.getEnabled() == false) { + getMissingTechtreeFromFTPServer = gameSettings->getTech(); + Lang &lang= Lang::getInstance(); + + char szBuf[1024]=""; + sprintf(szBuf,"%s %s ?",lang.get("DownloadMissingTechtreeQuestion").c_str(),gameSettings->getTech().c_str()); + + ftpMissingDataType = ftpmsg_MissingTechtree; + showFTPMessageBox(szBuf, lang.get("Question"), false); + } + } + + techtree.push_back("***missing***"); + + NetworkManager &networkManager= NetworkManager::getInstance(); + ClientInterface* clientInterface= networkManager.getClientInterface(); + const GameSettings *gameSettings = clientInterface->getGameSettings(); + + if(lastMissingTechtree != gameSettings->getTech()) { + lastMissingTechtree = gameSettings->getTech(); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + char szMsg[1024]=""; + if(lang.hasString("DataMissingTechtree") == true) { + sprintf(szMsg,lang.get("DataMissingTechtree").c_str(),getHumanPlayerName().c_str(),gameSettings->getTech().c_str()); + } + else { + sprintf(szMsg,"Player: %s is missing the techtree: %s",getHumanPlayerName().c_str(),gameSettings->getTech().c_str()); + } + clientInterface->sendTextMessage(szMsg,-1, true); + } + } + listBoxTechTree.setItems(techtree); + + // techtree + //techtree.push_back(formatString(gameSettings->getTech())); + //listBoxTechTree.setItems(techtree); + } // factions bool hasFactions = true; @@ -1913,7 +2000,7 @@ void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, FTP_Client // END // Reload tilesets for the UI - findDirs(Config::getInstance().getPathListForType(ptTilesets), tileSets); + findDirs(Config::getInstance().getPathListForType(ptTilesets), tilesetFiles); } else { curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW); @@ -1928,6 +2015,85 @@ void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, FTP_Client clientInterface->sendTextMessage(szMsg,-1, true); } } + else if(type == ftp_cct_Techtree) { + getMissingTechtreeFromFTPServerInProgress = false; + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] result = %d\n",itemName.c_str(),result); + + MutexSafeWrapper safeMutexFTPProgress(ftpClientThread->getProgressMutex(),string(__FILE__) + "_" + intToStr(__LINE__)); + fileFTPProgressList.erase(itemName); + safeMutexFTPProgress.ReleaseLock(true); + + NetworkManager &networkManager= NetworkManager::getInstance(); + ClientInterface* clientInterface= networkManager.getClientInterface(); + const GameSettings *gameSettings = clientInterface->getGameSettings(); + + if(result == ftp_crt_SUCCESS) { + char szMsg[1024]=""; + if(lang.hasString("DataMissingTechtreeSuccessDownload") == true) { + sprintf(szMsg,lang.get("DataMissingTechtreeSuccessDownload").c_str(),getHumanPlayerName().c_str(),gameSettings->getTech().c_str()); + } + else { + sprintf(szMsg,"Player: %s SUCCESSFULLY downloaded the techtree: %s",getHumanPlayerName().c_str(),gameSettings->getTech().c_str()); + } + clientInterface->sendTextMessage(szMsg,-1, true); + + // START + // Clear the CRC Cache if it is populated + // + // Clear the CRC file Cache + safeMutexFTPProgress.Lock(); + Checksum::clearFileCache(); + + vector paths = Config::getInstance().getPathListForType(ptTechs); + string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1; + std::map &crcTreeCache = CacheManager::getCachedItem< std::map >(cacheLookupId); + string pathSearchString = string("/") + itemName + string("/*"); + const string filterFileExt = ".xml"; + + string cacheKey = ""; + size_t count = paths.size(); + for(size_t idx = 0; idx < count; ++idx) { + string path = paths[idx] + pathSearchString; + + cacheKey += path + "_" + filterFileExt + "_"; + } + if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] CLEARING CACHED checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str()); + crcTreeCache.erase(cacheKey); + } + + cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2; + std::map &crcTreeCache2 = CacheManager::getCachedItem< std::map >(cacheLookupId); + + count = paths.size(); + for(size_t idx = 0; idx < count; ++idx) { + string path = paths[idx] + pathSearchString; + + string cacheKey = path + "_" + filterFileExt; + if(crcTreeCache2.find(cacheKey) != crcTreeCache2.end()) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] CLEARING CACHED checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str()); + crcTreeCache2.erase(cacheKey); + } + } + safeMutexFTPProgress.ReleaseLock(); + // END + + // Reload tilesets for the UI + findDirs(Config::getInstance().getPathListForType(ptTechs), techTreeFiles); + } + else { + curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW); + + char szMsg[1024]=""; + if(lang.hasString("DataMissingTechtreeFailDownload") == true) { + sprintf(szMsg,lang.get("DataMissingTechtreeFailDownload").c_str(),getHumanPlayerName().c_str(),gameSettings->getTech().c_str(),curlVersion->version); + } + else { + sprintf(szMsg,"Player: %s FAILED to download the techtree: [%s] using CURL version [%s]",getHumanPlayerName().c_str(),gameSettings->getTech().c_str(),curlVersion->version); + } + clientInterface->sendTextMessage(szMsg,-1, true); + } + } } }}//end namespace diff --git a/source/glest_game/menu/menu_state_connected_game.h b/source/glest_game/menu/menu_state_connected_game.h index 6af8df08..8930ff78 100644 --- a/source/glest_game/menu/menu_state_connected_game.h +++ b/source/glest_game/menu/menu_state_connected_game.h @@ -30,7 +30,8 @@ enum JoinMenu { enum FTPMessageType { ftpmsg_MissingNone, ftpmsg_MissingMap, - ftpmsg_MissingTileset + ftpmsg_MissingTileset, + ftpmsg_MissingTechtree }; // =============================== @@ -73,16 +74,10 @@ private: GraphicLabel labelAdvanced; GraphicListBox listBoxAdvanced; - - GraphicListBox listBoxMap; GraphicListBox listBoxFogOfWar; GraphicListBox listBoxTechTree; GraphicListBox listBoxTileset; - vector mapFiles; - vector techTreeFiles; - vector tilesetFiles; - vector factionFiles; GraphicLabel labelPlayers[GameConstants::maxPlayers]; GraphicLabel labelPlayerNames[GameConstants::maxPlayers]; GraphicListBox listBoxControls[GameConstants::maxPlayers]; @@ -142,7 +137,10 @@ private: std::string lastMissingTechtree; std::string lastMissingTileSet; - std::vector tileSets; + vector mapFiles; + vector techTreeFiles; + vector tilesetFiles; + vector factionFiles; GraphicMessageBox ftpMessageBox; FTPClientThread *ftpClientThread; @@ -154,6 +152,9 @@ private: string getMissingTilesetFromFTPServer; bool getMissingTilesetFromFTPServerInProgress; + string getMissingTechtreeFromFTPServer; + bool getMissingTechtreeFromFTPServerInProgress; + std::map > fileFTPProgressList; public: diff --git a/source/glest_game/menu/menu_state_custom_game.cpp b/source/glest_game/menu/menu_state_custom_game.cpp index 59c1d4e7..fad50120 100644 --- a/source/glest_game/menu/menu_state_custom_game.cpp +++ b/source/glest_game/menu/menu_state_custom_game.cpp @@ -2155,7 +2155,9 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings) { int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,""), string("/") + gameSettings->getTileset() + string("/*"), ".xml", NULL); gameSettings->setTilesetCRC(tilesetCRC); - //int32 techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,""), "/" + gameSettings->getTech() + "/*", ".xml", NULL); + int32 techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,""), "/" + gameSettings->getTech() + "/*", ".xml", NULL); + gameSettings->setTechCRC(techCRC); + Checksum checksum; string file = Map::getMapPath(gameSettings->getMap(),"",false); checksum.addFile(file); diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index c28435da..86822d65 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -93,10 +93,20 @@ ServerInterface::ServerInterface() :GameNetworkInterface() { } } + std::pair techtreesPath; + vector techtreesList = Config::getInstance().getPathListForType(ptTechs); + if(techtreesList.size() > 0) { + techtreesPath.first = techtreesList[0]; + if(techtreesList.size() > 1) { + techtreesPath.second = techtreesList[1]; + } + } + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); int portNumber = Config::getInstance().getInt("FTPServerPort",intToStr(ServerSocket::getFTPServerPort()).c_str()); ServerSocket::setFTPServerPort(portNumber); - ftpServer = new FTPServerThread(mapsPath,tilesetsPath,portNumber,GameConstants::maxPlayers,this); + ftpServer = new FTPServerThread(mapsPath,tilesetsPath,techtreesPath, + portNumber,GameConstants::maxPlayers,this); ftpServer->start(); } SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); diff --git a/source/shared_lib/include/platform/posix/miniftpclient.h b/source/shared_lib/include/platform/posix/miniftpclient.h index 33832144..88487e06 100644 --- a/source/shared_lib/include/platform/posix/miniftpclient.h +++ b/source/shared_lib/include/platform/posix/miniftpclient.h @@ -36,7 +36,8 @@ enum FTP_Client_ResultType { enum FTP_Client_CallbackType { ftp_cct_Map = 0, ftp_cct_Tileset = 1, - ftp_cct_DownloadProgress = 2 + ftp_cct_Techtree = 2, + ftp_cct_DownloadProgress = 3 }; class FTPClientCallbackInterface { @@ -61,6 +62,7 @@ protected: FTPClientCallbackInterface *pCBObject; std::pair mapsPath; std::pair tilesetsPath; + std::pair techtreesPath; Mutex mutexMapFileList; vector mapFileList; @@ -68,12 +70,18 @@ protected: Mutex mutexTilesetList; vector tilesetList; + Mutex mutexTechtreeList; + vector techtreeList; + void getMapFromServer(string mapFilename); FTP_Client_ResultType getMapFromServer(string mapFileName, string ftpUser, string ftpUserPassword); void getTilesetFromServer(string tileSetName); FTP_Client_ResultType getTilesetFromServer(string tileSetName, string tileSetNameSubfolder, string ftpUser, string ftpUserPassword, bool findArchive); + void getTechtreeFromServer(string techtreeName); + FTP_Client_ResultType getTechtreeFromServer(string techtreeName, string ftpUser, string ftpUserPassword); + Mutex mutexProgressMutex; string fileArchiveExtension; @@ -85,6 +93,7 @@ public: FTPClientThread(int portNumber,string serverUrl, std::pair mapsPath, std::pair tilesetsPath, + std::pair techtreesPath, FTPClientCallbackInterface *pCBObject, string fileArchiveExtension, string fileArchiveExtractCommand, @@ -95,6 +104,7 @@ public: void addMapToRequests(string mapFilename); void addTilesetToRequests(string tileSetName); + void addTechtreeToRequests(string techtreeName); FTPClientCallbackInterface * getCallBackObject(); void setCallBackObject(FTPClientCallbackInterface *value); diff --git a/source/shared_lib/include/platform/posix/miniftpserver.h b/source/shared_lib/include/platform/posix/miniftpserver.h index 807eebb2..beb343fc 100644 --- a/source/shared_lib/include/platform/posix/miniftpserver.h +++ b/source/shared_lib/include/platform/posix/miniftpserver.h @@ -33,13 +33,17 @@ class FTPServerThread : public BaseThread protected: std::pair mapsPath; std::pair tilesetsPath; + std::pair techtreesPath; + int portNumber; int maxPlayers; static FTPClientValidationInterface *ftpValidationIntf; public: - FTPServerThread(std::pair mapsPath, std::pair tilesetsPath, int portNumber,int maxPlayers, FTPClientValidationInterface *ftpValidationIntf); + FTPServerThread(std::pair mapsPath, + std::pair tilesetsPath, std::pair techtreesPath, + int portNumber,int maxPlayers, FTPClientValidationInterface *ftpValidationIntf); ~FTPServerThread(); virtual void execute(); virtual void signalQuit(); diff --git a/source/shared_lib/sources/platform/posix/miniftpclient.cpp b/source/shared_lib/sources/platform/posix/miniftpclient.cpp index aa762d1a..1fc51698 100644 --- a/source/shared_lib/sources/platform/posix/miniftpclient.cpp +++ b/source/shared_lib/sources/platform/posix/miniftpclient.cpp @@ -29,6 +29,9 @@ const char *FTP_MAPS_CUSTOM_USERNAME = "maps_custom"; const char *FTP_MAPS_USERNAME = "maps"; const char *FTP_TILESETS_CUSTOM_USERNAME = "tilesets_custom"; const char *FTP_TILESETS_USERNAME = "tilesets"; +const char *FTP_TECHTREES_CUSTOM_USERNAME = "techtrees_custom"; +const char *FTP_TECHTREES_USERNAME = "techtrees"; + const char *FTP_COMMON_PASSWORD = "mg_ftp_server"; /* @@ -198,13 +201,18 @@ int file_progress(struct FtpFile *out,double download_total, double download_now } FTPClientThread::FTPClientThread(int portNumber, string serverUrl, - std::pair mapsPath, std::pair tilesetsPath, - FTPClientCallbackInterface *pCBObject,string fileArchiveExtension, - string fileArchiveExtractCommand,string fileArchiveExtractCommandParameters) : BaseThread() { + std::pair mapsPath, + std::pair tilesetsPath, + std::pair techtreesPath, + FTPClientCallbackInterface *pCBObject, + string fileArchiveExtension, + string fileArchiveExtractCommand, + string fileArchiveExtractCommandParameters) : BaseThread() { this->portNumber = portNumber; this->serverUrl = serverUrl; this->mapsPath = mapsPath; this->tilesetsPath = tilesetsPath; + this->techtreesPath = techtreesPath; this->pCBObject = pCBObject; this->fileArchiveExtension = fileArchiveExtension; @@ -345,6 +353,13 @@ void FTPClientThread::addTilesetToRequests(string tileSetName) { } } +void FTPClientThread::addTechtreeToRequests(string techtreeName) { + MutexSafeWrapper safeMutex(&mutexTechtreeList,string(__FILE__) + "_" + intToStr(__LINE__)); + if(std::find(techtreeList.begin(),techtreeList.end(),techtreeName) == techtreeList.end()) { + techtreeList.push_back(techtreeName); + } +} + void FTPClientThread::getTilesetFromServer(string tileSetName) { bool findArchive = executeShellCommand(this->fileArchiveExtractCommand); @@ -546,6 +561,146 @@ FTP_Client_ResultType FTPClientThread::getTilesetFromServer(string tileSetName, return result; } +void FTPClientThread::getTechtreeFromServer(string techtreeName) { + FTP_Client_ResultType result = ftp_crt_FAIL; + bool findArchive = executeShellCommand(this->fileArchiveExtractCommand); + if(findArchive == true) { + result = getTechtreeFromServer(techtreeName, FTP_TECHTREES_CUSTOM_USERNAME, FTP_COMMON_PASSWORD); + if(result == ftp_crt_FAIL && this->getQuitStatus() == false) { + result = getTechtreeFromServer(techtreeName, FTP_TECHTREES_USERNAME, FTP_COMMON_PASSWORD); + } + } + + MutexSafeWrapper safeMutex(this->getProgressMutex(),string(__FILE__) + "_" + intToStr(__LINE__)); + if(this->pCBObject != NULL) { + this->pCBObject->FTPClient_CallbackEvent(techtreeName,ftp_cct_Techtree,result,NULL); + } +} + +FTP_Client_ResultType FTPClientThread::getTechtreeFromServer(string techtreeName, + string ftpUser, string ftpUserPassword) { + FTP_Client_ResultType result = ftp_crt_FAIL; + + string destFile = this->techtreesPath.second; + + // Root folder for the techtree + string destRootArchiveFolder = ""; + string destRootFolder = ""; + destRootFolder = this->techtreesPath.second; + if( EndsWith(destRootFolder,"/") == false && + EndsWith(destRootFolder,"\\") == false) { + destRootFolder += "/"; + } + destRootArchiveFolder = destRootFolder; + destRootFolder += techtreeName; + if( EndsWith(destRootFolder,"/") == false && + EndsWith(destRootFolder,"\\") == false) { + destRootFolder += "/"; + } + + createDirectoryPaths(destRootFolder); + + if(EndsWith(destFile,"/") == false && EndsWith(destFile,"\\") == false) { + destFile += "/"; + } + destFile += techtreeName; + if(EndsWith(destFile,"/") == false && EndsWith(destFile,"\\") == false) { + destFile += "/"; + } + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread about to try to RETR into [%s]\n",destFile.c_str()); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread about to try to RETR into [%s]\n",destFile.c_str()); + + struct FtpFile ftpfile = { + techtreeName.c_str(), + destFile.c_str(), // name to store the file as if succesful + destFile.c_str(), + NULL, + this, + "", + false + }; + + ftpfile.filepath = destRootArchiveFolder.c_str(); + + CURL *curl = SystemFlags::initHTTP(); + if(curl) { + ftpfile.stream = NULL; + + char szBuf[1024]=""; + sprintf(szBuf,"ftp://%s:%s@%s:%d/%s%s",ftpUser.c_str(),ftpUserPassword.c_str(),serverUrl.c_str(),portNumber,techtreeName.c_str(),this->fileArchiveExtension.c_str()); + + curl_easy_setopt(curl, CURLOPT_URL,szBuf); + curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L); + + // turn on wildcard matching + curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L); + + // callback is called before download of concrete file started + curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_comming); + // callback is called after data from the file have been transferred + curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded); + + curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &ftpfile); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); + + // Define our callback to get called when there's data to be written + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + // Set a pointer to our struct to pass to the callback + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); + + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, file_progress); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &ftpfile); + + // Max 10 minutes to transfer + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 600); + + // Switch on full protocol/debug output + if(SystemFlags::VERBOSE_MODE_ENABLED) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + + CURLcode res = curl_easy_perform(curl); + + if(res != CURLE_OK) { + // we failed + printf("curl FAILED with: %d [%s] attempting to remove folder contents [%s] szBuf [%s] ftpfile.isValidXfer = %d\n", res,curl_easy_strerror(res),destRootFolder.c_str(),szBuf,ftpfile.isValidXfer); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"curl FAILED with: %d [%s] attempting to remove folder contents [%s] szBuf [%s] ftpfile.isValidXfer = %d\n", res,curl_easy_strerror(res),destRootFolder.c_str(),szBuf,ftpfile.isValidXfer); + + if(res == CURLE_PARTIAL_FILE || ftpfile.isValidXfer == true) { + result = ftp_crt_PARTIALFAIL; + } + + if(destRootFolder != "") { + removeFolder(destRootFolder); + } + } + else { + result = ftp_crt_SUCCESS; + } + + SystemFlags::cleanupHTTP(&curl); + } + + if(ftpfile.stream) { + fclose(ftpfile.stream); + ftpfile.stream = NULL; + } + + // Extract the archive + if(result == ftp_crt_SUCCESS) { + string extractCmd = getFullFileArchiveExtractCommand(this->fileArchiveExtractCommand, + this->fileArchiveExtractCommandParameters, destRootArchiveFolder, + destRootArchiveFolder + techtreeName + this->fileArchiveExtension); + + if(executeShellCommand(extractCmd) == false) { + result = ftp_crt_FAIL; + } + } + + return result; +} + + FTPClientCallbackInterface * FTPClientThread::getCallBackObject() { MutexSafeWrapper safeMutex(this->getProgressMutex(),string(__FILE__) + "_" + intToStr(__LINE__)); return pCBObject; @@ -598,6 +753,18 @@ void FTPClientThread::execute() { safeMutex2.ReleaseLock(); } + MutexSafeWrapper safeMutex3(&mutexTechtreeList,string(__FILE__) + "_" + intToStr(__LINE__)); + if(techtreeList.size() > 0) { + string techtree = techtreeList[0]; + techtreeList.erase(techtreeList.begin() + 0); + safeMutex3.ReleaseLock(); + + getTechtreeFromServer(techtree); + } + else { + safeMutex3.ReleaseLock(); + } + if(this->getQuitStatus() == false) { sleep(25); } diff --git a/source/shared_lib/sources/platform/posix/miniftpserver.cpp b/source/shared_lib/sources/platform/posix/miniftpserver.cpp index e0b8b722..3dd39682 100644 --- a/source/shared_lib/sources/platform/posix/miniftpserver.cpp +++ b/source/shared_lib/sources/platform/posix/miniftpserver.cpp @@ -46,9 +46,13 @@ int isValidClientType(ip_t clientIp) { return result; } -FTPServerThread::FTPServerThread(std::pair mapsPath,std::pair tilesetsPath, int portNumber, int maxPlayers,FTPClientValidationInterface *ftpValidationIntf) : BaseThread() { +FTPServerThread::FTPServerThread(std::pair mapsPath, + std::pair tilesetsPath, std::pair techtreesPath, + int portNumber, int maxPlayers, + FTPClientValidationInterface *ftpValidationIntf) : BaseThread() { this->mapsPath = mapsPath; this->tilesetsPath = tilesetsPath; + this->techtreesPath = techtreesPath; this->portNumber = portNumber; this->maxPlayers = maxPlayers; this->ftpValidationIntf = ftpValidationIntf; @@ -125,6 +129,16 @@ void FTPServerThread::execute() { ftpCreateAccount("tilesets_custom", "mg_ftp_server", tilesetsPath.second.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); } + // Setup FTP Users and permissions for tilesets + if(techtreesPath.first != "") { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] techtreesPath #1 [%s]\n",__FILE__,__FUNCTION__,__LINE__,techtreesPath.first.c_str()); + ftpCreateAccount("techtrees", "mg_ftp_server", techtreesPath.first.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); + } + if(techtreesPath.second != "") { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] techtreesPath #2 [%s]\n",__FILE__,__FUNCTION__,__LINE__,techtreesPath.second.c_str()); + ftpCreateAccount("techtrees_custom", "mg_ftp_server", techtreesPath.second.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); + } + /* ftpCreateAccount("anonymous", "", "./", FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); ftpCreateAccount("nothing", "", "./", 0);