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 "net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h"
6
7 #include <errno.h>
8 #include <netinet/in.h>
9 #include <string.h>
10 #include <sys/epoll.h>
11 #include <sys/socket.h>
12 #include <unistd.h>
13
14 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
15 #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
16 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
17 #include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
18 #include "net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h"
19 #include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
20 #include "net/third_party/quiche/src/quic/core/quic_packets.h"
21 #include "net/third_party/quiche/src/quic/core/quic_server_id.h"
22 #include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
23 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
24 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
25 #include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
26
27 namespace quic {
28
29 namespace {
30 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
31 } // namespace
32
QuicClientEpollNetworkHelper(QuicEpollServer * epoll_server,QuicClientBase * client)33 QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper(
34 QuicEpollServer* epoll_server,
35 QuicClientBase* client)
36 : epoll_server_(epoll_server),
37 packets_dropped_(0),
38 overflow_supported_(false),
39 packet_reader_(new QuicPacketReader()),
40 client_(client),
41 max_reads_per_epoll_loop_(std::numeric_limits<int>::max()) {}
42
~QuicClientEpollNetworkHelper()43 QuicClientEpollNetworkHelper::~QuicClientEpollNetworkHelper() {
44 if (client_->connected()) {
45 client_->session()->connection()->CloseConnection(
46 QUIC_PEER_GOING_AWAY, "Client being torn down",
47 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
48 }
49
50 CleanUpAllUDPSockets();
51 }
52
Name() const53 std::string QuicClientEpollNetworkHelper::Name() const {
54 return "QuicClientEpollNetworkHelper";
55 }
56
CreateUDPSocketAndBind(QuicSocketAddress server_address,QuicIpAddress bind_to_address,int bind_to_port)57 bool QuicClientEpollNetworkHelper::CreateUDPSocketAndBind(
58 QuicSocketAddress server_address,
59 QuicIpAddress bind_to_address,
60 int bind_to_port) {
61 epoll_server_->set_timeout_in_us(50 * 1000);
62
63 int fd = CreateUDPSocket(server_address, &overflow_supported_);
64 if (fd < 0) {
65 return false;
66 }
67
68 QuicSocketAddress client_address;
69 if (bind_to_address.IsInitialized()) {
70 client_address = QuicSocketAddress(bind_to_address, client_->local_port());
71 } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) {
72 client_address = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port);
73 } else {
74 client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port);
75 }
76
77 sockaddr_storage addr = client_address.generic_address();
78 int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
79 if (rc < 0) {
80 QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno)
81 << " bind_to_address:" << bind_to_address
82 << ", bind_to_port:" << bind_to_port
83 << ", client_address:" << client_address;
84 return false;
85 }
86
87 if (client_address.FromSocket(fd) != 0) {
88 QUIC_LOG(ERROR) << "Unable to get self address. Error: "
89 << strerror(errno);
90 }
91
92 fd_address_map_[fd] = client_address;
93 epoll_server_->RegisterFD(fd, this, kEpollFlags);
94 return true;
95 }
96
CleanUpUDPSocket(int fd)97 void QuicClientEpollNetworkHelper::CleanUpUDPSocket(int fd) {
98 CleanUpUDPSocketImpl(fd);
99 fd_address_map_.erase(fd);
100 }
101
CleanUpAllUDPSockets()102 void QuicClientEpollNetworkHelper::CleanUpAllUDPSockets() {
103 for (std::pair<int, QuicSocketAddress> fd_address : fd_address_map_) {
104 CleanUpUDPSocketImpl(fd_address.first);
105 }
106 fd_address_map_.clear();
107 }
108
CleanUpUDPSocketImpl(int fd)109 void QuicClientEpollNetworkHelper::CleanUpUDPSocketImpl(int fd) {
110 if (fd > -1) {
111 epoll_server_->UnregisterFD(fd);
112 int rc = close(fd);
113 DCHECK_EQ(0, rc);
114 }
115 }
116
RunEventLoop()117 void QuicClientEpollNetworkHelper::RunEventLoop() {
118 QuicRunSystemEventLoopIteration();
119 epoll_server_->WaitForEventsAndExecuteCallbacks();
120 }
121
OnRegistration(QuicEpollServer *,int,int)122 void QuicClientEpollNetworkHelper::OnRegistration(QuicEpollServer* /*eps*/,
123 int /*fd*/,
124 int /*event_mask*/) {}
OnModification(int,int)125 void QuicClientEpollNetworkHelper::OnModification(int /*fd*/,
126 int /*event_mask*/) {}
OnUnregistration(int,bool)127 void QuicClientEpollNetworkHelper::OnUnregistration(int /*fd*/,
128 bool /*replaced*/) {}
OnShutdown(QuicEpollServer *,int)129 void QuicClientEpollNetworkHelper::OnShutdown(QuicEpollServer* /*eps*/,
130 int /*fd*/) {}
131
OnEvent(int,QuicEpollEvent * event)132 void QuicClientEpollNetworkHelper::OnEvent(int /*fd*/, QuicEpollEvent* event) {
133 if (event->in_events & EPOLLIN) {
134 QUIC_DVLOG(1) << "Read packets on EPOLLIN";
135 int times_to_read = max_reads_per_epoll_loop_;
136 bool more_to_read = true;
137 QuicPacketCount packets_dropped = 0;
138 while (client_->connected() && more_to_read && times_to_read > 0) {
139 more_to_read = packet_reader_->ReadAndDispatchPackets(
140 GetLatestFD(), GetLatestClientAddress().port(),
141 *client_->helper()->GetClock(), this,
142 overflow_supported_ ? &packets_dropped : nullptr);
143 --times_to_read;
144 }
145 if (packets_dropped_ < packets_dropped) {
146 QUIC_LOG(ERROR)
147 << packets_dropped - packets_dropped_
148 << " more packets are dropped in the socket receive buffer.";
149 packets_dropped_ = packets_dropped;
150 }
151 if (client_->connected() && more_to_read) {
152 event->out_ready_mask |= EPOLLIN;
153 }
154 }
155 if (client_->connected() && (event->in_events & EPOLLOUT)) {
156 client_->writer()->SetWritable();
157 client_->session()->connection()->OnCanWrite();
158 }
159 if (event->in_events & EPOLLERR) {
160 QUIC_DLOG(INFO) << "Epollerr";
161 }
162 }
163
CreateQuicPacketWriter()164 QuicPacketWriter* QuicClientEpollNetworkHelper::CreateQuicPacketWriter() {
165 return new QuicDefaultPacketWriter(GetLatestFD());
166 }
167
SetClientPort(int port)168 void QuicClientEpollNetworkHelper::SetClientPort(int port) {
169 fd_address_map_.back().second =
170 QuicSocketAddress(GetLatestClientAddress().host(), port);
171 }
172
GetLatestClientAddress() const173 QuicSocketAddress QuicClientEpollNetworkHelper::GetLatestClientAddress() const {
174 if (fd_address_map_.empty()) {
175 return QuicSocketAddress();
176 }
177
178 return fd_address_map_.back().second;
179 }
180
GetLatestFD() const181 int QuicClientEpollNetworkHelper::GetLatestFD() const {
182 if (fd_address_map_.empty()) {
183 return -1;
184 }
185
186 return fd_address_map_.back().first;
187 }
188
ProcessPacket(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,const QuicReceivedPacket & packet)189 void QuicClientEpollNetworkHelper::ProcessPacket(
190 const QuicSocketAddress& self_address,
191 const QuicSocketAddress& peer_address,
192 const QuicReceivedPacket& packet) {
193 client_->session()->ProcessUdpPacket(self_address, peer_address, packet);
194 }
195
CreateUDPSocket(QuicSocketAddress server_address,bool * overflow_supported)196 int QuicClientEpollNetworkHelper::CreateUDPSocket(
197 QuicSocketAddress server_address,
198 bool* overflow_supported) {
199 QuicUdpSocketApi api;
200 int fd = api.Create(server_address.host().AddressFamilyToInt(),
201 /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
202 /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
203 if (fd < 0) {
204 return fd;
205 }
206
207 *overflow_supported = api.EnableDroppedPacketCount(fd);
208 api.EnableReceiveTimestamp(fd);
209 return fd;
210 }
211 } // namespace quic
212