blob: 4fa19ad30f50f03aae1974cbdd577e0d8eb79ccb [file] [log] [blame]
[email protected]a9cf2b92013-10-30 12:08:491// Copyright 2013 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#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
danakj9c5cab52016-04-16 00:54:3312#include <memory>
[email protected]96868202014-01-09 10:38:0413#include <string>
Bence Békyb28709c22018-03-06 13:03:4414#include <vector>
[email protected]96868202014-01-09 10:38:0415
tfarinaea94afc232015-10-20 04:23:3616#include "base/macros.h"
[email protected]a9cf2b92013-10-30 12:08:4917#include "base/memory/weak_ptr.h"
[email protected]f4533ba2013-11-28 09:35:4118#include "base/supports_user_data.h"
bnc81c46c1f2016-10-04 16:25:5919#include "net/base/net_export.h"
yhiranoa7e05bb2014-11-06 05:40:3920#include "net/http/http_stream.h"
Bence Békyb28709c22018-03-06 13:03:4421#include "net/websockets/websocket_deflate_parameters.h"
[email protected]a9cf2b92013-10-30 12:08:4922#include "net/websockets/websocket_stream.h"
23
24namespace net {
25
26class ClientSocketHandle;
Bence Béky46bfbc12018-02-22 19:28:2027class SpdySession;
Bence Békyb28709c22018-03-06 13:03:4428class HttpRequestHeaders;
29class HttpResponseHeaders;
Bence Békyda280c62018-04-12 15:08:3730class WebSocketEndpointLockManager;
[email protected]a9cf2b92013-10-30 12:08:4931
32// WebSocketHandshakeStreamBase is the base class of
33// WebSocketBasicHandshakeStream. net/http code uses this interface to handle
34// WebSocketBasicHandshakeStream when it needs to be treated differently from
35// HttpStreamBase.
yhiranoa7e05bb2014-11-06 05:40:3936class NET_EXPORT WebSocketHandshakeStreamBase : public HttpStream {
[email protected]a9cf2b92013-10-30 12:08:4937 public:
Bence Békyde0be312018-03-13 17:51:5838 // These entries must match histogram Net.WebSocket.HandshakeResult2.
39 // Do not change or reuse values.
40 enum class HandshakeResult {
41 // Handshake not completed via Upgrade over HTTP/1 connection.
42 INCOMPLETE = 0,
43 // Server responded to Upgrade request with invalid status.
44 INVALID_STATUS = 1,
45 // Server responded to Upgrade request with empty response.
46 EMPTY_RESPONSE = 2,
47 // Server responded to Upgrade request with 101 status but there was some
48 // other network error.
49 FAILED_SWITCHING_PROTOCOLS = 3,
50 // Server responded to Upgrade request with invalid Upgrade header.
51 FAILED_UPGRADE = 4,
52 // Server responded to Upgrade request with invalid Sec-WebSocket-Accept
53 // header.
54 FAILED_ACCEPT = 5,
55 // Server responded to Upgrade request with invalid Connection header.
56 FAILED_CONNECTION = 6,
57 // Server responded to Upgrade request with invalid Sec-WebSocket-Protocol
58 // header.
59 FAILED_SUBPROTO = 7,
60 // Server responded to Upgrade request with invalid Sec-WebSocket-Extensions
61 // header.
62 FAILED_EXTENSIONS = 8,
63 // Upgrade request failed due to other network error.
64 FAILED = 9,
65 // Connected via Upgrade over HTTP/1 connection.
66 CONNECTED = 10,
67 // Handshake not completed over an HTTP/2 connection.
68 HTTP2_INCOMPLETE = 11,
69 // Server responded to WebSocket request over an HTTP/2 connection with
70 // invalid status code.
71 HTTP2_INVALID_STATUS = 12,
72 // Server responded to WebSocket request over an HTTP/2 connection with
73 // invalid sec-websocket-protocol header.
74 HTTP2_FAILED_SUBPROTO = 13,
75 // Server responded to WebSocket request over an HTTP/2 connection with
76 // invalid sec-websocket-extensions header.
77 HTTP2_FAILED_EXTENSIONS = 14,
78 // WebSocket request over an HTTP/2 connection failed with some other error.
79 HTTP2_FAILED = 15,
80 // Connected over an HTTP/2 connection.
81 HTTP2_CONNECTED = 16,
82 NUM_HANDSHAKE_RESULT_TYPES = 17
83 };
84
Bence Békyb28709c22018-03-06 13:03:4485 WebSocketHandshakeStreamBase() = default;
86 ~WebSocketHandshakeStreamBase() override = default;
87
[email protected]efa9e732013-11-29 02:55:0588 // An object that stores data needed for the creation of a
89 // WebSocketBasicHandshakeStream object. A new CreateHelper is used for each
90 // WebSocket connection.
91 class NET_EXPORT_PRIVATE CreateHelper : public base::SupportsUserData::Data {
[email protected]a9cf2b92013-10-30 12:08:4992 public:
dchengb03027d2014-10-21 12:00:2093 ~CreateHelper() override {}
[email protected]a9cf2b92013-10-30 12:08:4994
[email protected]7e841a52013-11-22 09:04:2195 // Create a WebSocketBasicHandshakeStream. This is called after the
[email protected]a9cf2b92013-10-30 12:08:4996 // underlying connection has been established but before any handshake data
[email protected]efa9e732013-11-29 02:55:0597 // has been transferred. This can be called more than once in the case that
98 // HTTP authentication is needed.
bnc615cf2f2017-05-19 18:53:2699 virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
danakj9c5cab52016-04-16 00:54:33100 std::unique_ptr<ClientSocketHandle> connection,
Bence Békyda280c62018-04-12 15:08:37101 bool using_proxy,
102 WebSocketEndpointLockManager* websocket_endpoint_lock_manager) = 0;
Bence Béky46bfbc12018-02-22 19:28:20103
104 // Create a WebSocketHttp2HandshakeStream. This is called after the
105 // underlying HTTP/2 connection has been established but before the stream
106 // has been opened. This cannot be called more than once.
107 virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
108 base::WeakPtr<SpdySession> session) = 0;
[email protected]a9cf2b92013-10-30 12:08:49109 };
110
[email protected]a9cf2b92013-10-30 12:08:49111 // After the handshake has completed, this method creates a WebSocketStream
112 // (of the appropriate type) from the WebSocketHandshakeStreamBase object.
113 // The WebSocketHandshakeStreamBase object is unusable after Upgrade() has
114 // been called.
danakj9c5cab52016-04-16 00:54:33115 virtual std::unique_ptr<WebSocketStream> Upgrade() = 0;
[email protected]a9cf2b92013-10-30 12:08:49116
Andrey Kosyakov83a6eee2017-08-14 19:20:04117 void SetRequestHeadersCallback(RequestHeadersCallback callback) override {}
118
Bence Békyb28709c22018-03-06 13:03:44119 static std::string MultipleHeaderValuesMessage(
120 const std::string& header_name);
121
Bence Békyca0da432019-01-24 15:03:20122 // Subclasses need to implement this method so that the resulting weak
123 // pointers are invalidated as soon as the derived class is destroyed.
124 virtual base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() = 0;
125
[email protected]a9cf2b92013-10-30 12:08:49126 protected:
Bence Békyb28709c22018-03-06 13:03:44127 // TODO(ricea): If more extensions are added, replace this with a more general
128 // mechanism.
129 struct WebSocketExtensionParams {
130 bool deflate_enabled = false;
131 WebSocketDeflateParameters deflate_parameters;
132 };
133
134 static void AddVectorHeaderIfNonEmpty(const char* name,
135 const std::vector<std::string>& value,
136 HttpRequestHeaders* headers);
137
138 static bool ValidateSubProtocol(
139 const HttpResponseHeaders* headers,
140 const std::vector<std::string>& requested_sub_protocols,
141 std::string* sub_protocol,
142 std::string* failure_message);
143
144 static bool ValidateExtensions(const HttpResponseHeaders* headers,
145 std::string* accepted_extensions_descriptor,
146 std::string* failure_message,
147 WebSocketExtensionParams* params);
[email protected]a9cf2b92013-10-30 12:08:49148
Bence Békyde0be312018-03-13 17:51:58149 void RecordHandshakeResult(HandshakeResult result);
Bence Békyde0be312018-03-13 17:51:58150
[email protected]a9cf2b92013-10-30 12:08:49151 private:
152 DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeStreamBase);
153};
154
155} // namespace net
156
157#endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_