summaryrefslogtreecommitdiffstats
path: root/net/server
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 /net/server
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
Diffstat (limited to 'net/server')
-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
3 files changed, 267 insertions, 184 deletions
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_