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.
5 #include "net/tools/quic/quic_client.h"
8 #include <netinet/in.h>
10 #include <sys/epoll.h>
11 #include <sys/socket.h>
14 #include "base/logging.h"
15 #include "net/quic/congestion_control/tcp_receiver.h"
16 #include "net/quic/crypto/quic_random.h"
17 #include "net/quic/quic_connection.h"
18 #include "net/quic/quic_data_reader.h"
19 #include "net/quic/quic_protocol.h"
20 #include "net/quic/quic_server_id.h"
21 #include "net/tools/balsa/balsa_headers.h"
22 #include "net/tools/epoll_server/epoll_server.h"
23 #include "net/tools/quic/quic_epoll_connection_helper.h"
24 #include "net/tools/quic/quic_socket_utils.h"
25 #include "net/tools/quic/quic_spdy_client_stream.h"
28 #define SO_RXQ_OVFL 40
34 const int kEpollFlags
= EPOLLIN
| EPOLLOUT
| EPOLLET
;
36 QuicClient::QuicClient(IPEndPoint server_address
,
37 const QuicServerId
& server_id
,
38 const QuicVersionVector
& supported_versions
,
40 EpollServer
* epoll_server
)
41 : server_address_(server_address
),
42 server_id_(server_id
),
44 epoll_server_(epoll_server
),
46 helper_(CreateQuicConnectionHelper()),
49 overflow_supported_(false),
50 supported_versions_(supported_versions
),
51 print_response_(print_response
) {
54 QuicClient::QuicClient(IPEndPoint server_address
,
55 const QuicServerId
& server_id
,
56 const QuicVersionVector
& supported_versions
,
58 const QuicConfig
& config
,
59 EpollServer
* epoll_server
)
60 : server_address_(server_address
),
61 server_id_(server_id
),
64 epoll_server_(epoll_server
),
66 helper_(CreateQuicConnectionHelper()),
69 overflow_supported_(false),
70 supported_versions_(supported_versions
),
71 print_response_(print_response
) {
74 QuicClient::~QuicClient() {
76 session()->connection()->SendConnectionClosePacket(
77 QUIC_PEER_GOING_AWAY
, "");
80 epoll_server_
->UnregisterFD(fd_
);
84 bool QuicClient::Initialize() {
85 DCHECK(!initialized_
);
87 epoll_server_
->set_timeout_in_us(50 * 1000);
89 if (!CreateUDPSocket()) {
93 epoll_server_
->RegisterFD(fd_
, this, kEpollFlags
);
98 QuicClient::DummyPacketWriterFactory::DummyPacketWriterFactory(
99 QuicPacketWriter
* writer
)
102 QuicClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
104 QuicPacketWriter
* QuicClient::DummyPacketWriterFactory::Create(
105 QuicConnection
* /*connection*/) const {
110 bool QuicClient::CreateUDPSocket() {
111 int address_family
= server_address_
.GetSockAddrFamily();
112 fd_
= socket(address_family
, SOCK_DGRAM
| SOCK_NONBLOCK
, IPPROTO_UDP
);
114 LOG(ERROR
) << "CreateSocket() failed: " << strerror(errno
);
118 int get_overflow
= 1;
119 int rc
= setsockopt(fd_
, SOL_SOCKET
, SO_RXQ_OVFL
, &get_overflow
,
120 sizeof(get_overflow
));
122 DLOG(WARNING
) << "Socket overflow detection not supported";
124 overflow_supported_
= true;
127 if (!QuicSocketUtils::SetReceiveBufferSize(fd_
,
128 TcpReceiver::kReceiveWindowTCP
)) {
132 if (!QuicSocketUtils::SetSendBufferSize(fd_
,
133 TcpReceiver::kReceiveWindowTCP
)) {
137 rc
= QuicSocketUtils::SetGetAddressInfo(fd_
, address_family
);
139 LOG(ERROR
) << "IP detection not supported" << strerror(errno
);
143 if (bind_to_address_
.size() != 0) {
144 client_address_
= IPEndPoint(bind_to_address_
, local_port_
);
145 } else if (address_family
== AF_INET
) {
146 IPAddressNumber any4
;
147 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4
));
148 client_address_
= IPEndPoint(any4
, local_port_
);
150 IPAddressNumber any6
;
151 CHECK(net::ParseIPLiteralToNumber("::", &any6
));
152 client_address_
= IPEndPoint(any6
, local_port_
);
155 sockaddr_storage raw_addr
;
156 socklen_t raw_addr_len
= sizeof(raw_addr
);
157 CHECK(client_address_
.ToSockAddr(reinterpret_cast<sockaddr
*>(&raw_addr
),
160 reinterpret_cast<const sockaddr
*>(&raw_addr
),
163 LOG(ERROR
) << "Bind failed: " << strerror(errno
);
167 SockaddrStorage storage
;
168 if (getsockname(fd_
, storage
.addr
, &storage
.addr_len
) != 0 ||
169 !client_address_
.FromSockAddr(storage
.addr
, storage
.addr_len
)) {
170 LOG(ERROR
) << "Unable to get self address. Error: " << strerror(errno
);
176 bool QuicClient::Connect() {
177 if (!StartConnect()) {
180 while (EncryptionBeingEstablished()) {
183 return session_
->connection()->connected();
186 bool QuicClient::StartConnect() {
187 DCHECK(initialized_
);
188 DCHECK(!connected());
190 QuicPacketWriter
* writer
= CreateQuicPacketWriter();
192 DummyPacketWriterFactory
factory(writer
);
194 session_
.reset(new QuicClientSession(
196 new QuicConnection(GenerateConnectionId(),
200 /* owns_writer= */ false,
201 /* is_server= */ false,
202 server_id_
.is_https(),
203 supported_versions_
)));
205 // Reset |writer_| after |session_| so that the old writer outlives the old
207 if (writer_
.get() != writer
) {
208 writer_
.reset(writer
);
210 session_
->InitializeSession(server_id_
, &crypto_config_
);
211 return session_
->CryptoConnect();
214 bool QuicClient::EncryptionBeingEstablished() {
215 return !session_
->IsEncryptionEstablished() &&
216 session_
->connection()->connected();
219 void QuicClient::Disconnect() {
220 DCHECK(initialized_
);
223 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY
);
225 epoll_server_
->UnregisterFD(fd_
);
228 initialized_
= false;
231 void QuicClient::SendRequestsAndWaitForResponse(
232 const base::CommandLine::StringVector
& args
) {
233 for (size_t i
= 0; i
< args
.size(); ++i
) {
234 BalsaHeaders headers
;
235 headers
.SetRequestFirstlineFromStringPieces("GET", args
[i
], "HTTP/1.1");
236 QuicSpdyClientStream
* stream
= CreateReliableClientStream();
237 DCHECK(stream
!= nullptr);
238 if (stream
== nullptr) {
239 LOG(ERROR
) << "stream creation failed!";
242 stream
->SendRequest(headers
, "", true);
243 stream
->set_visitor(this);
246 while (WaitForEvents()) {}
249 QuicSpdyClientStream
* QuicClient::CreateReliableClientStream() {
254 return session_
->CreateOutgoingDataStream();
257 void QuicClient::WaitForStreamToClose(QuicStreamId id
) {
260 while (connected() && !session_
->IsClosedStream(id
)) {
261 epoll_server_
->WaitForEventsAndExecuteCallbacks();
265 void QuicClient::WaitForCryptoHandshakeConfirmed() {
268 while (connected() && !session_
->IsCryptoHandshakeConfirmed()) {
269 epoll_server_
->WaitForEventsAndExecuteCallbacks();
273 bool QuicClient::WaitForEvents() {
276 epoll_server_
->WaitForEventsAndExecuteCallbacks();
277 return session_
->num_active_requests() != 0;
280 void QuicClient::OnEvent(int fd
, EpollEvent
* event
) {
283 if (event
->in_events
& EPOLLIN
) {
284 while (connected() && ReadAndProcessPacket()) {
287 if (connected() && (event
->in_events
& EPOLLOUT
)) {
288 writer_
->SetWritable();
289 session_
->connection()->OnCanWrite();
291 if (event
->in_events
& EPOLLERR
) {
292 DVLOG(1) << "Epollerr";
296 void QuicClient::OnClose(QuicDataStream
* stream
) {
297 QuicSpdyClientStream
* client_stream
=
298 static_cast<QuicSpdyClientStream
*>(stream
);
299 if (response_listener_
.get() != nullptr) {
300 response_listener_
->OnCompleteResponse(
301 stream
->id(), client_stream
->headers(), client_stream
->data());
304 if (!print_response_
) {
308 const BalsaHeaders
& headers
= client_stream
->headers();
309 printf("%s\n", headers
.first_line().as_string().c_str());
310 for (BalsaHeaders::const_header_lines_iterator i
=
311 headers
.header_lines_begin();
312 i
!= headers
.header_lines_end(); ++i
) {
313 printf("%s: %s\n", i
->first
.as_string().c_str(),
314 i
->second
.as_string().c_str());
316 printf("%s\n", client_stream
->data().c_str());
319 bool QuicClient::connected() const {
320 return session_
.get() && session_
->connection() &&
321 session_
->connection()->connected();
324 bool QuicClient::goaway_received() const {
325 return session_
!= nullptr && session_
->goaway_received();
328 QuicConnectionId
QuicClient::GenerateConnectionId() {
329 return QuicRandom::GetInstance()->RandUint64();
332 QuicEpollConnectionHelper
* QuicClient::CreateQuicConnectionHelper() {
333 return new QuicEpollConnectionHelper(epoll_server_
);
336 QuicPacketWriter
* QuicClient::CreateQuicPacketWriter() {
337 return new QuicDefaultPacketWriter(fd_
);
340 int QuicClient::ReadPacket(char* buffer
,
342 IPEndPoint
* server_address
,
343 IPAddressNumber
* client_ip
) {
344 return QuicSocketUtils::ReadPacket(
345 fd_
, buffer
, buffer_len
,
346 overflow_supported_
? &packets_dropped_
: nullptr, client_ip
,
350 bool QuicClient::ReadAndProcessPacket() {
351 // Allocate some extra space so we can send an error if the server goes over
353 char buf
[2 * kMaxPacketSize
];
355 IPEndPoint server_address
;
356 IPAddressNumber client_ip
;
358 int bytes_read
= ReadPacket(buf
, arraysize(buf
), &server_address
, &client_ip
);
360 if (bytes_read
< 0) {
364 QuicEncryptedPacket
packet(buf
, bytes_read
, false);
366 IPEndPoint
client_address(client_ip
, client_address_
.port());
367 session_
->connection()->ProcessUdpPacket(
368 client_address
, server_address
, packet
);