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