-/* $Id: httpd.js,v 1.66 2005/07/15 14:20:08 mmondor Exp $ */
+/* $Id: httpd.js,v 1.67 2005/07/15 21:57:52 mmondor Exp $ */
/*
* Copyright (c) 2005, Matthew Mondor
* Little example showing the versatility of ECMAScript, provided with a
* custom library for BSD socket support, using SpiderMonkey.
* This tiny HTTPd allows simultaneous concurrent client connections without
- * using multiple threads or processes. Must be ran through ../../src/test,
- * compiled with ../../src/classes/js_fd.[ch] support.
+ * using multiple threads or processes. Must be ran through
+ * ../../src/js-server.
*
* Configuration options can be found in options.js
*
* Server identification
*/
SERVER_VERSION = 'mmondor_js_httpd/0.0.1 (NetBSD)';
-SERVER_CVSID = '$Id: httpd.js,v 1.66 2005/07/15 14:20:08 mmondor Exp $';
+SERVER_CVSID = '$Id: httpd.js,v 1.67 2005/07/15 21:57:52 mmondor Exp $';
-/* $Id: js-server.c,v 1.1 2005/07/15 21:43:45 mmondor Exp $ */
+/* $Id: js-server.c,v 1.2 2005/07/15 21:57:06 mmondor Exp $ */
/* Copyright (c) 2004, Matthew Mondor */
* This however also required standard properties to be shared
* (JS_PROP_SHARED), otherwise api_class_property_add() would be called
* and even setting values to existing API system properties would fail in
- * user scripts. Scealing was also too strict.
+ * user scripts. Scealing was also too strict.
* I assumed that JS_AddNamedRoot() was required for the API class to
* never be freed, so that it can be reused after a call to
- * js_context_reset(). Perhaps this is not necessary.
+ * js_context_reset(). Perhaps this is not necessary.
*/
#include <js_fd.h>
#include <js_errno.h>
-#include <js_file.h>
+/*
+ * DEFINITIONS
+ */
/* Size runtime objects must take to run the GC */
#define GCBYTES 1048576 /* 1MB */
/* Size of stack to allocate for every context */
#define STACKBYTES 8192 /* 8KB */
-
-
-/* Structure used to link a context with custom objects we need to perform
- * some cleanup from before destroying the context. Ideally managed via
+/*
+ * Structure used to link a context with custom objects we need to perform
+ * some cleanup from before destroying the context. Ideally managed via
* mmpool(3) in a real world application for slap management and recycling.
* We'll have one of these per process in our pool of processes.
*/
JSObject *global, *class_fd, *class_errno;
} js_context_t;
+/*
+ * To hold loaded file objects (actually mmap(2)ed)
+ */
+typedef struct {
+ void *data;
+ size_t size;
+} file_t;
-
-/* Defaults for the global class */
+/*
+ * Defaults for the global class
+ */
static JSClass global_class = {
"global", 0, JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-/* Only here for a test */
-int main(int, char **);
+/*
+ * PROTOTYPES
+ */
+
+int main(int, char **);
+static JSBool branch_callback(JSContext *, JSScript *);
+
+static file_t *file_load(const char *);
+static void file_free(file_t *);
+
+/* Could be an exported API later on */
+static js_context_t *js_context_init(size_t, size_t);
+static void js_context_destroy(js_context_t *);
+static void js_context_reset(js_context_t *);
-static JSBool branch_callback(JSContext *, JSScript *);
-/* Exported API */
-js_context_t *js_context_init(size_t, size_t);
-void js_context_destroy(js_context_t *);
-void js_context_reset(js_context_t *);
}
-/* Exported API */
-js_context_t *
+/*
+ * Could be an exported API
+ */
+
+static js_context_t *
js_context_init(size_t gc_size, size_t stack_size)
{
js_context_t *cctx;
return cctx;
}
-void
+static void
js_context_destroy(js_context_t *cctx)
{
* having to destroy and recreate contexts everytime.
*/
/* ARGSUSED */
-void
+static void
js_context_reset(js_context_t *cctx)
{
/* XXX */
/* NOOP */
}
+
+
+
+/*
+ * Loads specified file and returns a file_t pointer. Note that we only
+ * internally keep the memory map for read access to the file, rather than an
+ * open filedescriptor.
+ */
+static file_t *
+file_load(const char *filename)
+{
+ int fd;
+ struct stat st;
+ file_t *file;
+
+ assert(filename != NULL);
+
+ if ((fd = open(filename, O_RDONLY)) != -1) {
+ if (fstat(fd, &st) == 0) {
+ if ((file = malloc(sizeof(file_t))) != NULL) {
+ file->size = (size_t)st.st_size;
+
+ if ((file->data = mmap(NULL, file->size,
+ PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0))
+ != MAP_FAILED) {
+ (void) close(fd);
+ return file;
+ }
+
+ free(file);
+ }
+ }
+ (void) close(fd);
+ }
+
+ return NULL;
+}
+
+/*
+ * Frees a file_t which was returned by a previous file_load() call.
+ */
+static void
+file_free(file_t *file)
+{
+
+ assert(file != NULL);
+
+ (void) munmap(file->data, file->size);
+ free(file);
+}