summaryrefslogtreecommitdiff
path: root/src/HttpServer.cc
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-11-14 22:44:55 -0800
committerPixel <pixel@nobis-crew.org>2011-11-14 22:44:55 -0800
commitcd8e8948ed17f1985898f8c1d59d32680262457e (patch)
treeafeed4987fd194081b180d3aa68d38f5dedb7f54 /src/HttpServer.cc
parentd2c436e49ae0e870015b106713a711d9356c39cb (diff)
Some more basic work on the HTTP server. Some of the main ideas are not fleshed up, and writing the actual server should now be sort of straightforward.
Diffstat (limited to 'src/HttpServer.cc')
-rw-r--r--src/HttpServer.cc95
1 files changed, 82 insertions, 13 deletions
diff --git a/src/HttpServer.cc b/src/HttpServer.cc
index acfc9d2..efdadda 100644
--- a/src/HttpServer.cc
+++ b/src/HttpServer.cc
@@ -1,3 +1,4 @@
+#include "Http.h"
#include "HttpServer.h"
#include "Socket.h"
#include "BStream.h"
@@ -8,53 +9,121 @@ namespace Balau {
class HttpWorker : public Task {
public:
- HttpWorker(IO<Socket> & io, void * server) : m_socket(io), m_parent((HttpServer *) server), m_evtTimeout(s_httpTimeout) { m_name.set("HttpWorker(%s)", m_socket->getName()); }
+ HttpWorker(IO<Socket> & io, void * server);
private:
virtual void Do();
virtual const char * getName();
+
+ bool handleClient();
+ void send400();
+
IO<Socket> m_socket;
+ IO<BStream> m_strm;
String m_name;
- HttpServer * m_parent;
- Events::Timeout m_evtTimeout;
};
};
-void Balau::HttpWorker::Do() {
- waitFor(&m_evtTimeout);
+Balau::HttpWorker::HttpWorker(IO<Socket> & io, void * _server) : m_socket(io), m_strm(new BStream(io)) {
+ HttpServer * server = (HttpServer *) _server;
+ m_name.set("HttpWorker(%s)", m_socket->getName());
+}
+
+void Balau::HttpWorker::send400() {
+ static const char str[] =
+"HTTP/1.0 400 Bad Request\r\n"
+"Content-Type: text/html; charset=UTF-8\r\n"
+"\r\n"
+"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\r\n"
+"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n"
+"<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n"
+" <head>\r\n"
+" <title>Bad Request</title>\r\n"
+" </head>\r\n"
+"\r\n"
+" <body>\r\n"
+" The HTTP request you've sent is invalid.\r\n"
+" </body>\r\n"
+"</html>\r\n";
+
+ m_socket->write(str, sizeof(str));
+ Balau::Printer::elog(Balau::E_HTTPSERVER, "%s had an invalid request", m_name.to_charp());
+}
+
+bool Balau::HttpWorker::handleClient() {
+ Events::Timeout evtTimeout(s_httpTimeout);
+ waitFor(&evtTimeout);
setOkayToEAgain(true);
String line;
- IO<BStream> strm(m_socket);
bool gotFirst = false;
+ int method = -1;
+ // read client's request
do {
try {
- line = strm->readString();
+ line = m_strm->readString();
}
catch (EAgain) {
- if (m_evtTimeout.gotSignal()) {
- // do some log
- return;
+ if (evtTimeout.gotSignal()) {
+ Balau::Printer::elog(Balau::E_HTTPSERVER, "%s timed out getting request", m_name.to_charp());
+ return false;
}
yield();
continue;
}
+ // until we get a blank line
if (line == "")
break;
if (!gotFirst) {
gotFirst = true;
- // parse request method, URL and HTTP version.
+ int urlBegin = 0;
+
+ // first line is in the form of METHOD URL HTTP/1.x
+ switch(line[0]) {
+ case 'G':
+ if ((line[1] == 'E') && (line[2] == 'T') && (line[3] == ' ')) {
+ urlBegin = 4;
+ method = Http::GET;
+ }
+ break;
+ case 'P':
+ if ((line[1] == 'O') && (line[2] == 'S') && (line[3] == 'T') && (line[4] == ' ')) {
+ urlBegin = 5;
+ method = Http::POST;
+ }
+ break;
+ }
+ if (urlBegin == 0) {
+ send400();
+ return false;
+ }
+
+ int urlEnd = line.strrchr(' ') - 1;
+
+ if (urlEnd < urlBegin) {
+ send400();
+ return false;
+ }
} else {
// parse HTTP header.
}
} while(true);
if (!gotFirst) {
- // do some log
- return;
+ send400();
+ return false;
}
+
+ return true;
+}
+
+void Balau::HttpWorker::Do() {
+ bool clientStop = false;
+
+ while (!clientStop)
+ clientStop = !handleClient() || m_socket.isClosed();
}
const char * Balau::HttpWorker::getName() {