| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/api/cast_channel/cast_socket.h" | 5 #include "extensions/browser/api/cast_channel/cast_socket.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 return false; | 155 return false; |
| 156 bool result = net::X509Certificate::GetDEREncoded( | 156 bool result = net::X509Certificate::GetDEREncoded( |
| 157 ssl_info.cert->os_cert_handle(), cert); | 157 ssl_info.cert->os_cert_handle(), cert); |
| 158 if (result) | 158 if (result) |
| 159 VLOG_WITH_CONNECTION(1) << "Successfully extracted peer certificate: " | 159 VLOG_WITH_CONNECTION(1) << "Successfully extracted peer certificate: " |
| 160 << *cert; | 160 << *cert; |
| 161 return result; | 161 return result; |
| 162 } | 162 } |
| 163 | 163 |
| 164 bool CastSocket::VerifyChallengeReply() { | 164 bool CastSocket::VerifyChallengeReply() { |
| 165 return AuthenticateChallengeReply(*challenge_reply_.get(), peer_cert_); | 165 return AuthenticateChallengeReply(*challenge_reply_, peer_cert_); |
| 166 } | 166 } |
| 167 | 167 |
| 168 void CastSocket::Connect(const net::CompletionCallback& callback) { | 168 void CastSocket::Connect(const net::CompletionCallback& callback) { |
| 169 DCHECK(CalledOnValidThread()); | 169 DCHECK(CalledOnValidThread()); |
| 170 VLOG_WITH_CONNECTION(1) << "Connect readyState = " << ready_state_; | 170 VLOG_WITH_CONNECTION(1) << "Connect readyState = " << ready_state_; |
| 171 if (ready_state_ != READY_STATE_NONE) { | 171 if (ready_state_ != READY_STATE_NONE) { |
| 172 callback.Run(net::ERR_CONNECTION_FAILED); | 172 callback.Run(net::ERR_CONNECTION_FAILED); |
| 173 return; | 173 return; |
| 174 } | 174 } |
| 175 ready_state_ = READY_STATE_CONNECTING; | 175 ready_state_ = READY_STATE_CONNECTING; |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 rv = DoRead(); | 555 rv = DoRead(); |
| 556 break; | 556 break; |
| 557 case READ_STATE_READ_COMPLETE: | 557 case READ_STATE_READ_COMPLETE: |
| 558 rv = DoReadComplete(rv); | 558 rv = DoReadComplete(rv); |
| 559 break; | 559 break; |
| 560 case READ_STATE_DO_CALLBACK: | 560 case READ_STATE_DO_CALLBACK: |
| 561 rv = DoReadCallback(); | 561 rv = DoReadCallback(); |
| 562 break; | 562 break; |
| 563 case READ_STATE_ERROR: | 563 case READ_STATE_ERROR: |
| 564 rv = DoReadError(rv); | 564 rv = DoReadError(rv); |
| 565 DCHECK_EQ(read_state_, READ_STATE_NONE); |
| 565 break; | 566 break; |
| 566 default: | 567 default: |
| 567 NOTREACHED() << "BUG in read flow. Unknown state: " << state; | 568 NOTREACHED() << "BUG in read flow. Unknown state: " << state; |
| 568 break; | 569 break; |
| 569 } | 570 } |
| 570 } while (rv != net::ERR_IO_PENDING && read_state_ != READ_STATE_NONE); | 571 } while (rv != net::ERR_IO_PENDING && read_state_ != READ_STATE_NONE); |
| 571 | 572 |
| 572 // Read loop is done - If the result is ERR_FAILED then close with error. | 573 if (rv == net::ERR_FAILED) { |
| 573 if (rv == net::ERR_FAILED) | 574 if (ready_state_ == READY_STATE_CONNECTING) { |
| 574 CloseWithError(error_state_); | 575 // Read errors during the handshake should notify the caller via |
| 576 // the connect callback, rather than the message event delegate. |
| 577 PostTaskToStartConnectLoop(net::ERR_FAILED); |
| 578 } else { |
| 579 // Connection is already established. |
| 580 // Close and send error status via the message event delegate. |
| 581 CloseWithError(error_state_); |
| 582 } |
| 583 } |
| 575 } | 584 } |
| 576 | 585 |
| 577 int CastSocket::DoRead() { | 586 int CastSocket::DoRead() { |
| 578 read_state_ = READ_STATE_READ_COMPLETE; | 587 read_state_ = READ_STATE_READ_COMPLETE; |
| 579 // Figure out whether to read header or body, and the remaining bytes. | 588 // Figure out whether to read header or body, and the remaining bytes. |
| 580 uint32 num_bytes_to_read = 0; | 589 uint32 num_bytes_to_read = 0; |
| 581 if (header_read_buffer_->RemainingCapacity() > 0) { | 590 if (header_read_buffer_->RemainingCapacity() > 0) { |
| 582 current_read_buffer_ = header_read_buffer_; | 591 current_read_buffer_ = header_read_buffer_; |
| 583 num_bytes_to_read = header_read_buffer_->RemainingCapacity(); | 592 num_bytes_to_read = header_read_buffer_->RemainingCapacity(); |
| 584 DCHECK_LE(num_bytes_to_read, MessageHeader::header_size()); | 593 CHECK_LE(num_bytes_to_read, MessageHeader::header_size()); |
| 585 } else { | 594 } else { |
| 586 DCHECK_GT(current_message_size_, 0U); | 595 DCHECK_GT(current_message_size_, 0U); |
| 587 num_bytes_to_read = current_message_size_ - body_read_buffer_->offset(); | 596 num_bytes_to_read = current_message_size_ - body_read_buffer_->offset(); |
| 588 current_read_buffer_ = body_read_buffer_; | 597 current_read_buffer_ = body_read_buffer_; |
| 589 DCHECK_LE(num_bytes_to_read, MessageHeader::max_message_size()); | 598 CHECK_LE(num_bytes_to_read, MessageHeader::max_message_size()); |
| 590 } | 599 } |
| 591 DCHECK_GT(num_bytes_to_read, 0U); | 600 CHECK_GT(num_bytes_to_read, 0U); |
| 592 | 601 |
| 593 // Read up to num_bytes_to_read into |current_read_buffer_|. | 602 // Read up to num_bytes_to_read into |current_read_buffer_|. |
| 594 return socket_->Read( | 603 return socket_->Read( |
| 595 current_read_buffer_.get(), | 604 current_read_buffer_.get(), |
| 596 num_bytes_to_read, | 605 num_bytes_to_read, |
| 597 base::Bind(&CastSocket::DoReadLoop, AsWeakPtr())); | 606 base::Bind(&CastSocket::DoReadLoop, AsWeakPtr())); |
| 598 } | 607 } |
| 599 | 608 |
| 600 int CastSocket::DoReadComplete(int result) { | 609 int CastSocket::DoReadComplete(int result) { |
| 601 VLOG_WITH_CONNECTION(2) << "DoReadComplete result = " << result | 610 VLOG_WITH_CONNECTION(2) << "DoReadComplete result = " << result |
| 602 << " header offset = " | 611 << " header offset = " |
| 603 << header_read_buffer_->offset() | 612 << header_read_buffer_->offset() |
| 604 << " body offset = " << body_read_buffer_->offset(); | 613 << " body offset = " << body_read_buffer_->offset(); |
| 605 if (result <= 0) { // 0 means EOF: the peer closed the socket | 614 if (result <= 0) { // 0 means EOF: the peer closed the socket |
| 606 VLOG_WITH_CONNECTION(1) << "Read error, peer closed the socket"; | 615 VLOG_WITH_CONNECTION(1) << "Read error, peer closed the socket"; |
| 607 error_state_ = CHANNEL_ERROR_SOCKET_ERROR; | 616 error_state_ = CHANNEL_ERROR_SOCKET_ERROR; |
| 608 read_state_ = READ_STATE_ERROR; | 617 read_state_ = READ_STATE_ERROR; |
| 609 return result == 0 ? net::ERR_FAILED : result; | 618 return result == 0 ? net::ERR_FAILED : result; |
| 610 } | 619 } |
| 611 | 620 |
| 612 // Some data was read. Move the offset in the current buffer forward. | 621 // Some data was read. Move the offset in the current buffer forward. |
| 613 DCHECK_LE(current_read_buffer_->offset() + result, | 622 CHECK_LE(current_read_buffer_->offset() + result, |
| 614 current_read_buffer_->capacity()); | 623 current_read_buffer_->capacity()); |
| 615 current_read_buffer_->set_offset(current_read_buffer_->offset() + result); | 624 current_read_buffer_->set_offset(current_read_buffer_->offset() + result); |
| 616 read_state_ = READ_STATE_READ; | 625 read_state_ = READ_STATE_READ; |
| 617 | 626 |
| 618 if (current_read_buffer_.get() == header_read_buffer_.get() && | 627 if (current_read_buffer_.get() == header_read_buffer_.get() && |
| 619 current_read_buffer_->RemainingCapacity() == 0) { | 628 current_read_buffer_->RemainingCapacity() == 0) { |
| 620 // A full header is read, process the contents. | 629 // A full header is read, process the contents. |
| 621 if (!ProcessHeader()) { | 630 if (!ProcessHeader()) { |
| 622 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE; | 631 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE; |
| 623 read_state_ = READ_STATE_ERROR; | 632 read_state_ = READ_STATE_ERROR; |
| 624 } | 633 } |
| 625 } else if (current_read_buffer_.get() == body_read_buffer_.get() && | 634 } else if (current_read_buffer_.get() == body_read_buffer_.get() && |
| 626 static_cast<uint32>(current_read_buffer_->offset()) == | 635 static_cast<uint32>(current_read_buffer_->offset()) == |
| 627 current_message_size_) { | 636 current_message_size_) { |
| 628 // Full body is read, process the contents. | 637 // Full body is read, process the contents. |
| 629 if (ProcessBody()) { | 638 if (ProcessBody()) { |
| 630 read_state_ = READ_STATE_DO_CALLBACK; | 639 read_state_ = READ_STATE_DO_CALLBACK; |
| 631 } else { | 640 } else { |
| 632 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE; | 641 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE; |
| 633 read_state_ = READ_STATE_ERROR; | 642 read_state_ = READ_STATE_ERROR; |
| 634 } | 643 } |
| 635 } | 644 } |
| 636 | 645 |
| 637 return net::OK; | 646 return net::OK; |
| 638 } | 647 } |
| 639 | 648 |
| 640 int CastSocket::DoReadCallback() { | 649 int CastSocket::DoReadCallback() { |
| 641 read_state_ = READ_STATE_READ; | 650 read_state_ = READ_STATE_READ; |
| 642 const CastMessage& message = *(current_message_.get()); | 651 const CastMessage& message = *current_message_; |
| 643 if (IsAuthMessage(message)) { | 652 if (ready_state_ == READY_STATE_CONNECTING) { |
| 644 // An auth message is received, check that connect flow is running. | 653 if (IsAuthMessage(message)) { |
| 645 if (ready_state_ == READY_STATE_CONNECTING) { | |
| 646 challenge_reply_.reset(new CastMessage(message)); | 654 challenge_reply_.reset(new CastMessage(message)); |
| 647 PostTaskToStartConnectLoop(net::OK); | 655 PostTaskToStartConnectLoop(net::OK); |
| 656 return net::OK; |
| 648 } else { | 657 } else { |
| 658 // Expected an auth message, got something else instead. Handle as error. |
| 649 read_state_ = READ_STATE_ERROR; | 659 read_state_ = READ_STATE_ERROR; |
| 660 return net::ERR_INVALID_RESPONSE; |
| 650 } | 661 } |
| 651 } else if (delegate_) { | |
| 652 MessageInfo message_info; | |
| 653 if (CastMessageToMessageInfo(message, &message_info)) | |
| 654 delegate_->OnMessage(this, message_info); | |
| 655 else | |
| 656 read_state_ = READ_STATE_ERROR; | |
| 657 } | 662 } |
| 663 |
| 664 MessageInfo message_info; |
| 665 if (!CastMessageToMessageInfo(message, &message_info)) { |
| 666 current_message_->Clear(); |
| 667 read_state_ = READ_STATE_ERROR; |
| 668 return net::ERR_INVALID_RESPONSE; |
| 669 } |
| 670 delegate_->OnMessage(this, message_info); |
| 658 current_message_->Clear(); | 671 current_message_->Clear(); |
| 659 return net::OK; | 672 return net::OK; |
| 660 } | 673 } |
| 661 | 674 |
| 662 int CastSocket::DoReadError(int result) { | 675 int CastSocket::DoReadError(int result) { |
| 663 DCHECK_LE(result, 0); | 676 DCHECK_LE(result, 0); |
| 664 // If inside connection flow, then get back to connect loop. | |
| 665 if (ready_state_ == READY_STATE_CONNECTING) { | |
| 666 PostTaskToStartConnectLoop(result); | |
| 667 // does not try to report error also. | |
| 668 return net::OK; | |
| 669 } | |
| 670 return net::ERR_FAILED; | 677 return net::ERR_FAILED; |
| 671 } | 678 } |
| 672 | 679 |
| 673 bool CastSocket::ProcessHeader() { | 680 bool CastSocket::ProcessHeader() { |
| 674 DCHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()), | 681 CHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()), |
| 675 MessageHeader::header_size()); | 682 MessageHeader::header_size()); |
| 676 MessageHeader header; | 683 MessageHeader header; |
| 677 MessageHeader::ReadFromIOBuffer(header_read_buffer_.get(), &header); | 684 MessageHeader::ReadFromIOBuffer(header_read_buffer_.get(), &header); |
| 678 if (header.message_size > MessageHeader::max_message_size()) | 685 if (header.message_size > MessageHeader::max_message_size()) |
| 679 return false; | 686 return false; |
| 680 | 687 |
| 681 VLOG_WITH_CONNECTION(2) << "Parsed header { message_size: " | 688 VLOG_WITH_CONNECTION(2) << "Parsed header { message_size: " |
| 682 << header.message_size << " }"; | 689 << header.message_size << " }"; |
| 683 current_message_size_ = header.message_size; | 690 current_message_size_ = header.message_size; |
| 684 return true; | 691 return true; |
| 685 } | 692 } |
| 686 | 693 |
| 687 bool CastSocket::ProcessBody() { | 694 bool CastSocket::ProcessBody() { |
| 688 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), | 695 CHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), |
| 689 current_message_size_); | 696 current_message_size_); |
| 690 if (!current_message_->ParseFromArray( | 697 if (!current_message_->ParseFromArray( |
| 691 body_read_buffer_->StartOfBuffer(), current_message_size_)) { | 698 body_read_buffer_->StartOfBuffer(), current_message_size_)) { |
| 692 return false; | 699 return false; |
| 693 } | 700 } |
| 694 current_message_size_ = 0; | 701 current_message_size_ = 0; |
| 695 header_read_buffer_->set_offset(0); | 702 header_read_buffer_->set_offset(0); |
| 696 body_read_buffer_->set_offset(0); | 703 body_read_buffer_->set_offset(0); |
| 697 current_read_buffer_ = header_read_buffer_; | 704 current_read_buffer_ = header_read_buffer_; |
| 698 return true; | 705 return true; |
| 699 } | 706 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 | 741 |
| 735 base::Timer* CastSocket::GetTimer() { | 742 base::Timer* CastSocket::GetTimer() { |
| 736 return connect_timeout_timer_.get(); | 743 return connect_timeout_timer_.get(); |
| 737 } | 744 } |
| 738 | 745 |
| 739 CastSocket::MessageHeader::MessageHeader() : message_size(0) { } | 746 CastSocket::MessageHeader::MessageHeader() : message_size(0) { } |
| 740 | 747 |
| 741 void CastSocket::MessageHeader::SetMessageSize(size_t size) { | 748 void CastSocket::MessageHeader::SetMessageSize(size_t size) { |
| 742 DCHECK_LT(size, static_cast<size_t>(kuint32max)); | 749 DCHECK_LT(size, static_cast<size_t>(kuint32max)); |
| 743 DCHECK_GT(size, 0U); | 750 DCHECK_GT(size, 0U); |
| 744 message_size = static_cast<size_t>(size); | 751 message_size = size; |
| 745 } | 752 } |
| 746 | 753 |
| 747 // TODO(mfoltz): Investigate replacing header serialization with base::Pickle, | 754 // TODO(mfoltz): Investigate replacing header serialization with base::Pickle, |
| 748 // if bit-for-bit compatible. | 755 // if bit-for-bit compatible. |
| 749 void CastSocket::MessageHeader::PrependToString(std::string* str) { | 756 void CastSocket::MessageHeader::PrependToString(std::string* str) { |
| 750 MessageHeader output = *this; | 757 MessageHeader output = *this; |
| 751 output.message_size = base::HostToNet32(message_size); | 758 output.message_size = base::HostToNet32(message_size); |
| 752 size_t header_size = base::checked_cast<size_t,uint32>( | 759 size_t header_size = base::checked_cast<size_t,uint32>( |
| 753 MessageHeader::header_size()); | 760 MessageHeader::header_size()); |
| 754 scoped_ptr<char, base::FreeDeleter> char_array( | 761 scoped_ptr<char, base::FreeDeleter> char_array( |
| (...skipping 30 matching lines...) Expand all Loading... |
| 785 return true; | 792 return true; |
| 786 } | 793 } |
| 787 | 794 |
| 788 CastSocket::WriteRequest::~WriteRequest() { } | 795 CastSocket::WriteRequest::~WriteRequest() { } |
| 789 | 796 |
| 790 } // namespace cast_channel | 797 } // namespace cast_channel |
| 791 } // namespace core_api | 798 } // namespace core_api |
| 792 } // namespace extensions | 799 } // namespace extensions |
| 793 | 800 |
| 794 #undef VLOG_WITH_CONNECTION | 801 #undef VLOG_WITH_CONNECTION |
| OLD | NEW |