diff options
author | nsylvain@chromium.org <nsylvain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-17 23:33:29 +0000 |
---|---|---|
committer | nsylvain@chromium.org <nsylvain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-17 23:33:29 +0000 |
commit | fa958d0c51c5ddf94b370c16ca01f1a606aa405e (patch) | |
tree | ea0e31753be212c395e11017048f7a380466c89c /net | |
parent | 637118fb52d4736b5ecef1253b4c879f5fdaf00e (diff) | |
download | chromium_src-fa958d0c51c5ddf94b370c16ca01f1a606aa405e.zip chromium_src-fa958d0c51c5ddf94b370c16ca01f1a606aa405e.tar.gz chromium_src-fa958d0c51c5ddf94b370c16ca01f1a606aa405e.tar.bz2 |
Revert change 26484 "This is not production code; landing some experimental network code." because
it broke the "check_deps" step on Chromium XP
Review URL: http://codereview.chromium.org/212015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26524 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/flip/flip_bitmasks.h | 16 | ||||
-rw-r--r-- | net/flip/flip_frame_builder.cc | 184 | ||||
-rw-r--r-- | net/flip/flip_frame_builder.h | 184 | ||||
-rw-r--r-- | net/flip/flip_framer.cc | 732 | ||||
-rw-r--r-- | net/flip/flip_framer.h | 228 | ||||
-rw-r--r-- | net/flip/flip_framer_test.cc | 251 | ||||
-rw-r--r-- | net/flip/flip_network_transaction.cc | 414 | ||||
-rw-r--r-- | net/flip/flip_network_transaction.h | 142 | ||||
-rw-r--r-- | net/flip/flip_network_transaction_unittest.cc | 190 | ||||
-rw-r--r-- | net/flip/flip_protocol.h | 203 | ||||
-rw-r--r-- | net/flip/flip_session.cc | 762 | ||||
-rw-r--r-- | net/flip/flip_session.h | 216 | ||||
-rw-r--r-- | net/flip/flip_session_pool.cc | 99 | ||||
-rw-r--r-- | net/flip/flip_session_pool.h | 57 | ||||
-rw-r--r-- | net/flip/flip_session_unittest.cc | 55 | ||||
-rw-r--r-- | net/flip/flip_transaction_factory.h | 36 |
16 files changed, 0 insertions, 3769 deletions
diff --git a/net/flip/flip_bitmasks.h b/net/flip/flip_bitmasks.h deleted file mode 100644 index 8f139e0..0000000 --- a/net/flip/flip_bitmasks.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_FLIP_FLIP_BITMASKS_H_ -#define NET_FLIP_FLIP_BITMASKS_H_ - -namespace flip { - -const int kStreamIdMask = 0x7fffffff; // StreamId mask from the FlipHeader -const int kControlFlagMask = 0x8000; // Control flag mask from the FlipHeader -const int kPriorityMask = 0xc0; // Priority mask from the SYN_FRAME -} // flip - -#endif // NET_FLIP_FLIP_BITMASKS_H_ - diff --git a/net/flip/flip_frame_builder.cc b/net/flip/flip_frame_builder.cc deleted file mode 100644 index 28d156c..0000000 --- a/net/flip/flip_frame_builder.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <limits> - -#include "flip_frame_builder.h" // cross-google3 directory naming. -#include "flip_protocol.h" - -namespace flip { - - // We mark a read only FlipFrameBuilder with a special capacity_. -static const size_t kCapacityReadOnly = std::numeric_limits<size_t>::max(); - -FlipFrameBuilder::FlipFrameBuilder() - : buffer_(NULL), - capacity_(0), - length_(0), - variable_buffer_offset_(0) { - Resize(kInitialPayload); -} - -FlipFrameBuilder::FlipFrameBuilder(const char* data, int data_len) - : buffer_(const_cast<char*>(data)), - capacity_(kCapacityReadOnly), - length_(data_len), - variable_buffer_offset_(0) { -} - -FlipFrameBuilder::~FlipFrameBuilder() { - if (capacity_ != kCapacityReadOnly) - delete[] buffer_; -} - -bool FlipFrameBuilder::ReadUInt16(void** iter, uint16* result) const { - DCHECK(iter); - if (!*iter) - *iter = const_cast<char*>(buffer_); - - if (!IteratorHasRoomFor(*iter, sizeof(*result))) - return false; - - *result = ntohs(*(reinterpret_cast<uint16*>(*iter))); - - UpdateIter(iter, sizeof(*result)); - return true; -} - -bool FlipFrameBuilder::ReadUInt32(void** iter, uint32* result) const { - DCHECK(iter); - if (!*iter) - *iter = const_cast<char*>(buffer_); - - if (!IteratorHasRoomFor(*iter, sizeof(*result))) - return false; - - *result = ntohl(*(reinterpret_cast<uint32*>(*iter))); - - UpdateIter(iter, sizeof(*result)); - return true; -} - -bool FlipFrameBuilder::ReadString(void** iter, std::string* result) const { - DCHECK(iter); - - uint16 len; - if (!ReadUInt16(iter, &len)) { - VLOG(1) << "Unable to read length"; - return false; - } - if (!IteratorHasRoomFor(*iter, len)) { - VLOG(1) << "!IteratorHasRoomFor"; - return false; - } - - char* chars = reinterpret_cast<char*>(*iter); - result->assign(chars, len); - - UpdateIter(iter, len); - return true; -} - -bool FlipFrameBuilder::ReadBytes(void** iter, const char** data, - uint16 length) const { - DCHECK(iter); - DCHECK(data); - - if (!IteratorHasRoomFor(*iter, length)) - return false; - - *data = reinterpret_cast<const char*>(*iter); - - UpdateIter(iter, length); - return true; -} - -bool FlipFrameBuilder::ReadData(void** iter, const char** data, - uint16* length) const { - DCHECK(iter); - DCHECK(data); - DCHECK(length); - - if (!ReadUInt16(iter, length)) - return false; - - return ReadBytes(iter, data, *length); -} - -char* FlipFrameBuilder::BeginWrite(size_t length) { - size_t offset = length_; - size_t needed_size = length_ + length; - if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) - return NULL; - -#ifdef ARCH_CPU_64_BITS - DCHECK_LE(length, std::numeric_limits<uint32>::max()); -#endif - - return buffer_ + offset; -} - -void FlipFrameBuilder::EndWrite(char* dest, int length) { -} - -bool FlipFrameBuilder::WriteBytes(const void* data, uint16 data_len) { - DCHECK(capacity_ != kCapacityReadOnly); - - char* dest = BeginWrite(data_len); - if (!dest) - return false; - - memcpy(dest, data, data_len); - - EndWrite(dest, data_len); - length_ += data_len; - return true; -} - -bool FlipFrameBuilder::WriteString(const std::string& value) { - if (value.size() > 0xffff) - return false; - - if (!WriteUInt16(static_cast<int>(value.size()))) - return false; - - return WriteBytes(value.data(), static_cast<uint16>(value.size())); -} - -char* FlipFrameBuilder::BeginWriteData(uint16 length) { - DCHECK_EQ(variable_buffer_offset_, 0U) << - "There can only be one variable buffer in a FlipFrameBuilder"; - - if (!WriteUInt16(length)) - return false; - - char *data_ptr = BeginWrite(length); - if (!data_ptr) - return NULL; - - variable_buffer_offset_ = data_ptr - buffer_ - sizeof(int); - - // EndWrite doesn't necessarily have to be called after the write operation, - // so we call it here to pad out what the caller will eventually write. - EndWrite(data_ptr, length); - return data_ptr; -} - -bool FlipFrameBuilder::Resize(size_t new_capacity) { - if (new_capacity < capacity_) - return true; - - char* p = new char[new_capacity]; - if (buffer_) { - memcpy(p, buffer_, capacity_); - delete[] buffer_; - } - if (!p && new_capacity > 0) - return false; - buffer_ = p; - capacity_ = new_capacity; - return true; -} - -} // namespace flip diff --git a/net/flip/flip_frame_builder.h b/net/flip/flip_frame_builder.h deleted file mode 100644 index 809f451..0000000 --- a/net/flip/flip_frame_builder.h +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_FLIP_FRAME_BUILDER_H_ -#define NET_FLIP_FRAME_BUILDER_H_ - -#ifdef WIN32 -#include <winsock2.h> // for htonl() functions -#else -#include <arpa/inet.h> -#endif - -#include <string> - -#include "base/logging.h" -#include "flip_protocol.h" // cross-google3 directory naming. - -#ifdef WIN32 -#undef VLOG -#define VLOG(x) LOG_IF(INFO, false) -#endif // WIN32 - -namespace flip { - -// This class provides facilities for basic binary value packing and unpacking -// into Flip frames. Note: this is similar to Chrome's pickle class, but is -// simplified to work in both the client and server, and without excess -// padding. -// -// The FlipFrameBuilder supports appending primitive values (int, string, etc) -// to a frame instance. The FlipFrameBuilder grows its internal memory buffer -// dynamically to hold the sequence of primitive values. The internal memory -// buffer is exposed as the "data" of the FlipFrameBuilder. -// -// When reading from a FlipFrameBuilder the consumer must know what value types -// to read and in what order to read them as the FlipFrameBuilder does not keep -// track of the type of data written to it. -class FlipFrameBuilder { - public: - FlipFrameBuilder(); - ~FlipFrameBuilder(); - - // Initializes a FlipFrameBuilder from a const block of data. The data is - // not copied; instead the data is merely referenced by this - // FlipFrameBuilder. Only const methods should be used when initialized - // this way. - FlipFrameBuilder(const char* data, int data_len); - - // Returns the size of the FlipFrameBuilder's data. - int length() const { return length_; } - - // Returns the data for this FlipFrameBuilder. - const FlipFrame* data() const { - return reinterpret_cast<FlipFrame*>(buffer_); - } - - // Takes the buffer from the FlipFrameBuilder. - FlipFrame* take() { - FlipFrame* rv = reinterpret_cast<FlipFrame*>(buffer_); - buffer_ = NULL; - capacity_ = 0; - length_ = 0; - return rv; - } - - // Methods for reading the payload of the FlipFrameBuilder. To read from the - // start of the FlipFrameBuilder, initialize *iter to NULL. If successful, - // these methods return true. Otherwise, false is returned to indicate that - // the result could not be extracted. - bool ReadUInt16(void** iter, uint16* result) const; - bool ReadUInt32(void** iter, uint32* result) const; - bool ReadString(void** iter, std::string* result) const; - bool ReadBytes(void** iter, const char** data, uint16 length) const; - bool ReadData(void** iter, const char** data, uint16* length) const; - - // Methods for adding to the payload. These values are appended to the end - // of the FlipFrameBuilder payload. When reading values, you must read them - // in the order they were added. Note - binary integers are converted from - // host to network form. - bool WriteUInt16(uint16 value) { - value = htons(value); - return WriteBytes(&value, sizeof(value)); - } - bool WriteUInt32(uint32 value) { - value = htonl(value); - return WriteBytes(&value, sizeof(value)); - } - bool WriteString(const std::string& value); - bool WriteBytes(const void* data, uint16 data_len); - - // Write an integer to a particular offset in the data buffer. - bool WriteUInt32ToOffset(int offset, uint32 value) { - if (offset + sizeof(value) > length_) - return false; - value = htonl(value); - char *ptr = buffer_ + offset; - memcpy(ptr, &value, sizeof(value)); - return true; - } - - // Allows the caller to write data directly into the FlipFrameBuilder. - // This saves a copy when the data is not already available in a buffer. - // The caller must not write more than the length it declares it will. - // Use ReadData to get the data. - // Returns NULL on failure. - // - // The returned pointer will only be valid until the next write operation - // on this FlipFrameBuilder. - char* BeginWriteData(uint16 length); - - // Returns true if the given iterator could point to data with the given - // length. If there is no room for the given data before the end of the - // payload, returns false. - bool IteratorHasRoomFor(const void* iter, int len) const { - const char* end_of_region = reinterpret_cast<const char*>(iter) + len; - VLOG(1) << "len: " << len; - if (len < 0) { - VLOG(1) << "Len < 0"; - return false; - } else if (iter < buffer_) { - VLOG(1) << "iter < buffer_"; - return false; - } else if (iter > end_of_payload()) { - VLOG(1) << "iter > end_of_payload())"; - return false; - } else if (iter > end_of_region) { - VLOG(1) << "iter > end_of_region)"; - return false; - } else if (end_of_region > end_of_payload()) { - VLOG(1) << "end_of_region > end_of_payload()"; - VLOG(1) << "end_of_region - end_of_payload(): " - << (end_of_region - end_of_payload()); - - return false; - } - - // Watch out for overflow in pointer calculation, which wraps. - return (iter <= end_of_region) && (end_of_region <= end_of_payload()); - } - - protected: - size_t capacity() const { - return capacity_; - } - - const char* end_of_payload() const { return buffer_ + length_; } - - // Resizes the buffer for use when writing the specified amount of data. The - // location that the data should be written at is returned, or NULL if there - // was an error. Call EndWrite with the returned offset and the given length - // to pad out for the next write. - char* BeginWrite(size_t length); - - // Completes the write operation by padding the data with NULL bytes until it - // is padded. Should be paired with BeginWrite, but it does not necessarily - // have to be called after the data is written. - void EndWrite(char* dest, int length); - - // Resize the capacity, note that the input value should include the size of - // the header: new_capacity = sizeof(Header) + desired_payload_capacity. - // A new failure will cause a Resize failure... and caller should check - // the return result for true (i.e., successful resizing). - bool Resize(size_t new_capacity); - - // Moves the iterator by the given number of bytes. - static void UpdateIter(void** iter, int bytes) { - *iter = static_cast<char*>(*iter) + bytes; - } - - // Initial size of the payload. - static const int kInitialPayload = 1024; - - private: - char* buffer_; - size_t capacity_; // Allocation size of payload (or -1 if buffer is const). - size_t length_; // current length of the buffer - size_t variable_buffer_offset_; // IF non-zero, then offset to a buffer. -}; - -} // namespace flip - -#endif // NET_FLIP_FRAME_BUILDER_H_ - diff --git a/net/flip/flip_framer.cc b/net/flip/flip_framer.cc deleted file mode 100644 index ec183cc..0000000 --- a/net/flip/flip_framer.cc +++ /dev/null @@ -1,732 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/scoped_ptr.h" -#include "base/stats_counters.h" - -#include "flip_framer.h" // cross-google3 directory naming. -#include "flip_frame_builder.h" -#include "flip_bitmasks.h" - -#ifdef WIN32 -#include "third_party/zlib/zlib.h" -#else -#include "third_party/zlib/v1_2_3/zlib.h" -#endif - -namespace flip { - -// The initial size of the control frame buffer; this is used internally -// as we we parse though control frames. -static const int kControlFrameBufferInitialSize = 32 * 1024; -// The maximum size of the control frame buffer that we support. -// TODO(mbelshe): We should make this stream-based so there are no limits. -static const int kControlFrameBufferMaxSize = 64 * 1024; - -// This implementation of Flip is version 1. -static const int kFlipProtocolVersion = 1; - -// By default is compression on or off. -bool FlipFramer::compression_default_ = true; - -#ifdef DEBUG_FLIP_STATE_CHANGES -#define CHANGE_STATE(newstate) \ -{ \ - do { \ - LOG(INFO) << "Changing state from: " \ - << StateToString(state_) \ - << " to " << StateToString(newstate) << "\n"; \ - state_ = newstate; \ - } while (false); \ -} -#else -#define CHANGE_STATE(newstate) (state_ = newstate) -#endif - -FlipFramer::FlipFramer() - : state_(FLIP_RESET), - error_code_(FLIP_NO_ERROR), - remaining_payload_(0), - remaining_control_payload_(0), - current_frame_buffer_(NULL), - current_frame_len_(0), - current_frame_capacity_(0), - enable_compression_(compression_default_), - visitor_(NULL) { -} - -FlipFramer::~FlipFramer() { - if (compressor_.get()) { - deflateEnd(compressor_.get()); - } - delete [] current_frame_buffer_; -} - -void FlipFramer::Reset() { - state_ = FLIP_RESET; - error_code_ = FLIP_NO_ERROR; - remaining_payload_ = 0; - remaining_control_payload_ = 0; - current_frame_len_ = 0; - if (current_frame_capacity_ != kControlFrameBufferInitialSize) { - delete [] current_frame_buffer_; - current_frame_buffer_ = 0; - current_frame_capacity_ = 0; - ExpandControlFrameBuffer(kControlFrameBufferInitialSize); - } -} - -const char* FlipFramer::StateToString(int state) { - switch (state) { - case FLIP_ERROR: - return "ERROR"; - case FLIP_DONE: - return "DONE"; - case FLIP_AUTO_RESET: - return "AUTO_RESET"; - case FLIP_RESET: - return "RESET"; - case FLIP_READING_COMMON_HEADER: - return "READING_COMMON_HEADER"; - case FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER: - return "INTERPRET_CONTROL_FRAME_COMMON_HEADER"; - case FLIP_CONTROL_FRAME_PAYLOAD: - return "CONTROL_FRAME_PAYLOAD"; - case FLIP_IGNORE_REMAINING_PAYLOAD: - return "IGNORE_REMAINING_PAYLOAD"; - case FLIP_FORWARD_STREAM_FRAME: - return "FORWARD_STREAM_FRAME"; - } - return "UNKNOWN_STATE"; -} - -uint32 FlipFramer::BytesSafeToRead() const { - switch (state_) { - case FLIP_ERROR: - case FLIP_DONE: - case FLIP_AUTO_RESET: - case FLIP_RESET: - return 0; - case FLIP_READING_COMMON_HEADER: - DCHECK(current_frame_len_ < sizeof(FlipFrame)); - return sizeof(FlipFrame) - current_frame_len_; - case FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER: - return 0; - case FLIP_CONTROL_FRAME_PAYLOAD: - case FLIP_IGNORE_REMAINING_PAYLOAD: - case FLIP_FORWARD_STREAM_FRAME: - return remaining_payload_; - } - // We should never get to here. - return 0; -} - -void FlipFramer::set_error(FlipError error) { - DCHECK(false); - DCHECK(visitor_); - error_code_ = error; - visitor_->OnError(this); -} - -const char* FlipFramer::ErrorCodeToString(int error_code) { - switch (error_code) { - case FLIP_NO_ERROR: - return "NO_ERROR"; - case FLIP_UNKNOWN_CONTROL_TYPE: - return "UNKNOWN_CONTROL_TYPE"; - case FLIP_INVALID_CONTROL_FRAME: - return "INVALID_CONTROL_FRAME"; - case FLIP_CONTROL_PAYLOAD_TOO_LARGE: - return "CONTROL_PAYLOAD_TOO_LARGE"; - case FLIP_ZLIB_INIT_FAILURE: - return "ZLIB_INIT_FAILURE"; - case FLIP_UNSUPPORTED_VERSION: - return "UNSUPPORTED_VERSION"; - case FLIP_DECOMPRESS_FAILURE: - return "DECOMPRESS_FAILURE"; - } - return "UNKNOWN_STATE"; -} - -uint32 FlipFramer::ProcessInput(const char* data, uint32 len) { - DCHECK(visitor_); - DCHECK(data); - - uint32 original_len = len; - while (len != 0) { - FlipControlFrame* current_control_frame = - reinterpret_cast<FlipControlFrame*>(current_frame_buffer_); - FlipDataFrame* current_data_frame = - reinterpret_cast<FlipDataFrame*>(current_frame_buffer_); - - switch (state_) { - case FLIP_ERROR: - case FLIP_DONE: - goto bottom; - - case FLIP_AUTO_RESET: - case FLIP_RESET: - Reset(); - CHANGE_STATE(FLIP_READING_COMMON_HEADER); - continue; - - case FLIP_READING_COMMON_HEADER: { - int bytes_read = ProcessCommonHeader(data, len); - len -= bytes_read; - data += bytes_read; - continue; - } - - // Arguably, this case is not necessary, as no bytes are consumed here. - // I felt it was a nice partitioning, however (which probably indicates - // that it should be refactored into its own function!) - case FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER: - DCHECK(error_code_ == 0); - DCHECK(current_frame_len_ >= sizeof(FlipFrame)); - // Do some sanity checking on the control frame sizes. - switch (current_control_frame->type()) { - case SYN_STREAM: - // NOTE: sizeof(FlipSynStreamControlFrame) is not accurate. - if (current_control_frame->length() < - sizeof(FlipSynStreamControlFrame) - sizeof(FlipControlFrame)) - set_error(FLIP_INVALID_CONTROL_FRAME); - break; - case SYN_REPLY: - if (current_control_frame->length() < - sizeof(FlipSynReplyControlFrame) - sizeof(FlipControlFrame)) - set_error(FLIP_INVALID_CONTROL_FRAME); - break; - case FIN_STREAM: - if (current_control_frame->length() != - sizeof(FlipFinStreamControlFrame) - sizeof(FlipFrame)) - set_error(FLIP_INVALID_CONTROL_FRAME); - break; - case NOOP: - // NOP. Swallow it. - CHANGE_STATE(FLIP_AUTO_RESET); - continue; - default: - set_error(FLIP_UNKNOWN_CONTROL_TYPE); - break; - } - - // We only support version 1 of this protocol. - if (current_control_frame->version() != kFlipProtocolVersion) - set_error(FLIP_UNSUPPORTED_VERSION); - - if (error_code_) { - CHANGE_STATE(FLIP_ERROR); - goto bottom; - } - - remaining_control_payload_ = current_control_frame->length(); - if (remaining_control_payload_ > kControlFrameBufferMaxSize) { - set_error(FLIP_CONTROL_PAYLOAD_TOO_LARGE); - CHANGE_STATE(FLIP_ERROR); - goto bottom; - } - ExpandControlFrameBuffer(remaining_control_payload_); - CHANGE_STATE(FLIP_CONTROL_FRAME_PAYLOAD); - continue; - - case FLIP_CONTROL_FRAME_PAYLOAD: { - int bytes_read = ProcessControlFramePayload(data, len); - len -= bytes_read; - data += bytes_read; - } - // intentional fallthrough - case FLIP_IGNORE_REMAINING_PAYLOAD: - // control frame has too-large payload - // intentional fallthrough - case FLIP_FORWARD_STREAM_FRAME: - if (remaining_payload_) { - uint32 amount_to_forward = std::min(remaining_payload_, len); - if (amount_to_forward && state_ != FLIP_IGNORE_REMAINING_PAYLOAD) { - const FlipDataFrame* data_frame = - reinterpret_cast<const FlipDataFrame*>(current_data_frame); - if (data_frame->flags() & DATA_FLAG_COMPRESSED) { - // TODO(mbelshe): Assert that the decompressor is init'ed. - if (!InitializeDecompressor()) - return NULL; - - int decompressed_max_size = amount_to_forward * 100; - scoped_array<char> decompressed(new char[decompressed_max_size]); - decompressor_->next_in = reinterpret_cast<Bytef*>( - const_cast<char*>(data)); - decompressor_->avail_in = amount_to_forward; - decompressor_->next_out = - reinterpret_cast<Bytef*>(decompressed.get()); - decompressor_->avail_out = decompressed_max_size; - - int rv = inflate(decompressor_.get(), Z_SYNC_FLUSH); - if (rv != Z_OK) { - set_error(FLIP_DECOMPRESS_FAILURE); - goto bottom; - } - int decompressed_size = decompressed_max_size - - decompressor_->avail_out; - visitor_->OnStreamFrameData(current_data_frame->stream_id(), - decompressed.get(), - decompressed_size); - amount_to_forward -= decompressor_->avail_in; - } else { - // The data frame was not compressed - visitor_->OnStreamFrameData(current_data_frame->stream_id(), - data, amount_to_forward); - } - } - data += amount_to_forward; - len -= amount_to_forward; - remaining_payload_ -= amount_to_forward; - } else { - CHANGE_STATE(FLIP_AUTO_RESET); - } - continue; - default: - break; - } - } - bottom: - return original_len - len; -} - -uint32 FlipFramer::ProcessCommonHeader(const char* data, uint32 len) { - // This should only be called when we're in the FLIP_READING_COMMON_HEADER - // state. - DCHECK(state_ == FLIP_READING_COMMON_HEADER); - - int original_len = len; - FlipDataFrame* current_frame = - reinterpret_cast<FlipDataFrame*>(current_frame_buffer_); - - do { - if (current_frame_len_ < sizeof(FlipFrame)) { - uint32 bytes_desired = sizeof(FlipFrame) - current_frame_len_; - uint32 bytes_to_append = std::min(bytes_desired, len); - char* header_buffer = current_frame_buffer_; - memcpy(&header_buffer[current_frame_len_], data, bytes_to_append); - current_frame_len_ += bytes_to_append; - data += bytes_to_append; - len -= bytes_to_append; - // Check for an empty data packet. - if (current_frame_len_ == sizeof(FlipFrame) && - !current_frame->is_control_frame() && - current_frame->length() == 0) { - visitor_->OnStreamFrameData(current_frame->stream_id(), NULL, 0); - CHANGE_STATE(FLIP_RESET); - } - break; - } - remaining_payload_ = current_frame->length(); - // if we're here, then we have the common header all received. - if (!current_frame->is_control_frame()) - CHANGE_STATE(FLIP_FORWARD_STREAM_FRAME); - else - CHANGE_STATE(FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER); - } while (false); - - return original_len - len; -} - -uint32 FlipFramer::ProcessControlFramePayload(const char* data, uint32 len) { - int original_len = len; - do { - if (remaining_control_payload_) { - uint32 amount_to_consume = std::min(remaining_control_payload_, len); - memcpy(¤t_frame_buffer_[current_frame_len_], data, - amount_to_consume); - current_frame_len_ += amount_to_consume; - data += amount_to_consume; - len -= amount_to_consume; - remaining_control_payload_ -= amount_to_consume; - remaining_payload_ -= amount_to_consume; - if (remaining_control_payload_) - break; - } - FlipControlFrame* control_frame = - reinterpret_cast<FlipControlFrame*>(current_frame_buffer_); - visitor_->OnControl(control_frame); - CHANGE_STATE(FLIP_IGNORE_REMAINING_PAYLOAD); - } while (false); - return original_len - len; -} - -void FlipFramer::ExpandControlFrameBuffer(int size) { - DCHECK(size < kControlFrameBufferMaxSize); - if (size < current_frame_capacity_) - return; - - int alloc_size = size + sizeof(FlipFrame); - char* new_buffer = new char[alloc_size]; - memcpy(new_buffer, current_frame_buffer_, current_frame_len_); - current_frame_capacity_ = alloc_size; - current_frame_buffer_ = new_buffer; -} - -bool FlipFramer::ParseHeaderBlock(const FlipFrame* frame, - FlipHeaderBlock* block) { - uint32 type = reinterpret_cast<const FlipControlFrame*>(frame)->type(); - if (type != SYN_STREAM && type != SYN_REPLY) - return false; - - // Find the header data within the control frame. - scoped_array<FlipSynStreamControlFrame> control_frame( - reinterpret_cast<FlipSynStreamControlFrame*>(DecompressFrame(frame))); - if (!control_frame.get()) - return false; - const char *header_data = control_frame.get()->header_block(); - int header_length = control_frame.get()->header_block_len(); - - FlipFrameBuilder builder(header_data, header_length); - void* iter = NULL; - uint16 num_headers; - if (builder.ReadUInt16(&iter, &num_headers)) { - VLOG(2) << "found num_headers: " << num_headers; - for (int index = 0; index < num_headers; ++index) { - std::string name; - std::string value; - if (!builder.ReadString(&iter, &name)) { - VLOG(1) << "couldn't read string (key)!"; - break; - } - if (!builder.ReadString(&iter, &value)) { - VLOG(1) << "couldn't read string (value)!"; - break; - } - if (block->empty()) { - (*block)[name] = value; - } else { - FlipHeaderBlock::iterator last = --block->end(); - if (block->key_comp()(last->first, name)) { - block->insert(block->end(), - std::pair<std::string, std::string>(name, value)); - } else { - return false; - } - } - } - return true; - } else { - VLOG(2) << "didn't find headers"; - } - return false; -} - -FlipSynStreamControlFrame* FlipFramer::CreateSynStream( - int stream_id, - int priority, - bool compress, - FlipHeaderBlock* headers) { - FlipFrameBuilder frame; - - frame.WriteUInt16(kControlFlagMask | kFlipProtocolVersion); - frame.WriteUInt16(SYN_STREAM); - frame.WriteUInt32(0); // Placeholder for the length. - frame.WriteUInt32(stream_id); - frame.WriteUInt16(ntohs(priority) << 6); // Priority. - - frame.WriteUInt16(headers->size()); // Number of headers. - FlipHeaderBlock::iterator it; - for (it = headers->begin(); it != headers->end(); ++it) { - frame.WriteString(it->first); - frame.WriteString(it->second); - } - // write the length - frame.WriteUInt32ToOffset(4, frame.length() - sizeof(FlipFrame)); - if (compress) { - FlipSynStreamControlFrame* new_frame = - reinterpret_cast<FlipSynStreamControlFrame*>( - CompressFrame(frame.data())); - return new_frame; - } - - return reinterpret_cast<FlipSynStreamControlFrame*>(frame.take()); -} - -/* static */ -FlipFinStreamControlFrame* FlipFramer::CreateFinStream(int stream_id, - int status) { - FlipFrameBuilder frame; - frame.WriteUInt16(kControlFlagMask | kFlipProtocolVersion); - frame.WriteUInt16(FIN_STREAM); - frame.WriteUInt32(8); - frame.WriteUInt32(stream_id); - frame.WriteUInt32(status); - return reinterpret_cast<FlipFinStreamControlFrame*>(frame.take()); -} - -FlipSynReplyControlFrame* FlipFramer::CreateSynReply(int stream_id, - bool compressed, FlipHeaderBlock* headers) { - - FlipFrameBuilder frame; - - frame.WriteUInt16(kControlFlagMask | kFlipProtocolVersion); - frame.WriteUInt16(SYN_REPLY); - frame.WriteUInt32(0); // Placeholder for the length. - frame.WriteUInt32(stream_id); - frame.WriteUInt16(0); // Priority. - - frame.WriteUInt16(headers->size()); // Number of headers. - FlipHeaderBlock::iterator it; - for (it = headers->begin(); it != headers->end(); ++it) { - // TODO(mbelshe): Headers need to be sorted. - frame.WriteString(it->first); - frame.WriteString(it->second); - } - // write the length - frame.WriteUInt32ToOffset(4, frame.length() - sizeof(FlipFrame)); - if (compressed) - return reinterpret_cast<FlipSynReplyControlFrame*>( - CompressFrame(frame.data())); - return reinterpret_cast<FlipSynReplyControlFrame*>(frame.take()); -} - -FlipDataFrame* FlipFramer::CreateDataFrame(int stream_id, - const char* data, - int len, bool compressed) { - FlipFrameBuilder frame; - - frame.WriteUInt32(stream_id); - - frame.WriteUInt32(len); - frame.WriteBytes(data, len); - if (compressed) - return reinterpret_cast<FlipDataFrame*>(CompressFrame(frame.data())); - return reinterpret_cast<FlipDataFrame*>(frame.take()); -} - -static const int kCompressorLevel = Z_DEFAULT_COMPRESSION; -// This is just a hacked dictionary to use for shrinking HTTP-like headers. -// TODO(mbelshe): Use a scientific methodology for computing the dictionary. -static const char dictionary[] = - "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" - "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" - "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" - "-agent10010120020120220320420520630030130230330430530630740040140240340440" - "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" - "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" - "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" - "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" - "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" - "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" - "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" - "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" - ".1statusversionurl"; -static uLong dictionary_id = 0; - -bool FlipFramer::InitializeCompressor() { - if (compressor_.get()) - return true; // Already initialized. - - compressor_.reset(new z_stream); - memset(compressor_.get(), 0, sizeof(z_stream)); - - int success = deflateInit(compressor_.get(), kCompressorLevel); - if (success == Z_OK) - success = deflateSetDictionary(compressor_.get(), - reinterpret_cast<const Bytef*>(dictionary), - sizeof(dictionary)); - if (success != Z_OK) - compressor_.reset(NULL); - return success == Z_OK; -} - -bool FlipFramer::InitializeDecompressor() { - if (decompressor_.get()) - return true; // Already initialized. - - decompressor_.reset(new z_stream); - memset(decompressor_.get(), 0, sizeof(z_stream)); - - // Compute the id of our dictionary so that we know we're using the - // right one when asked for it. - if (dictionary_id == 0) { - dictionary_id = adler32(0L, Z_NULL, 0); - dictionary_id = adler32(dictionary_id, - reinterpret_cast<const Bytef*>(dictionary), - sizeof(dictionary)); - } - - int success = inflateInit(decompressor_.get()); - if (success != Z_OK) - decompressor_.reset(NULL); - return success == Z_OK; -} - -bool FlipFramer::GetFrameBoundaries(const FlipFrame* frame, - int* payload_length, - int* header_length, - const unsigned char** payload) const { - if (frame->is_control_frame()) { - const FlipControlFrame* control_frame = - reinterpret_cast<const FlipControlFrame*>(frame); - switch (control_frame->type()) { - case SYN_STREAM: - case SYN_REPLY: - { - const FlipSynStreamControlFrame *syn_frame = - reinterpret_cast<const FlipSynStreamControlFrame*>(frame); - *payload_length = syn_frame->header_block_len(); - *header_length = sizeof(FlipFrame) + syn_frame->length() - - syn_frame->header_block_len(); - *payload = reinterpret_cast<const unsigned char*>(frame) + - *header_length; - } - break; - default: - // TODO(mbelshe): set an error? - return false; // We can't compress this frame! - } - } else { - *header_length = sizeof(FlipFrame); - *payload_length = frame->length(); - *payload = reinterpret_cast<const unsigned char*>(frame) + - sizeof(FlipFrame); - } - DCHECK(static_cast<size_t>(*header_length) <= - sizeof(FlipFrame) + *payload_length); - return true; -} - - -FlipFrame* FlipFramer::CompressFrame(const FlipFrame* frame) { - int payload_length; - int header_length; - const unsigned char* payload; - - static StatsCounter pre_compress_bytes("flip.PreCompressSize"); - static StatsCounter post_compress_bytes("flip.PostCompressSize"); - - if (!enable_compression_) - return DuplicateFrame(frame); - - if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) - return NULL; - - if (!InitializeCompressor()) - return NULL; - - // TODO(mbelshe): Should we have a zlib header like what http servers do? - - // Create an output frame. - int compressed_max_size = deflateBound(compressor_.get(), payload_length); - int new_frame_size = header_length + compressed_max_size; - FlipFrame* new_frame = - reinterpret_cast<FlipFrame*>(new char[new_frame_size]); - memcpy(new_frame, frame, header_length); - - compressor_->next_in = const_cast<Bytef*>(payload); - compressor_->avail_in = payload_length; - compressor_->next_out = reinterpret_cast<Bytef*>(new_frame) + header_length; - compressor_->avail_out = compressed_max_size; - - // Data packets have a 'compressed flag - if (!new_frame->is_control_frame()) { - FlipDataFrame* data_frame = reinterpret_cast<FlipDataFrame*>(new_frame); - data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED); - } - - int rv = deflate(compressor_.get(), Z_SYNC_FLUSH); - if (rv != Z_OK) { // How can we know that it compressed everything? - // This shouldn't happen, right? - free(new_frame); - return NULL; - } - - int compressed_size = compressed_max_size - compressor_->avail_out; - new_frame->set_length(header_length + compressed_size - sizeof(FlipFrame)); - - pre_compress_bytes.Add(payload_length); - post_compress_bytes.Add(new_frame->length()); - - return new_frame; -} - -FlipFrame* FlipFramer::DecompressFrame(const FlipFrame* frame) { - int payload_length; - int header_length; - const unsigned char* payload; - - static StatsCounter pre_decompress_bytes("flip.PreDeCompressSize"); - static StatsCounter post_decompress_bytes("flip.PostDeCompressSize"); - - if (!enable_compression_) - return DuplicateFrame(frame); - - if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) - return NULL; - - if (!frame->is_control_frame()) { - const FlipDataFrame* data_frame = - reinterpret_cast<const FlipDataFrame*>(frame); - if (!data_frame->flags() & DATA_FLAG_COMPRESSED) - return DuplicateFrame(frame); - } - - if (!InitializeDecompressor()) - return NULL; - - // TODO(mbelshe): Should we have a zlib header like what http servers do? - - // Create an output frame. Assume it does not need to be longer than - // the input data. - int decompressed_max_size = kControlFrameBufferInitialSize; - int new_frame_size = header_length + decompressed_max_size; - FlipFrame* new_frame = - reinterpret_cast<FlipFrame*>(new char[new_frame_size]); - memcpy(new_frame, frame, header_length); - - decompressor_->next_in = const_cast<Bytef*>(payload); - decompressor_->avail_in = payload_length; - decompressor_->next_out = reinterpret_cast<Bytef*>(new_frame) + - header_length; - decompressor_->avail_out = decompressed_max_size; - - int rv = inflate(decompressor_.get(), Z_SYNC_FLUSH); - if (rv == Z_NEED_DICT) { - // Need to try again with the right dictionary. - if (decompressor_->adler == dictionary_id) { - rv = inflateSetDictionary(decompressor_.get(), (const Bytef*)dictionary, - sizeof(dictionary)); - if (rv == Z_OK) - rv = inflate(decompressor_.get(), Z_SYNC_FLUSH); - } - } - if (rv != Z_OK) { // How can we know that it decompressed everything? - free(new_frame); - return NULL; - } - - // Unset the compressed flag for data frames. - if (!new_frame->is_control_frame()) { - FlipDataFrame* data_frame = reinterpret_cast<FlipDataFrame*>(new_frame); - data_frame->set_flags(data_frame->flags() & ~DATA_FLAG_COMPRESSED); - } - - int decompressed_size = decompressed_max_size - decompressor_->avail_out; - new_frame->set_length(header_length + decompressed_size - sizeof(FlipFrame)); - - pre_decompress_bytes.Add(frame->length()); - post_decompress_bytes.Add(new_frame->length()); - - return new_frame; -} - -FlipFrame* FlipFramer::DuplicateFrame(const FlipFrame* frame) { - int size = sizeof(FlipFrame) + frame->length(); - char* new_frame = new char[size]; - memcpy(new_frame, frame, size); - return reinterpret_cast<FlipFrame*>(new_frame); -} - -void FlipFramer::set_enable_compression(bool value) { - enable_compression_ = value; -} - -void FlipFramer::set_enable_compression_default(bool value) { - compression_default_ = value; -} - -} // namespace flip - diff --git a/net/flip/flip_framer.h b/net/flip/flip_framer.h deleted file mode 100644 index e50cc83..0000000 --- a/net/flip/flip_framer.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_FLIP_FLIP_FRAMER_H_ -#define NET_FLIP_FLIP_FRAMER_H_ - -#ifdef _WIN32 -#include <winsock2.h> -#else -#include <arpa/inet.h> -#endif -#include <map> -#include <string> - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest_prod.h" -#include "flip_protocol.h" // cross-google3 directory naming. - -typedef struct z_stream_s z_stream; // Forward declaration for zlib. - -namespace net { -class FlipNetworkTransactionTest; -} - -namespace flip { - -class FlipFramer; -class FlipFramerTest; - -// A datastructure for holding a set of headers from either a -// SYN_STREAM or SYN_REPLY frame. -typedef std::map<std::string, std::string> FlipHeaderBlock; - -// FlipFramerVisitorInterface is a set of callbacks for the FlipFramer. -// Implement this interface to receive event callbacks as frames are -// decoded from the framer. -class FlipFramerVisitorInterface { - public: - virtual ~FlipFramerVisitorInterface() {} - - // Called if an error is detected in the FlipFrame protocol. - virtual void OnError(FlipFramer* framer) = 0; - - // Called when a Control Frame is received. - virtual void OnControl(const FlipControlFrame* frame) = 0; - - // Called when data is received. - virtual void OnStreamFrameData(uint32 sream_id, - const char* data, - uint32 len) = 0; - - // TODO(fenix): Implement me! - virtual void OnLameDuck() = 0; -}; - -class FlipFramer { - public: - // Flip states. - // TODO(mbelshe): Can we move these into the implementation - // and avoid exposing through the header. (Needed for test) - enum FlipState { - FLIP_ERROR, - FLIP_DONE, - FLIP_RESET, - FLIP_AUTO_RESET, - FLIP_READING_COMMON_HEADER, - FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER, - FLIP_CONTROL_FRAME_PAYLOAD, - FLIP_IGNORE_REMAINING_PAYLOAD, - FLIP_FORWARD_STREAM_FRAME - }; - - // Flip error codes. - enum FlipError { - FLIP_NO_ERROR, - FLIP_UNKNOWN_CONTROL_TYPE, // Control frame is an unknown type. - FLIP_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. - FLIP_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. - FLIP_ZLIB_INIT_FAILURE, // The Zlib library could not initialize. - FLIP_UNSUPPORTED_VERSION, // Control frame has unsupported version. - FLIP_DECOMPRESS_FAILURE, // There was an error decompressing. - }; - - // Create a new Framer. - FlipFramer(); - virtual ~FlipFramer(); - - // Set callbacks to be called from the framer. A visitor must be set, or - // else the framer will likely crash. It is acceptable for the visitor - // to do nothing. If this is called multiple times, only the last visitor - // will be used. - void set_visitor(FlipFramerVisitorInterface* visitor) { - visitor_ = visitor; - } - - // Pass data into the framer for parsing. - // Returns the number of bytes consumed. It is safe to pass more bytes in - // than may be consumed. - uint32 ProcessInput(const char* data, uint32 len); - - // Resets the framer state after a frame has been successfully decoded. - // TODO(mbelshe): can we make this private? - void Reset(); - - // Check the state of the framer. - FlipError error_code() const { return error_code_; } - FlipState state() const { return state_; } - - bool MessageFullyRead() { - return state_ == FLIP_DONE || state_ == FLIP_AUTO_RESET; - } - bool HasError() { return state_ == FLIP_ERROR; } - - // Further parsing utilities. - // Given a control frame, parse out a FlipHeaderBlock. Only - // valid for SYN_STREAM and SYN_REPLY frames. - // Returns true if successfully parsed, false otherwise. - bool ParseHeaderBlock(const FlipFrame* frame, FlipHeaderBlock* block); - - // Frame creation utilities - // Create a FlipSynStreamControlFrame. The resulting frame will be - // compressed if |compressed| is true. - FlipSynStreamControlFrame* CreateSynStream(int stream_id, int priority, - bool compress, - FlipHeaderBlock* headers); - static FlipFinStreamControlFrame* CreateFinStream(int stream_id, int status); - - // Create a FlipSynReplyControlFrame.The resulting frame will be - // compressed if |compressed| is true. - FlipSynReplyControlFrame* CreateSynReply(int stream_id, - bool compress, - FlipHeaderBlock* headers); - - // Create a FlipDataFrame. The resulting frame will be - // compressed if |compressed| is true. - FlipDataFrame* CreateDataFrame(int stream_id, const char* data, - int len, bool compressed); - - // NOTES about frame compression. - // We want flip to compress headers across the entire session. As long as - // the session is over TCP, frames are sent serially. The client & server - // can each compress frames in the same order and then compress them in that - // order, and the remote can do the reverse. However, we ultimately want - // the creation of frames to be less sensitive to order so that they can be - // placed over a UDP based protocol and yet still benefit from some - // compression. We don't know of any good compression protocol which does - // not build its state in a serial (stream based) manner.... For now, we're - // using zlib anyway. - - // Compresses a FlipFrame. - // On success, returns a new FlipFrame with the payload compressed. - // Compression state is maintained as part of the FlipFramer. - // Returned frame must be freed with free(). - // On failure, returns NULL. - FlipFrame* CompressFrame(const FlipFrame* frame); - - // Decompresses a FlipFrame. - // On success, returns a new FlipFrame with the payload decompressed. - // Compression state is maintained as part of the FlipFramer. - // Returned frame must be freed with free(). - // On failure, returns NULL. - FlipFrame* DecompressFrame(const FlipFrame* frame); - - // Create a copy of a frame. - FlipFrame* DuplicateFrame(const FlipFrame* frame); - - // For debugging. - static const char* StateToString(int state); - static const char* ErrorCodeToString(int error_code); - - protected: - FRIEND_TEST(FlipFramerTest, Basic); - FRIEND_TEST(FlipFramerTest, HeaderBlockBarfsOnOutOfOrderHeaders); - friend class FlipNetworkTransactionTest; - - // For ease of testing we can tweak compression on/off. - void set_enable_compression(bool value); - static void set_enable_compression_default(bool value); - - private: - // Internal breakout from ProcessInput. Returns the number of bytes - // consumed from the data. - uint32 ProcessCommonHeader(const char* data, uint32 len); - uint32 ProcessControlFramePayload(const char* data, uint32 len); - - // Initialize the ZLib state. - bool InitializeCompressor(); - bool InitializeDecompressor(); - - // Not used (yet) - uint32 BytesSafeToRead() const; - - // Set the error code. - void set_error(FlipError error); - - // Expands the control frame buffer to accomodate a particular payload size. - void ExpandControlFrameBuffer(int size); - - // Given a frame, breakdown the variable payload length, the static header - // header length, and variable payload pointer. - bool GetFrameBoundaries(const FlipFrame* frame, int* payload_length, - int* header_length, - const unsigned char** payload) const; - - FlipState state_; - FlipError error_code_; - uint32 remaining_payload_; - uint32 remaining_control_payload_; - - char* current_frame_buffer_; - int current_frame_len_; // Number of bytes read into the current_frame_. - int current_frame_capacity_; - - bool enable_compression_; - scoped_ptr<z_stream> compressor_; - scoped_ptr<z_stream> decompressor_; - FlipFramerVisitorInterface* visitor_; - - static bool compression_default_; -}; - -} // namespace flip - -#endif // NET_FLIP_FLIP_FRAMER_H_ - diff --git a/net/flip/flip_framer_test.cc b/net/flip/flip_framer_test.cc deleted file mode 100644 index a786bc2..0000000 --- a/net/flip/flip_framer_test.cc +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <iostream> -#include "base/scoped_ptr.h" - -#include "flip_framer.h" // cross-google3 directory naming. -#include "flip_protocol.h" -#include "flip_frame_builder.h" -#ifdef _WIN32 -#include "testing/platform_test.h" -#else -#include "testing/base/public/gunit.h" - -#define PlatformTest ::testing::Test -#endif - -namespace flip { - -class FlipFramerTest : public PlatformTest { - public: - virtual void TearDown() {} -}; - -class TestFlipVisitor : public FlipFramerVisitorInterface { - public: - explicit TestFlipVisitor(FlipFramer* framer) - : framer_(framer), - error_count_(0), - syn_frame_count_(0), - syn_reply_frame_count_(0), - data_frame_count_(0), - fin_frame_count_(0) { - } - - void OnError(FlipFramer* f) { - error_count_++; - } - void OnStreamFrameData(FlipStreamId stream_id, - const char* data, - uint32 len) { - data_frame_count_++; -#ifdef TEST_LOGGING - std::cerr << "OnStreamFrameData(" << stream_id << ", \""; - if (len > 0) { - for (uint32 i = 0 ; i < len; ++i) { - std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec; - } - } - std::cerr << "\", " << len << ")\n"; -#endif // TEST_LOGGING - } - - void OnControl(const FlipControlFrame* frame) { - FlipHeaderBlock headers; - bool parsed_headers = false; - switch (frame->type()) { - case SYN_STREAM: - parsed_headers = framer_->ParseHeaderBlock( - reinterpret_cast<const FlipFrame*>(frame), &headers); - DCHECK(parsed_headers); - syn_frame_count_++; - VLOG(2) << "OnSyn(" << frame->stream_id() << ")\n"; - break; - case SYN_REPLY: - parsed_headers = framer_->ParseHeaderBlock( - reinterpret_cast<const FlipFrame*>(frame), &headers); - DCHECK(parsed_headers); - syn_reply_frame_count_++; - VLOG(2) << "OnSynReply(" << frame->stream_id() << ")\n"; - break; - case FIN_STREAM: - fin_frame_count_++; - VLOG(2) << "OnFin(" << frame->stream_id() << ")\n"; - break; - default: - DCHECK(false); // Error! - } - } - - void OnLameDuck() { - } - - FlipFramer* framer_; - // Counters from the visitor callbacks. - int error_count_; - int syn_frame_count_; - int syn_reply_frame_count_; - int data_frame_count_; - int fin_frame_count_; -}; - -// Test our protocol constants -TEST_F(FlipFramerTest, ProtocolConstants) { - EXPECT_EQ(8, sizeof(FlipFrame)); - EXPECT_EQ(8, sizeof(FlipDataFrame)); - EXPECT_EQ(12, sizeof(FlipControlFrame)); - EXPECT_EQ(16, sizeof(FlipSynStreamControlFrame)); - EXPECT_EQ(16, sizeof(FlipSynReplyControlFrame)); - EXPECT_EQ(16, sizeof(FlipFinStreamControlFrame)); - EXPECT_EQ(1, SYN_STREAM); - EXPECT_EQ(2, SYN_REPLY); - EXPECT_EQ(3, FIN_STREAM); -} - -// Test that we can encode and decode a FlipHeaderBlock. -TEST_F(FlipFramerTest, HeaderBlock) { - FlipHeaderBlock headers; - headers["alpha"] = "beta"; - headers["gamma"] = "charlie"; - FlipFramer framer; - - // Encode the header block into a SynStream frame. - scoped_ptr<FlipSynStreamControlFrame> frame( - framer.CreateSynStream(1, 1, true, &headers)); - EXPECT_TRUE(frame.get() != NULL); - - FlipHeaderBlock new_headers; - FlipFrame* control_frame = reinterpret_cast<FlipFrame*>(frame.get()); - framer.ParseHeaderBlock(control_frame, &new_headers); - - EXPECT_EQ(headers.size(), new_headers.size()); - EXPECT_EQ(headers["alpha"], new_headers["alpha"]); - EXPECT_EQ(headers["gamma"], new_headers["gamma"]); -} - -TEST_F(FlipFramerTest, HeaderBlockBarfsOnOutOfOrderHeaders) { - FlipFrameBuilder frame; - - frame.WriteUInt16(kControlFlagMask | 1); - frame.WriteUInt16(SYN_STREAM); - frame.WriteUInt32(0); // Placeholder for the length. - frame.WriteUInt32(3); // stream_id - frame.WriteUInt16(0); // Priority. - - frame.WriteUInt16(2); // Number of headers. - FlipHeaderBlock::iterator it; - frame.WriteString("gamma"); - frame.WriteString("gamma"); - frame.WriteString("alpha"); - frame.WriteString("alpha"); - // write the length - frame.WriteUInt32ToOffset(4, frame.length() - sizeof(FlipFrame)); - - FlipHeaderBlock new_headers; - const FlipFrame* control_frame = frame.data(); - FlipFramer framer; - framer.set_enable_compression(false); - EXPECT_FALSE(framer.ParseHeaderBlock(control_frame, &new_headers)); -} - -TEST_F(FlipFramerTest, BasicCompression) { - FlipHeaderBlock headers; - headers["server"] = "FlipServer 1.0"; - headers["date"] = "Mon 12 Jan 2009 12:12:12 PST"; - headers["status"] = "200"; - headers["version"] = "HTTP/1.1"; - headers["content-type"] = "text/html"; - headers["content-length"] = "12"; - - FlipFramer framer; - scoped_ptr<FlipSynStreamControlFrame> - frame1(framer.CreateSynStream(1, 1, true, &headers)); - scoped_ptr<FlipSynStreamControlFrame> - frame2(framer.CreateSynStream(1, 1, true, &headers)); - - // Expect the second frame to be more compact than the first. - EXPECT_LE(frame2->length(), frame1->length()); - - // Decompress the first frame - scoped_ptr<FlipFrame> frame3( - framer.DecompressFrame(reinterpret_cast<FlipFrame*>(frame1.get()))); - - // Decompress the second frame - scoped_ptr<FlipFrame> frame4( - framer.DecompressFrame(reinterpret_cast<FlipFrame*>(frame2.get()))); - - // Expect frames 3 & 4 to be the same. - EXPECT_EQ(0, - memcmp(frame3.get(), frame4.get(), - sizeof(FlipFrame) + frame3->length())); -} - -TEST_F(FlipFramerTest, Basic) { - const unsigned char input[] = { - 0x80, 0x01, 0x00, 0x01, // SYN Stream #1 - 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x02, 'h', 'h', - 0x00, 0x02, 'v', 'v', - - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 - 0x00, 0x00, 0x00, 0x0c, - 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, - - 0x80, 0x01, 0x00, 0x01, // SYN Stream #3 - 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 - 0x00, 0x00, 0x00, 0x08, - 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, - - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 - 0x00, 0x00, 0x00, 0x04, - 0xde, 0xad, 0xbe, 0xef, - - 0x80, 0x01, 0x00, 0x03, // FIN on Stream #1 - 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 - 0x00, 0x00, 0x00, 0x00, - - 0x80, 0x01, 0x00, 0x03, // FIN on Stream #3 - 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, - }; - - FlipFramer framer; - framer.set_enable_compression(false); - TestFlipVisitor visitor(&framer); - framer.set_visitor(&visitor); - size_t input_remaining = sizeof(input); - const char* input_ptr = reinterpret_cast<const char*>(input); - while (input_remaining > 0 && - framer.error_code() == FlipFramer::FLIP_NO_ERROR) { - size_t bytes_processed = framer.ProcessInput(input_ptr, sizeof(input)); - input_remaining -= bytes_processed; - input_ptr += bytes_processed; - if (framer.state() == FlipFramer::FLIP_DONE) - framer.Reset(); - } - EXPECT_EQ(0, visitor.error_count_); - EXPECT_EQ(2, visitor.syn_frame_count_); - EXPECT_EQ(0, visitor.syn_reply_frame_count_); - EXPECT_EQ(4, visitor.data_frame_count_); - EXPECT_EQ(2, visitor.fin_frame_count_); -} - -} // namespace flip - - diff --git a/net/flip/flip_network_transaction.cc b/net/flip/flip_network_transaction.cc deleted file mode 100644 index 88b931d..0000000 --- a/net/flip/flip_network_transaction.cc +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/flip/flip_network_transaction.h" - -#include "base/scoped_ptr.h" -#include "base/compiler_specific.h" -#include "base/field_trial.h" -#include "base/string_util.h" -#include "base/trace_event.h" -#include "build/build_config.h" -#include "net/base/connection_type_histograms.h" -#include "net/base/host_resolver.h" -#include "net/base/io_buffer.h" -#include "net/base/load_flags.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "net/base/upload_data_stream.h" -#include "net/http/http_auth.h" -#include "net/http/http_auth_handler.h" -#include "net/http/http_basic_stream.h" -#include "net/http/http_chunked_decoder.h" -#include "net/http/http_network_session.h" -#include "net/http/http_request_info.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_util.h" -#include "net/socket/client_socket_factory.h" -#include "net/socket/ssl_client_socket.h" - -using base::Time; - -namespace net { - -//----------------------------------------------------------------------------- - -FlipNetworkTransaction::FlipNetworkTransaction(HttpNetworkSession* session) - : flip_request_id_(0), - user_callback_(0), - user_buffer_bytes_remaining_(0), - session_(session), - request_(NULL), - response_complete_(false), - response_status_(net::OK), - next_state_(STATE_NONE) { -} - -FlipNetworkTransaction::~FlipNetworkTransaction() { - LOG(INFO) << "FlipNetworkTransaction dead. " << this; - if (flip_ && flip_request_id_) - flip_->CancelStream(flip_request_id_); -} - -const HttpRequestInfo* FlipNetworkTransaction::request() { - return request_; -} - -const UploadDataStream* FlipNetworkTransaction::data() { - return request_body_stream_.get(); -} - -void FlipNetworkTransaction::OnRequestSent(int status) { - if (status == OK) - next_state_ = STATE_SEND_REQUEST_COMPLETE; - else - next_state_ = STATE_NONE; - - int rv = DoLoop(status); -} - -void FlipNetworkTransaction::OnResponseReceived(HttpResponseInfo* response) { - next_state_ = STATE_READ_HEADERS_COMPLETE; - - response_ = *response; // TODO(mbelshe): avoid copy. - - int rv = DoLoop(net::OK); -} - -void FlipNetworkTransaction::OnDataReceived(const char* buffer, int bytes) { - // TODO(mbelshe): if data is received before a syn reply, this will crash. - - DCHECK(bytes >= 0); - next_state_ = STATE_READ_BODY; - - if (bytes > 0) { - DCHECK(buffer); - - // TODO(mbelshe): If read is pending, we should copy the data straight into - // the read buffer here. For now, we'll queue it always. - - IOBufferWithSize* io_buffer = new IOBufferWithSize(bytes); - memcpy(io_buffer->data(), buffer, bytes); - - response_body_.push_back(io_buffer); - } - int rv = DoLoop(net::OK); -} - -void FlipNetworkTransaction::OnClose(int status) { - next_state_ = STATE_READ_BODY_COMPLETE; - response_complete_ = true; - response_status_ = status; - flip_request_id_ = 0; // TODO(mbelshe) - do we need this? - int rv = DoLoop(status); -} - -void FlipNetworkTransaction::OnCancel() { - next_state_ = STATE_NONE; - response_complete_ = true; - response_status_ = net::ERR_ABORTED; - flip_request_id_ = 0; // TODO(mbelshe) - do we need this? - // Clear any data in our buffer. - while (response_body_.size()) - response_body_.pop_front(); -} - -int FlipNetworkTransaction::Start(const HttpRequestInfo* request_info, - CompletionCallback* callback, - LoadLog* load_log) { - request_ = request_info; - start_time_ = base::Time::Now(); - - next_state_ = STATE_INIT_CONNECTION; - int rv = DoLoop(OK); - if (rv == ERR_IO_PENDING) - user_callback_ = callback; - return rv; -} - -int FlipNetworkTransaction::RestartIgnoringLastError( - CompletionCallback* callback) { - // TODO(mbelshe): implement me. - NOTIMPLEMENTED(); - return ERR_NOT_IMPLEMENTED; -} - -int FlipNetworkTransaction::RestartWithCertificate( - X509Certificate* client_cert, CompletionCallback* callback) { - // TODO(mbelshe): implement me. - NOTIMPLEMENTED(); - return ERR_NOT_IMPLEMENTED; -} - -int FlipNetworkTransaction::RestartWithAuth( - const std::wstring& username, - const std::wstring& password, - CompletionCallback* callback) { - // TODO(mbelshe): implement me. - NOTIMPLEMENTED(); - return 0; -} - -int FlipNetworkTransaction::Read(IOBuffer* buf, int buf_len, - CompletionCallback* callback) { - DCHECK(buf); - DCHECK(buf_len > 0); - DCHECK(callback); - DCHECK(flip_.get()); - - // If we have data buffered, complete the IO immediately. - if (response_body_.size()) { - int bytes_read = 0; - while (response_body_.size() && buf_len > 0) { - scoped_refptr<IOBufferWithSize> data = response_body_.front(); - int bytes_to_copy = std::min(buf_len, data->size()); - memcpy(&(buf->data()[bytes_read]), data->data(), bytes_to_copy); - buf_len -= bytes_to_copy; - if (bytes_to_copy == data->size()) { - response_body_.pop_front(); - } else { - int bytes_remaining = data->size() - bytes_to_copy; - IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); - memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), - bytes_remaining); - response_body_.pop_front(); - response_body_.push_front(new_buffer); - } - bytes_read += bytes_to_copy; - } - return bytes_read; - } - - if (response_complete_) - return 0; // We already finished reading this stream. - - user_callback_ = callback; - user_buffer_ = buf; - user_buffer_bytes_remaining_ = buf_len; - return net::ERR_IO_PENDING; -} - -const HttpResponseInfo* FlipNetworkTransaction::GetResponseInfo() const { - return (response_.headers || response_.ssl_info.cert) ? &response_ : NULL; -} - -LoadState FlipNetworkTransaction::GetLoadState() const { - switch (next_state_) { - case STATE_INIT_CONNECTION_COMPLETE: - if (flip_.get()) - return flip_->GetLoadState(); - return LOAD_STATE_CONNECTING; - case STATE_SEND_REQUEST_COMPLETE: - return LOAD_STATE_SENDING_REQUEST; - case STATE_READ_HEADERS_COMPLETE: - return LOAD_STATE_WAITING_FOR_RESPONSE; - case STATE_READ_BODY_COMPLETE: - return LOAD_STATE_READING_RESPONSE; - default: - return LOAD_STATE_IDLE; - } -} - -uint64 FlipNetworkTransaction::GetUploadProgress() const { - if (!request_body_stream_.get()) - return 0; - - return request_body_stream_->position(); -} - - -void FlipNetworkTransaction::DoHttpTransactionCallback(int rv) { - DCHECK(rv != ERR_IO_PENDING); - - // Because IO is asynchronous from the caller, we could be completing an - // IO even though the user hasn't issued a Read() yet. - if (!user_callback_) - return; - - // Since Run may result in Read being called, clear user_callback_ up front. - CompletionCallback* c = user_callback_; - user_callback_ = NULL; - c->Run(rv); -} - -int FlipNetworkTransaction::DoLoop(int result) { - DCHECK(next_state_ != STATE_NONE); - DCHECK(request_); - - if (!request_) - return 0; - - int rv = result; - do { - State state = next_state_; - next_state_ = STATE_NONE; - switch (state) { - case STATE_INIT_CONNECTION: - DCHECK_EQ(OK, rv); - rv = DoInitConnection(); - break; - case STATE_INIT_CONNECTION_COMPLETE: - rv = DoInitConnectionComplete(rv); - break; - case STATE_SEND_REQUEST: - DCHECK_EQ(OK, rv); - rv = DoSendRequest(); - break; - case STATE_SEND_REQUEST_COMPLETE: - rv = DoSendRequestComplete(rv); - break; - case STATE_READ_HEADERS: - DCHECK_EQ(OK, rv); - rv = DoReadHeaders(); - break; - case STATE_READ_HEADERS_COMPLETE: - // DoReadHeadersComplete only returns OK becaue the transaction - // could be destroyed as part of the call. - rv = DoReadHeadersComplete(rv); - DCHECK(rv == net::OK); - return rv; - break; - case STATE_READ_BODY: - DCHECK_EQ(OK, rv); - rv = DoReadBody(); - // DoReadBody only returns OK becaue the transaction could be - // destroyed as part of the call. - DCHECK(rv == net::OK); - return rv; - break; - case STATE_READ_BODY_COMPLETE: - // We return here because the Transaction could be destroyed after this - // call. - rv = DoReadBodyComplete(rv); - DCHECK(rv == net::OK); - return rv; - break; - case STATE_NONE: - rv = ERR_FAILED; - break; - default: - NOTREACHED() << "bad state"; - rv = ERR_FAILED; - break; - } - } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); - - return rv; -} - -int FlipNetworkTransaction::DoInitConnection() { - next_state_ = STATE_INIT_CONNECTION_COMPLETE; - - std::string host = request_->url.HostNoBrackets(); - int port = request_->url.EffectiveIntPort(); - - std::string connection_group = "flip."; - connection_group.append(host); - - HostResolver::RequestInfo resolve_info(host, port); - -// TODO(mbelshe): Cleanup these testing tricks. -// If we want to use multiple connections, grab the flip session -// up front using the original domain name. -#undef USE_MULTIPLE_CONNECTIONS -#define DIVERT_URLS_TO_TEST_SERVER -#if defined(USE_MULTIPLE_CONNECTIONS) || !defined(DIVERT_URLS_TO_TEST_SERVER) - flip_ = FlipSession::GetFlipSession(resolve_info, session_); -#endif - -// Use this to divert URLs to a test server. -#ifdef DIVERT_URLS_TO_TEST_SERVER - // Fake out this session to go to our test server. - host = "servername"; - port = 443; - resolve_info = HostResolver::RequestInfo(host, port); -#ifndef USE_MULTIPLE_CONNECTIONS - flip_ = FlipSession::GetFlipSession(resolve_info, session_); -#endif // USE_MULTIPLE_CONNECTIONS - -#endif // DIVERT_URLS_TO_TEST_SERVER - - int rv = flip_->Connect(connection_group, resolve_info, request_->priority); - DCHECK(rv == net::OK); // The API says it will always return OK. - return net::OK; -} - -int FlipNetworkTransaction::DoInitConnectionComplete(int result) { - if (result < 0) - return result; - - next_state_ = STATE_SEND_REQUEST; - return net::OK; -} - -int FlipNetworkTransaction::DoSendRequest() { - // TODO(mbelshe): rethink this UploadDataStream wrapper. - if (request_->upload_data) - request_body_stream_.reset(new UploadDataStream(request_->upload_data)); - - flip_request_id_ = flip_->CreateStream(this); - - if (response_complete_) - return net::OK; - - // The FlipSession will always call us back when the send is complete. - return net::ERR_IO_PENDING; -} - -int FlipNetworkTransaction::DoSendRequestComplete(int result) { - if (result < 0) - return result; - - next_state_ = STATE_READ_HEADERS; - return net::OK; -} - -int FlipNetworkTransaction::DoReadHeaders() { - // The FlipSession will always call us back when the headers have been - // received. - return net::ERR_IO_PENDING; -} - -int FlipNetworkTransaction::DoReadHeadersComplete(int result) { - // Notify the user that the headers are ready. - DoHttpTransactionCallback(result); - return net::OK; -} - -int FlipNetworkTransaction::DoReadBody() { - // The caller has not issued a read request yet. - if (!user_callback_) - return net::OK; - - int bytes_read = 0; - while (response_body_.size() && user_buffer_bytes_remaining_ > 0) { - scoped_refptr<IOBufferWithSize> data = response_body_.front(); - int bytes_to_copy = std::min(user_buffer_bytes_remaining_, data->size()); - memcpy(&(user_buffer_->data()[bytes_read]), data->data(), bytes_to_copy); - user_buffer_bytes_remaining_ -= bytes_to_copy; - if (bytes_to_copy == data->size()) { - response_body_.pop_front(); - } else { - int bytes_remaining = data->size() - bytes_to_copy; - IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); - memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), - bytes_remaining); - response_body_.pop_front(); - response_body_.push_front(new_buffer); - } - bytes_read += bytes_to_copy; - } - - DoHttpTransactionCallback(bytes_read); - return net::OK; -} - -int FlipNetworkTransaction::DoReadBodyComplete(int result) { - // TODO(mbelshe): record success or failure of the transaction? - if (user_callback_) - DoHttpTransactionCallback(result); - return OK; -} - -} // namespace net diff --git a/net/flip/flip_network_transaction.h b/net/flip/flip_network_transaction.h deleted file mode 100644 index f4b0292..0000000 --- a/net/flip/flip_network_transaction.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_FLIP_NETWORK_TRANSACTION_H_ -#define NET_FLIP_NETWORK_TRANSACTION_H_ - -#include <string> -#include <deque> - -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "base/time.h" -#include "net/base/address_list.h" -#include "net/base/host_resolver.h" -#include "net/base/io_buffer.h" -#include "net/base/load_flags.h" -#include "net/base/load_states.h" -#include "net/base/ssl_config_service.h" -#include "net/flip/flip_session.h" -#include "net/http/http_auth.h" -#include "net/http/http_auth_handler.h" -#include "net/http/http_response_info.h" -#include "net/http/http_transaction.h" -#include "net/proxy/proxy_service.h" -#include "net/socket/client_socket_handle.h" -#include "net/socket/client_socket_pool.h" -#include "testing/gtest/include/gtest/gtest_prod.h" - -namespace net { - -class ClientSocketFactory; -class HttpNetworkSession; -class UploadDataStream; - -// A FlipNetworkTransaction can be used to fetch HTTP conent. -// The FlipDelegate is the consumer of events from the FlipSession. -class FlipNetworkTransaction : public HttpTransaction, public FlipDelegate { - public: - explicit FlipNetworkTransaction(HttpNetworkSession* session); - virtual ~FlipNetworkTransaction(); - - // FlipDelegate methods: - virtual const HttpRequestInfo* request(); - virtual const UploadDataStream* data(); - virtual void OnRequestSent(int status); - virtual void OnResponseReceived(HttpResponseInfo* response); - virtual void OnDataReceived(const char* buffer, int bytes); - virtual void OnClose(int status); - virtual void OnCancel(); - - // HttpTransaction methods: - virtual int Start(const HttpRequestInfo* request_info, - CompletionCallback* callback, - LoadLog* load_log); - virtual int RestartIgnoringLastError(CompletionCallback* callback); - virtual int RestartWithCertificate(X509Certificate* client_cert, - CompletionCallback* callback); - virtual int RestartWithAuth(const std::wstring& username, - const std::wstring& password, - CompletionCallback* callback); - virtual bool IsReadyToRestartForAuth() { return false; } - virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); - virtual const HttpResponseInfo* GetResponseInfo() const; - virtual LoadState GetLoadState() const; - virtual uint64 GetUploadProgress() const; - - protected: - friend class FlipNetworkTransactionTest; - - // Provide access to the session for testing. - FlipSession* GetFlipSession() { return flip_.get(); } - - private: - enum State { - STATE_INIT_CONNECTION, - STATE_INIT_CONNECTION_COMPLETE, - STATE_SEND_REQUEST, - STATE_SEND_REQUEST_COMPLETE, - STATE_READ_HEADERS, - STATE_READ_HEADERS_COMPLETE, - STATE_READ_BODY, - STATE_READ_BODY_COMPLETE, - STATE_NONE - }; - - // Used to callback an HttpTransaction call. - void DoHttpTransactionCallback(int result); - - // Runs the state transition loop. - int DoLoop(int result); - - // Each of these methods corresponds to a State value. Those with an input - // argument receive the result from the previous state. If a method returns - // ERR_IO_PENDING, then the result from OnIOComplete will be passed to the - // next state method as the result arg. - int DoInitConnection(); - int DoInitConnectionComplete(int result); - int DoSendRequest(); - int DoSendRequestComplete(int result); - int DoReadHeaders(); - int DoReadHeadersComplete(int result); - int DoReadBody(); - int DoReadBodyComplete(int result); - - // The Flip request id for this request. - int flip_request_id_; - - // The Flip session servicing this request. If NULL, the request has not - // started. - scoped_refptr<FlipSession> flip_; - - CompletionCallback* user_callback_; - scoped_refptr<IOBuffer> user_buffer_; - int user_buffer_bytes_remaining_; - - scoped_refptr<HttpNetworkSession> session_; - - const HttpRequestInfo* request_; - HttpResponseInfo response_; - - scoped_ptr<UploadDataStream> request_body_stream_; - - // We buffer the response body as it arrives asynchronously from the stream. - // TODO(mbelshe): is this infinite buffering? - std::deque<scoped_refptr<IOBufferWithSize> > response_body_; - bool response_complete_; - // Since we buffer the response, we also buffer the response status. - // Not valid until response_complete_ is true. - int response_status_; - - // The time the Start method was called. - base::Time start_time_; - - // The next state in the state machine. - State next_state_; -}; - -} // namespace net - -#endif // NET_HTTP_NETWORK_TRANSACTION_H_ - diff --git a/net/flip/flip_network_transaction_unittest.cc b/net/flip/flip_network_transaction_unittest.cc deleted file mode 100644 index 29db36c..0000000 --- a/net/flip/flip_network_transaction_unittest.cc +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <math.h> // ceil - -#include "base/compiler_specific.h" -#include "net/base/completion_callback.h" -#include "net/base/mock_host_resolver.h" -#include "net/base/ssl_config_service_defaults.h" -#include "net/base/ssl_info.h" -#include "net/base/test_completion_callback.h" -#include "net/base/upload_data.h" -#include "net/flip/flip_network_transaction.h" -#include "net/flip/flip_protocol.h" -#include "net/http/http_auth_handler_ntlm.h" -#include "net/http/http_network_session.h" -#include "net/http/http_network_transaction.h" -#include "net/http/http_transaction_unittest.h" -#include "net/proxy/proxy_config_service_fixed.h" -#include "net/socket/client_socket_factory.h" -#include "net/socket/socket_test_util.h" -#include "net/socket/ssl_client_socket.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -//----------------------------------------------------------------------------- - -namespace flip { - -using namespace net; - -// Create a proxy service which fails on all requests (falls back to direct). -ProxyService* CreateNullProxyService() { - return ProxyService::CreateNull(); -} - -// Helper to manage the lifetimes of the dependencies for a -// HttpNetworkTransaction. -class SessionDependencies { - public: - // Default set of dependencies -- "null" proxy service. - SessionDependencies() - : host_resolver(new MockHostResolver), - proxy_service(CreateNullProxyService()), - ssl_config_service(new SSLConfigServiceDefaults) {} - - // Custom proxy service dependency. - explicit SessionDependencies(ProxyService* proxy_service) - : host_resolver(new MockHostResolver), - proxy_service(proxy_service), - ssl_config_service(new SSLConfigServiceDefaults) {} - - scoped_refptr<MockHostResolverBase> host_resolver; - scoped_refptr<ProxyService> proxy_service; - scoped_refptr<SSLConfigService> ssl_config_service; - MockClientSocketFactory socket_factory; -}; - -ProxyService* CreateFixedProxyService(const std::string& proxy) { - net::ProxyConfig proxy_config; - proxy_config.proxy_rules.ParseFromString(proxy); - return ProxyService::CreateFixed(proxy_config); -} - - -HttpNetworkSession* CreateSession(SessionDependencies* session_deps) { - return new HttpNetworkSession(session_deps->host_resolver, - session_deps->proxy_service, - &session_deps->socket_factory, - session_deps->ssl_config_service); -} - -class FlipNetworkTransactionTest : public PlatformTest { - public: - virtual void SetUp() { - // Disable compression on this test. - FlipFramer::set_enable_compression_default(false); - } - - virtual void TearDown() { - // Empty the current queue. - MessageLoop::current()->RunAllPending(); - PlatformTest::TearDown(); - } - - protected: - void KeepAliveConnectionResendRequestTest(const MockRead& read_failure); - - struct SimpleGetHelperResult { - int rv; - std::string status_line; - std::string response_data; - }; - - SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) { - SimpleGetHelperResult out; - - SessionDependencies session_deps; - scoped_ptr<FlipNetworkTransaction> trans( - new FlipNetworkTransaction( - CreateSession(&session_deps))); - - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("http://www.google.com/"); - request.load_flags = 0; - - StaticMockSocket data(data_reads, NULL); - session_deps.socket_factory.AddMockSocket(&data); - - TestCompletionCallback callback; - - int rv = trans->Start(&request, &callback, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - out.rv = callback.WaitForResult(); - if (out.rv != OK) - return out; - - const HttpResponseInfo* response = trans->GetResponseInfo(); - EXPECT_TRUE(response != NULL); - - EXPECT_TRUE(response->headers != NULL); - out.status_line = response->headers->GetStatusLine(); - - rv = ReadTransaction(trans.get(), &out.response_data); - EXPECT_EQ(OK, rv); - - return out; - } - - void ConnectStatusHelperWithExpectedStatus(const MockRead& status, - int expected_status); - - void ConnectStatusHelper(const MockRead& status); -}; - -//----------------------------------------------------------------------------- - -// Verify FlipNetworkTransaction constructor. -TEST_F(FlipNetworkTransactionTest, Constructor) { - SessionDependencies session_deps; - scoped_refptr<net::HttpNetworkSession> session = - CreateSession(&session_deps); - scoped_ptr<HttpTransaction> trans(new FlipNetworkTransaction(session)); -} - -TEST_F(FlipNetworkTransactionTest, Connect) { - unsigned char syn_reply[] = { - 0x80, 0x01, 0x00, 0x02, // header - 0x00, 0x00, 0x00, 0x45, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x04, // 4 headers - 0x00, 0x05, 'h', 'e', 'l', 'l', 'o', // "hello" - 0x00, 0x03, 'b', 'y', 'e', // "bye" - 0x00, 0x06, 's', 't', 'a', 't', 'u', 's', // "status" - 0x00, 0x03, '2', '0', '0', // "200" - 0x00, 0x03, 'u', 'r', 'l', // "url" - 0x00, 0x0a, '/', 'i', 'n', 'd', 'e', 'x', '.', 'p', 'h', 'p', // "HTTP/1.1" - 0x00, 0x07, 'v', 'e', 'r', 's', 'i', 'o', 'n', // "version" - 0x00, 0x08, 'H', 'T', 'T', 'P', '/', '1', '.', '1', // "HTTP/1.1" - }; - unsigned char body_frame[] = { - 0x00, 0x00, 0x00, 0x01, // header - 0x00, 0x00, 0x00, 0x06, - 'h', 'e', 'l', 'l', 'o', '!', // "hello" - }; - unsigned char fin_frame[] = { - 0x80, 0x01, 0x00, 0x03, // header - 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, - }; - - MockRead data_reads[] = { - MockRead(true, reinterpret_cast<char*>(syn_reply), sizeof(syn_reply)), - MockRead(true, reinterpret_cast<char*>(body_frame), sizeof(body_frame)), - MockRead(true, reinterpret_cast<char*>(fin_frame), sizeof(fin_frame)), - MockRead(true, 0, 0), // EOF - }; - - SimpleGetHelperResult out = SimpleGetHelper(data_reads); - EXPECT_EQ(OK, out.rv); - EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); - EXPECT_EQ("hello!", out.response_data); -} - -} // namespace net - diff --git a/net/flip/flip_protocol.h b/net/flip/flip_protocol.h deleted file mode 100644 index 93c8a5a..0000000 --- a/net/flip/flip_protocol.h +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains some protocol structures for use with Flip. - -#ifndef NET_FLIP_FLIP_PROTOCOL_H_ -#define NET_FLIP_FLIP_PROTOCOL_H_ - -#ifdef WIN32 -#include <winsock2.h> -#else -#include <arpa/inet.h> -#endif -#include "base/basictypes.h" -#include "base/logging.h" -#include "flip_bitmasks.h" // cross-google3 directory naming. - - -// Stream Frame Format -// +-------------------------------+ -// |0| Stream-ID (31bits) | -// +-------------------------------+ -// |flags (16)| Length (16bits) | -// +-------------------------------+ -// | Data | -// +-------------------------------+ -// - -// Control Frame Format -// +-------------------------------+ -// |1| Version(15bits)|Type(16bits)| -// +-------------------------------+ -// | Length (32bits) | -// +-------------------------------+ -// | Data | -// +-------------------------------+ -// - - -// Control Frame: SYN_STREAM -// +----------------------------------+ -// |1|000000000000001|0000000000000001| -// +----------------------------------+ -// | Length (32bits) | >= 8 -// +----------------------------------+ -// |X| Stream-ID(31bits) | -// +----------------------------------+ -// |Pri| unused | Length (16bits)| -// +----------------------------------+ -// -// Control Frame: SYN_REPLY -// +----------------------------------+ -// |1|000000000000001|0000000000000010| -// +----------------------------------+ -// | Length (32bits) | >= 8 -// +----------------------------------+ -// |X| Stream-ID(31bits) | -// +----------------------------------+ -// | unused (16 bits)| Length (16bits)| -// +----------------------------------+ -// -// Control Frame: FIN_STREAM -// +----------------------------------+ -// |1|000000000000001|0000000000000011| -// +----------------------------------+ -// | Length (32bits) | >= 4 -// +----------------------------------+ -// |X| Stream-ID(31bits) | -// +----------------------------------+ -// | Status (32 bits) | -// +----------------------------------+ -// -// Control Frame: SetMaxStreams -// +----------------------------------+ -// |1|000000000000001|0000000000000100| -// +----------------------------------+ -// | Length (32bits) | >= 4 -// +----------------------------------+ -// |X| Stream-ID(31bits) | -// +----------------------------------+ - -// TODO(fenix): add ChangePriority support. - -namespace flip { - -// Note: all protocol data structures are on-the-wire format. That means that -// data is stored in network-normalized order. Readers must use the -// accessors provided or call ntohX() functions. - -// Types of Flip Control Frames. -typedef enum { - SYN_STREAM = 1, - SYN_REPLY, - FIN_STREAM, - NOOP -} FlipControlType; - -// Flags on data packets -typedef enum { - DATA_FLAG_COMPRESSED = 1 -} FlipDataFlags; - -// A FLIP stream id is a 31 bit entity. -typedef uint32 FlipStreamId; - -// FLIP Priorities. (there are only 2 bits) -#define FLIP_PRIORITY_LOWEST 3 -#define FLIP_PRIORITY_HIGHEST 0 - -// All Flip Frame types derive from the FlipFrame struct. -typedef struct { - uint32 length() const { return ntohs(data_.length_); } - void set_length(uint16 length) { data_.length_ = htons(length); } - bool is_control_frame() const { - return (ntohs(control_.version_) & kControlFlagMask) == kControlFlagMask; - } - - protected: - union { - struct { - uint16 version_; - uint16 type_; - uint32 length_; - } control_; - struct { - FlipStreamId stream_id_; - uint16 flags_; - uint16 length_; - } data_; - }; -} FlipFrame; - -// A Data Frame. -typedef struct : public FlipFrame { - FlipStreamId stream_id() const { - return ntohl(data_.stream_id_) & kStreamIdMask; - } - void set_stream_id(FlipStreamId id) { data_.stream_id_ = htonl(id); } - uint16 flags() const { return ntohs(data_.flags_); } - void set_flags(uint16 flags) { data_.flags_ = htons(flags); } -} FlipDataFrame; - -// A Control Frame. -typedef struct : public FlipFrame { - uint16 version() const { - const int kVersionMask = 0x7fff; - return ntohs(control_.version_) & kVersionMask; - } - FlipControlType type() const { - uint16 type = ntohs(control_.type_); - DCHECK(type >= SYN_STREAM && type <= NOOP); - return static_cast<FlipControlType>(type); - } - FlipStreamId stream_id() const { return ntohl(stream_id_) & kStreamIdMask; } - - private: - FlipStreamId stream_id_; -} FlipControlFrame; - -// A SYN_STREAM frame. -typedef struct FlipSynStreamControlFrame : public FlipControlFrame { - uint8 priority() const { return (priority_ & kPriorityMask) >> 6; } - int header_block_len() const { return length() - kHeaderBlockOffset; } - const char* header_block() const { - return reinterpret_cast<const char*>(this) + - sizeof(FlipFrame) + kHeaderBlockOffset; - } - private: - // Offset from the end of the FlipControlFrame to the FlipHeaderBlock. - static const int kHeaderBlockOffset = 6; - uint8 priority_; - uint8 unused_; - // Variable FlipHeaderBlock here. -} FlipSynStreamControlFrame; - -// A SYN_REPLY frame. -typedef struct FlipSynReplyControlFrame : public FlipControlFrame { - int header_block_len() const { return length() - kHeaderBlockOffset; } - const char* header_block() const { - return reinterpret_cast<const char*>(this) + - sizeof(FlipFrame) + kHeaderBlockOffset; - } - - private: - // Offset from the end of the FlipControlFrame to the FlipHeaderBlock. - static const int kHeaderBlockOffset = 6; - uint16 unused_; - // Variable FlipHeaderBlock here. -} FlipSynReplyControlFrame; - -// A FIN_STREAM frame. -typedef struct FlipFinStreamControlFrame : public FlipControlFrame { - uint32 status() const { return ntohl(status_); } - void set_status(int id) { status_ = htonl(id); } - private: - uint32 status_; -} FlipFinStreamControlFrame; - -} // namespace flip - -#endif // NET_FLIP_FLIP_PROTOCOL_H_ - diff --git a/net/flip/flip_session.cc b/net/flip/flip_session.cc deleted file mode 100644 index 3d63ef9..0000000 --- a/net/flip/flip_session.cc +++ /dev/null @@ -1,762 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/flip/flip_session.h" - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/rand_util.h" -#include "base/stats_counters.h" -#include "base/string_util.h" -#include "net/base/load_flags.h" -#include "net/flip/flip_frame_builder.h" -#include "net/flip/flip_protocol.h" -#include "net/http/http_network_session.h" -#include "net/http/http_request_info.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_response_info.h" -#include "net/tools/dump_cache/url_to_filename_encoder.h" - -namespace net { - -// static -scoped_ptr<FlipSessionPool> FlipSession::session_pool_; -// static -bool FlipSession::disable_compression_ = false; -// static -int PrioritizedIOBuffer::order_ = 0; - -// The FlipStreamImpl is an internal class representing an active FlipStream. -class FlipStreamImpl { - public: - // A FlipStreamImpl represents an active FlipStream. - // If |delegate| is NULL, then we're receiving pushed data from the server. - FlipStreamImpl(flip::FlipStreamId stream_id, FlipDelegate* delegate) - : stream_id_(stream_id), - delegate_(delegate), - response_(NULL), - data_complete_(false) {} - virtual ~FlipStreamImpl() { - LOG(INFO) << "Deleting FlipStreamImpl for stream " << stream_id_; - }; - - flip::FlipStreamId stream_id() const { return stream_id_; } - FlipDelegate* delegate() const { return delegate_; } - - // For pushed streams, we track a path to identify them. - std::string path() const { return path_; } - void set_path(const std::string& path) { path_ = path; } - - // Attach a delegate to a previously pushed data stream. - // Returns true if the caller should Deactivate and delete the FlipStreamImpl - // after this call. - bool AttachDelegate(FlipDelegate* delegate); - - // Called when a SYN_REPLY is received on the stream. - void OnReply(const flip::FlipHeaderBlock* headers); - - // Called when data is received on the stream. - // Returns true if the caller should Deactivate and delete the FlipStreamImpl - // after this call. - bool OnData(const char* data, int length); - - // Called if the stream is prematurely aborted. - // The caller should Deactivate and delete the FlipStreamImpl after this - // call. - void OnAbort(); - - private: - flip::FlipStreamId stream_id_; - std::string path_; - FlipDelegate* delegate_; - scoped_ptr<HttpResponseInfo> response_; - std::list<scoped_refptr<IOBufferWithSize>> response_body_; - bool data_complete_; -}; - -FlipSession* FlipSession::GetFlipSession( - const net::HostResolver::RequestInfo& info, - HttpNetworkSession* session) { - if (!session_pool_.get()) - session_pool_.reset(new FlipSessionPool()); - return session_pool_->Get(info, session); -} - -FlipSession::FlipSession(std::string host, HttpNetworkSession* session) - : ALLOW_THIS_IN_INITIALIZER_LIST( - connect_callback_(this, &FlipSession::OnSocketConnect)), - ALLOW_THIS_IN_INITIALIZER_LIST( - read_callback_(this, &FlipSession::OnReadComplete)), - ALLOW_THIS_IN_INITIALIZER_LIST( - write_callback_(this, &FlipSession::OnWriteComplete)), - domain_(host), - session_(session), - connection_started_(false), - delayed_write_pending_(false), - write_pending_(false), - read_buffer_(new net::MovableIOBuffer(kReadBufferSize)), - read_buffer_bytes_read_(0), - read_pending_(false), - stream_hi_water_mark_(0) { - // Always start at 1 for the first stream id. - // TODO(mbelshe): consider randomization. - stream_hi_water_mark_ = 1; - - flip_framer_.set_visitor(this); -} - -FlipSession::~FlipSession() { - if (connection_.is_initialized()) { - // With Flip we can't recycle sockets. - connection_.socket()->Disconnect(); - } - if (session_pool_.get()) - session_pool_->Remove(this); - - // TODO(mbelshe) - clear out streams (active and pushed) here? -} - -net::Error FlipSession::Connect(const std::string& group_name, - const HostResolver::RequestInfo& host, - int priority) { - DCHECK(priority >= 0 && priority < 4); - - // If the connect process is started, let the caller continue. - if (connection_started_) - return net::OK; - - connection_started_ = true; - - static StatsCounter flip_sessions("flip.sessions"); - flip_sessions.Increment(); - - int rv = connection_.Init(group_name, host, priority, &connect_callback_, - session_->tcp_socket_pool(), NULL); - - // If the connect is pending, we still return ok. The APIs enqueue - // work until after the connect completes asynchronously later. - if (rv == net::ERR_IO_PENDING) - return net::OK; - return static_cast<net::Error>(rv); -} - - -// Create a FlipHeaderBlock for a Flip SYN_STREAM Frame from -// a HttpRequestInfo block. -void CreateFlipHeadersFromHttpRequest( - const HttpRequestInfo* info, flip::FlipHeaderBlock* headers) { - static const std::string kHttpProtocolVersion("HTTP/1.1"); - - HttpUtil::HeadersIterator it(info->extra_headers.begin(), - info->extra_headers.end(), - "\r\n"); - while (it.GetNext()) { - std::string name = StringToLowerASCII(it.name()); - (*headers)[name] = it.values(); - } - -#define REWRITE_URLS -#ifdef REWRITE_URLS - // TODO(mbelshe): Figure out how to remove this. This is just for hooking - // up to a test server. - // For testing content on our test server, we modify the URL. - GURL url = info->url; - FilePath path = UrlToFilenameEncoder::Encode(url.spec(), FilePath()); - std::string hack_url = "/" + WideToASCII(path.value()); - - // switch backslashes. HACK - std::string::size_type pos(0); - while ((pos = hack_url.find('\\', pos)) != std::string::npos) { - hack_url.replace(pos, 1, "/"); - pos += 1; - } -#endif - - (*headers)["method"] = info->method; - // (*headers)["url"] = info->url.PathForRequest(); - (*headers)["url"] = hack_url; - (*headers)["version"] = kHttpProtocolVersion; - if (info->user_agent.length()) - (*headers)["user-agent"] = info->user_agent; - if (!info->referrer.is_empty()) - (*headers)["referer"] = info->referrer.spec(); - - // Honor load flags that impact proxy caches. - if (info->load_flags & LOAD_BYPASS_CACHE) { - (*headers)["pragma"] = "no-cache"; - (*headers)["cache-control"] = "no-cache"; - } else if (info->load_flags & LOAD_VALIDATE_CACHE) { - (*headers)["cache-control"] = "max-age=0"; - } -} - -int FlipSession::CreateStream(FlipDelegate* delegate) { - flip::FlipStreamId stream_id = GetNewStreamId(); - - GURL url = delegate->request()->url; - std::string path = url.PathForRequest(); - - FlipStreamImpl* stream = NULL; - - // Check if we have a push stream for this path. - if (delegate->request()->method == "GET") { - stream = GetPushStream(path); - if (stream) { - if (stream->AttachDelegate(delegate)) { - DeactivateStream(stream->stream_id()); - delete stream; - return 0; - } - return stream->stream_id(); - } - } - - // If we still don't have a stream, activate one now. - stream = ActivateStream(stream_id, delegate); - if (!stream) - return net::ERR_FAILED; - - LOG(INFO) << "FlipStream: Creating stream " << stream_id << " for " - << delegate->request()->url; - - // TODO(mbelshe): Optimize memory allocations - int priority = delegate->request()->priority; - - // Hack for the priorities - // TODO(mbelshe): These need to be plumbed through the Http Network Stack. - if (path.find(".css") != path.npos) { - priority = 1; - } else if (path.find(".html") != path.npos) { - priority = 0; - } else if (path.find(".js") != path.npos) { - priority = 1; - } else { - priority = 3; - } - - DCHECK(priority >= FLIP_PRIORITY_HIGHEST && - priority <= FLIP_PRIORITY_LOWEST); - - // Convert from HttpRequestHeaders to Flip Headers. - flip::FlipHeaderBlock headers; - CreateFlipHeadersFromHttpRequest(delegate->request(), &headers); - - // Create a SYN_STREAM packet and add to the output queue. - flip::FlipSynStreamControlFrame* syn_frame = - flip_framer_.CreateSynStream(stream_id, priority, false, &headers); - int length = sizeof(flip::FlipFrame) + syn_frame->length(); - IOBufferWithSize* buffer = - new IOBufferWithSize(length); - memcpy(buffer->data(), syn_frame, length); - delete syn_frame; - queue_.push(PrioritizedIOBuffer(buffer, priority)); - - static StatsCounter flip_requests("flip.requests"); - flip_requests.Increment(); - - LOG(INFO) << "FETCHING: " << delegate->request()->url.spec(); - - - // TODO(mbelshe): Implement POST Data here - - // Schedule to write to the socket after we've made it back - // to the message loop so that we can aggregate multiple - // requests. - // TODO(mbelshe): Should we do the "first" request immediately? - // maybe we should only 'do later' for subsequent - // requests. - WriteSocketLater(); - - return stream_id; -} - -bool FlipSession::CancelStream(int id) { - LOG(INFO) << "Cancelling stream " << id; - if (!IsStreamActive(id)) - return false; - DeactivateStream(id); - return true; -} - -bool FlipSession::IsStreamActive(int id) { - return active_streams_.find(id) != active_streams_.end(); -} - -LoadState FlipSession::GetLoadState() const { - // TODO(mbelshe): needs more work - return LOAD_STATE_CONNECTING; -} - -void FlipSession::OnSocketConnect(int result) { - LOG(INFO) << "Flip socket connected (result=" << result << ")"; - - if (result != net::OK) { - net::Error err = static_cast<net::Error>(result); - CloseAllStreams(err); - this->Release(); - return; - } - - // Adjust socket buffer sizes. - // FLIP uses one socket, and we want a really big buffer. - // This greatly helps on links with packet loss - we can even - // outperform Vista's dynamic window sizing algorithm. - // TODO(mbelshe): more study. - const int kSocketBufferSize = 512 * 1024; - connection_.socket()->SetReceiveBufferSize(kSocketBufferSize); - connection_.socket()->SetSendBufferSize(kSocketBufferSize); - - // After we've connected, send any data to the server, and then issue - // our read. - WriteSocketLater(); - ReadSocket(); -} - -void FlipSession::OnReadComplete(int bytes_read) { - // Parse a frame. For now this code requires that the frame fit into our - // buffer (32KB). - // TODO(mbelshe): support arbitrarily large frames! - - LOG(INFO) << "Flip socket read: " << bytes_read << " bytes"; - - read_pending_ = false; - - if (bytes_read <= 0) { - // Session is tearing down. - net::Error err = static_cast<net::Error>(bytes_read); - CloseAllStreams(err); - this->Release(); - return; - } - - char *data = read_buffer_->data(); - while (bytes_read && - flip_framer_.error_code() == flip::FlipFramer::FLIP_NO_ERROR) { - uint32 bytes_processed = flip_framer_.ProcessInput(data, bytes_read); - bytes_read -= bytes_processed; - data += bytes_processed; - if (flip_framer_.state() == flip::FlipFramer::FLIP_DONE) - flip_framer_.Reset(); - } - // NOTE(mbelshe): Could cause circular callbacks. (when ReadSocket - // completes synchronously, calling OnReadComplete, etc). Should - // probably return to the message loop. - ReadSocket(); -} - -void FlipSession::OnWriteComplete(int result) { - DCHECK(write_pending_); - write_pending_ = false; - - LOG(INFO) << "Flip write complete (result=" << result << ")"; - - // Cleanup the write which just completed. - in_flight_write_.release(); - - // Write more data. We're already in a continuation, so we can - // go ahead and write it immediately (without going back to the - // message loop). - WriteSocketLater(); -} - -void FlipSession::ReadSocket() { - if (read_pending_) - return; - - size_t max_bytes = kReadBufferSize; - read_buffer_->set_data(read_buffer_bytes_read_); - max_bytes -= read_buffer_bytes_read_; - int bytes_read = connection_.socket()->Read(read_buffer_.get(), max_bytes, - &read_callback_); - switch (bytes_read) { - case 0: - // Socket is closed! - // TODO(mbelshe): Need to abort any active streams here. - DCHECK(!active_streams_.size()); - return; - case net::ERR_IO_PENDING: - // Waiting for data. Nothing to do now. - read_pending_ = true; - return; - default: - // Data was read, process it. - // TODO(mbelshe): check that we can't get a recursive stack? - OnReadComplete(bytes_read); - break; - } -} - -void FlipSession::WriteSocketLater() { - if (delayed_write_pending_) - return; - - delayed_write_pending_ = true; - MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( - this, &net::FlipSession::WriteSocket)); -} - -void FlipSession::WriteSocket() { - // This function should only be called via WriteSocketLater. - DCHECK(delayed_write_pending_); - delayed_write_pending_ = false; - - // If the socket isn't connected yet, just wait; we'll get called - // again when the socket connection completes. - if (!connection_.is_initialized()) - return; - - if (write_pending_) // Another write is in progress still. - return; - - while (queue_.size()) { - const int kMaxSegmentSize = 1430; - const int kMaxPayload = 4 * kMaxSegmentSize; - int max_size = std::max(kMaxPayload, queue_.top().size()); - - int bytes = 0; - // If we have multiple IOs to do, accumulate up to 4 MSS's worth of data - // and send them in batch. - IOBufferWithSize* buffer = new IOBufferWithSize(max_size); - while (queue_.size() && bytes < max_size) { - PrioritizedIOBuffer next_buffer = queue_.top(); - - // Now that we're outputting the frame, we can finally compress it. - flip::FlipFrame* uncompressed_frame = - reinterpret_cast<flip::FlipFrame*>(next_buffer.buffer()->data()); - scoped_array<flip::FlipFrame> compressed_frame( - flip_framer_.CompressFrame(uncompressed_frame)); - int size = compressed_frame.get()->length() + sizeof(flip::FlipFrame); - if (bytes + size > kMaxPayload) - break; - memcpy(buffer->data() + bytes, compressed_frame.get(), size); - bytes += size; - queue_.pop(); - next_buffer.release(); - } - DCHECK(bytes > 0); - in_flight_write_ = PrioritizedIOBuffer(buffer, 0); - - int rv = connection_.socket()->Write(in_flight_write_.buffer(), - bytes, &write_callback_); - if (rv == net::ERR_IO_PENDING) { - write_pending_ = true; - break; - } - LOG(INFO) << "FLIPSession wrote " << rv << " bytes."; - in_flight_write_.release(); - } -} - -void FlipSession::CloseAllStreams(net::Error code) { - LOG(INFO) << "Closing all FLIP Streams"; - - static StatsCounter abandoned_streams("flip.abandoned_streams"); - static StatsCounter abandoned_push_streams("flip.abandoned_push_streams"); - - if (active_streams_.size()) { - abandoned_streams.Add(active_streams_.size()); - - // Create a copy of the list, since aborting streams can invalidate - // our list. - FlipStreamImpl** list = new FlipStreamImpl*[active_streams_.size()]; - ActiveStreamMap::const_iterator it; - int index = 0; - for (it = active_streams_.begin(); it != active_streams_.end(); ++it) - list[index++] = it->second; - - // Issue the aborts. - for (--index; index >= 0; index--) { - list[index]->OnAbort(); - delete list[index]; - } - - // Clear out anything pending. - active_streams_.clear(); - - delete list; - } - - if (pushed_streams_.size()) { - abandoned_push_streams.Add(pushed_streams_.size()); - pushed_streams_.clear(); - } -} - -int FlipSession::GetNewStreamId() { - int id = stream_hi_water_mark_; - stream_hi_water_mark_ += 2; - if (stream_hi_water_mark_ > 0x7fff) - stream_hi_water_mark_ = 1; - return id; -} - -FlipStreamImpl* FlipSession::ActivateStream(int id, FlipDelegate* delegate) { - DCHECK(!IsStreamActive(id)); - - FlipStreamImpl* stream = new FlipStreamImpl(id, delegate); - active_streams_[id] = stream; - return stream; -} - -void FlipSession::DeactivateStream(int id) { - DCHECK(IsStreamActive(id)); - - // Verify it is not on the pushed_streams_ list. - ActiveStreamList::iterator it; - for (it = pushed_streams_.begin(); it != pushed_streams_.end(); ++it) { - FlipStreamImpl* impl = *it; - if (id == impl->stream_id()) { - pushed_streams_.erase(it); - break; - } - } - - active_streams_.erase(id); -} - -FlipStreamImpl* FlipSession::GetPushStream(std::string path) { - static StatsCounter used_push_streams("flip.claimed_push_streams"); - - LOG(INFO) << "Looking for push stream: " << path; - - // We just walk a linear list here. - ActiveStreamList::iterator it; - for (it = pushed_streams_.begin(); it != pushed_streams_.end(); ++it) { - FlipStreamImpl* impl = *it; - if (path == impl->path()) { - pushed_streams_.erase(it); - used_push_streams.Increment(); - LOG(INFO) << "Push Stream Claim for: " << path; - return impl; - } - } - return NULL; -} - -void FlipSession::OnError(flip::FlipFramer* framer) { - LOG(ERROR) << "FlipSession error!"; - CloseAllStreams(net::ERR_UNEXPECTED); - this->Release(); -} - -void FlipSession::OnStreamFrameData(flip::FlipStreamId stream_id, - const char* data, - uint32 len) { - LOG(INFO) << "Flip data for stream " << stream_id << ", " << len << " bytes"; - bool valid_stream = IsStreamActive(stream_id); - if (!valid_stream) { - LOG(WARNING) << "Received data frame for invalid stream" << stream_id; - return; - } - if (!len) - return; // This was just an empty data packet. - FlipStreamImpl* stream = active_streams_[stream_id]; - if (stream->OnData(data, len)) { - DeactivateStream(stream->stream_id()); - delete stream; - } -} - -void FlipSession::OnSyn(const flip::FlipSynStreamControlFrame* frame, - const flip::FlipHeaderBlock* headers) { - flip::FlipStreamId stream_id = frame->stream_id(); - - // Server-initiated streams should have odd sequence numbers. - if ((stream_id & 0x1) != 0) { - LOG(WARNING) << "Received invalid OnSyn stream id " << stream_id; - return; - } - - if (IsStreamActive(stream_id)) { - LOG(WARNING) << "Received OnSyn for active stream " << stream_id; - return; - } - - FlipStreamImpl* stream = ActivateStream(stream_id, NULL); - stream->OnReply(headers); - - // Verify that the response had a URL for us. - DCHECK(stream->path().length() != 0); - if (stream->path().length() == 0) { - LOG(WARNING) << "Pushed stream did not contain a path."; - DeactivateStream(stream_id); - delete stream; - return; - } - pushed_streams_.push_back(stream); - - LOG(INFO) << "Got pushed stream for " << stream->path(); - - static StatsCounter push_requests("flip.pushed_streams"); - push_requests.Increment(); -} - -void FlipSession::OnSynReply(const flip::FlipSynReplyControlFrame* frame, - const flip::FlipHeaderBlock* headers) { - DCHECK(headers); - flip::FlipStreamId stream_id = frame->stream_id(); - bool valid_stream = IsStreamActive(stream_id); - if (!valid_stream) { - LOG(WARNING) << "Received SYN_REPLY for invalid stream" << stream_id; - return; - } - - FlipStreamImpl* stream = active_streams_[stream_id]; - stream->OnReply(headers); -} - -void FlipSession::OnControl(const flip::FlipControlFrame* frame) { - flip::FlipHeaderBlock headers; - bool parsed_headers = false; - uint32 type = frame->type(); - if (type == flip::SYN_STREAM || type == flip::SYN_REPLY) { - if (!flip_framer_.ParseHeaderBlock( - reinterpret_cast<const flip::FlipFrame*>(frame), &headers)) { - LOG(WARNING) << "Could not parse Flip Control Frame Header"; - return; - } - } - - switch (type) { - case flip::SYN_STREAM: - LOG(INFO) << "Flip SynStream for stream " << frame->stream_id(); - OnSyn(reinterpret_cast<const flip::FlipSynStreamControlFrame*>(frame), - &headers); - break; - case flip::SYN_REPLY: - LOG(INFO) << "Flip SynReply for stream " << frame->stream_id(); - OnSynReply( - reinterpret_cast<const flip::FlipSynReplyControlFrame*>(frame), - &headers); - break; - case flip::FIN_STREAM: - LOG(INFO) << "Flip Fin for stream " << frame->stream_id(); - OnFin(reinterpret_cast<const flip::FlipFinStreamControlFrame*>(frame)); - break; - default: - DCHECK(false); // Error! - } -} - -void FlipSession::OnFin(const flip::FlipFinStreamControlFrame* frame) { - flip::FlipStreamId stream_id = frame->stream_id(); - bool valid_stream = IsStreamActive(stream_id); - if (!valid_stream) { - LOG(WARNING) << "Received FIN for invalid stream" << stream_id; - return; - } - FlipStreamImpl* stream = active_streams_[stream_id]; - // TODO(mbelshe) - status codes are HTTP codes? - // Shouldn't it be zero/nonzero? - // For now Roberto is sending 200, so use that as "ok". - bool cleanup_stream = false; - if (frame->status() == 200 || frame->status() == 0) { - cleanup_stream = stream->OnData(NULL, 0); - } else { - stream->OnAbort(); - cleanup_stream = true; - } - - if (cleanup_stream) { - DeactivateStream(stream_id); - delete stream; - } -} - -void FlipSession::OnLameDuck() { - NOTIMPLEMENTED(); -} - -bool FlipStreamImpl::AttachDelegate(FlipDelegate* delegate) { - DCHECK(delegate_ == NULL); // Don't attach if already attached. - DCHECK(path_.length() > 0); // Path needs to be set for push streams. - delegate_ = delegate; - - // If there is pending data, send it up here. - - // Check for the OnReply, and pass it up. - if (response_.get()) - delegate_->OnResponseReceived(response_.get()); - - // Pass data up - while (response_body_.size()) { - scoped_refptr<IOBufferWithSize> buffer = response_body_.front(); - response_body_.pop_front(); - delegate_->OnDataReceived(buffer->data(), buffer->size()); - } - - // Finally send up the end-of-stream. - if (data_complete_) { - delegate_->OnClose(net::OK); - return true; // tell the caller to shut us down - } - return false; -} - -void FlipStreamImpl::OnReply(const flip::FlipHeaderBlock* headers) { - DCHECK(headers); - DCHECK(headers->find("version") != headers->end()); - DCHECK(headers->find("status") != headers->end()); - - // TODO(mbelshe): if no version or status is found, we need to error - // out the stream. - - // Server initiated streams must send a URL to us in the headers. - if (headers->find("path") != headers->end()) - path_ = headers->find("path")->second; - - // TODO(mbelshe): For now we convert from our nice hash map back - // to a string of headers; this is because the HttpResponseInfo - // is a bit rigid for its http (non-flip) design. - std::string raw_headers(headers->find("version")->second); - raw_headers.append(" ", 1); - raw_headers.append(headers->find("status")->second); - raw_headers.append("\0", 1); - flip::FlipHeaderBlock::const_iterator it; - for (it = headers->begin(); it != headers->end(); ++it) { - raw_headers.append(it->first); - raw_headers.append(":", 1); - raw_headers.append(it->second); - raw_headers.append("\0", 1); - } - - LOG(INFO) << "FlipStream: SynReply received for " << stream_id_; - - DCHECK(response_ == NULL); - response_.reset(new HttpResponseInfo()); - response_->headers = new HttpResponseHeaders(raw_headers); - if (delegate_) - delegate_->OnResponseReceived(response_.get()); -} - -bool FlipStreamImpl::OnData(const char* data, int length) { - LOG(INFO) << "FlipStream: Data (" << length << " bytes) received for " - << stream_id_; - if (length) { - if (delegate_) { - delegate_->OnDataReceived(data, length); - } else { - // Save the data for use later - IOBufferWithSize* io_buffer = new IOBufferWithSize(length); - memcpy(io_buffer->data(), data, length); - response_body_.push_back(io_buffer); - } - } else { - data_complete_ = true; - if (delegate_) { - delegate_->OnClose(net::OK); - return true; // Tell the caller to clean us up. - } - } - return false; -} - -void FlipStreamImpl::OnAbort() { - if (delegate_) - delegate_->OnClose(net::ERR_ABORTED); -} - -} // namespace net - diff --git a/net/flip/flip_session.h b/net/flip/flip_session.h deleted file mode 100644 index b608ddb..0000000 --- a/net/flip/flip_session.h +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_FLIP_FLIP_SESSION_H_ -#define NET_FLIP_FLIP_SESSION_H_ - -#include <deque> -#include <list> -#include <map> -#include <queue> -#include <string> - -#include "base/ref_counted.h" -#include "net/base/io_buffer.h" -#include "net/base/load_states.h" -#include "net/base/net_errors.h" -#include "net/base/upload_data_stream.h" -#include "net/flip/flip_framer.h" -#include "net/flip/flip_protocol.h" -#include "net/flip/flip_session_pool.h" -#include "net/socket/client_socket.h" -#include "net/socket/client_socket_handle.h" -#include "testing/platform_test.h" - -namespace net { - -class FlipStreamImpl; -class HttpNetworkSession; -class HttpRequestInfo; -class HttpResponseInfo; - -// A callback interface for HTTP content retrieved from the Flip stream. -class FlipDelegate { - public: - virtual ~FlipDelegate() {} - virtual const HttpRequestInfo* request() = 0; - virtual const UploadDataStream* data() = 0; - - virtual void OnRequestSent(int status) = 0; - virtual void OnResponseReceived(HttpResponseInfo* response) = 0; - virtual void OnDataReceived(const char* buffer, int bytes) = 0; - virtual void OnClose(int status) = 0; - virtual void OnCancel() = 0; -}; - -class PrioritizedIOBuffer { - public: - PrioritizedIOBuffer() : buffer_(0), priority_(0) {} - PrioritizedIOBuffer(IOBufferWithSize* buffer, int priority) - : buffer_(buffer), - priority_(priority), - position_(++order_) { - } - - IOBuffer* buffer() const { return buffer_; } - - int size() const { return buffer_->size(); } - - void release() { buffer_ = NULL; } - - int priority() { return priority_; } - - // Supports sorting. - bool operator<(const PrioritizedIOBuffer& other) const { - if (priority_ != other.priority_) - return priority_ > other.priority_; - return position_ >= other.position_; - } - - private: - scoped_refptr<IOBufferWithSize> buffer_; - int priority_; - int position_; - static int order_; // Maintains a FIFO order for equal priorities. -}; - -class FlipSession : public base::RefCounted<FlipSession>, - public flip::FlipFramerVisitorInterface { - public: - // Factory for finding open sessions. - // TODO(mbelshe): Break this out into a connection pool class? - static FlipSession* GetFlipSession(const HostResolver::RequestInfo&, - HttpNetworkSession* session); - virtual ~FlipSession(); - - // Get the domain for this FlipSession. - std::string domain() { return domain_; } - - // Connect the FLIP Socket. - // Returns net::Error::OK on success. - // Note that this call does not wait for the connect to complete. Callers can - // immediately start using the FlipSession while it connects. - net::Error Connect(const std::string& group_name, - const HostResolver::RequestInfo& host, int priority); - - // Create a new stream. - // FlipDelegate must remain valid until the stream is either cancelled by the - // creator via CancelStream or the FlipDelegate OnClose or OnCancel callbacks - // have been made. - // Once the stream is created, the delegate should wait for a callback. - int CreateStream(FlipDelegate* delegate); - - // Cancel a stream. - bool CancelStream(int id); - - // Check if a stream is active. - bool IsStreamActive(int id); - - // The LoadState is used for informing the user of the current network - // status, such as "resolving host", "connecting", etc. - LoadState GetLoadState() const; - protected: - friend class FlipNetworkTransactionTest; - friend class FlipSessionPool; - - // Provide access to the framer for testing. - flip::FlipFramer* GetFramer() { return &flip_framer_; } - - // Create a new FlipSession. - // |host| is the hostname that this session connects to. - FlipSession(std::string host, HttpNetworkSession* session); - - // Closes all open streams. Used as part of shutdown. - void CloseAllStreams(net::Error code); - - private: - // FlipFramerVisitorInterface - virtual void OnError(flip::FlipFramer*); - virtual void OnStreamFrameData(flip::FlipStreamId stream_id, - const char* data, - uint32 len); - virtual void OnControl(const flip::FlipControlFrame* frame); - virtual void OnLameDuck(); - - // Control frame handlers. - void OnSyn(const flip::FlipSynStreamControlFrame* frame, - const flip::FlipHeaderBlock* headers); - void OnSynReply(const flip::FlipSynReplyControlFrame* frame, - const flip::FlipHeaderBlock* headers); - void OnFin(const flip::FlipFinStreamControlFrame* frame); - - // IO Callbacks - void OnSocketConnect(int result); - void OnReadComplete(int result); - void OnWriteComplete(int result); - - // Start reading from the socket. - void ReadSocket(); - - // Write current data to the socket. - void WriteSocketLater(); - void WriteSocket(); - - // Get a new stream id. - int GetNewStreamId(); - - // Track active streams in the active stream list. - FlipStreamImpl* ActivateStream(int id, FlipDelegate* delegate); - void DeactivateStream(int id); - - // Check if we have a pending pushed-stream for this url - // Returns the stream if found (and returns it from the pending - // list), returns NULL otherwise. - FlipStreamImpl* GetPushStream(std::string url); - - // Callbacks for the Flip session. - CompletionCallbackImpl<FlipSession> connect_callback_; - CompletionCallbackImpl<FlipSession> read_callback_; - CompletionCallbackImpl<FlipSession> write_callback_; - - // The domain this session is connected to. - std::string domain_; - - scoped_refptr<HttpNetworkSession> session_; - - // The socket handle for this session. - ClientSocketHandle connection_; - bool connection_started_; - - // The read buffer used to read data from the socket. - enum { kReadBufferSize = (4 * 1024) }; - scoped_refptr<net::MovableIOBuffer> read_buffer_; - int read_buffer_bytes_read_; // bytes left in the buffer from prior read. - bool read_pending_; - - int stream_hi_water_mark_; // The next stream id to use. - - typedef std::map<int, FlipStreamImpl*> ActiveStreamMap; - typedef std::list<FlipStreamImpl*> ActiveStreamList; - ActiveStreamMap active_streams_; - - ActiveStreamList pushed_streams_; - - // As we gather data to be sent, we put it into the output queue. - typedef std::priority_queue<PrioritizedIOBuffer> OutputQueue; - OutputQueue queue_; - - // TODO(mbelshe): this is ugly!! - // The packet we are currently sending. - PrioritizedIOBuffer in_flight_write_; - bool delayed_write_pending_; - bool write_pending_; - - // Flip Frame state. - flip::FlipFramer flip_framer_; - - // This is our weak session pool - one session per domain. - static scoped_ptr<FlipSessionPool> session_pool_; - static bool disable_compression_; -}; - -} // namespace net - -#endif // NET_FLIP_FLIP_SESSION_H_ - diff --git a/net/flip/flip_session_pool.cc b/net/flip/flip_session_pool.cc deleted file mode 100644 index 2aef13a..0000000 --- a/net/flip/flip_session_pool.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/flip/flip_session_pool.h" - -#include "base/logging.h" -#include "net/flip/flip_session.h" - -namespace net { - -// The maximum number of sessions to open to a single domain. -const int kMaxSessionsPerDomain = 1; - -scoped_ptr<FlipSessionPool::FlipSessionsMap> FlipSessionPool::sessions_; - -FlipSession* FlipSessionPool::Get(const HostResolver::RequestInfo& info, - HttpNetworkSession* session) { - if (!sessions_.get()) - sessions_.reset(new FlipSessionsMap()); - - const std::string domain = info.hostname(); - FlipSession* flip_session = NULL; - FlipSessionList* list = GetSessionList(domain); - if (list) { - if (list->size() >= kMaxSessionsPerDomain) { - flip_session = list->front(); - list->pop_front(); - } - } else { - list = AddSessionList(domain); - } - - DCHECK(list); - if (!flip_session) { - flip_session = new FlipSession(domain, session); - flip_session->AddRef(); // Keep it in the cache. - } - - DCHECK(flip_session); - list->push_back(flip_session); - DCHECK(list->size() <= kMaxSessionsPerDomain); - return flip_session; -} - -void FlipSessionPool::Remove(FlipSession* session) { - std::string domain = session->domain(); - FlipSessionList* list = GetSessionList(domain); - if (list == NULL) - return; - list->remove(session); - if (!list->size()) - RemoveSessionList(domain); -} - -FlipSessionPool::FlipSessionList* - FlipSessionPool::AddSessionList(std::string domain) { - DCHECK(sessions_->find(domain) == sessions_->end()); - return (*sessions_)[domain] = new FlipSessionList(); -} - -// static -FlipSessionPool::FlipSessionList* - FlipSessionPool::GetSessionList(std::string domain) { - FlipSessionsMap::iterator it = sessions_->find(domain); - if (it == sessions_->end()) - return NULL; - return it->second; -} - -// static -void FlipSessionPool::RemoveSessionList(std::string domain) { - FlipSessionList* list = GetSessionList(domain); - if (list) { - delete list; - sessions_->erase(domain); - } else { - DCHECK(false) << "removing orphaned session list"; - } -} - -// static -void FlipSessionPool::CloseAllSessions() { - while (sessions_->size()) { - FlipSessionList* list = sessions_->begin()->second; - DCHECK(list); - sessions_->erase(sessions_->begin()->first); - while (list->size()) { - FlipSession* session = list->front(); - list->pop_front(); - session->CloseAllStreams(net::OK); - session->Release(); - } - delete list; - } -} - -} // namespace net - diff --git a/net/flip/flip_session_pool.h b/net/flip/flip_session_pool.h deleted file mode 100644 index 9562413..0000000 --- a/net/flip/flip_session_pool.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_FLIP_FLIP_SESSION_POOL_H_ -#define NET_FLIP_FLIP_SESSION_POOL_H_ - -#include <map> -#include <list> -#include <string> - -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "net/base/host_resolver.h" - -namespace net { - -class FlipSession; -class HttpNetworkSession; - -// This is a very simple pool for open FlipSessions. -// TODO(mbelshe): Make this production ready. -class FlipSessionPool { - public: - FlipSessionPool() {} - virtual ~FlipSessionPool() {} - - // Factory for finding open sessions. - FlipSession* Get(const HostResolver::RequestInfo& info, - HttpNetworkSession* session); - - // Close all Flip Sessions; used for debugging. - static void CloseAllSessions(); - - protected: - friend class FlipSession; - - // Return a FlipSession to the pool. - void Remove(FlipSession* session); - - private: - typedef std::list<FlipSession*> FlipSessionList; - typedef std::map<std::string, FlipSessionList*> FlipSessionsMap; - - // Helper functions for manipulating the lists. - FlipSessionList* AddSessionList(std::string domain); - static FlipSessionList* GetSessionList(std::string domain); - static void RemoveSessionList(std::string domain); - - // This is our weak session pool - one session per domain. - static scoped_ptr<FlipSessionsMap> sessions_; -}; - -} // namespace net - -#endif // NET_FLIP_FLIP_SESSION_POOL_H_ - diff --git a/net/flip/flip_session_unittest.cc b/net/flip/flip_session_unittest.cc deleted file mode 100644 index 016a197..0000000 --- a/net/flip/flip_session_unittest.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/test_completion_callback.h" -#include "net/socket/socket_test_util.h" -#include "testing/platform_test.h" - -#include "net/flip/flip_session.h" - -namespace net { - -class FlipSessionTest : public PlatformTest { - public: -}; - -// Test the PrioritizedIOBuffer class. -TEST_F(FlipSessionTest, PrioritizedIOBuffer) { - std::priority_queue<PrioritizedIOBuffer> queue_; - const int kQueueSize = 100; - - // Insert 100 items; pri 100 to 1. - for (int index = 0; index < kQueueSize; ++index) { - PrioritizedIOBuffer buffer(NULL, kQueueSize - index); - queue_.push(buffer); - } - - // Insert several priority 0 items last. - const int kNumDuplicates = 12; - IOBufferWithSize* buffers[kNumDuplicates]; - for (int index = 0; index < kNumDuplicates; ++index) { - buffers[index] = new IOBufferWithSize(index+1); - queue_.push(PrioritizedIOBuffer(buffers[index], 0)); - } - - EXPECT_EQ(kQueueSize + kNumDuplicates, queue_.size()); - - // Verify the P0 items come out in FIFO order. - for (int index = 0; index < kNumDuplicates; ++index) { - PrioritizedIOBuffer buffer = queue_.top(); - EXPECT_EQ(0, buffer.priority()); - EXPECT_EQ(index + 1, buffer.size()); - queue_.pop(); - } - - int priority = 1; - while (queue_.size()) { - PrioritizedIOBuffer buffer = queue_.top(); - EXPECT_EQ(priority++, buffer.priority()); - queue_.pop(); - } -} - -} // namespace net - diff --git a/net/flip/flip_transaction_factory.h b/net/flip/flip_transaction_factory.h deleted file mode 100644 index ce50686..0000000 --- a/net/flip/flip_transaction_factory.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_FLIP_FLIP_TRANSACTION_FACTORY_H__ -#define NET_FLIP_FLIP_TRANSACTION_FACTORY_H__ - -#include "net/flip/flip_network_transaction.h" -#include "net/http/http_transaction_factory.h" - -namespace net { - -class FlipTransactionFactory : public HttpTransactionFactory { - public: - explicit FlipTransactionFactory(HttpNetworkSession* session) - : session_(session) { - } - virtual ~FlipTransactionFactory() {} - - // HttpTransactionFactory Interface. - virtual HttpTransaction* CreateTransaction() { - return new FlipNetworkTransaction(session_); - } - virtual HttpCache* GetCache() { - return NULL; - } - virtual void Suspend(bool suspend) { - } - - private: - scoped_refptr<HttpNetworkSession> session_; -}; - -} // namespace net - -#endif // NET_FLIP_FLIP_TRANSACTION_FACTORY_H__ |