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
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
// This file is included from net/http files.
// Since net/http can be built without linking net/websockets code,
// this file must not introduce any link-time dependencies on websockets.
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "net/base/net_export.h"
#include "net/http/http_raw_request_headers.h"
#include "net/http/http_stream.h"
#include "net/quic/quic_chromium_client_session.h"
#include "net/websockets/websocket_deflate_parameters.h"
#include "net/websockets/websocket_stream.h"
namespace net {
class ClientSocketHandle;
class SpdySession;
class HttpRequestHeaders;
class HttpResponseHeaders;
class WebSocketEndpointLockManager;
class WebSocketStream;
// WebSocketHandshakeStreamBase is the base class of
// WebSocketBasicHandshakeStream. net/http code uses this interface to handle
// WebSocketBasicHandshakeStream when it needs to be treated differently from
// HttpStreamBase.
class NET_EXPORT WebSocketHandshakeStreamBase : public HttpStream {
public:
// These entries must match histogram Net.WebSocket.HandshakeResult2.
// Do not change or reuse values.
enum class HandshakeResult {
// Handshake not completed via Upgrade over HTTP/1 connection.
INCOMPLETE = 0,
// Server responded to Upgrade request with invalid status.
INVALID_STATUS = 1,
// Server responded to Upgrade request with empty response.
EMPTY_RESPONSE = 2,
// Server responded to Upgrade request with 101 status but there was some
// other network error.
FAILED_SWITCHING_PROTOCOLS = 3,
// Server responded to Upgrade request with invalid Upgrade header.
FAILED_UPGRADE = 4,
// Server responded to Upgrade request with invalid Sec-WebSocket-Accept
// header.
FAILED_ACCEPT = 5,
// Server responded to Upgrade request with invalid Connection header.
FAILED_CONNECTION = 6,
// Server responded to Upgrade request with invalid Sec-WebSocket-Protocol
// header.
FAILED_SUBPROTO = 7,
// Server responded to Upgrade request with invalid Sec-WebSocket-Extensions
// header.
FAILED_EXTENSIONS = 8,
// Upgrade request failed due to other network error.
FAILED = 9,
// Connected via Upgrade over HTTP/1 connection.
CONNECTED = 10,
// Handshake not completed over an HTTP/2 connection.
HTTP2_INCOMPLETE = 11,
// Server responded to WebSocket request over an HTTP/2 connection with
// invalid status code.
HTTP2_INVALID_STATUS = 12,
// Server responded to WebSocket request over an HTTP/2 connection with
// invalid sec-websocket-protocol header.
HTTP2_FAILED_SUBPROTO = 13,
// Server responded to WebSocket request over an HTTP/2 connection with
// invalid sec-websocket-extensions header.
HTTP2_FAILED_EXTENSIONS = 14,
// WebSocket request over an HTTP/2 connection failed with some other error.
HTTP2_FAILED = 15,
// Connected over an HTTP/2 connection.
HTTP2_CONNECTED = 16,
// Handshake not completed over an HTTP/3 connection.
HTTP3_INCOMPLETE = 17,
// Server responded to WebSocket request over an HTTP/3 connection with
// invalid status code.
HTTP3_INVALID_STATUS = 18,
// Server responded to WebSocket request over an HTTP/3 connection with
// invalid sec-websocket-protocol header.
HTTP3_FAILED_SUBPROTO = 19,
// Server responded to WebSocket request over an HTTP/3 connection with
// invalid sec-websocket-extensions header.
HTTP3_FAILED_EXTENSIONS = 20,
// WebSocket request over an HTTP/3 connection failed with some other error.
HTTP3_FAILED = 21,
// Connected over an HTTP/3 connection.
HTTP3_CONNECTED = 22,
NUM_HANDSHAKE_RESULT_TYPES = 23
};
WebSocketHandshakeStreamBase() = default;
WebSocketHandshakeStreamBase(const WebSocketHandshakeStreamBase&) = delete;
WebSocketHandshakeStreamBase& operator=(const WebSocketHandshakeStreamBase&) =
delete;
~WebSocketHandshakeStreamBase() override = default;
// An object that stores data needed for the creation of a
// WebSocketBasicHandshakeStream object. A new CreateHelper is used for each
// WebSocket connection.
class NET_EXPORT_PRIVATE CreateHelper : public base::SupportsUserData::Data {
public:
~CreateHelper() override = default;
// Create a WebSocketBasicHandshakeStream. This is called after the
// underlying connection has been established but before any handshake data
// has been transferred. This can be called more than once in the case that
// HTTP authentication is needed.
virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
std::unique_ptr<ClientSocketHandle> connection,
bool using_proxy,
WebSocketEndpointLockManager* websocket_endpoint_lock_manager) = 0;
// Create a WebSocketHttp2HandshakeStream. This is called after the
// underlying HTTP/2 connection has been established but before the stream
// has been opened. This cannot be called more than once.
virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
base::WeakPtr<SpdySession> session,
std::set<std::string> dns_aliases) = 0;
// Create a WebSocketHttp3HandshakeStream. This is called after the
// underlying HTTP/3 connection has been established but before the stream
// has been opened. This cannot be called more than once.
virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream(
std::unique_ptr<QuicChromiumClientSession::Handle> session,
std::set<std::string> dns_aliases) = 0;
};
// After the handshake has completed, this method creates a WebSocketStream
// (of the appropriate type) from the WebSocketHandshakeStreamBase object.
// The WebSocketHandshakeStreamBase object is unusable after Upgrade() has
// been called.
virtual std::unique_ptr<WebSocketStream> Upgrade() = 0;
// Returns true if a read from the stream will succeed. This should be true
// even if the stream is at EOF.
virtual bool CanReadFromStream() const = 0;
void SetRequestHeadersCallback(RequestHeadersCallback callback) override {}
static std::string MultipleHeaderValuesMessage(
const std::string& header_name);
// Subclasses need to implement this method so that the resulting weak
// pointers are invalidated as soon as the derived class is destroyed.
virtual base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() = 0;
protected:
// TODO(ricea): If more extensions are added, replace this with a more general
// mechanism.
struct WebSocketExtensionParams {
bool deflate_enabled = false;
WebSocketDeflateParameters deflate_parameters;
};
// Add the Sec-WebSocket-Extensions and Sec-WebSocket-Protocol headers to
// `headers`.
static void AddVectorHeaders(const std::vector<std::string>& extensions,
const std::vector<std::string>& protocols,
HttpRequestHeaders* headers);
static bool ValidateSubProtocol(
const HttpResponseHeaders* headers,
const std::vector<std::string>& requested_sub_protocols,
std::string* sub_protocol,
std::string* failure_message);
static bool ValidateExtensions(const HttpResponseHeaders* headers,
std::string* accepted_extensions_descriptor,
std::string* failure_message,
WebSocketExtensionParams* params);
void RecordHandshakeResult(HandshakeResult result);
};
} // namespace net
#endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
|