OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/websockets/websocket_job.h" | 5 #include "net/websockets/websocket_job.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/string_tokenizer.h" | 10 #include "base/string_tokenizer.h" |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 SocketStream* socket, AuthChallengeInfo* auth_info) { | 273 SocketStream* socket, AuthChallengeInfo* auth_info) { |
274 if (delegate_) | 274 if (delegate_) |
275 delegate_->OnAuthRequired(socket, auth_info); | 275 delegate_->OnAuthRequired(socket, auth_info); |
276 } | 276 } |
277 | 277 |
278 void WebSocketJob::OnError(const SocketStream* socket, int error) { | 278 void WebSocketJob::OnError(const SocketStream* socket, int error) { |
279 if (delegate_) | 279 if (delegate_) |
280 delegate_->OnError(socket, error); | 280 delegate_->OnError(socket, error); |
281 } | 281 } |
282 | 282 |
| 283 void WebSocketJob::OnCreatedSpdyStream(int result) { |
| 284 if (state_ == CLOSED) { |
| 285 spdy_websocket_stream_.reset(); |
| 286 //DoCallback(ERR_ABORTED); |
| 287 return; |
| 288 } |
| 289 DCHECK(spdy_websocket_stream_.get()); |
| 290 DCHECK(socket_.get()); |
| 291 DCHECK_NE(ERR_IO_PENDING, result); |
| 292 spdy_websocket_stream_.reset(); |
| 293 //DoCallback(result); |
| 294 } |
| 295 |
| 296 void WebSocketJob::OnSentSpdyHeaders(int result) { |
| 297 // TODO(toyoshim): Error handling on result. |
| 298 if (state_ != CONNECTING) |
| 299 return; |
| 300 if (delegate_) |
| 301 delegate_->OnSentData( |
| 302 socket_, |
| 303 handshake_request_->original_length()); |
| 304 handshake_request_.reset(); |
| 305 } |
| 306 |
| 307 int WebSocketJob::OnReceivedSpdyResponseHeader( |
| 308 const spdy::SpdyHeaderBlock& headers, int status) { |
| 309 DCHECK_NE(INITIALIZED, state_); |
| 310 if (state_ != CONNECTING) |
| 311 return status; |
| 312 if (status != OK) |
| 313 return status; |
| 314 // TODO(toyoshim): Fallback to non-spdy connection? |
| 315 handshake_response_->ParseResponseHeaderBlock(headers, challenge_); |
| 316 |
| 317 SaveCookiesAndNotifyHeaderComplete(); |
| 318 return OK; |
| 319 } |
| 320 |
| 321 void WebSocketJob::OnSentSpdyData(int amount_sent) { |
| 322 DCHECK_NE(INITIALIZED, state_); |
| 323 DCHECK_NE(CONNECTING, state_); |
| 324 if (state_ == CLOSED) |
| 325 return; |
| 326 if (!spdy_websocket_stream_.get()) |
| 327 return; |
| 328 OnSentData(socket_, amount_sent); |
| 329 } |
| 330 |
| 331 void WebSocketJob::OnReceivedSpdyData(const char* data, int length) { |
| 332 DCHECK_NE(INITIALIZED, state_); |
| 333 DCHECK_NE(CONNECTING, state_); |
| 334 if (state_ == CLOSED) |
| 335 return; |
| 336 if (!spdy_websocket_stream_.get()) |
| 337 return; |
| 338 OnReceivedData(socket_, data, length); |
| 339 } |
| 340 |
| 341 void WebSocketJob::OnCloseSpdyStream() { |
| 342 spdy_websocket_stream_.reset(); |
| 343 OnClose(socket_); |
| 344 } |
| 345 |
283 bool WebSocketJob::SendHandshakeRequest(const char* data, int len) { | 346 bool WebSocketJob::SendHandshakeRequest(const char* data, int len) { |
284 DCHECK_EQ(state_, CONNECTING); | 347 DCHECK_EQ(state_, CONNECTING); |
285 if (started_to_send_handshake_request_) | 348 if (started_to_send_handshake_request_) |
286 return false; | 349 return false; |
287 if (!handshake_request_->ParseRequest(data, len)) | 350 if (!handshake_request_->ParseRequest(data, len)) |
288 return false; | 351 return false; |
289 | 352 |
290 // handshake message is completed. | 353 // handshake message is completed. |
291 handshake_response_->set_protocol_version( | 354 handshake_response_->set_protocol_version( |
292 handshake_request_->protocol_version()); | 355 handshake_request_->protocol_version()); |
(...skipping 17 matching lines...) Expand all Loading... |
310 CookieOptions cookie_options; | 373 CookieOptions cookie_options; |
311 cookie_options.set_include_httponly(); | 374 cookie_options.set_include_httponly(); |
312 std::string cookie = | 375 std::string cookie = |
313 socket_->context()->cookie_store()->GetCookiesWithOptions( | 376 socket_->context()->cookie_store()->GetCookiesWithOptions( |
314 GetURLForCookies(), cookie_options); | 377 GetURLForCookies(), cookie_options); |
315 if (!cookie.empty()) | 378 if (!cookie.empty()) |
316 handshake_request_->AppendHeaderIfMissing("Cookie", cookie); | 379 handshake_request_->AppendHeaderIfMissing("Cookie", cookie); |
317 } | 380 } |
318 } | 381 } |
319 | 382 |
320 const std::string& handshake_request = handshake_request_->GetRawRequest(); | 383 if (spdy_websocket_stream_.get()) { |
321 handshake_request_sent_ = 0; | 384 linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock); |
322 socket_->net_log()->AddEvent( | 385 handshake_request_->GetRequestHeaderBlock( |
323 NetLog::TYPE_WEB_SOCKET_SEND_REQUEST_HEADERS, | 386 socket_->url(), headers.get(), &challenge_); |
324 make_scoped_refptr( | 387 spdy_websocket_stream_->SendRequest(headers); |
325 new NetLogWebSocketHandshakeParameter(handshake_request))); | 388 } else { |
326 socket_->SendData(handshake_request.data(), | 389 const std::string& handshake_request = |
327 handshake_request.size()); | 390 handshake_request_->GetRawRequest(); |
| 391 handshake_request_sent_ = 0; |
| 392 socket_->net_log()->AddEvent( |
| 393 NetLog::TYPE_WEB_SOCKET_SEND_REQUEST_HEADERS, |
| 394 make_scoped_refptr( |
| 395 new NetLogWebSocketHandshakeParameter(handshake_request))); |
| 396 socket_->SendData(handshake_request.data(), |
| 397 handshake_request.size()); |
| 398 } |
328 } | 399 } |
329 } | 400 } |
330 | 401 |
331 void WebSocketJob::OnSentHandshakeRequest( | 402 void WebSocketJob::OnSentHandshakeRequest( |
332 SocketStream* socket, int amount_sent) { | 403 SocketStream* socket, int amount_sent) { |
333 DCHECK_EQ(state_, CONNECTING); | 404 DCHECK_EQ(state_, CONNECTING); |
334 handshake_request_sent_ += amount_sent; | 405 handshake_request_sent_ += amount_sent; |
335 DCHECK_LE(handshake_request_sent_, handshake_request_->raw_length()); | 406 DCHECK_LE(handshake_request_sent_, handshake_request_->raw_length()); |
336 if (handshake_request_sent_ >= handshake_request_->raw_length()) { | 407 if (handshake_request_sent_ >= handshake_request_->raw_length()) { |
337 // handshake request has been sent. | 408 // handshake request has been sent. |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 // If so, use it to create the websocket stream. | 528 // If so, use it to create the websocket stream. |
458 HttpTransactionFactory* factory = | 529 HttpTransactionFactory* factory = |
459 socket_->context()->http_transaction_factory(); | 530 socket_->context()->http_transaction_factory(); |
460 if (factory) { | 531 if (factory) { |
461 scoped_refptr<HttpNetworkSession> session = factory->GetSession(); | 532 scoped_refptr<HttpNetworkSession> session = factory->GetSession(); |
462 if (session.get()) { | 533 if (session.get()) { |
463 SpdySessionPool* spdy_pool = session->spdy_session_pool(); | 534 SpdySessionPool* spdy_pool = session->spdy_session_pool(); |
464 const HostPortProxyPair pair(HostPortPair::FromURL(socket_->url()), | 535 const HostPortProxyPair pair(HostPortPair::FromURL(socket_->url()), |
465 socket_->proxy_server()); | 536 socket_->proxy_server()); |
466 if (spdy_pool->HasSession(pair)) { | 537 if (spdy_pool->HasSession(pair)) { |
467 // TODO(toyoshim): Switch to SpdyWebSocketStream here by returning | 538 scoped_refptr<SpdySession> spdy_session = |
468 // ERR_PROTOCOL_SWITCHED. | 539 spdy_pool->Get(pair, *socket_->net_log()); |
| 540 |
| 541 spdy_websocket_stream_.reset( |
| 542 new SpdyWebSocketStream(spdy_session, this)); |
| 543 |
| 544 int result = spdy_websocket_stream_->InitializeStream( |
| 545 socket_->url(), MEDIUM, *socket_->net_log()); |
| 546 if (result == OK) |
| 547 return ERR_PROTOCOL_SWITCHED; |
| 548 return result; |
469 } | 549 } |
470 } | 550 } |
471 } | 551 } |
472 } | 552 } |
473 // No SPDY session was available. | 553 // No SPDY session was available. |
474 // Fallback to connecting a new socket. | 554 // Fallback to connecting a new socket. |
475 return OK; | 555 return OK; |
476 } | 556 } |
477 | 557 |
478 void WebSocketJob::SetWaiting() { | 558 void WebSocketJob::SetWaiting() { |
(...skipping 19 matching lines...) Expand all Loading... |
498 // |callback_| may be NULL if OnClose() or DetachDelegate() was called. | 578 // |callback_| may be NULL if OnClose() or DetachDelegate() was called. |
499 if (callback_) { | 579 if (callback_) { |
500 net::CompletionCallback* callback = callback_; | 580 net::CompletionCallback* callback = callback_; |
501 callback_ = NULL; | 581 callback_ = NULL; |
502 callback->Run(result); | 582 callback->Run(result); |
503 Release(); // Balanced with OnStartOpenConnection(). | 583 Release(); // Balanced with OnStartOpenConnection(). |
504 } | 584 } |
505 } | 585 } |
506 | 586 |
507 bool WebSocketJob::SendDataInternal(const char* data, int length) { | 587 bool WebSocketJob::SendDataInternal(const char* data, int length) { |
508 // TODO(toyoshim): Call protocol specific SendData(). | 588 if (spdy_websocket_stream_.get()) { |
| 589 // TODO(toyoshim): Error handling. |
| 590 spdy_websocket_stream_->SendData(data, length); |
| 591 return true; |
| 592 } |
509 return socket_->SendData(data, length); | 593 return socket_->SendData(data, length); |
510 } | 594 } |
511 | 595 |
512 void WebSocketJob::CloseInternal() { | 596 void WebSocketJob::CloseInternal() { |
513 // TODO(toyoshim): Call protocol specific Close(). | 597 if (spdy_websocket_stream_.get()) |
514 socket_->Close(); | 598 spdy_websocket_stream_->Close(); |
| 599 else |
| 600 socket_->Close(); |
515 } | 601 } |
516 | 602 |
517 void WebSocketJob::SendPending() { | 603 void WebSocketJob::SendPending() { |
518 if (current_buffer_) | 604 if (current_buffer_) |
519 return; | 605 return; |
520 // Current buffer is done. Try next buffer if any. | 606 // Current buffer is done. Try next buffer if any. |
521 // Don't buffer sending data. See comment on case OPEN in SendData(). | 607 // Don't buffer sending data. See comment on case OPEN in SendData(). |
522 if (send_frame_handler_->UpdateCurrentBuffer(false) <= 0) { | 608 if (send_frame_handler_->UpdateCurrentBuffer(false) <= 0) { |
523 // No more data to send. | 609 // No more data to send. |
524 if (state_ == CLOSING) | 610 if (state_ == CLOSING) |
525 CloseInternal(); | 611 CloseInternal(); |
526 return; | 612 return; |
527 } | 613 } |
528 current_buffer_ = new DrainableIOBuffer( | 614 current_buffer_ = new DrainableIOBuffer( |
529 send_frame_handler_->GetCurrentBuffer(), | 615 send_frame_handler_->GetCurrentBuffer(), |
530 send_frame_handler_->GetCurrentBufferSize()); | 616 send_frame_handler_->GetCurrentBufferSize()); |
531 SendDataInternal(current_buffer_->data(), current_buffer_->BytesRemaining()); | 617 SendDataInternal(current_buffer_->data(), current_buffer_->BytesRemaining()); |
532 } | 618 } |
533 | 619 |
534 } // namespace net | 620 } // namespace net |
OLD | NEW |