blob: a36781a370aff10779c125137041bf3234ef154c [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;
93
94 epoll_server_->RegisterFD(fd, this, kEpollFlags);
95 return true;
96}
97
98void QuicClientEpollNetworkHelper::CleanUpUDPSocket(int fd) {
99 CleanUpUDPSocketImpl(fd);
100 fd_address_map_.erase(fd);
101}
102
103void QuicClientEpollNetworkHelper::CleanUpAllUDPSockets() {
104 for (std::pair<int, QuicSocketAddress> fd_address : fd_address_map_) {
105 CleanUpUDPSocketImpl(fd_address.first);
106 }
107 fd_address_map_.clear();
108}
109
110void QuicClientEpollNetworkHelper::CleanUpUDPSocketImpl(int fd) {
111 if (fd > -1) {
112 epoll_server_->UnregisterFD(fd);
113 int rc = close(fd);
114 DCHECK_EQ(0, rc);
115 }
116}
117
118void QuicClientEpollNetworkHelper::RunEventLoop() {
119 QuicRunSystemEventLoopIteration();
120 epoll_server_->WaitForEventsAndExecuteCallbacks();
121}
122
dschinazi17d42422019-06-18 16:35:07 -0700123void QuicClientEpollNetworkHelper::OnRegistration(QuicEpollServer* /*eps*/,
124 int /*fd*/,
125 int /*event_mask*/) {}
126void QuicClientEpollNetworkHelper::OnModification(int /*fd*/,
127 int /*event_mask*/) {}
128void QuicClientEpollNetworkHelper::OnUnregistration(int /*fd*/,
129 bool /*replaced*/) {}
130void QuicClientEpollNetworkHelper::OnShutdown(QuicEpollServer* /*eps*/,
131 int /*fd*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500132
133void QuicClientEpollNetworkHelper::OnEvent(int fd, QuicEpollEvent* event) {
134 DCHECK_EQ(fd, GetLatestFD());
135
136 if (event->in_events & EPOLLIN) {
bnc5de87052019-05-03 14:21:53 -0700137 QUIC_DVLOG(1) << "Read packets on EPOLLIN";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138 int times_to_read = max_reads_per_epoll_loop_;
139 bool more_to_read = true;
140 QuicPacketCount packets_dropped = 0;
141 while (client_->connected() && more_to_read && times_to_read > 0) {
142 more_to_read = packet_reader_->ReadAndDispatchPackets(
143 GetLatestFD(), GetLatestClientAddress().port(),
144 *client_->helper()->GetClock(), this,
145 overflow_supported_ ? &packets_dropped : nullptr);
146 --times_to_read;
147 }
148 if (packets_dropped_ < packets_dropped) {
149 QUIC_LOG(ERROR)
150 << packets_dropped - packets_dropped_
151 << " more packets are dropped in the socket receive buffer.";
152 packets_dropped_ = packets_dropped;
153 }
154 if (client_->connected() && more_to_read) {
155 event->out_ready_mask |= EPOLLIN;
156 }
157 }
158 if (client_->connected() && (event->in_events & EPOLLOUT)) {
159 client_->writer()->SetWritable();
160 client_->session()->connection()->OnCanWrite();
161 }
162 if (event->in_events & EPOLLERR) {
163 QUIC_DLOG(INFO) << "Epollerr";
164 }
165}
166
167QuicPacketWriter* QuicClientEpollNetworkHelper::CreateQuicPacketWriter() {
168 return new QuicDefaultPacketWriter(GetLatestFD());
169}
170
171void QuicClientEpollNetworkHelper::SetClientPort(int port) {
172 fd_address_map_.back().second =
173 QuicSocketAddress(GetLatestClientAddress().host(), port);
174}
175
176QuicSocketAddress QuicClientEpollNetworkHelper::GetLatestClientAddress() const {
177 if (fd_address_map_.empty()) {
178 return QuicSocketAddress();
179 }
180
181 return fd_address_map_.back().second;
182}
183
184int QuicClientEpollNetworkHelper::GetLatestFD() const {
185 if (fd_address_map_.empty()) {
186 return -1;
187 }
188
189 return fd_address_map_.back().first;
190}
191
192void QuicClientEpollNetworkHelper::ProcessPacket(
193 const QuicSocketAddress& self_address,
194 const QuicSocketAddress& peer_address,
195 const QuicReceivedPacket& packet) {
196 client_->session()->ProcessUdpPacket(self_address, peer_address, packet);
197}
198
199int QuicClientEpollNetworkHelper::CreateUDPSocket(
200 QuicSocketAddress server_address,
201 bool* overflow_supported) {
wubcfddec82020-01-13 07:45:27 -0800202 QuicUdpSocketApi api;
203 int fd = api.Create(server_address.host().AddressFamilyToInt(),
204 /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
205 /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
206 if (fd < 0) {
207 return fd;
208 }
209
210 *overflow_supported = api.EnableDroppedPacketCount(fd);
211 api.EnableReceiveTimestamp(fd);
212 return fd;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213}
214} // namespace quic