#include <folly/Format.h>
#include <folly/Memory.h>
#include <folly/Random.h>
+#include <folly/SharedMutex.h>
#include <folly/SpinLock.h>
+#include <folly/ThreadId.h>
// ---------------------------------------------------------------------
// SSLContext implementation
}
void SSLContext::ciphers(const std::string& ciphers) {
- providedCiphersString_ = ciphers;
setCiphersOrThrow(ciphers);
}
if (rc == 0) {
throw std::runtime_error("SSL_CTX_set_cipher_list: " + getErrors());
}
+ providedCiphersString_ = ciphers;
}
void SSLContext::setVerificationOption(const SSLContext::SSLVerifyPeerEnum&
lockType(inLockType) {
}
- void lock() {
+ void lock(bool read) {
if (lockType == SSLContext::LOCK_MUTEX) {
mutex.lock();
} else if (lockType == SSLContext::LOCK_SPINLOCK) {
spinLock.lock();
+ } else if (lockType == SSLContext::LOCK_SHAREDMUTEX) {
+ if (read) {
+ sharedMutex.lock_shared();
+ } else {
+ sharedMutex.lock();
+ }
}
// lockType == LOCK_NONE, no-op
}
- void unlock() {
+ void unlock(bool read) {
if (lockType == SSLContext::LOCK_MUTEX) {
mutex.unlock();
} else if (lockType == SSLContext::LOCK_SPINLOCK) {
spinLock.unlock();
+ } else if (lockType == SSLContext::LOCK_SHAREDMUTEX) {
+ if (read) {
+ sharedMutex.unlock_shared();
+ } else {
+ sharedMutex.unlock();
+ }
}
// lockType == LOCK_NONE, no-op
}
SSLContext::SSLLockType lockType;
folly::SpinLock spinLock{};
std::mutex mutex;
+ SharedMutex sharedMutex;
};
// Statics are unsafe in environments that call exit().
static void callbackLocking(int mode, int n, const char*, int) {
if (mode & CRYPTO_LOCK) {
- locks()[size_t(n)].lock();
+ locks()[size_t(n)].lock(mode & CRYPTO_READ);
} else {
- locks()[size_t(n)].unlock();
+ locks()[size_t(n)].unlock(mode & CRYPTO_READ);
}
}
static unsigned long callbackThreadID() {
- return static_cast<unsigned long>(
-#ifdef __APPLE__
- pthread_mach_thread_np(pthread_self())
-#elif _MSC_VER
- pthread_getw32threadid_np(pthread_self())
-#else
- pthread_self()
-#endif
- );
+ return static_cast<unsigned long>(folly::getCurrentThreadID());
}
static CRYPTO_dynlock_value* dyn_create(const char*, int) {
delete lock;
}
-void SSLContext::setSSLLockTypes(std::map<int, SSLLockType> inLockTypes) {
+void SSLContext::setSSLLockTypesLocked(std::map<int, SSLLockType> inLockTypes) {
lockTypes() = inLockTypes;
}
+void SSLContext::setSSLLockTypes(std::map<int, SSLLockType> inLockTypes) {
+ std::lock_guard<std::mutex> g(initMutex());
+ if (initialized_) {
+ // We set the locks on initialization, so if we are already initialized
+ // this would have no affect.
+ LOG(INFO) << "Ignoring setSSLLockTypes after initialization";
+ return;
+ }
+ setSSLLockTypesLocked(std::move(inLockTypes));
+}
+
+void SSLContext::setSSLLockTypesAndInitOpenSSL(
+ std::map<int, SSLLockType> inLockTypes) {
+ std::lock_guard<std::mutex> g(initMutex());
+ CHECK(!initialized_) << "OpenSSL is already initialized";
+ setSSLLockTypesLocked(std::move(inLockTypes));
+ initializeOpenSSLLocked();
+}
+
bool SSLContext::isSSLLockDisabled(int lockId) {
+ std::lock_guard<std::mutex> g(initMutex());
+ CHECK(initialized_) << "OpenSSL is not initialized yet";
const auto& sslLocks = lockTypes();
const auto it = sslLocks.find(lockId);
return it != sslLocks.end() &&