Home | History | Annotate | Download | only in websockets
      1 // Copyright (c) 2012 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 #ifndef NET_WEBSOCKETS_WEBSOCKET_JOB_H_
      6 #define NET_WEBSOCKETS_WEBSOCKET_JOB_H_
      7 
      8 #include <deque>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/memory/weak_ptr.h"
     13 #include "net/base/address_list.h"
     14 #include "net/base/completion_callback.h"
     15 #include "net/socket_stream/socket_stream_job.h"
     16 #include "net/spdy/spdy_header_block.h"
     17 #include "net/spdy/spdy_websocket_stream.h"
     18 
     19 class GURL;
     20 
     21 namespace net {
     22 
     23 class DrainableIOBuffer;
     24 class SSLInfo;
     25 class WebSocketHandshakeRequestHandler;
     26 class WebSocketHandshakeResponseHandler;
     27 
     28 // WebSocket protocol specific job on SocketStream.
     29 // It captures WebSocket handshake message and handles cookie operations.
     30 // Chrome security policy doesn't allow renderer process (except dev tools)
     31 // see HttpOnly cookies, so it injects cookie header in handshake request and
     32 // strips set-cookie headers in handshake response.
     33 // TODO(ukai): refactor websocket.cc to use this.
     34 class NET_EXPORT WebSocketJob
     35     : public SocketStreamJob,
     36       public SocketStream::Delegate,
     37       public SpdyWebSocketStream::Delegate {
     38  public:
     39   // This is state of WebSocket, not SocketStream.
     40   enum State {
     41     INITIALIZED = -1,
     42     CONNECTING = 0,
     43     OPEN = 1,
     44     CLOSING = 2,
     45     CLOSED = 3,
     46   };
     47 
     48   explicit WebSocketJob(SocketStream::Delegate* delegate);
     49 
     50   static void EnsureInit();
     51 
     52   // Enable or Disable WebSocket over SPDY feature.
     53   // This function is intended to be called before I/O thread starts.
     54   static void set_websocket_over_spdy_enabled(bool enabled);
     55 
     56   State state() const { return state_; }
     57   virtual void Connect() OVERRIDE;
     58   virtual bool SendData(const char* data, int len) OVERRIDE;
     59   virtual void Close() OVERRIDE;
     60   virtual void RestartWithAuth(const AuthCredentials& credentials) OVERRIDE;
     61   virtual void DetachDelegate() OVERRIDE;
     62 
     63   // SocketStream::Delegate methods.
     64   virtual int OnStartOpenConnection(
     65       SocketStream* socket, const CompletionCallback& callback) OVERRIDE;
     66   virtual void OnConnected(SocketStream* socket,
     67                            int max_pending_send_allowed) OVERRIDE;
     68   virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE;
     69   virtual void OnReceivedData(SocketStream* socket,
     70                               const char* data,
     71                               int len) OVERRIDE;
     72   virtual void OnClose(SocketStream* socket) OVERRIDE;
     73   virtual void OnAuthRequired(
     74       SocketStream* socket, AuthChallengeInfo* auth_info) OVERRIDE;
     75   virtual void OnSSLCertificateError(SocketStream* socket,
     76                                      const SSLInfo& ssl_info,
     77                                      bool fatal) OVERRIDE;
     78   virtual void OnError(const SocketStream* socket, int error) OVERRIDE;
     79 
     80   // SpdyWebSocketStream::Delegate methods.
     81   virtual void OnCreatedSpdyStream(int status) OVERRIDE;
     82   virtual void OnSentSpdyHeaders() OVERRIDE;
     83   virtual void OnSpdyResponseHeadersUpdated(
     84       const SpdyHeaderBlock& response_headers) OVERRIDE;
     85   virtual void OnSentSpdyData(size_t bytes_sent) OVERRIDE;
     86   virtual void OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) OVERRIDE;
     87   virtual void OnCloseSpdyStream() OVERRIDE;
     88 
     89  private:
     90   friend class WebSocketThrottle;
     91   friend class WebSocketJobTest;
     92   virtual ~WebSocketJob();
     93 
     94   bool SendHandshakeRequest(const char* data, int len);
     95   void AddCookieHeaderAndSend();
     96   void LoadCookieCallback(const std::string& cookie);
     97 
     98   void OnSentHandshakeRequest(SocketStream* socket, int amount_sent);
     99   // Parses received data into handshake_response_. When finished receiving the
    100   // response, calls SaveCookiesAndNotifyHeadersComplete().
    101   void OnReceivedHandshakeResponse(
    102       SocketStream* socket, const char* data, int len);
    103   // Saves received cookies to the cookie store, and then notifies the
    104   // delegate_ of completion of handshake.
    105   void SaveCookiesAndNotifyHeadersComplete();
    106   void SaveNextCookie();
    107   void OnCookieSaved(bool cookie_status);
    108   // Clears variables for handling cookies, rebuilds handshake string excluding
    109   // cookies, and then pass the handshake string to delegate_.
    110   void NotifyHeadersComplete();
    111   void DoSendData();
    112 
    113   GURL GetURLForCookies() const;
    114 
    115   const AddressList& address_list() const;
    116   int TrySpdyStream();
    117   void SetWaiting();
    118   bool IsWaiting() const;
    119   void Wakeup();
    120   void RetryPendingIO();
    121   void CompleteIO(int result);
    122 
    123   bool SendDataInternal(const char* data, int length);
    124   void CloseInternal();
    125   void SendPending();
    126 
    127   static bool websocket_over_spdy_enabled_;
    128 
    129   SocketStream::Delegate* delegate_;
    130   State state_;
    131   bool waiting_;
    132   AddressList addresses_;
    133   CompletionCallback callback_;  // for throttling.
    134 
    135   scoped_ptr<WebSocketHandshakeRequestHandler> handshake_request_;
    136   scoped_ptr<WebSocketHandshakeResponseHandler> handshake_response_;
    137 
    138   bool started_to_send_handshake_request_;
    139   size_t handshake_request_sent_;
    140 
    141   std::vector<std::string> response_cookies_;
    142   size_t response_cookies_save_index_;
    143 
    144   std::deque<scoped_refptr<IOBufferWithSize> > send_buffer_queue_;
    145   scoped_refptr<DrainableIOBuffer> current_send_buffer_;
    146   std::vector<char> received_data_after_handshake_;
    147 
    148   int spdy_protocol_version_;
    149   scoped_ptr<SpdyWebSocketStream> spdy_websocket_stream_;
    150   std::string challenge_;
    151 
    152   bool save_next_cookie_running_;
    153   bool callback_pending_;
    154 
    155   base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_;
    156   base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_for_send_pending_;
    157 
    158   DISALLOW_COPY_AND_ASSIGN(WebSocketJob);
    159 };
    160 
    161 }  // namespace
    162 
    163 #endif  // NET_WEBSOCKETS_WEBSOCKET_JOB_H_
    164