Decouple downloader from streamed package manager
parent
cfaae39b83
commit
b32b1becec
@ -0,0 +1,50 @@
|
|||||||
|
// NeL - MMORPG Framework <https://wiki.ryzom.dev/>
|
||||||
|
// Copyright (C) 2019 Jan BOON (jan.boon@kaetemi.be)
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef NLMISC_HTTP_PACKAGE_PROVIDER_H
|
||||||
|
#define NLMISC_HTTP_PACKAGE_PROVIDER_H
|
||||||
|
|
||||||
|
#include <nel/misc/types_nl.h>
|
||||||
|
#include <nel/misc/i_streamed_package_provider.h>
|
||||||
|
|
||||||
|
namespace NLMISC {
|
||||||
|
|
||||||
|
class CHttpPackageProvider : public IStreamedPackageProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CHttpPackageProvider();
|
||||||
|
virtual ~CHttpPackageProvider();
|
||||||
|
|
||||||
|
/// Download a file. This call is blocking
|
||||||
|
/// filePath: [out] ex. /games/nel/stream/00/00/000000000..
|
||||||
|
/// hash: [in]
|
||||||
|
virtual bool getFile(std::string &filePath, const CHashKey &hash, const std::string &name) NL_OVERRIDE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Set storage path (ex. stream/)
|
||||||
|
std::string Path;
|
||||||
|
|
||||||
|
/// Loads a package into the package manager (ex. http://cdn.ryzom.dev/open/stream/)
|
||||||
|
typedef std::vector<std::string> THosts;
|
||||||
|
THosts Hosts;
|
||||||
|
|
||||||
|
}; /* class CHttpPackageProvider */
|
||||||
|
|
||||||
|
} /* namespace NLMISC */
|
||||||
|
|
||||||
|
#endif /* #ifndef NLMISC_STREAMED_PACKAGE_MANAGER_H */
|
||||||
|
|
||||||
|
/* end of file */
|
@ -0,0 +1,44 @@
|
|||||||
|
// NeL - MMORPG Framework <https://wiki.ryzom.dev/>
|
||||||
|
// Copyright (C) 2019 Jan BOON (jan.boon@kaetemi.be)
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef NLMISC_STREAMED_PACKAGE_PROVIDER_H
|
||||||
|
#define NLMISC_STREAMED_PACKAGE_PROVIDER_H
|
||||||
|
|
||||||
|
#include <nel/misc/types_nl.h>
|
||||||
|
#include <nel/misc/sha1.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace NLMISC {
|
||||||
|
|
||||||
|
class IStreamedPackageProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IStreamedPackageProvider();
|
||||||
|
virtual ~IStreamedPackageProvider();
|
||||||
|
|
||||||
|
/// Download a file. This call is blocking
|
||||||
|
/// filePath: [out] ex. /games/nel/stream/00/00/000000000..
|
||||||
|
/// hash: [in]
|
||||||
|
/// name: [in] name for debugging
|
||||||
|
virtual bool getFile(std::string &filePath, const CHashKey &hash, const std::string &name = "");
|
||||||
|
|
||||||
|
}; /* class IStreamedPackageProvider */
|
||||||
|
|
||||||
|
} /* namespace NLMISC */
|
||||||
|
|
||||||
|
#endif /* #ifndef NLMISC_STREAMED_PACKAGE_PROVIDER_H */
|
||||||
|
|
||||||
|
/* end of file */
|
@ -0,0 +1,145 @@
|
|||||||
|
// NeL - MMORPG Framework <https://wiki.ryzom.dev/>
|
||||||
|
// Copyright (C) 2019 Jan BOON (jan.boon@kaetemi.be)
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "stdmisc.h"
|
||||||
|
|
||||||
|
// 3rd Party includes
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
// Project includes
|
||||||
|
#include <nel/misc/http_package_provider.h>
|
||||||
|
#include <nel/misc/streamed_package.h>
|
||||||
|
#include <nel/misc/file.h>
|
||||||
|
#include <nel/misc/path.h>
|
||||||
|
#include <nel/misc/seven_zip.h>
|
||||||
|
#include <nel/misc/sha1.h>
|
||||||
|
|
||||||
|
namespace NLMISC
|
||||||
|
{
|
||||||
|
|
||||||
|
CHttpPackageProvider::CHttpPackageProvider()
|
||||||
|
{
|
||||||
|
// init
|
||||||
|
}
|
||||||
|
|
||||||
|
CHttpPackageProvider::~CHttpPackageProvider()
|
||||||
|
{
|
||||||
|
// release
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHttpPackageProvider::getFile(std::string &filePath, const CHashKey &hash, const std::string &name)
|
||||||
|
{
|
||||||
|
CStreamedPackage::makePath(filePath, hash);
|
||||||
|
std::string downloadUrlFile = filePath + ".lzma";
|
||||||
|
filePath = Path + filePath;
|
||||||
|
std::string downloadPath = filePath + ".download." + toString(rand() * rand());
|
||||||
|
|
||||||
|
std::string storageDirectory = CFile::getPath(downloadPath);
|
||||||
|
CFile::createDirectoryTree(storageDirectory);
|
||||||
|
/*if (!CFile::isDirectory(storageDirectory) || !CFile::createDirectoryTree(storageDirectory))
|
||||||
|
{
|
||||||
|
nldebug("Unable to create directory '%s'", storageDirectory.c_str());
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// download
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (CFile::fileExists(filePath))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::string downloadUrl = Hosts[rand() % Hosts.size()] + downloadUrlFile;
|
||||||
|
nldebug("Download streamed package '%s' from '%s'", name.c_str(), downloadUrl.c_str());
|
||||||
|
|
||||||
|
FILE *fp = fopen(downloadPath.c_str(), "wb");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
nldebug("Unable to create file '%s' for '%s'", downloadPath.c_str(), name.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if (curl)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, downloadUrl.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FILE, fp);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
long r;
|
||||||
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &r);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
bool diskFull = ferror(fp) && errno == 28 /*ENOSPC*/;
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (diskFull)
|
||||||
|
{
|
||||||
|
CFile::deleteFile(downloadPath);
|
||||||
|
throw EDiskFullError(downloadPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != CURLE_OK || r < 200 || r >= 300)
|
||||||
|
{
|
||||||
|
CFile::deleteFile(downloadPath);
|
||||||
|
nldebug("Download failed '%s', retry in 1s", downloadUrl.c_str());
|
||||||
|
nlSleep(1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nldebug("Curl initialize failed");
|
||||||
|
fclose(fp);
|
||||||
|
CFile::deleteFile(downloadPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract into file
|
||||||
|
std::string unpackPath = filePath + ".extract." + toString(rand() * rand());
|
||||||
|
|
||||||
|
CHashKey outHash;
|
||||||
|
if (!unpackLZMA(downloadPath, unpackPath, outHash))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(outHash == hash))
|
||||||
|
{
|
||||||
|
std::string wantHashS = hash.toString();
|
||||||
|
std::string outHashS = outHash.toString();
|
||||||
|
nlwarning("Invalid SHA1 hash for file '%s', download has hash '%s'", wantHashS.c_str(), outHashS.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CFile::moveFile(filePath.c_str(), unpackPath.c_str()))
|
||||||
|
{
|
||||||
|
nldebug("Failed moving '%s' to '%s'", unpackPath.c_str(), filePath.c_str());
|
||||||
|
// in case downloaded from another thread
|
||||||
|
return CFile::fileExists(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace NLMISC */
|
||||||
|
|
||||||
|
/* end of file */
|
@ -0,0 +1,37 @@
|
|||||||
|
// NeL - MMORPG Framework <https://wiki.ryzom.dev/>
|
||||||
|
// Copyright (C) 2019 Jan BOON (jan.boon@kaetemi.be)
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "stdmisc.h"
|
||||||
|
|
||||||
|
// Project includes
|
||||||
|
#include <nel/misc/i_streamed_package_provider.h>
|
||||||
|
|
||||||
|
namespace NLMISC
|
||||||
|
{
|
||||||
|
|
||||||
|
IStreamedPackageProvider::IStreamedPackageProvider()
|
||||||
|
{
|
||||||
|
// init
|
||||||
|
}
|
||||||
|
|
||||||
|
IStreamedPackageProvider::~IStreamedPackageProvider()
|
||||||
|
{
|
||||||
|
// release
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace NLMISC */
|
||||||
|
|
||||||
|
/* end of file */
|
Loading…
Reference in New Issue