Lazily initialize AsyncSSLSocket EorBioMethod
authorSean Cannella <seanc@fb.com>
Fri, 1 May 2015 01:51:17 +0000 (18:51 -0700)
committerPraveen Kumar Ramakrishnan <praveenr@fb.com>
Tue, 12 May 2015 00:02:01 +0000 (17:02 -0700)
Summary:
Address another Android initialization crash by delaying
initialization of the EorBio method until first AsyncSSLSocket
construction.

Test Plan: existing tests

Reviewed By: pgriess@fb.com

Subscribers: net-systems@, ssl-diffs@, folly-diffs@, yfeldblum, chalfant, #csti

FB internal diff: D2036329

Tasks: 69255756925570

Signature: t1:2036329:1430444665:a3201f90860a34808a3cf3b42d530608c8a619a8

folly/io/async/AsyncSSLSocket.cpp
folly/io/async/AsyncSSLSocket.h

index a6e3307cb832ddea24297f0292e09ba3540f381a..cec2cdeb15ea6fd9703d76ebcd74b7ab67d204ce 100644 (file)
@@ -224,8 +224,7 @@ void setup_SSL_CTX(SSL_CTX *ctx) {
 
 BIO_METHOD eorAwareBioMethod;
 
-__attribute__((__constructor__))
-void initEorBioMethod(void) {
+void* initEorBioMethod(void) {
   memcpy(&eorAwareBioMethod, BIO_s_socket(), sizeof(eorAwareBioMethod));
   // override the bwrite method for MSG_EOR support
   eorAwareBioMethod.bwrite = AsyncSSLSocket::eorAwareBioWrite;
@@ -234,6 +233,10 @@ void initEorBioMethod(void) {
   // set here. openssl code seems to be checking ".type == BIO_TYPE_SOCKET" and
   // then have specific handlings. The eorAwareBioWrite should be compatible
   // with the one in openssl.
+
+  // Return something here to enable AsyncSSLSocket to call this method using
+  // a function-scoped static.
+  return nullptr;
 }
 
 } // anonymous namespace
@@ -254,7 +257,7 @@ AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext> &ctx,
     AsyncSocket(evb),
     ctx_(ctx),
     handshakeTimeout_(this, evb) {
-  setup_SSL_CTX(ctx_->getSSLCtx());
+  init();
 }
 
 /**
@@ -266,7 +269,7 @@ AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext>& ctx,
     server_(server),
     ctx_(ctx),
     handshakeTimeout_(this, evb) {
-  setup_SSL_CTX(ctx_->getSSLCtx());
+  init();
   if (server) {
     SSL_CTX_set_info_callback(ctx_->getSSLCtx(),
                               AsyncSSLSocket::sslInfoCallback);
@@ -281,11 +284,8 @@ AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext>& ctx,
 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext> &ctx,
                                  EventBase* evb,
                                  const std::string& serverName) :
-    AsyncSocket(evb),
-    ctx_(ctx),
-    handshakeTimeout_(this, evb),
-    tlsextHostname_(serverName) {
-  setup_SSL_CTX(ctx_->getSSLCtx());
+    AsyncSSLSocket(ctx, evb) {
+  tlsextHostname_ = serverName;
 }
 
 /**
@@ -295,11 +295,8 @@ AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext> &ctx,
 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext>& ctx,
                                  EventBase* evb, int fd,
                                  const std::string& serverName) :
-    AsyncSocket(evb, fd),
-    ctx_(ctx),
-    handshakeTimeout_(this, evb),
-    tlsextHostname_(serverName) {
-  setup_SSL_CTX(ctx_->getSSLCtx());
+    AsyncSSLSocket(ctx, evb, fd, false) {
+  tlsextHostname_ = serverName;
 }
 #endif
 
@@ -310,6 +307,13 @@ AsyncSSLSocket::~AsyncSSLSocket() {
           << sslState_ << ", events=" << eventFlags_ << ")";
 }
 
+void AsyncSSLSocket::init() {
+  // Do this here to ensure we initialize this once before any use of
+  // AsyncSSLSocket instances and not as part of library load.
+  static const auto eorAwareBioMethodInitializer = initEorBioMethod();
+  setup_SSL_CTX(ctx_->getSSLCtx());
+}
+
 void AsyncSSLSocket::closeNow() {
   // Close the SSL connection.
   if (ssl_ != nullptr && fd_ != -1) {
index ea7cbbdd5998b84143596702c5ee547a473aedd3..cce4c18b5fd3fa7d452178133e9552fee9a58595 100644 (file)
@@ -648,6 +648,10 @@ class AsyncSSLSocket : public virtual AsyncSocket {
     return minWriteSize_;
   }
 
+ private:
+
+  void init();
+
  protected:
 
   /**