Index: chrome/browser/extensions/api/cast_channel/cast_socket.cc |
diff --git a/chrome/browser/extensions/api/cast_channel/cast_socket.cc b/chrome/browser/extensions/api/cast_channel/cast_socket.cc |
index 6130d92e18755dc825880177b785f7536baf5afc..e4712dc9cf6d8d709bf3b7a2c0786660ff86dce0 100644 |
--- a/chrome/browser/extensions/api/cast_channel/cast_socket.cc |
+++ b/chrome/browser/extensions/api/cast_channel/cast_socket.cc |
@@ -158,7 +158,7 @@ bool CastSocket::ExtractPeerCert(std::string* cert) { |
} |
bool CastSocket::VerifyChallengeReply() { |
- return AuthenticateChallengeReply(*challenge_reply_.get(), peer_cert_); |
+ return AuthenticateChallengeReply(*challenge_reply_, peer_cert_); |
} |
void CastSocket::Connect(const net::CompletionCallback& callback) { |
@@ -532,6 +532,7 @@ void CastSocket::DoReadLoop(int result) { |
break; |
case READ_STATE_ERROR: |
rv = DoReadError(rv); |
+ DCHECK_EQ(read_state_, READ_STATE_NONE); |
break; |
default: |
NOTREACHED() << "BUG in read flow. Unknown state: " << state; |
@@ -539,9 +540,18 @@ void CastSocket::DoReadLoop(int result) { |
} |
} while (rv != net::ERR_IO_PENDING && read_state_ != READ_STATE_NONE); |
- // Read loop is done - If the result is ERR_FAILED then close with error. |
- if (rv == net::ERR_FAILED) |
- CloseWithError(error_state_); |
+ if (rv == net::ERR_FAILED) { |
+ if (ready_state_ == READY_STATE_CONNECTING) { |
+ // Connection not yet established. |
Wez
2014/07/23 21:27:42
nit: No need for this; should be implicit from rea
Kevin M
2014/07/23 23:40:46
Done.
|
+ // Read errors during the handshake should notify the caller via |
+ // the connect callback, rather than the message event delegate. |
+ PostTaskToStartConnectLoop(net::ERR_FAILED); |
+ } else { |
+ // Connection is already established. |
+ // Close and send error status via the message event delegate. |
+ CloseWithError(error_state_); |
+ } |
+ } |
} |
int CastSocket::DoRead() { |
@@ -551,14 +561,23 @@ int CastSocket::DoRead() { |
if (header_read_buffer_->RemainingCapacity() > 0) { |
current_read_buffer_ = header_read_buffer_; |
num_bytes_to_read = header_read_buffer_->RemainingCapacity(); |
- DCHECK_LE(num_bytes_to_read, MessageHeader::header_size()); |
+ if (num_bytes_to_read > MessageHeader::header_size()) { |
+ error_state_ = CHANNEL_ERROR_INVALID_MESSAGE; |
+ return net::ERR_FAILED; |
+ } |
} else { |
DCHECK_GT(current_message_size_, 0U); |
num_bytes_to_read = current_message_size_ - body_read_buffer_->offset(); |
current_read_buffer_ = body_read_buffer_; |
- DCHECK_LE(num_bytes_to_read, MessageHeader::max_message_size()); |
+ if (num_bytes_to_read > MessageHeader::max_message_size()) { |
+ error_state_ = CHANNEL_ERROR_INVALID_MESSAGE; |
+ return net::ERR_FAILED; |
+ } |
+ } |
+ if (num_bytes_to_read == 0) { |
+ error_state_ = CHANNEL_ERROR_INVALID_MESSAGE; |
+ return net::ERR_FAILED; |
} |
- DCHECK_GT(num_bytes_to_read, 0U); |
// Read up to num_bytes_to_read into |current_read_buffer_|. |
return socket_->Read( |
@@ -580,8 +599,8 @@ int CastSocket::DoReadComplete(int result) { |
} |
// Some data was read. Move the offset in the current buffer forward. |
- DCHECK_LE(current_read_buffer_->offset() + result, |
- current_read_buffer_->capacity()); |
+ CHECK_LE(current_read_buffer_->offset() + result, |
+ current_read_buffer_->capacity()); |
current_read_buffer_->set_offset(current_read_buffer_->offset() + result); |
read_state_ = READ_STATE_READ; |
@@ -609,40 +628,38 @@ int CastSocket::DoReadComplete(int result) { |
int CastSocket::DoReadCallback() { |
read_state_ = READ_STATE_READ; |
- const CastMessage& message = *(current_message_.get()); |
- if (IsAuthMessage(message)) { |
- // An auth message is received, check that connect flow is running. |
- if (ready_state_ == READY_STATE_CONNECTING) { |
+ const CastMessage& message = *current_message_; |
+ if (ready_state_ == READY_STATE_CONNECTING) { |
+ if (IsAuthMessage(message)) { |
challenge_reply_.reset(new CastMessage(message)); |
PostTaskToStartConnectLoop(net::OK); |
+ return net::OK; |
} else { |
+ // Expected an auth message, got something else instead. Handle as error. |
read_state_ = READ_STATE_ERROR; |
+ return net::ERR_INVALID_RESPONSE; |
} |
- } else if (delegate_) { |
- MessageInfo message_info; |
- if (CastMessageToMessageInfo(message, &message_info)) |
- delegate_->OnMessage(this, message_info); |
- else |
- read_state_ = READ_STATE_ERROR; |
} |
+ |
+ MessageInfo message_info; |
+ if (!CastMessageToMessageInfo(message, &message_info)) { |
+ current_message_->Clear(); |
+ read_state_ = READ_STATE_ERROR; |
+ return net::ERR_INVALID_RESPONSE; |
+ } |
+ delegate_->OnMessage(this, message_info); |
current_message_->Clear(); |
return net::OK; |
} |
int CastSocket::DoReadError(int result) { |
DCHECK_LE(result, 0); |
- // If inside connection flow, then get back to connect loop. |
- if (ready_state_ == READY_STATE_CONNECTING) { |
- PostTaskToStartConnectLoop(result); |
- // does not try to report error also. |
- return net::OK; |
- } |
return net::ERR_FAILED; |
} |
bool CastSocket::ProcessHeader() { |
- DCHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()), |
- MessageHeader::header_size()); |
+ CHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()), |
+ MessageHeader::header_size()); |
MessageHeader header; |
MessageHeader::ReadFromIOBuffer(header_read_buffer_.get(), &header); |
if (header.message_size > MessageHeader::max_message_size()) |
@@ -655,8 +672,10 @@ bool CastSocket::ProcessHeader() { |
} |
bool CastSocket::ProcessBody() { |
- DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), |
- current_message_size_); |
+ if (static_cast<uint32>(body_read_buffer_->offset()) != |
+ current_message_size_) { |
+ return false; |
+ } |
if (!current_message_->ParseFromArray( |
body_read_buffer_->StartOfBuffer(), current_message_size_)) { |
return false; |
@@ -679,10 +698,12 @@ bool CastSocket::Serialize(const CastMessage& message_proto, |
return false; |
} |
CastSocket::MessageHeader header; |
- header.SetMessageSize(message_size); |
+ if (!header.SetMessageSize(message_size)) { |
+ return false; |
+ } |
header.PrependToString(message_data); |
return true; |
-}; |
+} |
void CastSocket::CloseWithError(ChannelError error) { |
DCHECK(CalledOnValidThread()); |
@@ -704,10 +725,13 @@ bool CastSocket::CalledOnValidThread() const { |
CastSocket::MessageHeader::MessageHeader() : message_size(0) { } |
-void CastSocket::MessageHeader::SetMessageSize(size_t size) { |
- DCHECK(size < static_cast<size_t>(kuint32max)); |
- DCHECK(size > 0); |
+bool CastSocket::MessageHeader::SetMessageSize(size_t size) { |
+ if (size >= static_cast<size_t>(kuint32max) || |
Wez
2014/07/23 21:27:42
Don't we already have a check against max_message_
Ryan Sleevi
2014/07/23 22:31:13
It would matter for 64-bit
Wez
2014/07/23 22:33:31
Except that we already check against max_message_s
Kevin M
2014/07/23 23:40:46
True. Removed the check. Thanks.
|
+ size == 0) { |
+ return false; |
+ } |
message_size = static_cast<size_t>(size); |
Ryan Sleevi
2014/07/23 22:31:13
Why is this static cast needed?
It feels like bot
Kevin M
2014/07/23 23:40:46
Done.
|
+ return true; |
} |
// TODO(mfoltz): Investigate replacing header serialization with base::Pickle, |