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
25class MessageLoop;
26
27namespace net {
28
29class ClientSocketFactory;
30class HostResolver;
31
32class WebSocket;
33class WebSocketHandshake;
34
35// Delegate methods will be called on the same message loop as
36// WebSocket is constructed.
37class WebSocketDelegate {
38 public:
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.
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|.
55  virtual void OnSocketError(const WebSocket* socket, int error) {}
56};
57
58class 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:
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) {}
86    ~Request() {}
87
88    const GURL& url() const { return url_; }
89    const std::string& protocol() const { return protocol_; }
90    const std::string& origin() const { return origin_; }
91    const std::string& location() const { return location_; }
92    ProtocolVersion version() const { return version_; }
93    net::URLRequestContext* context() const { return context_; }
94
95    // Sets an alternative HostResolver. For testing purposes only.
96    void SetHostResolver(HostResolver* host_resolver) {
97      host_resolver_ = host_resolver;
98    }
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.
103    void SetClientSocketFactory(ClientSocketFactory* factory) {
104      client_socket_factory_ = factory;
105    }
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
129  const Request* request() const { return request_.get(); }
130  WebSocketDelegate* delegate() const { return delegate_; }
131
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