summaryrefslogtreecommitdiffstats
path: root/net/quic/quic_chromium_client_session.h
blob: 81d3c172dd981f12a699cb60e3d3be1a07e86f96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// A client specific QuicSession subclass.  This class owns the underlying
// QuicConnection and QuicConnectionHelper objects.  The connection stores
// a non-owning pointer to the helper so this session needs to ensure that
// the helper outlives the connection.

#ifndef NET_QUIC_QUIC_CHROMIUM_CLIENT_SESSION_H_
#define NET_QUIC_QUIC_CHROMIUM_CLIENT_SESSION_H_

#include <string>

#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
#include "net/base/socket_performance_watcher.h"
#include "net/proxy/proxy_server.h"
#include "net/quic/quic_client_session_base.h"
#include "net/quic/quic_connection_logger.h"
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_packet_reader.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_reliable_client_stream.h"

namespace net {

class CertVerifyResult;
class DatagramClientSocket;
class QuicConnectionHelper;
class QuicCryptoClientStreamFactory;
class QuicServerId;
class QuicServerInfo;
class QuicStreamFactory;
class SSLInfo;
class TransportSecurityState;

namespace test {
class QuicChromiumClientSessionPeer;
}  // namespace test

class NET_EXPORT_PRIVATE QuicChromiumClientSession
    : public QuicClientSessionBase,
      public QuicPacketReader::Visitor {
 public:
  // Reasons to disable QUIC, that is under certain pathological
  // connection errors.  Note: these values must be kept in sync with
  // the corresponding values of QuicDisabledReason in:
  // tools/metrics/histograms/histograms.xml
  enum QuicDisabledReason {
    QUIC_DISABLED_NOT = 0,  // default, not disabled
    QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE = 1,
    QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS = 2,
    QUIC_DISABLED_BAD_PACKET_LOSS_RATE = 3,
    QUIC_DISABLED_MAX = 4,
  };

  // An interface for observing events on a session.
  class NET_EXPORT_PRIVATE Observer {
   public:
    virtual ~Observer() {}
    virtual void OnCryptoHandshakeConfirmed() = 0;
    virtual void OnSessionClosed(int error) = 0;
  };

  // A helper class used to manage a request to create a stream.
  class NET_EXPORT_PRIVATE StreamRequest {
   public:
    StreamRequest();
    ~StreamRequest();

    // Starts a request to create a stream.  If OK is returned, then
    // |stream| will be updated with the newly created stream.  If
    // ERR_IO_PENDING is returned, then when the request is eventuallly
    // complete |callback| will be called.
    int StartRequest(const base::WeakPtr<QuicChromiumClientSession>& session,
                     QuicReliableClientStream** stream,
                     const CompletionCallback& callback);

    // Cancels any pending stream creation request. May be called
    // repeatedly.
    void CancelRequest();

   private:
    friend class QuicChromiumClientSession;

    // Called by |session_| for an asynchronous request when the stream
    // request has finished successfully.
    void OnRequestCompleteSuccess(QuicReliableClientStream* stream);

    // Called by |session_| for an asynchronous request when the stream
    // request has finished with an error. Also called with ERR_ABORTED
    // if |session_| is destroyed while the stream request is still pending.
    void OnRequestCompleteFailure(int rv);

    base::WeakPtr<QuicChromiumClientSession> session_;
    CompletionCallback callback_;
    QuicReliableClientStream** stream_;

    DISALLOW_COPY_AND_ASSIGN(StreamRequest);
  };

  // Constructs a new session which will own |connection|, but not
  // |stream_factory|, which must outlive this session.
  // TODO(rch): decouple the factory from the session via a Delegate interface.
  QuicChromiumClientSession(
      QuicConnection* connection,
      scoped_ptr<DatagramClientSocket> socket,
      QuicStreamFactory* stream_factory,
      QuicCryptoClientStreamFactory* crypto_client_stream_factory,
      TransportSecurityState* transport_security_state,
      scoped_ptr<QuicServerInfo> server_info,
      const QuicServerId& server_id,
      int cert_verify_flags,
      const QuicConfig& config,
      QuicCryptoClientConfig* crypto_config,
      const char* const connection_description,
      base::TimeTicks dns_resolution_end_time,
      base::TaskRunner* task_runner,
      scoped_ptr<SocketPerformanceWatcher> socket_performance_watcher,
      NetLog* net_log);
  ~QuicChromiumClientSession() override;

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Attempts to create a new stream.  If the stream can be
  // created immediately, returns OK.  If the open stream limit
  // has been reached, returns ERR_IO_PENDING, and |request|
  // will be added to the stream requets queue and will
  // be completed asynchronously.
  // TODO(rch): remove |stream| from this and use setter on |request|
  // and fix in spdy too.
  int TryCreateStream(StreamRequest* request,
                      QuicReliableClientStream** stream);

  // Cancels the pending stream creation request.
  void CancelRequest(StreamRequest* request);

  // QuicSession methods:
  void OnStreamFrame(const QuicStreamFrame& frame) override;
  QuicReliableClientStream* CreateOutgoingDynamicStream() override;
  QuicCryptoClientStream* GetCryptoStream() override;
  void CloseStream(QuicStreamId stream_id) override;
  void SendRstStream(QuicStreamId id,
                     QuicRstStreamErrorCode error,
                     QuicStreamOffset bytes_written) override;
  void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
  void OnCryptoHandshakeMessageSent(
      const CryptoHandshakeMessage& message) override;
  void OnCryptoHandshakeMessageReceived(
      const CryptoHandshakeMessage& message) override;

  // QuicClientSessionBase methods:
  void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override;
  void OnProofVerifyDetailsAvailable(
      const ProofVerifyDetails& verify_details) override;

  // QuicConnectionVisitorInterface methods:
  void OnConnectionClosed(QuicErrorCode error, bool from_peer) override;
  void OnSuccessfulVersionNegotiation(const QuicVersion& version) override;

  // QuicPacketReader::Visitor methods:
  void OnReadError(int result) override;
  bool OnPacket(const QuicEncryptedPacket& packet,
                IPEndPoint local_address,
                IPEndPoint peer_address) override;

  // Gets the SSL connection information.
  bool GetSSLInfo(SSLInfo* ssl_info) const;

  // Performs a crypto handshake with the server.
  int CryptoConnect(bool require_confirmation,
                    const CompletionCallback& callback);

  // Resumes a crypto handshake with the server after a timeout.
  int ResumeCryptoConnect(const CompletionCallback& callback);

  // Causes the QuicConnectionHelper to start reading from the socket
  // and passing the data along to the QuicConnection.
  void StartReading();

  // Close the session because of |error| and notifies the factory
  // that this session has been closed, which will delete the session.
  void CloseSessionOnError(int error, QuicErrorCode quic_error);

  // Close the session because of |error| and notifies the factory later that
  // this session has been closed, which will delete the session.
  void CloseSessionOnErrorAndNotifyFactoryLater(int error,
                                                QuicErrorCode quic_error);

  scoped_ptr<base::Value> GetInfoAsValue(const std::set<HostPortPair>& aliases);

  const BoundNetLog& net_log() const { return net_log_; }

  base::WeakPtr<QuicChromiumClientSession> GetWeakPtr();

  // Returns the number of client hello messages that have been sent on the
  // crypto stream. If the handshake has completed then this is one greater
  // than the number of round-trips needed for the handshake.
  int GetNumSentClientHellos() const;

  // Returns true if |hostname| may be pooled onto this session.  If this
  // is a secure QUIC session, then |hostname| must match the certificate
  // presented during the handshake.
  bool CanPool(const std::string& hostname, PrivacyMode privacy_mode) const;

  const QuicServerId& server_id() const { return server_id_; }

  QuicDisabledReason disabled_reason() const { return disabled_reason_; }

 protected:
  // QuicSession methods:
  QuicDataStream* CreateIncomingDynamicStream(QuicStreamId id) override;

 private:
  friend class test::QuicChromiumClientSessionPeer;

  typedef std::set<Observer*> ObserverSet;
  typedef std::list<StreamRequest*> StreamRequestQueue;

  QuicReliableClientStream* CreateOutgoingReliableStreamImpl();
  // A completion callback invoked when a read completes.
  void OnReadComplete(int result);

  void OnClosedStream();

  // Close the session because of |error| and records it in UMA histogram.
  void RecordAndCloseSessionOnError(int error, QuicErrorCode quic_error);

  // A Session may be closed via any of three methods:
  // OnConnectionClosed - called by the connection when the connection has been
  //     closed, perhaps due to a timeout or a protocol error.
  // CloseSessionOnError - called from the owner of the session,
  //     the QuicStreamFactory, when there is an error.
  // OnReadComplete - when there is a read error.
  // This method closes all stream and performs any necessary cleanup.
  void CloseSessionOnErrorInner(int net_error, QuicErrorCode quic_error);

  void CloseAllStreams(int net_error);
  void CloseAllObservers(int net_error);

  // Notifies the factory that this session is going away and no more streams
  // should be created from it.  This needs to be called before closing any
  // streams, because closing a stream may cause a new stream to be created.
  void NotifyFactoryOfSessionGoingAway();

  // Posts a task to notify the factory that this session has been closed.
  void NotifyFactoryOfSessionClosedLater();

  // Notifies the factory that this session has been closed which will
  // delete |this|.
  void NotifyFactoryOfSessionClosed();

  void OnConnectTimeout();

  QuicServerId server_id_;
  bool require_confirmation_;
  scoped_ptr<QuicCryptoClientStream> crypto_stream_;
  QuicStreamFactory* stream_factory_;
  scoped_ptr<DatagramClientSocket> socket_;
  TransportSecurityState* transport_security_state_;
  scoped_ptr<QuicServerInfo> server_info_;
  scoped_ptr<CertVerifyResult> cert_verify_result_;
  std::string pinning_failure_log_;
  ObserverSet observers_;
  StreamRequestQueue stream_requests_;
  CompletionCallback callback_;
  size_t num_total_streams_;
  base::TaskRunner* task_runner_;
  BoundNetLog net_log_;
  QuicPacketReader packet_reader_;
  base::TimeTicks dns_resolution_end_time_;
  base::TimeTicks handshake_start_;  // Time the handshake was started.
  scoped_ptr<QuicConnectionLogger> logger_;
  // True when the session is going away, and streams may no longer be created
  // on this session. Existing stream will continue to be processed.
  bool going_away_;
  QuicDisabledReason disabled_reason_;
  base::WeakPtrFactory<QuicChromiumClientSession> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(QuicChromiumClientSession);
};

}  // namespace net

#endif  // NET_QUIC_QUIC_CHROMIUM_CLIENT_SESSION_H_