[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 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/quic/quic_client_session.h" |
| 6 | |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 7 | #include "base/message_loop.h" |
| 8 | #include "base/stl_util.h" |
[email protected] | c5b061b | 2013-01-05 00:31:34 | [diff] [blame] | 9 | #include "base/string_number_conversions.h" |
| 10 | #include "base/values.h" |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 11 | #include "net/base/io_buffer.h" |
[email protected] | 8ee611b | 2012-11-20 01:48:12 | [diff] [blame] | 12 | #include "net/base/net_errors.h" |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 13 | #include "net/quic/quic_connection_helper.h" |
[email protected] | e8ff2684 | 2013-03-22 21:02:05 | [diff] [blame] | 14 | #include "net/quic/quic_crypto_client_stream_factory.h" |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 15 | #include "net/quic/quic_stream_factory.h" |
| 16 | #include "net/udp/datagram_client_socket.h" |
[email protected] | 8ee611b | 2012-11-20 01:48:12 | [diff] [blame] | 17 | |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 18 | namespace net { |
| 19 | |
[email protected] | e8ff2684 | 2013-03-22 21:02:05 | [diff] [blame] | 20 | QuicClientSession::QuicClientSession( |
| 21 | QuicConnection* connection, |
| 22 | DatagramClientSocket* socket, |
| 23 | QuicStreamFactory* stream_factory, |
| 24 | QuicCryptoClientStreamFactory* crypto_client_stream_factory, |
| 25 | const string& server_hostname, |
[email protected] | ef95114d | 2013-04-17 17:57:01 | [diff] [blame^] | 26 | QuicCryptoClientConfig* crypto_config, |
[email protected] | e8ff2684 | 2013-03-22 21:02:05 | [diff] [blame] | 27 | NetLog* net_log) |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 28 | : QuicSession(connection, false), |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 29 | ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 30 | stream_factory_(stream_factory), |
[email protected] | 6dcd1d5c | 2013-03-15 07:28:37 | [diff] [blame] | 31 | socket_(socket), |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 32 | read_buffer_(new IOBufferWithSize(kMaxPacketSize)), |
[email protected] | 0d10b59 | 2013-02-14 16:09:26 | [diff] [blame] | 33 | read_pending_(false), |
| 34 | num_total_streams_(0), |
[email protected] | 78b9fcd3 | 2013-02-20 17:10:24 | [diff] [blame] | 35 | net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)), |
| 36 | logger_(net_log_) { |
[email protected] | ef95114d | 2013-04-17 17:57:01 | [diff] [blame^] | 37 | 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] | 78b9fcd3 | 2013-02-20 17:10:24 | [diff] [blame] | 45 | connection->set_debug_visitor(&logger_); |
[email protected] | 0d10b59 | 2013-02-14 16:09:26 | [diff] [blame] | 46 | // 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] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | QuicClientSession::~QuicClientSession() { |
[email protected] | 78b9fcd3 | 2013-02-20 17:10:24 | [diff] [blame] | 53 | connection()->set_debug_visitor(NULL); |
[email protected] | 0d10b59 | 2013-02-14 16:09:26 | [diff] [blame] | 54 | net_log_.EndEvent(NetLog::TYPE_QUIC_SESSION); |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | QuicReliableClientStream* QuicClientSession::CreateOutgoingReliableStream() { |
[email protected] | e8ff2684 | 2013-03-22 21:02:05 | [diff] [blame] | 58 | if (!crypto_stream_->handshake_complete()) { |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 59 | 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] | 9db44391 | 2013-02-25 05:27:03 | [diff] [blame] | 67 | if (goaway_received()) { |
| 68 | DLOG(INFO) << "Failed to create a new outgoing stream. " |
| 69 | << "Already received goaway."; |
| 70 | return NULL; |
| 71 | } |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 72 | QuicReliableClientStream* stream = |
[email protected] | 0d10b59 | 2013-02-14 16:09:26 | [diff] [blame] | 73 | new QuicReliableClientStream(GetNextStreamId(), this, net_log_); |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 74 | ActivateStream(stream); |
[email protected] | 0d10b59 | 2013-02-14 16:09:26 | [diff] [blame] | 75 | ++num_total_streams_; |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 76 | return stream; |
| 77 | } |
| 78 | |
| 79 | QuicCryptoClientStream* QuicClientSession::GetCryptoStream() { |
[email protected] | e8ff2684 | 2013-03-22 21:02:05 | [diff] [blame] | 80 | return crypto_stream_.get(); |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 81 | }; |
| 82 | |
[email protected] | 8ee611b | 2012-11-20 01:48:12 | [diff] [blame] | 83 | int QuicClientSession::CryptoConnect(const CompletionCallback& callback) { |
[email protected] | e8ff2684 | 2013-03-22 21:02:05 | [diff] [blame] | 84 | if (!crypto_stream_->CryptoConnect()) { |
[email protected] | 872edd9e | 2013-01-16 08:51:15 | [diff] [blame] | 85 | // 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] | 8ee611b | 2012-11-20 01:48:12 | [diff] [blame] | 89 | |
| 90 | if (IsCryptoHandshakeComplete()) { |
| 91 | return OK; |
| 92 | } |
| 93 | |
| 94 | callback_ = callback; |
| 95 | return ERR_IO_PENDING; |
[email protected] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | ReliableQuicStream* QuicClientSession::CreateIncomingReliableStream( |
| 99 | QuicStreamId id) { |
| 100 | DLOG(ERROR) << "Server push not supported"; |
| 101 | return NULL; |
| 102 | } |
| 103 | |
[email protected] | f702d57 | 2012-12-04 15:56:20 | [diff] [blame] | 104 | void QuicClientSession::CloseStream(QuicStreamId stream_id) { |
| 105 | QuicSession::CloseStream(stream_id); |
| 106 | |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 107 | if (GetNumOpenStreams() == 0) { |
| 108 | stream_factory_->OnIdleSession(this); |
| 109 | } |
[email protected] | f702d57 | 2012-12-04 15:56:20 | [diff] [blame] | 110 | } |
| 111 | |
[email protected] | 8ee611b | 2012-11-20 01:48:12 | [diff] [blame] | 112 | void QuicClientSession::OnCryptoHandshakeComplete(QuicErrorCode error) { |
| 113 | if (!callback_.is_null()) { |
| 114 | callback_.Run(error == QUIC_NO_ERROR ? OK : ERR_UNEXPECTED); |
| 115 | } |
| 116 | } |
| 117 | |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 118 | void QuicClientSession::StartReading() { |
| 119 | if (read_pending_) { |
| 120 | return; |
| 121 | } |
| 122 | read_pending_ = true; |
[email protected] | 6dcd1d5c | 2013-03-15 07:28:37 | [diff] [blame] | 123 | int rv = socket_->Read(read_buffer_, read_buffer_->size(), |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 124 | 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] | 56dfb90 | 2013-01-03 23:17:55 | [diff] [blame] | 139 | void 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] | 0d10b59 | 2013-02-14 16:09:26 | [diff] [blame] | 146 | net_log_.BeginEvent( |
| 147 | NetLog::TYPE_QUIC_SESSION, |
| 148 | NetLog::IntegerCallback("net_error", error)); |
| 149 | // Will delete |this|. |
[email protected] | 56dfb90 | 2013-01-03 23:17:55 | [diff] [blame] | 150 | stream_factory_->OnSessionClose(this); |
| 151 | } |
| 152 | |
[email protected] | c5b061b | 2013-01-05 00:31:34 | [diff] [blame] | 153 | Value* 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] | 0d10b59 | 2013-02-14 16:09:26 | [diff] [blame] | 157 | dict->SetInteger("total_streams", num_total_streams_); |
[email protected] | c5b061b | 2013-01-05 00:31:34 | [diff] [blame] | 158 | dict->SetString("peer_address", peer_address().ToString()); |
| 159 | dict->SetString("guid", base::Uint64ToString(guid())); |
| 160 | return dict; |
| 161 | } |
| 162 | |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 163 | void 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] | 6dcd1d5c | 2013-03-15 07:28:37 | [diff] [blame] | 172 | socket_->GetLocalAddress(&local_address); |
| 173 | socket_->GetPeerAddress(&peer_address); |
[email protected] | e13201d8 | 2012-12-12 05:00:32 | [diff] [blame] | 174 | // 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] | dd3fd0e | 2012-11-04 05:14:40 | [diff] [blame] | 185 | } // namespace net |