memgraph/src/communication/init.cpp
2022-03-14 15:47:41 +01:00

76 lines
2.2 KiB
C++

// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#include "init.hpp"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <thread>
#include "utils/logging.hpp"
#include "utils/signals.hpp"
#include "utils/spin_lock.hpp"
namespace memgraph::communication {
namespace {
// OpenSSL before 1.1 did not have a out-of-the-box multithreading support
// You need to manually define locks, locking callbacks and id function.
// https://stackoverflow.com/a/42856544
// https://wiki.openssl.org/index.php/Library_Initialization#libssl_Initialization
// https://www.openssl.org/docs/man1.0.2/man3/CRYPTO_num_locks.html
#if OPENSSL_VERSION_NUMBER < 0x10100000L
std::vector<utils::SpinLock> crypto_locks;
void LockingFunction(int mode, int n, const char *file, int line) {
if (mode & CRYPTO_LOCK) {
crypto_locks[n].lock();
} else {
crypto_locks[n].unlock();
}
}
unsigned long IdFunction() { return (unsigned long)std::hash<std::thread::id>()(std::this_thread::get_id()); }
void SetupThreading() {
crypto_locks.resize(CRYPTO_num_locks());
CRYPTO_set_id_callback(IdFunction);
CRYPTO_set_locking_callback(LockingFunction);
}
void Cleanup() {
CRYPTO_set_id_callback(nullptr);
CRYPTO_set_locking_callback(nullptr);
crypto_locks.clear();
}
#else
void SetupThreading() {}
void Cleanup() {}
#endif
} // namespace
SSLInit::SSLInit() {
// Initialize the OpenSSL library.
SSL_library_init();
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
ERR_load_crypto_strings();
// Ignore SIGPIPE.
MG_ASSERT(utils::SignalIgnore(utils::Signal::Pipe), "Couldn't ignore SIGPIPE!");
SetupThreading();
}
SSLInit::~SSLInit() { Cleanup(); }
} // namespace memgraph::communication