Chromium Code Reviews| Index: chrome/browser/chromeos/gdata/test_servers/http_server.cc |
| diff --git a/chrome/browser/chromeos/gdata/test_servers/http_server.cc b/chrome/browser/chromeos/gdata/test_servers/http_server.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a7906f19670d0b65ee8582e2c4e54237a3f84461 |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/gdata/test_servers/http_server.cc |
| @@ -0,0 +1,126 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/chromeos/gdata/test_servers/http_server.h" |
| + |
| +#include "base/synchronization/waitable_event.h" |
| +#include "content/public/browser/browser_thread.h" |
| + |
| +#include <string> |
| +#include <sstream> |
| +#include "base/stl_util.h" |
| + |
| +namespace gdata { |
| +namespace test_servers { |
| + |
| +using content::BrowserThread; |
| + |
| +// static |
| +scoped_refptr<HttpServer> HttpServer::CreateServer( |
| + const std::string& address, |
| + int port, |
| + HttpConnectionDelegate* connection_delegate) { |
| + |
| + // Launching the server class in the IO thread and waiting for the result. |
| + // TODO(mtomasz): Change it to a completely new thread. |
| + base::WaitableEvent waiter(false, false); |
|
satorux1
2012/10/12 08:29:18
WaitableEvent should almost always be avoided.
I
mtomasz
2012/10/12 11:09:46
Correct me if I am wrong, but I think I really nee
satorux1
2012/10/16 03:12:18
I think you can make the object creation asynchron
|
| + HttpServer* server = NULL; |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(CreateServerOnIOThread, |
| + address, |
| + port, |
| + connection_delegate, |
| + &waiter, |
| + &server)); |
| + waiter.Wait(); |
| + |
| + return server; |
| +} |
| + |
| +void HttpServer::DropHttpConnection(HttpConnection* connection) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + connections_.erase(connection->socket_.get()); |
| + delete connection; |
| +} |
| + |
| +// static |
| +void HttpServer::CreateServerOnIOThread( |
|
satorux1
2012/10/12 08:29:18
I guess you can make it a free function in anonymo
mtomasz
2012/10/12 11:09:46
I wanted to keep the constructor private. Also Lis
satorux1
2012/10/16 03:12:18
Then that's fine. Thank you for the explanation.
|
| + const std::string& address, |
| + int port, |
| + HttpConnectionDelegate* connection_delegate, |
| + base::WaitableEvent* waiter, |
| + HttpServer** server_ptr) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + SocketDescriptor socket_descriptor = CreateAndBind(address, port); |
| + HttpServer* server = NULL; |
| + if (socket_descriptor != kInvalidSocket) { |
| + server = new HttpServer(socket_descriptor, connection_delegate); |
| + server->Listen(); |
| + } |
| + |
| + // Return the value and notify the caller (if provided) that the value |
| + // is available. |
| + *server_ptr = server; |
| + if (waiter) |
| + waiter->Signal(); |
| +} |
| + |
| +HttpServer::HttpServer(SocketDescriptor& socket, |
| + HttpConnectionDelegate* connection_delegate) : |
| + net::TCPListenSocket(socket, ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| + connection_delegate_(connection_delegate) { |
| +} |
| + |
| +HttpServer::~HttpServer() { |
| + STLDeleteContainerPairSecondPointers(connections_.begin(), |
| + connections_.end()); |
| +} |
| + |
| +void HttpServer::DidAccept(StreamListenSocket* server, |
| + StreamListenSocket* connection) { |
| + HttpConnection* http_connection = new HttpConnection(connection, |
| + connection_delegate_); |
| + connections_[connection] = http_connection; |
| +} |
| + |
| +void HttpServer::DidRead(StreamListenSocket* connection, |
| + const char* data, |
| + int length) { |
| + HttpConnection* http_connection = FindConnection(connection); |
| + if (http_connection == NULL) { |
| + LOG(ERROR) << "Unknown connection."; |
| + return; |
| + } |
| + if (!http_connection->ReceiveData(data, length)) { |
| + // Error occured during receiving data, or the request has not been |
| + // handled by any of request handlers, so we are dropping the connection. |
| + DropHttpConnection(http_connection); |
| + } |
| +} |
| + |
| +void HttpServer::DidClose(StreamListenSocket* connection) { |
| + HttpConnection* http_connection = FindConnection(connection); |
| + if (http_connection == NULL) { |
| + LOG(ERROR) << "Unknown connection."; |
| + return; |
| + } |
| + delete http_connection; |
| + connections_.erase(connection); |
| +} |
| + |
| +HttpConnection* HttpServer::FindConnection(StreamListenSocket* socket) { |
| + std::map<StreamListenSocket*, HttpConnection*>::iterator it = |
| + connections_.find(socket); |
| + if (it == connections_.end()) { |
| + return NULL; |
| + } |
| + return it->second; |
| +} |
| + |
| +} // namespace test_servers |
| +} // namespace gdata |