Chromium Code Reviews| 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 |