Home | History | Annotate | Download | only in websockets
      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:
     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 
     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:
     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