OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium 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 #include <windows.h> | 5 #include <windows.h> |
6 #include <objbase.h> | 6 #include <objbase.h> |
7 #include <urlmon.h> | 7 #include <urlmon.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 if (index != std::string::npos) { | 68 if (index != std::string::npos) { |
69 // Parse the headers before returning and chop them of the | 69 // Parse the headers before returning and chop them of the |
70 // data buffer we've already received. | 70 // data buffer we've already received. |
71 std::string headers(content_.substr(0, index + 2)); | 71 std::string headers(content_.substr(0, index + 2)); |
72 ParseHeaders(headers); | 72 ParseHeaders(headers); |
73 content_.erase(0, index + 4); | 73 content_.erase(0, index + 4); |
74 } | 74 } |
75 } | 75 } |
76 } | 76 } |
77 | 77 |
| 78 ResponseForPath::~ResponseForPath() { |
| 79 } |
| 80 |
| 81 SimpleResponse::~SimpleResponse() { |
| 82 } |
| 83 |
78 bool FileResponse::GetContentType(std::string* content_type) const { | 84 bool FileResponse::GetContentType(std::string* content_type) const { |
79 size_t length = ContentLength(); | 85 size_t length = ContentLength(); |
80 char buffer[4096]; | 86 char buffer[4096]; |
81 void* data = NULL; | 87 void* data = NULL; |
82 | 88 |
83 if (length) { | 89 if (length) { |
84 // Create a copy of the first few bytes of the file. | 90 // Create a copy of the first few bytes of the file. |
85 // If we try and use the mapped file directly, FindMimeFromData will crash | 91 // If we try and use the mapped file directly, FindMimeFromData will crash |
86 // 'cause it cheats and temporarily tries to write to the buffer! | 92 // 'cause it cheats and temporarily tries to write to the buffer! |
87 length = std::min(arraysize(buffer), length); | 93 length = std::min(arraysize(buffer), length); |
88 memcpy(buffer, file_->data(), length); | 94 memcpy(buffer, file_->data(), length); |
89 data = buffer; | 95 data = buffer; |
90 } | 96 } |
91 | 97 |
92 LPOLESTR mime_type = NULL; | 98 LPOLESTR mime_type = NULL; |
93 FindMimeFromData(NULL, file_path_.value().c_str(), data, length, NULL, | 99 FindMimeFromData(NULL, file_path_.value().c_str(), data, length, NULL, |
94 FMFD_DEFAULT, &mime_type, 0); | 100 FMFD_DEFAULT, &mime_type, 0); |
95 if (mime_type) { | 101 if (mime_type) { |
96 *content_type = WideToASCII(mime_type); | 102 *content_type = WideToASCII(mime_type); |
97 ::CoTaskMemFree(mime_type); | 103 ::CoTaskMemFree(mime_type); |
98 } | 104 } |
99 | 105 |
100 return content_type->length() > 0; | 106 return content_type->length() > 0; |
101 } | 107 } |
102 | 108 |
103 void FileResponse::WriteContents(net::ListenSocket* socket) const { | 109 void FileResponse::WriteContents(net::StreamListenSocket* socket) const { |
104 DCHECK(file_.get()); | 110 DCHECK(file_.get()); |
105 if (file_.get()) { | 111 if (file_.get()) { |
106 socket->Send(reinterpret_cast<const char*>(file_->data()), | 112 socket->Send(reinterpret_cast<const char*>(file_->data()), |
107 file_->length(), false); | 113 file_->length(), false); |
108 } | 114 } |
109 } | 115 } |
110 | 116 |
111 size_t FileResponse::ContentLength() const { | 117 size_t FileResponse::ContentLength() const { |
112 if (file_.get() == NULL) { | 118 if (file_.get() == NULL) { |
113 file_.reset(new file_util::MemoryMappedFile()); | 119 file_.reset(new file_util::MemoryMappedFile()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 for (it = responses_.begin(); it != responses_.end(); it++) { | 167 for (it = responses_.begin(); it != responses_.end(); it++) { |
162 Response* response = (*it); | 168 Response* response = (*it); |
163 if (response->Matches(request)) { | 169 if (response->Matches(request)) { |
164 return response; | 170 return response; |
165 } | 171 } |
166 } | 172 } |
167 return NULL; | 173 return NULL; |
168 } | 174 } |
169 | 175 |
170 Connection* SimpleWebServer::FindConnection( | 176 Connection* SimpleWebServer::FindConnection( |
171 const net::ListenSocket* socket) const { | 177 const net::StreamListenSocket* socket) const { |
172 ConnectionList::const_iterator it; | 178 ConnectionList::const_iterator it; |
173 for (it = connections_.begin(); it != connections_.end(); it++) { | 179 for (it = connections_.begin(); it != connections_.end(); it++) { |
174 if ((*it)->IsSame(socket)) { | 180 if ((*it)->IsSame(socket)) { |
175 return (*it); | 181 return (*it); |
176 } | 182 } |
177 } | 183 } |
178 return NULL; | 184 return NULL; |
179 } | 185 } |
180 | 186 |
181 void SimpleWebServer::DidAccept(net::ListenSocket* server, | 187 void SimpleWebServer::DidAccept(net::StreamListenSocket* server, |
182 net::ListenSocket* connection) { | 188 net::StreamListenSocket* connection) { |
183 connections_.push_back(new Connection(connection)); | 189 connections_.push_back(new Connection(connection)); |
184 } | 190 } |
185 | 191 |
186 void SimpleWebServer::DidRead(net::ListenSocket* connection, | 192 void SimpleWebServer::DidRead(net::StreamListenSocket* connection, |
187 const char* data, | 193 const char* data, |
188 int len) { | 194 int len) { |
189 Connection* c = FindConnection(connection); | 195 Connection* c = FindConnection(connection); |
190 DCHECK(c); | 196 DCHECK(c); |
191 Request& r = c->request(); | 197 Request& r = c->request(); |
192 std::string str(data, len); | 198 std::string str(data, len); |
193 r.OnDataReceived(str); | 199 r.OnDataReceived(str); |
194 if (r.AllContentReceived()) { | 200 if (r.AllContentReceived()) { |
195 const Request& request = c->request(); | 201 const Request& request = c->request(); |
196 Response* response = FindResponse(request); | 202 Response* response = FindResponse(request); |
(...skipping 16 matching lines...) Expand all Loading... |
213 std::string headers(base::StringPrintf(kDefaultHeaderTemplate, | 219 std::string headers(base::StringPrintf(kDefaultHeaderTemplate, |
214 kStatusNotFound, | 220 kStatusNotFound, |
215 kDefaultContentType, | 221 kDefaultContentType, |
216 payload.length())); | 222 payload.length())); |
217 connection->Send(headers, false); | 223 connection->Send(headers, false); |
218 connection->Send(payload, false); | 224 connection->Send(payload, false); |
219 } | 225 } |
220 } | 226 } |
221 } | 227 } |
222 | 228 |
223 void SimpleWebServer::DidClose(net::ListenSocket* sock) { | 229 void SimpleWebServer::DidClose(net::StreamListenSocket* sock) { |
224 // To keep the historical list of connections reasonably tidy, we delete | 230 // To keep the historical list of connections reasonably tidy, we delete |
225 // 404's when the connection ends. | 231 // 404's when the connection ends. |
226 Connection* c = FindConnection(sock); | 232 Connection* c = FindConnection(sock); |
227 DCHECK(c); | 233 DCHECK(c); |
228 c->OnSocketClosed(); | 234 c->OnSocketClosed(); |
229 if (!FindResponse(c->request())) { | 235 if (!FindResponse(c->request())) { |
230 // extremely inefficient, but in one line and not that common... :) | 236 // extremely inefficient, but in one line and not that common... :) |
231 connections_.erase(std::find(connections_.begin(), connections_.end(), c)); | 237 connections_.erase(std::find(connections_.begin(), connections_.end(), c)); |
232 delete c; | 238 delete c; |
233 } | 239 } |
234 } | 240 } |
235 | 241 |
236 HTTPTestServer::HTTPTestServer(int port, const std::wstring& address, | 242 HTTPTestServer::HTTPTestServer(int port, const std::wstring& address, |
237 FilePath root_dir) | 243 FilePath root_dir) |
238 : port_(port), address_(address), root_dir_(root_dir) { | 244 : port_(port), address_(address), root_dir_(root_dir) { |
239 net::EnsureWinsockInit(); | 245 net::EnsureWinsockInit(); |
240 server_ = | 246 server_ = |
241 net::TCPListenSocket::CreateAndListen(WideToUTF8(address), port, this); | 247 net::TCPListenSocket::CreateAndListen(WideToUTF8(address), port, this); |
242 } | 248 } |
243 | 249 |
244 HTTPTestServer::~HTTPTestServer() { | 250 HTTPTestServer::~HTTPTestServer() { |
245 server_ = NULL; | 251 server_ = NULL; |
246 } | 252 } |
247 | 253 |
248 std::list<scoped_refptr<ConfigurableConnection>>::iterator | 254 std::list<scoped_refptr<ConfigurableConnection>>::iterator |
249 HTTPTestServer::FindConnection(const net::ListenSocket* socket) { | 255 HTTPTestServer::FindConnection(const net::StreamListenSocket* socket) { |
250 ConnectionList::iterator it; | 256 ConnectionList::iterator it; |
251 // Scan through the list searching for the desired socket. Along the way, | 257 // Scan through the list searching for the desired socket. Along the way, |
252 // erase any connections for which the corresponding socket has already been | 258 // erase any connections for which the corresponding socket has already been |
253 // forgotten about as a result of all data having been sent. | 259 // forgotten about as a result of all data having been sent. |
254 for (it = connection_list_.begin(); it != connection_list_.end(); ) { | 260 for (it = connection_list_.begin(); it != connection_list_.end(); ) { |
255 ConfigurableConnection* connection = it->get(); | 261 ConfigurableConnection* connection = it->get(); |
256 if (connection->socket_ == NULL) { | 262 if (connection->socket_ == NULL) { |
257 connection_list_.erase(it++); | 263 connection_list_.erase(it++); |
258 continue; | 264 continue; |
259 } | 265 } |
260 if (connection->socket_ == socket) | 266 if (connection->socket_ == socket) |
261 break; | 267 break; |
262 ++it; | 268 ++it; |
263 } | 269 } |
264 | 270 |
265 return it; | 271 return it; |
266 } | 272 } |
267 | 273 |
268 scoped_refptr<ConfigurableConnection> HTTPTestServer::ConnectionFromSocket( | 274 scoped_refptr<ConfigurableConnection> HTTPTestServer::ConnectionFromSocket( |
269 const net::ListenSocket* socket) { | 275 const net::StreamListenSocket* socket) { |
270 ConnectionList::iterator it = FindConnection(socket); | 276 ConnectionList::iterator it = FindConnection(socket); |
271 if (it != connection_list_.end()) | 277 if (it != connection_list_.end()) |
272 return *it; | 278 return *it; |
273 return NULL; | 279 return NULL; |
274 } | 280 } |
275 | 281 |
276 void HTTPTestServer::DidAccept(net::ListenSocket* server, | 282 void HTTPTestServer::DidAccept(net::StreamListenSocket* server, |
277 net::ListenSocket* socket) { | 283 net::StreamListenSocket* socket) { |
278 connection_list_.push_back(new ConfigurableConnection(socket)); | 284 connection_list_.push_back(new ConfigurableConnection(socket)); |
279 } | 285 } |
280 | 286 |
281 void HTTPTestServer::DidRead(net::ListenSocket* socket, | 287 void HTTPTestServer::DidRead(net::StreamListenSocket* socket, |
282 const char* data, | 288 const char* data, |
283 int len) { | 289 int len) { |
284 scoped_refptr<ConfigurableConnection> connection = | 290 scoped_refptr<ConfigurableConnection> connection = |
285 ConnectionFromSocket(socket); | 291 ConnectionFromSocket(socket); |
286 if (connection) { | 292 if (connection) { |
287 std::string str(data, len); | 293 std::string str(data, len); |
288 connection->r_.OnDataReceived(str); | 294 connection->r_.OnDataReceived(str); |
289 if (connection->r_.AllContentReceived()) { | 295 if (connection->r_.AllContentReceived()) { |
290 VLOG(1) << __FUNCTION__ << ": " << connection->r_.method() << " " | 296 VLOG(1) << __FUNCTION__ << ": " << connection->r_.method() << " " |
291 << connection->r_.path(); | 297 << connection->r_.path(); |
292 std::wstring path = UTF8ToWide(connection->r_.path()); | 298 std::wstring path = UTF8ToWide(connection->r_.path()); |
293 if (LowerCaseEqualsASCII(connection->r_.method(), "post")) | 299 if (LowerCaseEqualsASCII(connection->r_.method(), "post")) |
294 this->Post(connection, path, connection->r_); | 300 this->Post(connection, path, connection->r_); |
295 else | 301 else |
296 this->Get(connection, path, connection->r_); | 302 this->Get(connection, path, connection->r_); |
297 } | 303 } |
298 } | 304 } |
299 } | 305 } |
300 | 306 |
301 void HTTPTestServer::DidClose(net::ListenSocket* socket) { | 307 void HTTPTestServer::DidClose(net::StreamListenSocket* socket) { |
302 ConnectionList::iterator it = FindConnection(socket); | 308 ConnectionList::iterator it = FindConnection(socket); |
303 if (it != connection_list_.end()) | 309 if (it != connection_list_.end()) |
304 connection_list_.erase(it); | 310 connection_list_.erase(it); |
305 } | 311 } |
306 | 312 |
307 std::wstring HTTPTestServer::Resolve(const std::wstring& path) { | 313 std::wstring HTTPTestServer::Resolve(const std::wstring& path) { |
308 // Remove the first '/' if needed. | 314 // Remove the first '/' if needed. |
309 std::wstring stripped_path = path; | 315 std::wstring stripped_path = path; |
310 if (path.size() && path[0] == L'/') | 316 if (path.size() && path[0] == L'/') |
311 stripped_path = path.substr(1); | 317 stripped_path = path.substr(1); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 content.size()); | 372 content.size()); |
367 } | 373 } |
368 | 374 |
369 // Save the options. | 375 // Save the options. |
370 options_ = options; | 376 options_ = options; |
371 | 377 |
372 if (options_.speed_ == SendOptions::IMMEDIATE) { | 378 if (options_.speed_ == SendOptions::IMMEDIATE) { |
373 socket_->Send(headers); | 379 socket_->Send(headers); |
374 socket_->Send(content_length_header, true); | 380 socket_->Send(content_length_header, true); |
375 socket_->Send(content); | 381 socket_->Send(content); |
376 // Post a task to close the socket since ListenSocket doesn't like instances | 382 // Post a task to close the socket since StreamListenSocket doesn't like |
377 // to go away from within its callbacks. | 383 // instances to go away from within its callbacks. |
378 MessageLoop::current()->PostTask( | 384 MessageLoop::current()->PostTask( |
379 FROM_HERE, base::Bind(&ConfigurableConnection::Close, this)); | 385 FROM_HERE, base::Bind(&ConfigurableConnection::Close, this)); |
380 | 386 |
381 return; | 387 return; |
382 } | 388 } |
383 | 389 |
384 if (options_.speed_ == SendOptions::IMMEDIATE_HEADERS_DELAYED_CONTENT) { | 390 if (options_.speed_ == SendOptions::IMMEDIATE_HEADERS_DELAYED_CONTENT) { |
385 socket_->Send(headers); | 391 socket_->Send(headers); |
386 socket_->Send(content_length_header, true); | 392 socket_->Send(content_length_header, true); |
387 VLOG(1) << "Headers sent: " << headers << content_length_header; | 393 VLOG(1) << "Headers sent: " << headers << content_length_header; |
388 data_.append(content); | 394 data_.append(content); |
389 } | 395 } |
390 | 396 |
391 if (options_.speed_ == SendOptions::DELAYED) { | 397 if (options_.speed_ == SendOptions::DELAYED) { |
392 data_ = headers; | 398 data_ = headers; |
393 data_.append(content_length_header); | 399 data_.append(content_length_header); |
394 data_.append("\r\n"); | 400 data_.append("\r\n"); |
395 } | 401 } |
396 | 402 |
397 MessageLoop::current()->PostDelayedTask( | 403 MessageLoop::current()->PostDelayedTask( |
398 FROM_HERE, base::Bind(&ConfigurableConnection::SendChunk, this), | 404 FROM_HERE, base::Bind(&ConfigurableConnection::SendChunk, this), |
399 base::TimeDelta::FromMilliseconds(options.timeout_)); | 405 base::TimeDelta::FromMilliseconds(options.timeout_)); |
400 } | 406 } |
401 | 407 |
402 } // namespace test_server | 408 } // namespace test_server |
OLD | NEW |