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
23class MessageLoop;
24
25namespace net {
26
27class ClientSocketFactory;
28class HostResolver;
29class HttpResponseHeaders;
30
31class WebSocket;
32
33// Delegate methods will be called on the same message loop as
34// WebSocket is constructed.
35class WebSocketDelegate {
36 public:
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|.
50  virtual void OnError(const WebSocket* socket, int error) {}
51};
52
53class 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:
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) {}
74    ~Request() {}
75
76    const GURL& url() const { return url_; }
77    bool is_secure() const;
78    const std::string& protocol() const { return protocol_; }
79    const std::string& origin() const { return origin_; }
80    const std::string& location() const { return location_; }
81    URLRequestContext* context() const { return context_; }
82
83    // Sets an alternative HostResolver. For testing purposes only.
84    void SetHostResolver(HostResolver* host_resolver) {
85      host_resolver_ = host_resolver;
86    }
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.
91    void SetClientSocketFactory(ClientSocketFactory* factory) {
92      client_socket_factory_ = factory;
93    }
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
119  const Request* request() const { return request_.get(); }
120  WebSocketDelegate* delegate() const { return delegate_; }
121
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