blob: 2a9ebbac0dd761b06b91fdeeccee542fcd96b501 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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"
wubcfddec82020-01-13 07:45:27 -080022#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#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"
QUICHE teama6ef0a62019-03-07 20:34:33 -050025#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050026
27namespace quic {
28
29namespace {
30const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
31} // namespace
32
33QuicClientEpollNetworkHelper::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
43QuicClientEpollNetworkHelper::~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
vasilvvc48c8712019-03-11 13:38:16 -070053std::string QuicClientEpollNetworkHelper::Name() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050054 return "QuicClientEpollNetworkHelper";
55}
56
57bool 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) {
wub448f04c2020-01-23 07:51:13 -080080 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;
QUICHE teama6ef0a62019-03-07 20:34:33 -050084 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;
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 epoll_server_->RegisterFD(fd, this, kEpollFlags);
94 return true;
95}
96
97void QuicClientEpollNetworkHelper::CleanUpUDPSocket(int fd) {
98 CleanUpUDPSocketImpl(fd);
99 fd_address_map_.erase(fd);
100}
101
102void 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
109void 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
117void QuicClientEpollNetworkHelper::RunEventLoop() {
118 QuicRunSystemEventLoopIteration();
119 epoll_server_->WaitForEventsAndExecuteCallbacks();
120}
121
dschinazi17d42422019-06-18 16:35:07 -0700122void QuicClientEpollNetworkHelper::OnRegistration(QuicEpollServer* /*eps*/,
123 int /*fd*/,
124 int /*event_mask*/) {}
125void QuicClientEpollNetworkHelper::OnModification(int /*fd*/,
126 int /*event_mask*/) {}
127void QuicClientEpollNetworkHelper::OnUnregistration(int /*fd*/,
128 bool /*replaced*/) {}
129void QuicClientEpollNetworkHelper::OnShutdown(QuicEpollServer* /*eps*/,
130 int /*fd*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131
wub0790f062020-03-20 15:28:36 -0700132void QuicClientEpollNetworkHelper::OnEvent(int /*fd*/, QuicEpollEvent* event) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500133 if (event->in_events & EPOLLIN) {
bnc5de87052019-05-03 14:21:53 -0700134 QUIC_DVLOG(1) << "Read packets on EPOLLIN";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 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
164QuicPacketWriter* QuicClientEpollNetworkHelper::CreateQuicPacketWriter() {
165 return new QuicDefaultPacketWriter(GetLatestFD());
166}
167
168void QuicClientEpollNetworkHelper::SetClientPort(int port) {
169 fd_address_map_.back().second =
170 QuicSocketAddress(GetLatestClientAddress().host(), port);
171}
172
173QuicSocketAddress QuicClientEpollNetworkHelper::GetLatestClientAddress() const {
174 if (fd_address_map_.empty()) {
175 return QuicSocketAddress();
176 }
177
178 return fd_address_map_.back().second;
179}
180
181int QuicClientEpollNetworkHelper::GetLatestFD() const {
182 if (fd_address_map_.empty()) {
183 return -1;
184 }
185
186 return fd_address_map_.back().first;
187}
188
189void 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
196int QuicClientEpollNetworkHelper::CreateUDPSocket(
197 QuicSocketAddress server_address,
198 bool* overflow_supported) {
wubcfddec82020-01-13 07:45:27 -0800199 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;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500210}
211} // namespace quic