| 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 "remoting/protocol/pepper_stream_channel.h" | 5 #include "remoting/protocol/pepper_stream_channel.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "crypto/hmac.h" | 8 #include "crypto/hmac.h" |
| 9 #include "jingle/glue/utils.h" | 9 #include "jingle/glue/utils.h" |
| 10 #include "net/base/cert_status_flags.h" | 10 #include "net/base/cert_status_flags.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 | 28 |
| 29 // Value is choosen to balance the extra latency against the reduced | 29 // Value is choosen to balance the extra latency against the reduced |
| 30 // load due to ACK traffic. | 30 // load due to ACK traffic. |
| 31 const int kTcpAckDelayMilliseconds = 10; | 31 const int kTcpAckDelayMilliseconds = 10; |
| 32 | 32 |
| 33 // Values for the TCP send and receive buffer size. This should be tuned to | 33 // Values for the TCP send and receive buffer size. This should be tuned to |
| 34 // accomodate high latency network but not backlog the decoding pipeline. | 34 // accomodate high latency network but not backlog the decoding pipeline. |
| 35 const int kTcpReceiveBufferSize = 256 * 1024; | 35 const int kTcpReceiveBufferSize = 256 * 1024; |
| 36 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; | 36 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; |
| 37 | 37 |
| 38 // Helper method to create a SSL client socket. | |
| 39 net::SSLClientSocket* CreateSSLClientSocket( | |
| 40 net::StreamSocket* socket, const std::string& der_cert, | |
| 41 net::CertVerifier* cert_verifier) { | |
| 42 net::SSLConfig ssl_config; | |
| 43 | |
| 44 // Certificate provided by the host doesn't need authority. | |
| 45 net::SSLConfig::CertAndStatus cert_and_status; | |
| 46 cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID; | |
| 47 cert_and_status.der_cert = der_cert; | |
| 48 ssl_config.allowed_bad_certs.push_back(cert_and_status); | |
| 49 | |
| 50 // Revocation checking is not needed because we use self-signed | |
| 51 // certs. Disable it so that SSL layer doesn't try to initialize | |
| 52 // OCSP (OCSP works only on IO thread). | |
| 53 ssl_config.rev_checking_enabled = false; | |
| 54 | |
| 55 // SSLClientSocket takes ownership of the |socket|. | |
| 56 net::HostPortPair host_and_port("chromoting", 0); | |
| 57 net::SSLClientSocketContext context; | |
| 58 context.cert_verifier = cert_verifier; | |
| 59 net::SSLClientSocket* ssl_socket = | |
| 60 net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket( | |
| 61 socket, host_and_port, ssl_config, NULL, context); | |
| 62 return ssl_socket; | |
| 63 } | |
| 64 | |
| 65 } // namespace | 38 } // namespace |
| 66 | 39 |
| 67 PepperStreamChannel::PepperStreamChannel( | 40 PepperStreamChannel::PepperStreamChannel( |
| 68 PepperSession* session, | 41 PepperSession* session, |
| 69 const std::string& name, | 42 const std::string& name, |
| 70 const Session::StreamChannelCallback& callback) | 43 const Session::StreamChannelCallback& callback) |
| 71 : session_(session), | 44 : session_(session), |
| 72 name_(name), | 45 name_(name), |
| 73 callback_(callback), | 46 callback_(callback), |
| 74 channel_(NULL), | 47 channel_(NULL), |
| 75 connected_(false), | 48 connected_(false), |
| 76 ssl_client_socket_(NULL), | |
| 77 ALLOW_THIS_IN_INITIALIZER_LIST(p2p_connect_callback_( | 49 ALLOW_THIS_IN_INITIALIZER_LIST(p2p_connect_callback_( |
| 78 this, &PepperStreamChannel::OnP2PConnect)), | 50 this, &PepperStreamChannel::OnP2PConnect)) { |
| 79 ALLOW_THIS_IN_INITIALIZER_LIST(ssl_connect_callback_( | |
| 80 this, &PepperStreamChannel::OnSSLConnect)) { | |
| 81 } | 51 } |
| 82 | 52 |
| 83 PepperStreamChannel::~PepperStreamChannel() { | 53 PepperStreamChannel::~PepperStreamChannel() { |
| 84 session_->OnDeleteChannel(this); | 54 session_->OnDeleteChannel(this); |
| 85 // Verify that the |channel_| is ether destroyed or we own it. | 55 // Verify that the |channel_| is ether destroyed or we own it. |
| 86 DCHECK_EQ(channel_, owned_channel_.get()); | 56 DCHECK_EQ(channel_, owned_channel_.get()); |
| 87 // Channel should be already destroyed if we were connected. | 57 // Channel should be already destroyed if we were connected. |
| 88 DCHECK(!connected_ || channel_ == NULL); | 58 DCHECK(!connected_ || channel_ == NULL); |
| 89 } | 59 } |
| 90 | 60 |
| 91 void PepperStreamChannel::Connect(pp::Instance* pp_instance, | 61 void PepperStreamChannel::Connect(pp::Instance* pp_instance, |
| 92 const TransportConfig& transport_config, | 62 const TransportConfig& transport_config, |
| 93 const std::string& remote_cert) { | 63 ChannelAuthenticator* authenticator) { |
| 94 DCHECK(CalledOnValidThread()); | 64 DCHECK(CalledOnValidThread()); |
| 95 | 65 |
| 96 remote_cert_ = remote_cert; | 66 authenticator_.reset(authenticator); |
| 97 | 67 |
| 98 pp::Transport_Dev* transport = | 68 pp::Transport_Dev* transport = |
| 99 new pp::Transport_Dev(pp_instance, name_.c_str(), | 69 new pp::Transport_Dev(pp_instance, name_.c_str(), |
| 100 PP_TRANSPORTTYPE_STREAM); | 70 PP_TRANSPORTTYPE_STREAM); |
| 101 | 71 |
| 102 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_RECEIVE_WINDOW, | 72 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_RECEIVE_WINDOW, |
| 103 pp::Var(kTcpReceiveBufferSize)) != PP_OK) { | 73 pp::Var(kTcpReceiveBufferSize)) != PP_OK) { |
| 104 LOG(ERROR) << "Failed to set TCP receive window"; | 74 LOG(ERROR) << "Failed to set TCP receive window"; |
| 105 } | 75 } |
| 106 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_SEND_WINDOW, | 76 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_SEND_WINDOW, |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 cricket::Candidate candidate_value; | 160 cricket::Candidate candidate_value; |
| 191 if (!jingle_glue::DeserializeP2PCandidate(candidate, &candidate_value)) { | 161 if (!jingle_glue::DeserializeP2PCandidate(candidate, &candidate_value)) { |
| 192 LOG(ERROR) << "Failed to parse candidate " << candidate; | 162 LOG(ERROR) << "Failed to parse candidate " << candidate; |
| 193 } | 163 } |
| 194 session_->AddLocalCandidate(candidate_value); | 164 session_->AddLocalCandidate(candidate_value); |
| 195 } | 165 } |
| 196 | 166 |
| 197 void PepperStreamChannel::OnP2PConnect(int result) { | 167 void PepperStreamChannel::OnP2PConnect(int result) { |
| 198 DCHECK(CalledOnValidThread()); | 168 DCHECK(CalledOnValidThread()); |
| 199 | 169 |
| 200 if (result != net::OK || !EstablishSSLConnection()) | 170 if (result != net::OK) |
| 201 NotifyConnectFailed(); | 171 NotifyConnectFailed(); |
| 172 |
| 173 authenticator_->SecureAndAuthenticate(owned_channel_.release(), base::Bind( |
| 174 &PepperStreamChannel::OnAuthenticationDone, base::Unretained(this))); |
| 202 } | 175 } |
| 203 | 176 |
| 204 bool PepperStreamChannel::EstablishSSLConnection() { | 177 |
| 178 void PepperStreamChannel::OnAuthenticationDone( |
| 179 net::Error error, net::StreamSocket* socket) { |
| 205 DCHECK(CalledOnValidThread()); | 180 DCHECK(CalledOnValidThread()); |
| 206 | 181 if (error != net::OK) { |
| 207 cert_verifier_.reset(new net::CertVerifier()); | |
| 208 | |
| 209 // Create client SSL socket. | |
| 210 ssl_client_socket_ = CreateSSLClientSocket( | |
| 211 owned_channel_.release(), remote_cert_, cert_verifier_.get()); | |
| 212 socket_.reset(ssl_client_socket_); | |
| 213 | |
| 214 int result = ssl_client_socket_->Connect(&ssl_connect_callback_); | |
| 215 | |
| 216 if (result == net::ERR_IO_PENDING) { | |
| 217 return true; | |
| 218 } else if (result != net::OK) { | |
| 219 LOG(ERROR) << "Failed to establish SSL connection"; | |
| 220 return false; | |
| 221 } | |
| 222 | |
| 223 // Reach here if net::OK is received. | |
| 224 ssl_connect_callback_.Run(net::OK); | |
| 225 return true; | |
| 226 } | |
| 227 | |
| 228 void PepperStreamChannel::OnSSLConnect(int result) { | |
| 229 DCHECK(CalledOnValidThread()); | |
| 230 | |
| 231 if (result != net::OK) { | |
| 232 LOG(ERROR) << "Error during SSL connection: " << result; | |
| 233 NotifyConnectFailed(); | 182 NotifyConnectFailed(); |
| 234 return; | 183 return; |
| 235 } | 184 } |
| 236 | 185 |
| 237 DCHECK(socket_->IsConnected()); | 186 NotifyConnected(socket); |
| 238 AuthenticateChannel(); | |
| 239 } | |
| 240 | |
| 241 void PepperStreamChannel::AuthenticateChannel() { | |
| 242 DCHECK(CalledOnValidThread()); | |
| 243 | |
| 244 authenticator_.reset( | |
| 245 new ClientChannelAuthenticator(session_->shared_secret())); | |
| 246 authenticator_->Authenticate(ssl_client_socket_, base::Bind( | |
| 247 &PepperStreamChannel::OnAuthenticationDone, base::Unretained(this))); | |
| 248 } | |
| 249 | |
| 250 void PepperStreamChannel::OnAuthenticationDone( | |
| 251 ChannelAuthenticator::Result result) { | |
| 252 DCHECK(CalledOnValidThread()); | |
| 253 | |
| 254 switch (result) { | |
| 255 case ChannelAuthenticator::SUCCESS: | |
| 256 NotifyConnected(socket_.release()); | |
| 257 break; | |
| 258 | |
| 259 case ChannelAuthenticator::FAILURE: | |
| 260 NotifyConnectFailed(); | |
| 261 break; | |
| 262 } | |
| 263 } | 187 } |
| 264 | 188 |
| 265 void PepperStreamChannel::NotifyConnected(net::StreamSocket* socket) { | 189 void PepperStreamChannel::NotifyConnected(net::StreamSocket* socket) { |
| 266 DCHECK(!connected_); | 190 DCHECK(!connected_); |
| 267 callback_.Run(socket); | 191 callback_.Run(socket); |
| 268 connected_ = true; | 192 connected_ = true; |
| 269 } | 193 } |
| 270 | 194 |
| 271 void PepperStreamChannel::NotifyConnectFailed() { | 195 void PepperStreamChannel::NotifyConnectFailed() { |
| 272 channel_ = NULL; | 196 channel_ = NULL; |
| 273 owned_channel_.reset(); | 197 owned_channel_.reset(); |
| 274 socket_.reset(); | 198 authenticator_.reset(); |
| 275 | 199 |
| 276 NotifyConnected(NULL); | 200 NotifyConnected(NULL); |
| 277 } | 201 } |
| 278 | 202 |
| 279 } // namespace protocol | 203 } // namespace protocol |
| 280 } // namespace remoting | 204 } // namespace remoting |
| OLD | NEW |