Use injected clock when injecting clock for testing into SSL adapter

Bug: webrtc:42223992
Change-Id: I763f56d4d56ee569283f1d7c01c3a7abb7aa99a3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/466060
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47563}
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index 90f907c..92555c2 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -1678,21 +1678,24 @@
     ":stream",
     ":stringutils",
     ":threading",
-    ":timeutils",
     "../api:field_trials_view",
     "../api:sequence_checker",
     "../api/environment",
     "../api/task_queue",
     "../api/task_queue:pending_task_safety_flag",
     "../api/units:time_delta",
+    "../api/units:timestamp",
+    "../system_wrappers",
+    "synchronization:mutex",
     "system:rtc_export",
     "task_utils:repeating_task",
     "//third_party/abseil-cpp/absl/base:core_headers",
+    "//third_party/abseil-cpp/absl/base:no_destructor",
     "//third_party/abseil-cpp/absl/base:nullability",
     "//third_party/abseil-cpp/absl/functional:any_invocable",
     "//third_party/abseil-cpp/absl/memory",
-    "//third_party/abseil-cpp/absl/strings",
     "//third_party/abseil-cpp/absl/strings:str_format",
+    "//third_party/abseil-cpp/absl/strings:string_view",
   ]
 
   # If we are building the SSL library ourselves, we know it's BoringSSL.
diff --git a/rtc_base/openssl_stream_adapter.cc b/rtc_base/openssl_stream_adapter.cc
index 403f4ca..ccc8823 100644
--- a/rtc_base/openssl_stream_adapter.cc
+++ b/rtc_base/openssl_stream_adapter.cc
@@ -26,6 +26,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/base/no_destructor.h"
 #include "absl/functional/any_invocable.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
@@ -35,6 +36,7 @@
 #include "api/task_queue/pending_task_safety_flag.h"
 #include "api/task_queue/task_queue_base.h"
 #include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -47,8 +49,9 @@
 #include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/stream.h"
 #include "rtc_base/string_encode.h"
+#include "rtc_base/synchronization/mutex.h"
 #include "rtc_base/task_utils/repeating_task.h"
-#include "rtc_base/time_utils.h"
+#include "system_wrappers/include/clock.h"
 
 #ifdef OPENSSL_IS_BORINGSSL
 #include <openssl/digest.h>
@@ -92,12 +95,12 @@
 #ifdef OPENSSL_IS_BORINGSSL
 // Enabled by EnableTimeCallbackForTesting. Should never be set in production
 // code.
-bool g_use_time_callback_for_testing = false;
-// Not used in production code. Actual time should be relative to Jan 1, 1970.
-void TimeCallbackForTesting(const SSL* ssl, struct timeval* out_clock) {
-  int64_t time = TimeNanos();
-  out_clock->tv_sec = time / kNumNanosecsPerSec;
-  out_clock->tv_usec = (time % kNumNanosecsPerSec) / kNumNanosecsPerMicrosec;
+constinit bool g_use_time_callback_for_testing = false;
+constinit size_t g_num_clock_for_testing_users = 0;
+constinit Clock* g_clock_for_testing = nullptr;
+Mutex& GlobalClockMutex() {
+  static absl::NoDestructor<Mutex> m;
+  return *m;
 }
 #endif
 
@@ -1105,6 +1108,36 @@
   timeout_task_.Stop();
 }
 
+#ifdef OPENSSL_IS_BORINGSSL
+OpenSSLStreamAdapter::ScopedClockForTesting::ScopedClockForTesting(
+    SSL_CTX* ctx,
+    Clock* clock) {
+  MutexLock lock(&GlobalClockMutex());
+  if (g_num_clock_for_testing_users == 0) {
+    g_clock_for_testing = clock;
+  } else {
+    RTC_CHECK(g_clock_for_testing == clock)
+        << "Multiple SSL clocks for testing is not implemented";
+  }
+  ++g_num_clock_for_testing_users;
+
+  // Not used in production code. Actual time should be relative to Jan 1, 1970.
+  SSL_CTX_set_current_time_cb(
+      ctx, +[](const SSL*, timeval* out_clock) {
+        Timestamp time = g_clock_for_testing->CurrentTime();
+        out_clock->tv_sec = time.us() / TimeDelta::Seconds(1).us();
+        out_clock->tv_usec = time.us() % TimeDelta::Seconds(1).us();
+      });
+}
+OpenSSLStreamAdapter::ScopedClockForTesting::~ScopedClockForTesting() {
+  MutexLock lock(&GlobalClockMutex());
+  --g_num_clock_for_testing_users;
+  if (g_num_clock_for_testing_users == 0) {
+    g_clock_for_testing = nullptr;
+  }
+}
+#endif
+
 SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
 #ifdef OPENSSL_IS_BORINGSSL
   // If X509 objects aren't used, we can use these methods to avoid
@@ -1130,7 +1163,9 @@
 #ifdef OPENSSL_IS_BORINGSSL
   // SSL_CTX_set_current_time_cb is only supported in BoringSSL.
   if (g_use_time_callback_for_testing) {
-    SSL_CTX_set_current_time_cb(ctx, &TimeCallbackForTesting);
+    // Clock should be injected to set one for testing.
+    RTC_CHECK(env_.has_value());
+    clock_for_testing_.emplace(ctx, &env_->clock());
   }
   SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool());
 #endif
diff --git a/rtc_base/openssl_stream_adapter.h b/rtc_base/openssl_stream_adapter.h
index 6aa5fd1..46335a7 100644
--- a/rtc_base/openssl_stream_adapter.h
+++ b/rtc_base/openssl_stream_adapter.h
@@ -32,6 +32,7 @@
 #include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/stream.h"
 #include "rtc_base/task_utils/repeating_task.h"
+#include "system_wrappers/include/clock.h"
 
 #ifdef OPENSSL_IS_BORINGSSL
 #include "rtc_base/boringssl_identity.h"
@@ -273,6 +274,15 @@
   // Kill switch (from field-trial) flag to disable the use of
   // SSL_set_group_ids.
   const bool disable_ssl_group_ids_ = false;
+
+#ifdef OPENSSL_IS_BORINGSSL
+  class ScopedClockForTesting {
+   public:
+    ScopedClockForTesting(SSL_CTX* ctx, Clock* clock);
+    ~ScopedClockForTesting();
+  };
+  std::optional<ScopedClockForTesting> clock_for_testing_;
+#endif
 };
 
 /////////////////////////////////////////////////////////////////////////////