// ============================================================== // This file is part of MegaGlest Shared Library (www.glest.org) // // Copyright (C) 2009-2010 Titus Tscharntke (info@titusgames.de) and // Mark Vejvoda (mark_vejvoda@hotmail.com) // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #include "miniftpclient.h" #include "util.h" #include "platform_common.h" #include #include #include using namespace Shared::Util; using namespace Shared::PlatformCommon; namespace Shared { namespace PlatformCommon { /* * This is an example showing how to get a single file from an FTP server. * It delays the actual destination file creation until the first write * callback so that it won't create an empty file in case the remote file * doesn't exist or something else fails. */ struct FtpFile { const char *filename; FILE *stream; }; static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { struct FtpFile *out=(struct FtpFile *)stream; if(out && !out->stream) { /* open file for writing */ out->stream=fopen(out->filename, "wb"); if(!out->stream) return -1; /* failure, can't open file to write */ } return fwrite(buffer, size, nmemb, out->stream); } FTPClientThread::FTPClientThread(string serverUrl, std::pair mapsPath, FTPClientCallbackInterface *pCBObject) : BaseThread() { this->serverUrl = serverUrl; this->mapsPath = mapsPath; this->pCBObject = pCBObject; } void FTPClientThread::signalQuit() { if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client: signalQuit\n"); BaseThread::signalQuit(); } bool FTPClientThread::shutdownAndWait() { if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client: shutdownAndWait\n"); signalQuit(); return BaseThread::shutdownAndWait(); } void FTPClientThread::getMapFromServer(string mapFileName) { CURLcode res; FTP_Client_ResultType result = ftp_crt_FAIL; string destFile = this->mapsPath.second + mapFileName; struct FtpFile ftpfile = { destFile.c_str(), /* name to store the file as if succesful */ NULL }; //curl_global_init(CURL_GLOBAL_DEFAULT); CURL *curl = curl_easy_init(); if(curl) { /* * You better replace the URL with one that works! */ char szBuf[1024]=""; sprintf(szBuf,"ftp://maps:mg_ftp_server@%s/maps/%s",serverUrl.c_str(),mapFileName.c_str()); curl_easy_setopt(curl, CURLOPT_URL,szBuf); /* 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); /* Switch on full protocol/debug output */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); res = curl_easy_perform(curl); /* always cleanup */ //curl_easy_cleanup(curl); if(CURLE_OK != res) { /* we failed */ fprintf(stderr, "curl told us %d\n", res); sprintf(szBuf,"ftp://maps_custom:mg_ftp_server@%s/maps/%s",serverUrl.c_str(),mapFileName.c_str()); curl_easy_setopt(curl, CURLOPT_URL,szBuf); /* 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); /* Switch on full protocol/debug output */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); res = curl_easy_perform(curl); /* always cleanup */ //curl_easy_cleanup(curl); if(CURLE_OK != res) { /* we failed */ fprintf(stderr, "curl told us %d\n", res); } else { result = ftp_crt_SUCCESS; } } else { result = ftp_crt_SUCCESS; } curl_easy_cleanup(curl); } if(ftpfile.stream) { fclose(ftpfile.stream); /* close the local file */ } //curl_global_cleanup(); if(this->pCBObject != NULL) { this->pCBObject->FTPClient_CallbackEvent(mapFileName,result); } } void FTPClientThread::addMapToRequests(string mapFilename) { MutexSafeWrapper safeMutex(&mutexMapFileList); mapFileList.push_back(mapFilename); } void FTPClientThread::execute() { { RunningStatusSafeWrapper runningStatus(this); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); if(getQuitStatus() == true) { return; } if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread is running\n"); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"FTP Client thread is running\n"); try { while(this->getQuitStatus() == false) { MutexSafeWrapper safeMutex(&mutexMapFileList); if(mapFileList.size() > 0) { string mapFilename = mapFileList[0]; mapFileList.erase(mapFileList.begin() + 0); safeMutex.ReleaseLock(); getMapFromServer(mapFilename); } else { safeMutex.ReleaseLock(); } sleep(25); } if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client exiting!\n"); } catch(const exception &ex) { SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); } catch(...) { SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__); } SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] FTP Client thread is exiting\n",__FILE__,__FUNCTION__,__LINE__); } // Delete ourself when the thread is done (no other actions can happen after this // such as the mutex which modifies the running status of this method //delete this; } }}//end namespace