| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_channel.h" | 5 #include "net/websockets/websocket_channel.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <limits.h> // for INT_MAX | 8 #include <limits.h> // for INT_MAX |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 // TODO(ricea): If current_send_quota_ has dropped below | 419 // TODO(ricea): If current_send_quota_ has dropped below |
| 420 // send_quota_low_water_mark_, it might be good to increase the "low | 420 // send_quota_low_water_mark_, it might be good to increase the "low |
| 421 // water mark" and "high water mark", but only if the link to the WebSocket | 421 // water mark" and "high water mark", but only if the link to the WebSocket |
| 422 // server is not saturated. | 422 // server is not saturated. |
| 423 scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size())); | 423 scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size())); |
| 424 std::copy(data.begin(), data.end(), buffer->data()); | 424 std::copy(data.begin(), data.end(), buffer->data()); |
| 425 return SendFrameFromIOBuffer(fin, op_code, buffer, data.size()); | 425 return SendFrameFromIOBuffer(fin, op_code, buffer, data.size()); |
| 426 // |this| may have been deleted. | 426 // |this| may have been deleted. |
| 427 } | 427 } |
| 428 | 428 |
| 429 void WebSocketChannel::SendFlowControl(int64_t quota) { | 429 ChannelState WebSocketChannel::SendFlowControl(int64_t quota) { |
| 430 DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED || | 430 DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED || |
| 431 state_ == CLOSE_WAIT); | 431 state_ == CLOSE_WAIT); |
| 432 // TODO(ricea): Kill the renderer if it tries to send us a negative quota | 432 // TODO(ricea): Kill the renderer if it tries to send us a negative quota |
| 433 // value or > INT_MAX. | 433 // value or > INT_MAX. |
| 434 DCHECK_GE(quota, 0); | 434 DCHECK_GE(quota, 0); |
| 435 DCHECK_LE(quota, INT_MAX); | 435 DCHECK_LE(quota, INT_MAX); |
| 436 if (!pending_received_frames_.empty()) { | 436 if (!pending_received_frames_.empty()) { |
| 437 DCHECK_EQ(0u, current_receive_quota_); | 437 DCHECK_EQ(0u, current_receive_quota_); |
| 438 } | 438 } |
| 439 while (!pending_received_frames_.empty() && quota > 0) { | 439 while (!pending_received_frames_.empty() && quota > 0) { |
| 440 PendingReceivedFrame& front = pending_received_frames_.front(); | 440 PendingReceivedFrame& front = pending_received_frames_.front(); |
| 441 const uint64_t data_size = front.size() - front.offset(); | 441 const uint64_t data_size = front.size() - front.offset(); |
| 442 const uint64_t bytes_to_send = | 442 const uint64_t bytes_to_send = |
| 443 std::min(base::checked_cast<uint64_t>(quota), data_size); | 443 std::min(base::checked_cast<uint64_t>(quota), data_size); |
| 444 const bool final = front.final() && data_size == bytes_to_send; | 444 const bool final = front.final() && data_size == bytes_to_send; |
| 445 const char* data = | 445 const char* data = |
| 446 front.data().get() ? front.data()->data() + front.offset() : NULL; | 446 front.data().get() ? front.data()->data() + front.offset() : NULL; |
| 447 DCHECK(!bytes_to_send || data) << "Non empty data should not be null."; | 447 DCHECK(!bytes_to_send || data) << "Non empty data should not be null."; |
| 448 const std::vector<char> data_vector(data, data + bytes_to_send); | 448 const std::vector<char> data_vector(data, data + bytes_to_send); |
| 449 DVLOG(3) << "Sending frame previously split due to quota to the " | 449 DVLOG(3) << "Sending frame previously split due to quota to the " |
| 450 << "renderer: quota=" << quota << " data_size=" << data_size | 450 << "renderer: quota=" << quota << " data_size=" << data_size |
| 451 << " bytes_to_send=" << bytes_to_send; | 451 << " bytes_to_send=" << bytes_to_send; |
| 452 if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) == | 452 if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) == |
| 453 CHANNEL_DELETED) | 453 CHANNEL_DELETED) |
| 454 return; | 454 return CHANNEL_DELETED; |
| 455 if (bytes_to_send < data_size) { | 455 if (bytes_to_send < data_size) { |
| 456 front.DidConsume(bytes_to_send); | 456 front.DidConsume(bytes_to_send); |
| 457 front.ResetOpcode(); | 457 front.ResetOpcode(); |
| 458 return; | 458 return CHANNEL_ALIVE; |
| 459 } | 459 } |
| 460 quota -= bytes_to_send; | 460 quota -= bytes_to_send; |
| 461 | 461 |
| 462 pending_received_frames_.pop(); | 462 pending_received_frames_.pop(); |
| 463 } | 463 } |
| 464 if (pending_received_frames_.empty() && has_received_close_frame_) { |
| 465 // We've been waiting for the client to consume the frames before |
| 466 // responding to the closing handshake initiated by the server. |
| 467 return RespondToClosingHandshake(); |
| 468 } |
| 469 |
| 464 // If current_receive_quota_ == 0 then there is no pending ReadFrames() | 470 // If current_receive_quota_ == 0 then there is no pending ReadFrames() |
| 465 // operation. | 471 // operation. |
| 466 const bool start_read = | 472 const bool start_read = |
| 467 current_receive_quota_ == 0 && quota > 0 && | 473 current_receive_quota_ == 0 && quota > 0 && |
| 468 (state_ == CONNECTED || state_ == SEND_CLOSED || state_ == CLOSE_WAIT); | 474 (state_ == CONNECTED || state_ == SEND_CLOSED || state_ == CLOSE_WAIT); |
| 469 current_receive_quota_ += quota; | 475 current_receive_quota_ += quota; |
| 470 if (start_read) | 476 if (start_read) |
| 471 ignore_result(ReadFrames()); | 477 return ReadFrames(); |
| 472 // |this| may have been deleted. | 478 return CHANNEL_ALIVE; |
| 473 } | 479 } |
| 474 | 480 |
| 475 void WebSocketChannel::StartClosingHandshake(uint16_t code, | 481 ChannelState WebSocketChannel::StartClosingHandshake( |
| 476 const std::string& reason) { | 482 uint16_t code, |
| 483 const std::string& reason) { |
| 477 if (InClosingState()) { | 484 if (InClosingState()) { |
| 478 // When the associated renderer process is killed while the channel is in | 485 // When the associated renderer process is killed while the channel is in |
| 479 // CLOSING state we reach here. | 486 // CLOSING state we reach here. |
| 480 DVLOG(1) << "StartClosingHandshake called in state " << state_ | 487 DVLOG(1) << "StartClosingHandshake called in state " << state_ |
| 481 << ". This may be a bug, or a harmless race."; | 488 << ". This may be a bug, or a harmless race."; |
| 482 return; | 489 return CHANNEL_ALIVE; |
| 490 } |
| 491 if (has_received_close_frame_) { |
| 492 // We reach here if the client wants to start a closing handshake while |
| 493 // the browser is waiting for the client to consume incoming data frames |
| 494 // before responding to a closing handshake initiated by the server. |
| 495 // As the client doesn't want the data frames any more, we can respond to |
| 496 // the closing handshake initiated by the server. |
| 497 return RespondToClosingHandshake(); |
| 483 } | 498 } |
| 484 if (state_ == CONNECTING) { | 499 if (state_ == CONNECTING) { |
| 485 // Abort the in-progress handshake and drop the connection immediately. | 500 // Abort the in-progress handshake and drop the connection immediately. |
| 486 stream_request_.reset(); | 501 stream_request_.reset(); |
| 487 SetState(CLOSED); | 502 SetState(CLOSED); |
| 488 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); | 503 return DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); |
| 489 return; | |
| 490 } | 504 } |
| 491 if (state_ != CONNECTED) { | 505 if (state_ != CONNECTED) { |
| 492 NOTREACHED() << "StartClosingHandshake() called in state " << state_; | 506 NOTREACHED() << "StartClosingHandshake() called in state " << state_; |
| 493 return; | 507 return CHANNEL_ALIVE; |
| 494 } | 508 } |
| 495 | 509 |
| 496 DCHECK(!close_timer_.IsRunning()); | 510 DCHECK(!close_timer_.IsRunning()); |
| 497 // This use of base::Unretained() is safe because we stop the timer in the | 511 // This use of base::Unretained() is safe because we stop the timer in the |
| 498 // destructor. | 512 // destructor. |
| 499 close_timer_.Start( | 513 close_timer_.Start( |
| 500 FROM_HERE, | 514 FROM_HERE, |
| 501 closing_handshake_timeout_, | 515 closing_handshake_timeout_, |
| 502 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this))); | 516 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this))); |
| 503 | 517 |
| 504 // Javascript actually only permits 1000 and 3000-4999, but the implementation | 518 // Javascript actually only permits 1000 and 3000-4999, but the implementation |
| 505 // itself may produce different codes. The length of |reason| is also checked | 519 // itself may produce different codes. The length of |reason| is also checked |
| 506 // by Javascript. | 520 // by Javascript. |
| 507 if (!IsStrictlyValidCloseStatusCode(code) || | 521 if (!IsStrictlyValidCloseStatusCode(code) || |
| 508 reason.size() > kMaximumCloseReasonLength) { | 522 reason.size() > kMaximumCloseReasonLength) { |
| 509 // "InternalServerError" is actually used for errors from any endpoint, per | 523 // "InternalServerError" is actually used for errors from any endpoint, per |
| 510 // errata 3227 to RFC6455. If the renderer is sending us an invalid code or | 524 // errata 3227 to RFC6455. If the renderer is sending us an invalid code or |
| 511 // reason it must be malfunctioning in some way, and based on that we | 525 // reason it must be malfunctioning in some way, and based on that we |
| 512 // interpret this as an internal error. | 526 // interpret this as an internal error. |
| 513 if (SendClose(kWebSocketErrorInternalServerError, "") != CHANNEL_DELETED) { | 527 if (SendClose(kWebSocketErrorInternalServerError, "") == CHANNEL_DELETED) |
| 514 DCHECK_EQ(CONNECTED, state_); | 528 return CHANNEL_DELETED; |
| 515 SetState(SEND_CLOSED); | 529 DCHECK_EQ(CONNECTED, state_); |
| 516 } | 530 SetState(SEND_CLOSED); |
| 517 return; | 531 return CHANNEL_ALIVE; |
| 518 } | 532 } |
| 519 if (SendClose( | 533 if (SendClose( |
| 520 code, | 534 code, |
| 521 StreamingUtf8Validator::Validate(reason) ? reason : std::string()) == | 535 StreamingUtf8Validator::Validate(reason) ? reason : std::string()) == |
| 522 CHANNEL_DELETED) | 536 CHANNEL_DELETED) |
| 523 return; | 537 return CHANNEL_DELETED; |
| 524 DCHECK_EQ(CONNECTED, state_); | 538 DCHECK_EQ(CONNECTED, state_); |
| 525 SetState(SEND_CLOSED); | 539 SetState(SEND_CLOSED); |
| 540 return CHANNEL_ALIVE; |
| 526 } | 541 } |
| 527 | 542 |
| 528 void WebSocketChannel::SendAddChannelRequestForTesting( | 543 void WebSocketChannel::SendAddChannelRequestForTesting( |
| 529 const GURL& socket_url, | 544 const GURL& socket_url, |
| 530 const std::vector<std::string>& requested_subprotocols, | 545 const std::vector<std::string>& requested_subprotocols, |
| 531 const url::Origin& origin, | 546 const url::Origin& origin, |
| 532 const WebSocketStreamCreator& creator) { | 547 const WebSocketStreamCreator& creator) { |
| 533 SendAddChannelRequestWithSuppliedCreator( | 548 SendAddChannelRequestWithSuppliedCreator( |
| 534 socket_url, requested_subprotocols, origin, creator); | 549 socket_url, requested_subprotocols, origin, creator); |
| 535 } | 550 } |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 true, WebSocketFrameHeader::kOpCodePong, data_buffer, size); | 853 true, WebSocketFrameHeader::kOpCodePong, data_buffer, size); |
| 839 DVLOG(3) << "Ignored ping in state " << state_; | 854 DVLOG(3) << "Ignored ping in state " << state_; |
| 840 return CHANNEL_ALIVE; | 855 return CHANNEL_ALIVE; |
| 841 | 856 |
| 842 case WebSocketFrameHeader::kOpCodePong: | 857 case WebSocketFrameHeader::kOpCodePong: |
| 843 DVLOG(1) << "Got Pong of size " << size; | 858 DVLOG(1) << "Got Pong of size " << size; |
| 844 // There is no need to do anything with pong messages. | 859 // There is no need to do anything with pong messages. |
| 845 return CHANNEL_ALIVE; | 860 return CHANNEL_ALIVE; |
| 846 | 861 |
| 847 case WebSocketFrameHeader::kOpCodeClose: { | 862 case WebSocketFrameHeader::kOpCodeClose: { |
| 848 // TODO(ricea): If there is a message which is queued for transmission to | |
| 849 // the renderer, then the renderer should not receive an | |
| 850 // OnClosingHandshake or OnDropChannel IPC until the queued message has | |
| 851 // been completedly transmitted. | |
| 852 uint16_t code = kWebSocketNormalClosure; | 863 uint16_t code = kWebSocketNormalClosure; |
| 853 std::string reason; | 864 std::string reason; |
| 854 std::string message; | 865 std::string message; |
| 855 if (!ParseClose(data_buffer, size, &code, &reason, &message)) { | 866 if (!ParseClose(data_buffer, size, &code, &reason, &message)) { |
| 856 return FailChannel(message, code, reason); | 867 return FailChannel(message, code, reason); |
| 857 } | 868 } |
| 858 // TODO(ricea): Find a way to safely log the message from the close | 869 // TODO(ricea): Find a way to safely log the message from the close |
| 859 // message (escape control codes and so on). | 870 // message (escape control codes and so on). |
| 860 DVLOG(1) << "Got Close with code " << code; | 871 DVLOG(1) << "Got Close with code " << code; |
| 861 switch (state_) { | 872 return HandleCloseFrame(code, reason); |
| 862 case CONNECTED: | |
| 863 SetState(RECV_CLOSED); | |
| 864 | |
| 865 if (SendClose(code, reason) == CHANNEL_DELETED) | |
| 866 return CHANNEL_DELETED; | |
| 867 DCHECK_EQ(RECV_CLOSED, state_); | |
| 868 | |
| 869 SetState(CLOSE_WAIT); | |
| 870 DCHECK(!close_timer_.IsRunning()); | |
| 871 // This use of base::Unretained() is safe because we stop the timer | |
| 872 // in the destructor. | |
| 873 close_timer_.Start( | |
| 874 FROM_HERE, | |
| 875 underlying_connection_close_timeout_, | |
| 876 base::Bind( | |
| 877 &WebSocketChannel::CloseTimeout, base::Unretained(this))); | |
| 878 | |
| 879 if (event_interface_->OnClosingHandshake() == CHANNEL_DELETED) | |
| 880 return CHANNEL_DELETED; | |
| 881 has_received_close_frame_ = true; | |
| 882 received_close_code_ = code; | |
| 883 received_close_reason_ = reason; | |
| 884 break; | |
| 885 | |
| 886 case SEND_CLOSED: | |
| 887 SetState(CLOSE_WAIT); | |
| 888 DCHECK(close_timer_.IsRunning()); | |
| 889 close_timer_.Stop(); | |
| 890 // This use of base::Unretained() is safe because we stop the timer | |
| 891 // in the destructor. | |
| 892 close_timer_.Start( | |
| 893 FROM_HERE, | |
| 894 underlying_connection_close_timeout_, | |
| 895 base::Bind( | |
| 896 &WebSocketChannel::CloseTimeout, base::Unretained(this))); | |
| 897 | |
| 898 // From RFC6455 section 7.1.5: "Each endpoint | |
| 899 // will see the status code sent by the other end as _The WebSocket | |
| 900 // Connection Close Code_." | |
| 901 has_received_close_frame_ = true; | |
| 902 received_close_code_ = code; | |
| 903 received_close_reason_ = reason; | |
| 904 break; | |
| 905 | |
| 906 default: | |
| 907 LOG(DFATAL) << "Got Close in unexpected state " << state_; | |
| 908 break; | |
| 909 } | |
| 910 return CHANNEL_ALIVE; | |
| 911 } | 873 } |
| 912 | 874 |
| 913 default: | 875 default: |
| 914 return FailChannel( | 876 return FailChannel( |
| 915 base::StringPrintf("Unrecognized frame opcode: %d", opcode), | 877 base::StringPrintf("Unrecognized frame opcode: %d", opcode), |
| 916 kWebSocketErrorProtocolError, | 878 kWebSocketErrorProtocolError, |
| 917 "Unknown opcode"); | 879 "Unknown opcode"); |
| 918 } | 880 } |
| 919 } | 881 } |
| 920 | 882 |
| 921 ChannelState WebSocketChannel::HandleDataFrame( | 883 ChannelState WebSocketChannel::HandleDataFrame( |
| 922 WebSocketFrameHeader::OpCode opcode, | 884 WebSocketFrameHeader::OpCode opcode, |
| 923 bool final, | 885 bool final, |
| 924 const scoped_refptr<IOBuffer>& data_buffer, | 886 const scoped_refptr<IOBuffer>& data_buffer, |
| 925 uint64_t size) { | 887 uint64_t size) { |
| 926 if (state_ != CONNECTED) { | 888 if (state_ != CONNECTED) { |
| 927 DVLOG(3) << "Ignored data packet received in state " << state_; | 889 DVLOG(3) << "Ignored data packet received in state " << state_; |
| 928 return CHANNEL_ALIVE; | 890 return CHANNEL_ALIVE; |
| 929 } | 891 } |
| 892 if (has_received_close_frame_) { |
| 893 DVLOG(3) << "Ignored data packet as we've received a close frame."; |
| 894 return CHANNEL_ALIVE; |
| 895 } |
| 930 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || | 896 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || |
| 931 opcode == WebSocketFrameHeader::kOpCodeText || | 897 opcode == WebSocketFrameHeader::kOpCodeText || |
| 932 opcode == WebSocketFrameHeader::kOpCodeBinary); | 898 opcode == WebSocketFrameHeader::kOpCodeBinary); |
| 933 const bool got_continuation = | 899 const bool got_continuation = |
| 934 (opcode == WebSocketFrameHeader::kOpCodeContinuation); | 900 (opcode == WebSocketFrameHeader::kOpCodeContinuation); |
| 935 if (got_continuation != expecting_to_handle_continuation_) { | 901 if (got_continuation != expecting_to_handle_continuation_) { |
| 936 const std::string console_log = got_continuation | 902 const std::string console_log = got_continuation |
| 937 ? "Received unexpected continuation frame." | 903 ? "Received unexpected continuation frame." |
| 938 : "Received start of new message but previous message is unfinished."; | 904 : "Received start of new message but previous message is unfinished."; |
| 939 const std::string reason = got_continuation | 905 const std::string reason = got_continuation |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 // TODO(ricea): Can this copy be eliminated? | 953 // TODO(ricea): Can this copy be eliminated? |
| 988 const char* const data_begin = size ? data_buffer->data() : NULL; | 954 const char* const data_begin = size ? data_buffer->data() : NULL; |
| 989 const char* const data_end = data_begin + size; | 955 const char* const data_end = data_begin + size; |
| 990 const std::vector<char> data(data_begin, data_end); | 956 const std::vector<char> data(data_begin, data_end); |
| 991 current_receive_quota_ -= size; | 957 current_receive_quota_ -= size; |
| 992 | 958 |
| 993 // Sends the received frame to the renderer process. | 959 // Sends the received frame to the renderer process. |
| 994 return event_interface_->OnDataFrame(final, opcode_to_send, data); | 960 return event_interface_->OnDataFrame(final, opcode_to_send, data); |
| 995 } | 961 } |
| 996 | 962 |
| 963 ChannelState WebSocketChannel::HandleCloseFrame(uint16_t code, |
| 964 const std::string& reason) { |
| 965 DVLOG(1) << "Got Close with code " << code; |
| 966 switch (state_) { |
| 967 case CONNECTED: |
| 968 has_received_close_frame_ = true; |
| 969 received_close_code_ = code; |
| 970 received_close_reason_ = reason; |
| 971 if (!pending_received_frames_.empty()) { |
| 972 // We have some data to be sent to the renderer before sending this |
| 973 // frame. |
| 974 return CHANNEL_ALIVE; |
| 975 } |
| 976 return RespondToClosingHandshake(); |
| 977 |
| 978 case SEND_CLOSED: |
| 979 SetState(CLOSE_WAIT); |
| 980 DCHECK(close_timer_.IsRunning()); |
| 981 close_timer_.Stop(); |
| 982 // This use of base::Unretained() is safe because we stop the timer |
| 983 // in the destructor. |
| 984 close_timer_.Start( |
| 985 FROM_HERE, underlying_connection_close_timeout_, |
| 986 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this))); |
| 987 |
| 988 // From RFC6455 section 7.1.5: "Each endpoint |
| 989 // will see the status code sent by the other end as _The WebSocket |
| 990 // Connection Close Code_." |
| 991 has_received_close_frame_ = true; |
| 992 received_close_code_ = code; |
| 993 received_close_reason_ = reason; |
| 994 break; |
| 995 |
| 996 default: |
| 997 LOG(DFATAL) << "Got Close in unexpected state " << state_; |
| 998 break; |
| 999 } |
| 1000 return CHANNEL_ALIVE; |
| 1001 } |
| 1002 |
| 1003 ChannelState WebSocketChannel::RespondToClosingHandshake() { |
| 1004 DCHECK(has_received_close_frame_); |
| 1005 DCHECK_EQ(CONNECTED, state_); |
| 1006 SetState(RECV_CLOSED); |
| 1007 if (SendClose(received_close_code_, received_close_reason_) == |
| 1008 CHANNEL_DELETED) |
| 1009 return CHANNEL_DELETED; |
| 1010 DCHECK_EQ(RECV_CLOSED, state_); |
| 1011 |
| 1012 SetState(CLOSE_WAIT); |
| 1013 DCHECK(!close_timer_.IsRunning()); |
| 1014 // This use of base::Unretained() is safe because we stop the timer |
| 1015 // in the destructor. |
| 1016 close_timer_.Start( |
| 1017 FROM_HERE, underlying_connection_close_timeout_, |
| 1018 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this))); |
| 1019 |
| 1020 return event_interface_->OnClosingHandshake(); |
| 1021 } |
| 1022 |
| 997 ChannelState WebSocketChannel::SendFrameFromIOBuffer( | 1023 ChannelState WebSocketChannel::SendFrameFromIOBuffer( |
| 998 bool fin, | 1024 bool fin, |
| 999 WebSocketFrameHeader::OpCode op_code, | 1025 WebSocketFrameHeader::OpCode op_code, |
| 1000 const scoped_refptr<IOBuffer>& buffer, | 1026 const scoped_refptr<IOBuffer>& buffer, |
| 1001 uint64_t size) { | 1027 uint64_t size) { |
| 1002 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED); | 1028 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED); |
| 1003 DCHECK(stream_); | 1029 DCHECK(stream_); |
| 1004 | 1030 |
| 1005 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(op_code)); | 1031 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(op_code)); |
| 1006 WebSocketFrameHeader& header = frame->header; | 1032 WebSocketFrameHeader& header = frame->header; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1142 } | 1168 } |
| 1143 | 1169 |
| 1144 void WebSocketChannel::CloseTimeout() { | 1170 void WebSocketChannel::CloseTimeout() { |
| 1145 stream_->Close(); | 1171 stream_->Close(); |
| 1146 SetState(CLOSED); | 1172 SetState(CLOSED); |
| 1147 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); | 1173 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); |
| 1148 // |this| has been deleted. | 1174 // |this| has been deleted. |
| 1149 } | 1175 } |
| 1150 | 1176 |
| 1151 } // namespace net | 1177 } // namespace net |
| OLD | NEW |