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