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/tools/quic/quic_client.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 "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"
26
27 #ifndef SO_RXQ_OVFL
28 #define SO_RXQ_OVFL 40
29 #endif
30
31 namespace net {
32 namespace tools {
33
34 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
35
QuicClient(IPEndPoint server_address,const QuicServerId & server_id,const QuicVersionVector & supported_versions,bool print_response,EpollServer * epoll_server)36 QuicClient::QuicClient(IPEndPoint server_address,
37 const QuicServerId& server_id,
38 const QuicVersionVector& supported_versions,
39 bool print_response,
40 EpollServer* epoll_server)
41 : server_address_(server_address),
42 server_id_(server_id),
43 local_port_(0),
44 epoll_server_(epoll_server),
45 fd_(-1),
46 helper_(CreateQuicConnectionHelper()),
47 initialized_(false),
48 packets_dropped_(0),
49 overflow_supported_(false),
50 supported_versions_(supported_versions),
51 print_response_(print_response) {
52 config_.SetDefaults();
53 }
54
QuicClient(IPEndPoint server_address,const QuicServerId & server_id,const QuicVersionVector & supported_versions,bool print_response,const QuicConfig & config,EpollServer * epoll_server)55 QuicClient::QuicClient(IPEndPoint server_address,
56 const QuicServerId& server_id,
57 const QuicVersionVector& supported_versions,
58 bool print_response,
59 const QuicConfig& config,
60 EpollServer* epoll_server)
61 : server_address_(server_address),
62 server_id_(server_id),
63 config_(config),
64 local_port_(0),
65 epoll_server_(epoll_server),
66 fd_(-1),
67 helper_(CreateQuicConnectionHelper()),
68 initialized_(false),
69 packets_dropped_(0),
70 overflow_supported_(false),
71 supported_versions_(supported_versions),
72 print_response_(print_response) {
73 }
74
~QuicClient()75 QuicClient::~QuicClient() {
76 if (connected()) {
77 session()->connection()->SendConnectionClosePacket(
78 QUIC_PEER_GOING_AWAY, "");
79 }
80 if (fd_ > 0) {
81 epoll_server_->UnregisterFD(fd_);
82 }
83 }
84
Initialize()85 bool QuicClient::Initialize() {
86 DCHECK(!initialized_);
87
88 epoll_server_->set_timeout_in_us(50 * 1000);
89 crypto_config_.SetDefaults();
90
91 if (!CreateUDPSocket()) {
92 return false;
93 }
94
95 epoll_server_->RegisterFD(fd_, this, kEpollFlags);
96 initialized_ = true;
97 return true;
98 }
99
CreateUDPSocket()100 bool QuicClient::CreateUDPSocket() {
101 int address_family = server_address_.GetSockAddrFamily();
102 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
103 if (fd_ < 0) {
104 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
105 return false;
106 }
107
108 int get_overflow = 1;
109 int rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
110 sizeof(get_overflow));
111 if (rc < 0) {
112 DLOG(WARNING) << "Socket overflow detection not supported";
113 } else {
114 overflow_supported_ = true;
115 }
116
117 if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
118 TcpReceiver::kReceiveWindowTCP)) {
119 return false;
120 }
121
122 if (!QuicSocketUtils::SetSendBufferSize(fd_,
123 TcpReceiver::kReceiveWindowTCP)) {
124 return false;
125 }
126
127 int get_local_ip = 1;
128 if (address_family == AF_INET) {
129 rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO,
130 &get_local_ip, sizeof(get_local_ip));
131 } else {
132 rc = setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVPKTINFO,
133 &get_local_ip, sizeof(get_local_ip));
134 }
135
136 if (rc < 0) {
137 LOG(ERROR) << "IP detection not supported" << strerror(errno);
138 return false;
139 }
140
141 if (bind_to_address_.size() != 0) {
142 client_address_ = IPEndPoint(bind_to_address_, local_port_);
143 } else if (address_family == AF_INET) {
144 IPAddressNumber any4;
145 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
146 client_address_ = IPEndPoint(any4, local_port_);
147 } else {
148 IPAddressNumber any6;
149 CHECK(net::ParseIPLiteralToNumber("::", &any6));
150 client_address_ = IPEndPoint(any6, local_port_);
151 }
152
153 sockaddr_storage raw_addr;
154 socklen_t raw_addr_len = sizeof(raw_addr);
155 CHECK(client_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
156 &raw_addr_len));
157 rc = bind(fd_,
158 reinterpret_cast<const sockaddr*>(&raw_addr),
159 sizeof(raw_addr));
160 if (rc < 0) {
161 LOG(ERROR) << "Bind failed: " << strerror(errno);
162 return false;
163 }
164
165 SockaddrStorage storage;
166 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
167 !client_address_.FromSockAddr(storage.addr, storage.addr_len)) {
168 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno);
169 }
170
171 return true;
172 }
173
Connect()174 bool QuicClient::Connect() {
175 if (!StartConnect()) {
176 return false;
177 }
178 while (EncryptionBeingEstablished()) {
179 WaitForEvents();
180 }
181 return session_->connection()->connected();
182 }
183
StartConnect()184 bool QuicClient::StartConnect() {
185 DCHECK(initialized_);
186 DCHECK(!connected());
187
188 QuicPacketWriter* writer = CreateQuicPacketWriter();
189 if (writer_.get() != writer) {
190 writer_.reset(writer);
191 }
192
193 session_.reset(new QuicClientSession(
194 server_id_,
195 config_,
196 new QuicConnection(GenerateConnectionId(), server_address_, helper_.get(),
197 writer_.get(), false, supported_versions_),
198 &crypto_config_));
199 return session_->CryptoConnect();
200 }
201
EncryptionBeingEstablished()202 bool QuicClient::EncryptionBeingEstablished() {
203 return !session_->IsEncryptionEstablished() &&
204 session_->connection()->connected();
205 }
206
Disconnect()207 void QuicClient::Disconnect() {
208 DCHECK(initialized_);
209
210 if (connected()) {
211 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
212 }
213 epoll_server_->UnregisterFD(fd_);
214 close(fd_);
215 fd_ = -1;
216 initialized_ = false;
217 }
218
SendRequestsAndWaitForResponse(const base::CommandLine::StringVector & args)219 void QuicClient::SendRequestsAndWaitForResponse(
220 const base::CommandLine::StringVector& args) {
221 for (size_t i = 0; i < args.size(); ++i) {
222 BalsaHeaders headers;
223 headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1");
224 QuicSpdyClientStream* stream = CreateReliableClientStream();
225 DCHECK(stream != NULL);
226 stream->SendRequest(headers, "", true);
227 stream->set_visitor(this);
228 }
229
230 while (WaitForEvents()) {}
231 }
232
CreateReliableClientStream()233 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() {
234 if (!connected()) {
235 return NULL;
236 }
237
238 return session_->CreateOutgoingDataStream();
239 }
240
WaitForStreamToClose(QuicStreamId id)241 void QuicClient::WaitForStreamToClose(QuicStreamId id) {
242 DCHECK(connected());
243
244 while (connected() && !session_->IsClosedStream(id)) {
245 epoll_server_->WaitForEventsAndExecuteCallbacks();
246 }
247 }
248
WaitForCryptoHandshakeConfirmed()249 void QuicClient::WaitForCryptoHandshakeConfirmed() {
250 DCHECK(connected());
251
252 while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
253 epoll_server_->WaitForEventsAndExecuteCallbacks();
254 }
255 }
256
WaitForEvents()257 bool QuicClient::WaitForEvents() {
258 DCHECK(connected());
259
260 epoll_server_->WaitForEventsAndExecuteCallbacks();
261 return session_->num_active_requests() != 0;
262 }
263
OnEvent(int fd,EpollEvent * event)264 void QuicClient::OnEvent(int fd, EpollEvent* event) {
265 DCHECK_EQ(fd, fd_);
266
267 if (event->in_events & EPOLLIN) {
268 while (connected() && ReadAndProcessPacket()) {
269 }
270 }
271 if (connected() && (event->in_events & EPOLLOUT)) {
272 writer_->SetWritable();
273 session_->connection()->OnCanWrite();
274 }
275 if (event->in_events & EPOLLERR) {
276 DVLOG(1) << "Epollerr";
277 }
278 }
279
OnClose(QuicDataStream * stream)280 void QuicClient::OnClose(QuicDataStream* stream) {
281 QuicSpdyClientStream* client_stream =
282 static_cast<QuicSpdyClientStream*>(stream);
283 if (response_listener_.get() != NULL) {
284 response_listener_->OnCompleteResponse(
285 stream->id(), client_stream->headers(), client_stream->data());
286 }
287
288 if (!print_response_) {
289 return;
290 }
291
292 const BalsaHeaders& headers = client_stream->headers();
293 printf("%s\n", headers.first_line().as_string().c_str());
294 for (BalsaHeaders::const_header_lines_iterator i =
295 headers.header_lines_begin();
296 i != headers.header_lines_end(); ++i) {
297 printf("%s: %s\n", i->first.as_string().c_str(),
298 i->second.as_string().c_str());
299 }
300 printf("%s\n", client_stream->data().c_str());
301 }
302
connected() const303 bool QuicClient::connected() const {
304 return session_.get() && session_->connection() &&
305 session_->connection()->connected();
306 }
307
GenerateConnectionId()308 QuicConnectionId QuicClient::GenerateConnectionId() {
309 return QuicRandom::GetInstance()->RandUint64();
310 }
311
CreateQuicConnectionHelper()312 QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() {
313 return new QuicEpollConnectionHelper(epoll_server_);
314 }
315
CreateQuicPacketWriter()316 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() {
317 return new QuicDefaultPacketWriter(fd_);
318 }
319
ReadPacket(char * buffer,int buffer_len,IPEndPoint * server_address,IPAddressNumber * client_ip)320 int QuicClient::ReadPacket(char* buffer,
321 int buffer_len,
322 IPEndPoint* server_address,
323 IPAddressNumber* client_ip) {
324 return QuicSocketUtils::ReadPacket(
325 fd_, buffer, buffer_len, overflow_supported_ ? &packets_dropped_ : NULL,
326 client_ip, server_address);
327 }
328
ReadAndProcessPacket()329 bool QuicClient::ReadAndProcessPacket() {
330 // Allocate some extra space so we can send an error if the server goes over
331 // the limit.
332 char buf[2 * kMaxPacketSize];
333
334 IPEndPoint server_address;
335 IPAddressNumber client_ip;
336
337 int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip);
338
339 if (bytes_read < 0) {
340 return false;
341 }
342
343 QuicEncryptedPacket packet(buf, bytes_read, false);
344
345 IPEndPoint client_address(client_ip, client_address_.port());
346 session_->connection()->ProcessUdpPacket(
347 client_address, server_address, packet);
348 return true;
349 }
350
351 } // namespace tools
352 } // namespace net
353