• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
13 namespace quic {
14 namespace test {
15 
ServerThread(std::unique_ptr<QuicServer> server,const QuicSocketAddress & address)16 ServerThread::ServerThread(std::unique_ptr<QuicServer> server,
17                            const QuicSocketAddress& address)
18     : QuicThread("server_thread"),
19       server_(std::move(server)),
20       clock_(QuicDefaultClock::Get()),
21       address_(address),
22       port_(0),
23       initialized_(false) {}
24 
25 ServerThread::~ServerThread() = default;
26 
Initialize()27 void ServerThread::Initialize() {
28   if (initialized_) {
29     return;
30   }
31   if (!server_->CreateUDPSocketAndListen(address_)) {
32     return;
33   }
34 
35   QuicWriterMutexLock lock(&port_lock_);
36   port_ = server_->port();
37 
38   initialized_ = true;
39 }
40 
Run()41 void ServerThread::Run() {
42   if (!initialized_) {
43     Initialize();
44   }
45 
46   while (!quit_.HasBeenNotified()) {
47     if (pause_.HasBeenNotified() && !resume_.HasBeenNotified()) {
48       paused_.Notify();
49       resume_.WaitForNotification();
50     }
51     server_->WaitForEvents();
52     ExecuteScheduledActions();
53     MaybeNotifyOfHandshakeConfirmation();
54   }
55 
56   server_->Shutdown();
57 }
58 
GetPort()59 int ServerThread::GetPort() {
60   QuicReaderMutexLock lock(&port_lock_);
61   int rc = port_;
62   return rc;
63 }
64 
Schedule(std::function<void ()> action)65 void ServerThread::Schedule(std::function<void()> action) {
66   QUICHE_DCHECK(!quit_.HasBeenNotified());
67   QuicWriterMutexLock lock(&scheduled_actions_lock_);
68   scheduled_actions_.push_back(std::move(action));
69 }
70 
WaitForCryptoHandshakeConfirmed()71 void ServerThread::WaitForCryptoHandshakeConfirmed() {
72   confirmed_.WaitForNotification();
73 }
74 
WaitUntil(std::function<bool ()> termination_predicate,QuicTime::Delta timeout)75 bool ServerThread::WaitUntil(std::function<bool()> termination_predicate,
76                              QuicTime::Delta timeout) {
77   const QuicTime deadline = clock_->Now() + timeout;
78   while (clock_->Now() < deadline) {
79     QuicNotification done_checking;
80     bool should_terminate = false;
81     Schedule([&] {
82       should_terminate = termination_predicate();
83       done_checking.Notify();
84     });
85     done_checking.WaitForNotification();
86     if (should_terminate) {
87       return true;
88     }
89   }
90   return false;
91 }
92 
Pause()93 void ServerThread::Pause() {
94   QUICHE_DCHECK(!pause_.HasBeenNotified());
95   pause_.Notify();
96   paused_.WaitForNotification();
97 }
98 
Resume()99 void ServerThread::Resume() {
100   QUICHE_DCHECK(!resume_.HasBeenNotified());
101   QUICHE_DCHECK(pause_.HasBeenNotified());
102   resume_.Notify();
103 }
104 
Quit()105 void ServerThread::Quit() {
106   if (pause_.HasBeenNotified() && !resume_.HasBeenNotified()) {
107     resume_.Notify();
108   }
109   if (!quit_.HasBeenNotified()) {
110     quit_.Notify();
111   }
112 }
113 
MaybeNotifyOfHandshakeConfirmation()114 void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
115   if (confirmed_.HasBeenNotified()) {
116     // Only notify once.
117     return;
118   }
119   QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server());
120   if (dispatcher->NumSessions() == 0) {
121     // Wait for a session to be created.
122     return;
123   }
124   QuicSession* session = QuicDispatcherPeer::GetFirstSessionIfAny(dispatcher);
125   if (session->OneRttKeysAvailable()) {
126     confirmed_.Notify();
127   }
128 }
129 
ExecuteScheduledActions()130 void ServerThread::ExecuteScheduledActions() {
131   quiche::QuicheCircularDeque<std::function<void()>> actions;
132   {
133     QuicWriterMutexLock lock(&scheduled_actions_lock_);
134     actions.swap(scheduled_actions_);
135   }
136   while (!actions.empty()) {
137     actions.front()();
138     actions.pop_front();
139   }
140 }
141 
142 }  // namespace test
143 }  // namespace quic
144