| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/tools/quic/test_tools/server_thread.h" |
| |
| #include "net/quic/test_tools/crypto_test_utils.h" |
| #include "net/tools/quic/quic_dispatcher.h" |
| #include "net/tools/quic/test_tools/quic_server_peer.h" |
| |
| namespace net { |
| namespace test { |
| |
| ServerThread::ServerThread(QuicServer* server, const QuicSocketAddress& address) |
| : SimpleThread("server_thread"), |
| confirmed_(base::WaitableEvent::ResetPolicy::MANUAL, |
| base::WaitableEvent::InitialState::NOT_SIGNALED), |
| pause_(base::WaitableEvent::ResetPolicy::MANUAL, |
| base::WaitableEvent::InitialState::NOT_SIGNALED), |
| paused_(base::WaitableEvent::ResetPolicy::MANUAL, |
| base::WaitableEvent::InitialState::NOT_SIGNALED), |
| resume_(base::WaitableEvent::ResetPolicy::MANUAL, |
| base::WaitableEvent::InitialState::NOT_SIGNALED), |
| quit_(base::WaitableEvent::ResetPolicy::MANUAL, |
| base::WaitableEvent::InitialState::NOT_SIGNALED), |
| server_(server), |
| address_(address), |
| port_(0), |
| initialized_(false) {} |
| |
| ServerThread::~ServerThread() {} |
| |
| void ServerThread::Initialize() { |
| if (initialized_) { |
| return; |
| } |
| |
| server_->CreateUDPSocketAndListen(address_); |
| |
| QuicWriterMutexLock lock(&port_lock_); |
| port_ = server_->port(); |
| |
| initialized_ = true; |
| } |
| |
| void ServerThread::Run() { |
| if (!initialized_) { |
| Initialize(); |
| } |
| |
| while (!quit_.IsSignaled()) { |
| if (pause_.IsSignaled() && !resume_.IsSignaled()) { |
| paused_.Signal(); |
| resume_.Wait(); |
| } |
| server_->WaitForEvents(); |
| ExecuteScheduledActions(); |
| MaybeNotifyOfHandshakeConfirmation(); |
| } |
| |
| server_->Shutdown(); |
| } |
| |
| int ServerThread::GetPort() { |
| QuicReaderMutexLock lock(&port_lock_); |
| int rc = port_; |
| return rc; |
| } |
| |
| void ServerThread::Schedule(std::function<void()> action) { |
| DCHECK(!quit_.IsSignaled()); |
| QuicWriterMutexLock lock(&scheduled_actions_lock_); |
| scheduled_actions_.push_back(std::move(action)); |
| } |
| |
| void ServerThread::WaitForCryptoHandshakeConfirmed() { |
| confirmed_.Wait(); |
| } |
| |
| void ServerThread::Pause() { |
| DCHECK(!pause_.IsSignaled()); |
| pause_.Signal(); |
| paused_.Wait(); |
| } |
| |
| void ServerThread::Resume() { |
| DCHECK(!resume_.IsSignaled()); |
| DCHECK(pause_.IsSignaled()); |
| resume_.Signal(); |
| } |
| |
| void ServerThread::Quit() { |
| if (pause_.IsSignaled() && !resume_.IsSignaled()) { |
| resume_.Signal(); |
| } |
| quit_.Signal(); |
| } |
| |
| void ServerThread::MaybeNotifyOfHandshakeConfirmation() { |
| if (confirmed_.IsSignaled()) { |
| // Only notify once. |
| return; |
| } |
| QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server()); |
| if (dispatcher->session_map().empty()) { |
| // Wait for a session to be created. |
| return; |
| } |
| QuicSession* session = dispatcher->session_map().begin()->second.get(); |
| if (session->IsCryptoHandshakeConfirmed()) { |
| confirmed_.Signal(); |
| } |
| } |
| |
| void ServerThread::ExecuteScheduledActions() { |
| std::deque<std::function<void()>> actions; |
| { |
| QuicWriterMutexLock lock(&scheduled_actions_lock_); |
| actions.swap(scheduled_actions_); |
| } |
| while (!actions.empty()) { |
| actions.front()(); |
| actions.pop_front(); |
| } |
| } |
| |
| } // namespace test |
| } // namespace net |