panda3d.exe should check mirrors too

This commit is contained in:
David Rose 2009-10-07 22:25:03 +00:00
parent 47b9e90b4c
commit 6c6f498ebb
11 changed files with 330 additions and 102 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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,

View File

@ -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";
} }

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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;

View File

@ -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;