AU multi-range fetcher requests properly closed ranges when their length
is known.

* HttpFetcher allows to set the length of data to be fetched.
  LibcurlHttpFetcher uses this value in applying the appropriate libcurl
  option (CURLOPT_RANGE).  MultiHttpFetcher sets the desired payload
  length in the underlying fetcher accordingly.

* Improved functionality of test_http_server: (a) correctly parses
  closed range intervals; (b) generalized response header generation;
  (c) unified and generalized get handling for both stable and flaky
  cases.

* Small scale refactoring, improved logging and readability.

BUG=chromium-os:24666
TEST=unit tests

Change-Id: I1727710ca747088c67a68305f355da683b07b6a3
Reviewed-on: https://gerrit.chromium.org/gerrit/13594
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
Commit-Ready: Gilad Arnold <garnold@chromium.org>
diff --git a/multi_range_http_fetcher.h b/multi_range_http_fetcher.h
index 342588a..19982ef 100644
--- a/multi_range_http_fetcher.h
+++ b/multi_range_http_fetcher.h
@@ -45,12 +45,20 @@
 
   void ClearRanges() { ranges_.clear(); }
 
-  void AddRange(off_t offset, off_t size) {
-    ranges_.push_back(std::make_pair(offset, size));
+  void AddRange(off_t offset, size_t size) {
+    CHECK_GT(size, 0);
+    ranges_.push_back(Range(offset, size));
+  }
+
+  void AddRange(off_t offset) {
+    ranges_.push_back(Range(offset));
   }
 
   virtual void SetOffset(off_t offset) {}  // for now, doesn't support this
 
+  virtual void SetLength(size_t length) {}  // unsupported
+  virtual void UnsetLength() {}
+
   // Begins the transfer to the specified URL.
   // State change: Stopped -> Downloading
   // (corner case: Stopped -> Stopped for an empty request)
@@ -85,8 +93,27 @@
   }
 
  private:
-  // pair<offset, length>:
-  typedef std::vector<std::pair<off_t, off_t> > RangesVect;
+  // A range object defining the offset and length of a download chunk.  Zero
+  // length indicates an unspecified end offset (note that it is impossible to
+  // request a zero-length range in HTTP).
+  class Range {
+   public:
+    Range(off_t offset, size_t length) : offset_(offset), length_(length) {}
+    Range(off_t offset) : offset_(offset), length_(0) {}
+
+    inline off_t offset() const { return offset_; }
+    inline size_t length() const { return length_; }
+
+    inline bool HasLength() const { return (length_ > 0); }
+
+    std::string ToString() const;
+
+   private:
+    off_t offset_;
+    size_t length_;
+  };
+
+  typedef std::vector<Range> RangesVect;
   
   // State change: Stopped or Downloading -> Downloading
   void StartTransfer();
@@ -120,7 +147,7 @@
   RangesVect ranges_;
 
   RangesVect::size_type current_index_;  // index into ranges_
-  off_t bytes_received_this_range_;
+  size_t bytes_received_this_range_;
 
   DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
 };