diff options
-rw-r--r-- | include/CopyJob.h | 10 | ||||
-rw-r--r-- | include/Exceptions.h | 23 | ||||
-rw-r--r-- | include/HttpServ.h | 10 | ||||
-rw-r--r-- | include/ReadJob.h | 8 | ||||
-rw-r--r-- | include/Task.h | 12 | ||||
-rw-r--r-- | lib/Buffer.cc | 2 | ||||
-rw-r--r-- | lib/CopyJob.cc | 35 | ||||
-rw-r--r-- | lib/Exceptions.cc | 20 | ||||
-rw-r--r-- | lib/Handle.cc | 4 | ||||
-rw-r--r-- | lib/HttpServ.cc | 43 | ||||
-rw-r--r-- | lib/ReadJob.cc | 31 | ||||
-rw-r--r-- | lib/Task.cc | 19 |
12 files changed, 154 insertions, 63 deletions
diff --git a/include/CopyJob.h b/include/CopyJob.h index 69eb088..3c88100 100644 --- a/include/CopyJob.h +++ b/include/CopyJob.h @@ -5,13 +5,19 @@ #include <Task.h> #include <Handle.h> +#define COPY_BUFSIZ 4096 + class CopyJob : public Task { public: - CopyJob(Handle &, Handle &); + CopyJob(Handle *, Handle *, ssize_t = -1); virtual ~CopyJob(); virtual int Do(); + virtual String GetName(); private: - Handle s, d; + Handle * s, * d; + ssize_t siz, cursiz; + char buffer[COPY_BUFSIZ]; + int current; }; #else diff --git a/include/Exceptions.h b/include/Exceptions.h index 87ba6d1..f04970c 100644 --- a/include/Exceptions.h +++ b/include/Exceptions.h @@ -37,6 +37,7 @@ class MemoryException; char * xstrdup(const char *) throw (MemoryException); void * xmalloc(ssize_t) throw (MemoryException); void xfree(void *&); +void * xrealloc(void *, size_t) throw (MemoryException); // On prédéfinit la classe String, pour éviter // les deadlocks de compilation... @@ -48,7 +49,10 @@ class Base { return xstrdup(s); } void * malloc(ssize_t s) const { - return malloc(s); + return xmalloc(s); + } + void * realloc(void * p, size_t s) { + return xrealloc(p, s); } void * operator new(size_t s) { return xmalloc(s); @@ -56,6 +60,9 @@ class Base { void * operator new(size_t s, void * p) { return memset(p, 0, s); } + void operator delete(void * p) { + xfree(p); + } void free(void * p) const { xfree(p); } @@ -86,19 +93,21 @@ enum op_t { IO_READ }; -class IOException : public GeneralException { +class IOGeneral : public GeneralException { public: - IOException(String, op_t, ssize_t); + IOGeneral(String); + protected: + IOGeneral(); }; -class IOGeneral : public GeneralException { +class IOException : public IOGeneral { public: - IOGeneral(String); + IOException(String, op_t, ssize_t); }; -class IOInternal : public GeneralException { +class IOAgain : public IOGeneral { public: - IOInternal(String, op_t); + IOAgain(); }; #else diff --git a/include/HttpServ.h b/include/HttpServ.h index dc89104..6bd2769 100644 --- a/include/HttpServ.h +++ b/include/HttpServ.h @@ -24,11 +24,11 @@ class HttpServ : public Base { private: String GetMime(const String &); void ProcessRequest(Action *, Socket); - bool ParseUri(String &, String &, Handle &); - void ParseVars(Handle &, int); - void ShowError(Handle &); - void SendHeads(Handle &, const String &); - void SendRedirect(Handle &); + bool ParseUri(String &, String &, Handle *); + void ParseVars(Handle *, int); + void ShowError(Handle *); + void SendHeads(Handle *, const String &); + void SendRedirect(Handle *); String name; Socket Listener; Variables * Vars; diff --git a/include/ReadJob.h b/include/ReadJob.h index 19009a6..2d53125 100644 --- a/include/ReadJob.h +++ b/include/ReadJob.h @@ -4,14 +4,18 @@ #include <Task.h> #include <Handle.h> +#include <regex.h> class ReadJob : public Task { public: - ReadJob(Handle &, Handle &); + ReadJob(Handle *, Handle *, String = "^$", int = REG_EXTENDED); virtual ~ReadJob(); virtual int Do(); + virtual String GetName(); private: - Handle s, d; + Handle * s, * d; + int current; + regex_t * preg; }; #else diff --git a/include/Task.h b/include/Task.h index 12e3bff..c67a59c 100644 --- a/include/Task.h +++ b/include/Task.h @@ -4,19 +4,21 @@ #include "Exceptions.h" -#define TASK_ON_HOLD 0 -#define TASK_DONE 1 -#define TASK_WAITING_HANDLE 2 -#define TASK_WAITING_TIMEOUT 3 +#define TASK_ON_HOLD 1 +#define TASK_DONE 2 +#define TASK_WAITING_HANDLE 4 +#define TASK_WAITING_TIMEOUT 8 +#define TASK_WAITING_TASK 16 class Task : public Base { public: Task(); virtual ~Task(); - virtual int Do(); + virtual String GetName(); int Run(); int GetState(); protected: + virtual int Do(); private: int state; diff --git a/lib/Buffer.cc b/lib/Buffer.cc index 164c961..57b1bf8 100644 --- a/lib/Buffer.cc +++ b/lib/Buffer.cc @@ -32,7 +32,7 @@ ssize_t Buffer::read(void *buf, size_t count) { ptr += count; if (ptr >= realloc_threshold) { - int numblocks = (ptr / realloc_threshold) - (bufsiz / realloc_threshold); + int numblocks = (bufsiz / realloc_threshold) - (ptr / realloc_threshold); memmove(buffer, buffer + numblocks * realloc_threshold, numblocks * realloc_threshold); buffer = (char *) realloc(buffer, bufsiz = (numblocks * realloc_threshold)); ptr -= numblocks * realloc_threshold; diff --git a/lib/CopyJob.cc b/lib/CopyJob.cc index 7dccbc5..73864bb 100644 --- a/lib/CopyJob.cc +++ b/lib/CopyJob.cc @@ -1,15 +1,38 @@ #include "CopyJob.h" +#include "General.h" -CopyJob::CopyJob(Handle & as, Handle & ad) : s(as), d(ad) { } +CopyJob::CopyJob(Handle * as, Handle * ad, ssize_t asiz) : s(as), d(ad), siz(asiz), cursiz(0), current(0) { } CopyJob::~CopyJob() { } int CopyJob::Do() { - int r; - char buffer[4096]; + int r, tr; - while (!s.IsClosed()) { - r = s.read(buffer, 4096); - d.write(buffer, r); + cerr << "CopyJob running...\n"; + + while (!s->IsClosed() || (siz != cursiz)) { + if (!current) { + tr = siz >= 0 ? siz - cursiz : COPY_BUFSIZ; + try { + r = s->read(buffer, MIN(COPY_BUFSIZ, tr)); + } + catch (IOAgain) { + return TASK_WAITING_HANDLE; + } + current = 0; + } + try { + d->write(buffer, r); + } + catch (IOAgain) { + current = 1; + return TASK_WAITING_HANDLE; + } + cursiz += r; } } + +String CopyJob::GetName() { + return (String("CopyJob from ") + s->GetName() + " to " + d->GetName()); +} + diff --git a/lib/Exceptions.cc b/lib/Exceptions.cc index eed138a..a4fca0f 100644 --- a/lib/Exceptions.cc +++ b/lib/Exceptions.cc @@ -32,14 +32,12 @@ IOException::IOException(String fn, op_t op, ssize_t s) { msg = strdup(t); } -IOInternal::IOInternal(String fn, op_t op) { - sprintf(t, _("Internal error: has occured while %s from %s: open for %s."), op == IO_WRITE ? _("writing") : _("reading"), - fn.to_charp(), op == IO_WRITE ? _("reading") : _("writing")); - msg = strdup(t); -} - IOGeneral::IOGeneral(String fn) : GeneralException(fn) { } +IOGeneral::IOGeneral() { } + +IOAgain::IOAgain() : IOGeneral(_("No more bytes for reading or writing.")) { } + char * xstrdup(const char * s) throw (MemoryException) { char * r; @@ -62,6 +60,16 @@ void * xmalloc(ssize_t s) throw (MemoryException) { return r; } +void * xrealloc(void * ptr, size_t s) throw (MemoryException) { + void * r; + + if (!(r = ::realloc(ptr, s))) { + throw MemoryException(s); + } + + return r; +} + #ifdef OVER_FREE #undef free #endif diff --git a/lib/Handle.cc b/lib/Handle.cc index 0f1791e..8ef2408 100644 --- a/lib/Handle.cc +++ b/lib/Handle.cc @@ -40,7 +40,7 @@ ssize_t Handle::write(const void *buf, size_t count) throw (IOException) { done = false; full = true; if (nonblock) { - return 0; + throw IOAgain(); } else { sleep(1); } @@ -66,7 +66,7 @@ ssize_t Handle::read(void *buf, size_t count) throw (IOException) { if ((!errno) || (errno = EAGAIN)) { // Avant de déclarer une erreur, on vérifie si ce n'est pas un // problème lié au fait qu'il n'y a plus d'octets. - return 0; + throw IOAgain(); } else { throw IOException(GetName(), IO_READ, count); } diff --git a/lib/HttpServ.cc b/lib/HttpServ.cc index 69dff1e..9ec6ba3 100644 --- a/lib/HttpServ.cc +++ b/lib/HttpServ.cc @@ -22,11 +22,12 @@ void HttpServ::MainLoop(Action * p) { void HttpServ::ProcessRequest(Action * p, Socket s) { String file, domain, t; Buffer b; - ReadJob c(s, b); + Task * c = new ReadJob(&s, &b); Action * f; int len; - c.Do(); + c->Run(); + delete c; bad = false; @@ -34,7 +35,7 @@ void HttpServ::ProcessRequest(Action * p, Socket s) { cerr << "Got a request\n----\n"; - bool post = ParseUri(file, domain, b); + bool post = ParseUri(file, domain, &b); len = -1; do { @@ -45,7 +46,7 @@ void HttpServ::ProcessRequest(Action * p, Socket s) { len = t.extract(16).to_int(); } } while (t.strlen()); - + if (post) { // On a pas eu de ligne 'Content-Length' mais on a eu une méthode POST. // Cela est une erreur. @@ -55,7 +56,7 @@ void HttpServ::ProcessRequest(Action * p, Socket s) { } else { cerr << "Got a POST request. Parsing variables. (len = " << len << ")\n"; // Les variables seront initialisées ici. - ParseVars(s, len); + ParseVars(&s, len); } } else { Vars = new Variables(0); @@ -78,19 +79,19 @@ void HttpServ::ProcessRequest(Action * p, Socket s) { } if (bad) { - ShowError(s); + ShowError(&s); } else { if (((domain == "") || (domain == "/")) && (file == "")) { // Si le navigateur a demandé l'URL '/', alors on renvoie une notification // de redirection. - SendRedirect(s); + SendRedirect(&s); } else if (domain == "/bin") { // Le domaine 'bin' est réservé aux actions. On cherche donc l'action à effectuer. if ((f = p->Look4URL(file))) { - SendHeads(s, "text/html"); + SendHeads(&s, "text/html"); f->Do(Vars, &s); } else { - ShowError(s); + ShowError(&s); } } else { // Dans tous les autres cas de domaine, on cherche le fichier dans le répertoire datas. @@ -98,12 +99,12 @@ void HttpServ::ProcessRequest(Action * p, Socket s) { // d'input renvoie une erreur. try { Input i(String("datas/") + file); - SendHeads(s, GetMime(file)); + SendHeads(&s, GetMime(file)); s.ReadFile(i); cerr << "File found, dumped.\n"; } catch (IOGeneral e) { - ShowError(s); + ShowError(&s); cerr << "File not found, error showed.\n"; } } @@ -114,7 +115,7 @@ void HttpServ::ProcessRequest(Action * p, Socket s) { cerr << "----\n"; } -void HttpServ::ParseVars(Handle & s, int len) { +void HttpServ::ParseVars(Handle * s, int len) { String t, v; char conv[3], l; int hconv, nbvars; @@ -122,7 +123,7 @@ void HttpServ::ParseVars(Handle & s, int len) { t = ""; for (int i = 0; i < len; i++) { - s.read(&l, 1); + s->read(&l, 1); t += l; } cerr << "Post variables line: '" <<t << "'\n"; @@ -174,13 +175,13 @@ void HttpServ::ParseVars(Handle & s, int len) { * c'est à dire la méthode demandée par le client. */ -bool HttpServ::ParseUri(String & file, String & domain, Handle & s) { +bool HttpServ::ParseUri(String & file, String & domain, Handle * s) { String t, Uri; bool post = false; char * p = NULL; ssize_t sppos; - s >> t; + *s >> t; cerr << t << endl; bad = false; @@ -233,8 +234,8 @@ bool HttpServ::ParseUri(String & file, String & domain, Handle & s) { /* * Ceci sert à rediriger le navigateur vers l'url de démarrage. */ -void HttpServ::SendRedirect(Handle & s) { - s << "HTTP/1.1 301 Moved Permanently" << endhl << +void HttpServ::SendRedirect(Handle * s) { + *s << "HTTP/1.1 301 Moved Permanently" << endhl << "Server: " << name << endhl << "Location: http://127.0.0.1:" << localport << "/bin/start" << endhl << "Cache-Control: no-cache" << endhl << @@ -250,8 +251,8 @@ void HttpServ::SendRedirect(Handle & s) { * Nous envoyons les entetes de réponse HTTP. */ -void HttpServ::SendHeads(Handle & s, const String & mime) { - s << "HTTP/1.1 200 OK" << endhl << +void HttpServ::SendHeads(Handle * s, const String & mime) { + *s << "HTTP/1.1 200 OK" << endhl << "Server: " << name << endhl << "Cache-Control: no-cache" << endhl << "Connection-Type: closed" << endhl << @@ -262,8 +263,8 @@ void HttpServ::SendHeads(Handle & s, const String & mime) { * Affichage d'une erreur 404. */ -void HttpServ::ShowError(Handle & s) { - s << "HTTP/1.1 404 Not Found" << endhl << +void HttpServ::ShowError(Handle * s) { + *s << "HTTP/1.1 404 Not Found" << endhl << "Server: " << name << endhl << "Cache-Control: no-cache" << endhl << "Connection-Type: closed" << endhl << diff --git a/lib/ReadJob.cc b/lib/ReadJob.cc index bd63377..d5b3212 100644 --- a/lib/ReadJob.cc +++ b/lib/ReadJob.cc @@ -1,6 +1,7 @@ #include "ReadJob.h" +#include "HttpServ.h" -ReadJob::ReadJob(Handle & as, Handle & ad) : s(as), d(ad) { } +ReadJob::ReadJob(Handle * as, Handle * ad, String regex, int flags) : s(as), d(ad), current(0) { } ReadJob::~ReadJob() { } @@ -8,9 +9,31 @@ int ReadJob::Do() { int r; String buff; - while (!s.IsClosed()) { - s >> buff; - d << buff; + cerr << "ReadJob running...\n"; + + while (!s->IsClosed()) { + if (!current) { + try { + *s >> buff; + } + catch (IOAgain) { + return TASK_WAITING_HANDLE; + } + current = 0; + } + try { + *d << buff << endnl; + } + catch (IOAgain) { + current = 1; + return TASK_WAITING_HANDLE; + } if (buff == "") return TASK_DONE; } + + return TASK_DONE; +} + +String ReadJob::GetName() { + return (String("ReadJob from ") + s->GetName() + " to " + d->GetName()); } diff --git a/lib/Task.cc b/lib/Task.cc index 79c39e1..27d2a24 100644 --- a/lib/Task.cc +++ b/lib/Task.cc @@ -1,6 +1,8 @@ +#include <iostream.h> #include "Task.h" +#include "String.h" -Task::Task() {} +Task::Task() : state(TASK_ON_HOLD) {} Task::~Task() {} int Task::Do() { @@ -8,9 +10,22 @@ int Task::Do() { } int Task::Run() { - return (state = Do()); + cerr << "Running task '" << GetName() << "'...\n"; + try { + while ((state = Do()) != TASK_DONE); + } + catch (GeneralException e) { + cerr << "Task " << GetName() << " caused an unexpected exception: '" << e.GetMsg() << "', closing it.\n"; + return TASK_DONE; + } + + return state; } int Task::GetState() { return state; } + +String Task::GetName() { + return "Unknow Task"; +} |