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