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/jingle_stream_connector.h" | 5 #include "remoting/protocol/jingle_stream_connector.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "jingle/glue/channel_socket_adapter.h" | 8 #include "jingle/glue/channel_socket_adapter.h" |
9 #include "jingle/glue/pseudotcp_adapter.h" | 9 #include "jingle/glue/pseudotcp_adapter.h" |
10 #include "net/base/cert_status_flags.h" | 10 #include "net/base/cert_status_flags.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 | 25 |
26 // Value is choosen to balance the extra latency against the reduced | 26 // Value is choosen to balance the extra latency against the reduced |
27 // load due to ACK traffic. | 27 // load due to ACK traffic. |
28 const int kTcpAckDelayMilliseconds = 10; | 28 const int kTcpAckDelayMilliseconds = 10; |
29 | 29 |
30 // Values for the TCP send and receive buffer size. This should be tuned to | 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. | 31 // accomodate high latency network but not backlog the decoding pipeline. |
32 const int kTcpReceiveBufferSize = 256 * 1024; | 32 const int kTcpReceiveBufferSize = 256 * 1024; |
33 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; | 33 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; |
34 | 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 adapter. | |
53 net::HostPortPair host_and_port( | |
54 ContentDescription::kChromotingContentName, 0); | |
55 net::SSLClientSocketContext context; | |
56 context.cert_verifier = cert_verifier; | |
57 net::SSLClientSocket* ssl_socket = | |
58 net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket( | |
59 socket, host_and_port, ssl_config, NULL, context); | |
60 return ssl_socket; | |
61 } | |
62 | |
63 } // namespace | 35 } // namespace |
64 | 36 |
65 JingleStreamConnector::JingleStreamConnector( | 37 JingleStreamConnector::JingleStreamConnector( |
66 JingleSession* session, | 38 JingleSession* session, |
67 const std::string& name, | 39 const std::string& name, |
68 const Session::StreamChannelCallback& callback) | 40 const Session::StreamChannelCallback& callback) |
69 : session_(session), | 41 : session_(session), |
70 name_(name), | 42 name_(name), |
71 callback_(callback), | 43 callback_(callback), |
72 initiator_(false), | |
73 local_private_key_(NULL), | |
74 raw_channel_(NULL), | 44 raw_channel_(NULL), |
75 ALLOW_THIS_IN_INITIALIZER_LIST(tcp_connect_callback_( | 45 ALLOW_THIS_IN_INITIALIZER_LIST(tcp_connect_callback_( |
76 this, &JingleStreamConnector::OnTCPConnect)), | 46 this, &JingleStreamConnector::OnTCPConnect)) { |
77 ALLOW_THIS_IN_INITIALIZER_LIST(ssl_connect_callback_( | |
78 this, &JingleStreamConnector::OnSSLConnect)) { | |
79 } | 47 } |
80 | 48 |
81 JingleStreamConnector::~JingleStreamConnector() { | 49 JingleStreamConnector::~JingleStreamConnector() { |
82 } | 50 } |
83 | 51 |
84 void JingleStreamConnector::Connect(bool initiator, | 52 void JingleStreamConnector::Connect(ChannelAuthenticator* authenticator, |
85 const std::string& local_cert, | |
86 const std::string& remote_cert, | |
87 crypto::RSAPrivateKey* local_private_key, | |
88 cricket::TransportChannel* raw_channel) { | 53 cricket::TransportChannel* raw_channel) { |
89 DCHECK(CalledOnValidThread()); | 54 DCHECK(CalledOnValidThread()); |
90 DCHECK(!raw_channel_); | 55 DCHECK(!raw_channel_); |
91 | 56 |
92 initiator_ = initiator; | 57 authenticator_.reset(authenticator); |
93 local_cert_ = local_cert; | |
94 remote_cert_ = remote_cert; | |
95 local_private_key_ = local_private_key; | |
96 raw_channel_ = raw_channel; | 58 raw_channel_ = raw_channel; |
97 | 59 |
98 net::Socket* socket = | 60 net::Socket* socket = |
99 new jingle_glue::TransportChannelSocketAdapter(raw_channel_); | 61 new jingle_glue::TransportChannelSocketAdapter(raw_channel_); |
100 | 62 |
101 if (!EstablishTCPConnection(socket)) | 63 if (!EstablishTCPConnection(socket)) |
102 NotifyError(); | 64 NotifyError(); |
103 } | 65 } |
104 | 66 |
105 bool JingleStreamConnector::EstablishTCPConnection(net::Socket* socket) { | 67 bool JingleStreamConnector::EstablishTCPConnection(net::Socket* socket) { |
(...skipping 19 matching lines...) Expand all Loading... |
125 if (result == net::ERR_IO_PENDING) { | 87 if (result == net::ERR_IO_PENDING) { |
126 return true; | 88 return true; |
127 } else if (result == net::OK) { | 89 } else if (result == net::OK) { |
128 tcp_connect_callback_.Run(result); | 90 tcp_connect_callback_.Run(result); |
129 return true; | 91 return true; |
130 } | 92 } |
131 | 93 |
132 return false; | 94 return false; |
133 } | 95 } |
134 | 96 |
135 bool JingleStreamConnector::EstablishSSLConnection() { | |
136 DCHECK(tcp_socket_->IsConnected()); | |
137 | |
138 int result; | |
139 if (initiator_) { | |
140 cert_verifier_.reset(new net::CertVerifier()); | |
141 | |
142 // Create client SSL socket. | |
143 net::SSLClientSocket* socket = CreateSSLClientSocket( | |
144 tcp_socket_.release(), remote_cert_, cert_verifier_.get()); | |
145 socket_.reset(socket); | |
146 | |
147 result = socket->Connect(&ssl_connect_callback_); | |
148 } else { | |
149 scoped_refptr<net::X509Certificate> cert = | |
150 net::X509Certificate::CreateFromBytes( | |
151 local_cert_.data(), local_cert_.length()); | |
152 if (!cert) { | |
153 LOG(ERROR) << "Failed to parse X509Certificate"; | |
154 return false; | |
155 } | |
156 | |
157 // Create server SSL socket. | |
158 net::SSLConfig ssl_config; | |
159 net::SSLServerSocket* socket = net::CreateSSLServerSocket( | |
160 tcp_socket_.release(), cert, local_private_key_, ssl_config); | |
161 socket_.reset(socket); | |
162 | |
163 result = socket->Handshake(&ssl_connect_callback_); | |
164 } | |
165 | |
166 if (result == net::ERR_IO_PENDING) { | |
167 return true; | |
168 } else if (result != net::OK) { | |
169 LOG(ERROR) << "Failed to establish SSL connection"; | |
170 return false; | |
171 } | |
172 | |
173 // Reach here if net::OK is received. | |
174 ssl_connect_callback_.Run(net::OK); | |
175 return true; | |
176 } | |
177 | |
178 void JingleStreamConnector::OnTCPConnect(int result) { | 97 void JingleStreamConnector::OnTCPConnect(int result) { |
179 DCHECK(CalledOnValidThread()); | 98 DCHECK(CalledOnValidThread()); |
180 | 99 |
181 if (result != net::OK) { | 100 if (result != net::OK) { |
182 LOG(ERROR) << "PseudoTCP connection failed: " << result; | 101 LOG(ERROR) << "PseudoTCP connection failed: " << result; |
183 NotifyError(); | 102 NotifyError(); |
184 return; | 103 return; |
185 } | 104 } |
186 | 105 |
187 if (!EstablishSSLConnection()) | 106 authenticator_->SecureAndAuthenticate(tcp_socket_.release(), base::Bind( |
188 NotifyError(); | |
189 } | |
190 | |
191 void JingleStreamConnector::OnSSLConnect(int result) { | |
192 DCHECK(CalledOnValidThread()); | |
193 | |
194 if (result != net::OK) { | |
195 LOG(ERROR) << "Error during SSL connection: " << result; | |
196 NotifyError(); | |
197 return; | |
198 } | |
199 | |
200 DCHECK(socket_->IsConnected()); | |
201 AuthenticateChannel(); | |
202 } | |
203 | |
204 void JingleStreamConnector::AuthenticateChannel() { | |
205 if (initiator_) { | |
206 authenticator_.reset( | |
207 new ClientChannelAuthenticator(session_->shared_secret())); | |
208 } else { | |
209 authenticator_.reset( | |
210 new HostChannelAuthenticator(session_->shared_secret())); | |
211 } | |
212 authenticator_->Authenticate(socket_.get(), base::Bind( | |
213 &JingleStreamConnector::OnAuthenticationDone, base::Unretained(this))); | 107 &JingleStreamConnector::OnAuthenticationDone, base::Unretained(this))); |
214 } | 108 } |
215 | 109 |
216 void JingleStreamConnector::OnAuthenticationDone( | 110 void JingleStreamConnector::OnAuthenticationDone( |
217 ChannelAuthenticator::Result result) { | 111 net::Error error, net::StreamSocket* socket) { |
218 switch (result) { | 112 if (error != net::OK) { |
219 case ChannelAuthenticator::SUCCESS: | 113 NotifyError(); |
220 NotifyDone(socket_.release()); | 114 } else { |
221 break; | 115 NotifyDone(socket); |
222 | |
223 case ChannelAuthenticator::FAILURE: | |
224 NotifyError(); | |
225 break; | |
226 } | 116 } |
227 } | 117 } |
228 | 118 |
229 void JingleStreamConnector::NotifyDone(net::StreamSocket* socket) { | 119 void JingleStreamConnector::NotifyDone(net::StreamSocket* socket) { |
230 session_->OnChannelConnectorFinished(name_, this); | 120 session_->OnChannelConnectorFinished(name_, this); |
231 callback_.Run(socket); | 121 callback_.Run(socket); |
232 delete this; | 122 delete this; |
233 } | 123 } |
234 | 124 |
235 void JingleStreamConnector::NotifyError() { | 125 void JingleStreamConnector::NotifyError() { |
236 socket_.reset(); | |
237 NotifyDone(NULL); | 126 NotifyDone(NULL); |
238 } | 127 } |
239 | 128 |
240 } // namespace protocol | 129 } // namespace protocol |
241 } // namespace remoting | 130 } // namespace remoting |
OLD | NEW |