OLD | NEW |
(Empty) | |
| 1 // 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_BASIC_STREAM_H_ |
| 6 #define NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ |
| 7 |
| 8 #include <string> |
| 9 |
| 10 #include "base/callback.h" |
| 11 #include "base/memory/ref_counted.h" |
| 12 #include "base/memory/scoped_vector.h" |
| 13 #include "base/strings/string_piece.h" |
| 14 #include "net/base/io_buffer.h" |
| 15 #include "net/websockets/websocket_frame_parser.h" |
| 16 #include "net/websockets/websocket_stream.h" |
| 17 |
| 18 namespace net { |
| 19 |
| 20 class ClientSocketHandle; |
| 21 class DrainableIOBuffer; |
| 22 class GrowableIOBuffer; |
| 23 class HttpRequestHeaders; |
| 24 class HttpResponseHeaders; |
| 25 class HttpResponseInfo; |
| 26 struct WebSocketFrameChunk; |
| 27 |
| 28 // Implementation of WebSocketStream for non-multiplexed ws:// connections (or |
| 29 // the physical side of a multiplexed ws:// connection). |
| 30 class WebSocketBasicStream : public WebSocketStream { |
| 31 public: |
| 32 // This class should not normally be constructed directly; see |
| 33 // WebSocketStream::CreateAndConnectStream. |
| 34 explicit WebSocketBasicStream(scoped_ptr<ClientSocketHandle> connection); |
| 35 |
| 36 // We need to make sure the connection is closed when we finish so that it |
| 37 // does not get returned to the pool. |
| 38 virtual ~WebSocketBasicStream(); |
| 39 |
| 40 // Read one or more frame chunks. See WebSocketStream for the full |
| 41 // specification of the behaviour. |
| 42 virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, |
| 43 const CompletionCallback& callback) OVERRIDE; |
| 44 |
| 45 virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, |
| 46 const CompletionCallback& callback) OVERRIDE; |
| 47 |
| 48 // Close the stream, cancelling all pending IO operations without calling the |
| 49 // callbacks. |
| 50 virtual void Close() OVERRIDE; |
| 51 |
| 52 // Return the optional sub-protocol that was negotiated with the server. |
| 53 virtual std::string GetSubProtocol() const OVERRIDE; |
| 54 |
| 55 // Return the extensions that were negotiated with the server. |
| 56 virtual std::string GetExtensions() const OVERRIDE; |
| 57 |
| 58 // Writes WebSocket handshake request HTTP-style to the connection. Adds |
| 59 // "Sec-Websocket-Key" header; this should not be included in |headers|. |
| 60 // |
| 61 // "callback" will only be called if this method returns ERR_IO_PENDING. |
| 62 // |
| 63 // |response_info| must remain valid until the callback from |
| 64 // ReadHandshakeResponse has been called. |
| 65 virtual int SendHandshakeRequest(const GURL& url, |
| 66 const HttpRequestHeaders& headers, |
| 67 HttpResponseInfo* response_info, |
| 68 const CompletionCallback& callback) OVERRIDE; |
| 69 |
| 70 // Reads WebSocket handshake response from the connection. The callback |
| 71 // function completes when the response headers have been completely |
| 72 // received. Must be called after SendHandshakeRequest() completes (including |
| 73 // the callback, if relevant). If the result was not available synchronously, |
| 74 // then it will be passed to the callback. Note that the actual response info |
| 75 // is passed into the HttpResponseInfo object that was passed to |
| 76 // SendHandshakeResponse. |
| 77 virtual int ReadHandshakeResponse(const CompletionCallback& callback) |
| 78 OVERRIDE; |
| 79 |
| 80 private: |
| 81 // The type of an element of the array passed to ParseRequestHeaders, below. |
| 82 struct ParseRequestHeadersArg; |
| 83 |
| 84 // The semantics of WriteFrames() are such that it only returns OK or calls |
| 85 // the callback when everything is written or something has failed. But |
| 86 // Socket::Write() can do partial writes, so we need to wrap it in a loop. |
| 87 int WriteEverything(const scoped_refptr<DrainableIOBuffer>& buffer, |
| 88 const CompletionCallback& callback); |
| 89 |
| 90 // Wrap the callback method to handle partial writes. |
| 91 void WriteDone(const scoped_refptr<DrainableIOBuffer>& buffer, |
| 92 const CompletionCallback& callback, |
| 93 int result); |
| 94 |
| 95 // Called when a read completes. |
| 96 void ReadDone(ScopedVector<WebSocketFrameChunk>* frame_chunks, |
| 97 const CompletionCallback& callback, |
| 98 int result); |
| 99 |
| 100 // Called when the handshake completes. If it was successful, then we can now |
| 101 // upgrade to WebSocketitude. |
| 102 void HandshakeDone(const CompletionCallback& callback, int result); |
| 103 |
| 104 // Read the value of the headers named in args[].key as a vector of |
| 105 // comma-separated tokens from |headers| into args[].tokens. |count| is the |
| 106 // number of items in args. If a header is not present, or empty, then nothing |
| 107 // will be written to args[].tokens. |
| 108 static void ParseRequestHeaders(const HttpRequestHeaders& headers, |
| 109 ParseRequestHeadersArg args[], |
| 110 size_t count); |
| 111 |
| 112 // Return true if a header named |name| containing exactly one token with |
| 113 // value exactly |value| is contained in |headers|. |
| 114 static bool ValidateSingleTokenHeader( |
| 115 const scoped_refptr<HttpResponseHeaders>& headers, |
| 116 const base::StringPiece& name, |
| 117 const std::string& value); |
| 118 |
| 119 // Return true if |headers| contains "Upgrade: websocket" (case-insensitive) |
| 120 static bool ValidateUpgradeResponseHeader( |
| 121 const scoped_refptr<HttpResponseHeaders>& headers); |
| 122 |
| 123 // Return true if |headers| contains a Sec-Websocket-Accept header field and |
| 124 // it correctly contains the encoded value of the Sec-WebSocket-Key header |
| 125 // from the request. |
| 126 bool ValidateSecWebSocketAcceptResponseHeader( |
| 127 const scoped_refptr<HttpResponseHeaders>& headers); |
| 128 |
| 129 // Process a handshake, deciding whether to accept it or not, and recording |
| 130 // protocol_ and extensions_ if relevant. Returns OK if the handshake was |
| 131 // acceptable, otherwise an appropriate ERR_* code. |
| 132 int ProcessHandshake(); |
| 133 |
| 134 // Storage for pending reads. All active WebSockets spend all the time with a |
| 135 // call to ReadFrames() pending, so there is no benefit in trying to share |
| 136 // this. |
| 137 scoped_refptr<IOBufferWithSize> read_buffer_; |
| 138 |
| 139 // The connection, wrapped in a ClientSocketHandle so that we can prevent it |
| 140 // from being returned to the pool. |
| 141 scoped_ptr<ClientSocketHandle> connection_; |
| 142 |
| 143 // A holder for data that is only used during the handshake portion of the |
| 144 // connection, then freed afterwards. |
| 145 struct HandshakeData; |
| 146 |
| 147 // The data that is used during the handshake. |
| 148 scoped_ptr<HandshakeData> handshake_data_; |
| 149 |
| 150 // Only used during handshake. Some data may be left in this buffer after the |
| 151 // handshake, in which case it will be picked up during the first call to |
| 152 // ReadFrames(). Because it may continue be accessed after the handshake |
| 153 // proper has completed, it is not part of handshake_data_. |
| 154 scoped_refptr<GrowableIOBuffer> http_read_buffer_; |
| 155 |
| 156 // This keeps the current parse state (including any incomplete headers) and |
| 157 // parses frames. |
| 158 WebSocketFrameParser parser_; |
| 159 |
| 160 // The negotated sub-protocol, or empty for none. |
| 161 std::string sub_protocol_; |
| 162 |
| 163 // The extensions negotiated with the remote server. |
| 164 std::string extensions_; |
| 165 }; |
| 166 |
| 167 } // namespace net |
| 168 |
| 169 #endif // NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ |
OLD | NEW |