Browse Source

rework early-random-seed a bit

David Rose 20 years ago
parent
commit
6c3f5aca2a

+ 41 - 8
panda/src/downloader/config_downloader.cxx

@@ -62,14 +62,6 @@ ConfigVariableDouble extractor_frequency
 ConfigVariableInt patcher_buffer_size
 ("patcher-buffer-size", 4096);
 
-ConfigVariableBool early_random_seed
-("early-random-seed", true,
- PRC_DESC("Configure this true (the default) to compute the SSL random seed "
-          "early on in the application (specifically, when the first "
-          "HTTPClient is created), or false to defer this until it is actually "
-          "needed, causing a delay the first time a https connection is "
-          "attempted."));
-
 ConfigVariableBool verify_ssl
 ("verify-ssl", true,
  PRC_DESC("Configure this true (the default) to insist on verifying all SSL "
@@ -156,9 +148,50 @@ ConfigVariableList http_username
           "If the server or realm is empty, they will match anything."));
 
 ConfigureFn(config_downloader) {
+  init_libdownloader();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_libdownloader
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_libdownloader() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
 #ifdef HAVE_SSL
   HTTPChannel::init_type();
 
+  // We need to define this here, rather than above, to guarantee that
+  // it has been initialized by the time we check it.
+  ConfigVariableBool early_random_seed
+    ("early-random-seed", false,
+     PRC_DESC("Configure this true to compute the SSL random seed "
+              "early on in the application (specifically, when the libpandaexpress "
+              "library is loaded), or false to defer this until it is actually "
+              "needed (which will be the first time you open an https connection "
+              "or otherwise use encryption services).  You can also call "
+              "HTTPClient::initialize_ssl() to "
+              "do this when you are ready.  The issue is that on Windows, "
+              "OpenSSL will attempt to "
+              "randomize its seed by crawling through the entire heap of "
+              "allocated memory, which can be extremely large in a Panda "
+              "application, especially if you have already opened a window and "
+              "started rendering; and so this can take as much as 30 seconds "
+              "or more.  For this reason it is best to initialize the random "
+              "seed at startup, when the application is still very small."));
+  if (early_random_seed) {
+    HTTPClient::init_random_seed();
+  }
+
   PandaSystem *ps = PandaSystem::get_global_ptr();
   ps->add_system("OpenSSL");
 #endif

+ 2 - 1
panda/src/downloader/config_downloader.h

@@ -46,7 +46,6 @@ extern ConfigVariableDouble extractor_frequency;
 
 extern ConfigVariableInt patcher_buffer_size;
 
-extern ConfigVariableBool early_random_seed;
 extern ConfigVariableBool verify_ssl;
 extern ConfigVariableString ssl_cipher_list;
 extern ConfigVariableList expected_ssl_server;
@@ -64,4 +63,6 @@ extern ConfigVariableFilename http_client_certificate_filename;
 extern ConfigVariableString http_client_certificate_passphrase;
 extern ConfigVariableList http_username;
 
+extern EXPCL_PANDAEXPRESS void init_libdownloader();
+
 #endif

+ 23 - 7
panda/src/downloader/httpClient.cxx

@@ -193,6 +193,29 @@ HTTPClient::
   unload_client_certificate();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: HTTPClient::init_random_seed
+//       Access: Published, Static
+//  Description: This may be called once, presumably at the beginning
+//               of an application, to initialize OpenSSL's random
+//               seed.  On Windows, it is particularly important to
+//               call this at startup if you are going to be perfoming
+//               any https operations or otherwise use encryption,
+//               since the Windows algorithm for getting a random seed
+//               takes 2-3 seconds at startup, but can take 30 seconds
+//               or more after you have opened a 3-D graphics window
+//               and started rendering.
+//
+//               There is no harm in calling this method multiple
+//               times, or in not calling it at all.
+////////////////////////////////////////////////////////////////////
+void HTTPClient::
+init_random_seed() {
+  // This call is sufficient to kick OpenSSL into generating its
+  // random seed if it hasn't already.
+  RAND_status();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: HTTPClient::set_proxy_spec
 //       Access: Published
@@ -1354,13 +1377,6 @@ unload_client_certificate() {
 void HTTPClient::
 initialize_ssl() {
   OpenSSL_add_all_algorithms();
-
-  // Call RAND_status() here to force the random number generator to
-  // initialize early.
-  if (early_random_seed) {
-    RAND_status();
-  }
-
   _ssl_initialized = true;
 }
 

+ 2 - 0
panda/src/downloader/httpClient.h

@@ -65,6 +65,8 @@ PUBLISHED:
   void operator = (const HTTPClient &copy);
   ~HTTPClient();
 
+  static void init_random_seed();
+
   void set_proxy_spec(const string &proxy_spec);
   string get_proxy_spec() const;