| // 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 "quic/tools/quic_server.h" | 
 |  | 
 | #include "absl/base/macros.h" | 
 | #include "quic/core/crypto/quic_random.h" | 
 | #include "quic/core/quic_epoll_alarm_factory.h" | 
 | #include "quic/core/quic_epoll_connection_helper.h" | 
 | #include "quic/core/quic_utils.h" | 
 | #include "quic/platform/api/quic_flags.h" | 
 | #include "quic/platform/api/quic_logging.h" | 
 | #include "quic/platform/api/quic_port_utils.h" | 
 | #include "quic/platform/api/quic_socket_address.h" | 
 | #include "quic/platform/api/quic_test.h" | 
 | #include "quic/platform/api/quic_test_loopback.h" | 
 | #include "quic/test_tools/crypto_test_utils.h" | 
 | #include "quic/test_tools/mock_quic_dispatcher.h" | 
 | #include "quic/test_tools/quic_server_peer.h" | 
 | #include "quic/tools/quic_memory_cache_backend.h" | 
 | #include "quic/tools/quic_simple_crypto_server_stream_helper.h" | 
 |  | 
 | namespace quic { | 
 | namespace test { | 
 |  | 
 | using ::testing::_; | 
 |  | 
 | namespace { | 
 |  | 
 | class MockQuicSimpleDispatcher : public QuicSimpleDispatcher { | 
 |  public: | 
 |   MockQuicSimpleDispatcher( | 
 |       const QuicConfig* config, | 
 |       const QuicCryptoServerConfig* crypto_config, | 
 |       QuicVersionManager* version_manager, | 
 |       std::unique_ptr<QuicConnectionHelperInterface> helper, | 
 |       std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper, | 
 |       std::unique_ptr<QuicAlarmFactory> alarm_factory, | 
 |       QuicSimpleServerBackend* quic_simple_server_backend) | 
 |       : QuicSimpleDispatcher(config, | 
 |                              crypto_config, | 
 |                              version_manager, | 
 |                              std::move(helper), | 
 |                              std::move(session_helper), | 
 |                              std::move(alarm_factory), | 
 |                              quic_simple_server_backend, | 
 |                              kQuicDefaultConnectionIdLength) {} | 
 |   ~MockQuicSimpleDispatcher() override = default; | 
 |  | 
 |   MOCK_METHOD(void, OnCanWrite, (), (override)); | 
 |   MOCK_METHOD(bool, HasPendingWrites, (), (const, override)); | 
 |   MOCK_METHOD(bool, HasChlosBuffered, (), (const, override)); | 
 |   MOCK_METHOD(void, ProcessBufferedChlos, (size_t), (override)); | 
 | }; | 
 |  | 
 | class TestQuicServer : public QuicServer { | 
 |  public: | 
 |   TestQuicServer() | 
 |       : QuicServer(crypto_test_utils::ProofSourceForTesting(), | 
 |                    &quic_simple_server_backend_) {} | 
 |  | 
 |   ~TestQuicServer() override = default; | 
 |  | 
 |   MockQuicSimpleDispatcher* mock_dispatcher() { return mock_dispatcher_; } | 
 |  | 
 |  protected: | 
 |   QuicDispatcher* CreateQuicDispatcher() override { | 
 |     mock_dispatcher_ = new MockQuicSimpleDispatcher( | 
 |         &config(), &crypto_config(), version_manager(), | 
 |         std::unique_ptr<QuicEpollConnectionHelper>( | 
 |             new QuicEpollConnectionHelper(epoll_server(), | 
 |                                           QuicAllocator::BUFFER_POOL)), | 
 |         std::unique_ptr<QuicCryptoServerStreamBase::Helper>( | 
 |             new QuicSimpleCryptoServerStreamHelper()), | 
 |         std::unique_ptr<QuicEpollAlarmFactory>( | 
 |             new QuicEpollAlarmFactory(epoll_server())), | 
 |         &quic_simple_server_backend_); | 
 |     return mock_dispatcher_; | 
 |   } | 
 |  | 
 |   MockQuicSimpleDispatcher* mock_dispatcher_ = nullptr; | 
 |   QuicMemoryCacheBackend quic_simple_server_backend_; | 
 | }; | 
 |  | 
 | class QuicServerEpollInTest : public QuicTest { | 
 |  public: | 
 |   QuicServerEpollInTest() | 
 |       : port_(QuicPickServerPortForTestsOrDie()), | 
 |         server_address_(TestLoopback(), port_) {} | 
 |  | 
 |   void StartListening() { | 
 |     server_.CreateUDPSocketAndListen(server_address_); | 
 |     server_address_ = QuicSocketAddress(server_address_.host(), server_.port()); | 
 |  | 
 |     ASSERT_TRUE(QuicServerPeer::SetSmallSocket(&server_)); | 
 |  | 
 |     if (!server_.overflow_supported()) { | 
 |       QUIC_LOG(WARNING) << "Overflow not supported.  Not testing."; | 
 |       return; | 
 |     } | 
 |   } | 
 |  | 
 |  protected: | 
 |   int port_; | 
 |   QuicSocketAddress server_address_; | 
 |   TestQuicServer server_; | 
 | }; | 
 |  | 
 | // Tests that if dispatcher has CHLOs waiting for connection creation, EPOLLIN | 
 | // event should try to create connections for them. And set epoll mask with | 
 | // EPOLLIN if there are still CHLOs remaining at the end of epoll event. | 
 | TEST_F(QuicServerEpollInTest, ProcessBufferedCHLOsOnEpollin) { | 
 |   // Given an EPOLLIN event, try to create session for buffered CHLOs. In first | 
 |   // event, dispatcher can't create session for all of CHLOs. So listener should | 
 |   // register another EPOLLIN event by itself. Even without new packet arrival, | 
 |   // the rest CHLOs should be process in next epoll event. | 
 |   StartListening(); | 
 |   bool more_chlos = true; | 
 |   MockQuicSimpleDispatcher* dispatcher_ = server_.mock_dispatcher(); | 
 |   QUICHE_DCHECK(dispatcher_ != nullptr); | 
 |   EXPECT_CALL(*dispatcher_, OnCanWrite()).Times(testing::AnyNumber()); | 
 |   EXPECT_CALL(*dispatcher_, ProcessBufferedChlos(_)).Times(2); | 
 |   EXPECT_CALL(*dispatcher_, HasPendingWrites()).Times(testing::AnyNumber()); | 
 |   // Expect there are still CHLOs buffered after 1st event. But not any more | 
 |   // after 2nd event. | 
 |   EXPECT_CALL(*dispatcher_, HasChlosBuffered()) | 
 |       .WillOnce(testing::Return(true)) | 
 |       .WillOnce( | 
 |           DoAll(testing::Assign(&more_chlos, false), testing::Return(false))); | 
 |  | 
 |   // Send a packet to trigger epoll event. | 
 |   int fd = socket( | 
 |       AddressFamilyUnderTest() == IpAddressFamily::IP_V4 ? AF_INET : AF_INET6, | 
 |       SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); | 
 |   ASSERT_LT(0, fd); | 
 |  | 
 |   char buf[1024]; | 
 |   memset(buf, 0, ABSL_ARRAYSIZE(buf)); | 
 |   sockaddr_storage storage = server_address_.generic_address(); | 
 |   int rc = sendto(fd, buf, ABSL_ARRAYSIZE(buf), 0, | 
 |                   reinterpret_cast<sockaddr*>(&storage), sizeof(storage)); | 
 |   if (rc < 0) { | 
 |     QUIC_DLOG(INFO) << errno << " " << strerror(errno); | 
 |   } | 
 |  | 
 |   while (more_chlos) { | 
 |     server_.WaitForEvents(); | 
 |   } | 
 | } | 
 |  | 
 | class QuicServerDispatchPacketTest : public QuicTest { | 
 |  public: | 
 |   QuicServerDispatchPacketTest() | 
 |       : crypto_config_("blah", | 
 |                        QuicRandom::GetInstance(), | 
 |                        crypto_test_utils::ProofSourceForTesting(), | 
 |                        KeyExchangeSource::Default()), | 
 |         version_manager_(AllSupportedVersions()), | 
 |         dispatcher_( | 
 |             &config_, | 
 |             &crypto_config_, | 
 |             &version_manager_, | 
 |             std::unique_ptr<QuicEpollConnectionHelper>( | 
 |                 new QuicEpollConnectionHelper(&eps_, | 
 |                                               QuicAllocator::BUFFER_POOL)), | 
 |             std::unique_ptr<QuicCryptoServerStreamBase::Helper>( | 
 |                 new QuicSimpleCryptoServerStreamHelper()), | 
 |             std::unique_ptr<QuicEpollAlarmFactory>( | 
 |                 new QuicEpollAlarmFactory(&eps_)), | 
 |             &quic_simple_server_backend_) { | 
 |     dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234)); | 
 |   } | 
 |  | 
 |   void DispatchPacket(const QuicReceivedPacket& packet) { | 
 |     QuicSocketAddress client_addr, server_addr; | 
 |     dispatcher_.ProcessPacket(server_addr, client_addr, packet); | 
 |   } | 
 |  | 
 |  protected: | 
 |   QuicConfig config_; | 
 |   QuicCryptoServerConfig crypto_config_; | 
 |   QuicVersionManager version_manager_; | 
 |   QuicEpollServer eps_; | 
 |   QuicMemoryCacheBackend quic_simple_server_backend_; | 
 |   MockQuicDispatcher dispatcher_; | 
 | }; | 
 |  | 
 | TEST_F(QuicServerDispatchPacketTest, DispatchPacket) { | 
 |   // clang-format off | 
 |   unsigned char valid_packet[] = { | 
 |     // public flags (8 byte connection_id) | 
 |     0x3C, | 
 |     // connection_id | 
 |     0x10, 0x32, 0x54, 0x76, | 
 |     0x98, 0xBA, 0xDC, 0xFE, | 
 |     // packet number | 
 |     0xBC, 0x9A, 0x78, 0x56, | 
 |     0x34, 0x12, | 
 |     // private flags | 
 |     0x00 | 
 |   }; | 
 |   // clang-format on | 
 |   QuicReceivedPacket encrypted_valid_packet( | 
 |       reinterpret_cast<char*>(valid_packet), ABSL_ARRAYSIZE(valid_packet), | 
 |       QuicTime::Zero(), false); | 
 |  | 
 |   EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1); | 
 |   DispatchPacket(encrypted_valid_packet); | 
 | } | 
 |  | 
 | }  // namespace | 
 | }  // namespace test | 
 | }  // namespace quic |