Index: net/websockets/websocket_basic_stream.h |
diff --git a/net/websockets/websocket_basic_stream.h b/net/websockets/websocket_basic_stream.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..76450f6d7d1070e9b5b8e9671b6a3359fbb5a1b5 |
--- /dev/null |
+++ b/net/websockets/websocket_basic_stream.h |
@@ -0,0 +1,169 @@ |
+// Copyright 2013 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. |
+ |
+#ifndef NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ |
+#define NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ |
+ |
+#include <string> |
+ |
+#include "base/callback.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_vector.h" |
+#include "base/strings/string_piece.h" |
+#include "net/base/io_buffer.h" |
+#include "net/websockets/websocket_frame_parser.h" |
+#include "net/websockets/websocket_stream.h" |
+ |
+namespace net { |
+ |
+class ClientSocketHandle; |
+class DrainableIOBuffer; |
+class GrowableIOBuffer; |
+class HttpRequestHeaders; |
+class HttpResponseHeaders; |
+class HttpResponseInfo; |
+struct WebSocketFrameChunk; |
+ |
+// Implementation of WebSocketStream for non-multiplexed ws:// connections (or |
+// the physical side of a multiplexed ws:// connection). |
+class WebSocketBasicStream : public WebSocketStream { |
+ public: |
+ // This class should not normally be constructed directly; see |
+ // WebSocketStream::CreateAndConnectStream. |
+ explicit WebSocketBasicStream(scoped_ptr<ClientSocketHandle> connection); |
+ |
+ // We need to make sure the connection is closed when we finish so that it |
+ // does not get returned to the pool. |
+ virtual ~WebSocketBasicStream(); |
+ |
+ // Read one or more frame chunks. See WebSocketStream for the full |
+ // specification of the behaviour. |
+ virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, |
+ const CompletionCallback& callback) OVERRIDE; |
+ |
+ virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, |
+ const CompletionCallback& callback) OVERRIDE; |
+ |
+ // Close the stream, cancelling all pending IO operations without calling the |
+ // callbacks. |
+ virtual void Close() OVERRIDE; |
+ |
+ // Return the optional sub-protocol that was negotiated with the server. |
+ virtual std::string GetSubProtocol() const OVERRIDE; |
+ |
+ // Return the extensions that were negotiated with the server. |
+ virtual std::string GetExtensions() const OVERRIDE; |
+ |
+ // Writes WebSocket handshake request HTTP-style to the connection. Adds |
+ // "Sec-Websocket-Key" header; this should not be included in |headers|. |
+ // |
+ // "callback" will only be called if this method returns ERR_IO_PENDING. |
+ // |
+ // |response_info| must remain valid until the callback from |
+ // ReadHandshakeResponse has been called. |
+ virtual int SendHandshakeRequest(const GURL& url, |
+ const HttpRequestHeaders& headers, |
+ HttpResponseInfo* response_info, |
+ const CompletionCallback& callback) OVERRIDE; |
+ |
+ // Reads WebSocket handshake response from the connection. The callback |
+ // function completes when the response headers have been completely |
+ // received. Must be called after SendHandshakeRequest() completes (including |
+ // the callback, if relevant). If the result was not available synchronously, |
+ // then it will be passed to the callback. Note that the actual response info |
+ // is passed into the HttpResponseInfo object that was passed to |
+ // SendHandshakeResponse. |
+ virtual int ReadHandshakeResponse(const CompletionCallback& callback) |
+ OVERRIDE; |
+ |
+ private: |
+ // The type of an element of the array passed to ParseRequestHeaders, below. |
+ struct ParseRequestHeadersArg; |
+ |
+ // The semantics of WriteFrames() are such that it only returns OK or calls |
+ // the callback when everything is written or something has failed. But |
+ // Socket::Write() can do partial writes, so we need to wrap it in a loop. |
+ int WriteEverything(const scoped_refptr<DrainableIOBuffer>& buffer, |
+ const CompletionCallback& callback); |
+ |
+ // Wrap the callback method to handle partial writes. |
+ void WriteDone(const scoped_refptr<DrainableIOBuffer>& buffer, |
+ const CompletionCallback& callback, |
+ int result); |
+ |
+ // Called when a read completes. |
+ void ReadDone(ScopedVector<WebSocketFrameChunk>* frame_chunks, |
+ const CompletionCallback& callback, |
+ int result); |
+ |
+ // Called when the handshake completes. If it was successful, then we can now |
+ // upgrade to WebSocketitude. |
+ void HandshakeDone(const CompletionCallback& callback, int result); |
+ |
+ // Read the value of the headers named in args[].key as a vector of |
+ // comma-separated tokens from |headers| into args[].tokens. |count| is the |
+ // number of items in args. If a header is not present, or empty, then nothing |
+ // will be written to args[].tokens. |
+ static void ParseRequestHeaders(const HttpRequestHeaders& headers, |
+ ParseRequestHeadersArg args[], |
+ size_t count); |
+ |
+ // Return true if a header named |name| containing exactly one token with |
+ // value exactly |value| is contained in |headers|. |
+ static bool ValidateSingleTokenHeader( |
+ const scoped_refptr<HttpResponseHeaders>& headers, |
+ const base::StringPiece& name, |
+ const std::string& value); |
+ |
+ // Return true if |headers| contains "Upgrade: websocket" (case-insensitive) |
+ static bool ValidateUpgradeResponseHeader( |
+ const scoped_refptr<HttpResponseHeaders>& headers); |
+ |
+ // Return true if |headers| contains a Sec-Websocket-Accept header field and |
+ // it correctly contains the encoded value of the Sec-WebSocket-Key header |
+ // from the request. |
+ bool ValidateSecWebSocketAcceptResponseHeader( |
+ const scoped_refptr<HttpResponseHeaders>& headers); |
+ |
+ // Process a handshake, deciding whether to accept it or not, and recording |
+ // protocol_ and extensions_ if relevant. Returns OK if the handshake was |
+ // acceptable, otherwise an appropriate ERR_* code. |
+ int ProcessHandshake(); |
+ |
+ // Storage for pending reads. All active WebSockets spend all the time with a |
+ // call to ReadFrames() pending, so there is no benefit in trying to share |
+ // this. |
+ scoped_refptr<IOBufferWithSize> read_buffer_; |
+ |
+ // The connection, wrapped in a ClientSocketHandle so that we can prevent it |
+ // from being returned to the pool. |
+ scoped_ptr<ClientSocketHandle> connection_; |
+ |
+ // A holder for data that is only used during the handshake portion of the |
+ // connection, then freed afterwards. |
+ struct HandshakeData; |
+ |
+ // The data that is used during the handshake. |
+ scoped_ptr<HandshakeData> handshake_data_; |
+ |
+ // Only used during handshake. Some data may be left in this buffer after the |
+ // handshake, in which case it will be picked up during the first call to |
+ // ReadFrames(). Because it may continue be accessed after the handshake |
+ // proper has completed, it is not part of handshake_data_. |
+ scoped_refptr<GrowableIOBuffer> http_read_buffer_; |
+ |
+ // This keeps the current parse state (including any incomplete headers) and |
+ // parses frames. |
+ WebSocketFrameParser parser_; |
+ |
+ // The negotated sub-protocol, or empty for none. |
+ std::string sub_protocol_; |
+ |
+ // The extensions negotiated with the remote server. |
+ std::string extensions_; |
+}; |
+ |
+} // namespace net |
+ |
+#endif // NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ |