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

Side by Side Diff: net/socket/websocket_transport_client_socket_pool.cc

Issue 240873003: Create WebSocketTransportClientSocketPool (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixes for clang style complaints. Created 6 years, 6 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/socket/websocket_transport_client_socket_pool.h"
6
7 #include <algorithm>
8 #include <limits>
tyoshino (SeeGerritForStatus) 2014/06/20 12:12:07 remove
Adam Rice 2014/06/23 10:06:26 Done.
9 #include <map>
tyoshino (SeeGerritForStatus) 2014/06/20 12:12:07 remove
Adam Rice 2014/06/23 10:06:26 Done.
10 #include <utility>
tyoshino (SeeGerritForStatus) 2014/06/20 12:12:07 remove
Adam Rice 2014/06/23 10:06:26 Done.
11
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/singleton.h"
tyoshino (SeeGerritForStatus) 2014/06/20 12:12:07 remove
Adam Rice 2014/06/23 10:06:26 Done.
15 #include "base/numerics/safe_conversions.h"
16 #include "base/stl_util.h"
tyoshino (SeeGerritForStatus) 2014/06/20 12:12:06 remove
Adam Rice 2014/06/23 10:06:26 Done.
17 #include "base/strings/string_util.h"
18 #include "base/time/time.h"
19 #include "base/values.h"
20 #include "net/base/ip_endpoint.h"
tyoshino (SeeGerritForStatus) 2014/06/20 12:12:06 can be removed?
Adam Rice 2014/06/23 10:06:26 Done.
21 #include "net/base/net_errors.h"
22 #include "net/base/net_log.h"
23 #include "net/socket/client_socket_handle.h"
24 #include "net/socket/client_socket_pool_base.h"
25 #include "net/socket/websocket_endpoint_lock_manager.h"
26 #include "net/socket/websocket_transport_connect_sub_job.h"
27
28 namespace net {
29
30 namespace {
31
32 using base::TimeDelta;
33
34 // TODO(ricea): For now, we implement a global timeout for compatability with
35 // TransportConnectJob. Since WebSocketTransportConnectJob controls the address
36 // selection process more tightly, it could do something smarter here.
37 const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes.
38
39 } // namespace
40
41 WebSocketTransportConnectJob::WebSocketTransportConnectJob(
42 const std::string& group_name,
43 RequestPriority priority,
44 const scoped_refptr<TransportSocketParams>& params,
45 TimeDelta timeout_duration,
46 const CompletionCallback& callback,
47 ClientSocketFactory* client_socket_factory,
48 HostResolver* host_resolver,
49 ClientSocketHandle* handle,
50 Delegate* delegate,
51 NetLog* pool_net_log,
52 const BoundNetLog& request_net_log)
53 : ConnectJob(group_name,
54 timeout_duration,
55 priority,
56 delegate,
57 BoundNetLog::Make(pool_net_log, NetLog::SOURCE_CONNECT_JOB)),
58 helper_(params, client_socket_factory, host_resolver, &connect_timing_),
59 race_result_(TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN),
60 handle_(handle),
61 callback_(callback),
62 request_net_log_(request_net_log),
63 had_ipv4_(false),
64 had_ipv6_(false) {
65 helper_.SetOnIOComplete(this);
66 }
67
68 WebSocketTransportConnectJob::~WebSocketTransportConnectJob() {}
69
70 LoadState WebSocketTransportConnectJob::GetLoadState() const {
71 LoadState load_state = LOAD_STATE_RESOLVING_HOST;
72 if (ipv6_job_)
73 load_state = ipv6_job_->GetLoadState();
74 // This method should return LOAD_STATE_CONNECTING in preference to
75 // LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET when possible because "waiting for
76 // available socket" implies that nothing is happening.
77 if (ipv4_job_ && load_state != LOAD_STATE_CONNECTING)
78 load_state = ipv4_job_->GetLoadState();
79 return load_state;
80 }
81
82 int WebSocketTransportConnectJob::DoResolveHost() {
83 return helper_.DoResolveHost(priority(), net_log());
84 }
85
86 int WebSocketTransportConnectJob::DoResolveHostComplete(int result) {
87 return helper_.DoResolveHostComplete(result, net_log());
88 }
89
90 int WebSocketTransportConnectJob::DoTransportConnect() {
91 AddressList ipv4_addresses;
92 AddressList ipv6_addresses;
93 int result = ERR_UNEXPECTED;
94 helper_.set_next_state(
95 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE);
96
97 for (AddressList::const_iterator it = helper_.addresses().begin();
98 it != helper_.addresses().end();
99 ++it) {
100 switch (it->GetFamily()) {
101 case ADDRESS_FAMILY_IPV4:
102 ipv4_addresses.push_back(*it);
103 break;
104
105 case ADDRESS_FAMILY_IPV6:
106 ipv6_addresses.push_back(*it);
107 break;
108
109 default:
110 DVLOG(1) << "Unexpected ADDRESS_FAMILY: " << it->GetFamily();
111 break;
112 }
113 }
114
115 if (!ipv4_addresses.empty()) {
116 had_ipv4_ = true;
117 ipv4_job_.reset(new WebSocketTransportConnectSubJob(
118 ipv4_addresses, this, SUB_JOB_IPV4));
119 }
120
121 if (!ipv6_addresses.empty()) {
122 had_ipv6_ = true;
123 ipv6_job_.reset(new WebSocketTransportConnectSubJob(
124 ipv6_addresses, this, SUB_JOB_IPV6));
125 result = ipv6_job_->Start();
126 switch (result) {
127 case OK:
128 SetSocket(ipv6_job_->PassSocket());
129 race_result_ =
130 had_ipv4_
131 ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE
132 : TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
133 return result;
134
135 case ERR_IO_PENDING:
136 if (ipv4_job_) {
137 // This use of base::Unretained is safe because |fallback_timer_| is
138 // owned by this object.
139 fallback_timer_.Start(
140 FROM_HERE,
141 TimeDelta::FromMilliseconds(
142 TransportConnectJobHelper::kIPv6FallbackTimerInMs),
143 base::Bind(&WebSocketTransportConnectJob::StartIPv4JobAsync,
144 base::Unretained(this)));
145 }
146 return result;
147
148 default:
149 ipv6_job_.reset();
150 }
151 }
152
153 DCHECK(!ipv6_job_);
154 if (ipv4_job_) {
155 result = ipv4_job_->Start();
156 if (result == OK) {
157 SetSocket(ipv4_job_->PassSocket());
158 race_result_ =
159 had_ipv6_
160 ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE
161 : TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
162 }
163 }
164
165 return result;
166 }
167
168 int WebSocketTransportConnectJob::DoTransportConnectComplete(int result) {
169 if (result == OK)
170 helper_.HistogramDuration(race_result_);
171 return result;
172 }
173
174 void WebSocketTransportConnectJob::OnSubJobComplete(
175 int result,
176 WebSocketTransportConnectSubJob* job) {
177 if (result == OK) {
178 switch (job->type()) {
179 case SUB_JOB_IPV4:
180 race_result_ =
181 had_ipv6_
182 ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE
183 : TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
184 break;
185
186 case SUB_JOB_IPV6:
187 race_result_ =
188 had_ipv4_
189 ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE
190 : TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
191 break;
192 }
193 SetSocket(job->PassSocket());
194
195 // Make sure all connections are cancelled even if this object fails to be
196 // deleted.
197 ipv4_job_.reset();
198 ipv6_job_.reset();
199 } else {
200 switch (job->type()) {
201 case SUB_JOB_IPV4:
202 ipv4_job_.reset();
203 break;
204
205 case SUB_JOB_IPV6:
206 ipv6_job_.reset();
207 if (ipv4_job_ && !ipv4_job_->started()) {
208 fallback_timer_.Stop();
209 result = ipv4_job_->Start();
210 if (result != ERR_IO_PENDING) {
211 OnSubJobComplete(result, ipv4_job_.get());
212 return;
213 }
214 }
215 break;
216 }
217 if (ipv4_job_ || ipv6_job_)
218 return;
219 }
220 helper_.OnIOComplete(this, result);
221 }
222
223 void WebSocketTransportConnectJob::StartIPv4JobAsync() {
224 DCHECK(ipv4_job_);
225 int result = ipv4_job_->Start();
226 if (result != ERR_IO_PENDING)
227 OnSubJobComplete(result, ipv4_job_.get());
228 }
229
230 int WebSocketTransportConnectJob::ConnectInternal() {
231 return helper_.DoConnectInternal(this);
232 }
233
234 WebSocketTransportClientSocketPool::WebSocketTransportClientSocketPool(
235 int max_sockets,
236 int max_sockets_per_group,
237 ClientSocketPoolHistograms* histograms,
238 HostResolver* host_resolver,
239 ClientSocketFactory* client_socket_factory,
240 NetLog* net_log)
241 : TransportClientSocketPool(max_sockets,
242 max_sockets_per_group,
243 histograms,
244 host_resolver,
245 client_socket_factory,
246 net_log),
247 connect_job_delegate_(this),
248 histograms_(histograms),
249 pool_net_log_(net_log),
250 client_socket_factory_(client_socket_factory),
251 host_resolver_(host_resolver),
252 max_sockets_(max_sockets),
253 handed_out_socket_count_(0),
254 weak_factory_(this) {}
255
256 WebSocketTransportClientSocketPool::~WebSocketTransportClientSocketPool() {
Johnny 2014/06/20 21:32:58 I think I'm surprised by these dcheck's. What's th
Adam Rice 2014/06/23 10:06:26 I'm not completely sure about this, since unlike t
257 DCHECK(pending_connects_.empty());
258 DCHECK_EQ(0, handed_out_socket_count_);
259 DCHECK(stalled_request_queue_.empty());
260 DCHECK(stalled_request_map_.empty());
261 }
262
263 // static
264 void WebSocketTransportClientSocketPool::UnlockEndpoint(
265 ClientSocketHandle* handle) {
266 DCHECK(handle->is_initialized());
267 WebSocketEndpointLockManager::GetInstance()->UnlockSocket(handle->socket());
268 }
269
270 int WebSocketTransportClientSocketPool::RequestSocket(
271 const std::string& group_name,
272 const void* params,
273 RequestPriority priority,
274 ClientSocketHandle* handle,
275 const CompletionCallback& callback,
276 const BoundNetLog& request_net_log) {
277 DCHECK(params);
278 const scoped_refptr<TransportSocketParams>& casted_params =
279 *static_cast<const scoped_refptr<TransportSocketParams>*>(params);
280
281 NetLogTcpClientSocketPoolRequestedSocket(request_net_log, &casted_params);
282
283 CHECK(!callback.is_null());
284 CHECK(handle);
285
286 request_net_log.BeginEvent(NetLog::TYPE_SOCKET_POOL);
287
288 if (ReachedMaxSocketsLimit() && !casted_params->ignore_limits()) {
289 request_net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS);
290 // TODO(ricea): Use emplace_back when C++11 becomes allowed.
291 StalledRequest request(
292 casted_params, priority, handle, callback, request_net_log);
293 stalled_request_queue_.push_back(request);
294 StalledRequestQueue::iterator iterator = stalled_request_queue_.end();
295 --iterator;
296 DCHECK_EQ(handle, iterator->handle);
297 stalled_request_map_.insert(
298 StalledRequestMap::value_type(handle, iterator));
tyoshino (SeeGerritForStatus) 2014/06/20 12:12:07 please write why we can use the std::list iterator
Adam Rice 2014/06/23 10:06:26 Done.
299 return ERR_IO_PENDING;
300 }
301
302 scoped_ptr<WebSocketTransportConnectJob> connect_job(
303 new WebSocketTransportConnectJob(group_name,
304 priority,
305 casted_params,
306 ConnectionTimeout(),
307 callback,
308 client_socket_factory_,
309 host_resolver_,
310 handle,
311 &connect_job_delegate_,
312 pool_net_log_,
313 request_net_log));
314
315 int rv = connect_job->Connect();
316 // Regardless of the outcome of |connect_job|, it will always be bound to
317 // |handle|, since this pool uses early-binding. So the binding is logged
318 // here, without waiting for the result.
319 request_net_log.AddEvent(
320 NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
321 connect_job->net_log().source().ToEventParametersCallback());
322 if (rv == OK) {
323 HandOutSocket(connect_job->PassSocket(),
324 connect_job->connect_timing(),
325 handle,
326 request_net_log);
327 request_net_log.EndEvent(NetLog::TYPE_SOCKET_POOL);
328 } else if (rv == ERR_IO_PENDING) {
329 // TODO(ricea): Implement backup job timer?
330 AddJob(handle, connect_job.Pass());
331 } else {
332 scoped_ptr<StreamSocket> error_socket;
333 connect_job->GetAdditionalErrorState(handle);
334 error_socket = connect_job->PassSocket();
335 if (error_socket) {
336 HandOutSocket(error_socket.Pass(),
337 connect_job->connect_timing(),
338 handle,
339 request_net_log);
340 }
341 }
342
343 if (rv != ERR_IO_PENDING) {
344 request_net_log.EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv);
345 }
346
347 return rv;
348 }
349
350 void WebSocketTransportClientSocketPool::RequestSockets(
351 const std::string& group_name,
352 const void* params,
353 int num_sockets,
354 const BoundNetLog& net_log) {
355 NOTIMPLEMENTED();
356 }
357
358 void WebSocketTransportClientSocketPool::CancelRequest(
359 const std::string& group_name,
360 ClientSocketHandle* handle) {
361 if (DeleteStalledRequest(handle))
362 return;
363 if (!DeleteJob(handle))
364 pending_callbacks_.erase(handle);
365 if (!ReachedMaxSocketsLimit() && !stalled_request_queue_.empty())
366 ActivateStalledRequest();
367 }
368
369 void WebSocketTransportClientSocketPool::ReleaseSocket(
370 const std::string& group_name,
371 scoped_ptr<StreamSocket> socket,
372 int id) {
373 WebSocketEndpointLockManager::GetInstance()->UnlockSocket(socket.get());
374 CHECK_GT(handed_out_socket_count_, 0);
375 --handed_out_socket_count_;
376 if (!ReachedMaxSocketsLimit() && !stalled_request_queue_.empty())
377 ActivateStalledRequest();
378 }
379
380 void WebSocketTransportClientSocketPool::FlushWithError(int error) {
Johnny 2014/06/20 21:32:58 Are there re-entrance concerns with these loops? E
Adam Rice 2014/06/23 10:06:26 Well spotted! I have added tests and a flag to gua
381 for (PendingConnectsMap::iterator it = pending_connects_.begin();
382 it != pending_connects_.end();
383 ++it) {
384 InvokeUserCallbackLater(
385 it->second->handle(), it->second->callback(), error);
386 delete it->second;
387 }
388 pending_connects_.clear();
389 for (StalledRequestQueue::iterator it = stalled_request_queue_.begin();
390 it != stalled_request_queue_.end();
391 ++it) {
392 InvokeUserCallbackLater(it->handle, it->callback, error);
393 }
394 stalled_request_map_.clear();
395 stalled_request_queue_.clear();
396 handed_out_socket_count_ = 0;
397 }
398
399 void WebSocketTransportClientSocketPool::CloseIdleSockets() {
400 // We have no idle sockets.
401 }
402
403 int WebSocketTransportClientSocketPool::IdleSocketCount() const {
404 return 0;
405 }
406
407 int WebSocketTransportClientSocketPool::IdleSocketCountInGroup(
408 const std::string& group_name) const {
409 return 0;
410 }
411
412 LoadState WebSocketTransportClientSocketPool::GetLoadState(
413 const std::string& group_name,
414 const ClientSocketHandle* handle) const {
415 if (stalled_request_map_.find(handle) != stalled_request_map_.end())
416 return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET;
417 if (pending_callbacks_.count(handle))
418 return LOAD_STATE_CONNECTING;
419 return LookupConnectJob(handle)->GetLoadState();
420 }
421
422 base::DictionaryValue* WebSocketTransportClientSocketPool::GetInfoAsValue(
423 const std::string& name,
424 const std::string& type,
425 bool include_nested_pools) const {
426 base::DictionaryValue* dict = new base::DictionaryValue();
427 dict->SetString("name", name);
428 dict->SetString("type", type);
429 dict->SetInteger("handed_out_socket_count", handed_out_socket_count_);
430 dict->SetInteger("connecting_socket_count", pending_connects_.size());
431 dict->SetInteger("idle_socket_count", 0);
432 dict->SetInteger("max_socket_count", max_sockets_);
433 dict->SetInteger("max_sockets_per_group", max_sockets_);
434 dict->SetInteger("pool_generation_number", 0);
435 return dict;
436 }
437
438 TimeDelta WebSocketTransportClientSocketPool::ConnectionTimeout() const {
439 return TimeDelta::FromSeconds(kTransportConnectJobTimeoutInSeconds);
440 }
441
442 ClientSocketPoolHistograms* WebSocketTransportClientSocketPool::histograms()
443 const {
444 return histograms_;
445 }
446
447 bool WebSocketTransportClientSocketPool::IsStalled() const {
448 return !stalled_request_queue_.empty();
449 }
450
451 void WebSocketTransportClientSocketPool::OnConnectJobComplete(
452 int result,
453 WebSocketTransportConnectJob* job) {
454 DCHECK_NE(ERR_IO_PENDING, result);
455
456 scoped_ptr<StreamSocket> socket = job->PassSocket();
457
458 BoundNetLog request_net_log = job->request_net_log();
459 CompletionCallback callback = job->callback();
460 LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing();
461
462 ClientSocketHandle* const handle = job->handle();
463 bool handed_out_socket = false;
464
465 if (result == OK) {
466 DCHECK(socket.get());
467 handed_out_socket = true;
468 HandOutSocket(socket.Pass(), connect_timing, handle, request_net_log);
469 request_net_log.EndEvent(NetLog::TYPE_SOCKET_POOL);
470 } else {
471 // If we got a socket, it must contain error information so pass that
472 // up so that the caller can retrieve it.
473 job->GetAdditionalErrorState(handle);
474 if (socket.get()) {
475 handed_out_socket = true;
476 HandOutSocket(socket.Pass(), connect_timing, handle, request_net_log);
477 }
478 request_net_log.EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, result);
479 }
480 bool delete_succeeded = DeleteJob(handle);
481 DCHECK(delete_succeeded);
482 if (!handed_out_socket && !stalled_request_queue_.empty() &&
483 !ReachedMaxSocketsLimit())
484 ActivateStalledRequest();
485 InvokeUserCallbackLater(handle, callback, result);
486 }
487
488 void WebSocketTransportClientSocketPool::InvokeUserCallbackLater(
489 ClientSocketHandle* handle,
490 const CompletionCallback& callback,
491 int rv) {
492 DCHECK(!pending_callbacks_.count(handle));
493 pending_callbacks_.insert(handle);
494 base::MessageLoop::current()->PostTask(
495 FROM_HERE,
496 base::Bind(&WebSocketTransportClientSocketPool::InvokeUserCallback,
497 weak_factory_.GetWeakPtr(),
498 handle,
499 callback,
500 rv));
501 }
502
503 void WebSocketTransportClientSocketPool::InvokeUserCallback(
504 ClientSocketHandle* handle,
505 const CompletionCallback& callback,
506 int rv) {
507 if (pending_callbacks_.erase(handle))
508 callback.Run(rv);
509 }
510
511 bool WebSocketTransportClientSocketPool::ReachedMaxSocketsLimit() const {
512 return handed_out_socket_count_ >= max_sockets_ ||
513 base::checked_cast<int>(pending_connects_.size()) >=
514 max_sockets_ - handed_out_socket_count_;
515 }
516
517 void WebSocketTransportClientSocketPool::HandOutSocket(
518 scoped_ptr<StreamSocket> socket,
519 const LoadTimingInfo::ConnectTiming& connect_timing,
520 ClientSocketHandle* handle,
521 const BoundNetLog& net_log) {
522 DCHECK(socket);
523 handle->SetSocket(socket.Pass());
524 DCHECK_EQ(ClientSocketHandle::UNUSED, handle->reuse_type());
525 DCHECK_EQ(0, handle->idle_time().InMicroseconds());
526 handle->set_pool_id(0);
527 handle->set_connect_timing(connect_timing);
528
529 net_log.AddEvent(
530 NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
531 handle->socket()->NetLog().source().ToEventParametersCallback());
532
533 ++handed_out_socket_count_;
534 }
535
536 void WebSocketTransportClientSocketPool::AddJob(
537 ClientSocketHandle* handle,
538 scoped_ptr<WebSocketTransportConnectJob> connect_job) {
539 bool inserted =
540 pending_connects_.insert(PendingConnectsMap::value_type(
541 handle, connect_job.release())).second;
542 DCHECK(inserted);
543 }
544
545 bool WebSocketTransportClientSocketPool::DeleteJob(ClientSocketHandle* handle) {
546 PendingConnectsMap::iterator it = pending_connects_.find(handle);
547 if (it == pending_connects_.end())
548 return false;
549 delete it->second, it->second = NULL;
Johnny 2014/06/20 21:32:58 Could |it| be invalidated here?
Adam Rice 2014/06/23 10:06:26 No. I have added a comment and a DCHECK to clarify
550 pending_connects_.erase(it);
551 return true;
552 }
553
554 const WebSocketTransportConnectJob*
555 WebSocketTransportClientSocketPool::LookupConnectJob(
556 const ClientSocketHandle* handle) const {
557 PendingConnectsMap::const_iterator it = pending_connects_.find(handle);
558 CHECK(it != pending_connects_.end());
559 return it->second;
560 }
561
562 void WebSocketTransportClientSocketPool::ActivateStalledRequest() {
563 DCHECK(!stalled_request_queue_.empty());
564 DCHECK(!ReachedMaxSocketsLimit());
565 // Usually we will only be able to activate one stalled request at a time,
566 // however if all the connects fail synchronously for some reason, we may be
567 // able to clear the whole queue at once.
568 while (!stalled_request_queue_.empty() && !ReachedMaxSocketsLimit()) {
569 StalledRequest request(stalled_request_queue_.front());
570 stalled_request_queue_.pop_front();
571 stalled_request_map_.erase(request.handle);
572 int rv = RequestSocket("ignored",
573 &request.params,
574 request.priority,
575 request.handle,
576 request.callback,
577 request.net_log);
578 if (rv != ERR_IO_PENDING)
579 InvokeUserCallbackLater(request.handle, request.callback, rv);
580 }
581 }
582
583 bool WebSocketTransportClientSocketPool::DeleteStalledRequest(
584 ClientSocketHandle* handle) {
585 StalledRequestMap::iterator it = stalled_request_map_.find(handle);
586 if (it == stalled_request_map_.end())
587 return false;
588 stalled_request_queue_.erase(it->second);
589 stalled_request_map_.erase(it);
590 return true;
591 }
592
593 WebSocketTransportClientSocketPool::ConnectJobDelegate::ConnectJobDelegate(
594 WebSocketTransportClientSocketPool* owner)
595 : owner_(owner) {}
596
597 WebSocketTransportClientSocketPool::ConnectJobDelegate::~ConnectJobDelegate() {}
598
599 void
600 WebSocketTransportClientSocketPool::ConnectJobDelegate::OnConnectJobComplete(
601 int result,
602 ConnectJob* job) {
603 owner_->OnConnectJobComplete(result,
604 static_cast<WebSocketTransportConnectJob*>(job));
605 }
606
607 WebSocketTransportClientSocketPool::StalledRequest::StalledRequest(
608 const scoped_refptr<TransportSocketParams>& params,
609 RequestPriority priority,
610 ClientSocketHandle* handle,
611 const CompletionCallback& callback,
612 const BoundNetLog& net_log)
613 : params(params),
614 priority(priority),
615 handle(handle),
616 callback(callback),
617 net_log(net_log) {}
618
619 WebSocketTransportClientSocketPool::StalledRequest::~StalledRequest() {}
620
621 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698