init.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * Copyright (c) 2020 Paul-Louis Ageneau
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "init.hpp"
  19. #include "globals.hpp"
  20. #include "impl/certificate.hpp"
  21. #include "impl/dtlstransport.hpp"
  22. #include "impl/sctptransport.hpp"
  23. #include "impl/threadpool.hpp"
  24. #include "impl/tls.hpp"
  25. #if RTC_ENABLE_WEBSOCKET
  26. #include "impl/tlstransport.hpp"
  27. #endif
  28. #if RTC_ENABLE_MEDIA
  29. #include "impl/dtlssrtptransport.hpp"
  30. #endif
  31. #ifdef _WIN32
  32. #include <winsock2.h>
  33. #endif
  34. namespace rtc {
  35. namespace {
  36. void doInit() {
  37. PLOG_DEBUG << "Global initialization";
  38. #ifdef _WIN32
  39. WSADATA wsaData;
  40. if (WSAStartup(MAKEWORD(2, 2), &wsaData))
  41. throw std::runtime_error("WSAStartup failed, error=" + std::to_string(WSAGetLastError()));
  42. #endif
  43. impl::ThreadPool::Instance().spawn(THREADPOOL_SIZE);
  44. #if USE_GNUTLS
  45. // Nothing to do
  46. #else
  47. openssl::init();
  48. #endif
  49. impl::SctpTransport::Init();
  50. impl::DtlsTransport::Init();
  51. #if RTC_ENABLE_WEBSOCKET
  52. impl::TlsTransport::Init();
  53. #endif
  54. #if RTC_ENABLE_MEDIA
  55. impl::DtlsSrtpTransport::Init();
  56. #endif
  57. }
  58. void doCleanup() {
  59. PLOG_DEBUG << "Global cleanup";
  60. impl::ThreadPool::Instance().join();
  61. impl::CleanupCertificateCache();
  62. impl::SctpTransport::Cleanup();
  63. impl::DtlsTransport::Cleanup();
  64. #if RTC_ENABLE_WEBSOCKET
  65. impl::TlsTransport::Cleanup();
  66. #endif
  67. #if RTC_ENABLE_MEDIA
  68. impl::DtlsSrtpTransport::Cleanup();
  69. #endif
  70. #ifdef _WIN32
  71. WSACleanup();
  72. #endif
  73. }
  74. } // namespace
  75. weak_ptr<void> Init::Weak;
  76. shared_ptr<void> *Init::Global = nullptr;
  77. bool Init::Initialized = false;
  78. std::recursive_mutex Init::Mutex;
  79. init_token Init::Token() {
  80. std::unique_lock lock(Mutex);
  81. if (auto token = Weak.lock())
  82. return token;
  83. delete Global;
  84. Global = new shared_ptr<void>(new Init());
  85. Weak = *Global;
  86. return *Global;
  87. }
  88. void Init::Preload() {
  89. std::unique_lock lock(Mutex);
  90. auto token = Token();
  91. if (!Global)
  92. Global = new shared_ptr<void>(token);
  93. PLOG_DEBUG << "Preloading certificate";
  94. impl::make_certificate().wait();
  95. }
  96. void Init::Cleanup() {
  97. std::unique_lock lock(Mutex);
  98. delete Global;
  99. Global = nullptr;
  100. }
  101. Init::Init() {
  102. // Mutex is locked by Token() here
  103. if (!std::exchange(Initialized, true))
  104. doInit();
  105. }
  106. Init::~Init() {
  107. std::thread t([]() {
  108. // We need to lock Mutex ourselves
  109. std::unique_lock lock(Mutex);
  110. if (Global)
  111. return;
  112. if (std::exchange(Initialized, false))
  113. doCleanup();
  114. });
  115. t.detach();
  116. }
  117. } // namespace rtc