blob: 32c55399c02cb168d5705649778068e3be0bfebf [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001// 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
David Ghandehari00be30f2017-04-27 21:30:48 -070012#include "base/memory/scoped_ptr.h"
David Ghandehari9e5b5872016-07-28 09:50:04 -070013#include "base/memory/weak_ptr.h"
David Ghandehari00be30f2017-04-27 21:30:48 -070014#include "base/time.h"
15#include "base/timer.h"
David Ghandehari9e5b5872016-07-28 09:50:04 -070016#include "net/base/address_list.h"
17#include "net/base/completion_callback.h"
18#include "net/socket_stream/socket_stream_job.h"
David Ghandehari9e5b5872016-07-28 09:50:04 -070019
20class GURL;
21
22namespace net {
23
24class DrainableIOBuffer;
25class SSLInfo;
26class WebSocketHandshakeRequestHandler;
27class WebSocketHandshakeResponseHandler;
28
29// WebSocket protocol specific job on SocketStream.
30// It captures WebSocket handshake message and handles cookie operations.
31// Chrome security policy doesn't allow renderer process (except dev tools)
32// see HttpOnly cookies, so it injects cookie header in handshake request and
33// strips set-cookie headers in handshake response.
34// TODO(ukai): refactor websocket.cc to use this.
35class NET_EXPORT WebSocketJob
36 : public SocketStreamJob,
David Ghandehari175e9c82017-02-21 15:46:11 -080037 public SocketStream::Delegate {
David Ghandehari9e5b5872016-07-28 09:50:04 -070038 public:
39 // This is state of WebSocket, not SocketStream.
40 enum State {
41 INITIALIZED = -1,
42 CONNECTING = 0,
43 OPEN = 1,
David Ghandehari00be30f2017-04-27 21:30:48 -070044 SEND_CLOSED = 2, // A Close frame has been sent but not received.
45 RECV_CLOSED = 3, // Used briefly between receiving a Close frame and
46 // sending the response. Once the response is sent, the
47 // state changes to CLOSED.
48 CLOSE_WAIT = 4, // The Closing Handshake has completed, but the remote
49 // server has not yet closed the connection.
50 CLOSED = 5, // The Closing Handshake has completed and the connection
51 // has been closed; or the connection is failed.
David Ghandehari9e5b5872016-07-28 09:50:04 -070052 };
53
54 explicit WebSocketJob(SocketStream::Delegate* delegate);
55
56 static void EnsureInit();
57
David Ghandehari9e5b5872016-07-28 09:50:04 -070058 State state() const { return state_; }
59 virtual void Connect() OVERRIDE;
60 virtual bool SendData(const char* data, int len) OVERRIDE;
61 virtual void Close() OVERRIDE;
62 virtual void RestartWithAuth(const AuthCredentials& credentials) OVERRIDE;
63 virtual void DetachDelegate() OVERRIDE;
64
65 // SocketStream::Delegate methods.
66 virtual int OnStartOpenConnection(
67 SocketStream* socket, const CompletionCallback& callback) OVERRIDE;
68 virtual void OnConnected(SocketStream* socket,
69 int max_pending_send_allowed) OVERRIDE;
70 virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE;
71 virtual void OnReceivedData(SocketStream* socket,
72 const char* data,
73 int len) OVERRIDE;
74 virtual void OnClose(SocketStream* socket) OVERRIDE;
75 virtual void OnAuthRequired(
76 SocketStream* socket, AuthChallengeInfo* auth_info) OVERRIDE;
77 virtual void OnSSLCertificateError(SocketStream* socket,
78 const SSLInfo& ssl_info,
79 bool fatal) OVERRIDE;
80 virtual void OnError(const SocketStream* socket, int error) OVERRIDE;
81
David Ghandehari175e9c82017-02-21 15:46:11 -080082 WebSocketHandshakeResponseHandler* GetHandshakeResponse() {
83 return handshake_response_.get();
84 }
David Ghandehari9e5b5872016-07-28 09:50:04 -070085
David Ghandehari00be30f2017-04-27 21:30:48 -070086 void SetState(const State new_state) {
87 DCHECK_GE(new_state, state_); // states should only move forward.
88 state_ = new_state;
89 }
90
David Ghandehari9e5b5872016-07-28 09:50:04 -070091 private:
92 friend class WebSocketThrottle;
David Ghandehari9e5b5872016-07-28 09:50:04 -070093 virtual ~WebSocketJob();
94
95 bool SendHandshakeRequest(const char* data, int len);
96 void AddCookieHeaderAndSend();
97 void LoadCookieCallback(const std::string& cookie);
98
99 void OnSentHandshakeRequest(SocketStream* socket, int amount_sent);
100 void OnReceivedHandshakeResponse(
101 SocketStream* socket, const char* data, int len);
102 void SaveCookiesAndNotifyHeaderComplete();
103 void SaveNextCookie();
104 void SaveCookieCallback(bool cookie_status);
105 void DoSendData();
106
107 GURL GetURLForCookies() const;
108
109 const AddressList& address_list() const;
David Ghandehari9e5b5872016-07-28 09:50:04 -0700110 void SetWaiting();
111 bool IsWaiting() const;
112 void Wakeup();
113 void RetryPendingIO();
114 void CompleteIO(int result);
115
116 bool SendDataInternal(const char* data, int length);
117 void CloseInternal();
118 void SendPending();
David Ghandehari00be30f2017-04-27 21:30:48 -0700119 void CloseTimeout();
120 void StopTimer(base::WaitableEvent* timer_stop_event);
121
122 void WaitForSocketClose();
123 void DelayedClose();
David Ghandehari9e5b5872016-07-28 09:50:04 -0700124
David Ghandehari9e5b5872016-07-28 09:50:04 -0700125 SocketStream::Delegate* delegate_;
126 State state_;
127 bool waiting_;
128 AddressList addresses_;
129 CompletionCallback callback_; // for throttling.
130
131 scoped_ptr<WebSocketHandshakeRequestHandler> handshake_request_;
132 scoped_ptr<WebSocketHandshakeResponseHandler> handshake_response_;
133
134 bool started_to_send_handshake_request_;
135 size_t handshake_request_sent_;
136
137 std::vector<std::string> response_cookies_;
138 size_t response_cookies_save_index_;
139
140 std::deque<scoped_refptr<IOBufferWithSize> > send_buffer_queue_;
141 scoped_refptr<DrainableIOBuffer> current_send_buffer_;
142 std::vector<char> received_data_after_handshake_;
143
David Ghandehari9e5b5872016-07-28 09:50:04 -0700144 std::string challenge_;
145
David Ghandehari00be30f2017-04-27 21:30:48 -0700146 base::TimeDelta closing_handshake_timeout_;
147 scoped_ptr<base::OneShotTimer<WebSocketJob> > close_timer_;
148
David Ghandehari9e5b5872016-07-28 09:50:04 -0700149 base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_;
150 base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_for_send_pending_;
151
152 DISALLOW_COPY_AND_ASSIGN(WebSocketJob);
153};
154
155} // namespace
156
157#endif // NET_WEBSOCKETS_WEBSOCKET_JOB_H_