From e72624ab203439ffea88cd55c145cdbbc57286e4 Mon Sep 17 00:00:00 2001 From: Pixel Date: Tue, 15 Nov 2011 17:00:03 -0800 Subject: Adding a potential event to cancel a forced read/write, such as a timeout. --- src/Handle.cc | 8 +++-- src/HttpServer.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/Handle.cc b/src/Handle.cc index 8fa0417..839c58a 100644 --- a/src/Handle.cc +++ b/src/Handle.cc @@ -83,7 +83,7 @@ ssize_t Balau::Handle::write(const void * buf, size_t count) throw (GeneralExcep return -1; } -ssize_t Balau::Handle::forceRead(void * _buf, size_t count) throw (GeneralException) { +ssize_t Balau::Handle::forceRead(void * _buf, size_t count, Events::BaseEvent * evt) throw (GeneralException) { ssize_t total; uint8_t * buf = (uint8_t *) _buf; if (!canRead()) @@ -95,6 +95,8 @@ ssize_t Balau::Handle::forceRead(void * _buf, size_t count) throw (GeneralExcept r = read(buf, count); } catch (EAgain e) { + if (evt && evt->gotSignal()) + return total; Task::yield(e.getEvent()); continue; } @@ -108,7 +110,7 @@ ssize_t Balau::Handle::forceRead(void * _buf, size_t count) throw (GeneralExcept return total; } -ssize_t Balau::Handle::forceWrite(const void * _buf, size_t count) throw (GeneralException) { +ssize_t Balau::Handle::forceWrite(const void * _buf, size_t count, Events::BaseEvent * evt) throw (GeneralException) { ssize_t total; const uint8_t * buf = (const uint8_t *) _buf; if (!canWrite()) @@ -120,6 +122,8 @@ ssize_t Balau::Handle::forceWrite(const void * _buf, size_t count) throw (Genera r = write(buf, count); } catch (EAgain e) { + if (evt && evt->gotSignal()) + return total; Task::yield(e.getEvent()); continue; } diff --git a/src/HttpServer.cc b/src/HttpServer.cc index f3b95a7..530dcf5 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -5,13 +5,14 @@ #include "Socket.h" #include "BStream.h" -static const ev_tstamp s_httpTimeout = 5; +static const ev_tstamp s_httpTimeout = 15; namespace Balau { class HttpWorker : public Task { public: HttpWorker(IO & io, void * server); + ~HttpWorker(); private: virtual void Do(); virtual const char * getName(); @@ -22,33 +23,45 @@ class HttpWorker : public Task { IO m_socket; IO m_strm; String m_name; + + uint8_t * m_postData; }; }; -Balau::HttpWorker::HttpWorker(IO & io, void * _server) : m_socket(io), m_strm(new BStream(io)) { +Balau::HttpWorker::HttpWorker(IO & io, void * _server) : m_socket(io), m_strm(new BStream(io)), m_postData(NULL) { HttpServer * server = (HttpServer *) _server; m_name.set("HttpWorker(%s)", m_socket->getName()); + // copy stuff from server, such as port number, root document, base URL, etc... +} + +Balau::HttpWorker::~HttpWorker() { + if (m_postData) { + free(m_postData); + m_postData = NULL; + } } 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" +"Connection: close\r\n" "\r\n" -"\r\n" -"\r\n" -" \r\n" -" Bad Request\r\n" -" \r\n" -"\r\n" -" \r\n" -" The HTTP request you've sent is invalid.\r\n" -" \r\n" -"\r\n"; - - m_socket->write(str, sizeof(str)); +"\n" +"\n" +" \n" +" Bad Request\n" +" \n" +"\n" +" \n" +" The HTTP request you've sent is invalid.\n" +" \n" +"\n"; + + setOkayToEAgain(false); + m_socket->writeString(str, sizeof(str)); Balau::Printer::elog(Balau::E_HTTPSERVER, "%s had an invalid request", m_name.to_charp()); } @@ -62,7 +75,13 @@ bool Balau::HttpWorker::handleClient() { int method = -1; String url; String HttpVersion; - std::map HttpHeaders; + typedef std::map HttpHeaders_t; + HttpHeaders_t HttpHeaders; + if (m_postData) { + free(m_postData); + m_postData = NULL; + } + bool persistent = false; // read client's request do { @@ -158,7 +177,45 @@ bool Balau::HttpWorker::handleClient() { return false; } - return true; + if (method == Http::POST) { + int lengthStr = 0; + HttpHeaders_t::iterator i = HttpHeaders.find("Content-Length"); + + if (i != HttpHeaders.end()) + lengthStr = i->second.to_int(); + + m_postData = (uint8_t *) malloc(lengthStr); + + try { + m_strm->forceRead(m_postData, lengthStr); + } + catch (EAgain) { + Assert(evtTimeout.gotSignal()); + Balau::Printer::elog(Balau::E_HTTPSERVER, "%s timed out getting request (reading POST values)", m_name.to_charp()); + return false; + } + } + + if (HttpVersion == "1.1") { + HttpHeaders_t::iterator i = HttpHeaders.find("Connection"); + + if (i != HttpHeaders.end()) { + if (i->second != "close") { + send400(); + return false; + } + } else { + persistent = true; + } + } + + // process query; everything should be here now + + + + // query process finished; wrapping up and exiting. + + return persistent; } void Balau::HttpWorker::Do() { -- cgit v1.2.3