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 #include "quiche/quic/tools/quic_client_default_network_helper.h"
6 
7 #include "absl/cleanup/cleanup.h"
8 #include "quiche/quic/core/io/quic_event_loop.h"
9 #include "quiche/quic/core/quic_default_packet_writer.h"
10 #include "quiche/quic/core/quic_packets.h"
11 #include "quiche/quic/core/quic_types.h"
12 #include "quiche/quic/core/quic_udp_socket.h"
13 #include "quiche/quic/platform/api/quic_logging.h"
14 #include "quiche/common/platform/api/quiche_logging.h"
15 #include "quiche/common/platform/api/quiche_system_event_loop.h"
16 
17 namespace quic {
18 
CreateDefaultWriterForEventLoop(SocketFd fd,QuicEventLoop * event_loop)19 std::unique_ptr<QuicPacketWriter> CreateDefaultWriterForEventLoop(
20     SocketFd fd, QuicEventLoop* event_loop) {
21   if (event_loop->SupportsEdgeTriggered()) {
22     return std::make_unique<QuicDefaultPacketWriter>(fd);
23   } else {
24     return std::make_unique<QuicLevelTriggeredPacketWriter>(fd, event_loop);
25   }
26 }
27 
QuicClientDefaultNetworkHelper(QuicEventLoop * event_loop,QuicClientBase * client)28 QuicClientDefaultNetworkHelper::QuicClientDefaultNetworkHelper(
29     QuicEventLoop* event_loop, QuicClientBase* client)
30     : event_loop_(event_loop),
31       packets_dropped_(0),
32       overflow_supported_(false),
33       packet_reader_(new QuicPacketReader()),
34       client_(client),
35       max_reads_per_event_loop_(std::numeric_limits<int>::max()) {}
36 
~QuicClientDefaultNetworkHelper()37 QuicClientDefaultNetworkHelper::~QuicClientDefaultNetworkHelper() {
38   if (client_->connected()) {
39     client_->session()->connection()->CloseConnection(
40         QUIC_PEER_GOING_AWAY, "Client being torn down",
41         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
42   }
43 
44   CleanUpAllUDPSockets();
45 }
46 
CreateUDPSocketAndBind(QuicSocketAddress server_address,QuicIpAddress bind_to_address,int bind_to_port)47 bool QuicClientDefaultNetworkHelper::CreateUDPSocketAndBind(
48     QuicSocketAddress server_address, QuicIpAddress bind_to_address,
49     int bind_to_port) {
50   SocketFd fd = CreateUDPSocket(server_address, &overflow_supported_);
51   if (fd == kInvalidSocketFd) {
52     return false;
53   }
54   auto closer = absl::MakeCleanup([fd] { (void)socket_api::Close(fd); });
55 
56   QuicSocketAddress client_address;
57   if (bind_to_address.IsInitialized()) {
58     client_address = QuicSocketAddress(bind_to_address, client_->local_port());
59   } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) {
60     client_address = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port);
61   } else {
62     client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port);
63   }
64 
65   // Some platforms expect that the addrlen given to bind() exactly matches the
66   // size of the associated protocol family's sockaddr struct.
67   // TODO(b/179430548): Revert this when affected platforms are updated to
68   // to support binding with an addrelen of sizeof(sockaddr_storage)
69   socklen_t addrlen;
70   switch (client_address.host().address_family()) {
71     case IpAddressFamily::IP_V4:
72       addrlen = sizeof(sockaddr_in);
73       break;
74     case IpAddressFamily::IP_V6:
75       addrlen = sizeof(sockaddr_in6);
76       break;
77     case IpAddressFamily::IP_UNSPEC:
78       addrlen = 0;
79       break;
80   }
81 
82   sockaddr_storage addr = client_address.generic_address();
83   int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), addrlen);
84   if (rc < 0) {
85     QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno)
86                     << " bind_to_address:" << bind_to_address
87                     << ", bind_to_port:" << bind_to_port
88                     << ", client_address:" << client_address;
89     return false;
90   }
91 
92   if (client_address.FromSocket(fd) != 0) {
93     QUIC_LOG(ERROR) << "Unable to get self address.  Error: "
94                     << strerror(errno);
95   }
96 
97   if (event_loop_->RegisterSocket(
98           fd, kSocketEventReadable | kSocketEventWritable, this)) {
99     fd_address_map_[fd] = client_address;
100     std::move(closer).Cancel();
101     return true;
102   }
103   return false;
104 }
105 
CleanUpUDPSocket(SocketFd fd)106 void QuicClientDefaultNetworkHelper::CleanUpUDPSocket(SocketFd fd) {
107   CleanUpUDPSocketImpl(fd);
108   fd_address_map_.erase(fd);
109 }
110 
CleanUpAllUDPSockets()111 void QuicClientDefaultNetworkHelper::CleanUpAllUDPSockets() {
112   for (std::pair<int, QuicSocketAddress> fd_address : fd_address_map_) {
113     CleanUpUDPSocketImpl(fd_address.first);
114   }
115   fd_address_map_.clear();
116 }
117 
CleanUpUDPSocketImpl(SocketFd fd)118 void QuicClientDefaultNetworkHelper::CleanUpUDPSocketImpl(SocketFd fd) {
119   if (fd != kInvalidSocketFd) {
120     bool success = event_loop_->UnregisterSocket(fd);
121     QUICHE_DCHECK(success || fds_unregistered_externally_);
122     absl::Status rc = socket_api::Close(fd);
123     QUICHE_DCHECK(rc.ok()) << rc;
124   }
125 }
126 
RunEventLoop()127 void QuicClientDefaultNetworkHelper::RunEventLoop() {
128   quiche::QuicheRunSystemEventLoopIteration();
129   event_loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(50));
130 }
131 
OnSocketEvent(QuicEventLoop *,QuicUdpSocketFd fd,QuicSocketEventMask events)132 void QuicClientDefaultNetworkHelper::OnSocketEvent(
133     QuicEventLoop* /*event_loop*/, QuicUdpSocketFd fd,
134     QuicSocketEventMask events) {
135   if (events & kSocketEventReadable) {
136     QUIC_DVLOG(1) << "Read packets on kSocketEventReadable";
137     int times_to_read = max_reads_per_event_loop_;
138     bool more_to_read = true;
139     QuicPacketCount packets_dropped = 0;
140     while (client_->connected() && more_to_read && times_to_read > 0) {
141       more_to_read = packet_reader_->ReadAndDispatchPackets(
142           fd, GetLatestClientAddress().port(), *client_->helper()->GetClock(),
143           this, overflow_supported_ ? &packets_dropped : nullptr);
144       --times_to_read;
145     }
146     if (packets_dropped_ < packets_dropped) {
147       QUIC_LOG(ERROR)
148           << packets_dropped - packets_dropped_
149           << " more packets are dropped in the socket receive buffer.";
150       packets_dropped_ = packets_dropped;
151     }
152     if (client_->connected() && more_to_read) {
153       bool success =
154           event_loop_->ArtificiallyNotifyEvent(fd, kSocketEventReadable);
155       QUICHE_DCHECK(success);
156     } else if (!event_loop_->SupportsEdgeTriggered()) {
157       bool success = event_loop_->RearmSocket(fd, kSocketEventReadable);
158       QUICHE_DCHECK(success);
159     }
160   }
161   if (client_->connected() && (events & kSocketEventWritable)) {
162     client_->writer()->SetWritable();
163     client_->session()->connection()->OnCanWrite();
164   }
165 }
166 
CreateQuicPacketWriter()167 QuicPacketWriter* QuicClientDefaultNetworkHelper::CreateQuicPacketWriter() {
168   return CreateDefaultWriterForEventLoop(GetLatestFD(), event_loop_).release();
169 }
170 
SetClientPort(int port)171 void QuicClientDefaultNetworkHelper::SetClientPort(int port) {
172   fd_address_map_.back().second =
173       QuicSocketAddress(GetLatestClientAddress().host(), port);
174 }
175 
GetLatestClientAddress() const176 QuicSocketAddress QuicClientDefaultNetworkHelper::GetLatestClientAddress()
177     const {
178   if (fd_address_map_.empty()) {
179     return QuicSocketAddress();
180   }
181 
182   return fd_address_map_.back().second;
183 }
184 
GetLatestFD() const185 SocketFd QuicClientDefaultNetworkHelper::GetLatestFD() const {
186   if (fd_address_map_.empty()) {
187     return -1;
188   }
189 
190   return fd_address_map_.back().first;
191 }
192 
ProcessPacket(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,const QuicReceivedPacket & packet)193 void QuicClientDefaultNetworkHelper::ProcessPacket(
194     const QuicSocketAddress& self_address,
195     const QuicSocketAddress& peer_address, const QuicReceivedPacket& packet) {
196   client_->session()->ProcessUdpPacket(self_address, peer_address, packet);
197 }
198 
CreateUDPSocket(QuicSocketAddress server_address,bool * overflow_supported)199 SocketFd QuicClientDefaultNetworkHelper::CreateUDPSocket(
200     QuicSocketAddress server_address, bool* overflow_supported) {
201   QuicUdpSocketApi api;
202   SocketFd fd = api.Create(server_address.host().AddressFamilyToInt(),
203                            /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
204                            /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
205   if (fd == kInvalidSocketFd) {
206     return fd;
207   }
208 
209   *overflow_supported = api.EnableDroppedPacketCount(fd);
210   api.EnableReceiveTimestamp(fd);
211 
212   if (!BindInterfaceNameIfNeeded(fd)) {
213     CleanUpUDPSocket(fd);
214     return kQuicInvalidSocketFd;
215   }
216 
217   return fd;
218 }
219 
BindInterfaceNameIfNeeded(SocketFd fd)220 bool QuicClientDefaultNetworkHelper::BindInterfaceNameIfNeeded(SocketFd fd) {
221   QuicUdpSocketApi api;
222   std::string interface_name = client_->interface_name();
223   if (!interface_name.empty()) {
224     if (!api.BindInterface(fd, interface_name)) {
225       QUIC_DLOG(WARNING) << "Failed to bind socket (" << fd
226                          << ") to interface (" << interface_name << ").";
227       return false;
228     }
229   }
230   return true;
231 }
232 
233 }  // namespace quic
234