diff options
Diffstat (limited to 'lib/HttpServ.cc')
-rw-r--r-- | lib/HttpServ.cc | 221 |
1 files changed, 129 insertions, 92 deletions
diff --git a/lib/HttpServ.cc b/lib/HttpServ.cc index 7464e5b..fe48f54 100644 --- a/lib/HttpServ.cc +++ b/lib/HttpServ.cc @@ -3,6 +3,7 @@ #include "HttpServ.h" #include "Buffer.h" #include "ReadJob.h" +#include "CopyJob.h" #include "Task.h" #include "config.h" @@ -10,7 +11,7 @@ String endhl = "\r\n", endnl = "\n"; class ProcessRequest : public Task { public: - ProcessRequest(Action *, const Socket &); + ProcessRequest(Action *, const Socket &, const String &, int); virtual ~ProcessRequest() {} virtual String GetName(); protected: @@ -25,121 +26,152 @@ class ProcessRequest : public Task { String file, domain, t; Buffer b; - Task * c; + Task * c, * a; Action * f; - int len; + int len, localport; Action * p; Socket s; String name; Variables * Vars; - bool bad; - + bool bad, hasvars, post; }; -ProcessRequest::ProcessRequest(Action * ap, const Socket & as) : p(ap), s(as) { } +ProcessRequest::ProcessRequest(Action * ap, const Socket & as, const String & aname, int aport) : localport(aport), p(ap), s(as), name(aname) { } String ProcessRequest::GetName() { return "Processing HTTP request"; } int ProcessRequest::Do() { - c = new ReadJob(&s, &b); - -} + switch (current) { + case 0: + c = new ReadJob(&s, &b); + WaitFor(c); + current = 1; + Suspend(); -void ProcessRequest::ProcessRequest(Action * p, Socket s) { - c = new ReadJob(&s, &b); + case 1: + delete c; - s.SetNonBlock(); + bad = false; - c->Run(); - delete c; - - bad = false; + if (!s.IsConnected()) return TASK_DONE; - if (!s.IsConnected()) return; + cerr << "Got a request\n----\n"; - cerr << "Got a request\n----\n"; - - bool post = ParseUri(file, domain, &b); - - len = -1; - do { - b >> t; - cerr << t << endl; - if ((t.strstr("Content-Length: ") == 0) || (t.strstr("Content-length: ") == 0)) { - cerr << "Saw 'Content-Lenght:', reading length from '" << t.extract(16) << "'\n"; - 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. - if (len == -1) { - bad = true; - Vars = new Variables(0); + post = ParseUri(file, domain, &b); + + len = -1; + do { + b >> t; + cerr << t << endl; + if ((t.strstr("Content-Length: ") == 0) || (t.strstr("Content-length: ") == 0)) { + cerr << "Saw 'Content-Lenght:', reading length from '" << t.extract(16) << "'\n"; + len = t.extract(16).to_int(); + } + } while (t.strlen()); + + hasvars = false; + + if (post) { + // On a pas eu de ligne 'Content-Length' mais on a eu une méthode POST. + // Cela est une erreur. + if (len == -1) { + bad = true; + Vars = new Variables(); + } else { + cerr << "Got a POST request. Parsing variables. (len = " << len << ")\n"; + // Les variables seront initialisées ici. + hasvars = true; + } } else { - cerr << "Got a POST request. Parsing variables. (len = " << len << ")\n"; - // Les variables seront initialisées ici. - ParseVars(&s, len); + Vars = new Variables(); } - } else { - Vars = new Variables(0); - } + + c = new CopyJob(&s, &b, len); + WaitFor(c); + current = 2; + Suspend(); + + case 2: + delete c; + ParseVars(&s, len); - cerr << " Domain = '" << domain << "' - File = '" << file << "'\n"; + cerr << " Domain = '" << domain << "' - File = '" << file << "'\n"; - if (!bad) { - // Nous vérifions le domaine. - if (domain != "") { - bad = true; - // Les domaines valides sont '/', '/bin' et '/image'. - if (domain == "/image") bad = false; - if (domain == "/bin") bad = false; - if (domain == "/") bad = false; - } else { - // L'url sans domaine ni fichier est valide. (cela arrive sur certains navigateurs...) - bad = (file != ""); - } - } - - if (bad) { - ShowError(&s); - } else { - if (((domain == "") || (domain == "/")) && (file == "")) { - // Si le navigateur a demandé l'URL '/', alors on renvoie une notification - // de redirection. - 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"); - f->Do(Vars, &s); + if (!bad) { + // Nous vérifions le domaine. + if (domain != "") { + bad = true; + // Les domaines valides sont '/', '/bin' et '/image'. + if (domain == "/image") bad = false; + if (domain == "/bin") bad = false; + if (domain == "/") bad = false; } else { - ShowError(&s); + // L'url sans domaine ni fichier est valide. (cela arrive sur certains navigateurs...) + bad = (file != ""); } + } + + a = 0; + + if (bad) { + ShowError(&b); } else { - // Dans tous les autres cas de domaine, on cherche le fichier dans le répertoire datas. - // On utilise try au cas où le fichier n'existe pas et donc que le constructeur - // d'input renvoie une erreur. - try { - Input i(String("datas/") + file); - SendHeads(&s, GetMime(file)); - s.ReadFile(i); - cerr << "File found, dumped.\n"; - } - catch (IOGeneral e) { - ShowError(&s); - cerr << "File not found, error showed.\n"; + if (((domain == "") || (domain == "/")) && (file == "")) { + // Si le navigateur a demandé l'URL '/', alors on renvoie une notification + // de redirection. + SendRedirect(&b); + } 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"); + a = f->Do(Vars, &s); + } else { + ShowError(&b); + } + } else { + // Dans tous les autres cas de domaine, on cherche le fichier dans le répertoire datas. + // On utilise try au cas où le fichier n'existe pas et donc que le constructeur + // d'input renvoie une erreur. + try { + Handle * i = new Input(String("datas/") + file); + SendHeads(&b, GetMime(file)); + a = new CopyJob(i, &s, -1, true); + cerr << "File found, dumping.\n"; + } + catch (IOGeneral e) { + ShowError(&b); + cerr << "File not found, error showed.\n"; + } } } - } - delete Vars; + if (a) a->Stop(); + + delete Vars; + c = new CopyJob(&b, &s); + WaitFor(c); + current = 3; + Suspend(); + + case 3: + delete c; + + if (a) { + a->Restart(); + WaitFor(a); + current = 4; + Suspend(); + } + + case 4: + if (a) delete a; - cerr << "----\n"; + cerr << "----\n"; + } + return TASK_DONE; } void ProcessRequest::ParseVars(Handle * s, int len) { @@ -205,7 +237,7 @@ void ProcessRequest::ParseVars(Handle * s, int len) { bool ProcessRequest::ParseUri(String & file, String & domain, Handle * s) { String t, Uri; bool post = false; - const char * p = NULL; + const char * p = 0; ssize_t sppos; *s >> t; @@ -326,7 +358,7 @@ String ProcessRequest::GetMime(const String & f) { return "text/plain"; } -HttpServ::HttpServ(int port, const String & nname) throw (GeneralException) : name(nname), localport(port) { +HttpServ::HttpServ(Action * ap, int port, const String & nname) throw (GeneralException) : p(ap), name(nname), localport(port) { bool r = true; r = Listener.SetLocal("", port); @@ -338,18 +370,23 @@ HttpServ::HttpServ(int port, const String & nname) throw (GeneralException) : na throw GeneralException("Initialisation of the Mini HTTP-Server failed."); } - r.SetNonBlock(); + Listener.SetNonBlock(); + WaitFor(&Listener); cerr << "Mini HTTP-Server '" << name << "' ready and listening for port " << port << endl; } -int HttpServ::Do(Action * p) { +int HttpServ::Do() { try { Socket s = Listener.Accept(); - new ProcessRequest(p, Listener.Accept()); + s.SetNonBlock(); + new ProcessRequest(p, s, name, localport); } catch (GeneralException) { - return TASK_ON_HOLD; } + return TASK_ON_HOLD; } +String HttpServ::GetName() { + return String("Mini HTTP-Server '") + name + "'"; +} |