xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/test_tools/server_thread.h"
6 
7 #include "quiche/quic/core/quic_default_clock.h"
8 #include "quiche/quic/core/quic_dispatcher.h"
9 #include "quiche/quic/test_tools/crypto_test_utils.h"
10 #include "quiche/quic/test_tools/quic_dispatcher_peer.h"
11 #include "quiche/quic/test_tools/quic_server_peer.h"
12 #include "quiche/common/quiche_callbacks.h"
13 
14 namespace quic {
15 namespace test {
16 
ServerThread(std::unique_ptr<QuicServer> server,const QuicSocketAddress & address)17 ServerThread::ServerThread(std::unique_ptr<QuicServer> server,
18                            const QuicSocketAddress& address)
19     : QuicThread("server_thread"),
20       server_(std::move(server)),
21       clock_(QuicDefaultClock::Get()),
22       address_(address),
23       port_(0),
24       initialized_(false) {}
25 
26 ServerThread::~ServerThread() = default;
27 
Initialize()28 void ServerThread::Initialize() {
29   if (initialized_) {
30     return;
31   }
32   if (!server_->CreateUDPSocketAndListen(address_)) {
33     return;
34   }
35 
36   QuicWriterMutexLock lock(&port_lock_);
37   port_ = server_->port();
38 
39   initialized_ = true;
40 }
41 
Run()42 void ServerThread::Run() {
43   if (!initialized_) {
44     Initialize();
45   }
46 
47   while (!quit_.HasBeenNotified()) {
48     if (pause_.HasBeenNotified() && !resume_.HasBeenNotified()) {
49       paused_.Notify();
50       resume_.WaitForNotification();
51     }
52     server_->WaitForEvents();
53     ExecuteScheduledActions();
54     MaybeNotifyOfHandshakeConfirmation();
55   }
56 
57   server_->Shutdown();
58 }
59 
GetPort()60 int ServerThread::GetPort() {
61   QuicReaderMutexLock lock(&port_lock_);
62   int rc = port_;
63   return rc;
64 }
65 
Schedule(quiche::SingleUseCallback<void ()> action)66 void ServerThread::Schedule(quiche::SingleUseCallback<void()> action) {
67   QUICHE_DCHECK(!quit_.HasBeenNotified());
68   QuicWriterMutexLock lock(&scheduled_actions_lock_);
69   scheduled_actions_.push_back(std::move(action));
70 }
71 
ScheduleAndWaitForCompletion(quiche::SingleUseCallback<void ()> action)72 void ServerThread::ScheduleAndWaitForCompletion(
73     quiche::SingleUseCallback<void()> action) {
74   QuicNotification action_done;
75   Schedule([&] {
76     std::move(action)();
77     action_done.Notify();
78   });
79   action_done.WaitForNotification();
80 }
81 
WaitForCryptoHandshakeConfirmed()82 void ServerThread::WaitForCryptoHandshakeConfirmed() {
83   confirmed_.WaitForNotification();
84 }
85 
WaitUntil(quiche::UnretainedCallback<bool ()> termination_predicate,QuicTime::Delta timeout)86 bool ServerThread::WaitUntil(
87     quiche::UnretainedCallback<bool()> termination_predicate,
88     QuicTime::Delta timeout) {
89   const QuicTime deadline = clock_->Now() + timeout;
90   while (clock_->Now() < deadline) {
91     QuicNotification done_checking;
92     bool should_terminate = false;
93     Schedule([&] {
94       should_terminate = termination_predicate();
95       done_checking.Notify();
96     });
97     done_checking.WaitForNotification();
98     if (should_terminate) {
99       return true;
100     }
101   }
102   return false;
103 }
104 
Pause()105 void ServerThread::Pause() {
106   QUICHE_DCHECK(!pause_.HasBeenNotified());
107   pause_.Notify();
108   paused_.WaitForNotification();
109 }
110 
Resume()111 void ServerThread::Resume() {
112   QUICHE_DCHECK(!resume_.HasBeenNotified());
113   QUICHE_DCHECK(pause_.HasBeenNotified());
114   resume_.Notify();
115 }
116 
Quit()117 void ServerThread::Quit() {
118   if (pause_.HasBeenNotified() && !resume_.HasBeenNotified()) {
119     resume_.Notify();
120   }
121   if (!quit_.HasBeenNotified()) {
122     quit_.Notify();
123   }
124 }
125 
MaybeNotifyOfHandshakeConfirmation()126 void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
127   if (confirmed_.HasBeenNotified()) {
128     // Only notify once.
129     return;
130   }
131   QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server());
132   if (dispatcher->NumSessions() == 0) {
133     // Wait for a session to be created.
134     return;
135   }
136   QuicSession* session = QuicDispatcherPeer::GetFirstSessionIfAny(dispatcher);
137   if (session->OneRttKeysAvailable()) {
138     confirmed_.Notify();
139   }
140 }
141 
ExecuteScheduledActions()142 void ServerThread::ExecuteScheduledActions() {
143   quiche::QuicheCircularDeque<quiche::SingleUseCallback<void()>> actions;
144   {
145     QuicWriterMutexLock lock(&scheduled_actions_lock_);
146     actions.swap(scheduled_actions_);
147   }
148   while (!actions.empty()) {
149     std::move(actions.front())();
150     actions.pop_front();
151   }
152 }
153 
154 }  // namespace test
155 }  // namespace quic
156