| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file implements a simple HTTP server. It can exhibit odd behavior | 5 // This file implements a simple HTTP server. It can exhibit odd behavior |
| 6 // that's useful for testing. For example, it's useful to test that | 6 // that's useful for testing. For example, it's useful to test that |
| 7 // the updater can continue a connection if it's dropped, or that it | 7 // the updater can continue a connection if it's dropped, or that it |
| 8 // handles very slow data transfers. | 8 // handles very slow data transfers. |
| 9 | 9 |
| 10 // To use this, simply make an HTTP connection to localhost:port and | 10 // To use this, simply make an HTTP connection to localhost:port and |
| 11 // GET a url. | 11 // GET a url. |
| 12 | 12 |
| 13 #include <netinet/in.h> | 13 #include <netinet/in.h> |
| 14 #include <sys/socket.h> | 14 #include <sys/socket.h> |
| 15 #include <sys/types.h> | 15 #include <sys/types.h> |
| 16 #include <errno.h> | 16 #include <errno.h> |
| 17 #include <inttypes.h> |
| 17 #include <stdio.h> | 18 #include <stdio.h> |
| 18 #include <stdlib.h> | 19 #include <stdlib.h> |
| 19 #include <string.h> | 20 #include <string.h> |
| 20 #include <unistd.h> | 21 #include <unistd.h> |
| 21 #include <algorithm> | 22 #include <algorithm> |
| 22 #include <string> | 23 #include <string> |
| 23 #include <vector> | 24 #include <vector> |
| 24 #include "chromeos/obsolete_logging.h" | 25 #include "chromeos/obsolete_logging.h" |
| 25 | 26 |
| 26 using std::min; | 27 using std::min; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 perror("write"); | 92 perror("write"); |
| 92 return; | 93 return; |
| 93 } | 94 } |
| 94 bytes_written += r; | 95 bytes_written += r; |
| 95 } | 96 } |
| 96 LOG(INFO) << "WriteString wrote " << bytes_written << " bytes"; | 97 LOG(INFO) << "WriteString wrote " << bytes_written << " bytes"; |
| 97 } | 98 } |
| 98 | 99 |
| 99 string Itoa(off_t num) { | 100 string Itoa(off_t num) { |
| 100 char buf[100] = {0}; | 101 char buf[100] = {0}; |
| 101 snprintf(buf, sizeof(buf), "%lld", num); | 102 snprintf(buf, sizeof(buf), "%" PRIi64, num); |
| 102 return buf; | 103 return buf; |
| 103 } | 104 } |
| 104 | 105 |
| 105 void WriteHeaders(int fd, bool support_range, off_t full_size, | 106 void WriteHeaders(int fd, bool support_range, off_t full_size, |
| 106 off_t start_offset) { | 107 off_t start_offset) { |
| 107 LOG(INFO) << "writing headers"; | 108 LOG(INFO) << "writing headers"; |
| 108 WriteString(fd, "HTTP/1.1 200 OK\r\n"); | 109 WriteString(fd, "HTTP/1.1 200 OK\r\n"); |
| 109 WriteString(fd, "Content-Type: application/octet-stream\r\n"); | 110 WriteString(fd, "Content-Type: application/octet-stream\r\n"); |
| 110 if (support_range) { | 111 if (support_range) { |
| 111 WriteString(fd, "Accept-Ranges: bytes\r\n"); | 112 WriteString(fd, "Accept-Ranges: bytes\r\n"); |
| 112 WriteString(fd, string("Content-Range: bytes ") + Itoa(start_offset) + | 113 WriteString(fd, string("Content-Range: bytes ") + Itoa(start_offset) + |
| 113 "-" + Itoa(full_size - 1) + "/" + Itoa(full_size) + "\r\n"); | 114 "-" + Itoa(full_size - 1) + "/" + Itoa(full_size) + "\r\n"); |
| 114 } | 115 } |
| 115 off_t content_length = full_size; | 116 off_t content_length = full_size; |
| 116 if (support_range) | 117 if (support_range) |
| 117 content_length -= start_offset; | 118 content_length -= start_offset; |
| 118 WriteString(fd, string("Content-Length: ") + Itoa(content_length) + "\r\n"); | 119 WriteString(fd, string("Content-Length: ") + Itoa(content_length) + "\r\n"); |
| 119 WriteString(fd, "\r\n"); | 120 WriteString(fd, "\r\n"); |
| 120 } | 121 } |
| 121 | 122 |
| 122 void HandleQuitQuitQuit(int fd) { | 123 void HandleQuitQuitQuit(int fd) { |
| 124 WriteHeaders(fd, true, 0, 0); |
| 123 exit(0); | 125 exit(0); |
| 124 } | 126 } |
| 125 | 127 |
| 126 void HandleBig(int fd, const HttpRequest& request) { | 128 void HandleBig(int fd, const HttpRequest& request) { |
| 127 const off_t full_length = kBigLength; | 129 const off_t full_length = kBigLength; |
| 128 WriteHeaders(fd, true, full_length, request.offset); | 130 WriteHeaders(fd, true, full_length, request.offset); |
| 129 const off_t content_length = full_length - request.offset; | 131 const off_t content_length = full_length - request.offset; |
| 130 int i = request.offset; | 132 int i = request.offset; |
| 131 for (; i % 10; i++) | 133 for (; i % 10; i++) |
| 132 WriteString(fd, string(1, 'a' + (i % 10))); | 134 WriteString(fd, string(1, 'a' + (i % 10))); |
| 133 CHECK_EQ(i % 10, 0); | 135 CHECK_EQ(i % 10, 0); |
| 134 for (; i < content_length; i += 10) | 136 for (; i < content_length; i += 10) |
| 135 WriteString(fd, "abcdefghij"); | 137 WriteString(fd, "abcdefghij"); |
| 136 CHECK_EQ(i, full_length); | 138 CHECK_EQ(i, full_length); |
| 137 } | 139 } |
| 138 | 140 |
| 139 // This is like /big, but it writes at most 9000 bytes. Also, | 141 // This is like /big, but it writes at most 9000 bytes. Also, |
| 140 // half way through it sleeps for 70 seconds | 142 // half way through it sleeps for 70 seconds |
| 141 // (technically, when (offset % (9000 * 7)) == 0). | 143 // (technically, when (offset % (9000 * 7)) == 0). |
| 142 void HandleFlaky(int fd, const HttpRequest& request) { | 144 void HandleFlaky(int fd, const HttpRequest& request) { |
| 143 const off_t full_length = kBigLength; | 145 const off_t full_length = kBigLength; |
| 144 WriteHeaders(fd, true, full_length, request.offset); | 146 WriteHeaders(fd, true, full_length, request.offset); |
| 145 const off_t content_length = min(9000LL, full_length - request.offset); | 147 const off_t content_length = |
| 148 min(static_cast<off_t>(9000), full_length - request.offset); |
| 146 const bool should_sleep = (request.offset % (9000 * 7)) == 0; | 149 const bool should_sleep = (request.offset % (9000 * 7)) == 0; |
| 147 | 150 |
| 148 string buf; | 151 string buf; |
| 149 | 152 |
| 150 for (int i = request.offset; i % 10; i++) | 153 for (int i = request.offset; i % 10; i++) |
| 151 buf.append(1, 'a' + (i % 10)); | 154 buf.append(1, 'a' + (i % 10)); |
| 152 while (buf.size() < content_length) | 155 while (static_cast<off_t>(buf.size()) < content_length) |
| 153 buf.append("abcdefghij"); | 156 buf.append("abcdefghij"); |
| 154 buf.resize(content_length); | 157 buf.resize(content_length); |
| 155 | 158 |
| 156 if (!should_sleep) { | 159 if (!should_sleep) { |
| 157 LOG(INFO) << "writing data blob of size " << buf.size(); | 160 LOG(INFO) << "writing data blob of size " << buf.size(); |
| 158 WriteString(fd, buf); | 161 WriteString(fd, buf); |
| 159 } else { | 162 } else { |
| 160 string::size_type half_way_point = buf.size() / 2; | 163 string::size_type half_way_point = buf.size() / 2; |
| 161 LOG(INFO) << "writing small data blob of size " << half_way_point; | 164 LOG(INFO) << "writing small data blob of size " << half_way_point; |
| 162 WriteString(fd, buf.substr(0, half_way_point)); | 165 WriteString(fd, buf.substr(0, half_way_point)); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 int client_fd = accept(listen_fd, | 234 int client_fd = accept(listen_fd, |
| 232 (struct sockaddr *) &client_addr, | 235 (struct sockaddr *) &client_addr, |
| 233 &clilen); | 236 &clilen); |
| 234 LOG(INFO) << "got past accept"; | 237 LOG(INFO) << "got past accept"; |
| 235 if (client_fd < 0) | 238 if (client_fd < 0) |
| 236 LOG(FATAL) << "ERROR on accept"; | 239 LOG(FATAL) << "ERROR on accept"; |
| 237 HandleConnection(client_fd); | 240 HandleConnection(client_fd); |
| 238 } | 241 } |
| 239 return 0; | 242 return 0; |
| 240 } | 243 } |
| OLD | NEW |