1 // Copyright (c) 2009 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 // WebSocket protocol implementation in chromium. 6 // It is intended to be used for live experiment of WebSocket connectivity 7 // metrics. 8 // Note that it is not used for WebKit's WebSocket communication. 9 // See third_party/WebKit/WebCore/websockets/ instead. 10 11 #ifndef NET_WEBSOCKETS_WEBSOCKET_H_ 12 #define NET_WEBSOCKETS_WEBSOCKET_H_ 13 14 #include <deque> 15 #include <string> 16 17 #include "base/ref_counted.h" 18 #include "googleurl/src/gurl.h" 19 #include "net/base/io_buffer.h" 20 #include "net/socket_stream/socket_stream.h" 21 #include "net/url_request/url_request_context.h" 22 23 class MessageLoop; 24 25 namespace net { 26 27 class ClientSocketFactory; 28 class HostResolver; 29 class HttpResponseHeaders; 30 31 class WebSocket; 32 33 // Delegate methods will be called on the same message loop as 34 // WebSocket is constructed. 35 class WebSocketDelegate { 36 public: ~WebSocketDelegate()37 virtual ~WebSocketDelegate() {} 38 39 // Called when WebSocket connection has been established. 40 virtual void OnOpen(WebSocket* socket) = 0; 41 42 // Called when |msg| is received at |socket|. 43 // |msg| should be in UTF-8. 44 virtual void OnMessage(WebSocket* socket, const std::string& msg) = 0; 45 46 // Called when |socket| is closed. 47 virtual void OnClose(WebSocket* socket) = 0; 48 49 // Called when an error occured on |socket|. OnError(const WebSocket * socket,int error)50 virtual void OnError(const WebSocket* socket, int error) {} 51 }; 52 53 class WebSocket : public base::RefCountedThreadSafe<WebSocket>, 54 public SocketStream::Delegate { 55 public: 56 enum State { 57 INITIALIZED = -1, 58 CONNECTING = 0, 59 OPEN = 1, 60 CLOSED = 2, 61 }; 62 class Request { 63 public: Request(const GURL & url,const std::string protocol,const std::string origin,const std::string location,URLRequestContext * context)64 Request(const GURL& url, const std::string protocol, 65 const std::string origin, const std::string location, 66 URLRequestContext* context) 67 : url_(url), 68 protocol_(protocol), 69 origin_(origin), 70 location_(location), 71 context_(context), 72 host_resolver_(NULL), 73 client_socket_factory_(NULL) {} ~Request()74 ~Request() {} 75 url()76 const GURL& url() const { return url_; } 77 bool is_secure() const; protocol()78 const std::string& protocol() const { return protocol_; } origin()79 const std::string& origin() const { return origin_; } location()80 const std::string& location() const { return location_; } context()81 URLRequestContext* context() const { return context_; } 82 83 // Sets an alternative HostResolver. For testing purposes only. SetHostResolver(HostResolver * host_resolver)84 void SetHostResolver(HostResolver* host_resolver) { 85 host_resolver_ = host_resolver; 86 } host_resolver()87 HostResolver* host_resolver() const { return host_resolver_; } 88 89 // Sets an alternative ClientSocketFactory. Doesn't take ownership of 90 // |factory|. For testing purposes only. SetClientSocketFactory(ClientSocketFactory * factory)91 void SetClientSocketFactory(ClientSocketFactory* factory) { 92 client_socket_factory_ = factory; 93 } client_socket_factory()94 ClientSocketFactory* client_socket_factory() const { 95 return client_socket_factory_; 96 } 97 98 // Creates the client handshake message from |this|. 99 std::string CreateClientHandshakeMessage() const; 100 101 private: 102 GURL url_; 103 std::string protocol_; 104 std::string origin_; 105 std::string location_; 106 scoped_refptr<URLRequestContext> context_; 107 108 scoped_refptr<HostResolver> host_resolver_; 109 ClientSocketFactory* client_socket_factory_; 110 111 DISALLOW_COPY_AND_ASSIGN(Request); 112 }; 113 114 // Constructs new WebSocket. 115 // It takes ownership of |req|. 116 // |delegate| must be alive while this object is alive. 117 WebSocket(Request* req, WebSocketDelegate* delegate); 118 request()119 const Request* request() const { return request_.get(); } delegate()120 WebSocketDelegate* delegate() const { return delegate_; } 121 ready_state()122 State ready_state() const { return ready_state_; } 123 124 // Connects new WebSocket. 125 void Connect(); 126 127 // Sends |msg| on the WebSocket connection. 128 // |msg| should be in UTF-8. 129 void Send(const std::string& msg); 130 131 // Closes the WebSocket connection. 132 void Close(); 133 134 // Detach delegate. Call before delegate is deleted. 135 // Once delegate is detached, close the WebSocket connection and never call 136 // delegate back. 137 void DetachDelegate(); 138 139 // SocketStream::Delegate methods. 140 // Called on IO thread. 141 virtual void OnConnected(SocketStream* socket_stream, 142 int max_pending_send_allowed); 143 virtual void OnSentData(SocketStream* socket_stream, int amount_sent); 144 virtual void OnReceivedData(SocketStream* socket_stream, 145 const char* data, int len); 146 virtual void OnClose(SocketStream* socket); 147 virtual void OnError(const SocketStream* socket, int error); 148 149 private: 150 enum Mode { 151 MODE_INCOMPLETE, MODE_NORMAL, MODE_AUTHENTICATE, 152 }; 153 typedef std::deque< scoped_refptr<IOBufferWithSize> > PendingDataQueue; 154 155 friend class WebSocketTest; 156 157 friend class base::RefCountedThreadSafe<WebSocket>; 158 virtual ~WebSocket(); 159 160 // Checks handshake. 161 // Prerequisite: Server handshake message is received in |current_read_buf_|. 162 // Returns number of bytes for server handshake message, 163 // or negative if server handshake message is not received fully yet. 164 int CheckHandshake(); 165 166 // Processes server handshake message, parsed as |headers|, and updates 167 // |ws_origin_|, |ws_location_| and |ws_protocol_|. 168 // Returns true if it's ok. 169 // Returns false otherwise (e.g. duplicate WebSocket-Origin: header, etc.) 170 bool ProcessHeaders(const HttpResponseHeaders& headers); 171 172 // Checks |ws_origin_|, |ws_location_| and |ws_protocol_| are valid 173 // against |request_|. 174 // Returns true if it's ok. 175 // Returns false otherwise (e.g. origin mismatch, etc.) 176 bool CheckResponseHeaders() const; 177 178 // Sends pending data in |current_write_buf_| and/or |pending_write_bufs_|. 179 void SendPending(); 180 181 // Handles received data. 182 void DoReceivedData(); 183 184 // Processes frame data in |current_read_buf_|. 185 void ProcessFrameData(); 186 187 // Adds |len| bytes of |data| to |current_read_buf_|. 188 void AddToReadBuffer(const char* data, int len); 189 190 // Skips |len| bytes in |current_read_buf_|. 191 void SkipReadBuffer(int len); 192 193 // Handles closed connection. 194 void DoClose(); 195 196 // Handles error report. 197 void DoError(int error); 198 199 State ready_state_; 200 Mode mode_; 201 scoped_ptr<Request> request_; 202 WebSocketDelegate* delegate_; 203 MessageLoop* origin_loop_; 204 205 // Handshake messages that server sent. 206 std::string ws_origin_; 207 std::string ws_location_; 208 std::string ws_protocol_; 209 210 scoped_refptr<SocketStream> socket_stream_; 211 int max_pending_send_allowed_; 212 213 // [0..offset) is received data from |socket_stream_|. 214 // [0..read_consumed_len_) is already processed. 215 // [read_consumed_len_..offset) is unprocessed data. 216 // [offset..capacity) is free space. 217 scoped_refptr<GrowableIOBuffer> current_read_buf_; 218 int read_consumed_len_; 219 220 // Drainable IOBuffer on the front of |pending_write_bufs_|. 221 // [0..offset) is already sent to |socket_stream_|. 222 // [offset..size) is being sent to |socket_stream_|, waiting OnSentData. 223 scoped_refptr<DrainableIOBuffer> current_write_buf_; 224 225 // Deque of IOBuffers in pending. 226 // Front IOBuffer is being sent via |current_write_buf_|. 227 PendingDataQueue pending_write_bufs_; 228 229 DISALLOW_COPY_AND_ASSIGN(WebSocket); 230 }; 231 232 } // namespace net 233 234 #endif // NET_WEBSOCKETS_WEBSOCKET_H_ 235