summaryrefslogtreecommitdiff
path: root/lib/HttpServ.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/HttpServ.cc')
-rw-r--r--lib/HttpServ.cc221
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 + "'";
+}