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 |