diff options
author | Pixel <pixel@nobis-crew.org> | 2011-11-14 22:44:55 -0800 |
---|---|---|
committer | Pixel <pixel@nobis-crew.org> | 2011-11-14 22:44:55 -0800 |
commit | cd8e8948ed17f1985898f8c1d59d32680262457e (patch) | |
tree | afeed4987fd194081b180d3aa68d38f5dedb7f54 /src | |
parent | d2c436e49ae0e870015b106713a711d9356c39cb (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')
-rw-r--r-- | src/HttpServer.cc | 95 |
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() { |