summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-03 17:23:24 +0000
committerpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-03 17:23:24 +0000
commita33721a77396c8f7607d330cd3d07b82f4ebc0ed (patch)
treeeee496f02500b7acefee4450aa9d6859aad3901c
parent2d354bbcb647825dab961834b23ed6756489b73a (diff)
downloadchromium_src-a33721a77396c8f7607d330cd3d07b82f4ebc0ed.zip
chromium_src-a33721a77396c8f7607d330cd3d07b82f4ebc0ed.tar.gz
chromium_src-a33721a77396c8f7607d330cd3d07b82f4ebc0ed.tar.bz2
DevTools: split http_listen_socket into http_server and connection.
BUG= TEST= Review URL: http://codereview.chromium.org/6410033 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73631 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/debugger/devtools_http_protocol_handler.cc197
-rw-r--r--chrome/browser/debugger/devtools_http_protocol_handler.h51
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--net/base/listen_socket.cc5
-rw-r--r--net/net.gyp6
-rw-r--r--net/server/http_listen_socket.h72
-rw-r--r--net/server/http_server.cc (renamed from net/server/http_listen_socket.cc)283
-rw-r--r--net/server/http_server.h96
8 files changed, 402 insertions, 310 deletions
diff --git a/chrome/browser/debugger/devtools_http_protocol_handler.cc b/chrome/browser/debugger/devtools_http_protocol_handler.cc
index 940e942..9351b40 100644
--- a/chrome/browser/debugger/devtools_http_protocol_handler.cc
+++ b/chrome/browser/debugger/devtools_http_protocol_handler.cc
@@ -22,7 +22,6 @@
#include "chrome/common/net/url_request_context_getter.h"
#include "googleurl/src/gurl.h"
#include "net/base/io_buffer.h"
-#include "net/base/listen_socket.h"
#include "net/server/http_server_request_info.h"
#include "net/url_request/url_request_context.h"
@@ -34,8 +33,12 @@ namespace {
// messages sent for DevToolsClient to a DebuggerShell instance.
class DevToolsClientHostImpl : public DevToolsClientHost {
public:
- explicit DevToolsClientHostImpl(HttpListenSocket* socket)
- : socket_(socket) {}
+ DevToolsClientHostImpl(
+ HttpServer* server,
+ int connection_id)
+ : server_(server),
+ connection_id_(connection_id) {
+ }
~DevToolsClientHostImpl() {}
// DevToolsClientHost interface
@@ -43,8 +46,9 @@ class DevToolsClientHostImpl : public DevToolsClientHost {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- NewRunnableMethod(socket_,
- &HttpListenSocket::Close));
+ NewRunnableMethod(server_,
+ &HttpServer::Close,
+ connection_id_));
}
virtual void SendMessageToClient(const IPC::Message& msg) {
@@ -64,10 +68,18 @@ class DevToolsClientHostImpl : public DevToolsClientHost {
private:
// Message handling routines
void OnDispatchOnInspectorFrontend(const std::string& data) {
- socket_->SendOverWebSocket(data);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableMethod(server_,
+ &HttpServer::SendOverWebSocket,
+ connection_id_,
+ data));
}
+
virtual void FrameNavigating(const std::string& url) {}
- HttpListenSocket* socket_;
+ HttpServer* server_;
+ int connection_id_;
};
} // namespace
@@ -102,7 +114,7 @@ void DevToolsHttpProtocolHandler::Stop() {
}
void DevToolsHttpProtocolHandler::OnHttpRequest(
- HttpListenSocket* socket,
+ int connection_id,
const HttpServerRequestInfo& info) {
if (info.path == "" || info.path == "/") {
// Pages discovery request.
@@ -111,28 +123,28 @@ void DevToolsHttpProtocolHandler::OnHttpRequest(
FROM_HERE,
NewRunnableMethod(this,
&DevToolsHttpProtocolHandler::OnHttpRequestUI,
- make_scoped_refptr(socket),
+ connection_id,
info));
return;
}
size_t pos = info.path.find("/devtools/");
if (pos != 0) {
- socket->Send404();
+ server_->Send404(connection_id);
return;
}
// Proxy static files from chrome://devtools/*.
net::URLRequest* request = new net::URLRequest(
GURL("chrome:/" + info.path), this);
- Bind(request, socket);
+ Bind(request, connection_id);
request->set_context(
Profile::GetDefaultRequestContext()->GetURLRequestContext());
request->Start();
}
void DevToolsHttpProtocolHandler::OnWebSocketRequest(
- HttpListenSocket* socket,
+ int connection_id,
const HttpServerRequestInfo& request) {
BrowserThread::PostTask(
BrowserThread::UI,
@@ -140,35 +152,37 @@ void DevToolsHttpProtocolHandler::OnWebSocketRequest(
NewRunnableMethod(
this,
&DevToolsHttpProtocolHandler::OnWebSocketRequestUI,
- make_scoped_refptr(socket),
+ connection_id,
request));
}
-void DevToolsHttpProtocolHandler::OnWebSocketMessage(HttpListenSocket* socket,
- const std::string& data) {
+void DevToolsHttpProtocolHandler::OnWebSocketMessage(
+ int connection_id,
+ const std::string& data) {
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
NewRunnableMethod(
this,
&DevToolsHttpProtocolHandler::OnWebSocketMessageUI,
- make_scoped_refptr(socket),
+ connection_id,
data));
}
-void DevToolsHttpProtocolHandler::OnClose(HttpListenSocket* socket) {
- SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
- if (it != socket_to_requests_io_.end()) {
+void DevToolsHttpProtocolHandler::OnClose(int connection_id) {
+ ConnectionToRequestsMap::iterator it =
+ connection_to_requests_io_.find(connection_id);
+ if (it != connection_to_requests_io_.end()) {
// Dispose delegating socket.
for (std::set<net::URLRequest*>::iterator it2 = it->second.begin();
it2 != it->second.end(); ++it2) {
net::URLRequest* request = *it2;
request->Cancel();
- request_to_socket_io_.erase(request);
+ request_to_connection_io_.erase(request);
request_to_buffer_io_.erase(request);
delete request;
}
- socket_to_requests_io_.erase(socket);
+ connection_to_requests_io_.erase(connection_id);
}
BrowserThread::PostTask(
@@ -177,11 +191,11 @@ void DevToolsHttpProtocolHandler::OnClose(HttpListenSocket* socket) {
NewRunnableMethod(
this,
&DevToolsHttpProtocolHandler::OnCloseUI,
- make_scoped_refptr(socket)));
+ connection_id));
}
void DevToolsHttpProtocolHandler::OnHttpRequestUI(
- HttpListenSocket* socket,
+ int connection_id,
const HttpServerRequestInfo& info) {
std::string response = "<html><body><script>"
"function addTab(id, url, attached, frontendUrl) {"
@@ -226,51 +240,53 @@ void DevToolsHttpProtocolHandler::OnHttpRequestUI(
}
response += "</script></body></html>";
- Send200(socket, response, "text/html; charset=UTF-8");
+ Send200(connection_id, response, "text/html; charset=UTF-8");
}
void DevToolsHttpProtocolHandler::OnWebSocketRequestUI(
- HttpListenSocket* socket,
+ int connection_id,
const HttpServerRequestInfo& request) {
std::string prefix = "/devtools/page/";
size_t pos = request.path.find(prefix);
if (pos != 0) {
- Send404(socket);
+ Send404(connection_id);
return;
}
std::string page_id = request.path.substr(prefix.length());
int id = 0;
if (!base::StringToInt(page_id, &id)) {
- Send500(socket, "Invalid page id: " + page_id);
+ Send500(connection_id, "Invalid page id: " + page_id);
return;
}
TabContents* tab_contents = GetTabContents(id);
if (tab_contents == NULL) {
- Send500(socket, "No such page id: " + page_id);
+ Send500(connection_id, "No such page id: " + page_id);
return;
}
DevToolsManager* manager = DevToolsManager::GetInstance();
if (manager->GetDevToolsClientHostFor(tab_contents->render_view_host())) {
- Send500(socket, "Page with given id is being inspected: " + page_id);
+ Send500(connection_id, "Page with given id is being inspected: " + page_id);
return;
}
- DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl(socket);
- socket_to_client_host_ui_[socket] = client_host;
+ DevToolsClientHostImpl* client_host =
+ new DevToolsClientHostImpl(server_, connection_id);
+ connection_to_client_host_ui_[connection_id] = client_host;
manager->RegisterDevToolsClientHostFor(
tab_contents->render_view_host(),
client_host);
- AcceptWebSocket(socket, request);
+ AcceptWebSocket(connection_id, request);
}
void DevToolsHttpProtocolHandler::OnWebSocketMessageUI(
- HttpListenSocket* socket,
+ int connection_id,
const std::string& data) {
- SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
- if (it == socket_to_client_host_ui_.end())
+ ConnectionToClientHostMap::iterator it =
+ connection_to_client_host_ui_.find(connection_id);
+ if (it == connection_to_client_host_ui_.end())
return;
DevToolsManager* manager = DevToolsManager::GetInstance();
@@ -287,35 +303,24 @@ void DevToolsHttpProtocolHandler::OnWebSocketMessageUI(
DevToolsAgentMsg_DispatchOnInspectorBackend(data));
}
-void DevToolsHttpProtocolHandler::OnCloseUI(HttpListenSocket* socket) {
- SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
- if (it != socket_to_client_host_ui_.end()) {
+void DevToolsHttpProtocolHandler::OnCloseUI(int connection_id) {
+ ConnectionToClientHostMap::iterator it =
+ connection_to_client_host_ui_.find(connection_id);
+ if (it != connection_to_client_host_ui_.end()) {
DevToolsClientHostImpl* client_host =
static_cast<DevToolsClientHostImpl*>(it->second);
client_host->NotifyCloseListener();
delete client_host;
- socket_to_client_host_ui_.erase(socket);
+ connection_to_client_host_ui_.erase(connection_id);
}
-
- // We are holding last reference to scoped refptr 'socket' here.
- // We can't exit method just like that since 'socket' is going to
- // be destroyed on the UI thread then. Schedule no-op to IO thread
- // so that socket is destroyed on IO instead.
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- NewRunnableMethod(
- this,
- &DevToolsHttpProtocolHandler::ReleaseSocket,
- make_scoped_refptr(socket)));
}
void DevToolsHttpProtocolHandler::OnResponseStarted(net::URLRequest* request) {
- RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
- if (it == request_to_socket_io_.end())
+ RequestToSocketMap::iterator it = request_to_connection_io_.find(request);
+ if (it == request_to_connection_io_.end())
return;
- HttpListenSocket* socket = it->second;
+ int connection_id = it->second;
int expected_size = static_cast<int>(request->GetExpectedContentSize());
@@ -323,14 +328,14 @@ void DevToolsHttpProtocolHandler::OnResponseStarted(net::URLRequest* request) {
request->GetMimeType(&content_type);
if (request->status().is_success()) {
- socket->Send(StringPrintf("HTTP/1.1 200 OK\r\n"
- "Content-Type:%s\r\n"
- "Content-Length:%d\r\n"
- "\r\n",
- content_type.c_str(),
- expected_size));
+ server_->Send(connection_id, StringPrintf("HTTP/1.1 200 OK\r\n"
+ "Content-Type:%s\r\n"
+ "Content-Length:%d\r\n"
+ "\r\n",
+ content_type.c_str(),
+ expected_size));
} else {
- socket->Send404();
+ server_->Send404(connection_id);
}
int bytes_read = 0;
@@ -346,17 +351,17 @@ void DevToolsHttpProtocolHandler::OnResponseStarted(net::URLRequest* request) {
void DevToolsHttpProtocolHandler::OnReadCompleted(net::URLRequest* request,
int bytes_read) {
- RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
- if (it == request_to_socket_io_.end())
+ RequestToSocketMap::iterator it = request_to_connection_io_.find(request);
+ if (it == request_to_connection_io_.end())
return;
- HttpListenSocket* socket = it->second;
+ int connection_id = it->second;
net::IOBuffer* buffer = request_to_buffer_io_[request].get();
do {
if (!request->status().is_success() || bytes_read <= 0)
break;
- socket->Send(buffer->data(), bytes_read);
+ server_->Send(connection_id, buffer->data(), bytes_read);
} while (request->Read(buffer, kBufferSize, &bytes_read));
// See comments re: HEAD requests in OnResponseStarted().
@@ -370,14 +375,13 @@ DevToolsHttpProtocolHandler::DevToolsHttpProtocolHandler(
TabContentsProvider* provider)
: port_(port),
overriden_frontend_url_(frontend_host),
- server_(NULL),
tab_contents_provider_(provider) {
if (overriden_frontend_url_.empty())
overriden_frontend_url_ = "/devtools/devtools.html";
}
void DevToolsHttpProtocolHandler::Init() {
- server_ = HttpListenSocket::Listen("127.0.0.1", port_, this);
+ server_ = new HttpServer("127.0.0.1", port_, this);
}
// Run on I/O thread
@@ -386,74 +390,75 @@ void DevToolsHttpProtocolHandler::Teardown() {
}
void DevToolsHttpProtocolHandler::Bind(net::URLRequest* request,
- HttpListenSocket* socket) {
- request_to_socket_io_[request] = socket;
- SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
- if (it == socket_to_requests_io_.end()) {
- std::pair<HttpListenSocket*, std::set<net::URLRequest*> > value(
- socket,
+ int connection_id) {
+ request_to_connection_io_[request] = connection_id;
+ ConnectionToRequestsMap::iterator it =
+ connection_to_requests_io_.find(connection_id);
+ if (it == connection_to_requests_io_.end()) {
+ std::pair<int, std::set<net::URLRequest*> > value(
+ connection_id,
std::set<net::URLRequest*>());
- it = socket_to_requests_io_.insert(value).first;
+ it = connection_to_requests_io_.insert(value).first;
}
it->second.insert(request);
request_to_buffer_io_[request] = new net::IOBuffer(kBufferSize);
}
void DevToolsHttpProtocolHandler::RequestCompleted(net::URLRequest* request) {
- RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
- if (it == request_to_socket_io_.end())
+ RequestToSocketMap::iterator it = request_to_connection_io_.find(request);
+ if (it == request_to_connection_io_.end())
return;
- HttpListenSocket* socket = it->second;
- request_to_socket_io_.erase(request);
- SocketToRequestsMap::iterator it2 = socket_to_requests_io_.find(socket);
+ int connection_id = it->second;
+ request_to_connection_io_.erase(request);
+ ConnectionToRequestsMap::iterator it2 =
+ connection_to_requests_io_.find(connection_id);
it2->second.erase(request);
request_to_buffer_io_.erase(request);
delete request;
}
-void DevToolsHttpProtocolHandler::Send200(HttpListenSocket* socket,
+void DevToolsHttpProtocolHandler::Send200(int connection_id,
const std::string& data,
const std::string& mime_type) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- NewRunnableMethod(socket,
- &HttpListenSocket::Send200,
+ NewRunnableMethod(server_.get(),
+ &HttpServer::Send200,
+ connection_id,
data,
mime_type));
}
-void DevToolsHttpProtocolHandler::Send404(HttpListenSocket* socket) {
+void DevToolsHttpProtocolHandler::Send404(int connection_id) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- NewRunnableMethod(socket,
- &HttpListenSocket::Send404));
+ NewRunnableMethod(server_.get(),
+ &HttpServer::Send404,
+ connection_id));
}
-void DevToolsHttpProtocolHandler::Send500(HttpListenSocket* socket,
+void DevToolsHttpProtocolHandler::Send500(int connection_id,
const std::string& message) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- NewRunnableMethod(socket,
- &HttpListenSocket::Send500,
+ NewRunnableMethod(server_.get(),
+ &HttpServer::Send500,
+ connection_id,
message));
}
void DevToolsHttpProtocolHandler::AcceptWebSocket(
- HttpListenSocket* socket,
+ int connection_id,
const HttpServerRequestInfo& request) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- NewRunnableMethod(socket,
- &HttpListenSocket::AcceptWebSocket,
+ NewRunnableMethod(server_.get(),
+ &HttpServer::AcceptWebSocket,
+ connection_id,
request));
}
-void DevToolsHttpProtocolHandler::ReleaseSocket(
- HttpListenSocket* socket) {
- // This in fact is scoped ref ptr. It'll get nuked on exit.
-}
-
TabContents* DevToolsHttpProtocolHandler::GetTabContents(int session_id) {
InspectableTabs inspectable_tabs =
tab_contents_provider_->GetInspectableTabs();
diff --git a/chrome/browser/debugger/devtools_http_protocol_handler.h b/chrome/browser/debugger/devtools_http_protocol_handler.h
index 1bb4726..bfa2de8 100644
--- a/chrome/browser/debugger/devtools_http_protocol_handler.h
+++ b/chrome/browser/debugger/devtools_http_protocol_handler.h
@@ -12,7 +12,7 @@
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
-#include "net/server/http_listen_socket.h"
+#include "net/server/http_server.h"
#include "net/url_request/url_request.h"
class DevToolsClientHost;
@@ -21,7 +21,7 @@ class TabContents;
class TabContentsWrapper;
class DevToolsHttpProtocolHandler
- : public HttpListenSocket::Delegate,
+ : public HttpServer::Delegate,
public net::URLRequest::Delegate,
public base::RefCountedThreadSafe<DevToolsHttpProtocolHandler> {
public:
@@ -54,22 +54,22 @@ class DevToolsHttpProtocolHandler
virtual ~DevToolsHttpProtocolHandler();
void Start();
- // HttpListenSocket::Delegate implementation.
- virtual void OnHttpRequest(HttpListenSocket* socket,
+ // HttpServer::Delegate implementation.
+ virtual void OnHttpRequest(int connection_id,
const HttpServerRequestInfo& info);
- virtual void OnWebSocketRequest(HttpListenSocket* socket,
+ virtual void OnWebSocketRequest(int connection_id,
const HttpServerRequestInfo& info);
- virtual void OnWebSocketMessage(HttpListenSocket* socket,
+ virtual void OnWebSocketMessage(int connection_id,
const std::string& data);
- virtual void OnClose(HttpListenSocket* socket);
+ virtual void OnClose(int connection_id);
- virtual void OnHttpRequestUI(HttpListenSocket* socket,
+ virtual void OnHttpRequestUI(int connection_id,
const HttpServerRequestInfo& info);
- virtual void OnWebSocketRequestUI(HttpListenSocket* socket,
+ virtual void OnWebSocketRequestUI(int connection_id,
const HttpServerRequestInfo& info);
- virtual void OnWebSocketMessageUI(HttpListenSocket* socket,
+ virtual void OnWebSocketMessageUI(int connection_id,
const std::string& data);
- virtual void OnCloseUI(HttpListenSocket* socket);
+ virtual void OnCloseUI(int connection_id);
// net::URLRequest::Delegate implementation.
virtual void OnResponseStarted(net::URLRequest* request);
@@ -77,36 +77,35 @@ class DevToolsHttpProtocolHandler
void Init();
void Teardown();
- void Bind(net::URLRequest* request, HttpListenSocket* socket);
+ void Bind(net::URLRequest* request, int connection_id);
void RequestCompleted(net::URLRequest* request);
- void Send200(HttpListenSocket* socket,
+ void Send200(int connection_id,
const std::string& data,
const std::string& mime_type = "text/html");
- void Send404(HttpListenSocket* socket);
- void Send500(HttpListenSocket* socket,
+ void Send404(int connection_id);
+ void Send500(int connection_id,
const std::string& message);
- void AcceptWebSocket(HttpListenSocket* socket,
+ void AcceptWebSocket(int connection_id,
const HttpServerRequestInfo& request);
- void ReleaseSocket(HttpListenSocket* socket);
TabContents* GetTabContents(int session_id);
int port_;
std::string overriden_frontend_url_;
- scoped_refptr<HttpListenSocket> server_;
- typedef std::map<net::URLRequest*, HttpListenSocket*>
+ scoped_refptr<HttpServer> server_;
+ typedef std::map<net::URLRequest*, int>
RequestToSocketMap;
- RequestToSocketMap request_to_socket_io_;
- typedef std::map<HttpListenSocket*, std::set<net::URLRequest*> >
- SocketToRequestsMap;
- SocketToRequestsMap socket_to_requests_io_;
+ RequestToSocketMap request_to_connection_io_;
+ typedef std::map<int, std::set<net::URLRequest*> >
+ ConnectionToRequestsMap;
+ ConnectionToRequestsMap connection_to_requests_io_;
typedef std::map<net::URLRequest*, scoped_refptr<net::IOBuffer> >
BuffersMap;
BuffersMap request_to_buffer_io_;
- typedef std::map<HttpListenSocket*, DevToolsClientHost*>
- SocketToClientHostMap;
- SocketToClientHostMap socket_to_client_host_ui_;
+ typedef std::map<int, DevToolsClientHost*>
+ ConnectionToClientHostMap;
+ ConnectionToClientHostMap connection_to_client_host_ui_;
scoped_ptr<TabContentsProvider> tab_contents_provider_;
DISALLOW_COPY_AND_ASSIGN(DevToolsHttpProtocolHandler);
};
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 63c9480..f1da091e 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -498,7 +498,7 @@
'dependencies': [
'chrome_resources',
'chrome_strings',
- '../net/net.gyp:http_listen_socket',
+ '../net/net.gyp:http_server',
'theme_resources',
'../skia/skia.gyp:skia',
'../third_party/icu/icu.gyp:icui18n',
diff --git a/net/base/listen_socket.cc b/net/base/listen_socket.cc
index 274837a..6ca8dcc 100644
--- a/net/base/listen_socket.cc
+++ b/net/base/listen_socket.cc
@@ -107,6 +107,11 @@ ListenSocket::~ListenSocket() {
SOCKET ListenSocket::Listen(std::string ip, int port) {
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s != kInvalidSocket) {
+#if defined(OS_POSIX)
+ // Allow rapid reuse.
+ static const int kOn = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
+#endif
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
diff --git a/net/net.gyp b/net/net.gyp
index c242f27..bda8cb4 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -1292,7 +1292,7 @@
],
},
{
- 'target_name': 'http_listen_socket',
+ 'target_name': 'http_server',
'type': '<(library)',
'dependencies': [
'net',
@@ -1301,8 +1301,8 @@
],
'msvs_guid': 'FCB894A4-CC6C-48C2-B495-52C80527E9BE',
'sources': [
- 'server/http_listen_socket.cc',
- 'server/http_listen_socket.h',
+ 'server/http_server.cc',
+ 'server/http_server.h',
'server/http_server_request_info.cc',
'server/http_server_request_info.h',
],
diff --git a/net/server/http_listen_socket.h b/net/server/http_listen_socket.h
deleted file mode 100644
index 8b0bbc2..0000000
--- a/net/server/http_listen_socket.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef NET_SERVER_HTTP_LISTEN_SOCKET_H_
-#define NET_SERVER_HTTP_LISTEN_SOCKET_H_
-#pragma once
-
-#include "net/base/listen_socket.h"
-
-class HttpServerRequestInfo;
-
-// Implements a simple HTTP listen socket on top of the raw socket interface.
-class HttpListenSocket : public ListenSocket,
- public ListenSocket::ListenSocketDelegate {
- public:
- class Delegate {
- public:
- virtual void OnHttpRequest(HttpListenSocket* socket,
- const HttpServerRequestInfo& info) = 0;
-
- virtual void OnWebSocketRequest(HttpListenSocket* socket,
- const HttpServerRequestInfo& info) = 0;
-
- virtual void OnWebSocketMessage(HttpListenSocket* socket,
- const std::string& data) = 0;
-
- virtual void OnClose(HttpListenSocket* socket) = 0;
- protected:
- virtual ~Delegate() {}
- };
-
- virtual void Accept();
-
- static HttpListenSocket* Listen(const std::string& ip,
- int port,
- HttpListenSocket::Delegate* delegate);
-
- void AcceptWebSocket(const HttpServerRequestInfo& request);
-
- void SendOverWebSocket(const std::string& data);
-
- void Send200(const std::string& data, const std::string& mime_type);
- void Send404();
- void Send500(const std::string& message);
-
- virtual void Close();
- virtual void Listen();
-
- // ListenSocketDelegate
- virtual void DidAccept(ListenSocket* server, ListenSocket* connection);
- virtual void DidRead(ListenSocket* connection, const char* data, int len);
- virtual void DidClose(ListenSocket* sock);
-
- private:
- static const int kReadBufSize = 16 * 1024;
- HttpListenSocket(SOCKET s, HttpListenSocket::Delegate* del);
- virtual ~HttpListenSocket();
-
- // Expects the raw data to be stored in recv_data_. If parsing is successful,
- // will remove the data parsed from recv_data_, leaving only the unused
- // recv data.
- bool ParseHeaders(HttpServerRequestInfo* info);
-
- HttpListenSocket::Delegate* delegate_;
- bool is_web_socket_;
- std::string recv_data_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpListenSocket);
-};
-
-#endif // NET_SERVER_HTTP_LISTEN_SOCKET_H_
diff --git a/net/server/http_listen_socket.cc b/net/server/http_server.cc
index a946bd9..87b50fa 100644
--- a/net/server/http_listen_socket.cc
+++ b/net/server/http_server.cc
@@ -2,64 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <map>
+
#ifdef _WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
-#include <map>
-
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/md5.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
-#include "net/server/http_listen_socket.h"
+#include "net/server/http_server.h"
#include "net/server/http_server_request_info.h"
-// must run in the IO thread
-HttpListenSocket::HttpListenSocket(SOCKET s,
- HttpListenSocket::Delegate* delegate)
- : ALLOW_THIS_IN_INITIALIZER_LIST(ListenSocket(s, this)),
- delegate_(delegate),
- is_web_socket_(false) {
+int HttpServer::Connection::lastId_ = 0;
+HttpServer::HttpServer(const std::string& host,
+ int port,
+ HttpServer::Delegate* del)
+ : delegate_(del) {
+ server_ = ListenSocket::Listen(host, port, this);
}
-// must run in the IO thread
-HttpListenSocket::~HttpListenSocket() {
-}
+HttpServer::~HttpServer() {
+ IdToConnectionMap copy = id_to_connection_;
+ for (IdToConnectionMap::iterator it = copy.begin(); it != copy.end(); ++it)
+ delete it->second;
-void HttpListenSocket::Accept() {
- SOCKET conn = ListenSocket::Accept(socket_);
- DCHECK_NE(conn, ListenSocket::kInvalidSocket);
- if (conn == ListenSocket::kInvalidSocket) {
- // TODO
- } else {
- scoped_refptr<HttpListenSocket> sock(
- new HttpListenSocket(conn, delegate_));
-#if defined(OS_POSIX)
- sock->WatchSocket(WAITING_READ);
-#endif
- // it's up to the delegate to AddRef if it wants to keep it around
- DidAccept(this, sock);
- }
-}
-
-HttpListenSocket* HttpListenSocket::Listen(
- const std::string& ip,
- int port,
- HttpListenSocket::Delegate* delegate) {
- SOCKET s = ListenSocket::Listen(ip, port);
- if (s == ListenSocket::kInvalidSocket) {
- // TODO (ibrar): error handling
- } else {
- HttpListenSocket *serv = new HttpListenSocket(s, delegate);
- serv->Listen();
- return serv;
- }
- return NULL;
+ server_ = NULL;
}
std::string GetHeaderValue(
@@ -91,7 +64,13 @@ uint32 WebSocketKeyFingerprint(const std::string& str) {
return htonl(static_cast<uint32>(number / spaces));
}
-void HttpListenSocket::AcceptWebSocket(const HttpServerRequestInfo& request) {
+void HttpServer::AcceptWebSocket(
+ int connection_id,
+ const HttpServerRequestInfo& request) {
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1");
std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2");
@@ -109,52 +88,113 @@ void HttpListenSocket::AcceptWebSocket(const HttpServerRequestInfo& request) {
std::string origin = GetHeaderValue(request, "Origin");
std::string host = GetHeaderValue(request, "Host");
std::string location = "ws://" + host + request.path;
- is_web_socket_ = true;
- Send(base::StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: %s\r\n"
- "Sec-WebSocket-Location: %s\r\n"
- "\r\n",
- origin.c_str(),
- location.c_str()));
- Send(reinterpret_cast<char*>(digest.a), 16);
+ connection->is_web_socket_ = true;
+ connection->socket_->Send(base::StringPrintf(
+ "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Origin: %s\r\n"
+ "Sec-WebSocket-Location: %s\r\n"
+ "\r\n",
+ origin.c_str(),
+ location.c_str()));
+ connection->socket_->Send(reinterpret_cast<char*>(digest.a), 16);
}
-void HttpListenSocket::SendOverWebSocket(const std::string& data) {
- DCHECK(is_web_socket_);
+void HttpServer::SendOverWebSocket(int connection_id,
+ const std::string& data) {
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
+ DCHECK(connection->is_web_socket_);
char message_start = 0;
char message_end = -1;
- Send(&message_start, 1);
- Send(data);
- Send(&message_end, 1);
+ connection->socket_->Send(&message_start, 1);
+ connection->socket_->Send(data);
+ connection->socket_->Send(&message_end, 1);
+}
+
+void HttpServer::Send(int connection_id, const std::string& data) {
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
+ connection->socket_->Send(data);
+}
+
+void HttpServer::Send(int connection_id, const char* bytes, int len) {
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
+ connection->socket_->Send(bytes, len);
}
-void HttpListenSocket::Send200(const std::string& data,
- const std::string& content_type) {
- Send(base::StringPrintf("HTTP/1.1 200 OK\r\n"
- "Content-Type:%s\r\n"
- "Content-Length:%d\r\n"
- "\r\n",
- content_type.c_str(),
- static_cast<int>(data.length())));
- Send(data);
+void HttpServer::Send200(int connection_id,
+ const std::string& data,
+ const std::string& content_type) {
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
+ connection->socket_->Send(base::StringPrintf(
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Type:%s\r\n"
+ "Content-Length:%d\r\n"
+ "\r\n",
+ content_type.c_str(),
+ static_cast<int>(data.length())));
+ connection->socket_->Send(data);
}
-void HttpListenSocket::Send404() {
- Send("HTTP/1.1 404 Not Found\r\n"
- "Content-Length: 0\r\n"
- "\r\n");
+void HttpServer::Send404(int connection_id) {
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
+ connection->socket_->Send(
+ "HTTP/1.1 404 Not Found\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n");
+}
+
+void HttpServer::Send500(int connection_id, const std::string& message) {
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
+ connection->socket_->Send(base::StringPrintf(
+ "HTTP/1.1 500 Internal Error\r\n"
+ "Content-Type:text/html\r\n"
+ "Content-Length:%d\r\n"
+ "\r\n"
+ "%s",
+ static_cast<int>(message.length()),
+ message.c_str()));
+}
+
+void HttpServer::Close(int connection_id)
+{
+ Connection* connection = FindConnection(connection_id);
+ if (connection == NULL)
+ return;
+
+ connection->DetachSocket();
}
-void HttpListenSocket::Send500(const std::string& message) {
- Send(base::StringPrintf("HTTP/1.1 500 Internal Error\r\n"
- "Content-Type:text/html\r\n"
- "Content-Length:%d\r\n"
- "\r\n"
- "%s",
- static_cast<int>(message.length()),
- message.c_str()));
+HttpServer::Connection::Connection(ListenSocket* sock)
+ : socket_(sock),
+ is_web_socket_(false) {
+ id_ = lastId_++;
+}
+
+HttpServer::Connection::~Connection() {
+ DetachSocket();
+}
+
+void HttpServer::Connection::DetachSocket() {
+ socket_ = NULL;
}
//
@@ -231,15 +271,16 @@ int charToInput(char ch) {
return INPUT_DEFAULT;
}
-bool HttpListenSocket::ParseHeaders(HttpServerRequestInfo* info) {
+bool HttpServer::ParseHeaders(Connection* connection,
+ HttpServerRequestInfo* info) {
int pos = 0;
- int data_len = recv_data_.length();
- int state = is_web_socket_ ? ST_WS_READY : ST_METHOD;
+ int data_len = connection->recv_data_.length();
+ int state = connection->is_web_socket_ ? ST_WS_READY : ST_METHOD;
std::string buffer;
std::string header_name;
std::string header_value;
while (pos < data_len) {
- char ch = recv_data_[pos++];
+ char ch = connection->recv_data_[pos++];
int input = charToInput(ch);
int next_state = parser_state[state][input];
@@ -275,7 +316,7 @@ bool HttpListenSocket::ParseHeaders(HttpServerRequestInfo* info) {
buffer.append(&ch, 1);
break;
case ST_WS_FRAME:
- recv_data_ = recv_data_.substr(pos);
+ connection->recv_data_ = connection->recv_data_.substr(pos);
info->data = buffer;
buffer.clear();
return true;
@@ -294,12 +335,12 @@ bool HttpListenSocket::ParseHeaders(HttpServerRequestInfo* info) {
buffer.append(&ch, 1);
break;
case ST_DONE:
- recv_data_ = recv_data_.substr(pos);
- info->data = recv_data_;
- recv_data_.clear();
+ connection->recv_data_ = connection->recv_data_.substr(pos);
+ info->data = connection->recv_data_;
+ connection->recv_data_.clear();
return true;
case ST_WS_CLOSE:
- is_web_socket_ = false;
+ connection->is_web_socket_ = false;
return false;
case ST_ERR:
return false;
@@ -310,48 +351,66 @@ bool HttpListenSocket::ParseHeaders(HttpServerRequestInfo* info) {
return false;
}
-void HttpListenSocket::Close() {
- ListenSocket::Close();
+void HttpServer::DidAccept(ListenSocket* server,
+ ListenSocket* socket) {
+ Connection* connection = new Connection(socket);
+ id_to_connection_[connection->id_] = connection;
+ socket_to_connection_[socket] = connection;
}
-void HttpListenSocket::Listen() {
- ListenSocket::Listen();
-}
+void HttpServer::DidRead(ListenSocket* socket,
+ const char* data,
+ int len) {
+ Connection* connection = FindConnection(socket);
+ DCHECK(connection != NULL);
+ if (connection == NULL)
+ return;
-void HttpListenSocket::DidAccept(ListenSocket* server,
- ListenSocket* connection) {
- connection->AddRef();
-}
-
-void HttpListenSocket::DidRead(ListenSocket*,
- const char* data,
- int len) {
- recv_data_.append(data, len);
- while (recv_data_.length()) {
+ connection->recv_data_.append(data, len);
+ while (connection->recv_data_.length()) {
HttpServerRequestInfo request;
- if (!ParseHeaders(&request))
+ if (!ParseHeaders(connection, &request))
break;
- if (is_web_socket_) {
- delegate_->OnWebSocketMessage(this, request.data);
+ if (connection->is_web_socket_) {
+ delegate_->OnWebSocketMessage(connection->id_, request.data);
continue;
}
- std::string connection = GetHeaderValue(request, "Connection");
- if (connection == "Upgrade") {
+ std::string connection_header = GetHeaderValue(request, "Connection");
+ if (connection_header == "Upgrade") {
// Is this WebSocket and if yes, upgrade the connection.
std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1");
std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2");
if (!key1.empty() && !key2.empty()) {
- delegate_->OnWebSocketRequest(this, request);
+ delegate_->OnWebSocketRequest(connection->id_, request);
continue;
}
}
- delegate_->OnHttpRequest(this, request);
+ delegate_->OnHttpRequest(connection->id_, request);
}
+
+}
+
+void HttpServer::DidClose(ListenSocket* socket) {
+ Connection* connection = FindConnection(socket);
+ DCHECK(connection != NULL);
+ delegate_->OnClose(connection->id_);
+ id_to_connection_.erase(connection->id_);
+ socket_to_connection_.erase(connection->socket_);
+ delete connection;
+}
+
+HttpServer::Connection* HttpServer::FindConnection(int connection_id) {
+ IdToConnectionMap::iterator it = id_to_connection_.find(connection_id);
+ if (it == id_to_connection_.end())
+ return NULL;
+ return it->second;
}
-void HttpListenSocket::DidClose(ListenSocket* sock) {
- delegate_->OnClose(this);
- sock->Release();
+HttpServer::Connection* HttpServer::FindConnection(ListenSocket* socket) {
+ SocketToConnectionMap::iterator it = socket_to_connection_.find(socket);
+ if (it == socket_to_connection_.end())
+ return NULL;
+ return it->second;
}
diff --git a/net/server/http_server.h b/net/server/http_server.h
new file mode 100644
index 0000000..fc87cdb
--- /dev/null
+++ b/net/server/http_server.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2010 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.
+
+#ifndef NET_SERVER_HTTP_SERVER_H_
+#define NET_SERVER_HTTP_SERVER_H_
+#pragma once
+
+#include <list>
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "net/base/listen_socket.h"
+
+class HttpServerRequestInfo;
+
+class HttpServer : public ListenSocket::ListenSocketDelegate,
+ public base::RefCountedThreadSafe<HttpServer> {
+ public:
+ class Delegate {
+ public:
+ virtual void OnHttpRequest(int connection_id,
+ const HttpServerRequestInfo& info) = 0;
+
+ virtual void OnWebSocketRequest(int connection_id,
+ const HttpServerRequestInfo& info) = 0;
+
+ virtual void OnWebSocketMessage(int connection_id,
+ const std::string& data) = 0;
+
+ virtual void OnClose(int connection_id) = 0;
+ protected:
+ virtual ~Delegate() {}
+ };
+
+ HttpServer(const std::string& host, int port, HttpServer::Delegate* del);
+ virtual ~HttpServer();
+
+ void AcceptWebSocket(int connection_id,
+ const HttpServerRequestInfo& request);
+ void SendOverWebSocket(int connection_id, const std::string& data);
+ void Send(int connection_id, const std::string& data);
+ void Send(int connection_id, const char* bytes, int len);
+ void Send200(int connection_id,
+ const std::string& data,
+ const std::string& mime_type);
+ void Send404(int connection_id);
+ void Send500(int connection_id, const std::string& message);
+ void Close(int connection_id);
+
+private:
+ friend class base::RefCountedThreadSafe<HttpServer>;
+ class Connection {
+ private:
+ static int lastId_;
+ friend class HttpServer;
+
+ explicit Connection(ListenSocket* sock);
+ ~Connection();
+
+ void DetachSocket();
+
+ scoped_refptr<ListenSocket> socket_;
+ bool is_web_socket_;
+ std::string recv_data_;
+ int id_;
+
+ DISALLOW_COPY_AND_ASSIGN(Connection);
+ };
+
+
+ // ListenSocketDelegate
+ virtual void DidAccept(ListenSocket* server, ListenSocket* socket);
+ virtual void DidRead(ListenSocket* socket, const char* data, int len);
+ virtual void DidClose(ListenSocket* socket);
+
+ // Expects the raw data to be stored in recv_data_. If parsing is successful,
+ // will remove the data parsed from recv_data_, leaving only the unused
+ // recv data.
+ bool ParseHeaders(Connection* connection, HttpServerRequestInfo* info);
+
+ Connection* FindConnection(int connection_id);
+ Connection* FindConnection(ListenSocket* socket);
+
+ HttpServer::Delegate* delegate_;
+ scoped_refptr<ListenSocket> server_;
+ typedef std::map<int, Connection*> IdToConnectionMap;
+ IdToConnectionMap id_to_connection_;
+ typedef std::map<ListenSocket*, Connection*> SocketToConnectionMap;
+ SocketToConnectionMap socket_to_connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(HttpServer);
+};
+
+#endif // NET_SERVER_HTTP_SERVER_H_