| 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> | |
| 14 #include <sys/socket.h> | |
| 15 #include <sys/types.h> | |
| 16 #include <errno.h> | 13 #include <errno.h> |
| 17 #include <inttypes.h> | 14 #include <inttypes.h> |
| 15 #include <netinet/in.h> |
| 16 #include <signal.h> |
| 18 #include <stdio.h> | 17 #include <stdio.h> |
| 19 #include <stdlib.h> | 18 #include <stdlib.h> |
| 20 #include <string.h> | 19 #include <string.h> |
| 20 #include <sys/socket.h> |
| 21 #include <sys/types.h> |
| 21 #include <unistd.h> | 22 #include <unistd.h> |
| 23 |
| 22 #include <algorithm> | 24 #include <algorithm> |
| 23 #include <string> | 25 #include <string> |
| 24 #include <vector> | 26 #include <vector> |
| 25 #include "base/logging.h" | 27 |
| 28 #include <base/logging.h> |
| 26 | 29 |
| 27 using std::min; | 30 using std::min; |
| 28 using std::string; | 31 using std::string; |
| 29 using std::vector; | 32 using std::vector; |
| 30 | 33 |
| 31 namespace chromeos_update_engine { | 34 namespace chromeos_update_engine { |
| 32 | 35 |
| 33 struct HttpRequest { | 36 struct HttpRequest { |
| 34 HttpRequest() : offset(0), return_code(200) {} | 37 HttpRequest() : offset(0), return_code(200) {} |
| 35 string host; | 38 string host; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 CHECK_NE(string::npos, host_end); | 97 CHECK_NE(string::npos, host_end); |
| 95 string host = headers.substr(host_start, host_end - host_start); | 98 string host = headers.substr(host_start, host_end - host_start); |
| 96 | 99 |
| 97 LOG(INFO) << "Host: " << host; | 100 LOG(INFO) << "Host: " << host; |
| 98 request->host = host; | 101 request->host = host; |
| 99 } | 102 } |
| 100 | 103 |
| 101 return true; | 104 return true; |
| 102 } | 105 } |
| 103 | 106 |
| 104 void WriteString(int fd, const string& str) { | 107 bool WriteString(int fd, const string& str) { |
| 105 unsigned int bytes_written = 0; | 108 unsigned int bytes_written = 0; |
| 106 while (bytes_written < str.size()) { | 109 while (bytes_written < str.size()) { |
| 107 ssize_t r = write(fd, str.c_str() + bytes_written, | 110 ssize_t r = write(fd, str.data() + bytes_written, |
| 108 str.size() - bytes_written); | 111 str.size() - bytes_written); |
| 109 LOG(INFO) << "write() wrote " << r << " bytes"; | |
| 110 if (r < 0) { | 112 if (r < 0) { |
| 111 perror("write"); | 113 perror("write"); |
| 112 return; | 114 LOG(INFO) << "write failed"; |
| 115 return false; |
| 113 } | 116 } |
| 114 bytes_written += r; | 117 bytes_written += r; |
| 115 } | 118 } |
| 116 LOG(INFO) << "WriteString wrote " << bytes_written << " bytes"; | 119 return true; |
| 117 } | 120 } |
| 118 | 121 |
| 119 string Itoa(off_t num) { | 122 string Itoa(off_t num) { |
| 120 char buf[100] = {0}; | 123 char buf[100] = {0}; |
| 121 snprintf(buf, sizeof(buf), "%" PRIi64, num); | 124 snprintf(buf, sizeof(buf), "%" PRIi64, num); |
| 122 return buf; | 125 return buf; |
| 123 } | 126 } |
| 124 | 127 |
| 125 void WriteHeaders(int fd, bool support_range, off_t full_size, | 128 void WriteHeaders(int fd, bool support_range, off_t full_size, |
| 126 off_t start_offset, int return_code) { | 129 off_t start_offset, int return_code) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 138 WriteString(fd, string("Content-Length: ") + Itoa(content_length) + "\r\n"); | 141 WriteString(fd, string("Content-Length: ") + Itoa(content_length) + "\r\n"); |
| 139 WriteString(fd, "\r\n"); | 142 WriteString(fd, "\r\n"); |
| 140 } | 143 } |
| 141 | 144 |
| 142 void HandleQuitQuitQuit(int fd) { | 145 void HandleQuitQuitQuit(int fd) { |
| 143 WriteHeaders(fd, true, 0, 0, 200); | 146 WriteHeaders(fd, true, 0, 0, 200); |
| 144 exit(0); | 147 exit(0); |
| 145 } | 148 } |
| 146 | 149 |
| 147 void HandleBig(int fd, const HttpRequest& request, int big_length) { | 150 void HandleBig(int fd, const HttpRequest& request, int big_length) { |
| 151 LOG(INFO) << "starting big"; |
| 148 const off_t full_length = big_length; | 152 const off_t full_length = big_length; |
| 149 WriteHeaders(fd, true, full_length, request.offset, request.return_code); | 153 WriteHeaders(fd, true, full_length, request.offset, request.return_code); |
| 150 const off_t content_length = full_length - request.offset; | |
| 151 int i = request.offset; | 154 int i = request.offset; |
| 152 for (; i % 10; i++) | 155 bool success = true; |
| 153 WriteString(fd, string(1, 'a' + (i % 10))); | 156 for (; (i % 10) && success; i++) |
| 154 CHECK_EQ(i % 10, 0); | 157 success = WriteString(fd, string(1, 'a' + (i % 10))); |
| 155 for (; i < content_length; i += 10) | 158 if (success) |
| 156 WriteString(fd, "abcdefghij"); | 159 CHECK_EQ(i % 10, 0); |
| 157 CHECK_EQ(i, full_length); | 160 for (; (i < full_length) && success; i += 10) { |
| 161 success = WriteString(fd, "abcdefghij"); |
| 162 } |
| 163 if (success) |
| 164 CHECK_EQ(i, full_length); |
| 165 LOG(INFO) << "Done w/ big"; |
| 158 } | 166 } |
| 159 | 167 |
| 160 // This is like /big, but it writes at most 9000 bytes. Also, | 168 // This is like /big, but it writes at most 9000 bytes. Also, |
| 161 // half way through it sleeps for 70 seconds | 169 // half way through it sleeps for 70 seconds |
| 162 // (technically, when (offset % (9000 * 7)) == 0). | 170 // (technically, when (offset % (9000 * 7)) == 0). |
| 163 void HandleFlaky(int fd, const HttpRequest& request) { | 171 void HandleFlaky(int fd, const HttpRequest& request) { |
| 164 const off_t full_length = kBigLength; | 172 const off_t full_length = kBigLength; |
| 165 WriteHeaders(fd, true, full_length, request.offset, request.return_code); | 173 WriteHeaders(fd, true, full_length, request.offset, request.return_code); |
| 166 const off_t content_length = | 174 const off_t content_length = |
| 167 min(static_cast<off_t>(9000), full_length - request.offset); | 175 min(static_cast<off_t>(9000), full_length - request.offset); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 HandleDefault(fd, request); | 253 HandleDefault(fd, request); |
| 246 | 254 |
| 247 close(fd); | 255 close(fd); |
| 248 } | 256 } |
| 249 | 257 |
| 250 } // namespace chromeos_update_engine | 258 } // namespace chromeos_update_engine |
| 251 | 259 |
| 252 using namespace chromeos_update_engine; | 260 using namespace chromeos_update_engine; |
| 253 | 261 |
| 254 int main(int argc, char** argv) { | 262 int main(int argc, char** argv) { |
| 263 // Ignore SIGPIPE on write() to sockets. |
| 264 signal(SIGPIPE, SIG_IGN); |
| 265 |
| 255 socklen_t clilen; | 266 socklen_t clilen; |
| 256 struct sockaddr_in server_addr; | 267 struct sockaddr_in server_addr; |
| 257 struct sockaddr_in client_addr; | 268 struct sockaddr_in client_addr; |
| 258 memset(&server_addr, 0, sizeof(server_addr)); | 269 memset(&server_addr, 0, sizeof(server_addr)); |
| 259 memset(&client_addr, 0, sizeof(client_addr)); | 270 memset(&client_addr, 0, sizeof(client_addr)); |
| 260 | 271 |
| 261 int listen_fd = socket(AF_INET, SOCK_STREAM, 0); | 272 int listen_fd = socket(AF_INET, SOCK_STREAM, 0); |
| 262 if (listen_fd < 0) | 273 if (listen_fd < 0) |
| 263 LOG(FATAL) << "socket() failed"; | 274 LOG(FATAL) << "socket() failed"; |
| 264 | 275 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 287 int client_fd = accept(listen_fd, | 298 int client_fd = accept(listen_fd, |
| 288 (struct sockaddr *) &client_addr, | 299 (struct sockaddr *) &client_addr, |
| 289 &clilen); | 300 &clilen); |
| 290 LOG(INFO) << "got past accept"; | 301 LOG(INFO) << "got past accept"; |
| 291 if (client_fd < 0) | 302 if (client_fd < 0) |
| 292 LOG(FATAL) << "ERROR on accept"; | 303 LOG(FATAL) << "ERROR on accept"; |
| 293 HandleConnection(client_fd); | 304 HandleConnection(client_fd); |
| 294 } | 305 } |
| 295 return 0; | 306 return 0; |
| 296 } | 307 } |
| OLD | NEW |