AU: MultiHttpFetcher, an HttpFetcher for specific byte ranges
MultiHttpFetcher takes an HttpFetcher class via template parameter,
and a collection of byte ranges. It hits up the URL multiple times,
once per range specified. For each time, it uses a new HttpFetcher of
the type specified and fast-forwards to the offset requested, and
aborting after enough bytes have been downloaded. Any range many
specify a length of -1, which means until the end of the file (as
dictated by the server). Thus, a single range of [0, -1] makes
MultiHttpFetcher a pass-through.
HttpFetcher change: ability to supply an offset.
LibcurlHttpFetcher changes: offset support (from HttpFetcher API),
ability to be terminted in a write-callback.
test_http_fetcher: support for failures in write() on the socket (at
least in the /big url case).
BUG=7391
TEST=unittests
Review URL: http://codereview.chromium.org/3591018
diff --git a/test_http_server.cc b/test_http_server.cc
index 9573c31..de5c619 100644
--- a/test_http_server.cc
+++ b/test_http_server.cc
@@ -10,19 +10,22 @@
// To use this, simply make an HTTP connection to localhost:port and
// GET a url.
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/types.h>
#include <errno.h>
#include <inttypes.h>
+#include <netinet/in.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
+
#include <algorithm>
#include <string>
#include <vector>
-#include "base/logging.h"
+
+#include <base/logging.h>
using std::min;
using std::string;
@@ -101,19 +104,19 @@
return true;
}
-void WriteString(int fd, const string& str) {
+bool WriteString(int fd, const string& str) {
unsigned int bytes_written = 0;
while (bytes_written < str.size()) {
- ssize_t r = write(fd, str.c_str() + bytes_written,
+ ssize_t r = write(fd, str.data() + bytes_written,
str.size() - bytes_written);
- LOG(INFO) << "write() wrote " << r << " bytes";
if (r < 0) {
perror("write");
- return;
+ LOG(INFO) << "write failed";
+ return false;
}
bytes_written += r;
}
- LOG(INFO) << "WriteString wrote " << bytes_written << " bytes";
+ return true;
}
string Itoa(off_t num) {
@@ -145,16 +148,21 @@
}
void HandleBig(int fd, const HttpRequest& request, int big_length) {
+ LOG(INFO) << "starting big";
const off_t full_length = big_length;
WriteHeaders(fd, true, full_length, request.offset, request.return_code);
- const off_t content_length = full_length - request.offset;
int i = request.offset;
- for (; i % 10; i++)
- WriteString(fd, string(1, 'a' + (i % 10)));
- CHECK_EQ(i % 10, 0);
- for (; i < content_length; i += 10)
- WriteString(fd, "abcdefghij");
- CHECK_EQ(i, full_length);
+ bool success = true;
+ for (; (i % 10) && success; i++)
+ success = WriteString(fd, string(1, 'a' + (i % 10)));
+ if (success)
+ CHECK_EQ(i % 10, 0);
+ for (; (i < full_length) && success; i += 10) {
+ success = WriteString(fd, "abcdefghij");
+ }
+ if (success)
+ CHECK_EQ(i, full_length);
+ LOG(INFO) << "Done w/ big";
}
// This is like /big, but it writes at most 9000 bytes. Also,
@@ -252,6 +260,9 @@
using namespace chromeos_update_engine;
int main(int argc, char** argv) {
+ // Ignore SIGPIPE on write() to sockets.
+ signal(SIGPIPE, SIG_IGN);
+
socklen_t clilen;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;