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

Side by Side Diff: chrome/browser/extensions/api/cast_channel/cast_socket.cc

Issue 79673003: Refactor CastSocket code for the following: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 6 years, 11 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
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/extensions/api/cast_channel/cast_socket.h" 5 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
(...skipping 17 matching lines...) Expand all
28 #include "net/socket/tcp_client_socket.h" 28 #include "net/socket/tcp_client_socket.h"
29 #include "net/ssl/ssl_config_service.h" 29 #include "net/ssl/ssl_config_service.h"
30 #include "net/ssl/ssl_info.h" 30 #include "net/ssl/ssl_info.h"
31 31
32 namespace { 32 namespace {
33 33
34 // Allowed schemes for Cast device URLs. 34 // Allowed schemes for Cast device URLs.
35 const char kCastInsecureScheme[] = "cast"; 35 const char kCastInsecureScheme[] = "cast";
36 const char kCastSecureScheme[] = "casts"; 36 const char kCastSecureScheme[] = "casts";
37 37
38 // Size of the message header, in bytes. Don't use sizeof(MessageHeader)
39 // because of alignment; instead, sum the sizeof() for the fields.
40 const uint32 kMessageHeaderSize = sizeof(uint32);
41
42 // The default keepalive delay. On Linux, keepalives probes will be sent after 38 // The default keepalive delay. On Linux, keepalives probes will be sent after
43 // the socket is idle for this length of time, and the socket will be closed 39 // the socket is idle for this length of time, and the socket will be closed
44 // after 9 failed probes. So the total idle time before close is 10 * 40 // after 9 failed probes. So the total idle time before close is 10 *
45 // kTcpKeepAliveDelaySecs. 41 // kTcpKeepAliveDelaySecs.
46 const int kTcpKeepAliveDelaySecs = 10; 42 const int kTcpKeepAliveDelaySecs = 10;
47 43
48 } // namespace 44 } // namespace
49 45
50 namespace extensions { 46 namespace extensions {
51 47
52 static base::LazyInstance< 48 static base::LazyInstance<
53 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> > > 49 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> > >
54 g_factory = LAZY_INSTANCE_INITIALIZER; 50 g_factory = LAZY_INSTANCE_INITIALIZER;
55 51
56 // static 52 // static
57 template <> 53 template <>
58 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> >* 54 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> >*
59 ApiResourceManager<api::cast_channel::CastSocket>::GetFactoryInstance() { 55 ApiResourceManager<api::cast_channel::CastSocket>::GetFactoryInstance() {
60 return &g_factory.Get(); 56 return &g_factory.Get();
61 } 57 }
62 58
63 namespace api { 59 namespace api {
64 namespace cast_channel { 60 namespace cast_channel {
65 61
66 const uint32 kMaxMessageSize = 65536; 62 const uint32 kMaxMessageSize = 65536;
63 // Don't use sizeof(MessageHeader) because of alignment; instead, sum the
64 // sizeof() for the fields.
65 const uint32 kMessageHeaderSize = sizeof(uint32);
67 66
68 CastSocket::CastSocket(const std::string& owner_extension_id, 67 CastSocket::CastSocket(const std::string& owner_extension_id,
69 const GURL& url, 68 const GURL& url,
70 CastSocket::Delegate* delegate, 69 CastSocket::Delegate* delegate,
71 net::NetLog* net_log) : 70 net::NetLog* net_log) :
72 ApiResource(owner_extension_id), 71 ApiResource(owner_extension_id),
73 channel_id_(0), 72 channel_id_(0),
74 url_(url), 73 url_(url),
75 delegate_(delegate), 74 delegate_(delegate),
76 auth_required_(false), 75 auth_required_(false),
77 error_state_(CHANNEL_ERROR_NONE),
78 ready_state_(READY_STATE_NONE),
79 write_callback_pending_(false),
80 read_callback_pending_(false),
81 current_message_size_(0), 76 current_message_size_(0),
82 net_log_(net_log), 77 net_log_(net_log),
83 next_state_(CONN_STATE_NONE), 78 connect_state_(CONN_STATE_NONE),
84 in_connect_loop_(false) { 79 write_state_(WRITE_STATE_NONE),
80 read_state_(READ_STATE_NONE),
81 error_state_(CHANNEL_ERROR_NONE),
82 ready_state_(READY_STATE_NONE) {
85 DCHECK(net_log_); 83 DCHECK(net_log_);
86 net_log_source_.type = net::NetLog::SOURCE_SOCKET; 84 net_log_source_.type = net::NetLog::SOURCE_SOCKET;
87 net_log_source_.id = net_log_->NextID(); 85 net_log_source_.id = net_log_->NextID();
88 86
89 // We reuse these buffers for each message. 87 // Reuse these buffers for each message.
90 header_read_buffer_ = new net::GrowableIOBuffer(); 88 header_read_buffer_ = new net::GrowableIOBuffer();
91 header_read_buffer_->SetCapacity(kMessageHeaderSize); 89 header_read_buffer_->SetCapacity(kMessageHeaderSize);
92 body_read_buffer_ = new net::GrowableIOBuffer(); 90 body_read_buffer_ = new net::GrowableIOBuffer();
93 body_read_buffer_->SetCapacity(kMaxMessageSize); 91 body_read_buffer_->SetCapacity(kMaxMessageSize);
94 current_read_buffer_ = header_read_buffer_; 92 current_read_buffer_ = header_read_buffer_;
95 } 93 }
96 94
97 CastSocket::~CastSocket() { } 95 CastSocket::~CastSocket() { }
98 96
99 const GURL& CastSocket::url() const { 97 const GURL& CastSocket::url() const {
100 return url_; 98 return url_;
101 } 99 }
102 100
103 scoped_ptr<net::TCPClientSocket> CastSocket::CreateTcpSocket() { 101 scoped_ptr<net::TCPClientSocket> CastSocket::CreateTcpSocket() {
104 net::AddressList addresses(ip_endpoint_); 102 net::AddressList addresses(ip_endpoint_);
105 scoped_ptr<net::TCPClientSocket> tcp_socket( 103 return scoped_ptr<net::TCPClientSocket>(
106 new net::TCPClientSocket(addresses, net_log_, net_log_source_)); 104 new net::TCPClientSocket(addresses, net_log_, net_log_source_));
107 // Options cannot be set on the TCPClientSocket yet, because the 105 // Options cannot be set on the TCPClientSocket yet, because the
108 // underlying platform socket will not be created until we Bind() 106 // underlying platform socket will not be created until Bind()
109 // or Connect() it. 107 // or Connect() is called.
110 return tcp_socket.Pass();
111 } 108 }
112 109
113 scoped_ptr<net::SSLClientSocket> CastSocket::CreateSslSocket() { 110 scoped_ptr<net::SSLClientSocket> CastSocket::CreateSslSocket(
111 scoped_ptr<net::StreamSocket> socket) {
114 net::SSLConfig ssl_config; 112 net::SSLConfig ssl_config;
115 // If a peer cert was extracted in a previous attempt to connect, then 113 // If a peer cert was extracted in a previous attempt to connect, then
116 // whitelist that cert. 114 // whitelist that cert.
117 if (!peer_cert_.empty()) { 115 if (!peer_cert_.empty()) {
118 net::SSLConfig::CertAndStatus cert_and_status; 116 net::SSLConfig::CertAndStatus cert_and_status;
119 cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID; 117 cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
120 cert_and_status.der_cert = peer_cert_; 118 cert_and_status.der_cert = peer_cert_;
121 ssl_config.allowed_bad_certs.push_back(cert_and_status); 119 ssl_config.allowed_bad_certs.push_back(cert_and_status);
122 } 120 }
123 121
124 cert_verifier_.reset(net::CertVerifier::CreateDefault()); 122 cert_verifier_.reset(net::CertVerifier::CreateDefault());
125 transport_security_state_.reset(new net::TransportSecurityState); 123 transport_security_state_.reset(new net::TransportSecurityState);
126 net::SSLClientSocketContext context; 124 net::SSLClientSocketContext context;
127 // CertVerifier and TransportSecurityState are owned by us, not the 125 // CertVerifier and TransportSecurityState are owned by us, not the
128 // context object. 126 // context object.
129 context.cert_verifier = cert_verifier_.get(); 127 context.cert_verifier = cert_verifier_.get();
130 context.transport_security_state = transport_security_state_.get(); 128 context.transport_security_state = transport_security_state_.get();
131 129
132 scoped_ptr<net::ClientSocketHandle> connection(new net::ClientSocketHandle); 130 scoped_ptr<net::ClientSocketHandle> connection(new net::ClientSocketHandle);
133 connection->SetSocket(tcp_socket_.PassAs<net::StreamSocket>()); 131 connection->SetSocket(socket.Pass());
134 net::HostPortPair host_and_port = net::HostPortPair::FromIPEndPoint( 132 net::HostPortPair host_and_port = net::HostPortPair::FromIPEndPoint(
135 ip_endpoint_); 133 ip_endpoint_);
136 134
137 return net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket( 135 return net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
138 connection.Pass(), host_and_port, ssl_config, context); 136 connection.Pass(), host_and_port, ssl_config, context);
139 } 137 }
140 138
141 bool CastSocket::ExtractPeerCert(std::string* cert) { 139 bool CastSocket::ExtractPeerCert(std::string* cert) {
142 DCHECK(cert); 140 DCHECK(cert);
143 DCHECK(peer_cert_.empty()); 141 DCHECK(peer_cert_.empty());
144 net::SSLInfo ssl_info; 142 net::SSLInfo ssl_info;
145 if (!socket_->GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) 143 if (!socket_->GetSSLInfo(&ssl_info) || !ssl_info.cert.get())
146 return false; 144 return false;
147 bool result = net::X509Certificate::GetDEREncoded( 145 bool result = net::X509Certificate::GetDEREncoded(
148 ssl_info.cert->os_cert_handle(), cert); 146 ssl_info.cert->os_cert_handle(), cert);
149 if (result) 147 if (result)
150 VLOG(1) << "Successfully extracted peer certificate: " << *cert; 148 VLOG(1) << "[URL: " << url_.spec()
149 << "] Successfully extracted peer certificate: " << *cert;
151 return result; 150 return result;
152 } 151 }
153 152
154 int CastSocket::SendAuthChallenge() { 153 bool CastSocket::VerifyChallengeReply() {
155 CastMessage challenge_message; 154 return AuthenticateChallengeReply(*challenge_reply_.get(), peer_cert_);
156 CreateAuthChallengeMessage(&challenge_message);
157 VLOG(1) << "Sending challenge: " << CastMessageToString(challenge_message);
158 int result = SendMessageInternal(
159 challenge_message,
160 base::Bind(&CastSocket::OnChallengeEvent, AsWeakPtr()));
161 return (result < 0) ? result : net::OK;
162 }
163
164 int CastSocket::ReadAuthChallengeReply() {
165 int result = ReadData();
166 return (result < 0) ? result : net::OK;
167 }
168
169 void CastSocket::OnConnectComplete(int result) {
170 int rv = DoConnectLoop(result);
171 if (rv != net::ERR_IO_PENDING)
172 DoConnectCallback(rv);
173 }
174
175 void CastSocket::OnChallengeEvent(int result) {
176 // result >= 0 means read or write succeeded synchronously.
177 int rv = DoConnectLoop(result >= 0 ? net::OK : result);
178 if (rv != net::ERR_IO_PENDING)
179 DoConnectCallback(rv);
180 } 155 }
181 156
182 void CastSocket::Connect(const net::CompletionCallback& callback) { 157 void CastSocket::Connect(const net::CompletionCallback& callback) {
183 DCHECK(CalledOnValidThread()); 158 DCHECK(CalledOnValidThread());
184 int result = net::ERR_CONNECTION_FAILED;
185 VLOG(1) << "Connect readyState = " << ready_state_; 159 VLOG(1) << "Connect readyState = " << ready_state_;
186 if (ready_state_ != READY_STATE_NONE) { 160 if (ready_state_ != READY_STATE_NONE) {
187 callback.Run(result); 161 callback.Run(net::ERR_CONNECTION_FAILED);
188 return; 162 return;
189 } 163 }
190 if (!ParseChannelUrl(url_)) { 164 if (!ParseChannelUrl(url_)) {
191 CloseWithError(cast_channel::CHANNEL_ERROR_CONNECT_ERROR); 165 callback.Run(net::ERR_CONNECTION_FAILED);
192 callback.Run(result);
193 return; 166 return;
194 } 167 }
168
169 ready_state_ = READY_STATE_CONNECTING;
195 connect_callback_ = callback; 170 connect_callback_ = callback;
196 next_state_ = CONN_STATE_TCP_CONNECT; 171 connect_state_ = CONN_STATE_TCP_CONNECT;
197 int rv = DoConnectLoop(net::OK); 172 DoConnectLoop(net::OK);
198 if (rv != net::ERR_IO_PENDING) 173 }
199 DoConnectCallback(rv); 174
175 void CastSocket::PostTaskToStartConnectLoop(int result) {
176 DCHECK(CalledOnValidThread());
177 base::MessageLoop::current()->PostTask(
178 FROM_HERE,
179 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr(), result));
200 } 180 }
201 181
202 // This method performs the state machine transitions for connection flow. 182 // This method performs the state machine transitions for connection flow.
203 // There are two entry points to this method: 183 // There are two entry points to this method:
204 // 1. public Connect method: this starts the flow 184 // 1. Connect method: this starts the flow
205 // 2. OnConnectComplete: callback method called when an async operation 185 // 2. Callback from network operations that finish asynchronously
206 // is done. OnConnectComplete calls this method to continue the state 186 void CastSocket::DoConnectLoop(int result) {
207 // machine transitions.
208 int CastSocket::DoConnectLoop(int result) {
209 // Avoid re-entrancy as a result of synchronous completion.
210 if (in_connect_loop_)
211 return net::ERR_IO_PENDING;
212 in_connect_loop_ = true;
213
214 // Network operations can either finish synchronously or asynchronously. 187 // Network operations can either finish synchronously or asynchronously.
215 // This method executes the state machine transitions in a loop so that 188 // This method executes the state machine transitions in a loop so that
216 // correct state transitions happen even when network operations finish 189 // correct state transitions happen even when network operations finish
217 // synchronously. 190 // synchronously.
218 int rv = result; 191 int rv = result;
219 do { 192 do {
220 ConnectionState state = next_state_; 193 ConnectionState state = connect_state_;
221 // All the Do* methods do not set next_state_ in case of an 194 // Default to CONN_STATE_NONE, which breaks the processing loop if any
222 // error. So set next_state_ to NONE to figure out if the Do* 195 // handler fails to transition to another state to continue processing.
223 // method changed state or not. 196 connect_state_ = CONN_STATE_NONE;
224 next_state_ = CONN_STATE_NONE;
225 switch (state) { 197 switch (state) {
226 case CONN_STATE_TCP_CONNECT: 198 case CONN_STATE_TCP_CONNECT:
227 rv = DoTcpConnect(); 199 rv = DoTcpConnect();
228 break; 200 break;
229 case CONN_STATE_TCP_CONNECT_COMPLETE: 201 case CONN_STATE_TCP_CONNECT_COMPLETE:
230 rv = DoTcpConnectComplete(rv); 202 rv = DoTcpConnectComplete(rv);
231 break; 203 break;
232 case CONN_STATE_SSL_CONNECT: 204 case CONN_STATE_SSL_CONNECT:
233 DCHECK_EQ(net::OK, rv); 205 DCHECK_EQ(net::OK, rv);
234 rv = DoSslConnect(); 206 rv = DoSslConnect();
235 break; 207 break;
236 case CONN_STATE_SSL_CONNECT_COMPLETE: 208 case CONN_STATE_SSL_CONNECT_COMPLETE:
237 rv = DoSslConnectComplete(rv); 209 rv = DoSslConnectComplete(rv);
238 break; 210 break;
239 case CONN_STATE_AUTH_CHALLENGE_SEND: 211 case CONN_STATE_AUTH_CHALLENGE_SEND:
240 rv = DoAuthChallengeSend(); 212 rv = DoAuthChallengeSend();
241 break; 213 break;
242 case CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE: 214 case CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE:
243 rv = DoAuthChallengeSendComplete(rv); 215 rv = DoAuthChallengeSendComplete(rv);
244 break; 216 break;
245 case CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE: 217 case CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE:
246 rv = DoAuthChallengeReplyComplete(rv); 218 rv = DoAuthChallengeReplyComplete(rv);
247 break; 219 break;
248
249 default: 220 default:
250 NOTREACHED() << "BUG in CastSocket state machine code"; 221 NOTREACHED() << "BUG in connect flow. Unknown state: " << state;
251 break; 222 break;
252 } 223 }
253 } while (rv != net::ERR_IO_PENDING && next_state_ != CONN_STATE_NONE); 224 } while (rv != net::ERR_IO_PENDING && connect_state_ != CONN_STATE_NONE);
254 // Get out of the loop either when: 225 // Get out of the loop either when:
255 // a. A network operation is pending, OR 226 // a. A network operation is pending, OR
256 // b. The Do* method called did not change state 227 // b. The Do* method called did not change state
257 228
258 in_connect_loop_ = false; 229 // Connect loop is finished: if there is no pending IO invoke the callback.
259 230 if (rv != net::ERR_IO_PENDING)
260 return rv; 231 DoConnectCallback(rv);
261 } 232 }
262 233
263 int CastSocket::DoTcpConnect() { 234 int CastSocket::DoTcpConnect() {
264 VLOG(1) << "DoTcpConnect"; 235 VLOG(1) << "DoTcpConnect";
265 next_state_ = CONN_STATE_TCP_CONNECT_COMPLETE; 236 connect_state_ = CONN_STATE_TCP_CONNECT_COMPLETE;
266 tcp_socket_ = CreateTcpSocket(); 237 tcp_socket_ = CreateTcpSocket();
267 return tcp_socket_->Connect( 238 return tcp_socket_->Connect(
268 base::Bind(&CastSocket::OnConnectComplete, AsWeakPtr())); 239 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr()));
269 } 240 }
270 241
271 int CastSocket::DoTcpConnectComplete(int result) { 242 int CastSocket::DoTcpConnectComplete(int result) {
272 VLOG(1) << "DoTcpConnectComplete: " << result; 243 VLOG(1) << "DoTcpConnectComplete: " << result;
273 if (result == net::OK) { 244 if (result == net::OK) {
274 // Enable TCP protocol-level keep-alive. 245 // Enable TCP protocol-level keep-alive.
275 bool result = tcp_socket_->SetKeepAlive(true, kTcpKeepAliveDelaySecs); 246 bool result = tcp_socket_->SetKeepAlive(true, kTcpKeepAliveDelaySecs);
276 LOG_IF(WARNING, !result) << "Failed to SetKeepAlive."; 247 LOG_IF(WARNING, !result) << "Failed to SetKeepAlive.";
277 next_state_ = CONN_STATE_SSL_CONNECT; 248 connect_state_ = CONN_STATE_SSL_CONNECT;
278 } 249 }
279 return result; 250 return result;
280 } 251 }
281 252
282 int CastSocket::DoSslConnect() { 253 int CastSocket::DoSslConnect() {
283 VLOG(1) << "DoSslConnect"; 254 VLOG(1) << "DoSslConnect";
284 next_state_ = CONN_STATE_SSL_CONNECT_COMPLETE; 255 connect_state_ = CONN_STATE_SSL_CONNECT_COMPLETE;
285 socket_ = CreateSslSocket(); 256 socket_ = CreateSslSocket(tcp_socket_.PassAs<net::StreamSocket>());
286 return socket_->Connect( 257 return socket_->Connect(
287 base::Bind(&CastSocket::OnConnectComplete, AsWeakPtr())); 258 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr()));
288 } 259 }
289 260
290 int CastSocket::DoSslConnectComplete(int result) { 261 int CastSocket::DoSslConnectComplete(int result) {
291 VLOG(1) << "DoSslConnectComplete: " << result; 262 VLOG(1) << "DoSslConnectComplete: " << result;
292 if (result == net::ERR_CERT_AUTHORITY_INVALID && 263 if (result == net::ERR_CERT_AUTHORITY_INVALID &&
293 peer_cert_.empty() && 264 peer_cert_.empty() &&
294 ExtractPeerCert(&peer_cert_)) { 265 ExtractPeerCert(&peer_cert_)) {
295 next_state_ = CONN_STATE_TCP_CONNECT; 266 connect_state_ = CONN_STATE_TCP_CONNECT;
296 } else if (result == net::OK && auth_required_) { 267 } else if (result == net::OK && auth_required_) {
297 next_state_ = CONN_STATE_AUTH_CHALLENGE_SEND; 268 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND;
298 } 269 }
299 return result; 270 return result;
300 } 271 }
301 272
302 int CastSocket::DoAuthChallengeSend() { 273 int CastSocket::DoAuthChallengeSend() {
303 VLOG(1) << "DoAuthChallengeSend"; 274 VLOG(1) << "DoAuthChallengeSend";
304 next_state_ = CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE; 275 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE;
305 return SendAuthChallenge(); 276 CastMessage challenge_message;
277 CreateAuthChallengeMessage(&challenge_message);
278 VLOG(1) << "Sending challenge: " << CastMessageToString(challenge_message);
279 // Post a task to send auth challenge so that DoWriteLoop is not nested inside
280 // DoConnectLoop. This is not strictly necessary but keeps the write loop
281 // code decoupled from connect loop code.
282 base::MessageLoop::current()->PostTask(
283 FROM_HERE,
284 base::Bind(&CastSocket::SendCastMessageInternal, AsWeakPtr(),
285 challenge_message,
286 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())));
287 // Always return IO_PENDING since the result is always asynchronous.
288 return net::ERR_IO_PENDING;
306 } 289 }
307 290
308 int CastSocket::DoAuthChallengeSendComplete(int result) { 291 int CastSocket::DoAuthChallengeSendComplete(int result) {
309 VLOG(1) << "DoAuthChallengeSendComplete: " << result; 292 VLOG(1) << "DoAuthChallengeSendComplete: " << result;
310 if (result != net::OK) 293 if (result < 0)
311 return result; 294 return result;
312 next_state_ = CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE; 295 connect_state_ = CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE;
313 return ReadAuthChallengeReply(); 296 // Post a task to start read loop so that DoReadLoop is not nested inside
297 // DoConnectLoop. This is not strictly necessary but keeps the read loop
298 // code decoupled from connect loop code.
299 PostTaskToStartReadLoop();
300 // Always return IO_PENDING since the result is always asynchronous.
301 return net::ERR_IO_PENDING;
314 } 302 }
315 303
316 int CastSocket::DoAuthChallengeReplyComplete(int result) { 304 int CastSocket::DoAuthChallengeReplyComplete(int result) {
317 VLOG(1) << "DoAuthChallengeReplyComplete: " << result; 305 VLOG(1) << "DoAuthChallengeReplyComplete: " << result;
318 if (result != net::OK) 306 if (result < 0)
319 return result; 307 return result;
320 if (!VerifyChallengeReply()) 308 if (!VerifyChallengeReply())
321 return net::ERR_FAILED; 309 return net::ERR_FAILED;
322 VLOG(1) << "Auth challenge verification succeeded"; 310 VLOG(1) << "Auth challenge verification succeeded";
323 return net::OK; 311 return net::OK;
324 } 312 }
325 313
326 bool CastSocket::VerifyChallengeReply() {
327 return AuthenticateChallengeReply(*challenge_reply_.get(), peer_cert_);
328 }
329
330 void CastSocket::DoConnectCallback(int result) { 314 void CastSocket::DoConnectCallback(int result) {
331 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED; 315 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED;
332 error_state_ = (result == net::OK) ? 316 error_state_ = (result == net::OK) ?
333 CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR; 317 CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR;
318 if (result == net::OK) // Start the read loop
319 PostTaskToStartReadLoop();
334 base::ResetAndReturn(&connect_callback_).Run(result); 320 base::ResetAndReturn(&connect_callback_).Run(result);
335 // Start the ReadData loop if not already started.
336 // If auth_required_ is true we would've started a ReadData loop already.
337 // TODO(munjal): This is a bit ugly. Refactor read and write code.
338 if (result == net::OK && !auth_required_)
339 ReadData();
340 } 321 }
341 322
342 void CastSocket::Close(const net::CompletionCallback& callback) { 323 void CastSocket::Close(const net::CompletionCallback& callback) {
343 DCHECK(CalledOnValidThread()); 324 DCHECK(CalledOnValidThread());
344 VLOG(1) << "Close ReadyState = " << ready_state_; 325 VLOG(1) << "Close ReadyState = " << ready_state_;
345 tcp_socket_.reset(NULL); 326 tcp_socket_.reset();
346 socket_.reset(NULL); 327 socket_.reset();
347 cert_verifier_.reset(NULL); 328 cert_verifier_.reset();
348 transport_security_state_.reset(NULL); 329 transport_security_state_.reset();
349 ready_state_ = READY_STATE_CLOSED; 330 ready_state_ = READY_STATE_CLOSED;
350 callback.Run(net::OK); 331 callback.Run(net::OK);
332 // |callback| can delete |this|
351 } 333 }
352 334
353 void CastSocket::SendMessage(const MessageInfo& message, 335 void CastSocket::SendMessage(const MessageInfo& message,
354 const net::CompletionCallback& callback) { 336 const net::CompletionCallback& callback) {
355 DCHECK(CalledOnValidThread()); 337 DCHECK(CalledOnValidThread());
356 VLOG(1) << "Send ReadyState " << ready_state_;
357 int result = net::ERR_FAILED;
358 if (ready_state_ != READY_STATE_OPEN) { 338 if (ready_state_ != READY_STATE_OPEN) {
359 callback.Run(result); 339 callback.Run(net::ERR_FAILED);
360 return; 340 return;
361 } 341 }
362 CastMessage message_proto; 342 CastMessage message_proto;
363 if (!MessageInfoToCastMessage(message, &message_proto)) { 343 if (!MessageInfoToCastMessage(message, &message_proto)) {
364 CloseWithError(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE); 344 callback.Run(net::ERR_FAILED);
365 // TODO(mfoltz): Do a better job of signaling cast_channel errors to the 345 return;
366 // caller. 346 }
367 callback.Run(net::OK); 347
368 return; 348 SendCastMessageInternal(message_proto, callback);
369 } 349 }
370 SendMessageInternal(message_proto, callback); 350
371 } 351 void CastSocket::SendCastMessageInternal(
372 352 const CastMessage& message,
373 int CastSocket::SendMessageInternal(const CastMessage& message_proto, 353 const net::CompletionCallback& callback) {
374 const net::CompletionCallback& callback) {
375 WriteRequest write_request(callback); 354 WriteRequest write_request(callback);
376 if (!write_request.SetContent(message_proto)) 355 if (!write_request.SetContent(message)) {
377 return net::ERR_FAILED; 356 callback.Run(net::ERR_FAILED);
357 return;
358 }
359
378 write_queue_.push(write_request); 360 write_queue_.push(write_request);
379 return WriteData(); 361 if (write_state_ == WRITE_STATE_NONE) {
380 } 362 write_state_ = WRITE_STATE_WRITE;
381 363 DoWriteLoop(net::OK);
382 int CastSocket::WriteData() { 364 }
365 }
366
367 void CastSocket::DoWriteLoop(int result) {
383 DCHECK(CalledOnValidThread()); 368 DCHECK(CalledOnValidThread());
384 VLOG(1) << "WriteData q = " << write_queue_.size(); 369 VLOG(1) << "WriteData q = " << write_queue_.size();
385 if (write_queue_.empty() || write_callback_pending_) 370
386 return net::ERR_FAILED; 371 if (write_queue_.empty()) {
387 372 write_state_ = WRITE_STATE_NONE;
373 return;
374 }
375
376 // Network operations can either finish synchronously or asynchronously.
377 // This method executes the state machine transitions in a loop so that
378 // write state transitions happen even when network operations finish
379 // synchronously.
380 int rv = result;
381 do {
382 WriteState state = write_state_;
383 write_state_ = WRITE_STATE_NONE;
384 switch (state) {
385 case WRITE_STATE_WRITE:
386 rv = DoWrite();
387 break;
388 case WRITE_STATE_WRITE_COMPLETE:
389 rv = DoWriteComplete(rv);
390 break;
391 case WRITE_STATE_DO_CALLBACK:
392 rv = DoWriteCallback();
393 break;
394 case WRITE_STATE_ERROR:
395 rv = DoWriteError(rv);
396 break;
397 default:
398 NOTREACHED() << "BUG in write flow. Unknown state: " << state;
399 break;
400 }
401 } while (!write_queue_.empty() &&
402 rv != net::ERR_IO_PENDING &&
403 write_state_ != WRITE_STATE_NONE);
404
405 // If write loop is done because the queue is empty then set write
406 // state to NONE
407 if (write_queue_.empty())
408 write_state_ = WRITE_STATE_NONE;
409
410 // Write loop is done - if the result is ERR_FAILED then close with error.
411 if (rv == net::ERR_FAILED)
412 CloseWithError(error_state_);
413 }
414
415 int CastSocket::DoWrite() {
416 DCHECK(!write_queue_.empty());
388 WriteRequest& request = write_queue_.front(); 417 WriteRequest& request = write_queue_.front();
389 418
390 VLOG(1) << "WriteData byte_count = " << request.io_buffer->size() 419 VLOG(1) << "WriteData byte_count = " << request.io_buffer->size()
391 << " bytes_written " << request.io_buffer->BytesConsumed(); 420 << " bytes_written " << request.io_buffer->BytesConsumed();
392 421
393 write_callback_pending_ = true; 422 write_state_ = WRITE_STATE_WRITE_COMPLETE;
394 int result = socket_->Write( 423
424 return socket_->Write(
395 request.io_buffer.get(), 425 request.io_buffer.get(),
396 request.io_buffer->BytesRemaining(), 426 request.io_buffer->BytesRemaining(),
397 base::Bind(&CastSocket::OnWriteData, AsWeakPtr())); 427 base::Bind(&CastSocket::DoWriteLoop, AsWeakPtr()));
398 428 }
399 if (result != net::ERR_IO_PENDING) 429
400 OnWriteData(result); 430 int CastSocket::DoWriteComplete(int result) {
401 431 DCHECK(!write_queue_.empty());
402 return result; 432 if (result <= 0) { // NOTE that 0 also indicates an error
403 } 433 error_state_ = CHANNEL_ERROR_SOCKET_ERROR;
404 434 write_state_ = WRITE_STATE_ERROR;
405 void CastSocket::OnWriteData(int result) { 435 return result == 0 ? net::ERR_FAILED : result;
406 DCHECK(CalledOnValidThread()); 436 }
407 VLOG(1) << "OnWriteComplete result = " << result; 437
408 DCHECK(write_callback_pending_); 438 // Some bytes were successfully written
409 DCHECK(!write_queue_.empty());
410 write_callback_pending_ = false;
411 WriteRequest& request = write_queue_.front(); 439 WriteRequest& request = write_queue_.front();
412 scoped_refptr<net::DrainableIOBuffer> io_buffer = request.io_buffer; 440 scoped_refptr<net::DrainableIOBuffer> io_buffer = request.io_buffer;
413 441 io_buffer->DidConsume(result);
414 if (result >= 0) { 442 if (io_buffer->BytesRemaining() == 0) // Message fully sent
415 io_buffer->DidConsume(result); 443 write_state_ = WRITE_STATE_DO_CALLBACK;
416 if (io_buffer->BytesRemaining() > 0) { 444 else
417 VLOG(1) << "OnWriteComplete size = " << io_buffer->size() 445 write_state_ = WRITE_STATE_WRITE;
418 << " consumed " << io_buffer->BytesConsumed() 446
419 << " remaining " << io_buffer->BytesRemaining() 447 return net::OK;
420 << " # requests " << write_queue_.size(); 448 }
421 WriteData(); 449
422 return; 450 int CastSocket::DoWriteCallback() {
451 DCHECK(!write_queue_.empty());
452 WriteRequest& request = write_queue_.front();
453 int bytes_consumed = request.io_buffer->BytesConsumed();
454
455 // If inside connection flow, then there should be exaclty one item in
456 // the write queue.
457 if (ready_state_ == READY_STATE_CONNECTING) {
458 write_queue_.pop();
459 DCHECK(write_queue_.empty());
460 PostTaskToStartConnectLoop(bytes_consumed);
461 } else {
462 WriteRequest& request = write_queue_.front();
463 request.callback.Run(bytes_consumed);
464 write_queue_.pop();
465 }
466 write_state_ = WRITE_STATE_WRITE;
467 return net::OK;
468 }
469
470 int CastSocket::DoWriteError(int result) {
471 DCHECK(!write_queue_.empty());
472 DCHECK_LT(result, 0);
473
474 // If inside connection flow, then there should be exactly one item in
475 // the write queue.
476 if (ready_state_ == READY_STATE_CONNECTING) {
477 write_queue_.pop();
478 DCHECK(write_queue_.empty());
479 PostTaskToStartConnectLoop(result);
480 // Connect loop will handle the error. Return net::OK so that write flow
481 // does not try to report error also.
482 return net::OK;
483 }
484
485 while (!write_queue_.empty()) {
486 WriteRequest& request = write_queue_.front();
487 request.callback.Run(result);
488 write_queue_.pop();
489 }
490 return net::ERR_FAILED;
491 }
492
493 void CastSocket::PostTaskToStartReadLoop() {
494 DCHECK(CalledOnValidThread());
495 base::MessageLoop::current()->PostTask(
496 FROM_HERE,
497 base::Bind(&CastSocket::StartReadLoop, AsWeakPtr()));
498 }
499
500 void CastSocket::StartReadLoop() {
501 // Read loop would have already been started if read state is not NONE
502 if (read_state_ == READ_STATE_NONE) {
503 read_state_ = READ_STATE_READ;
504 DoReadLoop(net::OK);
505 }
506 }
507
508 void CastSocket::DoReadLoop(int result) {
509 DCHECK(CalledOnValidThread());
510 // Network operations can either finish synchronously or asynchronously.
511 // This method executes the state machine transitions in a loop so that
512 // write state transitions happen even when network operations finish
513 // synchronously.
514 int rv = result;
515 do {
516 ReadState state = read_state_;
517 read_state_ = READ_STATE_NONE;
518
519 switch (state) {
520 case READ_STATE_READ:
521 rv = DoRead();
522 break;
523 case READ_STATE_READ_COMPLETE:
524 rv = DoReadComplete(rv);
525 break;
526 case READ_STATE_DO_CALLBACK:
527 rv = DoReadCallback();
528 break;
529 case READ_STATE_ERROR:
530 rv = DoReadError(rv);
531 break;
532 default:
533 NOTREACHED() << "BUG in read flow. Unknown state: " << state;
534 break;
423 } 535 }
424 DCHECK_EQ(io_buffer->BytesConsumed(), io_buffer->size()); 536 } while (rv != net::ERR_IO_PENDING && read_state_ != READ_STATE_NONE);
425 DCHECK_EQ(io_buffer->BytesRemaining(), 0); 537
426 result = io_buffer->BytesConsumed(); 538 // Read loop is done - If the result is ERR_FAILED then close with error.
427 } 539 if (rv == net::ERR_FAILED)
428 540 CloseWithError(error_state_);
429 request.callback.Run(result); 541 }
430 write_queue_.pop(); 542
431 543 int CastSocket::DoRead() {
432 VLOG(1) << "OnWriteComplete size = " << io_buffer->size() 544 read_state_ = READ_STATE_READ_COMPLETE;
433 << " consumed " << io_buffer->BytesConsumed() 545 // Figure out whether to read header or body, and the remaining bytes.
434 << " remaining " << io_buffer->BytesRemaining()
435 << " # requests " << write_queue_.size();
436
437 if (result < 0) {
438 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR);
439 return;
440 }
441
442 if (!write_queue_.empty())
443 WriteData();
444 }
445
446 int CastSocket::ReadData() {
447 DCHECK(CalledOnValidThread());
448 if (!socket_.get())
449 return net::ERR_FAILED;
450 DCHECK(!read_callback_pending_);
451 read_callback_pending_ = true;
452 // Figure out if we are reading the header or body, and the remaining bytes.
453 uint32 num_bytes_to_read = 0; 546 uint32 num_bytes_to_read = 0;
454 if (header_read_buffer_->RemainingCapacity() > 0) { 547 if (header_read_buffer_->RemainingCapacity() > 0) {
455 current_read_buffer_ = header_read_buffer_; 548 current_read_buffer_ = header_read_buffer_;
456 num_bytes_to_read = header_read_buffer_->RemainingCapacity(); 549 num_bytes_to_read = header_read_buffer_->RemainingCapacity();
457 DCHECK_LE(num_bytes_to_read, kMessageHeaderSize); 550 DCHECK_LE(num_bytes_to_read, kMessageHeaderSize);
458 } else { 551 } else {
459 DCHECK_GT(current_message_size_, 0U); 552 DCHECK_GT(current_message_size_, 0U);
460 num_bytes_to_read = current_message_size_ - body_read_buffer_->offset(); 553 num_bytes_to_read = current_message_size_ - body_read_buffer_->offset();
461 current_read_buffer_ = body_read_buffer_; 554 current_read_buffer_ = body_read_buffer_;
462 DCHECK_LE(num_bytes_to_read, kMaxMessageSize); 555 DCHECK_LE(num_bytes_to_read, kMaxMessageSize);
463 } 556 }
464 DCHECK_GT(num_bytes_to_read, 0U); 557 DCHECK_GT(num_bytes_to_read, 0U);
465 // We read up to num_bytes_to_read into |current_read_buffer_|. 558
466 int result = socket_->Read( 559 // Read up to num_bytes_to_read into |current_read_buffer_|.
560 return socket_->Read(
467 current_read_buffer_.get(), 561 current_read_buffer_.get(),
468 num_bytes_to_read, 562 num_bytes_to_read,
469 base::Bind(&CastSocket::OnReadData, AsWeakPtr())); 563 base::Bind(&CastSocket::DoReadLoop, AsWeakPtr()));
470 VLOG(1) << "ReadData result = " << result;
471 if (result > 0) {
472 OnReadData(result);
473 } else if (result != net::ERR_IO_PENDING) {
474 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR);
475 }
476 return result;
477 } 564 }
478 565
479 void CastSocket::OnReadData(int result) { 566 int CastSocket::DoReadComplete(int result) {
480 DCHECK(CalledOnValidThread()); 567 VLOG(1) << "DoReadDataComplete result = " << result
481 VLOG(1) << "OnReadData result = " << result
482 << " header offset = " << header_read_buffer_->offset() 568 << " header offset = " << header_read_buffer_->offset()
483 << " body offset = " << body_read_buffer_->offset(); 569 << " body offset = " << body_read_buffer_->offset();
484 read_callback_pending_ = false; 570 if (result <= 0) { // 0 means EOF: the peer closed the socket
485 if (result <= 0) { 571 error_state_ = CHANNEL_ERROR_SOCKET_ERROR;
486 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR); 572 read_state_ = READ_STATE_ERROR;
487 return; 573 return result == 0 ? net::ERR_FAILED : result;
488 } 574 }
489 // We read some data. Move the offset in the current buffer forward. 575
576 // Some data was read. Move the offset in the current buffer forward.
490 DCHECK_LE(current_read_buffer_->offset() + result, 577 DCHECK_LE(current_read_buffer_->offset() + result,
491 current_read_buffer_->capacity()); 578 current_read_buffer_->capacity());
492 current_read_buffer_->set_offset(current_read_buffer_->offset() + result); 579 current_read_buffer_->set_offset(current_read_buffer_->offset() + result);
580 read_state_ = READ_STATE_READ;
493 581
494 bool should_continue = true;
495 if (current_read_buffer_.get() == header_read_buffer_.get() && 582 if (current_read_buffer_.get() == header_read_buffer_.get() &&
496 current_read_buffer_->RemainingCapacity() == 0) { 583 current_read_buffer_->RemainingCapacity() == 0) {
497 // If we have read a full header, process the contents. 584 // A full header is read, process the contents.
498 should_continue = ProcessHeader(); 585 if (!ProcessHeader()) {
586 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE;
587 read_state_ = READ_STATE_ERROR;
588 }
499 } else if (current_read_buffer_.get() == body_read_buffer_.get() && 589 } else if (current_read_buffer_.get() == body_read_buffer_.get() &&
500 static_cast<uint32>(current_read_buffer_->offset()) == 590 static_cast<uint32>(current_read_buffer_->offset()) ==
501 current_message_size_) { 591 current_message_size_) {
502 // If we have read a full body, process the contents. 592 // Full body is read, process the contents.
503 should_continue = ProcessBody(); 593 if (ProcessBody()) {
594 read_state_ = READ_STATE_DO_CALLBACK;
595 } else {
596 error_state_ = cast_channel::CHANNEL_ERROR_INVALID_MESSAGE;
597 read_state_ = READ_STATE_ERROR;
598 }
504 } 599 }
505 if (should_continue) 600
506 ReadData(); 601 return net::OK;
602 }
603
604 int CastSocket::DoReadCallback() {
605 read_state_ = READ_STATE_READ;
606 if (IsAuthMessage(current_message_)) {
607 // An auth message is received, check that connect flow is running.
608 if (ready_state_ == READY_STATE_CONNECTING) {
609 challenge_reply_.reset(new CastMessage(current_message_));
610 PostTaskToStartConnectLoop(net::OK);
611 } else {
612 read_state_ = READ_STATE_ERROR;
613 }
614 } else if (delegate_) {
615 MessageInfo message;
616 if (CastMessageToMessageInfo(current_message_, &message))
617 delegate_->OnMessage(this, message);
618 else
619 read_state_ = READ_STATE_ERROR;
620 }
621 current_message_.Clear();
622 return net::OK;
623 }
624
625 int CastSocket::DoReadError(int result) {
626 DCHECK_LE(result, 0);
627 // If inside connection flow, then get back to connect loop.
628 if (ready_state_ == READY_STATE_CONNECTING) {
629 PostTaskToStartConnectLoop(result);
630 // does not try to report error also.
631 return net::OK;
632 }
633 return net::ERR_FAILED;
507 } 634 }
508 635
509 bool CastSocket::ProcessHeader() { 636 bool CastSocket::ProcessHeader() {
510 DCHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()), 637 DCHECK_EQ(static_cast<uint32>(header_read_buffer_->offset()),
511 kMessageHeaderSize); 638 kMessageHeaderSize);
512 MessageHeader header; 639 MessageHeader header;
513 MessageHeader::ReadFromIOBuffer(header_read_buffer_.get(), &header); 640 MessageHeader::ReadFromIOBuffer(header_read_buffer_.get(), &header);
514 if (header.message_size > kMaxMessageSize) { 641 if (header.message_size > kMaxMessageSize)
515 CloseWithError(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE);
516 return false; 642 return false;
517 } 643
518 VLOG(1) << "Parsed header { message_size: " << header.message_size << " }"; 644 VLOG(1) << "Parsed header { message_size: " << header.message_size << " }";
519 current_message_size_ = header.message_size; 645 current_message_size_ = header.message_size;
520 return true; 646 return true;
521 } 647 }
522 648
523 bool CastSocket::ProcessBody() { 649 bool CastSocket::ProcessBody() {
524 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), 650 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()),
525 current_message_size_); 651 current_message_size_);
526 if (!ParseMessageFromBody()) { 652 if (!current_message_.ParseFromArray(
527 CloseWithError(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE); 653 body_read_buffer_->StartOfBuffer(), current_message_size_)) {
528 return false; 654 return false;
529 } 655 }
530 current_message_size_ = 0; 656 current_message_size_ = 0;
531 header_read_buffer_->set_offset(0); 657 header_read_buffer_->set_offset(0);
532 body_read_buffer_->set_offset(0); 658 body_read_buffer_->set_offset(0);
533 current_read_buffer_ = header_read_buffer_; 659 current_read_buffer_ = header_read_buffer_;
534 return true; 660 return true;
535 } 661 }
536 662
537 bool CastSocket::ParseMessageFromBody() {
538 DCHECK(CalledOnValidThread());
539 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()),
540 current_message_size_);
541 CastMessage message_proto;
542 if (!message_proto.ParseFromArray(
543 body_read_buffer_->StartOfBuffer(),
544 current_message_size_))
545 return false;
546 VLOG(1) << "Parsed message " << CastMessageToString(message_proto);
547 // If the message is an auth message then we handle it internally.
548 if (IsAuthMessage(message_proto)) {
549 challenge_reply_.reset(new CastMessage(message_proto));
550 OnChallengeEvent(net::OK);
551 } else if (delegate_) {
552 MessageInfo message;
553 if (!CastMessageToMessageInfo(message_proto, &message))
554 return false;
555 delegate_->OnMessage(this, message);
556 }
557 return true;
558 }
559
560 // static 663 // static
561 bool CastSocket::Serialize(const CastMessage& message_proto, 664 bool CastSocket::Serialize(const CastMessage& message_proto,
562 std::string* message_data) { 665 std::string* message_data) {
563 DCHECK(message_data); 666 DCHECK(message_data);
564 message_proto.SerializeToString(message_data); 667 message_proto.SerializeToString(message_data);
565 size_t message_size = message_data->size(); 668 size_t message_size = message_data->size();
566 if (message_size > kMaxMessageSize) { 669 if (message_size > kMaxMessageSize) {
567 message_data->clear(); 670 message_data->clear();
568 return false; 671 return false;
569 } 672 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 if (!base::StringToInt(port_str, &port)) 717 if (!base::StringToInt(port_str, &port))
615 return false; 718 return false;
616 net::IPAddressNumber ip_address; 719 net::IPAddressNumber ip_address;
617 if (!net::ParseIPLiteralToNumber(ip_address_str, &ip_address)) 720 if (!net::ParseIPLiteralToNumber(ip_address_str, &ip_address))
618 return false; 721 return false;
619 ip_endpoint_ = net::IPEndPoint(ip_address, port); 722 ip_endpoint_ = net::IPEndPoint(ip_address, port);
620 return true; 723 return true;
621 }; 724 };
622 725
623 void CastSocket::FillChannelInfo(ChannelInfo* channel_info) const { 726 void CastSocket::FillChannelInfo(ChannelInfo* channel_info) const {
624 DCHECK(CalledOnValidThread());
625 channel_info->channel_id = channel_id_; 727 channel_info->channel_id = channel_id_;
626 channel_info->url = url_.spec(); 728 channel_info->url = url_.spec();
627 channel_info->ready_state = ready_state_; 729 channel_info->ready_state = ready_state_;
628 channel_info->error_state = error_state_; 730 channel_info->error_state = error_state_;
629 } 731 }
630 732
631 bool CastSocket::CalledOnValidThread() const { 733 bool CastSocket::CalledOnValidThread() const {
632 return thread_checker_.CalledOnValidThread(); 734 return thread_checker_.CalledOnValidThread();
633 } 735 }
634 736
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 io_buffer = new net::DrainableIOBuffer(new net::StringIOBuffer(message_data), 772 io_buffer = new net::DrainableIOBuffer(new net::StringIOBuffer(message_data),
671 message_data.size()); 773 message_data.size());
672 return true; 774 return true;
673 } 775 }
674 776
675 CastSocket::WriteRequest::~WriteRequest() { } 777 CastSocket::WriteRequest::~WriteRequest() { }
676 778
677 } // namespace cast_channel 779 } // namespace cast_channel
678 } // namespace api 780 } // namespace api
679 } // namespace extensions 781 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698