• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
6 #define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
7 
8 // This file is included from net/http files.
9 // Since net/http can be built without linking net/websockets code,
10 // this file must not introduce any link-time dependencies on websockets.
11 
12 #include <memory>
13 #include <set>
14 #include <string>
15 #include <vector>
16 
17 #include "base/memory/weak_ptr.h"
18 #include "base/supports_user_data.h"
19 #include "net/base/net_export.h"
20 #include "net/http/http_stream.h"
21 #include "net/quic/quic_chromium_client_session.h"
22 #include "net/websockets/websocket_deflate_parameters.h"
23 #include "net/websockets/websocket_stream.h"
24 
25 namespace net {
26 
27 class ClientSocketHandle;
28 class SpdySession;
29 class HttpRequestHeaders;
30 class HttpResponseHeaders;
31 class WebSocketEndpointLockManager;
32 
33 // WebSocketHandshakeStreamBase is the base class of
34 // WebSocketBasicHandshakeStream.  net/http code uses this interface to handle
35 // WebSocketBasicHandshakeStream when it needs to be treated differently from
36 // HttpStreamBase.
37 class NET_EXPORT WebSocketHandshakeStreamBase : public HttpStream {
38  public:
39   // These entries must match histogram Net.WebSocket.HandshakeResult2.
40   // Do not change or reuse values.
41   enum class HandshakeResult {
42     // Handshake not completed via Upgrade over HTTP/1 connection.
43     INCOMPLETE = 0,
44     // Server responded to Upgrade request with invalid status.
45     INVALID_STATUS = 1,
46     // Server responded to Upgrade request with empty response.
47     EMPTY_RESPONSE = 2,
48     // Server responded to Upgrade request with 101 status but there was some
49     // other network error.
50     FAILED_SWITCHING_PROTOCOLS = 3,
51     // Server responded to Upgrade request with invalid Upgrade header.
52     FAILED_UPGRADE = 4,
53     // Server responded to Upgrade request with invalid Sec-WebSocket-Accept
54     // header.
55     FAILED_ACCEPT = 5,
56     // Server responded to Upgrade request with invalid Connection header.
57     FAILED_CONNECTION = 6,
58     // Server responded to Upgrade request with invalid Sec-WebSocket-Protocol
59     // header.
60     FAILED_SUBPROTO = 7,
61     // Server responded to Upgrade request with invalid Sec-WebSocket-Extensions
62     // header.
63     FAILED_EXTENSIONS = 8,
64     // Upgrade request failed due to other network error.
65     FAILED = 9,
66     // Connected via Upgrade over HTTP/1 connection.
67     CONNECTED = 10,
68     // Handshake not completed over an HTTP/2 connection.
69     HTTP2_INCOMPLETE = 11,
70     // Server responded to WebSocket request over an HTTP/2 connection with
71     // invalid status code.
72     HTTP2_INVALID_STATUS = 12,
73     // Server responded to WebSocket request over an HTTP/2 connection with
74     // invalid sec-websocket-protocol header.
75     HTTP2_FAILED_SUBPROTO = 13,
76     // Server responded to WebSocket request over an HTTP/2 connection with
77     // invalid sec-websocket-extensions header.
78     HTTP2_FAILED_EXTENSIONS = 14,
79     // WebSocket request over an HTTP/2 connection failed with some other error.
80     HTTP2_FAILED = 15,
81     // Connected over an HTTP/2 connection.
82     HTTP2_CONNECTED = 16,
83     // Handshake not completed over an HTTP/3 connection.
84     HTTP3_INCOMPLETE = 17,
85     // Server responded to WebSocket request over an HTTP/3 connection with
86     // invalid status code.
87     HTTP3_INVALID_STATUS = 18,
88     // Server responded to WebSocket request over an HTTP/3 connection with
89     // invalid sec-websocket-protocol header.
90     HTTP3_FAILED_SUBPROTO = 19,
91     // Server responded to WebSocket request over an HTTP/3 connection with
92     // invalid sec-websocket-extensions header.
93     HTTP3_FAILED_EXTENSIONS = 20,
94     // WebSocket request over an HTTP/3 connection failed with some other error.
95     HTTP3_FAILED = 21,
96     // Connected over an HTTP/3 connection.
97     HTTP3_CONNECTED = 22,
98     NUM_HANDSHAKE_RESULT_TYPES = 23
99   };
100 
101   WebSocketHandshakeStreamBase() = default;
102 
103   WebSocketHandshakeStreamBase(const WebSocketHandshakeStreamBase&) = delete;
104   WebSocketHandshakeStreamBase& operator=(const WebSocketHandshakeStreamBase&) =
105       delete;
106 
107   ~WebSocketHandshakeStreamBase() override = default;
108 
109   // An object that stores data needed for the creation of a
110   // WebSocketBasicHandshakeStream object. A new CreateHelper is used for each
111   // WebSocket connection.
112   class NET_EXPORT_PRIVATE CreateHelper : public base::SupportsUserData::Data {
113    public:
114     ~CreateHelper() override = default;
115 
116     // Create a WebSocketBasicHandshakeStream. This is called after the
117     // underlying connection has been established but before any handshake data
118     // has been transferred. This can be called more than once in the case that
119     // HTTP authentication is needed.
120     virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
121         std::unique_ptr<ClientSocketHandle> connection,
122         bool using_proxy,
123         WebSocketEndpointLockManager* websocket_endpoint_lock_manager) = 0;
124 
125     // Create a WebSocketHttp2HandshakeStream. This is called after the
126     // underlying HTTP/2 connection has been established but before the stream
127     // has been opened.  This cannot be called more than once.
128     virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
129         base::WeakPtr<SpdySession> session,
130         std::set<std::string> dns_aliases) = 0;
131 
132     // Create a WebSocketHttp3HandshakeStream. This is called after the
133     // underlying HTTP/3 connection has been established but before the stream
134     // has been opened.  This cannot be called more than once.
135     virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream(
136         std::unique_ptr<QuicChromiumClientSession::Handle> session,
137         std::set<std::string> dns_aliases) = 0;
138   };
139 
140   // After the handshake has completed, this method creates a WebSocketStream
141   // (of the appropriate type) from the WebSocketHandshakeStreamBase object.
142   // The WebSocketHandshakeStreamBase object is unusable after Upgrade() has
143   // been called.
144   virtual std::unique_ptr<WebSocketStream> Upgrade() = 0;
145 
SetRequestHeadersCallback(RequestHeadersCallback callback)146   void SetRequestHeadersCallback(RequestHeadersCallback callback) override {}
147 
148   static std::string MultipleHeaderValuesMessage(
149       const std::string& header_name);
150 
151   // Subclasses need to implement this method so that the resulting weak
152   // pointers are invalidated as soon as the derived class is destroyed.
153   virtual base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() = 0;
154 
155  protected:
156   // TODO(ricea): If more extensions are added, replace this with a more general
157   // mechanism.
158   struct WebSocketExtensionParams {
159     bool deflate_enabled = false;
160     WebSocketDeflateParameters deflate_parameters;
161   };
162 
163   static void AddVectorHeaderIfNonEmpty(const char* name,
164                                         const std::vector<std::string>& value,
165                                         HttpRequestHeaders* headers);
166 
167   static bool ValidateSubProtocol(
168       const HttpResponseHeaders* headers,
169       const std::vector<std::string>& requested_sub_protocols,
170       std::string* sub_protocol,
171       std::string* failure_message);
172 
173   static bool ValidateExtensions(const HttpResponseHeaders* headers,
174                                  std::string* accepted_extensions_descriptor,
175                                  std::string* failure_message,
176                                  WebSocketExtensionParams* params);
177 
178   void RecordHandshakeResult(HandshakeResult result);
179 };
180 
181 }  // namespace net
182 
183 #endif  // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
184