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