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

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 // 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 // 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
66
67 PepperStreamChannel::PepperStreamChannel(
68 PepperSession* session,
69 const std::string& name,
70 const Session::StreamChannelCallback& callback)
71 : session_(session),
72 name_(name),
73 callback_(callback),
74 channel_(NULL),
75 connected_(false),
76 ssl_client_socket_(NULL),
77 ALLOW_THIS_IN_INITIALIZER_LIST(p2p_connect_callback_(
78 this, &PepperStreamChannel::OnP2PConnect)),
79 ALLOW_THIS_IN_INITIALIZER_LIST(ssl_connect_callback_(
80 this, &PepperStreamChannel::OnSSLConnect)) {
81 }
82
83 PepperStreamChannel::~PepperStreamChannel() {
84 // Verify that the |channel_| is ether destroyed or we own it.
85 DCHECK_EQ(channel_, owned_channel_.get());
86 // Channel should be already destroyed if we were connected.
87 DCHECK(!connected_ || channel_ == NULL);
88 }
89
90 void PepperStreamChannel::Connect(pp::Instance* pp_instance,
91 const TransportConfig& transport_config,
92 const std::string& remote_cert) {
93 DCHECK(CalledOnValidThread());
94
95 remote_cert_ = remote_cert;
96
97 pp::Transport_Dev* transport =
98 new pp::Transport_Dev(pp_instance, name_.c_str(), "tcp");
99
100 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_RECEIVE_WINDOW,
101 pp::Var(kTcpReceiveBufferSize)) != PP_OK) {
102 LOG(ERROR) << "Failed to set TCP receive window";
103 }
104 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_SEND_WINDOW,
105 pp::Var(kTcpSendBufferSize)) != PP_OK) {
106 LOG(ERROR) << "Failed to set TCP send window";
107 }
108
109 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_NO_DELAY,
110 pp::Var(true)) != PP_OK) {
111 LOG(ERROR) << "Failed to set TCP_NODELAY";
112 }
113
114 if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_ACK_DELAY,
115 pp::Var(kTcpAckDelayMilliseconds)) != PP_OK) {
116 LOG(ERROR) << "Failed to set TCP ACK delay.";
117 }
118
119 if (transport_config.nat_traversal) {
120 if (transport->SetProperty(
121 PP_TRANSPORTPROPERTY_STUN_SERVER,
122 pp::Var(transport_config.stun_server)) != PP_OK) {
123 LOG(ERROR) << "Failed to set STUN server.";
124 }
125
126 if (transport->SetProperty(
127 PP_TRANSPORTPROPERTY_RELAY_SERVER,
128 pp::Var(transport_config.relay_server)) != PP_OK) {
129 LOG(ERROR) << "Failed to set Relay server.";
130 }
131
132 if (transport->SetProperty(
133 PP_TRANSPORTPROPERTY_RELAY_TOKEN,
134 pp::Var(transport_config.relay_token)) != PP_OK) {
135 LOG(ERROR) << "Failed to set Relay token.";
136 }
137 }
138
139 channel_ = new PepperTransportSocketAdapter(transport, name_, this);
140 owned_channel_.reset(channel_);
141
142 int result = channel_->Connect(&p2p_connect_callback_);
143 if (result != net::ERR_IO_PENDING)
144 OnP2PConnect(result);
145 }
146
147 void PepperStreamChannel::AddRemoveCandidate(
148 const cricket::Candidate& candidate) {
149 DCHECK(CalledOnValidThread());
150 if (channel_)
151 channel_->AddRemoteCandidate(jingle_glue::SerializeP2PCandidate(candidate));
152 }
153
154 const std::string& PepperStreamChannel::name() {
155 DCHECK(CalledOnValidThread());
156 return name_;
157 }
158
159 void PepperStreamChannel::OnChannelDeleted() {
160 if (connected_) {
161 channel_ = NULL;
162 // The PepperTransportSocketAdapter is being deleted, so delete the
163 // channel too.
164 session_->OnDeleteChannel(this);
165 delete this;
166 }
167 }
168
169 void PepperStreamChannel::OnChannelNewLocalCandidate(
170 const std::string& candidate) {
171 DCHECK(CalledOnValidThread());
172
173 cricket::Candidate candidate_value;
174 if (!jingle_glue::DeserializeP2PCandidate(candidate, &candidate_value)) {
175 LOG(ERROR) << "Failed to parse candidate " << candidate;
176 }
177 session_->AddLocalCandidate(candidate_value);
178 }
179
180 void PepperStreamChannel::OnP2PConnect(int result) {
181 DCHECK(CalledOnValidThread());
182
183 if (result != net::OK || !EstablishSSLConnection())
184 NotifyConnectFailed();
185 }
186
187 bool PepperStreamChannel::EstablishSSLConnection() {
188 DCHECK(CalledOnValidThread());
189
190 cert_verifier_.reset(new net::CertVerifier());
191
192 // Create client SSL socket.
193 ssl_client_socket_ = CreateSSLClientSocket(
194 owned_channel_.release(), remote_cert_, cert_verifier_.get());
195 socket_.reset(ssl_client_socket_);
196
197 int result = ssl_client_socket_->Connect(&ssl_connect_callback_);
198
199 if (result == net::ERR_IO_PENDING) {
200 return true;
201 } else if (result != net::OK) {
202 LOG(ERROR) << "Failed to establish SSL connection";
203 return false;
204 }
205
206 // Reach here if net::OK is received.
207 ssl_connect_callback_.Run(net::OK);
208 return true;
209 }
210
211 void PepperStreamChannel::OnSSLConnect(int result) {
212 DCHECK(CalledOnValidThread());
213
214 if (result != net::OK) {
215 LOG(ERROR) << "Error during SSL connection: " << result;
216 NotifyConnectFailed();
217 return;
218 }
219
220 DCHECK(socket_->IsConnected());
221 AuthenticateChannel();
222 }
223
224 void PepperStreamChannel::AuthenticateChannel() {
225 DCHECK(CalledOnValidThread());
226
227 authenticator_.reset(new ClientChannelAuthenticator(ssl_client_socket_));
228 authenticator_->Authenticate(
229 session_->shared_secret(),
230 base::Bind(&PepperStreamChannel::OnAuthenticationDone,
231 base::Unretained(this)));
232 }
233
234 void PepperStreamChannel::OnAuthenticationDone(
235 ChannelAuthenticator::Result result) {
236 DCHECK(CalledOnValidThread());
237
238 switch (result) {
239 case ChannelAuthenticator::SUCCESS:
240 NotifyConnected(socket_.release());
241 break;
242
243 case ChannelAuthenticator::FAILURE:
244 NotifyConnectFailed();
245 break;
246 }
247 }
248
249 void PepperStreamChannel::NotifyConnected(net::StreamSocket* socket) {
250 DCHECK(!connected_);
251 callback_.Run(socket);
252 connected_ = true;
253 }
254
255 void PepperStreamChannel::NotifyConnectFailed() {
256 channel_ = NULL;
257 owned_channel_.reset();
258 socket_.reset();
259
260 NotifyConnected(NULL);
261 }
262
263 } // namespace protocol
264 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/pepper_stream_channel.h ('k') | remoting/protocol/pepper_transport_socket_adapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698