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