Chromium Code Reviews| 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 "chrome/browser/extensions/api/cast_channel/cast_socket.h" | 5 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 #include "net/cert/x509_certificate.h" | 22 #include "net/cert/x509_certificate.h" |
| 23 #include "net/http/transport_security_state.h" | 23 #include "net/http/transport_security_state.h" |
| 24 #include "net/socket/client_socket_factory.h" | 24 #include "net/socket/client_socket_factory.h" |
| 25 #include "net/socket/client_socket_handle.h" | 25 #include "net/socket/client_socket_handle.h" |
| 26 #include "net/socket/ssl_client_socket.h" | 26 #include "net/socket/ssl_client_socket.h" |
| 27 #include "net/socket/stream_socket.h" | 27 #include "net/socket/stream_socket.h" |
| 28 #include "net/socket/tcp_client_socket.h" | 28 #include "net/socket/tcp_client_socket.h" |
| 29 #include "net/ssl/ssl_config_service.h" | 29 #include "net/ssl/ssl_config_service.h" |
| 30 #include "net/ssl/ssl_info.h" | 30 #include "net/ssl/ssl_info.h" |
| 31 | 31 |
| 32 // Assumes member name url_. Anyway compile error will occur if that changes. | |
|
mark a. foltz
2014/02/12 23:05:51
Please #undef the macro after the last usage (even
Munjal (Google)
2014/02/12 23:25:28
Done.
| |
| 33 #define VLOG_WITH_URL(level) VLOG(level) << "[" + url_.spec() + "] " | |
| 34 | |
| 32 namespace { | 35 namespace { |
| 33 | 36 |
| 34 // Allowed schemes for Cast device URLs. | 37 // Allowed schemes for Cast device URLs. |
| 35 const char kCastInsecureScheme[] = "cast"; | 38 const char kCastInsecureScheme[] = "cast"; |
| 36 const char kCastSecureScheme[] = "casts"; | 39 const char kCastSecureScheme[] = "casts"; |
| 37 | 40 |
| 38 // The default keepalive delay. On Linux, keepalives probes will be sent after | 41 // The default keepalive delay. On Linux, keepalives probes will be sent after |
| 39 // the socket is idle for this length of time, and the socket will be closed | 42 // the socket is idle for this length of time, and the socket will be closed |
| 40 // after 9 failed probes. So the total idle time before close is 10 * | 43 // after 9 failed probes. So the total idle time before close is 10 * |
| 41 // kTcpKeepAliveDelaySecs. | 44 // kTcpKeepAliveDelaySecs. |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 67 CastSocket::CastSocket(const std::string& owner_extension_id, | 70 CastSocket::CastSocket(const std::string& owner_extension_id, |
| 68 const GURL& url, | 71 const GURL& url, |
| 69 CastSocket::Delegate* delegate, | 72 CastSocket::Delegate* delegate, |
| 70 net::NetLog* net_log) : | 73 net::NetLog* net_log) : |
| 71 ApiResource(owner_extension_id), | 74 ApiResource(owner_extension_id), |
| 72 channel_id_(0), | 75 channel_id_(0), |
| 73 url_(url), | 76 url_(url), |
| 74 delegate_(delegate), | 77 delegate_(delegate), |
| 75 auth_required_(false), | 78 auth_required_(false), |
| 76 current_message_size_(0), | 79 current_message_size_(0), |
| 80 current_message_(new CastMessage()), | |
| 77 net_log_(net_log), | 81 net_log_(net_log), |
| 78 connect_state_(CONN_STATE_NONE), | 82 connect_state_(CONN_STATE_NONE), |
| 79 write_state_(WRITE_STATE_NONE), | 83 write_state_(WRITE_STATE_NONE), |
| 80 read_state_(READ_STATE_NONE), | 84 read_state_(READ_STATE_NONE), |
| 81 error_state_(CHANNEL_ERROR_NONE), | 85 error_state_(CHANNEL_ERROR_NONE), |
| 82 ready_state_(READY_STATE_NONE) { | 86 ready_state_(READY_STATE_NONE) { |
| 83 DCHECK(net_log_); | 87 DCHECK(net_log_); |
| 84 net_log_source_.type = net::NetLog::SOURCE_SOCKET; | 88 net_log_source_.type = net::NetLog::SOURCE_SOCKET; |
| 85 net_log_source_.id = net_log_->NextID(); | 89 net_log_source_.id = net_log_->NextID(); |
| 86 | 90 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 | 142 |
| 139 bool CastSocket::ExtractPeerCert(std::string* cert) { | 143 bool CastSocket::ExtractPeerCert(std::string* cert) { |
| 140 DCHECK(cert); | 144 DCHECK(cert); |
| 141 DCHECK(peer_cert_.empty()); | 145 DCHECK(peer_cert_.empty()); |
| 142 net::SSLInfo ssl_info; | 146 net::SSLInfo ssl_info; |
| 143 if (!socket_->GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) | 147 if (!socket_->GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) |
| 144 return false; | 148 return false; |
| 145 bool result = net::X509Certificate::GetDEREncoded( | 149 bool result = net::X509Certificate::GetDEREncoded( |
| 146 ssl_info.cert->os_cert_handle(), cert); | 150 ssl_info.cert->os_cert_handle(), cert); |
| 147 if (result) | 151 if (result) |
| 148 VLOG(1) << "[URL: " << url_.spec() | 152 VLOG_WITH_URL(1) << "Successfully extracted peer certificate: " << *cert; |
| 149 << "] Successfully extracted peer certificate: " << *cert; | |
| 150 return result; | 153 return result; |
| 151 } | 154 } |
| 152 | 155 |
| 153 bool CastSocket::VerifyChallengeReply() { | 156 bool CastSocket::VerifyChallengeReply() { |
| 154 return AuthenticateChallengeReply(*challenge_reply_.get(), peer_cert_); | 157 return AuthenticateChallengeReply(*challenge_reply_.get(), peer_cert_); |
| 155 } | 158 } |
| 156 | 159 |
| 157 void CastSocket::Connect(const net::CompletionCallback& callback) { | 160 void CastSocket::Connect(const net::CompletionCallback& callback) { |
| 158 DCHECK(CalledOnValidThread()); | 161 DCHECK(CalledOnValidThread()); |
| 159 VLOG(1) << "Connect readyState = " << ready_state_; | 162 VLOG_WITH_URL(1) << "Connect readyState = " << ready_state_; |
| 160 if (ready_state_ != READY_STATE_NONE) { | 163 if (ready_state_ != READY_STATE_NONE) { |
| 161 callback.Run(net::ERR_CONNECTION_FAILED); | 164 callback.Run(net::ERR_CONNECTION_FAILED); |
| 162 return; | 165 return; |
| 163 } | 166 } |
| 164 if (!ParseChannelUrl(url_)) { | 167 if (!ParseChannelUrl(url_)) { |
| 165 callback.Run(net::ERR_CONNECTION_FAILED); | 168 callback.Run(net::ERR_CONNECTION_FAILED); |
| 166 return; | 169 return; |
| 167 } | 170 } |
| 168 | 171 |
| 169 ready_state_ = READY_STATE_CONNECTING; | 172 ready_state_ = READY_STATE_CONNECTING; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 // Get out of the loop either when: | 228 // Get out of the loop either when: |
| 226 // a. A network operation is pending, OR | 229 // a. A network operation is pending, OR |
| 227 // b. The Do* method called did not change state | 230 // b. The Do* method called did not change state |
| 228 | 231 |
| 229 // Connect loop is finished: if there is no pending IO invoke the callback. | 232 // Connect loop is finished: if there is no pending IO invoke the callback. |
| 230 if (rv != net::ERR_IO_PENDING) | 233 if (rv != net::ERR_IO_PENDING) |
| 231 DoConnectCallback(rv); | 234 DoConnectCallback(rv); |
| 232 } | 235 } |
| 233 | 236 |
| 234 int CastSocket::DoTcpConnect() { | 237 int CastSocket::DoTcpConnect() { |
| 235 VLOG(1) << "DoTcpConnect"; | 238 VLOG_WITH_URL(1) << "DoTcpConnect"; |
| 236 connect_state_ = CONN_STATE_TCP_CONNECT_COMPLETE; | 239 connect_state_ = CONN_STATE_TCP_CONNECT_COMPLETE; |
| 237 tcp_socket_ = CreateTcpSocket(); | 240 tcp_socket_ = CreateTcpSocket(); |
| 238 return tcp_socket_->Connect( | 241 return tcp_socket_->Connect( |
| 239 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())); | 242 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())); |
| 240 } | 243 } |
| 241 | 244 |
| 242 int CastSocket::DoTcpConnectComplete(int result) { | 245 int CastSocket::DoTcpConnectComplete(int result) { |
| 243 VLOG(1) << "DoTcpConnectComplete: " << result; | 246 VLOG_WITH_URL(1) << "DoTcpConnectComplete: " << result; |
| 244 if (result == net::OK) { | 247 if (result == net::OK) { |
| 245 // Enable TCP protocol-level keep-alive. | 248 // Enable TCP protocol-level keep-alive. |
| 246 bool result = tcp_socket_->SetKeepAlive(true, kTcpKeepAliveDelaySecs); | 249 bool result = tcp_socket_->SetKeepAlive(true, kTcpKeepAliveDelaySecs); |
| 247 LOG_IF(WARNING, !result) << "Failed to SetKeepAlive."; | 250 LOG_IF(WARNING, !result) << "Failed to SetKeepAlive."; |
| 248 connect_state_ = CONN_STATE_SSL_CONNECT; | 251 connect_state_ = CONN_STATE_SSL_CONNECT; |
| 249 } | 252 } |
| 250 return result; | 253 return result; |
| 251 } | 254 } |
| 252 | 255 |
| 253 int CastSocket::DoSslConnect() { | 256 int CastSocket::DoSslConnect() { |
| 254 VLOG(1) << "DoSslConnect"; | 257 VLOG_WITH_URL(1) << "DoSslConnect"; |
| 255 connect_state_ = CONN_STATE_SSL_CONNECT_COMPLETE; | 258 connect_state_ = CONN_STATE_SSL_CONNECT_COMPLETE; |
| 256 socket_ = CreateSslSocket(tcp_socket_.PassAs<net::StreamSocket>()); | 259 socket_ = CreateSslSocket(tcp_socket_.PassAs<net::StreamSocket>()); |
| 257 return socket_->Connect( | 260 return socket_->Connect( |
| 258 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())); | 261 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())); |
| 259 } | 262 } |
| 260 | 263 |
| 261 int CastSocket::DoSslConnectComplete(int result) { | 264 int CastSocket::DoSslConnectComplete(int result) { |
| 262 VLOG(1) << "DoSslConnectComplete: " << result; | 265 VLOG_WITH_URL(1) << "DoSslConnectComplete: " << result; |
| 263 if (result == net::ERR_CERT_AUTHORITY_INVALID && | 266 if (result == net::ERR_CERT_AUTHORITY_INVALID && |
| 264 peer_cert_.empty() && | 267 peer_cert_.empty() && |
| 265 ExtractPeerCert(&peer_cert_)) { | 268 ExtractPeerCert(&peer_cert_)) { |
| 266 connect_state_ = CONN_STATE_TCP_CONNECT; | 269 connect_state_ = CONN_STATE_TCP_CONNECT; |
| 267 } else if (result == net::OK && auth_required_) { | 270 } else if (result == net::OK && auth_required_) { |
| 268 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND; | 271 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND; |
| 269 } | 272 } |
| 270 return result; | 273 return result; |
| 271 } | 274 } |
| 272 | 275 |
| 273 int CastSocket::DoAuthChallengeSend() { | 276 int CastSocket::DoAuthChallengeSend() { |
| 274 VLOG(1) << "DoAuthChallengeSend"; | 277 VLOG_WITH_URL(1) << "DoAuthChallengeSend"; |
| 275 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE; | 278 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE; |
| 276 CastMessage challenge_message; | 279 CastMessage challenge_message; |
| 277 CreateAuthChallengeMessage(&challenge_message); | 280 CreateAuthChallengeMessage(&challenge_message); |
| 278 VLOG(1) << "Sending challenge: " << CastMessageToString(challenge_message); | 281 VLOG_WITH_URL(1) << "Sending challenge: " |
| 282 << CastMessageToString(challenge_message); | |
| 279 // Post a task to send auth challenge so that DoWriteLoop is not nested inside | 283 // Post a task to send auth challenge so that DoWriteLoop is not nested inside |
| 280 // DoConnectLoop. This is not strictly necessary but keeps the write loop | 284 // DoConnectLoop. This is not strictly necessary but keeps the write loop |
| 281 // code decoupled from connect loop code. | 285 // code decoupled from connect loop code. |
| 282 base::MessageLoop::current()->PostTask( | 286 base::MessageLoop::current()->PostTask( |
| 283 FROM_HERE, | 287 FROM_HERE, |
| 284 base::Bind(&CastSocket::SendCastMessageInternal, AsWeakPtr(), | 288 base::Bind(&CastSocket::SendCastMessageInternal, AsWeakPtr(), |
| 285 challenge_message, | 289 challenge_message, |
| 286 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr()))); | 290 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr()))); |
| 287 // Always return IO_PENDING since the result is always asynchronous. | 291 // Always return IO_PENDING since the result is always asynchronous. |
| 288 return net::ERR_IO_PENDING; | 292 return net::ERR_IO_PENDING; |
| 289 } | 293 } |
| 290 | 294 |
| 291 int CastSocket::DoAuthChallengeSendComplete(int result) { | 295 int CastSocket::DoAuthChallengeSendComplete(int result) { |
| 292 VLOG(1) << "DoAuthChallengeSendComplete: " << result; | 296 VLOG_WITH_URL(1) << "DoAuthChallengeSendComplete: " << result; |
| 293 if (result < 0) | 297 if (result < 0) |
| 294 return result; | 298 return result; |
| 295 connect_state_ = CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE; | 299 connect_state_ = CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE; |
| 296 // Post a task to start read loop so that DoReadLoop is not nested inside | 300 // Post a task to start read loop so that DoReadLoop is not nested inside |
| 297 // DoConnectLoop. This is not strictly necessary but keeps the read loop | 301 // DoConnectLoop. This is not strictly necessary but keeps the read loop |
| 298 // code decoupled from connect loop code. | 302 // code decoupled from connect loop code. |
| 299 PostTaskToStartReadLoop(); | 303 PostTaskToStartReadLoop(); |
| 300 // Always return IO_PENDING since the result is always asynchronous. | 304 // Always return IO_PENDING since the result is always asynchronous. |
| 301 return net::ERR_IO_PENDING; | 305 return net::ERR_IO_PENDING; |
| 302 } | 306 } |
| 303 | 307 |
| 304 int CastSocket::DoAuthChallengeReplyComplete(int result) { | 308 int CastSocket::DoAuthChallengeReplyComplete(int result) { |
| 305 VLOG(1) << "DoAuthChallengeReplyComplete: " << result; | 309 VLOG_WITH_URL(1) << "DoAuthChallengeReplyComplete: " << result; |
| 306 if (result < 0) | 310 if (result < 0) |
| 307 return result; | 311 return result; |
| 308 if (!VerifyChallengeReply()) | 312 if (!VerifyChallengeReply()) |
| 309 return net::ERR_FAILED; | 313 return net::ERR_FAILED; |
| 310 VLOG(1) << "Auth challenge verification succeeded"; | 314 VLOG_WITH_URL(1) << "Auth challenge verification succeeded"; |
| 311 return net::OK; | 315 return net::OK; |
| 312 } | 316 } |
| 313 | 317 |
| 314 void CastSocket::DoConnectCallback(int result) { | 318 void CastSocket::DoConnectCallback(int result) { |
| 315 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED; | 319 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED; |
| 316 error_state_ = (result == net::OK) ? | 320 error_state_ = (result == net::OK) ? |
| 317 CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR; | 321 CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR; |
| 318 if (result == net::OK) // Start the read loop | 322 if (result == net::OK) // Start the read loop |
| 319 PostTaskToStartReadLoop(); | 323 PostTaskToStartReadLoop(); |
| 320 base::ResetAndReturn(&connect_callback_).Run(result); | 324 base::ResetAndReturn(&connect_callback_).Run(result); |
| 321 } | 325 } |
| 322 | 326 |
| 323 void CastSocket::Close(const net::CompletionCallback& callback) { | 327 void CastSocket::Close(const net::CompletionCallback& callback) { |
| 324 DCHECK(CalledOnValidThread()); | 328 DCHECK(CalledOnValidThread()); |
| 325 VLOG(1) << "Close ReadyState = " << ready_state_; | 329 VLOG_WITH_URL(1) << "Close ReadyState = " << ready_state_; |
| 326 tcp_socket_.reset(); | 330 tcp_socket_.reset(); |
| 327 socket_.reset(); | 331 socket_.reset(); |
| 328 cert_verifier_.reset(); | 332 cert_verifier_.reset(); |
| 329 transport_security_state_.reset(); | 333 transport_security_state_.reset(); |
| 330 ready_state_ = READY_STATE_CLOSED; | 334 ready_state_ = READY_STATE_CLOSED; |
| 331 callback.Run(net::OK); | 335 callback.Run(net::OK); |
| 332 // |callback| can delete |this| | 336 // |callback| can delete |this| |
| 333 } | 337 } |
| 334 | 338 |
| 335 void CastSocket::SendMessage(const MessageInfo& message, | 339 void CastSocket::SendMessage(const MessageInfo& message, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 359 | 363 |
| 360 write_queue_.push(write_request); | 364 write_queue_.push(write_request); |
| 361 if (write_state_ == WRITE_STATE_NONE) { | 365 if (write_state_ == WRITE_STATE_NONE) { |
| 362 write_state_ = WRITE_STATE_WRITE; | 366 write_state_ = WRITE_STATE_WRITE; |
| 363 DoWriteLoop(net::OK); | 367 DoWriteLoop(net::OK); |
| 364 } | 368 } |
| 365 } | 369 } |
| 366 | 370 |
| 367 void CastSocket::DoWriteLoop(int result) { | 371 void CastSocket::DoWriteLoop(int result) { |
| 368 DCHECK(CalledOnValidThread()); | 372 DCHECK(CalledOnValidThread()); |
| 369 VLOG(1) << "WriteData q = " << write_queue_.size(); | 373 VLOG_WITH_URL(1) << "DoWriteLoop queue size: " << write_queue_.size(); |
| 370 | 374 |
| 371 if (write_queue_.empty()) { | 375 if (write_queue_.empty()) { |
| 372 write_state_ = WRITE_STATE_NONE; | 376 write_state_ = WRITE_STATE_NONE; |
| 373 return; | 377 return; |
| 374 } | 378 } |
| 375 | 379 |
| 376 // Network operations can either finish synchronously or asynchronously. | 380 // Network operations can either finish synchronously or asynchronously. |
| 377 // This method executes the state machine transitions in a loop so that | 381 // This method executes the state machine transitions in a loop so that |
| 378 // write state transitions happen even when network operations finish | 382 // write state transitions happen even when network operations finish |
| 379 // synchronously. | 383 // synchronously. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 409 | 413 |
| 410 // Write loop is done - if the result is ERR_FAILED then close with error. | 414 // Write loop is done - if the result is ERR_FAILED then close with error. |
| 411 if (rv == net::ERR_FAILED) | 415 if (rv == net::ERR_FAILED) |
| 412 CloseWithError(error_state_); | 416 CloseWithError(error_state_); |
| 413 } | 417 } |
| 414 | 418 |
| 415 int CastSocket::DoWrite() { | 419 int CastSocket::DoWrite() { |
| 416 DCHECK(!write_queue_.empty()); | 420 DCHECK(!write_queue_.empty()); |
| 417 WriteRequest& request = write_queue_.front(); | 421 WriteRequest& request = write_queue_.front(); |
| 418 | 422 |
| 419 VLOG(1) << "WriteData byte_count = " << request.io_buffer->size() | 423 VLOG_WITH_URL(2) << "WriteData byte_count = " << request.io_buffer->size() |
| 420 << " bytes_written " << request.io_buffer->BytesConsumed(); | 424 << " bytes_written " << request.io_buffer->BytesConsumed(); |
| 421 | 425 |
| 422 write_state_ = WRITE_STATE_WRITE_COMPLETE; | 426 write_state_ = WRITE_STATE_WRITE_COMPLETE; |
| 423 | 427 |
| 424 return socket_->Write( | 428 return socket_->Write( |
| 425 request.io_buffer.get(), | 429 request.io_buffer.get(), |
| 426 request.io_buffer->BytesRemaining(), | 430 request.io_buffer->BytesRemaining(), |
| 427 base::Bind(&CastSocket::DoWriteLoop, AsWeakPtr())); | 431 base::Bind(&CastSocket::DoWriteLoop, AsWeakPtr())); |
| 428 } | 432 } |
| 429 | 433 |
| 430 int CastSocket::DoWriteComplete(int result) { | 434 int CastSocket::DoWriteComplete(int result) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 557 DCHECK_GT(num_bytes_to_read, 0U); | 561 DCHECK_GT(num_bytes_to_read, 0U); |
| 558 | 562 |
| 559 // Read up to num_bytes_to_read into |current_read_buffer_|. | 563 // Read up to num_bytes_to_read into |current_read_buffer_|. |
| 560 return socket_->Read( | 564 return socket_->Read( |
| 561 current_read_buffer_.get(), | 565 current_read_buffer_.get(), |
| 562 num_bytes_to_read, | 566 num_bytes_to_read, |
| 563 base::Bind(&CastSocket::DoReadLoop, AsWeakPtr())); | 567 base::Bind(&CastSocket::DoReadLoop, AsWeakPtr())); |
| 564 } | 568 } |
| 565 | 569 |
| 566 int CastSocket::DoReadComplete(int result) { | 570 int CastSocket::DoReadComplete(int result) { |
| 567 VLOG(1) << "DoReadDataComplete result = " << result | 571 VLOG_WITH_URL(2) << "DoReadComplete result = " << result |
| 568 << " header offset = " << header_read_buffer_->offset() | 572 << " header offset = " << header_read_buffer_->offset() |
| 569 << " body offset = " << body_read_buffer_->offset(); | 573 << " body offset = " << body_read_buffer_->offset(); |
| 570 if (result <= 0) { // 0 means EOF: the peer closed the socket | 574 if (result <= 0) { // 0 means EOF: the peer closed the socket |
| 575 VLOG_WITH_URL(1) << "Read error, peer closed the socket"; | |
| 571 error_state_ = CHANNEL_ERROR_SOCKET_ERROR; | 576 error_state_ = CHANNEL_ERROR_SOCKET_ERROR; |
| 572 read_state_ = READ_STATE_ERROR; | 577 read_state_ = READ_STATE_ERROR; |
| 573 return result == 0 ? net::ERR_FAILED : result; | 578 return result == 0 ? net::ERR_FAILED : result; |
| 574 } | 579 } |
| 575 | 580 |
| 576 // Some data was read. Move the offset in the current buffer forward. | 581 // Some data was read. Move the offset in the current buffer forward. |
| 577 DCHECK_LE(current_read_buffer_->offset() + result, | 582 DCHECK_LE(current_read_buffer_->offset() + result, |
| 578 current_read_buffer_->capacity()); | 583 current_read_buffer_->capacity()); |
| 579 current_read_buffer_->set_offset(current_read_buffer_->offset() + result); | 584 current_read_buffer_->set_offset(current_read_buffer_->offset() + result); |
| 580 read_state_ = READ_STATE_READ; | 585 read_state_ = READ_STATE_READ; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 596 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE; | 601 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE; |
| 597 read_state_ = READ_STATE_ERROR; | 602 read_state_ = READ_STATE_ERROR; |
| 598 } | 603 } |
| 599 } | 604 } |
| 600 | 605 |
| 601 return net::OK; | 606 return net::OK; |
| 602 } | 607 } |
| 603 | 608 |
| 604 int CastSocket::DoReadCallback() { | 609 int CastSocket::DoReadCallback() { |
| 605 read_state_ = READ_STATE_READ; | 610 read_state_ = READ_STATE_READ; |
| 606 if (IsAuthMessage(current_message_)) { | 611 const CastMessage& message = *(current_message_.get()); |
| 612 if (IsAuthMessage(message)) { | |
| 607 // An auth message is received, check that connect flow is running. | 613 // An auth message is received, check that connect flow is running. |
| 608 if (ready_state_ == READY_STATE_CONNECTING) { | 614 if (ready_state_ == READY_STATE_CONNECTING) { |
| 609 challenge_reply_.reset(new CastMessage(current_message_)); | 615 challenge_reply_.reset(new CastMessage(message)); |
| 610 PostTaskToStartConnectLoop(net::OK); | 616 PostTaskToStartConnectLoop(net::OK); |
| 611 } else { | 617 } else { |
| 612 read_state_ = READ_STATE_ERROR; | 618 read_state_ = READ_STATE_ERROR; |
| 613 } | 619 } |
| 614 } else if (delegate_) { | 620 } else if (delegate_) { |
| 615 MessageInfo message; | 621 MessageInfo message_info; |
| 616 if (CastMessageToMessageInfo(current_message_, &message)) | 622 if (CastMessageToMessageInfo(message, &message_info)) |
| 617 delegate_->OnMessage(this, message); | 623 delegate_->OnMessage(this, message_info); |
| 618 else | 624 else |
| 619 read_state_ = READ_STATE_ERROR; | 625 read_state_ = READ_STATE_ERROR; |
| 620 } | 626 } |
| 621 current_message_.Clear(); | 627 current_message_->Clear(); |
| 622 return net::OK; | 628 return net::OK; |
| 623 } | 629 } |
| 624 | 630 |
| 625 int CastSocket::DoReadError(int result) { | 631 int CastSocket::DoReadError(int result) { |
| 626 DCHECK_LE(result, 0); | 632 DCHECK_LE(result, 0); |
| 627 // If inside connection flow, then get back to connect loop. | 633 // If inside connection flow, then get back to connect loop. |
| 628 if (ready_state_ == READY_STATE_CONNECTING) { | 634 if (ready_state_ == READY_STATE_CONNECTING) { |
| 629 PostTaskToStartConnectLoop(result); | 635 PostTaskToStartConnectLoop(result); |
| 630 // does not try to report error also. | 636 // does not try to report error also. |
| 631 return net::OK; | 637 return net::OK; |
| 632 } | 638 } |
| 633 return net::ERR_FAILED; | 639 return net::ERR_FAILED; |
| 634 } | 640 } |
| 635 | 641 |
| 636 bool CastSocket::ProcessHeader() { | 642 bool CastSocket::ProcessHeader() { |
| 637 DCHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()), | 643 DCHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()), |
| 638 kMessageHeaderSize); | 644 kMessageHeaderSize); |
| 639 MessageHeader header; | 645 MessageHeader header; |
| 640 MessageHeader::ReadFromIOBuffer(header_read_buffer_.get(), &header); | 646 MessageHeader::ReadFromIOBuffer(header_read_buffer_.get(), &header); |
| 641 if (header.message_size > kMaxMessageSize) | 647 if (header.message_size > kMaxMessageSize) |
| 642 return false; | 648 return false; |
| 643 | 649 |
| 644 VLOG(1) << "Parsed header { message_size: " << header.message_size << " }"; | 650 VLOG_WITH_URL(2) << "Parsed header { message_size: " |
| 651 << header.message_size << " }"; | |
| 645 current_message_size_ = header.message_size; | 652 current_message_size_ = header.message_size; |
| 646 return true; | 653 return true; |
| 647 } | 654 } |
| 648 | 655 |
| 649 bool CastSocket::ProcessBody() { | 656 bool CastSocket::ProcessBody() { |
| 650 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), | 657 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), |
| 651 current_message_size_); | 658 current_message_size_); |
| 652 if (!current_message_.ParseFromArray( | 659 if (!current_message_->ParseFromArray( |
| 653 body_read_buffer_->StartOfBuffer(), current_message_size_)) { | 660 body_read_buffer_->StartOfBuffer(), current_message_size_)) { |
| 654 return false; | 661 return false; |
| 655 } | 662 } |
| 656 current_message_size_ = 0; | 663 current_message_size_ = 0; |
| 657 header_read_buffer_->set_offset(0); | 664 header_read_buffer_->set_offset(0); |
| 658 body_read_buffer_->set_offset(0); | 665 body_read_buffer_->set_offset(0); |
| 659 current_read_buffer_ = header_read_buffer_; | 666 current_read_buffer_ = header_read_buffer_; |
| 660 return true; | 667 return true; |
| 661 } | 668 } |
| 662 | 669 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 679 void CastSocket::CloseWithError(ChannelError error) { | 686 void CastSocket::CloseWithError(ChannelError error) { |
| 680 DCHECK(CalledOnValidThread()); | 687 DCHECK(CalledOnValidThread()); |
| 681 socket_.reset(NULL); | 688 socket_.reset(NULL); |
| 682 ready_state_ = READY_STATE_CLOSED; | 689 ready_state_ = READY_STATE_CLOSED; |
| 683 error_state_ = error; | 690 error_state_ = error; |
| 684 if (delegate_) | 691 if (delegate_) |
| 685 delegate_->OnError(this, error); | 692 delegate_->OnError(this, error); |
| 686 } | 693 } |
| 687 | 694 |
| 688 bool CastSocket::ParseChannelUrl(const GURL& url) { | 695 bool CastSocket::ParseChannelUrl(const GURL& url) { |
| 689 VLOG(1) << "url = " + url.spec(); | 696 VLOG_WITH_URL(2) << "ParseChannelUrl"; |
| 690 if (url.SchemeIs(kCastInsecureScheme)) { | 697 if (url.SchemeIs(kCastInsecureScheme)) { |
| 691 auth_required_ = false; | 698 auth_required_ = false; |
| 692 } else if (url.SchemeIs(kCastSecureScheme)) { | 699 } else if (url.SchemeIs(kCastSecureScheme)) { |
| 693 auth_required_ = true; | 700 auth_required_ = true; |
| 694 } else { | 701 } else { |
| 695 return false; | 702 return false; |
| 696 } | 703 } |
| 697 // TODO(mfoltz): Manual parsing, yech. Register cast[s] as standard schemes? | 704 // TODO(mfoltz): Manual parsing, yech. Register cast[s] as standard schemes? |
| 698 // TODO(mfoltz): Test for IPv6 addresses. Brackets or no brackets? | 705 // TODO(mfoltz): Test for IPv6 addresses. Brackets or no brackets? |
| 699 // TODO(mfoltz): Maybe enforce restriction to IPv4 private and IPv6 link-local | 706 // TODO(mfoltz): Maybe enforce restriction to IPv4 private and IPv6 |
| 700 // networks | 707 // link-local networks |
| 701 const std::string& path = url.path(); | 708 const std::string& path = url.path(); |
| 702 // Shortest possible: //A:B | 709 // Shortest possible: //A:B |
| 703 if (path.size() < 5) { | 710 if (path.size() < 5) { |
| 704 return false; | 711 return false; |
| 705 } | 712 } |
| 706 if (path.find("//") != 0) { | 713 if (path.find("//") != 0) { |
| 707 return false; | 714 return false; |
| 708 } | 715 } |
| 709 size_t colon = path.find_last_of(':'); | 716 size_t colon = path.find_last_of(':'); |
| 710 if (colon == std::string::npos || colon < 3 || colon > path.size() - 2) { | 717 if (colon == std::string::npos || colon < 3 || colon > path.size() - 2) { |
| 711 return false; | 718 return false; |
| 712 } | 719 } |
| 713 const std::string& ip_address_str = path.substr(2, colon - 2); | 720 const std::string& ip_address_str = path.substr(2, colon - 2); |
| 714 const std::string& port_str = path.substr(colon + 1); | 721 const std::string& port_str = path.substr(colon + 1); |
| 715 VLOG(1) << "addr " << ip_address_str << " port " << port_str; | 722 VLOG_WITH_URL(2) << "IP: " << ip_address_str << " Port: " << port_str; |
| 716 int port; | 723 int port; |
| 717 if (!base::StringToInt(port_str, &port)) | 724 if (!base::StringToInt(port_str, &port)) |
| 718 return false; | 725 return false; |
| 719 net::IPAddressNumber ip_address; | 726 net::IPAddressNumber ip_address; |
| 720 if (!net::ParseIPLiteralToNumber(ip_address_str, &ip_address)) | 727 if (!net::ParseIPLiteralToNumber(ip_address_str, &ip_address)) |
| 721 return false; | 728 return false; |
| 722 ip_endpoint_ = net::IPEndPoint(ip_address, port); | 729 ip_endpoint_ = net::IPEndPoint(ip_address, port); |
| 723 return true; | 730 return true; |
| 724 }; | 731 }; |
| 725 | 732 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 772 io_buffer = new net::DrainableIOBuffer(new net::StringIOBuffer(message_data), | 779 io_buffer = new net::DrainableIOBuffer(new net::StringIOBuffer(message_data), |
| 773 message_data.size()); | 780 message_data.size()); |
| 774 return true; | 781 return true; |
| 775 } | 782 } |
| 776 | 783 |
| 777 CastSocket::WriteRequest::~WriteRequest() { } | 784 CastSocket::WriteRequest::~WriteRequest() { } |
| 778 | 785 |
| 779 } // namespace cast_channel | 786 } // namespace cast_channel |
| 780 } // namespace api | 787 } // namespace api |
| 781 } // namespace extensions | 788 } // namespace extensions |
| OLD | NEW |