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

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

Powered by Google App Engine
This is Rietveld 408576698