blob: 5e1e80f6911d9638a762af842a4aae75fb547f89 [file] [log] [blame]
[email protected]dd3fd0e2012-11-04 05:14:401// 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/quic/quic_client_session.h"
6
[email protected]e13201d82012-12-12 05:00:327#include "base/message_loop.h"
8#include "base/stl_util.h"
[email protected]c5b061b2013-01-05 00:31:349#include "base/string_number_conversions.h"
10#include "base/values.h"
[email protected]e13201d82012-12-12 05:00:3211#include "net/base/io_buffer.h"
[email protected]8ee611b2012-11-20 01:48:1212#include "net/base/net_errors.h"
[email protected]e13201d82012-12-12 05:00:3213#include "net/quic/quic_connection_helper.h"
[email protected]e8ff26842013-03-22 21:02:0514#include "net/quic/quic_crypto_client_stream_factory.h"
[email protected]e13201d82012-12-12 05:00:3215#include "net/quic/quic_stream_factory.h"
16#include "net/udp/datagram_client_socket.h"
[email protected]8ee611b2012-11-20 01:48:1217
[email protected]dd3fd0e2012-11-04 05:14:4018namespace net {
19
[email protected]e8ff26842013-03-22 21:02:0520QuicClientSession::QuicClientSession(
21 QuicConnection* connection,
22 DatagramClientSocket* socket,
23 QuicStreamFactory* stream_factory,
24 QuicCryptoClientStreamFactory* crypto_client_stream_factory,
25 const string& server_hostname,
[email protected]ef95114d2013-04-17 17:57:0126 QuicCryptoClientConfig* crypto_config,
[email protected]e8ff26842013-03-22 21:02:0527 NetLog* net_log)
[email protected]dd3fd0e2012-11-04 05:14:4028 : QuicSession(connection, false),
[email protected]e13201d82012-12-12 05:00:3229 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
[email protected]e13201d82012-12-12 05:00:3230 stream_factory_(stream_factory),
[email protected]6dcd1d5c2013-03-15 07:28:3731 socket_(socket),
[email protected]e13201d82012-12-12 05:00:3232 read_buffer_(new IOBufferWithSize(kMaxPacketSize)),
[email protected]0d10b592013-02-14 16:09:2633 read_pending_(false),
34 num_total_streams_(0),
[email protected]78b9fcd32013-02-20 17:10:2435 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)),
36 logger_(net_log_) {
[email protected]ef95114d2013-04-17 17:57:0137 config_.SetDefaults();
38 crypto_stream_.reset(
39 crypto_client_stream_factory ?
40 crypto_client_stream_factory->CreateQuicCryptoClientStream(
41 server_hostname, config_, this, crypto_config) :
42 new QuicCryptoClientStream(
43 server_hostname, config_, this, crypto_config));
44
[email protected]78b9fcd32013-02-20 17:10:2445 connection->set_debug_visitor(&logger_);
[email protected]0d10b592013-02-14 16:09:2646 // TODO(rch): pass in full host port proxy pair
47 net_log_.BeginEvent(
48 NetLog::TYPE_QUIC_SESSION,
49 NetLog::StringCallback("host", &server_hostname));
[email protected]dd3fd0e2012-11-04 05:14:4050}
51
52QuicClientSession::~QuicClientSession() {
[email protected]78b9fcd32013-02-20 17:10:2453 connection()->set_debug_visitor(NULL);
[email protected]0d10b592013-02-14 16:09:2654 net_log_.EndEvent(NetLog::TYPE_QUIC_SESSION);
[email protected]dd3fd0e2012-11-04 05:14:4055}
56
57QuicReliableClientStream* QuicClientSession::CreateOutgoingReliableStream() {
[email protected]e8ff26842013-03-22 21:02:0558 if (!crypto_stream_->handshake_complete()) {
[email protected]dd3fd0e2012-11-04 05:14:4059 DLOG(INFO) << "Crypto handshake not complete, no outgoing stream created.";
60 return NULL;
61 }
62 if (GetNumOpenStreams() >= get_max_open_streams()) {
63 DLOG(INFO) << "Failed to create a new outgoing stream. "
64 << "Already " << GetNumOpenStreams() << " open.";
65 return NULL;
66 }
[email protected]9db443912013-02-25 05:27:0367 if (goaway_received()) {
68 DLOG(INFO) << "Failed to create a new outgoing stream. "
69 << "Already received goaway.";
70 return NULL;
71 }
[email protected]dd3fd0e2012-11-04 05:14:4072 QuicReliableClientStream* stream =
[email protected]0d10b592013-02-14 16:09:2673 new QuicReliableClientStream(GetNextStreamId(), this, net_log_);
[email protected]dd3fd0e2012-11-04 05:14:4074 ActivateStream(stream);
[email protected]0d10b592013-02-14 16:09:2675 ++num_total_streams_;
[email protected]dd3fd0e2012-11-04 05:14:4076 return stream;
77}
78
79QuicCryptoClientStream* QuicClientSession::GetCryptoStream() {
[email protected]e8ff26842013-03-22 21:02:0580 return crypto_stream_.get();
[email protected]dd3fd0e2012-11-04 05:14:4081};
82
[email protected]8ee611b2012-11-20 01:48:1283int QuicClientSession::CryptoConnect(const CompletionCallback& callback) {
[email protected]e8ff26842013-03-22 21:02:0584 if (!crypto_stream_->CryptoConnect()) {
[email protected]872edd9e2013-01-16 08:51:1585 // TODO(wtc): change crypto_stream_.CryptoConnect() to return a
86 // QuicErrorCode and map it to a net error code.
87 return ERR_CONNECTION_FAILED;
88 }
[email protected]8ee611b2012-11-20 01:48:1289
90 if (IsCryptoHandshakeComplete()) {
91 return OK;
92 }
93
94 callback_ = callback;
95 return ERR_IO_PENDING;
[email protected]dd3fd0e2012-11-04 05:14:4096}
97
98ReliableQuicStream* QuicClientSession::CreateIncomingReliableStream(
99 QuicStreamId id) {
100 DLOG(ERROR) << "Server push not supported";
101 return NULL;
102}
103
[email protected]f702d572012-12-04 15:56:20104void QuicClientSession::CloseStream(QuicStreamId stream_id) {
105 QuicSession::CloseStream(stream_id);
106
[email protected]e13201d82012-12-12 05:00:32107 if (GetNumOpenStreams() == 0) {
108 stream_factory_->OnIdleSession(this);
109 }
[email protected]f702d572012-12-04 15:56:20110}
111
[email protected]8ee611b2012-11-20 01:48:12112void QuicClientSession::OnCryptoHandshakeComplete(QuicErrorCode error) {
113 if (!callback_.is_null()) {
114 callback_.Run(error == QUIC_NO_ERROR ? OK : ERR_UNEXPECTED);
115 }
116}
117
[email protected]e13201d82012-12-12 05:00:32118void QuicClientSession::StartReading() {
119 if (read_pending_) {
120 return;
121 }
122 read_pending_ = true;
[email protected]6dcd1d5c2013-03-15 07:28:37123 int rv = socket_->Read(read_buffer_, read_buffer_->size(),
[email protected]e13201d82012-12-12 05:00:32124 base::Bind(&QuicClientSession::OnReadComplete,
125 weak_factory_.GetWeakPtr()));
126 if (rv == ERR_IO_PENDING) {
127 return;
128 }
129
130 // Data was read, process it.
131 // Schedule the work through the message loop to avoid recursive
132 // callbacks.
133 MessageLoop::current()->PostTask(
134 FROM_HERE,
135 base::Bind(&QuicClientSession::OnReadComplete,
136 weak_factory_.GetWeakPtr(), rv));
137}
138
[email protected]56dfb902013-01-03 23:17:55139void QuicClientSession::CloseSessionOnError(int error) {
140 while (!streams()->empty()) {
141 ReliableQuicStream* stream = streams()->begin()->second;
142 QuicStreamId id = stream->id();
143 static_cast<QuicReliableClientStream*>(stream)->OnError(error);
144 CloseStream(id);
145 }
[email protected]0d10b592013-02-14 16:09:26146 net_log_.BeginEvent(
147 NetLog::TYPE_QUIC_SESSION,
148 NetLog::IntegerCallback("net_error", error));
149 // Will delete |this|.
[email protected]56dfb902013-01-03 23:17:55150 stream_factory_->OnSessionClose(this);
151}
152
[email protected]c5b061b2013-01-05 00:31:34153Value* QuicClientSession::GetInfoAsValue(const HostPortPair& pair) const {
154 DictionaryValue* dict = new DictionaryValue();
155 dict->SetString("host_port_pair", pair.ToString());
156 dict->SetInteger("open_streams", GetNumOpenStreams());
[email protected]0d10b592013-02-14 16:09:26157 dict->SetInteger("total_streams", num_total_streams_);
[email protected]c5b061b2013-01-05 00:31:34158 dict->SetString("peer_address", peer_address().ToString());
159 dict->SetString("guid", base::Uint64ToString(guid()));
160 return dict;
161}
162
[email protected]e13201d82012-12-12 05:00:32163void QuicClientSession::OnReadComplete(int result) {
164 read_pending_ = false;
165 // TODO(rch): Inform the connection about the result.
166 if (result > 0) {
167 scoped_refptr<IOBufferWithSize> buffer(read_buffer_);
168 read_buffer_ = new IOBufferWithSize(kMaxPacketSize);
169 QuicEncryptedPacket packet(buffer->data(), result);
170 IPEndPoint local_address;
171 IPEndPoint peer_address;
[email protected]6dcd1d5c2013-03-15 07:28:37172 socket_->GetLocalAddress(&local_address);
173 socket_->GetPeerAddress(&peer_address);
[email protected]e13201d82012-12-12 05:00:32174 // ProcessUdpPacket might result in |this| being deleted, so we
175 // use a weak pointer to be safe.
176 connection()->ProcessUdpPacket(local_address, peer_address, packet);
177 if (!connection()->connected()) {
178 stream_factory_->OnSessionClose(this);
179 return;
180 }
181 StartReading();
182 }
183}
184
[email protected]dd3fd0e2012-11-04 05:14:40185} // namespace net