Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: remoting/protocol/pepper_stream_channel.cc

Issue 7778022: Chromoting protocol implementation based on P2P Transport API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 const char kTcpProtocol[] = "tcp";
Wez 2011/09/09 23:39:12 nit: This name makes it unclear whether it means t
Sergey Ulanov 2011/09/12 19:50:50 Just removed this constant, and replaced it with "
30
31 // Value is choosen to balance the extra latency against the reduced
32 // load due to ACK traffic.
33 const int kTcpAckDelayMilliseconds = 10;
34
35 // Values for the TCP send and receive buffer size. This should be tuned to
36 // accomodate high latency network but not backlog the decoding pipeline.
37 const int kTcpReceiveBufferSize = 256 * 1024;
38 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024;
39
40 // Helper method to create a SSL client socket.
41 net::SSLClientSocket* CreateSSLClientSocket(
42 net::StreamSocket* socket, const std::string& der_cert,
43 net::CertVerifier* cert_verifier) {
44 net::SSLConfig ssl_config;
45
46 // Certificate provided by the host doesn't need authority.
47 net::SSLConfig::CertAndStatus cert_and_status;
48 cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
49 cert_and_status.der_cert = der_cert;
50 ssl_config.allowed_bad_certs.push_back(cert_and_status);
51
52 // Revocation checking is not needed because we use self-signed
53 // certs. Disable it so that SSL layer doesn't try to initialize
54 // OCSP (OCSP works only on IO thread).
55 ssl_config.rev_checking_enabled = false;
56
57 // SSLClientSocket takes ownership of the |socket|.
58 net::HostPortPair host_and_port("chromoting", 0);
59 net::SSLClientSocketContext context;
60 context.cert_verifier = cert_verifier;
61 net::SSLClientSocket* ssl_socket =
62 net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
63 socket, host_and_port, ssl_config, NULL, context);
64 return ssl_socket;
65 }
66
67 } // namespace
68
69 PepperStreamChannel::PepperStreamChannel(
70 PepperSession* session,
71 const std::string& name,
72 const Session::StreamChannelCallback& callback)
73 : session_(session),
74 name_(name),
75 callback_(callback),
76 channel_(NULL),
77 connected_(false),
78 ssl_client_socket_(NULL),
79 ALLOW_THIS_IN_INITIALIZER_LIST(p2p_connect_callback_(
80 this, &PepperStreamChannel::OnP2PConnect)),
81 ALLOW_THIS_IN_INITIALIZER_LIST(ssl_connect_callback_(
82 this, &PepperStreamChannel::OnSSLConnect)) {
83 }
84
85 PepperStreamChannel::~PepperStreamChannel() {
86 // Verify that the |channel_| is ether destroyed or we own it.
87 DCHECK_EQ(channel_, owned_channel_.get());
88 // Channel should be already destroyed if we were connected.
89 DCHECK(!connected_ || channel_ == NULL);
90 }
91
92 void PepperStreamChannel::Connect(pp::Instance* pp_instance,
93 const TransportConfig& transport_config,
94 const std::string& remote_cert) {
95 DCHECK(CalledOnValidThread());
96
97 remote_cert_ = remote_cert;
98
99 pp::Transport_Dev* transport =
100 new pp::Transport_Dev(pp_instance, name_.c_str(),
101 kTcpProtocol);
102
103 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_RECEIVE_WINDOW,
104 pp::Var(kTcpReceiveBufferSize)) != PP_OK) {
105 LOG(ERROR) << "Failed to set TCP receive window";
106 }
107 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_SEND_WINDOW,
108 pp::Var(kTcpSendBufferSize)) != PP_OK) {
109 LOG(ERROR) << "Failed to set TCP send window";
110 }
111
112 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_NO_DELAY,
113 pp::Var(true)) != PP_OK) {
114 LOG(ERROR) << "Failed to set TCP_NODELAY";
115 }
116
117 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_ACK_DELAY,
118 pp::Var(kTcpAckDelayMilliseconds)) != PP_OK) {
119 LOG(ERROR) << "Failed to set TCP ACK delay.";
120 }
121
122 if (transport_config.nat_traversal) {
123 if (transport->SetProperty(
124 PP_TRANSPORTPROPERTY_STUN_SERVER,
125 pp::Var(transport_config.stun_server)) != PP_OK) {
126 LOG(ERROR) << "Failed to set STUN server.";
127 }
128 }
129
130 channel_ = new PepperTransportSocketAdapter(transport, name_, this);
131 owned_channel_.reset(channel_);
132
133 int result = channel_->Connect(&p2p_connect_callback_);
134 if (result != net::ERR_IO_PENDING)
135 OnP2PConnect(result);
136 }
137
138 void PepperStreamChannel::AddRemoveCandidate(
139 const cricket::Candidate& candidate) {
140 DCHECK(CalledOnValidThread());
141 if (channel_)
142 channel_->AddRemoteCandidate(jingle_glue::SerializeP2PCandidate(candidate));
143 }
144
145 const std::string& PepperStreamChannel::name() {
146 DCHECK(CalledOnValidThread());
147 return name_;
148 }
149
150 void PepperStreamChannel::OnChannelDeleted() {
151 if (connected_) {
152 channel_ = NULL;
153 // The PepperTransportSocketAdapter is being deleted, so delete the
154 // channel too.
155 session_->OnDeleteChannel(this);
156 delete this;
157 }
158 }
159
160 void PepperStreamChannel::OnChannelNewLocalCandidate(
161 const std::string& candidate) {
162 DCHECK(CalledOnValidThread());
163
164 cricket::Candidate candidate_value;
165 if (!jingle_glue::DeserializeP2PCandidate(candidate, &candidate_value)) {
166 LOG(ERROR) << "Failed to parse candidate " << candidate;
167 }
168 session_->AddLocalCandidate(candidate_value);
169 }
170
171 void PepperStreamChannel::OnP2PConnect(int result) {
172 DCHECK(CalledOnValidThread());
173
174 if (result != net::OK || !EstablishSSLConnection())
175 NotifyConnectFailed();
176 }
177
178 bool PepperStreamChannel::EstablishSSLConnection() {
179 DCHECK(CalledOnValidThread());
180
181 cert_verifier_.reset(new net::CertVerifier());
182
183 // Create client SSL socket.
184 ssl_client_socket_ = CreateSSLClientSocket(
185 owned_channel_.release(), remote_cert_, cert_verifier_.get());
186 socket_.reset(ssl_client_socket_);
187
188 int result = ssl_client_socket_->Connect(&ssl_connect_callback_);
189
190 if (result == net::ERR_IO_PENDING) {
191 return true;
192 } else if (result != net::OK) {
193 LOG(ERROR) << "Failed to establish SSL connection";
194 return false;
195 }
196
197 // Reach here if net::OK is received.
198 ssl_connect_callback_.Run(net::OK);
199 return true;
200 }
201
202 void PepperStreamChannel::OnSSLConnect(int result) {
203 DCHECK(CalledOnValidThread());
204
205 if (result != net::OK) {
206 LOG(ERROR) << "Error during SSL connection: " << result;
207 NotifyConnectFailed();
208 return;
209 }
210
211 DCHECK(socket_->IsConnected());
212 AuthenticateChannel();
213 }
214
215 void PepperStreamChannel::AuthenticateChannel() {
216 DCHECK(CalledOnValidThread());
217
218 authenticator_.reset(new ClientChannelAuthenticator(ssl_client_socket_));
219 authenticator_->Authenticate(
220 session_->shared_secret(),
221 base::Bind(&PepperStreamChannel::OnAuthenticationDone,
222 base::Unretained(this)));
223 }
224
225 void PepperStreamChannel::OnAuthenticationDone(
226 ChannelAuthenticator::Result result) {
227 DCHECK(CalledOnValidThread());
228
229 switch (result) {
230 case ChannelAuthenticator::SUCCESS:
231 NotifyConnected(socket_.release());
232 break;
233
234 case ChannelAuthenticator::FAILURE:
235 NotifyConnectFailed();
236 break;
237 }
238 }
239
240 void PepperStreamChannel::NotifyConnected(net::StreamSocket* socket) {
241 DCHECK(!connected_);
242 callback_.Run(socket);
243 connected_ = true;
244 }
245
246 void PepperStreamChannel::NotifyConnectFailed() {
247 channel_ = NULL;
248 owned_channel_.reset();
249 socket_.reset();
250
251 NotifyConnected(NULL);
252 }
253
254 } // namespace protocol
255 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698