mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
panda3d.exe should check mirrors too
This commit is contained in:
parent
47b9e90b4c
commit
6c6f498ebb
@ -2700,15 +2700,11 @@ class Packager:
|
|||||||
xcontents = doc.FirstChildElement('contents')
|
xcontents = doc.FirstChildElement('contents')
|
||||||
if xcontents:
|
if xcontents:
|
||||||
xhost = xcontents.FirstChildElement('host')
|
xhost = xcontents.FirstChildElement('host')
|
||||||
while xhost:
|
if xhost:
|
||||||
he = self.HostEntry()
|
he = self.HostEntry()
|
||||||
he.loadXml(xhost, self)
|
he.loadXml(xhost, self)
|
||||||
self.hosts[he.url] = he
|
self.hosts[he.url] = he
|
||||||
xhost = xhost.NextSiblingElement('host')
|
self.host = he.url
|
||||||
|
|
||||||
host = xcontents.Attribute('host')
|
|
||||||
if host:
|
|
||||||
self.host = host
|
|
||||||
|
|
||||||
xpackage = xcontents.FirstChildElement('package')
|
xpackage = xcontents.FirstChildElement('package')
|
||||||
while xpackage:
|
while xpackage:
|
||||||
@ -2736,7 +2732,6 @@ class Packager:
|
|||||||
|
|
||||||
xcontents = TiXmlElement('contents')
|
xcontents = TiXmlElement('contents')
|
||||||
if self.host:
|
if self.host:
|
||||||
xcontents.SetAttribute('host', self.host)
|
|
||||||
he = self.hosts.get(self.host, None)
|
he = self.hosts.get(self.host, None)
|
||||||
if he:
|
if he:
|
||||||
xhost = he.makeXml(packager = self)
|
xhost = he.makeXml(packager = self)
|
||||||
|
@ -125,7 +125,7 @@ static void unload_dso();
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool
|
bool
|
||||||
load_plugin(const string &p3d_plugin_filename,
|
load_plugin(const string &p3d_plugin_filename,
|
||||||
const string &contents_filename, const string &download_url,
|
const string &contents_filename, const string &host_url,
|
||||||
bool verify_contents, const string &platform,
|
bool verify_contents, const string &platform,
|
||||||
const string &log_directory, const string &log_basename,
|
const string &log_directory, const string &log_basename,
|
||||||
bool trusted_environment, bool console_environment,
|
bool trusted_environment, bool console_environment,
|
||||||
@ -311,7 +311,7 @@ load_plugin(const string &p3d_plugin_filename,
|
|||||||
plugin_loaded = true;
|
plugin_loaded = true;
|
||||||
|
|
||||||
if (!P3D_initialize(P3D_API_VERSION, contents_filename.c_str(),
|
if (!P3D_initialize(P3D_API_VERSION, contents_filename.c_str(),
|
||||||
download_url.c_str(), verify_contents, platform.c_str(),
|
host_url.c_str(), verify_contents, platform.c_str(),
|
||||||
log_directory.c_str(), log_basename.c_str(),
|
log_directory.c_str(), log_basename.c_str(),
|
||||||
trusted_environment, console_environment)) {
|
trusted_environment, console_environment)) {
|
||||||
// Oops, failure to initialize.
|
// Oops, failure to initialize.
|
||||||
|
@ -61,7 +61,7 @@ extern P3D_instance_handle_event_func *P3D_instance_handle_event;
|
|||||||
string get_plugin_basename();
|
string get_plugin_basename();
|
||||||
bool
|
bool
|
||||||
load_plugin(const string &p3d_plugin_filename,
|
load_plugin(const string &p3d_plugin_filename,
|
||||||
const string &contents_filename, const string &download_url,
|
const string &contents_filename, const string &host_url,
|
||||||
bool verify_contents, const string &platform,
|
bool verify_contents, const string &platform,
|
||||||
const string &log_directory, const string &log_basename,
|
const string &log_directory, const string &log_basename,
|
||||||
bool trusted_environment, bool console_environment,
|
bool trusted_environment, bool console_environment,
|
||||||
|
@ -169,7 +169,7 @@ P3DInstanceManager::
|
|||||||
// redownloaded.
|
// redownloaded.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool P3DInstanceManager::
|
bool P3DInstanceManager::
|
||||||
initialize(const string &contents_filename, const string &download_url,
|
initialize(const string &contents_filename, const string &host_url,
|
||||||
bool verify_contents,
|
bool verify_contents,
|
||||||
const string &platform, const string &log_directory,
|
const string &platform, const string &log_directory,
|
||||||
const string &log_basename, bool trusted_environment,
|
const string &log_basename, bool trusted_environment,
|
||||||
@ -312,7 +312,7 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
<< ", _temp_directory = " << _temp_directory
|
<< ", _temp_directory = " << _temp_directory
|
||||||
<< ", platform = " << _platform
|
<< ", platform = " << _platform
|
||||||
<< ", contents_filename = " << contents_filename
|
<< ", contents_filename = " << contents_filename
|
||||||
<< ", download_url = " << download_url
|
<< ", host_url = " << host_url
|
||||||
<< ", verify_contents = " << verify_contents
|
<< ", verify_contents = " << verify_contents
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
@ -330,10 +330,10 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
_is_initialized = true;
|
_is_initialized = true;
|
||||||
|
|
||||||
if (!_verify_contents &&
|
if (!_verify_contents &&
|
||||||
!download_url.empty() && !contents_filename.empty()) {
|
!host_url.empty() && !contents_filename.empty()) {
|
||||||
// Attempt to pre-read the supplied contents.xml file, to avoid an
|
// Attempt to pre-read the supplied contents.xml file, to avoid an
|
||||||
// unnecessary download later.
|
// unnecessary download later.
|
||||||
P3DHost *host = get_host(download_url);
|
P3DHost *host = get_host(host_url);
|
||||||
if (!host->read_contents_file(contents_filename)) {
|
if (!host->read_contents_file(contents_filename)) {
|
||||||
nout << "Couldn't read " << contents_filename << "\n";
|
nout << "Couldn't read " << contents_filename << "\n";
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
bool initialize(const string &contents_filename,
|
bool initialize(const string &contents_filename,
|
||||||
const string &download_url,
|
const string &host_url,
|
||||||
bool verify_contents,
|
bool verify_contents,
|
||||||
const string &platform,
|
const string &platform,
|
||||||
const string &log_directory,
|
const string &log_directory,
|
||||||
|
@ -35,7 +35,7 @@ LOCK _api_lock;
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
P3D_initialize(int api_version, const char *contents_filename,
|
P3D_initialize(int api_version, const char *contents_filename,
|
||||||
const char *download_url, bool verify_contents,
|
const char *host_url, bool verify_contents,
|
||||||
const char *platform,
|
const char *platform,
|
||||||
const char *log_directory, const char *log_basename,
|
const char *log_directory, const char *log_basename,
|
||||||
bool trusted_environment, bool console_environment) {
|
bool trusted_environment, bool console_environment) {
|
||||||
@ -54,8 +54,8 @@ P3D_initialize(int api_version, const char *contents_filename,
|
|||||||
contents_filename = "";
|
contents_filename = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (download_url == NULL){
|
if (host_url == NULL){
|
||||||
download_url = "";
|
host_url = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platform == NULL) {
|
if (platform == NULL) {
|
||||||
@ -71,7 +71,7 @@ P3D_initialize(int api_version, const char *contents_filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
bool result = inst_mgr->initialize(contents_filename, download_url,
|
bool result = inst_mgr->initialize(contents_filename, host_url,
|
||||||
verify_contents, platform,
|
verify_contents, platform,
|
||||||
log_directory, log_basename,
|
log_directory, log_basename,
|
||||||
trusted_environment, console_environment);
|
trusted_environment, console_environment);
|
||||||
|
@ -95,7 +95,7 @@ extern "C" {
|
|||||||
file that has already been downloaded and verified from the server.
|
file that has already been downloaded and verified from the server.
|
||||||
If this is NULL, a new file will be downloaded as needed.
|
If this is NULL, a new file will be downloaded as needed.
|
||||||
|
|
||||||
If download_url is not NULL or empty, it specifies the root URL of
|
If host_url is not NULL or empty, it specifies the root URL of
|
||||||
the download server that provided the contents_filename.
|
the download server that provided the contents_filename.
|
||||||
|
|
||||||
If verify_contents is true, it means that the download server will
|
If verify_contents is true, it means that the download server will
|
||||||
@ -141,7 +141,7 @@ extern "C" {
|
|||||||
immediately unload the DLL and (if possible) download a new one. */
|
immediately unload the DLL and (if possible) download a new one. */
|
||||||
typedef bool
|
typedef bool
|
||||||
P3D_initialize_func(int api_version, const char *contents_filename,
|
P3D_initialize_func(int api_version, const char *contents_filename,
|
||||||
const char *download_url, bool verify_contents,
|
const char *host_url, bool verify_contents,
|
||||||
const char *platform,
|
const char *platform,
|
||||||
const char *log_directory, const char *log_basename,
|
const char *log_directory, const char *log_basename,
|
||||||
bool trusted_environment, bool console_environment);
|
bool trusted_environment, bool console_environment);
|
||||||
|
@ -686,6 +686,43 @@ variant_to_p3dobj(const NPVariant *variant) {
|
|||||||
return P3D_new_none_object();
|
return P3D_new_none_object();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPInstance::find_host
|
||||||
|
// Access: Private
|
||||||
|
// Description: Scans the <contents> element for the matching <host>
|
||||||
|
// element.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPInstance::
|
||||||
|
find_host(TiXmlElement *xcontents) {
|
||||||
|
string host_url = PANDA_PACKAGE_HOST_URL;
|
||||||
|
TiXmlElement *xhost = xcontents->FirstChildElement("host");
|
||||||
|
if (xhost != NULL) {
|
||||||
|
const char *url = xhost->Attribute("url");
|
||||||
|
if (url != NULL && host_url == string(url)) {
|
||||||
|
// We're the primary host. This is the normal case.
|
||||||
|
read_xhost(xhost);
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// We're not the primary host; perhaps we're an alternate host.
|
||||||
|
TiXmlElement *xalthost = xhost->FirstChildElement("alt_host");
|
||||||
|
while (xalthost != NULL) {
|
||||||
|
const char *url = xalthost->Attribute("url");
|
||||||
|
if (url != NULL && host_url == string(url)) {
|
||||||
|
// Yep, we're this alternate host.
|
||||||
|
read_xhost(xhost);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xalthost = xalthost->NextSiblingElement("alt_host");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hmm, didn't find the URL we used mentioned. Assume we're the
|
||||||
|
// primary host.
|
||||||
|
read_xhost(xhost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPInstance::read_xhost
|
// Function: PPInstance::read_xhost
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -841,28 +878,7 @@ read_contents_file(const string &contents_filename) {
|
|||||||
if (xcontents != NULL) {
|
if (xcontents != NULL) {
|
||||||
// Look for the <host> entry; it might point us at a different
|
// Look for the <host> entry; it might point us at a different
|
||||||
// download URL, and it might mention some mirrors.
|
// download URL, and it might mention some mirrors.
|
||||||
string host_url = PANDA_PACKAGE_HOST_URL;
|
find_host(xcontents);
|
||||||
TiXmlElement *xhost = xcontents->FirstChildElement("host");
|
|
||||||
if (xhost != NULL) {
|
|
||||||
const char *url = xhost->Attribute("url");
|
|
||||||
if (url != NULL && host_url == string(url)) {
|
|
||||||
// We're the primary host. This is the normal case.
|
|
||||||
read_xhost(xhost);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// We're not the primary host; perhaps we're an alternate host.
|
|
||||||
TiXmlElement *xalthost = xhost->FirstChildElement("alt_host");
|
|
||||||
while (xalthost != NULL) {
|
|
||||||
const char *url = xalthost->Attribute("url");
|
|
||||||
if (url != NULL && host_url == string(url)) {
|
|
||||||
// Yep, we're this alternate host.
|
|
||||||
read_xhost(xhost);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
xalthost = xalthost->NextSiblingElement("alt_host");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now look for the core API package.
|
// Now look for the core API package.
|
||||||
TiXmlElement *xpackage = xcontents->FirstChildElement("package");
|
TiXmlElement *xpackage = xcontents->FirstChildElement("package");
|
||||||
|
@ -64,6 +64,7 @@ public:
|
|||||||
static void output_np_variant(ostream &out, const NPVariant &result);
|
static void output_np_variant(ostream &out, const NPVariant &result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void find_host(TiXmlElement *xcontents);
|
||||||
void read_xhost(TiXmlElement *xhost);
|
void read_xhost(TiXmlElement *xhost);
|
||||||
void add_mirror(string mirror_url);
|
void add_mirror(string mirror_url);
|
||||||
void choose_random_mirrors(vector<string> &result, int num_mirrors);
|
void choose_random_mirrors(vector<string> &result, int num_mirrors);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
@ -52,6 +53,10 @@ Panda3D() {
|
|||||||
_root_dir = find_root_dir();
|
_root_dir = find_root_dir();
|
||||||
_reporting_download = false;
|
_reporting_download = false;
|
||||||
_enable_security = false;
|
_enable_security = false;
|
||||||
|
|
||||||
|
// Seed the lame random number generator in rand(); we use it to
|
||||||
|
// select a mirror for downloading.
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -71,10 +76,10 @@ run(int argc, char *argv[]) {
|
|||||||
const char *optstr = "+mu:M:Sp:fw:t:s:o:l:ih";
|
const char *optstr = "+mu:M:Sp:fw:t:s:o:l:ih";
|
||||||
|
|
||||||
bool allow_multiple = false;
|
bool allow_multiple = false;
|
||||||
string download_url = PANDA_PACKAGE_HOST_URL;
|
_host_url = PANDA_PACKAGE_HOST_URL;
|
||||||
string super_mirror_url;
|
string super_mirror_url;
|
||||||
string this_platform = DTOOL_PLATFORM;
|
_this_platform = DTOOL_PLATFORM;
|
||||||
bool verify_contents = false;
|
_verify_contents = false;
|
||||||
|
|
||||||
P3D_window_type window_type = P3D_WT_toplevel;
|
P3D_window_type window_type = P3D_WT_toplevel;
|
||||||
int win_x = 0, win_y = 0;
|
int win_x = 0, win_y = 0;
|
||||||
@ -89,7 +94,7 @@ run(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
download_url = optarg;
|
_host_url = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
@ -101,11 +106,11 @@ run(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
this_platform = optarg;
|
_this_platform = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
verify_contents = true;
|
_verify_contents = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
@ -192,10 +197,12 @@ run(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the download URL ends with a slash.
|
// Set host_url_prefix to end with a slash.
|
||||||
if (!download_url.empty() && download_url[download_url.length() - 1] != '/') {
|
_host_url_prefix = _host_url;
|
||||||
download_url += '/';
|
if (!_host_url_prefix.empty() && _host_url_prefix[_host_url_prefix.length() - 1] != '/') {
|
||||||
|
_host_url_prefix += '/';
|
||||||
}
|
}
|
||||||
|
_download_url_prefix = _host_url_prefix;
|
||||||
|
|
||||||
// If the "super mirror" URL is a filename, convert it to a file:// url.
|
// If the "super mirror" URL is a filename, convert it to a file:// url.
|
||||||
if (!super_mirror_url.empty()) {
|
if (!super_mirror_url.empty()) {
|
||||||
@ -210,9 +217,15 @@ run(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
super_mirror_url = "file://" + path;
|
super_mirror_url = "file://" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// And make sure the super_mirror_url_prefix ends with a slash.
|
||||||
|
_super_mirror_url_prefix = super_mirror_url;
|
||||||
|
if (!_super_mirror_url_prefix.empty() && _super_mirror_url_prefix[_super_mirror_url_prefix.length() - 1] != '/') {
|
||||||
|
_super_mirror_url_prefix += '/';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_plugin(download_url, this_platform, verify_contents)) {
|
if (!get_plugin()) {
|
||||||
cerr << "Unable to load Panda3D plugin.\n";
|
cerr << "Unable to load Panda3D plugin.\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -403,18 +416,48 @@ run(int argc, char *argv[]) {
|
|||||||
// true on success, false on failure.
|
// true on success, false on failure.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool Panda3D::
|
bool Panda3D::
|
||||||
get_plugin(const string &download_url, const string &this_platform,
|
get_plugin() {
|
||||||
bool verify_contents) {
|
|
||||||
// First, look for the existing contents.xml file.
|
// First, look for the existing contents.xml file.
|
||||||
Filename contents_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
|
Filename contents_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
|
||||||
if (!verify_contents && read_contents_file(contents_filename, download_url, this_platform, verify_contents)) {
|
if (!_verify_contents && read_contents_file(contents_filename)) {
|
||||||
// Got the file, and it's good.
|
// Got the file, and it's good.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Couldn't read it, so go get it.
|
// Couldn't read it, so go get it.
|
||||||
|
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||||
|
|
||||||
|
// Try the super_mirror first.
|
||||||
|
if (!_super_mirror_url_prefix.empty()) {
|
||||||
|
// We don't bother putting a uniquifying query string when we're
|
||||||
|
// downloading this file from the super_mirror. The super_mirror
|
||||||
|
// is by definition a cache, so it doesn't make sense to bust
|
||||||
|
// caches here.
|
||||||
|
string url = _super_mirror_url_prefix + "contents.xml";
|
||||||
|
PT(HTTPChannel) channel = http->make_channel(false);
|
||||||
|
channel->get_document(url);
|
||||||
|
|
||||||
|
Filename tempfile = Filename::temporary("", "p3d_");
|
||||||
|
if (!channel->download_to_file(tempfile)) {
|
||||||
|
cerr << "Unable to download " << url << "\n";
|
||||||
|
tempfile.unlink();
|
||||||
|
} else {
|
||||||
|
// Successfully downloaded from the super_mirror; move it into
|
||||||
|
// place and try to read it.
|
||||||
|
contents_filename.make_dir();
|
||||||
|
contents_filename.unlink();
|
||||||
|
tempfile.rename_to(contents_filename);
|
||||||
|
if (read_contents_file(contents_filename)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failed to download from the super_mirror.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go download contents.xml from the actual host.
|
||||||
ostringstream strm;
|
ostringstream strm;
|
||||||
strm << download_url << "contents.xml";
|
strm << _host_url_prefix << "contents.xml";
|
||||||
// Append a uniquifying query string to the URL to force the
|
// Append a uniquifying query string to the URL to force the
|
||||||
// download to go all the way through any caches. We use the time
|
// download to go all the way through any caches. We use the time
|
||||||
// in seconds; that's unique enough.
|
// in seconds; that's unique enough.
|
||||||
@ -425,8 +468,7 @@ get_plugin(const string &download_url, const string &this_platform,
|
|||||||
// since we have an interface for that via HTTPChannel.
|
// since we have an interface for that via HTTPChannel.
|
||||||
DocumentSpec request(url);
|
DocumentSpec request(url);
|
||||||
request.set_cache_control(DocumentSpec::CC_no_cache);
|
request.set_cache_control(DocumentSpec::CC_no_cache);
|
||||||
|
|
||||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
|
||||||
PT(HTTPChannel) channel = http->make_channel(false);
|
PT(HTTPChannel) channel = http->make_channel(false);
|
||||||
channel->get_document(request);
|
channel->get_document(request);
|
||||||
|
|
||||||
@ -447,9 +489,9 @@ get_plugin(const string &download_url, const string &this_platform,
|
|||||||
|
|
||||||
// Since we had to download some of it, might as well ask the core
|
// Since we had to download some of it, might as well ask the core
|
||||||
// API to check all of it.
|
// API to check all of it.
|
||||||
verify_contents = true;
|
_verify_contents = true;
|
||||||
|
|
||||||
return read_contents_file(contents_filename, download_url, this_platform, verify_contents);
|
return read_contents_file(contents_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -460,40 +502,158 @@ get_plugin(const string &download_url, const string &this_platform,
|
|||||||
// possible. Returns true on success, false on failure.
|
// possible. Returns true on success, false on failure.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool Panda3D::
|
bool Panda3D::
|
||||||
read_contents_file(Filename contents_filename, const string &download_url,
|
read_contents_file(const Filename &contents_filename) {
|
||||||
const string &this_platform, bool verify_contents) {
|
string os_contents_filename = contents_filename.to_os_specific();
|
||||||
ifstream in;
|
TiXmlDocument doc(os_contents_filename.c_str());
|
||||||
contents_filename.set_text();
|
if (!doc.LoadFile()) {
|
||||||
if (!contents_filename.open_read(in)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TiXmlDocument doc;
|
|
||||||
in >> doc;
|
|
||||||
|
|
||||||
TiXmlElement *xcontents = doc.FirstChildElement("contents");
|
TiXmlElement *xcontents = doc.FirstChildElement("contents");
|
||||||
if (xcontents != NULL) {
|
if (xcontents != NULL) {
|
||||||
|
// Look for the <host> entry; it might point us at a different
|
||||||
|
// download URL, and it might mention some mirrors.
|
||||||
|
find_host(xcontents);
|
||||||
|
|
||||||
|
// Now look for the core API package.
|
||||||
TiXmlElement *xpackage = xcontents->FirstChildElement("package");
|
TiXmlElement *xpackage = xcontents->FirstChildElement("package");
|
||||||
while (xpackage != NULL) {
|
while (xpackage != NULL) {
|
||||||
const char *name = xpackage->Attribute("name");
|
const char *name = xpackage->Attribute("name");
|
||||||
if (name != NULL && strcmp(name, "coreapi") == 0) {
|
if (name != NULL && strcmp(name, "coreapi") == 0) {
|
||||||
const char *xplatform = xpackage->Attribute("platform");
|
const char *platform = xpackage->Attribute("platform");
|
||||||
if (xplatform != NULL && strcmp(xplatform, this_platform.c_str()) == 0) {
|
if (platform != NULL && _this_platform == string(platform)) {
|
||||||
return get_core_api(contents_filename, download_url,
|
return get_core_api(contents_filename, xpackage);
|
||||||
this_platform, verify_contents, xpackage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xpackage = xpackage->NextSiblingElement("package");
|
xpackage = xpackage->NextSiblingElement("package");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Couldn't find the coreapi plugin description.
|
// Couldn't find the coreapi package description.
|
||||||
cerr << "No coreapi plugin defined in contents file for "
|
nout << "No coreapi package defined in contents file for "
|
||||||
<< this_platform << "\n";
|
<< _this_platform << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Panda3D::find_host
|
||||||
|
// Access: Private
|
||||||
|
// Description: Scans the <contents> element for the matching <host>
|
||||||
|
// element.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void Panda3D::
|
||||||
|
find_host(TiXmlElement *xcontents) {
|
||||||
|
TiXmlElement *xhost = xcontents->FirstChildElement("host");
|
||||||
|
if (xhost != NULL) {
|
||||||
|
const char *url = xhost->Attribute("url");
|
||||||
|
if (url != NULL && _host_url == string(url)) {
|
||||||
|
// We're the primary host. This is the normal case.
|
||||||
|
read_xhost(xhost);
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// We're not the primary host; perhaps we're an alternate host.
|
||||||
|
TiXmlElement *xalthost = xhost->FirstChildElement("alt_host");
|
||||||
|
while (xalthost != NULL) {
|
||||||
|
const char *url = xalthost->Attribute("url");
|
||||||
|
if (url != NULL && _host_url == string(url)) {
|
||||||
|
// Yep, we're this alternate host.
|
||||||
|
read_xhost(xhost);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xalthost = xalthost->NextSiblingElement("alt_host");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hmm, didn't find the URL we used mentioned. Assume we're the
|
||||||
|
// primary host.
|
||||||
|
read_xhost(xhost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Panda3D::read_xhost
|
||||||
|
// Access: Private
|
||||||
|
// Description: Reads the host data from the <host> (or <alt_host>)
|
||||||
|
// entry in the contents.xml file.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void Panda3D::
|
||||||
|
read_xhost(TiXmlElement *xhost) {
|
||||||
|
// Get the "download" URL, which is the source from which we
|
||||||
|
// download everything other than the contents.xml file.
|
||||||
|
const char *download_url = xhost->Attribute("download_url");
|
||||||
|
if (download_url == NULL) {
|
||||||
|
download_url = xhost->Attribute("url");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (download_url != NULL) {
|
||||||
|
_download_url_prefix = download_url;
|
||||||
|
} else {
|
||||||
|
_download_url_prefix = _host_url_prefix;
|
||||||
|
}
|
||||||
|
if (!_download_url_prefix.empty()) {
|
||||||
|
if (_download_url_prefix[_download_url_prefix.size() - 1] != '/') {
|
||||||
|
_download_url_prefix += "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TiXmlElement *xmirror = xhost->FirstChildElement("mirror");
|
||||||
|
while (xmirror != NULL) {
|
||||||
|
const char *url = xmirror->Attribute("url");
|
||||||
|
if (url != NULL) {
|
||||||
|
add_mirror(url);
|
||||||
|
}
|
||||||
|
xmirror = xmirror->NextSiblingElement("mirror");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Panda3D::add_mirror
|
||||||
|
// Access: Private
|
||||||
|
// Description: Adds a new URL to serve as a mirror for this host.
|
||||||
|
// The mirrors will be consulted first, before
|
||||||
|
// consulting the host directly.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void Panda3D::
|
||||||
|
add_mirror(string mirror_url) {
|
||||||
|
// Ensure the URL ends in a slash.
|
||||||
|
if (!mirror_url.empty() && mirror_url[mirror_url.size() - 1] != '/') {
|
||||||
|
mirror_url += '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add it to the _mirrors list, but only if it's not already
|
||||||
|
// there.
|
||||||
|
if (find(_mirrors.begin(), _mirrors.end(), mirror_url) == _mirrors.end()) {
|
||||||
|
_mirrors.push_back(mirror_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Panda3D::choose_random_mirrors
|
||||||
|
// Access: Public
|
||||||
|
// Description: Selects num_mirrors elements, chosen at random, from
|
||||||
|
// the _mirrors list. Adds the selected mirrors to
|
||||||
|
// result. If there are fewer than num_mirrors elements
|
||||||
|
// in the list, adds only as many mirrors as we can get.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void Panda3D::
|
||||||
|
choose_random_mirrors(vector_string &result, int num_mirrors) {
|
||||||
|
pvector<size_t> selected;
|
||||||
|
|
||||||
|
size_t num_to_select = min(_mirrors.size(), (size_t)num_mirrors);
|
||||||
|
while (num_to_select > 0) {
|
||||||
|
size_t i = (size_t)(((double)rand() / (double)RAND_MAX) * _mirrors.size());
|
||||||
|
while (find(selected.begin(), selected.end(), i) != selected.end()) {
|
||||||
|
// Already found this i, find a new one.
|
||||||
|
i = (size_t)(((double)rand() / (double)RAND_MAX) * _mirrors.size());
|
||||||
|
}
|
||||||
|
selected.push_back(i);
|
||||||
|
result.push_back(_mirrors[i]);
|
||||||
|
--num_to_select;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Panda3D::get_core_api
|
// Function: Panda3D::get_core_api
|
||||||
@ -503,33 +663,79 @@ read_contents_file(Filename contents_filename, const string &download_url,
|
|||||||
// if necessary.
|
// if necessary.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool Panda3D::
|
bool Panda3D::
|
||||||
get_core_api(const Filename &contents_filename, const string &download_url,
|
get_core_api(const Filename &contents_filename, TiXmlElement *xpackage) {
|
||||||
const string &this_platform, bool verify_contents,
|
|
||||||
TiXmlElement *xpackage) {
|
|
||||||
_core_api_dll.load_xml(xpackage);
|
_core_api_dll.load_xml(xpackage);
|
||||||
|
|
||||||
if (!_core_api_dll.quick_verify(_root_dir)) {
|
if (!_core_api_dll.quick_verify(_root_dir)) {
|
||||||
// The DLL file needs to be downloaded. Go get it.
|
// The DLL file needs to be downloaded. Build up our list of
|
||||||
string url = download_url;
|
// URL's to attempt to download it from, in reverse order.
|
||||||
|
string url;
|
||||||
|
vector_string core_urls;
|
||||||
|
|
||||||
|
// Our last act of desperation: hit the original host, with a
|
||||||
|
// query uniquifier, to break through any caches.
|
||||||
|
ostringstream strm;
|
||||||
|
strm << _download_url_prefix << _core_api_dll.get_filename()
|
||||||
|
<< "?" << time(NULL);
|
||||||
|
url = strm.str();
|
||||||
|
core_urls.push_back(url);
|
||||||
|
|
||||||
|
// Before we try that, we'll hit the original host, without a
|
||||||
|
// uniquifier.
|
||||||
|
url = _download_url_prefix;
|
||||||
url += _core_api_dll.get_filename();
|
url += _core_api_dll.get_filename();
|
||||||
|
core_urls.push_back(url);
|
||||||
Filename pathname = Filename::from_os_specific(_core_api_dll.get_pathname(_root_dir));
|
|
||||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
// And before we try that, we'll try two mirrors, at random.
|
||||||
PT(HTTPChannel) channel = http->get_document(url);
|
vector_string mirrors;
|
||||||
pathname.make_dir();
|
choose_random_mirrors(mirrors, 2);
|
||||||
if (!channel->download_to_file(pathname)) {
|
for (vector_string::iterator si = mirrors.begin();
|
||||||
cerr << "Unable to download " << url << "\n";
|
si != mirrors.end();
|
||||||
return false;
|
++si) {
|
||||||
|
url = (*si) + _core_api_dll.get_filename();
|
||||||
|
core_urls.push_back(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_core_api_dll.full_verify(_root_dir)) {
|
// The very first thing we'll try is the super_mirror, if we have
|
||||||
cerr << "Mismatched download for " << url << "\n";
|
// one.
|
||||||
|
if (!_super_mirror_url_prefix.empty()) {
|
||||||
|
url = _super_mirror_url_prefix + _core_api_dll.get_filename();
|
||||||
|
core_urls.push_back(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now pick URL's off the list, and try them, until we have
|
||||||
|
// success.
|
||||||
|
Filename pathname = Filename::from_os_specific(_core_api_dll.get_pathname(_root_dir));
|
||||||
|
pathname.make_dir();
|
||||||
|
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
while (!core_urls.empty()) {
|
||||||
|
url = core_urls.back();
|
||||||
|
core_urls.pop_back();
|
||||||
|
|
||||||
|
PT(HTTPChannel) channel = http->get_document(url);
|
||||||
|
if (!channel->download_to_file(pathname)) {
|
||||||
|
cerr << "Unable to download " << url << "\n";
|
||||||
|
|
||||||
|
} else if (!_core_api_dll.full_verify(_root_dir)) {
|
||||||
|
cerr << "Mismatched download for " << url << "\n";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// successfully downloaded!
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
cerr << "Couldn't download core API.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we had to download some of it, might as well ask the core
|
// Since we had to download some of it, might as well ask the core
|
||||||
// API to check all of it.
|
// API to check all of it.
|
||||||
verify_contents = true;
|
_verify_contents = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we've got the DLL. Load it.
|
// Now we've got the DLL. Load it.
|
||||||
@ -556,7 +762,7 @@ get_core_api(const Filename &contents_filename, const string &download_url,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!load_plugin(pathname, contents_filename.to_os_specific(),
|
if (!load_plugin(pathname, contents_filename.to_os_specific(),
|
||||||
download_url, verify_contents, this_platform, _log_dirname,
|
_host_url, _verify_contents, _this_platform, _log_dirname,
|
||||||
_log_basename, trusted_environment, console_environment,
|
_log_basename, trusted_environment, console_environment,
|
||||||
cerr)) {
|
cerr)) {
|
||||||
cerr << "Unable to launch core API in " << pathname << "\n" << flush;
|
cerr << "Unable to launch core API in " << pathname << "\n" << flush;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "ramfile.h"
|
#include "ramfile.h"
|
||||||
#include "fileSpec.h"
|
#include "fileSpec.h"
|
||||||
#include "pset.h"
|
#include "pset.h"
|
||||||
|
#include "vector_string.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : Panda3D
|
// Class : Panda3D
|
||||||
@ -42,14 +43,13 @@ public:
|
|||||||
int run(int argc, char *argv[]);
|
int run(int argc, char *argv[]);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool get_plugin(const string &download_url, const string &this_platform,
|
bool get_plugin();
|
||||||
bool verify_contents);
|
bool read_contents_file(const Filename &contents_filename);
|
||||||
bool read_contents_file(Filename contents_filename,
|
void find_host(TiXmlElement *xcontents);
|
||||||
const string &download_url,
|
void read_xhost(TiXmlElement *xhost);
|
||||||
const string &this_platform, bool verify_contents);
|
void add_mirror(string mirror_url);
|
||||||
bool get_core_api(const Filename &contents_filename,
|
void choose_random_mirrors(vector_string &result, int num_mirrors);
|
||||||
const string &download_url, const string &this_platform,
|
bool get_core_api(const Filename &contents_filename, TiXmlElement *xplugin);
|
||||||
bool verify_contents, TiXmlElement *xplugin);
|
|
||||||
void run_getters();
|
void run_getters();
|
||||||
void handle_request(P3D_request *request);
|
void handle_request(P3D_request *request);
|
||||||
void make_parent_window(P3D_window_handle &parent_window,
|
void make_parent_window(P3D_window_handle &parent_window,
|
||||||
@ -79,6 +79,16 @@ private:
|
|||||||
string _root_dir;
|
string _root_dir;
|
||||||
string _log_dirname;
|
string _log_dirname;
|
||||||
string _log_basename;
|
string _log_basename;
|
||||||
|
string _this_platform;
|
||||||
|
bool _verify_contents;
|
||||||
|
|
||||||
|
string _host_url;
|
||||||
|
string _super_mirror_url_prefix;
|
||||||
|
string _host_url_prefix;
|
||||||
|
string _download_url_prefix;
|
||||||
|
typedef pvector<string> Mirrors;
|
||||||
|
Mirrors _mirrors;
|
||||||
|
|
||||||
FileSpec _core_api_dll;
|
FileSpec _core_api_dll;
|
||||||
bool _reporting_download;
|
bool _reporting_download;
|
||||||
bool _enable_security;
|
bool _enable_security;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user