summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/CopyJob.cc12
-rw-r--r--lib/Handle.cc6
-rw-r--r--lib/HttpServ.cc20
-rw-r--r--lib/ReadJob.cc10
-rw-r--r--lib/Task.cc6
-rw-r--r--lib/TaskMan.cc67
6 files changed, 72 insertions, 49 deletions
diff --git a/lib/CopyJob.cc b/lib/CopyJob.cc
index fd31eff..5f348db 100644
--- a/lib/CopyJob.cc
+++ b/lib/CopyJob.cc
@@ -2,8 +2,9 @@
#include "General.h"
CopyJob::CopyJob(Handle * as, Handle * ad, ssize_t asiz, bool ads) : s(as), d(ad), ds(ads), siz(asiz), cursiz(0), r(0) {
- WaitFor(s, W4_STICKY | W4_READING);
- WaitFor(d, W4_STICKY | W4_WRITING);
+ s->SetNonBlock();
+ d->SetNonBlock();
+ WaitFor(s, W4_READING);
}
CopyJob::~CopyJob() { }
@@ -18,17 +19,19 @@ int CopyJob::Do() throw (GeneralException) {
r = s->read(buffer, MIN(COPY_BUFSIZ, tr));
}
catch (IOAgain e) {
+ WaitFor(s, W4_READING);
Suspend(TASK_ON_HOLD);
}
- case 1:
if (!r) {
return TASK_DONE;
}
+ case 1:
try {
d->write(buffer, r);
}
catch (IOAgain e) {
current = 1;
+ WaitFor(d, W4_WRITING);
Suspend(TASK_ON_HOLD);
}
current = 0;
@@ -36,7 +39,8 @@ int CopyJob::Do() throw (GeneralException) {
cursiz += r;
if (!s->IsClosed() && (siz != cursiz)) {
- throw TaskSwitch();
+ WaitFor(s, W4_READING);
+ Suspend(TASK_ON_HOLD);
}
if (ds) {
diff --git a/lib/Handle.cc b/lib/Handle.cc
index 4124231..253ddbf 100644
--- a/lib/Handle.cc
+++ b/lib/Handle.cc
@@ -26,7 +26,7 @@ ssize_t Handle::write(const void *buf, size_t count) throw (GeneralException) {
done = true;
errno = 0;
if ((r = ::write(h, buf, count)) < 0) {
- if ((!errno) || (errno = EAGAIN)) {
+ if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) {
// 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 de place libre. Cela peut
// arriver si l'on agit sur un pipe ou un handle. Nous
@@ -61,7 +61,7 @@ ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) {
errno = 0;
if ((r = ::read(h, buf, count)) < 0) {
- if ((!errno) || (errno = EAGAIN)) {
+ if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) {
// 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.
throw IOAgain();
@@ -133,6 +133,8 @@ void Handle::close() {
::close(h);
}
+ h = -1;
+
closed = 1;
}
diff --git a/lib/HttpServ.cc b/lib/HttpServ.cc
index 602ebe0..ccff319 100644
--- a/lib/HttpServ.cc
+++ b/lib/HttpServ.cc
@@ -32,7 +32,7 @@ class ProcessRequest : public Task {
Action * p;
Socket s;
- String name;
+ String name, host;
Variables * Vars;
bool bad, hasvars, post;
};
@@ -60,18 +60,21 @@ int ProcessRequest::Do() {
bad = false;
- cerr << "---- Got a request\n";
+ cerr << "---- Got a request from handle " << s.GetHandle() << " \n";
post = ParseUri(file, domain, &b);
len = -1;
do {
b >> t;
- // cerr << "Read Request (n): " << t << endl;
+ cerr << "Read Request (n): " << 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();
}
+ if (t.strstr("Host: ") == 0) {
+ host = t.extract(6);
+ }
} while (t.strlen());
// cerr << "---- Processing it.\n";
@@ -152,6 +155,7 @@ int ProcessRequest::Do() {
try {
Handle * i = new Input(String("datas/") + file);
SendHeads(&b, GetMime(file), String("Accept-Ranges: bytes") + endhl + "Content-Length: " + (unsigned long long int) i->GetSize() + endhl, i->GetModif());
+ i->SetNonBlock();
a = new CopyJob(i, &s);
cerr << "File found, dumping.\n";
}
@@ -297,8 +301,10 @@ bool ProcessRequest::ParseUri(String & file, String & domain, Handle * s) {
posslash = Uri.strchr('/');
// Certains navigateurs indiqueront uniquement http://host comme URL.
if (posslash >= 0) {
+ host = Uri.extract(0, posslash - 1);
Uri = Uri.to_charp(posslash);
} else {
+ host = Uri;
Uri = "";
}
}
@@ -319,13 +325,13 @@ bool ProcessRequest::ParseUri(String & file, String & domain, Handle * s) {
void ProcessRequest::SendRedirect(Handle * s) {
*s << "HTTP/1.1 301 Moved Permanently" << endhl <<
"Server: " << name << endhl <<
- "Location: http://127.0.0.1:" << localport << "/bin/start" << endhl <<
+ "Location: http://" << host << "/bin/start" << endhl <<
"Cache-Control: no-cache" << endhl <<
"Connection: closed" << endhl <<
"Content-Type: text/html" << endhl << endhl <<
"<HTML><HEAD><TITLE>301 - Moved Permanently</TITLE></HEAD>" << endnl <<
"<BODY><center><b><h2>You should be redirected to the " << endnl << endnl <<
- "<a href=\"http://localhost/bin/start\">start page</a></h2></b></center>" << endnl <<
+ "<a href=\"http://" << host << "/bin/start\">start page</a></h2></b></center>" << endnl <<
"</BODY></HTML>" << endnl;
}
@@ -346,9 +352,7 @@ void ProcessRequest::SendHeads(Handle * s, const String & mime, const String & e
strftime(buf, 1024, "%a, %d %b %Y %H:%M:%S GMT", ft);
}
*s << "Last-Modified: " << buf << endhl << extra <<
- "Cache-Control: no-cache" << endhl <<
- "Keep-Alive: timeout=0, max=0" << endhl <<
- "Connection: Keep-Alive" << endhl <<
+ "Connection: closed" << endhl <<
"Content-Type: " << mime << endhl << endhl;
}
diff --git a/lib/ReadJob.cc b/lib/ReadJob.cc
index 3083040..d5cabca 100644
--- a/lib/ReadJob.cc
+++ b/lib/ReadJob.cc
@@ -2,8 +2,9 @@
#include "HttpServ.h"
ReadJob::ReadJob(Handle * as, Handle * ad) : s(as), d(ad) {
- WaitFor(s, W4_STICKY | W4_READING);
- WaitFor(d, W4_STICKY | W4_WRITING);
+ s->SetNonBlock();
+ d->SetNonBlock();
+ WaitFor(s, W4_READING);
}
ReadJob::~ReadJob() { }
@@ -17,6 +18,7 @@ int ReadJob::Do() throw (GeneralException) {
*s >> buff;
}
catch (IOAgain e) {
+ WaitFor(s, W4_READING);
Suspend(TASK_ON_HOLD);
}
case 1:
@@ -25,13 +27,15 @@ int ReadJob::Do() throw (GeneralException) {
}
catch (IOAgain e) {
current = 1;
- throw TaskSwitch();
+ WaitFor(d, W4_WRITING);
+ Suspend(TASK_ON_HOLD);
}
current = 0;
if (buff == "") return TASK_DONE;
}
if (!s->IsClosed()) {
+ WaitFor(s, W4_READING);
Suspend(TASK_ON_HOLD);
}
diff --git a/lib/Task.cc b/lib/Task.cc
index bc7c7a0..72023e4 100644
--- a/lib/Task.cc
+++ b/lib/Task.cc
@@ -17,20 +17,17 @@ int Task::Do() throw (GeneralException) {
}
int Task::Run() {
- cerr << "==== Task: \"" << GetName() << "\" running.\n";
try {
state = Do();
}
catch (TaskSwitch) {
- cerr << "==== Task: \"" << GetName() << "\" caugh a task switch. returning " << (state == TASK_ON_HOLD ? "TASK_ON_HOLD" : "TASK_DONE") << endl;
return state;
}
catch (GeneralException e) {
- cerr << "Task " << GetName() << " caused an unexpected exception. Terminating.\n";
+ cerr << "Task " << GetName() << " caused an unexpected exception: \"" << e.GetMsg() << "\". Terminating.\n";
return TASK_DONE;
}
- cerr << "==== Task: \"" << GetName() << "\" exitted. returning " << (state == TASK_ON_HOLD ? "TASK_ON_HOLD" : "TASK_DONE") << endl;
return state;
}
@@ -51,6 +48,7 @@ void Task::Suspend(int newstate) throw (GeneralException) {
}
void Task::WaitFor(Handle * h, int flags) {
+ h->SetNonBlock();
TaskMan::WaitFor(h, this, flags);
}
diff --git a/lib/TaskMan.cc b/lib/TaskMan.cc
index 4d782a0..cf411cc 100644
--- a/lib/TaskMan.cc
+++ b/lib/TaskMan.cc
@@ -34,6 +34,10 @@ void taskman_sigchild(int sig) {
signal(SIGCHLD, taskman_sigchild);
}
+void taskman_sigpipe(int sig) {
+ signal(SIGPIPE, taskman_sigpipe);
+}
+
int TaskMan::GotChild(pid_t pid, int status) {
int r = 0;
@@ -54,6 +58,7 @@ void TaskMan::Init() throw (GeneralException) {
}
signal(SIGCHLD, taskman_sigchild);
+ signal(SIGPIPE, taskman_sigpipe);
inited = true;
number = 0;
@@ -108,6 +113,7 @@ void TaskMan::RemoveFromWatches(Task * t) {
}
void TaskMan::WaitFor(Handle * h, Task * t, int flags) {
+ h->SetNonBlock();
w4ha.push_back(w4ha_t(h, flags, t));
}
@@ -134,7 +140,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
throw GeneralException("TaskMan: No more task to manage.");
}
- cerr << "==== TaskMan: main loop.\n";
+ cerr << "-=- TaskMan: begin main loop with " << number << " task to manage.\n";
no_burst = 0;
while (!no_burst) {
@@ -144,7 +150,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
Task * t = *p;
if (t->GetState() == TASK_BURST) {
- cerr << "==== TaskMan: running burning task \"" << t->GetName() << "\".\n";
+ cerr << "-=- TaskMan: running burning task " << t->GetName() << endl;
t->Run();
/* if the task added some new tasks, we have to rerun the loop */
no_burst = 0;
@@ -163,8 +169,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
}
nfds = w4ha.size();
-
- cerr << "==== TaskMan: polling.\n";
+ no_burst = 1;
if (nfds != 0) {
int r;
@@ -179,22 +184,28 @@ void TaskMan::MainLoop() throw (GeneralException) {
#ifdef USE_POLL
ufsd = (struct pollfd *) malloc(nfds * sizeof(struct pollfd));
for (q = ufsd, p = w4ha.begin(); p && (p != w4ha.end()); p++, q++) {
+ p->dirthy = false;
if (p->T->IsStopped()) {
q->fd = 0;
q->events = 0;
} else {
- cerr << "==== TaskMan: adding watch over handle \"" << p->ha->GetName() << "\" for task \"" << p->T->GetName() << "\"\n";
if (p->ha->CanWatch()) {
q->fd = p->ha->GetHandle();
q->events = (p->flags & W4_READING ? POLLIN : 0) | (p->flags & W4_WRITING ? POLLOUT : 0);
} else {
- cerr << "==== TaskMan: handle can't watch, switching task to burst.\n";
p->T->SetBurst();
+ no_burst = 0;
+ if (!(p->flags & W4_STICKY)) {
+ w4ha.erase(p);
+ p--;
+ }
+ q->fd = 0;
+ q->events = 0;
}
}
}
- r = poll(ufsd, nfds, -1);
+ r = poll(ufsd, nfds, (no_burst) && !(Zombies.size()) ? -1: 1);
#else
FD_ZERO(readfds);
FD_ZERO(writefds);
@@ -228,22 +239,21 @@ void TaskMan::MainLoop() throw (GeneralException) {
struct pollfd * q;
int i;
for (q = ufsd, i = 0; i < nfds; i++, q++) {
-
if (q->revents & POLLNVAL) {
throw GeneralException(String("Error with poll, handle ") + q->fd + " invalid.");
}
if (q->revents & POLLERR) {
- throw GeneralException(String("Error condition whith poll, handle ") + q->fd);
+ cerr << "Error condition whith poll, handle " << q->fd << endl;
}
if (q->revents & POLLHUP) {
- cerr << "Handle " << q->fd << " hung up.";
+ cerr << "Handle " << q->fd << " hung up.\n";
// What should I do now?
}
fd = q->fd;
- if (q->revents & (POLLIN | POLLOUT)) {
+ if (q->revents & (POLLIN | POLLOUT | POLLERR | POLLHUP)) {
#else
/* Later perhaps... Let's use poll for now.
The following is independant of the use of select or poll.
@@ -252,33 +262,33 @@ void TaskMan::MainLoop() throw (GeneralException) {
the test "if handle has changed" */
#endif
// We have to look into the handle structure now...
- for (vector<w4ha_t>::iterator p = w4ha.begin(); p && (p != w4ha.end()); p++) {
- if ((p->ha->GetHandle() == fd) && (!p->T->IsStopped())) {
+ bool touched;
+ for (vector<w4ha_t>::iterator p = w4ha.begin(); p && (p != w4ha.end()); p = touched ? w4ha.begin() : p + 1) {
+ touched = false;
+ if ((p->ha->GetHandle() == fd) && (!p->T->IsStopped()) && (p->T->GetState() != TASK_DONE) && (!p->dirthy)) {
// We've got one, launch it.
- bool erased;
+ cerr << "-=- TaskMan: launching task " << p->T->GetName() << " for handle " << p->ha->GetHandle() << endl;
+ w4ha_t w4 = *p;
+ p->dirthy = true;
- cerr << "==== TaskMan: event over handle \"" << p->ha->GetName() << "\"\n";
-
- erased = false;
- p->T->Run();
+ if (!(p->flags & W4_STICKY)) {
+ w4ha.erase(p);
+ }
+
+ touched = true;
+
+ w4.T->Run();
- if (p->T->GetState() == TASK_DONE) {
+ if (w4.T->GetState() == TASK_DONE) {
// This task died, remove it.
- TaskList_t::iterator q = FindTask(p->T);
+ TaskList_t::iterator q = FindTask(w4.T);
if (q) {
TaskList.erase(q);
number--;
- Zombies.push_back(p->T);
- w4ha.erase(p);
- p--;
- erased = true;
+ Zombies.push_back(w4.T);
}
}
- if (!erased && !(p->flags & W4_STICKY)) {
- w4ha.erase(p);
- p--;
- }
}
}
}
@@ -303,6 +313,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
}
if ((o = t->WaitedBy())) {
+ cerr << "-=- TaskMan: running task " << o->GetName() << " for task " << t->GetName() << endl;
o->Run();
if (o->GetState() == TASK_DONE) {