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

Side by Side Diff: net/http/http_pipelined_connection_impl.cc

Issue 7289006: Basic HTTP pipelining support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix trybot issues Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_pipelined_connection_impl.h"
6
7 #include "base/message_loop.h"
8 #include "base/stl_util.h"
9 #include "net/base/io_buffer.h"
10 #include "net/http/http_pipelined_stream.h"
11 #include "net/http/http_request_info.h"
12 #include "net/http/http_stream_parser.h"
13 #include "net/socket/client_socket_handle.h"
14
15 namespace net {
16
17 HttpPipelinedConnectionImpl::HttpPipelinedConnectionImpl(
18 ClientSocketHandle* connection,
19 HttpPipelinedConnection::Delegate* delegate,
20 const SSLConfig& used_ssl_config,
21 const ProxyInfo& used_proxy_info,
22 const BoundNetLog& net_log,
23 bool was_npn_negotiated)
24 : delegate_(delegate),
25 connection_(connection),
26 used_ssl_config_(used_ssl_config),
27 used_proxy_info_(used_proxy_info),
28 net_log_(net_log),
29 was_npn_negotiated_(was_npn_negotiated),
30 read_buf_(new GrowableIOBuffer()),
31 next_pipeline_id_(1),
32 active_(false),
33 usable_(true),
34 completed_one_request_(false),
35 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
36 send_next_state_(SEND_STATE_NONE),
37 ALLOW_THIS_IN_INITIALIZER_LIST(send_io_callback_(
38 this, &HttpPipelinedConnectionImpl::OnSendIOCallback)),
39 send_user_callback_(NULL),
40 read_next_state_(READ_STATE_NONE),
41 ALLOW_THIS_IN_INITIALIZER_LIST(read_io_callback_(
42 this, &HttpPipelinedConnectionImpl::OnReadIOCallback)),
43 read_user_callback_(NULL) {
44 CHECK(connection_.get());
45 }
46
47 HttpPipelinedConnectionImpl::~HttpPipelinedConnectionImpl() {
48 CHECK_EQ(depth(), 0);
49 CHECK(stream_info_map_.empty());
50 CHECK(deferred_request_queue_.empty());
51 CHECK(request_order_.empty());
52 CHECK_EQ(send_next_state_, SEND_STATE_NONE);
53 CHECK_EQ(read_next_state_, READ_STATE_NONE);
54 CHECK(!send_user_callback_);
55 CHECK(!read_user_callback_);
56 if (!usable_) {
57 connection_->socket()->Disconnect();
58 }
59 connection_->Reset();
60 }
61
62 HttpPipelinedStream* HttpPipelinedConnectionImpl::CreateNewStream() {
63 int pipeline_id = next_pipeline_id_++;
64 CHECK(pipeline_id);
65 HttpPipelinedStream* stream = new HttpPipelinedStream(this, pipeline_id);
66 stream_info_map_.insert(std::make_pair(pipeline_id, StreamInfo()));
67 return stream;
68 }
69
70 void HttpPipelinedConnectionImpl::InitializeParser(
71 int pipeline_id,
72 const HttpRequestInfo* request,
73 const BoundNetLog& net_log) {
74 CHECK(ContainsKey(stream_info_map_, pipeline_id));
75 CHECK(!stream_info_map_[pipeline_id].parser.get());
76 stream_info_map_[pipeline_id].state = STREAM_BOUND;
77 stream_info_map_[pipeline_id].parser.reset(new HttpStreamParser(
78 connection_.get(), request, read_buf_.get(), net_log));
79
80 // In case our first stream doesn't SendRequest() immediately, we should still
81 // allow others to use this pipeline.
82 if (pipeline_id == 1) {
83 MessageLoop::current()->PostTask(
84 FROM_HERE,
85 method_factory_.NewRunnableMethod(
86 &HttpPipelinedConnectionImpl::ActivatePipeline));
87 }
88 }
89
90 void HttpPipelinedConnectionImpl::ActivatePipeline() {
91 if (!active_) {
92 active_ = true;
93 delegate_->OnPipelineHasCapacity(this);
94 }
95 }
96
97 void HttpPipelinedConnectionImpl::OnStreamDeleted(int pipeline_id) {
98 CHECK(ContainsKey(stream_info_map_, pipeline_id));
99 Close(pipeline_id, false);
100
101 if (stream_info_map_[pipeline_id].state != STREAM_CREATED &&
102 stream_info_map_[pipeline_id].state != STREAM_UNUSED) {
103 CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_CLOSED);
104 CHECK(stream_info_map_[pipeline_id].parser.get());
105 stream_info_map_[pipeline_id].parser.reset();
106 }
107 CHECK(!stream_info_map_[pipeline_id].parser.get());
108 CHECK(!stream_info_map_[pipeline_id].read_headers_callback);
109 stream_info_map_.erase(pipeline_id);
110
111 delegate_->OnPipelineHasCapacity(this);
112 }
113
114 int HttpPipelinedConnectionImpl::SendRequest(int pipeline_id,
115 const std::string& request_line,
116 const HttpRequestHeaders& headers,
117 UploadDataStream* request_body,
118 HttpResponseInfo* response,
119 OldCompletionCallback* callback) {
120 CHECK(ContainsKey(stream_info_map_, pipeline_id));
121 CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_BOUND);
122 if (!usable_) {
123 return ERR_PIPELINE_EVICTION;
124 }
125
126 DeferredSendRequest deferred_request;
127 deferred_request.pipeline_id = pipeline_id;
128 deferred_request.request_line = request_line;
129 deferred_request.headers = headers;
130 deferred_request.request_body = request_body;
131 deferred_request.response = response;
132 deferred_request.callback = callback;
133 deferred_request_queue_.push(deferred_request);
134
135 int rv;
136 if (send_next_state_ == SEND_STATE_NONE) {
137 send_next_state_ = SEND_STATE_NEXT_REQUEST;
138 rv = DoSendRequestLoop(OK);
139 } else {
140 rv = ERR_IO_PENDING;
141 }
142 ActivatePipeline();
143 return rv;
144 }
145
146 int HttpPipelinedConnectionImpl::DoSendRequestLoop(int result) {
147 int rv = result;
148 do {
149 SendRequestState state = send_next_state_;
150 send_next_state_ = SEND_STATE_NONE;
151 switch (state) {
152 case SEND_STATE_NEXT_REQUEST:
153 rv = DoSendNextRequest(rv);
154 break;
155 case SEND_STATE_COMPLETE:
156 rv = DoSendComplete(rv);
157 break;
158 case SEND_STATE_UNUSABLE:
159 rv = DoEvictPendingSendRequests(rv);
160 break;
161 default:
162 NOTREACHED() << "bad send state: " << state;
163 rv = ERR_FAILED;
164 break;
165 }
166 } while (rv != ERR_IO_PENDING && send_next_state_ != SEND_STATE_NONE);
167 return rv;
168 }
169
170 void HttpPipelinedConnectionImpl::OnSendIOCallback(int result) {
171 CHECK(send_user_callback_);
172 DoSendRequestLoop(result);
173 }
174
175 int HttpPipelinedConnectionImpl::DoSendNextRequest(int result) {
176 CHECK(!deferred_request_queue_.empty());
177 const DeferredSendRequest& deferred_request = deferred_request_queue_.front();
178 CHECK(ContainsKey(stream_info_map_, deferred_request.pipeline_id));
179 if (stream_info_map_[deferred_request.pipeline_id].state == STREAM_CLOSED) {
180 deferred_request_queue_.pop();
181 if (deferred_request_queue_.empty()) {
182 send_next_state_ = SEND_STATE_NONE;
183 } else {
184 send_next_state_ = SEND_STATE_NEXT_REQUEST;
185 }
186 return OK;
187 }
188 CHECK(stream_info_map_[deferred_request.pipeline_id].parser.get());
189 int rv = stream_info_map_[deferred_request.pipeline_id].parser->SendRequest(
190 deferred_request.request_line,
191 deferred_request.headers,
192 deferred_request.request_body,
193 deferred_request.response,
194 &send_io_callback_);
195 // |result| == ERR_IO_PENDING means this function was *not* called on the same
196 // stack as SendRequest(). That means we returned ERR_IO_PENDING to
197 // SendRequest() earlier and will need to invoke its callback.
198 if (result == ERR_IO_PENDING || rv == ERR_IO_PENDING) {
199 send_user_callback_ = deferred_request.callback;
200 }
201 stream_info_map_[deferred_request.pipeline_id].state = STREAM_SENDING;
202 send_next_state_ = SEND_STATE_COMPLETE;
203 return rv;
204 }
205
206 int HttpPipelinedConnectionImpl::DoSendComplete(int result) {
207 CHECK(!deferred_request_queue_.empty());
208 const DeferredSendRequest& deferred_request = deferred_request_queue_.front();
209 CHECK_EQ(stream_info_map_[deferred_request.pipeline_id].state,
210 STREAM_SENDING);
211 request_order_.push(deferred_request.pipeline_id);
212 stream_info_map_[deferred_request.pipeline_id].state = STREAM_SENT;
213 deferred_request_queue_.pop();
214 if (result == ERR_SOCKET_NOT_CONNECTED && completed_one_request_) {
215 result = ERR_PIPELINE_EVICTION;
216 }
217 if (result < OK) {
218 send_next_state_ = SEND_STATE_UNUSABLE;
219 usable_ = false;
220 }
221 if (send_user_callback_) {
222 MessageLoop::current()->PostTask(
223 FROM_HERE,
224 method_factory_.NewRunnableMethod(
225 &HttpPipelinedConnectionImpl::FireUserCallback,
226 send_user_callback_,
227 result));
228 send_user_callback_ = NULL;
229 }
230 if (result < OK) {
231 return result;
232 }
233 if (deferred_request_queue_.empty()) {
234 send_next_state_ = SEND_STATE_NONE;
235 return OK;
236 }
237 send_next_state_ = SEND_STATE_NEXT_REQUEST;
238 return OK;
239 }
240
241 int HttpPipelinedConnectionImpl::DoEvictPendingSendRequests(int result) {
242 send_next_state_ = SEND_STATE_NONE;
243 while (!deferred_request_queue_.empty()) {
244 const DeferredSendRequest& evicted_send = deferred_request_queue_.front();
245 if (stream_info_map_[evicted_send.pipeline_id].state != STREAM_CLOSED) {
246 evicted_send.callback->Run(ERR_PIPELINE_EVICTION);
247 }
248 deferred_request_queue_.pop();
249 }
250 return result;
251 }
252
253 int HttpPipelinedConnectionImpl::ReadResponseHeaders(
254 int pipeline_id,
255 OldCompletionCallback* callback) {
256 CHECK(ContainsKey(stream_info_map_, pipeline_id));
257 CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_SENT);
258 CHECK(!stream_info_map_[pipeline_id].read_headers_callback);
259 if (!usable_) {
260 return ERR_PIPELINE_EVICTION;
261 }
262 stream_info_map_[pipeline_id].state = STREAM_READ_PENDING;
263 stream_info_map_[pipeline_id].read_headers_callback = callback;
264 if (read_next_state_ == READ_STATE_NONE) {
265 read_next_state_ = READ_STATE_NEXT_HEADERS;
266 return DoReadHeadersLoop(OK);
267 } else {
268 return ERR_IO_PENDING;
269 }
270 }
271
272 int HttpPipelinedConnectionImpl::DoReadHeadersLoop(int result) {
273 int rv = result;
274 do {
275 ReadHeadersState state = read_next_state_;
276 read_next_state_ = READ_STATE_NONE;
277 switch (state) {
278 case READ_STATE_NEXT_HEADERS:
279 rv = DoReadNextHeaders(rv);
280 break;
281 case READ_STATE_COMPLETE:
282 rv = DoReadHeadersComplete(rv);
283 break;
284 case READ_STATE_WAITING_FOR_CLOSE:
285 rv = DoReadWaitingForClose(rv);
286 return rv;
287 case READ_STATE_STREAM_CLOSED:
288 rv = DoReadStreamClosed();
289 break;
290 case READ_STATE_UNUSABLE:
291 rv = DoEvictPendingReadHeaders(rv);
292 break;
293 case READ_STATE_NONE:
294 break;
295 default:
296 NOTREACHED() << "bad read state";
297 rv = ERR_FAILED;
298 break;
299 }
300 } while (rv != ERR_IO_PENDING && read_next_state_ != READ_STATE_NONE);
301 return rv;
302 }
303
304 void HttpPipelinedConnectionImpl::OnReadIOCallback(int result) {
305 CHECK(read_user_callback_);
306 DoReadHeadersLoop(result);
307 }
308
309 int HttpPipelinedConnectionImpl::DoReadNextHeaders(int result) {
310 CHECK(!request_order_.empty());
311 int pipeline_id = request_order_.front();
312 CHECK(ContainsKey(stream_info_map_, pipeline_id));
313 if (stream_info_map_[pipeline_id].state == STREAM_CLOSED) {
314 // Since nobody will read whatever data is on the pipeline associated with
315 // this closed request, we must shut down the rest of the pipeline.
316 read_next_state_ = READ_STATE_UNUSABLE;
317 return OK;
318 }
319 if (stream_info_map_[pipeline_id].read_headers_callback == NULL) {
320 return ERR_IO_PENDING;
321 }
322 CHECK(stream_info_map_[pipeline_id].parser.get());
323
324 if (result == ERR_IO_PENDING) {
325 CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_ACTIVE);
326 } else {
327 CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_READ_PENDING);
328 stream_info_map_[pipeline_id].state = STREAM_ACTIVE;
329 }
330
331 int rv = stream_info_map_[pipeline_id].parser->ReadResponseHeaders(
332 &read_io_callback_);
333 if (rv == ERR_IO_PENDING) {
334 read_next_state_ = READ_STATE_COMPLETE;
335 read_user_callback_ = stream_info_map_[pipeline_id].read_headers_callback;
336 } else if (rv < OK) {
337 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
338 if (rv == ERR_SOCKET_NOT_CONNECTED && completed_one_request_)
339 rv = ERR_PIPELINE_EVICTION;
340 } else {
341 CHECK_LE(OK, rv);
342 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
343 }
344
345 // |result| == ERR_IO_PENDING means this function was *not* called on the same
346 // stack as ReadResponseHeaders(). That means we returned ERR_IO_PENDING to
347 // ReadResponseHeaders() earlier and now need to invoke its callback.
348 if (rv != ERR_IO_PENDING && result == ERR_IO_PENDING) {
349 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
350 read_user_callback_ = stream_info_map_[pipeline_id].read_headers_callback;
351 MessageLoop::current()->PostTask(
352 FROM_HERE,
353 method_factory_.NewRunnableMethod(
354 &HttpPipelinedConnectionImpl::FireUserCallback,
355 read_user_callback_,
356 rv));
357 }
358 return rv;
359 }
360
361 int HttpPipelinedConnectionImpl::DoReadHeadersComplete(int result) {
362 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
363 if (read_user_callback_) {
364 MessageLoop::current()->PostTask(
365 FROM_HERE,
366 method_factory_.NewRunnableMethod(
367 &HttpPipelinedConnectionImpl::FireUserCallback,
368 read_user_callback_,
369 result));
370 read_user_callback_ = NULL;
371 }
372 return result;
373 }
374
375 int HttpPipelinedConnectionImpl::DoReadWaitingForClose(int result) {
376 read_next_state_ = READ_STATE_WAITING_FOR_CLOSE;
377 return result;
378 }
379
380 int HttpPipelinedConnectionImpl::DoReadStreamClosed() {
381 CHECK(!request_order_.empty());
382 int pipeline_id = request_order_.front();
383 CHECK(ContainsKey(stream_info_map_, pipeline_id));
384 CHECK_EQ(stream_info_map_[pipeline_id].state, STREAM_CLOSED);
385 CHECK(stream_info_map_[pipeline_id].read_headers_callback);
386 stream_info_map_[pipeline_id].read_headers_callback = NULL;
387 request_order_.pop();
388 if (!usable_) {
389 read_next_state_ = READ_STATE_UNUSABLE;
390 return OK;
391 } else {
392 completed_one_request_ = true;
393 if (!request_order_.empty()) {
394 int next_pipeline_id = request_order_.front();
395 CHECK(ContainsKey(stream_info_map_, next_pipeline_id));
396 if (stream_info_map_[next_pipeline_id].read_headers_callback) {
397 stream_info_map_[next_pipeline_id].state = STREAM_ACTIVE;
398 read_next_state_ = READ_STATE_NEXT_HEADERS;
399 MessageLoop::current()->PostTask(
400 FROM_HERE,
401 method_factory_.NewRunnableMethod(
402 &HttpPipelinedConnectionImpl::DoReadHeadersLoop,
403 ERR_IO_PENDING));
404 return ERR_IO_PENDING; // Wait for the task to fire.
405 }
406 }
407 read_next_state_ = READ_STATE_NONE;
408 return OK;
409 }
410 }
411
412 int HttpPipelinedConnectionImpl::DoEvictPendingReadHeaders(int result) {
413 while (!request_order_.empty()) {
414 int evicted_id = request_order_.front();
415 request_order_.pop();
416 if (stream_info_map_[evicted_id].read_headers_callback == NULL) {
417 continue;
418 }
419 if (stream_info_map_[evicted_id].state != STREAM_CLOSED) {
420 MessageLoop::current()->PostTask(
421 FROM_HERE,
422 method_factory_.NewRunnableMethod(
423 &HttpPipelinedConnectionImpl::FireUserCallback,
424 stream_info_map_[evicted_id].read_headers_callback,
425 ERR_PIPELINE_EVICTION));
426 }
427 stream_info_map_[evicted_id].read_headers_callback = NULL;
428 }
429 read_next_state_ = READ_STATE_NONE;
430 return result;
431 }
432
433 void HttpPipelinedConnectionImpl::Close(int pipeline_id,
434 bool not_reusable) {
435 CHECK(ContainsKey(stream_info_map_, pipeline_id));
436 switch (stream_info_map_[pipeline_id].state) {
437 case STREAM_CREATED:
438 stream_info_map_[pipeline_id].state = STREAM_UNUSED;
439 break;
440
441 case STREAM_BOUND:
442 stream_info_map_[pipeline_id].state = STREAM_CLOSED;
443 break;
444
445 case STREAM_SENDING:
446 usable_ = false;
447 stream_info_map_[pipeline_id].state = STREAM_CLOSED;
448 send_user_callback_ = NULL;
449 send_next_state_ = SEND_STATE_UNUSABLE;
450 DoSendRequestLoop(OK);
451 break;
452
453 case STREAM_SENT:
454 case STREAM_READ_PENDING:
455 usable_ = false;
456 stream_info_map_[pipeline_id].state = STREAM_CLOSED;
457 if (read_next_state_ == READ_STATE_NONE) {
458 read_next_state_ = READ_STATE_UNUSABLE;
459 DoReadHeadersLoop(OK);
460 }
461 break;
462
463 case STREAM_ACTIVE:
464 stream_info_map_[pipeline_id].state = STREAM_CLOSED;
465 if (not_reusable) {
466 usable_ = false;
467 }
468 read_next_state_ = READ_STATE_STREAM_CLOSED;
469 read_user_callback_ = NULL;
470 DoReadHeadersLoop(OK);
471 break;
472
473 case STREAM_CLOSED:
474 case STREAM_UNUSED:
475 // TODO(simonjam): Why is Close() sometimes called twice?
476 break;
477
478 default:
479 NOTREACHED();
480 break;
481 }
482 }
483
484 int HttpPipelinedConnectionImpl::ReadResponseBody(
485 int pipeline_id,
486 IOBuffer* buf,
487 int buf_len,
488 OldCompletionCallback* callback) {
489 CHECK(ContainsKey(stream_info_map_, pipeline_id));
490 CHECK(!request_order_.empty());
491 CHECK_EQ(pipeline_id, request_order_.front());
492 CHECK(stream_info_map_[pipeline_id].parser.get());
493 return stream_info_map_[pipeline_id].parser->ReadResponseBody(
494 buf, buf_len, callback);
495 }
496
497 uint64 HttpPipelinedConnectionImpl::GetUploadProgress(int pipeline_id) const {
498 CHECK(ContainsKey(stream_info_map_, pipeline_id));
499 CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
500 return stream_info_map_.find(pipeline_id)->second.parser->GetUploadProgress();
501 }
502
503 HttpResponseInfo* HttpPipelinedConnectionImpl::GetResponseInfo(
504 int pipeline_id) {
505 CHECK(ContainsKey(stream_info_map_, pipeline_id));
506 CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
507 return stream_info_map_.find(pipeline_id)->second.parser->GetResponseInfo();
508 }
509
510 bool HttpPipelinedConnectionImpl::IsResponseBodyComplete(
511 int pipeline_id) const {
512 CHECK(ContainsKey(stream_info_map_, pipeline_id));
513 CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
514 return stream_info_map_.find(pipeline_id)->second.parser->
515 IsResponseBodyComplete();
516 }
517
518 bool HttpPipelinedConnectionImpl::CanFindEndOfResponse(int pipeline_id) const {
519 CHECK(ContainsKey(stream_info_map_, pipeline_id));
520 CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
521 return stream_info_map_.find(pipeline_id)->second.parser->
522 CanFindEndOfResponse();
523 }
524
525 bool HttpPipelinedConnectionImpl::IsMoreDataBuffered(int pipeline_id) const {
526 CHECK(ContainsKey(stream_info_map_, pipeline_id));
527 return read_buf_->offset() != 0;
528 }
529
530 bool HttpPipelinedConnectionImpl::IsConnectionReused(int pipeline_id) const {
531 CHECK(ContainsKey(stream_info_map_, pipeline_id));
532 if (pipeline_id > 1) {
533 return true;
534 }
535 ClientSocketHandle::SocketReuseType reuse_type = connection_->reuse_type();
536 return connection_->is_reused() ||
537 reuse_type == ClientSocketHandle::UNUSED_IDLE;
538 }
539
540 void HttpPipelinedConnectionImpl::SetConnectionReused(int pipeline_id) {
541 CHECK(ContainsKey(stream_info_map_, pipeline_id));
542 connection_->set_is_reused(true);
543 }
544
545 void HttpPipelinedConnectionImpl::GetSSLInfo(int pipeline_id,
546 SSLInfo* ssl_info) {
547 CHECK(ContainsKey(stream_info_map_, pipeline_id));
548 CHECK(stream_info_map_[pipeline_id].parser.get());
549 return stream_info_map_[pipeline_id].parser->GetSSLInfo(ssl_info);
550 }
551
552 void HttpPipelinedConnectionImpl::GetSSLCertRequestInfo(
553 int pipeline_id,
554 SSLCertRequestInfo* cert_request_info) {
555 CHECK(ContainsKey(stream_info_map_, pipeline_id));
556 CHECK(stream_info_map_[pipeline_id].parser.get());
557 return stream_info_map_[pipeline_id].parser->GetSSLCertRequestInfo(
558 cert_request_info);
559 }
560
561 void HttpPipelinedConnectionImpl::FireUserCallback(
562 OldCompletionCallback* callback,
563 int result) {
564 CHECK(callback);
565 callback->Run(result);
566 }
567
568 int HttpPipelinedConnectionImpl::depth() const {
569 return stream_info_map_.size();
570 }
571
572 bool HttpPipelinedConnectionImpl::usable() const {
573 return usable_;
574 }
575
576 bool HttpPipelinedConnectionImpl::active() const {
577 return active_;
578 }
579
580 const SSLConfig& HttpPipelinedConnectionImpl::used_ssl_config() const {
581 return used_ssl_config_;
582 }
583
584 const ProxyInfo& HttpPipelinedConnectionImpl::used_proxy_info() const {
585 return used_proxy_info_;
586 }
587
588 const NetLog::Source& HttpPipelinedConnectionImpl::source() const {
589 return net_log_.source();
590 }
591
592 bool HttpPipelinedConnectionImpl::was_npn_negotiated() const {
593 return was_npn_negotiated_;
594 }
595
596 HttpPipelinedConnectionImpl::DeferredSendRequest::DeferredSendRequest() {
597 }
598
599 HttpPipelinedConnectionImpl::DeferredSendRequest::~DeferredSendRequest() {
600 }
601
602 HttpPipelinedConnectionImpl::StreamInfo::StreamInfo()
603 : read_headers_callback(NULL),
604 state(STREAM_CREATED) {
605 }
606
607 HttpPipelinedConnectionImpl::StreamInfo::~StreamInfo() {
608 }
609
610 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698