OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "net/flip/flip_session.h" | 5 #include "net/flip/flip_session.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 #include "net/http/http_response_info.h" | 21 #include "net/http/http_response_info.h" |
22 #include "net/socket/client_socket_factory.h" | 22 #include "net/socket/client_socket_factory.h" |
23 #include "net/socket/ssl_client_socket.h" | 23 #include "net/socket/ssl_client_socket.h" |
24 #include "net/tools/dump_cache/url_to_filename_encoder.h" | 24 #include "net/tools/dump_cache/url_to_filename_encoder.h" |
25 | 25 |
26 namespace net { | 26 namespace net { |
27 | 27 |
28 // static | 28 // static |
29 scoped_ptr<FlipSessionPool> FlipSession::session_pool_; | 29 scoped_ptr<FlipSessionPool> FlipSession::session_pool_; |
30 bool FlipSession::use_ssl_ = true; | 30 bool FlipSession::use_ssl_ = true; |
31 int PrioritizedIOBuffer::order_ = 0; | |
32 | 31 |
33 FlipSession* FlipSession::GetFlipSession( | 32 FlipSession* FlipSession::GetFlipSession( |
34 const HostResolver::RequestInfo& info, | 33 const HostResolver::RequestInfo& info, |
35 HttpNetworkSession* session) { | 34 HttpNetworkSession* session) { |
36 if (!session_pool_.get()) | 35 if (!session_pool_.get()) |
37 session_pool_.reset(new FlipSessionPool()); | 36 session_pool_.reset(new FlipSessionPool()); |
38 return session_pool_->Get(info, session); | 37 return session_pool_->Get(info, session); |
39 } | 38 } |
40 | 39 |
41 FlipSession::FlipSession(std::string host, HttpNetworkSession* session) | 40 FlipSession::FlipSession(std::string host, HttpNetworkSession* session) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 static const std::string kHttpProtocolVersion("HTTP/1.1"); | 106 static const std::string kHttpProtocolVersion("HTTP/1.1"); |
108 | 107 |
109 HttpUtil::HeadersIterator it(info->extra_headers.begin(), | 108 HttpUtil::HeadersIterator it(info->extra_headers.begin(), |
110 info->extra_headers.end(), | 109 info->extra_headers.end(), |
111 "\r\n"); | 110 "\r\n"); |
112 while (it.GetNext()) { | 111 while (it.GetNext()) { |
113 std::string name = StringToLowerASCII(it.name()); | 112 std::string name = StringToLowerASCII(it.name()); |
114 (*headers)[name] = it.values(); | 113 (*headers)[name] = it.values(); |
115 } | 114 } |
116 | 115 |
117 #undef DIVERT_URLS_TO_TEST_SERVER | |
118 #ifdef DIVERT_URLS_TO_TEST_SERVER | |
119 // TODO(mbelshe): Figure out how to remove this. This is just for hooking | |
120 // up to a test server. | |
121 // For testing content on our test server, we modify the URL. | |
122 GURL url = info->url; | |
123 FilePath path(UrlToFilenameEncoder::Encode(url.spec(), FilePath())); | |
124 | |
125 // We do the unusual conversion from a FilePath::StringType to | |
126 // an ascii string. Recognize that StringType is a wstring on windows, | |
127 // so a failure is technically possible, but this is just used as a test | |
128 // case, so it's okay. This code will be deleted. | |
129 std::string hack_url("/"); | |
130 #if defined(OS_WIN) | |
131 hack_url.append(WideToASCII(path.value())); | |
132 #else | |
133 hack_url.append(path.value()); | |
134 #endif | |
135 | |
136 // switch backslashes. HACK | |
137 std::string::size_type pos(0); | |
138 while ((pos = hack_url.find('\\', pos)) != std::string::npos) { | |
139 hack_url.replace(pos, 1, "/"); | |
140 pos += 1; | |
141 } | |
142 #else | |
143 std::string hack_url(info->url.PathForRequest()); | |
144 #endif // REWRITE_URLS | |
145 | |
146 (*headers)["method"] = info->method; | 116 (*headers)["method"] = info->method; |
147 (*headers)["url"] = hack_url; | 117 (*headers)["url"] = info->url.PathForRequest(); |
148 (*headers)["version"] = kHttpProtocolVersion; | 118 (*headers)["version"] = kHttpProtocolVersion; |
149 (*headers)["host"] = GetHostAndOptionalPort(info->url); | 119 (*headers)["host"] = GetHostAndOptionalPort(info->url); |
150 if (info->user_agent.length()) | 120 if (info->user_agent.length()) |
151 (*headers)["user-agent"] = info->user_agent; | 121 (*headers)["user-agent"] = info->user_agent; |
152 if (!info->referrer.is_empty()) | 122 if (!info->referrer.is_empty()) |
153 (*headers)["referer"] = info->referrer.spec(); | 123 (*headers)["referer"] = info->referrer.spec(); |
154 | 124 |
155 // Honor load flags that impact proxy caches. | 125 // Honor load flags that impact proxy caches. |
156 if (info->load_flags & LOAD_BYPASS_CACHE) { | 126 if (info->load_flags & LOAD_BYPASS_CACHE) { |
157 (*headers)["pragma"] = "no-cache"; | 127 (*headers)["pragma"] = "no-cache"; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 flags = flip::CONTROL_FLAG_FIN; | 197 flags = flip::CONTROL_FLAG_FIN; |
228 | 198 |
229 // Create a SYN_STREAM packet and add to the output queue. | 199 // Create a SYN_STREAM packet and add to the output queue. |
230 flip::FlipSynStreamControlFrame* syn_frame = | 200 flip::FlipSynStreamControlFrame* syn_frame = |
231 flip_framer_.CreateSynStream(stream_id, priority, flags, false, &headers); | 201 flip_framer_.CreateSynStream(stream_id, priority, flags, false, &headers); |
232 int length = sizeof(flip::FlipFrame) + syn_frame->length(); | 202 int length = sizeof(flip::FlipFrame) + syn_frame->length(); |
233 IOBufferWithSize* buffer = | 203 IOBufferWithSize* buffer = |
234 new IOBufferWithSize(length); | 204 new IOBufferWithSize(length); |
235 memcpy(buffer->data(), syn_frame, length); | 205 memcpy(buffer->data(), syn_frame, length); |
236 delete[] syn_frame; | 206 delete[] syn_frame; |
237 queue_.push(PrioritizedIOBuffer(buffer, priority)); | 207 queue_.push(FlipIOBuffer(buffer, priority, stream)); |
238 | 208 |
239 static StatsCounter flip_requests("flip.requests"); | 209 static StatsCounter flip_requests("flip.requests"); |
240 flip_requests.Increment(); | 210 flip_requests.Increment(); |
241 | 211 |
242 LOG(INFO) << "FETCHING: " << delegate->request()->url.spec(); | 212 LOG(INFO) << "FETCHING: " << delegate->request()->url.spec(); |
243 | 213 |
244 | 214 |
245 // TODO(mbelshe): Implement POST Data here | 215 // TODO(mbelshe): Implement POST Data here |
246 | 216 |
247 // Schedule to write to the socket after we've made it back | 217 // Schedule to write to the socket after we've made it back |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 ReadSocket(); | 340 ReadSocket(); |
371 } | 341 } |
372 | 342 |
373 void FlipSession::OnWriteComplete(int result) { | 343 void FlipSession::OnWriteComplete(int result) { |
374 DCHECK(write_pending_); | 344 DCHECK(write_pending_); |
375 write_pending_ = false; | 345 write_pending_ = false; |
376 | 346 |
377 LOG(INFO) << "Flip write complete (result=" << result << ")"; | 347 LOG(INFO) << "Flip write complete (result=" << result << ")"; |
378 | 348 |
379 if (result >= 0) { | 349 if (result >= 0) { |
350 // TODO(mbelshe) Verify that we wrote ALL the bytes we needed to. | |
351 // The code current is broken in the case of a partial write. | |
352 DCHECK_EQ(static_cast<size_t>(result), in_flight_write_.size()); | |
353 | |
380 // Cleanup the write which just completed. | 354 // Cleanup the write which just completed. |
381 in_flight_write_.release(); | 355 in_flight_write_.release(); |
382 | 356 |
383 // Write more data. We're already in a continuation, so we can | 357 // Write more data. We're already in a continuation, so we can |
384 // go ahead and write it immediately (without going back to the | 358 // go ahead and write it immediately (without going back to the |
385 // message loop). | 359 // message loop). |
386 WriteSocketLater(); | 360 WriteSocketLater(); |
387 } else { | 361 } else { |
388 // TODO(mbelshe): Deal with result < 0 error case. | 362 // TODO(mbelshe): Deal with result < 0 error case. |
389 NOTIMPLEMENTED(); | 363 NOTIMPLEMENTED(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
430 delayed_write_pending_ = false; | 404 delayed_write_pending_ = false; |
431 | 405 |
432 // If the socket isn't connected yet, just wait; we'll get called | 406 // If the socket isn't connected yet, just wait; we'll get called |
433 // again when the socket connection completes. | 407 // again when the socket connection completes. |
434 if (!connection_ready_) | 408 if (!connection_ready_) |
435 return; | 409 return; |
436 | 410 |
437 if (write_pending_) // Another write is in progress still. | 411 if (write_pending_) // Another write is in progress still. |
438 return; | 412 return; |
439 | 413 |
414 // Loop sending frames until we've sent everything or until the write | |
415 // returns ERR_IO_PENDING. | |
wtc
2009/11/03 23:28:13
This comment needs updating to match the new code.
| |
440 while (queue_.size()) { | 416 while (queue_.size()) { |
441 const size_t kMaxSegmentSize = 1430; | 417 // Grab the next FlipFrame to send. |
442 const size_t kMaxPayload = 4 * kMaxSegmentSize; | 418 FlipIOBuffer next_buffer = queue_.top(); |
443 size_t max_size = std::max(kMaxPayload, queue_.top().size()); | 419 queue_.pop(); |
444 | 420 |
445 size_t bytes = 0; | 421 // We've deferred compression until just before we write it to the socket, |
446 // If we have multiple IOs to do, accumulate up to 4 MSS's worth of data | 422 // which is now. |
447 // and send them in batch. | 423 flip::FlipFrame* uncompressed_frame = |
448 IOBufferWithSize* buffer = new IOBufferWithSize(max_size); | 424 reinterpret_cast<flip::FlipFrame*>(next_buffer.buffer()->data()); |
449 while (queue_.size() && bytes < max_size) { | 425 scoped_array<flip::FlipFrame> compressed_frame( |
450 PrioritizedIOBuffer next_buffer = queue_.top(); | 426 flip_framer_.CompressFrame(uncompressed_frame)); |
427 size_t size = compressed_frame.get()->length() + sizeof(flip::FlipFrame); | |
451 | 428 |
452 // Now that we're outputting the frame, we can finally compress it. | 429 |
wtc
2009/11/03 23:28:13
Nit: you added an extra blank line.
| |
453 flip::FlipFrame* uncompressed_frame = | 430 DCHECK(size > 0); |
454 reinterpret_cast<flip::FlipFrame*>(next_buffer.buffer()->data()); | 431 |
455 scoped_array<flip::FlipFrame> compressed_frame( | 432 // TODO(mbelshe): We have too much copying of data here. |
456 flip_framer_.CompressFrame(uncompressed_frame)); | 433 IOBufferWithSize* buffer = new IOBufferWithSize(size); |
457 size_t size = compressed_frame.get()->length() + sizeof(flip::FlipFrame); | 434 memcpy(buffer->data(), compressed_frame.get(), size); |
458 if (bytes + size > kMaxPayload) | 435 |
459 break; | 436 // Attempt to send the frame. |
460 memcpy(buffer->data() + bytes, compressed_frame.get(), size); | 437 in_flight_write_ = FlipIOBuffer(buffer, 0, next_buffer.stream()); |
461 bytes += size; | |
462 queue_.pop(); | |
463 next_buffer.release(); | |
464 } | |
465 DCHECK(bytes > 0); | |
466 in_flight_write_ = PrioritizedIOBuffer(buffer, 0); | |
467 write_pending_ = true; | 438 write_pending_ = true; |
468 | |
469 int rv = connection_.socket()->Write(in_flight_write_.buffer(), | 439 int rv = connection_.socket()->Write(in_flight_write_.buffer(), |
470 bytes, &write_callback_); | 440 size, &write_callback_); |
471 if (rv == net::ERR_IO_PENDING) | 441 if (rv == net::ERR_IO_PENDING) |
472 break; | 442 break; |
443 | |
444 // We sent the frame successfully. | |
473 OnWriteComplete(rv); | 445 OnWriteComplete(rv); |
446 | |
447 // TODO(mbelshe): Test this error case. | |
448 if (rv < 0) | |
wtc
2009/11/03 23:28:13
I agree with this new code. We may need to do som
| |
449 break; | |
474 } | 450 } |
475 } | 451 } |
476 | 452 |
477 void FlipSession::CloseAllStreams(net::Error code) { | 453 void FlipSession::CloseAllStreams(net::Error code) { |
478 LOG(INFO) << "Closing all FLIP Streams"; | 454 LOG(INFO) << "Closing all FLIP Streams"; |
479 | 455 |
480 static StatsCounter abandoned_streams("flip.abandoned_streams"); | 456 static StatsCounter abandoned_streams("flip.abandoned_streams"); |
481 static StatsCounter abandoned_push_streams("flip.abandoned_push_streams"); | 457 static StatsCounter abandoned_push_streams("flip.abandoned_push_streams"); |
482 | 458 |
483 if (active_streams_.size()) { | 459 if (active_streams_.size()) { |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
728 DeactivateStream(stream_id); | 704 DeactivateStream(stream_id); |
729 delete stream; | 705 delete stream; |
730 } | 706 } |
731 } | 707 } |
732 | 708 |
733 void FlipSession::OnLameDuck() { | 709 void FlipSession::OnLameDuck() { |
734 NOTIMPLEMENTED(); | 710 NOTIMPLEMENTED(); |
735 } | 711 } |
736 | 712 |
737 } // namespace net | 713 } // namespace net |
OLD | NEW |