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

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

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

Powered by Google App Engine
This is Rietveld 408576698