-/* $Id: httpd.js,v 1.37 2006/08/22 10:12:54 mmondor Exp $ */
+/* $Id: httpd.js,v 1.38 2006/08/22 12:50:07 mmondor Exp $ */
/*
* Copyright (c) 2005-2006, Matthew Mondor
* Server identification
*/
const SERVER_VERSION = 'mmondor_js_httpd/0.1.0 (NetBSD)';
-const SERVER_CVSID = '$Id: httpd.js,v 1.37 2006/08/22 10:12:54 mmondor Exp $';
+const SERVER_CVSID = '$Id: httpd.js,v 1.38 2006/08/22 12:50:07 mmondor Exp $';
/*
* Open standard error FD for diagnostics output
*/
-var err = new FD();
-err.set(FD.STDERR_FILENO);
+var stderr = new FD();
+stderr.set(FD.STDERR_FILENO);
} else
fd = file;
} catch (x) {
- err.put(x + " at file_read()\n");
+ stderr.put(x + " at file_read()\n");
}
try {
contents += data;
}
} catch (x) {
- err.put(x + " at file_read()\n");
+ stderr.put(x + " at file_read()\n");
}
fd.close();
try {
eval(file_read('options.js')); /* Configuration */
} catch (x) {
- err.put(x + " while reading options file\n");
+ stderr.put(x + " while reading options file\n");
exit();
}
eval(file_read(ilibprefix + 'fd.js'));
const STYPE_CONNECT = 1;
const STYPE_HTTP = 2;
const STYPE_APPSERV = 3;
+/*
+const STYPE_LDEBUG = 4;
+const STYPE_DEBUG = 5;
+*/
/*
* Client file transfer states (enumeration)
}
if (s == undefined)
- err.put("No more free appserv slots\n");
+ stderr.put("No more free appserv slots\n");
return s;
},
*/
/*
+function state_debug_read(time)
+{
+ var data;
+
+ while ((data = this.breadline(255, false)) != null) {
+ if (data.length > 0) {
+ this.bwrite('you typed: "' + data + '"' + "\n",
+ true, false);
+ } else
+ break;
+ }
+ if (data == null) {
+ if (this.berror != this.BEAGAIN) {
+ stderr.put(this.berrorStr[this.berror] +
+ " at state_debug_read()\n");
+ return PSTAT_CLOSE_SUCCESS;
+ }
+ }
+
+ return PSTAT_CONTINUE;
+}
+*/
+
+/*
* Reset FD to a consistent known state, to use after accept(2).
* To be passed current time in seconds since epoch.
*/
if (data == null) {
/* Error */
if (this.berror != this.BEAGAIN) {
- /* XXX */ err.put(this.berrorStr[this.berror] + "\n");
+ /* XXX */ stderr.put(this.berrorStr[this.berror]
+ + "\n");
if (this.berror == this.BTOOLONG)
http_error(this, 413,
'Request Entity Too Large',
len = this.http_content_length - this.post_data.length;
if ((data = this.bread(len, false)) == null) {
if (this.berror != this.BEAGAIN) {
- /* XXX */ err.put(this.berrorStr[this.berror] +
- "\n");
+ /* XXX */ stderr.put(
+ this.berrorStr[this.berror] + "\n");
return PSTAT_CLOSE_ERROR;
}
}
try {
fd.lseek(from, FD.SEEK_SET);
} catch(x) {
- err.put(x + " at lseek()\n");
+ stderr.put(x +
+ " at lseek()\n");
}
}
}
pollset.add(fd);
} catch (x) {
- err.put(x + " in appserv_connect()\n");
+ stderr.put(x + " in appserv_connect()\n");
return false;
}
try {
var v = new VHost(vhosts[i]);
} catch (x) {
- err.put(x + " creating VHost object\n");
+ stderr.put(x + " creating VHost object\n");
}
}
/*
* Attempt to link default_vhost to a VHost object
*/
if (options.default_vhost == undefined) {
- err.put("No default_vhost property in options, exiting\n");
+ stderr.put("No default_vhost property in options, exiting\n");
exit();
}
if (vhosts_table[options.default_vhost.toLowerCase()] != undefined)
default_vhost =
vhosts_table[options.default_vhost.toLowerCase()];
else {
- err.put('Default vhost ' + options.default_vhost +
+ stderr.put('Default vhost ' + options.default_vhost +
" unkonwn, exiting\n");
exit();
}
for (i2 in mimetypes[i]) {
ext = mimetypes[i][i2].toLowerCase();
if (mimetypes_table[ext] != undefined) {
- err.put('Conflicting mime type ' +
+ stderr.put('Conflicting mime type ' +
ext + ' -> ' + i + "\n");
continue;
}
}
/*
+ * Add debugging port XXX Make this optional and allow to specify
+ * address and port number
+ */
+ /*
+ try {
+ fd = new FD();
+ fd.socket(FD.AF_INET, FD.SOCK_STREAM, 0);
+ fd.bind('127.0.0.1', 8199);
+ fd.setsockopt(FD.SO_REUSEADDR, 1);
+ fd.fcntl(FD.F_SETFL, FD.O_NONBLOCK);
+ fd.listen(0);
+ fd.events = FD.POLLIN;
+ fd.type = STYPE_LDEBUG;
+ pollset.add(fd);
+ } catch (x) {
+ stderr.put(x + " preparing debugging socket\n");
+ }
+ */
+
+ /*
* Initialize server
*/
for (i in listen) {
fd.type = STYPE_LISTEN;
pollset.add(fd);
} catch (x) {
- err.put(x + " preparing listening socket\n");
+ stderr.put(x + " preparing listening socket\n");
}
}
if (pollset.count == 0)
exit();
+
+ /*
+ * Reset pollset.min to avoid overwriting static descriptors
+ */
pollset.min = pollset.count;
/*
try {
e = FD.poll(pollset.set, exp * 1000);
} catch (x) {
- err.put(x + " for poll(2)\n");
+ stderr.put(x + " for poll(2)\n");
continue;
}
continue;
efd = e[i];
+ /* XXX Make this optional */
+ /*
+ if (efd.type == STYPE_LDEBUG &&
+ (efd.revents & FD.POLLIN) != 0) {
+ try {
+ fd = efd.accept();
+ fd.type = STYPE_DEBUG;
+ fd.state = state_debug_read;
+ pollset.add(fd);
+ } catch (x) {
+ stderr.put(x + " at accept(2)\n");
+ fd.close();
+ }
+ continue;
+ }
+ if (efd.type == STYPE_DEBUG) {
+ if ((efd.revents & (FD.POLLHUP | FD.POLLERR))
+ != 0)
+ efd.stat = PSTAT_CLOSE_ERROR;
+ if (efd.stat == PSTAT_CONTINUE &&
+ (efd.revents & (FD.POLLIN | FD.POLLOUT))
+ != 0) {
+ try {
+ efd.stat = efd.state(cur);
+ } catch (x) {
+ efd.stat == PSTAT_CLOSE_ERROR;
+ }
+ }
+ if (efd.stat == PSTAT_CONTINUE)
+ continue;
+ try {
+ efd.close();
+ } catch (x) {}
+ pollset.remove(efd);
+ continue;
+ }
+ */
+
/*
* If descriptor is a bound one, attempt to accept
* the new client connection
fd.state_http_init(cur);
pollset.add(fd);
} catch (x) {
- err.put(x + " at accept(2)\n");
+ stderr.put(x + " at accept(2)\n");
fd.close();
}
continue;
-/* $Id: fd.js,v 1.8 2006/08/22 11:43:59 mmondor Exp $ */
+/* $Id: fd.js,v 1.9 2006/08/22 12:49:57 mmondor Exp $ */
/*
* Copyright (C) 2006, Matthew Mondor
this.berror = this.BTIMEOUT;
return null;
}
- if ((e[0].revents & FD.POLLHUP) == 1) {
+ if ((e[0].revents & (FD.POLLHUP | FD.POLLERR))
+ != 0) {
this.berror = this.BEOF;
return null;
}
if (len == data.length)
return 0;
this.bwrite_buffer += data.substr(len);
+ this.events |= FD.POLLOUT;
return 1;
} else {
+ this.events |= FD.POLLOUT;
this.bwrite_buffer += data;
if (this.bwrite_buffer.length > 65535)
return this.bflushw(poll);
}
}
this.bwrite_buffer = this.bwrite_buffer.substr(len);
- if (this.bwrite_buffer.length == 0) {
- this.berror = this.BSUCCESS;
- return 0;
- }
+ if (this.bwrite_buffer.length == 0)
+ break;
if (!poll) {
this.berror = this.BEAGAIN;
+ this.events |= FD.POLLOUT;
return 1;
}
try {
- this.events = FD.POLLOUT | FD.POLLHUP;
+ this.events = FD.POLLOUT;
e = FD.poll([this], this.output_timeout);
if (e.length == 0) {
this.berror = this.BTIMEOUT;
return -1;
}
- if ((e[0].revents & FD.POLLHUP) == 1) {
+ if ((e[0].revents & (FD.POLLHUP | FD.POLLERR)) != 0) {
this.berror = this.BEOF;
return -1;
}
}
this.berror = this.BSUCCESS;
+ this.events &= ~FD.POLLOUT;
return 0;
}