Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(866)

Side by Side Diff: chrome/browser/net/websocket_experiment/websocket_experiment_task.cc

Issue 333045: WIP: websocket live experiment (Closed)
Patch Set: fix comment Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/net/websocket_experiment/websocket_experiment_task.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #include "chrome/browser/net/websocket_experiment/websocket_experiment_task.h"
6
7 #include "base/message_loop.h"
8 #include "chrome/browser/net/url_request_context_getter.h"
9 #include "chrome/browser/profile.h"
10 #include "net/websockets/websocket.h"
11
12 namespace chrome_browser_net_websocket_experiment {
13
14 URLFetcher* WebSocketExperimentTask::Context::CreateURLFetcher() {
15 return new URLFetcher(config_.http_url, URLFetcher::HEAD, task_);
16 }
17
18 net::WebSocket* WebSocketExperimentTask::Context::CreateWebSocket() {
19 URLRequestContextGetter* getter =
20 Profile::GetDefaultRequestContext();
21 DCHECK(getter);
22 net::WebSocket::Request* request(
23 new net::WebSocket::Request(config_.url,
24 config_.ws_protocol,
25 config_.ws_origin,
26 config_.ws_location,
27 getter->GetURLRequestContext()));
28 return new net::WebSocket(request, task_);
29 }
30
31 WebSocketExperimentTask::WebSocketExperimentTask(
32 const Config& config,
33 net::CompletionCallback* callback)
34 : config_(config),
35 context_(ALLOW_THIS_IN_INITIALIZER_LIST(new Context(config, this))),
36 message_loop_(MessageLoopForIO::current()),
37 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
38 callback_(callback),
39 next_state_(STATE_NONE) {
40 DCHECK(message_loop_);
41 }
42
43 WebSocketExperimentTask::~WebSocketExperimentTask() {
44 DCHECK(!websocket_);
45 }
46
47 void WebSocketExperimentTask::Run() {
48 next_state_ = STATE_URL_FETCH;
49 DoLoop(net::OK);
50 }
51
52 // URLFetcher::Delegate method.
53 void WebSocketExperimentTask::OnURLFetchComplete(
54 const URLFetcher* source,
55 const GURL& url,
56 const URLRequestStatus& status,
57 int response_code,
58 const ResponseCookies& cookies,
59 const std::string& data) {
60 result_.url_fetch = base::TimeTicks::Now() - url_fetch_start_time_;
61 RevokeTimeoutTimer();
62 int result = net::ERR_FAILED;
63 if (next_state_ != STATE_URL_FETCH_COMPLETE)
64 result = net::ERR_UNEXPECTED;
65 else if (response_code == 200)
66 result = net::OK;
67 DoLoop(result);
68 }
69
70 // net::WebSocketDelegate
71 void WebSocketExperimentTask::OnOpen(net::WebSocket* websocket) {
72 result_.websocket_connect =
73 base::TimeTicks::Now() - websocket_connect_start_time_;
74 RevokeTimeoutTimer();
75 if (next_state_ == STATE_WEBSOCKET_CONNECT_COMPLETE)
76 DoLoop(net::OK);
77 else
78 DoLoop(net::ERR_UNEXPECTED);
79 }
80
81 void WebSocketExperimentTask::OnMessage(
82 net::WebSocket* websocket, const std::string& msg) {
83 if (!result_.websocket_echo.ToInternalValue())
84 result_.websocket_echo =
85 base::TimeTicks::Now() - websocket_echo_start_time_;
86 if (!websocket_idle_start_time_.is_null() &&
87 !result_.websocket_idle.ToInternalValue())
88 result_.websocket_idle =
89 base::TimeTicks::Now() - websocket_idle_start_time_;
90 RevokeTimeoutTimer();
91 received_messages_.push_back(msg);
92 int result = net::ERR_UNEXPECTED;
93 switch (next_state_) {
94 case STATE_WEBSOCKET_RECV_HELLO:
95 case STATE_WEBSOCKET_RECV_PUSH_MESSAGE:
96 case STATE_WEBSOCKET_RECV_BYE:
97 result = net::OK;
98 break;
99 default:
100 break;
101 }
102 DoLoop(result);
103 }
104
105 void WebSocketExperimentTask::OnClose(net::WebSocket* websocket) {
106 RevokeTimeoutTimer();
107 int result = net::ERR_CONNECTION_CLOSED;
108 if (next_state_ == STATE_WEBSOCKET_CLOSE_COMPLETE)
109 result = net::OK;
110 DoLoop(result);
111 }
112
113 void WebSocketExperimentTask::SetContext(Context* context) {
114 context_.reset(context);
115 }
116
117 void WebSocketExperimentTask::OnTimedOut() {
118 RevokeTimeoutTimer();
119 DoLoop(net::ERR_TIMED_OUT);
120 }
121
122 void WebSocketExperimentTask::DoLoop(int result) {
123 do {
124 State state = next_state_;
125 next_state_ = STATE_NONE;
126 switch (state) {
127 case STATE_URL_FETCH:
128 result = DoURLFetch();
129 break;
130 case STATE_URL_FETCH_COMPLETE:
131 result = DoURLFetchComplete(result);
132 break;
133 case STATE_WEBSOCKET_CONNECT:
134 result = DoWebSocketConnect();
135 break;
136 case STATE_WEBSOCKET_CONNECT_COMPLETE:
137 result = DoWebSocketConnectComplete(result);
138 break;
139 case STATE_WEBSOCKET_SEND_HELLO:
140 result = DoWebSocketSendHello();
141 break;
142 case STATE_WEBSOCKET_RECV_HELLO:
143 result = DoWebSocketReceiveHello(result);
144 break;
145 case STATE_WEBSOCKET_KEEP_IDLE:
146 result = DoWebSocketKeepIdle();
147 break;
148 case STATE_WEBSOCKET_KEEP_IDLE_COMPLETE:
149 result = DoWebSocketKeepIdleComplete(result);
150 break;
151 case STATE_WEBSOCKET_RECV_PUSH_MESSAGE:
152 result = DoWebSocketReceivePushMessage(result);
153 break;
154 case STATE_WEBSOCKET_ECHO_BACK_MESSAGE:
155 result = DoWebSocketEchoBackMessage();
156 break;
157 case STATE_WEBSOCKET_RECV_BYE:
158 result = DoWebSocketReceiveBye(result);
159 break;
160 case STATE_WEBSOCKET_CLOSE:
161 result = DoWebSocketClose();
162 break;
163 case STATE_WEBSOCKET_CLOSE_COMPLETE:
164 result = DoWebSocketCloseComplete(result);
165 break;
166 default:
167 NOTREACHED();
168 break;
169 }
170 } while (result != net::ERR_IO_PENDING && next_state_ != STATE_NONE);
171
172 if (result != net::ERR_IO_PENDING)
173 Finish(result);
174 }
175
176 int WebSocketExperimentTask::DoURLFetch() {
177 next_state_ = STATE_URL_FETCH_COMPLETE;
178 DCHECK(!url_fetcher_.get());
179
180 url_fetcher_.reset(context_->CreateURLFetcher());
181 url_fetch_start_time_ = base::TimeTicks::Now();
182 url_fetcher_->Start();
183
184 SetTimeout(config_.url_fetch_deadline_ms);
185 return net::ERR_IO_PENDING;
186 }
187
188 int WebSocketExperimentTask::DoURLFetchComplete(int result) {
189 url_fetcher_.reset();
190
191 if (result < 0)
192 return result;
193
194 next_state_ = STATE_WEBSOCKET_CONNECT;
195 return net::OK;
196 }
197
198 int WebSocketExperimentTask::DoWebSocketConnect() {
199 DCHECK(!websocket_);
200
201 next_state_ = STATE_WEBSOCKET_CONNECT_COMPLETE;
202 websocket_ = context_->CreateWebSocket();
203 websocket_connect_start_time_ = base::TimeTicks::Now();
204 websocket_->Connect();
205
206 SetTimeout(config_.websocket_onopen_deadline_ms);
207 return net::ERR_IO_PENDING;
208 }
209
210 int WebSocketExperimentTask::DoWebSocketConnectComplete(int result) {
211 if (result < 0)
212 return result;
213 DCHECK(websocket_);
214
215 next_state_ = STATE_WEBSOCKET_SEND_HELLO;
216 return net::OK;
217 }
218
219 int WebSocketExperimentTask::DoWebSocketSendHello() {
220 DCHECK(websocket_);
221
222 next_state_ = STATE_WEBSOCKET_RECV_HELLO;
223
224 websocket_echo_start_time_ = base::TimeTicks::Now();
225 websocket_->Send(config_.websocket_hello_message);
226 SetTimeout(config_.websocket_hello_echoback_deadline_ms);
227 return net::ERR_IO_PENDING;
228 }
229
230 int WebSocketExperimentTask::DoWebSocketReceiveHello(int result) {
231 if (result < 0)
232 return result;
233
234 DCHECK(websocket_);
235
236 if (received_messages_.size() != 1)
237 return net::ERR_INVALID_RESPONSE;
238
239 std::string msg = received_messages_.front();
240 received_messages_.pop_front();
241 if (msg != config_.websocket_hello_message)
242 return net::ERR_INVALID_RESPONSE;
243
244 next_state_ = STATE_WEBSOCKET_KEEP_IDLE;
245 return net::OK;
246 }
247
248 int WebSocketExperimentTask::DoWebSocketKeepIdle() {
249 DCHECK(websocket_);
250
251 next_state_ = STATE_WEBSOCKET_KEEP_IDLE_COMPLETE;
252 websocket_idle_start_time_ = base::TimeTicks::Now();
253 SetTimeout(config_.websocket_idle_ms);
254 return net::ERR_IO_PENDING;
255 }
256
257 int WebSocketExperimentTask::DoWebSocketKeepIdleComplete(int result) {
258 if (result != net::ERR_TIMED_OUT) {
259 // Server sends back too early, or unexpected close?
260 if (result == net::OK)
261 result = net::ERR_UNEXPECTED;
262 return result;
263 }
264
265 DCHECK(websocket_);
266
267 next_state_ = STATE_WEBSOCKET_RECV_PUSH_MESSAGE;
268 SetTimeout(config_.websocket_receive_push_message_deadline_ms);
269 return net::ERR_IO_PENDING;
270 }
271
272 int WebSocketExperimentTask::DoWebSocketReceivePushMessage(int result) {
273 if (result < 0)
274 return result;
275
276 DCHECK(websocket_);
277 if (received_messages_.size() != 1)
278 return net::ERR_INVALID_RESPONSE;
279
280 push_message_ = received_messages_.front();
281 received_messages_.pop_front();
282
283 next_state_ = STATE_WEBSOCKET_ECHO_BACK_MESSAGE;
284 return net::OK;
285 }
286
287 int WebSocketExperimentTask::DoWebSocketEchoBackMessage() {
288 DCHECK(websocket_);
289 DCHECK(!push_message_.empty());
290
291 next_state_ = STATE_WEBSOCKET_RECV_BYE;
292 websocket_->Send(push_message_);
293 SetTimeout(config_.websocket_bye_deadline_ms);
294 return net::ERR_IO_PENDING;
295 }
296
297 int WebSocketExperimentTask::DoWebSocketReceiveBye(int result) {
298 if (result < 0)
299 return result;
300
301 DCHECK(websocket_);
302
303 if (received_messages_.size() != 1)
304 return net::ERR_INVALID_RESPONSE;
305
306 std::string bye = received_messages_.front();
307 received_messages_.pop_front();
308
309 if (bye != config_.websocket_bye_message)
310 return net::ERR_INVALID_RESPONSE;
311
312 next_state_ = STATE_WEBSOCKET_CLOSE;
313 return net::OK;
314 }
315
316 int WebSocketExperimentTask::DoWebSocketClose() {
317 DCHECK(websocket_);
318
319 next_state_ = STATE_WEBSOCKET_CLOSE_COMPLETE;
320 websocket_->Close();
321 SetTimeout(config_.websocket_close_deadline_ms);
322 return net::ERR_IO_PENDING;
323 }
324
325 int WebSocketExperimentTask::DoWebSocketCloseComplete(int result) {
326 websocket_ = NULL;
327 return result;
328 }
329
330 void WebSocketExperimentTask::SetTimeout(int64 deadline_ms) {
331 message_loop_->PostDelayedTask(
332 FROM_HERE,
333 method_factory_.NewRunnableMethod(&WebSocketExperimentTask::OnTimedOut),
334 deadline_ms);
335 }
336
337 void WebSocketExperimentTask::RevokeTimeoutTimer() {
338 method_factory_.RevokeAll();
339 }
340
341 void WebSocketExperimentTask::Finish(int result) {
342 callback_->Run(result);
343 }
344
345 } // namespace chrome_browser_net
OLDNEW
« no previous file with comments | « chrome/browser/net/websocket_experiment/websocket_experiment_task.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698