1 // Copyright (c) 2012 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 #ifndef QUICHE_QUIC_TOOLS_QUIC_CLIENT_DEFAULT_NETWORK_HELPER_H_ 6 #define QUICHE_QUIC_TOOLS_QUIC_CLIENT_DEFAULT_NETWORK_HELPER_H_ 7 8 #include <cstdint> 9 #include <memory> 10 #include <optional> 11 #include <string> 12 13 #include "quiche/quic/core/io/quic_event_loop.h" 14 #include "quiche/quic/core/io/socket.h" 15 #include "quiche/quic/core/quic_default_packet_writer.h" 16 #include "quiche/quic/core/quic_packet_reader.h" 17 #include "quiche/quic/core/quic_udp_socket.h" 18 #include "quiche/quic/tools/quic_client_base.h" 19 #include "quiche/common/quiche_linked_hash_map.h" 20 21 namespace quic { 22 23 namespace test { 24 class QuicClientPeer; 25 } // namespace test 26 27 // For level-triggered I/O, we need to manually rearm the kSocketEventWritable 28 // listener whenever the socket gets blocked. 29 class QuicLevelTriggeredPacketWriter : public QuicDefaultPacketWriter { 30 public: QuicLevelTriggeredPacketWriter(SocketFd fd,QuicEventLoop * event_loop)31 explicit QuicLevelTriggeredPacketWriter(SocketFd fd, 32 QuicEventLoop* event_loop) 33 : QuicDefaultPacketWriter(fd), event_loop_(event_loop) { 34 QUICHE_DCHECK(!event_loop->SupportsEdgeTriggered()); 35 } 36 WritePacket(const char * buffer,size_t buf_len,const QuicIpAddress & self_address,const QuicSocketAddress & peer_address,PerPacketOptions * options,const QuicPacketWriterParams & params)37 WriteResult WritePacket(const char* buffer, size_t buf_len, 38 const QuicIpAddress& self_address, 39 const QuicSocketAddress& peer_address, 40 PerPacketOptions* options, 41 const QuicPacketWriterParams& params) override { 42 WriteResult result = QuicDefaultPacketWriter::WritePacket( 43 buffer, buf_len, self_address, peer_address, options, params); 44 if (IsWriteBlockedStatus(result.status)) { 45 bool success = event_loop_->RearmSocket(fd(), kSocketEventWritable); 46 QUICHE_DCHECK(success); 47 } 48 return result; 49 } 50 51 private: 52 QuicEventLoop* event_loop_; 53 }; 54 55 std::unique_ptr<QuicPacketWriter> CreateDefaultWriterForEventLoop( 56 SocketFd fd, QuicEventLoop* event_loop); 57 58 // An implementation of the QuicClientBase::NetworkHelper interface that is 59 // based on the QuicEventLoop API. 60 class QuicClientDefaultNetworkHelper : public QuicClientBase::NetworkHelper, 61 public QuicSocketEventListener, 62 public ProcessPacketInterface { 63 public: 64 QuicClientDefaultNetworkHelper(QuicEventLoop* event_loop, 65 QuicClientBase* client); 66 QuicClientDefaultNetworkHelper(const QuicClientDefaultNetworkHelper&) = 67 delete; 68 QuicClientDefaultNetworkHelper& operator=( 69 const QuicClientDefaultNetworkHelper&) = delete; 70 71 ~QuicClientDefaultNetworkHelper() override; 72 73 // From QuicSocketEventListener. 74 void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd, 75 QuicSocketEventMask events) override; 76 77 // From ProcessPacketInterface. This will be called for each received 78 // packet. 79 void ProcessPacket(const QuicSocketAddress& self_address, 80 const QuicSocketAddress& peer_address, 81 const QuicReceivedPacket& packet) override; 82 83 // From NetworkHelper. 84 void RunEventLoop() override; 85 bool CreateUDPSocketAndBind(QuicSocketAddress server_address, 86 QuicIpAddress bind_to_address, 87 int bind_to_port) override; 88 void CleanUpAllUDPSockets() override; 89 QuicSocketAddress GetLatestClientAddress() const override; 90 QuicPacketWriter* CreateQuicPacketWriter() override; 91 92 // Accessors provided for convenience, not part of any interface. event_loop()93 QuicEventLoop* event_loop() { return event_loop_; } 94 const quiche::QuicheLinkedHashMap<SocketFd, QuicSocketAddress>& fd_address_map()95 fd_address_map() const { 96 return fd_address_map_; 97 } 98 99 // If the client has at least one UDP socket, return the latest created one. 100 // Otherwise, return -1. 101 SocketFd GetLatestFD() const; 102 103 // Create a socket for connection to |server_address| with default socket 104 // options. Returns the FD of the resulting socket. 105 virtual SocketFd CreateUDPSocket(QuicSocketAddress server_address, 106 bool* overflow_supported); 107 client()108 QuicClientBase* client() { return client_; } 109 set_max_reads_per_event_loop(int num_reads)110 void set_max_reads_per_event_loop(int num_reads) { 111 max_reads_per_event_loop_ = num_reads; 112 } 113 // If |fd| is an open UDP socket, unregister and close it. Otherwise, do 114 // nothing. 115 void CleanUpUDPSocket(SocketFd fd); 116 117 // Used for testing. 118 void SetClientPort(int port); 119 120 // Indicates that some of the FDs owned by the network helper may be 121 // unregistered by the external code by manually calling 122 // event_loop()->UnregisterSocket() (this is useful for certain scenarios 123 // where an external event loop is used). AllowFdsToBeUnregisteredExternally()124 void AllowFdsToBeUnregisteredExternally() { 125 fds_unregistered_externally_ = true; 126 } 127 128 // Bind a socket to a specific network interface. 129 bool BindInterfaceNameIfNeeded(SocketFd fd); 130 131 // Actually clean up |fd|. 132 virtual void CleanUpUDPSocketImpl(SocketFd fd); 133 134 private: 135 // Listens for events on the client socket. 136 QuicEventLoop* event_loop_; 137 138 // Map mapping created UDP sockets to their addresses. By using linked hash 139 // map, the order of socket creation can be recorded. 140 quiche::QuicheLinkedHashMap<SocketFd, QuicSocketAddress> fd_address_map_; 141 142 // If overflow_supported_ is true, this will be the number of packets dropped 143 // during the lifetime of the server. 144 QuicPacketCount packets_dropped_; 145 146 // True if the kernel supports SO_RXQ_OVFL, the number of packets dropped 147 // because the socket would otherwise overflow. 148 bool overflow_supported_; 149 150 // Point to a QuicPacketReader object on the heap. The reader allocates more 151 // space than allowed on the stack. 152 std::unique_ptr<QuicPacketReader> packet_reader_; 153 154 QuicClientBase* client_; 155 156 int max_reads_per_event_loop_; 157 158 // If true, some of the FDs owned by the network helper may be unregistered by 159 // the external code. 160 bool fds_unregistered_externally_ = false; 161 }; 162 163 } // namespace quic 164 165 #endif // QUICHE_QUIC_TOOLS_QUIC_CLIENT_DEFAULT_NETWORK_HELPER_H_ 166