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