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