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_ptr.h" | |
13 #include "base/memory/scoped_vector.h" | |
14 #include "net/websockets/websocket_frame_parser.h" | |
15 #include "net/websockets/websocket_stream.h" | |
16 | |
17 namespace net { | |
18 | |
19 class ClientSocketHandle; | |
20 class DrainableIOBuffer; | |
21 class GrowableIOBuffer; | |
22 class IOBufferWithSize; | |
23 struct WebSocketFrame; | |
24 struct WebSocketFrameChunk; | |
25 | |
26 // Implementation of WebSocketStream for non-multiplexed ws:// connections (or | |
27 // the physical side of a multiplexed ws:// connection). | |
28 class NET_EXPORT_PRIVATE WebSocketBasicStream : public WebSocketStream { | |
29 public: | |
30 typedef WebSocketMaskingKey (*WebSocketMaskingKeyGeneratorFunction)(); | |
31 | |
32 // This class should not normally be constructed directly; see | |
33 // WebSocketStream::CreateAndConnectStream() and | |
34 // WebSocketBasicHandshakeStream::Upgrade(). | |
35 WebSocketBasicStream( | |
36 scoped_ptr<ClientSocketHandle> connection, | |
37 const scoped_refptr<GrowableIOBuffer>& http_read_buffer, | |
38 const std::string& sub_protocol, | |
39 const std::string& extensions); | |
40 | |
41 // The destructor has to make sure the connection is closed when we finish so | |
42 // that it does not get returned to the pool. | |
43 ~WebSocketBasicStream() override; | |
44 | |
45 // WebSocketStream implementation. | |
46 int ReadFrames(ScopedVector<WebSocketFrame>* frames, | |
47 const CompletionCallback& callback) override; | |
48 | |
49 int WriteFrames(ScopedVector<WebSocketFrame>* frames, | |
50 const CompletionCallback& callback) override; | |
51 | |
52 void Close() override; | |
53 | |
54 std::string GetSubProtocol() const override; | |
55 | |
56 std::string GetExtensions() const override; | |
57 | |
58 //////////////////////////////////////////////////////////////////////////// | |
59 // Methods for testing only. | |
60 | |
61 static scoped_ptr<WebSocketBasicStream> CreateWebSocketBasicStreamForTesting( | |
62 scoped_ptr<ClientSocketHandle> connection, | |
63 const scoped_refptr<GrowableIOBuffer>& http_read_buffer, | |
64 const std::string& sub_protocol, | |
65 const std::string& extensions, | |
66 WebSocketMaskingKeyGeneratorFunction key_generator_function); | |
67 | |
68 private: | |
69 // Returns OK or calls |callback| when the |buffer| is fully drained or | |
70 // something has failed. | |
71 int WriteEverything(const scoped_refptr<DrainableIOBuffer>& buffer, | |
72 const CompletionCallback& callback); | |
73 | |
74 // Wraps the |callback| to continue writing until everything has been written. | |
75 void OnWriteComplete(const scoped_refptr<DrainableIOBuffer>& buffer, | |
76 const CompletionCallback& callback, | |
77 int result); | |
78 | |
79 // Attempts to parse the output of a read as WebSocket frames. On success, | |
80 // returns OK and places the frame(s) in |frames|. | |
81 int HandleReadResult(int result, ScopedVector<WebSocketFrame>* frames); | |
82 | |
83 // Converts the chunks in |frame_chunks| into frames and writes them to | |
84 // |frames|. |frame_chunks| is destroyed in the process. Returns | |
85 // ERR_WS_PROTOCOL_ERROR if an invalid chunk was found. If one or more frames | |
86 // was added to |frames|, then returns OK, otherwise returns ERR_IO_PENDING. | |
87 int ConvertChunksToFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks, | |
88 ScopedVector<WebSocketFrame>* frames); | |
89 | |
90 // Converts a |chunk| to a |frame|. |*frame| should be NULL on entry to this | |
91 // method. If |chunk| is an incomplete control frame, or an empty middle | |
92 // frame, then |*frame| may still be NULL on exit. If an invalid control frame | |
93 // is found, returns ERR_WS_PROTOCOL_ERROR and the stream is no longer | |
94 // usable. Otherwise returns OK (even if frame is still NULL). | |
95 int ConvertChunkToFrame(scoped_ptr<WebSocketFrameChunk> chunk, | |
96 scoped_ptr<WebSocketFrame>* frame); | |
97 | |
98 // Creates a frame based on the value of |is_final_chunk|, |data| and | |
99 // |current_frame_header_|. Clears |current_frame_header_| if |is_final_chunk| | |
100 // is true. |data| may be NULL if the frame has an empty payload. A frame in | |
101 // the middle of a message with no data is not useful; in this case the | |
102 // returned frame will be NULL. Otherwise, |current_frame_header_->opcode| is | |
103 // set to Continuation after use if it was Text or Binary, in accordance with | |
104 // WebSocket RFC6455 section 5.4. | |
105 scoped_ptr<WebSocketFrame> CreateFrame( | |
106 bool is_final_chunk, | |
107 const scoped_refptr<IOBufferWithSize>& data); | |
108 | |
109 // Adds |data_buffer| to the end of |incomplete_control_frame_body_|, applying | |
110 // bounds checks. | |
111 void AddToIncompleteControlFrameBody( | |
112 const scoped_refptr<IOBufferWithSize>& data_buffer); | |
113 | |
114 // Called when a read completes. Parses the result and (unless no complete | |
115 // header has been received) calls |callback|. | |
116 void OnReadComplete(ScopedVector<WebSocketFrame>* frames, | |
117 const CompletionCallback& callback, | |
118 int result); | |
119 | |
120 // Storage for pending reads. All active WebSockets spend all the time with a | |
121 // call to ReadFrames() pending, so there is no benefit in trying to share | |
122 // this between sockets. | |
123 scoped_refptr<IOBufferWithSize> read_buffer_; | |
124 | |
125 // The connection, wrapped in a ClientSocketHandle so that we can prevent it | |
126 // from being returned to the pool. | |
127 scoped_ptr<ClientSocketHandle> connection_; | |
128 | |
129 // Frame header for the frame currently being received. Only non-NULL while we | |
130 // are processing the frame. If the frame arrives in multiple chunks, it can | |
131 // remain non-NULL until additional chunks arrive. If the header of the frame | |
132 // was invalid, this is set to NULL, the channel is failed, and subsequent | |
133 // chunks of the same frame will be ignored. | |
134 scoped_ptr<WebSocketFrameHeader> current_frame_header_; | |
135 | |
136 // Although it should rarely happen in practice, a control frame can arrive | |
137 // broken into chunks. This variable provides storage for a partial control | |
138 // frame until the rest arrives. It will be NULL the rest of the time. | |
139 scoped_refptr<GrowableIOBuffer> incomplete_control_frame_body_; | |
140 | |
141 // Only used during handshake. Some data may be left in this buffer after the | |
142 // handshake, in which case it will be picked up during the first call to | |
143 // ReadFrames(). The type is GrowableIOBuffer for compatibility with | |
144 // net::HttpStreamParser, which is used to parse the handshake. | |
145 scoped_refptr<GrowableIOBuffer> http_read_buffer_; | |
146 | |
147 // This keeps the current parse state (including any incomplete headers) and | |
148 // parses frames. | |
149 WebSocketFrameParser parser_; | |
150 | |
151 // The negotated sub-protocol, or empty for none. | |
152 const std::string sub_protocol_; | |
153 | |
154 // The extensions negotiated with the remote server. | |
155 const std::string extensions_; | |
156 | |
157 // This can be overridden in tests to make the output deterministic. We don't | |
158 // use a Callback here because a function pointer is faster and good enough | |
159 // for our purposes. | |
160 WebSocketMaskingKeyGeneratorFunction generate_websocket_masking_key_; | |
161 }; | |
162 | |
163 } // namespace net | |
164 | |
165 #endif // NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ | |
OLD | NEW |