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 #ifndef NET_WEBSOCKETS_WEBSOCKET_STREAM_H_ 6 #define NET_WEBSOCKETS_WEBSOCKET_STREAM_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/callback_forward.h" 13 #include "base/macros.h" 14 #include "base/memory/scoped_refptr.h" 15 #include "base/optional.h" 16 #include "base/time/time.h" 17 #include "net/base/completion_once_callback.h" 18 #include "net/base/net_export.h" 19 #include "net/base/network_isolation_key.h" 20 #include "net/cookies/site_for_cookies.h" 21 #include "net/websockets/websocket_event_interface.h" 22 #include "net/websockets/websocket_handshake_request_info.h" 23 #include "net/websockets/websocket_handshake_response_info.h" 24 25 class GURL; 26 27 namespace base { 28 class OneShotTimer; 29 } 30 31 namespace url { 32 class Origin; 33 } // namespace url 34 35 namespace net { 36 37 class AuthChallengeInfo; 38 class AuthCredentials; 39 class HttpRequestHeaders; 40 class HttpResponseHeaders; 41 class IPEndPoint; 42 class NetLogWithSource; 43 class URLRequest; 44 class URLRequestContext; 45 struct WebSocketFrame; 46 class WebSocketBasicHandshakeStream; 47 class WebSocketHttp2HandshakeStream; 48 49 // WebSocketStreamRequest is the caller's handle to the process of creation of a 50 // WebSocketStream. Deleting the object before the ConnectDelegate OnSuccess or 51 // OnFailure callbacks are called will cancel the request (and neither callback 52 // will be called). After OnSuccess or OnFailure have been called, this object 53 // may be safely deleted without side-effects. 54 class NET_EXPORT_PRIVATE WebSocketStreamRequest { 55 public: 56 virtual ~WebSocketStreamRequest(); 57 }; 58 59 // A subclass of WebSocketStreamRequest that exposes methods that are used as 60 // part of the handshake. 61 class NET_EXPORT_PRIVATE WebSocketStreamRequestAPI 62 : public WebSocketStreamRequest { 63 public: 64 virtual void OnBasicHandshakeStreamCreated( 65 WebSocketBasicHandshakeStream* handshake_stream) = 0; 66 virtual void OnHttp2HandshakeStreamCreated( 67 WebSocketHttp2HandshakeStream* handshake_stream) = 0; 68 virtual void OnFailure(const std::string& message) = 0; 69 }; 70 71 // WebSocketStream is a transport-agnostic interface for reading and writing 72 // WebSocket frames. This class provides an abstraction for WebSocket streams 73 // based on various transport layers, such as normal WebSocket connections 74 // (WebSocket protocol upgraded from HTTP handshake), SPDY transports, or 75 // WebSocket connections with multiplexing extension. Subtypes of 76 // WebSocketStream are responsible for managing the underlying transport 77 // appropriately. 78 // 79 // All functions except Close() can be asynchronous. If an operation cannot 80 // be finished synchronously, the function returns ERR_IO_PENDING, and 81 // |callback| will be called when the operation is finished. Non-null |callback| 82 // must be provided to these functions. 83 // 84 // Please update the traffic annotations in the websocket_basic_stream.cc and 85 // websocket_stream.cc if the class is used for any communication with Google. 86 // In such a case, annotation should be passed from the callers to this class 87 // and a local annotation can not be used anymore. 88 89 class NET_EXPORT_PRIVATE WebSocketStream { 90 public: 91 // A concrete object derived from ConnectDelegate is supplied by the caller to 92 // CreateAndConnectStream() to receive the result of the connection. 93 class NET_EXPORT_PRIVATE ConnectDelegate { 94 public: 95 virtual ~ConnectDelegate(); 96 // Called when the URLRequest is created. 97 virtual void OnCreateRequest(URLRequest* url_request) = 0; 98 99 // Called on successful connection. The parameter is an object derived from 100 // WebSocketStream. 101 virtual void OnSuccess( 102 std::unique_ptr<WebSocketStream> stream, 103 std::unique_ptr<WebSocketHandshakeResponseInfo> response) = 0; 104 105 // Called on failure to connect. 106 // |message| contains defails of the failure. 107 virtual void OnFailure(const std::string& message) = 0; 108 109 // Called when the WebSocket Opening Handshake starts. 110 virtual void OnStartOpeningHandshake( 111 std::unique_ptr<WebSocketHandshakeRequestInfo> request) = 0; 112 113 // Called when there is an SSL certificate error. Should call 114 // ssl_error_callbacks->ContinueSSLRequest() or 115 // ssl_error_callbacks->CancelSSLRequest(). 116 virtual void OnSSLCertificateError( 117 std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> 118 ssl_error_callbacks, 119 int net_error, 120 const SSLInfo& ssl_info, 121 bool fatal) = 0; 122 123 // Called when authentication is required. Returns a net error. The opening 124 // handshake is blocked when this function returns ERR_IO_PENDING. 125 // In that case calling |callback| resumes the handshake. |callback| can be 126 // called during the opening handshake. An implementation can rewrite 127 // |*credentials| (in the sync case) or provide new credentials (in the 128 // async case). 129 // Providing null credentials (nullopt in the sync case and nullptr in the 130 // async case) cancels authentication. Otherwise the new credentials are set 131 // and the opening handshake will be retried with the credentials. 132 virtual int OnAuthRequired( 133 const AuthChallengeInfo& auth_info, 134 scoped_refptr<HttpResponseHeaders> response_headers, 135 const IPEndPoint& remote_endpoint, 136 base::OnceCallback<void(const AuthCredentials*)> callback, 137 base::Optional<AuthCredentials>* credentials) = 0; 138 }; 139 140 // Create and connect a WebSocketStream of an appropriate type. The actual 141 // concrete type returned depends on whether multiplexing or SPDY are being 142 // used to communicate with the remote server. If the handshake completed 143 // successfully, then connect_delegate->OnSuccess() is called with a 144 // WebSocketStream instance. If it failed, then connect_delegate->OnFailure() 145 // is called with a WebSocket result code corresponding to the error. Deleting 146 // the returned WebSocketStreamRequest object will cancel the connection, in 147 // which case the |connect_delegate| object that the caller passed will be 148 // deleted without any of its methods being called. Unless cancellation is 149 // required, the caller should keep the WebSocketStreamRequest object alive 150 // until connect_delegate->OnSuccess() or OnFailure() have been called, then 151 // it is safe to delete. 152 static std::unique_ptr<WebSocketStreamRequest> CreateAndConnectStream( 153 const GURL& socket_url, 154 const std::vector<std::string>& requested_subprotocols, 155 const url::Origin& origin, 156 const SiteForCookies& site_for_cookies, 157 const net::NetworkIsolationKey& network_isolation_key, 158 const HttpRequestHeaders& additional_headers, 159 URLRequestContext* url_request_context, 160 const NetLogWithSource& net_log, 161 std::unique_ptr<ConnectDelegate> connect_delegate); 162 163 // Alternate version of CreateAndConnectStream() for testing use only. It 164 // takes |timer| as the handshake timeout timer, and for methods on 165 // WebSocketStreamRequestAPI calls the |api_delegate| object before the 166 // in-built behaviour if non-null. 167 static std::unique_ptr<WebSocketStreamRequest> 168 CreateAndConnectStreamForTesting( 169 const GURL& socket_url, 170 const std::vector<std::string>& requested_subprotocols, 171 const url::Origin& origin, 172 const SiteForCookies& site_for_cookies, 173 const net::NetworkIsolationKey& network_isolation_key, 174 const HttpRequestHeaders& additional_headers, 175 URLRequestContext* url_request_context, 176 const NetLogWithSource& net_log, 177 std::unique_ptr<ConnectDelegate> connect_delegate, 178 std::unique_ptr<base::OneShotTimer> timer, 179 std::unique_ptr<WebSocketStreamRequestAPI> api_delegate); 180 181 // Derived classes must make sure Close() is called when the stream is not 182 // closed on destruction. 183 virtual ~WebSocketStream(); 184 185 // Reads WebSocket frame data. This operation finishes when new frame data 186 // becomes available. 187 // 188 // |frames| remains owned by the caller and must be valid until the 189 // operation completes or Close() is called. |frames| must be empty on 190 // calling. 191 // 192 // This function should not be called while the previous call of ReadFrames() 193 // is still pending. 194 // 195 // Returns net::OK or one of the net::ERR_* codes. 196 // 197 // frames->size() >= 1 if the result is OK. 198 // 199 // Only frames with complete header information are inserted into |frames|. If 200 // the currently available bytes of a new frame do not form a complete frame 201 // header, then the implementation will buffer them until all the fields in 202 // the WebSocketFrameHeader object can be filled. If ReadFrames() is freshly 203 // called in this situation, it will return ERR_IO_PENDING exactly as if no 204 // data was available. 205 // 206 // Original frame boundaries are not preserved. In particular, if only part of 207 // a frame is available, then the frame will be split, and the available data 208 // will be returned immediately. 209 // 210 // When the socket is closed on the remote side, this method will return 211 // ERR_CONNECTION_CLOSED. It will not return OK with an empty vector. 212 // 213 // If the connection is closed in the middle of receiving an incomplete frame, 214 // ReadFrames may discard the incomplete frame. Since the renderer will 215 // discard any incomplete messages when the connection is closed, this makes 216 // no difference to the overall semantics. 217 // 218 // Implementations of ReadFrames() must be able to handle being deleted during 219 // the execution of callback.Run(). In practice this means that the method 220 // calling callback.Run() (and any calling methods in the same object) must 221 // return immediately without any further method calls or access to member 222 // variables. Implementors should write test(s) for this case. 223 // 224 // Extensions which use reserved header bits should clear them when they are 225 // set correctly. If the reserved header bits are set incorrectly, it is okay 226 // to leave it to the caller to report the error. 227 // 228 // Each WebSocketFrame.data is owned by WebSocketStream and must be valid 229 // until next ReadFrames() call. 230 virtual int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames, 231 CompletionOnceCallback callback) = 0; 232 233 // Writes WebSocket frame data. 234 // 235 // |frames| must be valid until the operation completes or Close() is called. 236 // 237 // This function must not be called while a previous call of WriteFrames() is 238 // still pending. 239 // 240 // This method will only return OK if all frames were written completely. 241 // Otherwise it will return an appropriate net error code. 242 // 243 // The callback implementation is permitted to delete this 244 // object. Implementations of WriteFrames() should be robust against 245 // this. This generally means returning to the event loop immediately after 246 // calling the callback. 247 virtual int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames, 248 CompletionOnceCallback callback) = 0; 249 250 // Closes the stream. All pending I/O operations (if any) are cancelled 251 // at this point, so |frames| can be freed. 252 virtual void Close() = 0; 253 254 // The subprotocol that was negotiated for the stream. If no protocol was 255 // negotiated, then the empty string is returned. 256 virtual std::string GetSubProtocol() const = 0; 257 258 // The extensions that were negotiated for the stream. Since WebSocketStreams 259 // can be layered, this may be different from what this particular 260 // WebSocketStream implements. The primary purpose of this accessor is to make 261 // the data available to Javascript. The format of the string is identical to 262 // the contents of the Sec-WebSocket-Extensions header supplied by the server, 263 // with some canonicalisations applied (leading and trailing whitespace 264 // removed, multiple headers concatenated into one comma-separated list). See 265 // RFC6455 section 9.1 for the exact format specification. If no 266 // extensions were negotiated, the empty string is returned. 267 virtual std::string GetExtensions() const = 0; 268 269 protected: 270 WebSocketStream(); 271 272 private: 273 DISALLOW_COPY_AND_ASSIGN(WebSocketStream); 274 }; 275 276 // A helper function used in the implementation of CreateAndConnectStream() and 277 // WebSocketBasicHandshakeStream. It creates a WebSocketHandshakeResponseInfo 278 // object and dispatches it to the OnFinishOpeningHandshake() method of the 279 // supplied |connect_delegate|. 280 void WebSocketDispatchOnFinishOpeningHandshake( 281 WebSocketStream::ConnectDelegate* connect_delegate, 282 const GURL& gurl, 283 const scoped_refptr<HttpResponseHeaders>& headers, 284 const IPEndPoint& remote_endpoint, 285 base::Time response_time); 286 287 } // namespace net 288 289 #endif // NET_WEBSOCKETS_WEBSOCKET_STREAM_H_ 290