| OLD | NEW | 
 | (Empty) | 
|    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 |  | 
|    3 // found in the LICENSE file. |  | 
|    4  |  | 
|    5 #include "remoting/protocol/pepper_stream_channel.h" |  | 
|    6  |  | 
|    7 #include "base/bind.h" |  | 
|    8 #include "crypto/hmac.h" |  | 
|    9 #include "jingle/glue/utils.h" |  | 
|   10 #include "net/base/cert_status_flags.h" |  | 
|   11 #include "net/base/cert_verifier.h" |  | 
|   12 #include "net/base/host_port_pair.h" |  | 
|   13 #include "net/base/ssl_config_service.h" |  | 
|   14 #include "net/socket/ssl_client_socket.h" |  | 
|   15 #include "net/socket/client_socket_factory.h" |  | 
|   16 #include "ppapi/c/pp_errors.h" |  | 
|   17 #include "ppapi/cpp/dev/transport_dev.h" |  | 
|   18 #include "ppapi/cpp/var.h" |  | 
|   19 #include "remoting/protocol/channel_authenticator.h" |  | 
|   20 #include "remoting/protocol/pepper_session.h" |  | 
|   21 #include "remoting/protocol/transport_config.h" |  | 
|   22 #include "third_party/libjingle/source/talk/p2p/base/candidate.h" |  | 
|   23  |  | 
|   24 namespace remoting { |  | 
|   25 namespace protocol { |  | 
|   26  |  | 
|   27 namespace { |  | 
|   28  |  | 
|   29 // Value is choosen to balance the extra latency against the reduced |  | 
|   30 // load due to ACK traffic. |  | 
|   31 const int kTcpAckDelayMilliseconds = 10; |  | 
|   32  |  | 
|   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. |  | 
|   35 const int kTcpReceiveBufferSize = 256 * 1024; |  | 
|   36 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; |  | 
|   37  |  | 
|   38 }  // namespace |  | 
|   39  |  | 
|   40 PepperStreamChannel::PepperStreamChannel( |  | 
|   41     PepperSession* session, |  | 
|   42     const std::string& name, |  | 
|   43     const Session::StreamChannelCallback& callback) |  | 
|   44     : session_(session), |  | 
|   45       name_(name), |  | 
|   46       callback_(callback), |  | 
|   47       channel_(NULL), |  | 
|   48       connected_(false) { |  | 
|   49 } |  | 
|   50  |  | 
|   51 PepperStreamChannel::~PepperStreamChannel() { |  | 
|   52   session_->OnDeleteChannel(this); |  | 
|   53   // Channel should be already destroyed if we were connected. |  | 
|   54   DCHECK(!connected_ || channel_ == NULL); |  | 
|   55 } |  | 
|   56  |  | 
|   57 void PepperStreamChannel::Connect( |  | 
|   58     pp::Instance* pp_instance, |  | 
|   59     const TransportConfig& transport_config, |  | 
|   60     scoped_ptr<ChannelAuthenticator> authenticator) { |  | 
|   61   DCHECK(CalledOnValidThread()); |  | 
|   62  |  | 
|   63   authenticator_ = authenticator.Pass(); |  | 
|   64  |  | 
|   65   pp::Transport_Dev* transport = |  | 
|   66       new pp::Transport_Dev(pp_instance, name_.c_str(), |  | 
|   67                             PP_TRANSPORTTYPE_STREAM); |  | 
|   68  |  | 
|   69   if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_RECEIVE_WINDOW, |  | 
|   70                              pp::Var(kTcpReceiveBufferSize)) != PP_OK) { |  | 
|   71     LOG(ERROR) << "Failed to set TCP receive window"; |  | 
|   72   } |  | 
|   73   if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_SEND_WINDOW, |  | 
|   74                              pp::Var(kTcpSendBufferSize)) != PP_OK) { |  | 
|   75     LOG(ERROR) << "Failed to set TCP send window"; |  | 
|   76   } |  | 
|   77  |  | 
|   78   if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_NO_DELAY, |  | 
|   79                              pp::Var(true)) != PP_OK) { |  | 
|   80     LOG(ERROR) << "Failed to set TCP_NODELAY"; |  | 
|   81   } |  | 
|   82  |  | 
|   83   if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_ACK_DELAY, |  | 
|   84                              pp::Var(kTcpAckDelayMilliseconds)) != PP_OK) { |  | 
|   85     LOG(ERROR) << "Failed to set TCP ACK delay."; |  | 
|   86   } |  | 
|   87  |  | 
|   88   if (transport_config.nat_traversal) { |  | 
|   89     if (transport->SetProperty( |  | 
|   90             PP_TRANSPORTPROPERTY_STUN_SERVER, |  | 
|   91             pp::Var(transport_config.stun_server)) != PP_OK) { |  | 
|   92       LOG(ERROR) << "Failed to set STUN server."; |  | 
|   93     } |  | 
|   94  |  | 
|   95     if (transport->SetProperty( |  | 
|   96             PP_TRANSPORTPROPERTY_RELAY_SERVER, |  | 
|   97             pp::Var(transport_config.relay_server)) != PP_OK) { |  | 
|   98       LOG(ERROR) << "Failed to set relay server."; |  | 
|   99     } |  | 
|  100  |  | 
|  101     if (transport->SetProperty( |  | 
|  102             PP_TRANSPORTPROPERTY_RELAY_PASSWORD, |  | 
|  103             pp::Var(transport_config.relay_token)) != PP_OK) { |  | 
|  104       LOG(ERROR) << "Failed to set relay token."; |  | 
|  105     } |  | 
|  106  |  | 
|  107     if (transport->SetProperty( |  | 
|  108             PP_TRANSPORTPROPERTY_RELAY_MODE, |  | 
|  109             pp::Var(PP_TRANSPORTRELAYMODE_GOOGLE)) != PP_OK) { |  | 
|  110       LOG(ERROR) << "Failed to set relay mode."; |  | 
|  111     } |  | 
|  112   } |  | 
|  113  |  | 
|  114   if (transport->SetProperty(PP_TRANSPORTPROPERTY_DISABLE_TCP_TRANSPORT, |  | 
|  115                              pp::Var(true)) != PP_OK) { |  | 
|  116     LOG(ERROR) << "Failed to set DISABLE_TCP_TRANSPORT flag."; |  | 
|  117   } |  | 
|  118  |  | 
|  119   channel_ = new PepperTransportSocketAdapter(transport, name_, this); |  | 
|  120   owned_channel_.reset(channel_); |  | 
|  121  |  | 
|  122   int result = channel_->Connect(base::Bind(&PepperStreamChannel::OnP2PConnect, |  | 
|  123                                             base::Unretained(this))); |  | 
|  124   if (result != net::ERR_IO_PENDING) |  | 
|  125     OnP2PConnect(result); |  | 
|  126 } |  | 
|  127  |  | 
|  128 void PepperStreamChannel::AddRemoteCandidate( |  | 
|  129     const cricket::Candidate& candidate) { |  | 
|  130   DCHECK(CalledOnValidThread()); |  | 
|  131   if (channel_) |  | 
|  132     channel_->AddRemoteCandidate(jingle_glue::SerializeP2PCandidate(candidate)); |  | 
|  133 } |  | 
|  134  |  | 
|  135 const std::string& PepperStreamChannel::name() const { |  | 
|  136   DCHECK(CalledOnValidThread()); |  | 
|  137   return name_; |  | 
|  138 } |  | 
|  139  |  | 
|  140 bool PepperStreamChannel::is_connected() const { |  | 
|  141   DCHECK(CalledOnValidThread()); |  | 
|  142   return connected_; |  | 
|  143 } |  | 
|  144  |  | 
|  145 void PepperStreamChannel::OnChannelDeleted() { |  | 
|  146   if (connected_) { |  | 
|  147     channel_ = NULL; |  | 
|  148     // The PepperTransportSocketAdapter is being deleted, so delete |  | 
|  149     // the channel too. |  | 
|  150     delete this; |  | 
|  151   } |  | 
|  152 } |  | 
|  153  |  | 
|  154 void PepperStreamChannel::OnChannelNewLocalCandidate( |  | 
|  155     const std::string& candidate) { |  | 
|  156   DCHECK(CalledOnValidThread()); |  | 
|  157  |  | 
|  158   cricket::Candidate candidate_value; |  | 
|  159   if (!jingle_glue::DeserializeP2PCandidate(candidate, &candidate_value)) { |  | 
|  160     LOG(ERROR) << "Failed to parse candidate " << candidate; |  | 
|  161   } |  | 
|  162   session_->AddLocalCandidate(candidate_value); |  | 
|  163 } |  | 
|  164  |  | 
|  165 void PepperStreamChannel::OnP2PConnect(int result) { |  | 
|  166   DCHECK(CalledOnValidThread()); |  | 
|  167  |  | 
|  168   if (result != net::OK) |  | 
|  169     NotifyConnectFailed(); |  | 
|  170  |  | 
|  171   authenticator_->SecureAndAuthenticate( |  | 
|  172       owned_channel_.PassAs<net::StreamSocket>(), |  | 
|  173       base::Bind(&PepperStreamChannel::OnAuthenticationDone, |  | 
|  174                  base::Unretained(this))); |  | 
|  175 } |  | 
|  176  |  | 
|  177  |  | 
|  178 void PepperStreamChannel::OnAuthenticationDone( |  | 
|  179     net::Error error, scoped_ptr<net::StreamSocket> socket) { |  | 
|  180   DCHECK(CalledOnValidThread()); |  | 
|  181   if (error != net::OK) { |  | 
|  182     NotifyConnectFailed(); |  | 
|  183     return; |  | 
|  184   } |  | 
|  185  |  | 
|  186   NotifyConnected(socket.Pass()); |  | 
|  187 } |  | 
|  188  |  | 
|  189 void PepperStreamChannel::NotifyConnected( |  | 
|  190     scoped_ptr<net::StreamSocket> socket) { |  | 
|  191   DCHECK(!connected_); |  | 
|  192   callback_.Run(socket.Pass()); |  | 
|  193   connected_ = true; |  | 
|  194 } |  | 
|  195  |  | 
|  196 void PepperStreamChannel::NotifyConnectFailed() { |  | 
|  197   channel_ = NULL; |  | 
|  198   owned_channel_.reset(); |  | 
|  199   authenticator_.reset(); |  | 
|  200  |  | 
|  201   NotifyConnected(scoped_ptr<net::StreamSocket>(NULL)); |  | 
|  202 } |  | 
|  203  |  | 
|  204 }  // namespace protocol |  | 
|  205 }  // namespace remoting |  | 
| OLD | NEW |