• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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