# HG changeset patch # User Olaf Wintermann # Date 1315340852 -7200 # Node ID 3c066d52342d10f03f6b43422cd37c79be655775 # Parent 4c89c7683fb6c06c2bd87895f2447360a89b92ef added source diff -r 4c89c7683fb6 -r 3c066d52342d src/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Makefile Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,33 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2011 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +BUILD_ROOT = ../ + +all: + cd server; $(MAKE) all + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/LinkedList.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/LinkedList.hh Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,272 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINKED_LIST_H_ +#define _LINKED_LIST_H_ + +/* + * Provided a template implementation of a simple linked list. + * It is a reference based container (stores the pointers to the + * objects contained) It doesn't check for duplicates etc and find + * (delete) will find(delete) the first occurence of an element. + * + * Iterator class can be used for traversal using the "++" operator. + */ +template class CList; // forward declaration +template class CListIterator; // forward declaration +template class CListConstIterator; // forward declaration + +template class CListElmt { + friend class CList; + friend class CListIterator; + friend class CListConstIterator; + private: + CListElmt(C* refP, int id) : _refP(refP), _nextP(0), _prevP(0), _id(id) + { + // Nothing really has to be done here + }; + + + private: + int _id; + C *_refP; +#if defined(AIX) + CListElmt *_nextP; + CListElmt *_prevP; +#else + CListElmt *_nextP; + CListElmt *_prevP; +#endif +}; + +// +// NOTE : If you need the find functionality, make sure that +// class C has "==" defined. +// +template class CList { + friend class CListIterator; + friend class CListConstIterator; + private: + CListElmt* _headP; + CListElmt* _tailP; + CListElmt* Lookup(C * memberP) + { + CListElmt *curEltP = _headP; + + while (curEltP) + { + if (curEltP->_refP == memberP) + break; + curEltP = curEltP->_nextP; + }; + return(curEltP); + }; + + int _nextId; + int _numElts; + int autoDestroy; + C* Remove(CListElmt *elmtP) + { + C *recP = NULL; + if (elmtP) + { + if (elmtP->_nextP) + elmtP->_nextP->_prevP = elmtP->_prevP; + if (elmtP->_prevP) + elmtP->_prevP->_nextP = elmtP->_nextP; + if (elmtP == _tailP) + _tailP = elmtP->_prevP; + if (elmtP == _headP) + _headP = _headP->_nextP; + recP = elmtP->_refP; + _numElts--; + delete elmtP; + }; + if ( (1==autoDestroy) && recP) + delete recP; + + return(recP); + }; + + + public: + CList() : _headP(0), _tailP(0), _nextId(0), _numElts(0), autoDestroy(0) + { + // Nothing really has to be done here + }; + + void setAutoDestroy(int setting) + { + autoDestroy = setting; + }; + + virtual ~CList() + { + while (_headP) + Remove(_headP); + }; + + int NextId() + { + return _nextId; + }; + + int Append(C* refP) + { + CListElmt *newElmtP = new CListElmt(refP, _nextId++); + newElmtP->_prevP = _tailP; + if (_tailP) + _tailP->_nextP = newElmtP; + if (_headP == 0) + _headP = newElmtP; + _tailP = newElmtP; + _numElts++; + return(newElmtP->_id); + }; + + int Member(C* memberP) + { + return(Lookup(memberP) != 0); + }; + + int Delete(C* memberP) + { + CListElmt *listElmtP = Lookup(memberP); + if (listElmtP) + { + (void) Remove(listElmtP); + return(1); + } + return(0); + }; + + int NumEntries() const { return _numElts; } + C* Find(C* memberP) // Lookup based on == operator for class C + { + CListElmt *curEltP = _headP; + + while (curEltP) + { + if (curEltP->_refP == memberP) + break; + curEltP = curEltP->_nextP; + }; + return(curEltP ? curEltP->_refP : 0); + }; + + C* First() { return(_headP ? _headP->_refP : 0); } + C* Last() { return(_tailP ? _tailP->_refP : 0); } +}; + +template class CListIterator { + private: + CList* _listP; + int _curId; + public: + CListIterator(CList* linkedListP) : _listP(linkedListP), _curId(-1) + { + // Nothing more to be done + }; + + virtual ~CListIterator() + { + _listP = NULL; + }; + + C* operator++() // Define ++ operator to move forward along the list. + { + C *valueP = NULL; + CListElmt *curEltP = _listP->_headP; + + while (curEltP) + { + if (curEltP->_id > _curId) + { + _curId = curEltP->_id; + return(curEltP->_refP); + } + curEltP = curEltP->_nextP; + } + _curId = -1; + return(NULL); + }; + + void operator()() // Overload the function operator to reset the iterator + { + _curId = -1; + }; + +}; + +template class CListConstIterator { + private: + const CList* _listP; + int _curId; + public: + CListConstIterator(const CList* linkedListP) + : _listP(linkedListP), _curId(-1) + { + // Nothing more to be done + }; + + virtual ~CListConstIterator() + { + _listP = NULL; + }; + + const C* operator++() // Define ++ operator to move forward along the list. + { + const C *valueP = NULL; + const CListElmt *curEltP = _listP->_headP; + + while (curEltP) + { + if (curEltP->_id > _curId) + { + _curId = curEltP->_id; + return(curEltP->_refP); + } + curEltP = curEltP->_nextP; + } + _curId = -1; + return(NULL); + }; + + void operator()() // Overload the function operator to reset the iterator + { + _curId = -1; + }; + +}; + +#endif // _LINKED_LIST_H_ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/Makefile Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,53 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2011 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +BUILD_ROOT = ../../ +OBJ_DIR = $(BUILD_ROOT)build/ + +CFLAGS = -I/usr/include/mps +LDFLAGS = -L/usr/lib/mps -lplds4 -lplc4 -lnspr4 -lpthread -ldl -lposix4 -lsocket -lnsl -lgen -lm -R/usr/lib/mps + +MAIN_TARGET = $(BUILD_ROOT)work/bin/webservd + +include objs.mk + +all: preparation $(MAIN_TARGET) + +preparation: + mkdir -p $(OBJPRE) + mkdir -p $(BUILD_ROOT)work/bin + +$(MAIN_TARGET): $(MAINOBJS) + CC -o $(MAIN_TARGET) $(LDFLAGS) $(MAINOBJS) + +$(OBJPRE)%.o: %.c + cc -o $@ -c $(CFLAGS) $< + +$(OBJPRE)%.o: %.cpp + CC -o $@ -c $(CFLAGS) $< + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/conf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/conf.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,50 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "nsapi.h" + +#include +#include + +#include "httplistener.h" +#include "conf.h" + +void load_init_conf(char *file) { + printf("load_init_conf\n"); +} + +void load_server_conf(char *file) { + printf("load_server_conf\n"); + + ListenerConfig *conf = malloc(sizeof(ListenerConfig)); + conf->port = 8080; + conf->nacceptors = 1; + conf->name = "default"; + + http_listener_new(conf); +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/conf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/conf.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,47 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CONF_H +#define CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +void load_init_conf(char *file); + +void load_server_conf(char *file); + + + +#ifdef __cplusplus +} +#endif + +#endif /* CONF_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/ereport.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/ereport.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,125 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_EREPORT_H +#define BASE_EREPORT_H + +#ifndef NOINTNSAPI +#define INTNSAPI +#endif /* !NOINTNSAPI */ + +/* + * ereport.h: Records transactions, reports errors to administrators, etc. + * + * Rob McCool + */ + +#ifndef BASE_SESSION_H +#include "session.h" +#endif /* !BASE_SESSION_H */ + +/* Pseudo-filename to enable logging to syslog */ +#define EREPORT_SYSLOG "SYSLOG" + +/* NSAPI degrees used by Java but not exposed in nsapi.h */ +#define LOG_FINER 7 +#define LOG_FINEST 8 + +/* --- Begin function prototypes --- */ + +#ifdef INTNSAPI + +NSPR_BEGIN_EXTERN_C + +/* + * INTereport logs an error of the given degree and formats the arguments with + * the printf() style fmt. Returns whether the log was successful. Records + * the current date. + */ + +NSAPI_PUBLIC int INTereport(int degree, const char *fmt, ...); +NSAPI_PUBLIC int INTereport_v(int degree, const char *fmt, va_list args); + +/* + * INTereport_init initializes the error logging subsystem and opens the static + * file descriptors. It returns NULL upon success and an error string upon + * error. If a userpw is given, the logs will be chowned to that user. + */ + +NSAPI_PUBLIC +char *INTereport_init(const char *err_fn, const char *email, struct passwd *pwuser, const char *version, int restarted); + +NSAPI_PUBLIC void INTereport_terminate(void); + +/* For restarts */ +NSAPI_PUBLIC SYS_FILE INTereport_getfd(void); + +NSPR_END_EXTERN_C + +#ifdef __cplusplus +class EreportableException; +NSAPI_PUBLIC int INTereport_exception(const EreportableException& e); +#endif + +/* --- End function prototypes --- */ + +#define ereport INTereport +#define ereport_v INTereport_v +#define ereport_init INTereport_init +#define ereport_terminate INTereport_terminate +#define ereport_getfd INTereport_getfd +#define ereport_exception INTereport_exception + +typedef int (EreportFunc)(const VirtualServer* vs, int degree, const char *formatted, int formattedlen, const char *raw, int rawlen, void *data); + +void ereport_set_servername(const char* name); +void ereport_set_logvsid(PRBool b); +void ereport_set_logall(PRBool b); +void ereport_set_alwaysreopen(PRBool b); +void ereport_set_timefmt(const char* timeFmt); +void ereport_set_degree(int degree); +int ereport_level2degree(const char *level, int defdegree); +PRBool ereport_can_log(int degree); +int ereport_request(Request* rq, int degree, const char *fmt, ...); +char *ereport_abs_filename(const char *filename); +void ereport_rotate(const char* ext); +void ereport_set_rotate_callback(void (*fn)(const char* filenameNew, const char* filenameOld)); +void ereport_reopen(void); +void ereport_outofmemory(void); +void ereport_disaster(int degree, const char *fmt, ...); +NSAPI_PUBLIC int ereport_register_cb(EreportFunc* ereport_func, void* data); +NSAPI_PUBLIC int ereport_register_thread_cb(EreportFunc* ereport_func, void* data); + +#endif /* INTNSAPI */ + +#endif /* !BASE_EREPORT_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/func.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/func.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,55 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + +#include "nsapi.h" +#include "map.h" +#include "func.h" + +hashmap_t *function_map; + +void func_init() { + function_map = hashmap_new(128); +} + +void add_function(struct FuncStruct *func) { + struct FuncStruct *f = malloc(sizeof(FuncStruct)); + *f = *func; + hashmap_put(function_map, sstr((char*)f->name), func); +} + +void add_functions(struct FuncStruct *funcs) { + int i = 0; + while(funcs[i].func != NULL) { + add_function(&funcs[i]); + i++; + } +} + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/func.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/func.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,50 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FUNC_H +#define FUNC_H + +#include "nsapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void func_init(); + +void add_function(struct FuncStruct *func); + +void add_functions(struct FuncStruct *funcs); + + +#ifdef __cplusplus +} +#endif + +#endif /* FUNC_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/httplistener.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/httplistener.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,178 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "nsapi.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "map.h" +#include "httplistener.h" + +#include "session.h" + +hashmap_t *listener_map = NULL; + + +int start_all_listener() { + HttpListener *listener = get_http_listener("default"); + http_listener_start(listener); + + return 0; +} + +HttpListener* get_http_listener(char *name) { + return hashmap_get(listener_map, sstr(name)); +} + + +HttpListener* http_listener_new(ListenerConfig *conf) { + HttpListener *listener = malloc(sizeof(HttpListener)); + listener->session_handler = create_basic_session_handler(); + listener->nacceptors = conf->nacceptors; + + struct sockaddr_in servaddr; /* server address */ + + /* init address structure */ + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(conf->port); + + /* create socket */ + if((listener->server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + perror("Error: http_listener_new: socket"); + return NULL; + } + + int o = 1; + setsockopt( + listener->server_socket, + SOL_SOCKET, SO_REUSEADDR, + &o, + sizeof(int)); + + /* bind server socket to address */ + if(bind(listener->server_socket, (struct sockaddr*)&servaddr, sizeof(servaddr))){ + perror("Error: http_listener_new: bind"); + return NULL; + } + + /* create acceptors */ + listener->acceptors = calloc(listener->nacceptors, sizeof(void*)); + for (int i=0;inacceptors;i++) { + listener->acceptors[i] = acceptor_new(listener); + } + + if(listener_map == NULL) { + listener_map = hashmap_new(8); + } + hashmap_put(listener_map, sstr(conf->name), listener); + return listener; +} + +int http_listener_start(HttpListener *listener) { + printf("INFO: start listener\n"); + + if (listen(listener->server_socket, 16) == -1) { + perror("Error: http_listener_start: listen"); + return -1; + } + + /* start acceptor threads */ + for (int i=0;inacceptors;i++) { + acceptor_start(listener->acceptors[i]); + } +} + + + +Acceptor* acceptor_new(HttpListener *listener) { + Acceptor *acceptor = malloc(sizeof(Acceptor)); + acceptor->listener = listener; + return acceptor; +} + +void acceptor_start(Acceptor *a) { + if(pthread_create( + &a->tid, + NULL, + (void*(*)(void*))acceptor_thread, + a) != 0) + { + perror("Error: acceptor_start: pthread_create"); + } +} + +void* acceptor_thread(Acceptor *acceptor) { + HttpListener *listener = acceptor->listener; + + for (;;) { + /* accept connections */ + struct sockaddr_in ca; + int length = sizeof(ca); + int clientfd; + + /* accept a connection */ + clientfd = accept( + listener->server_socket, + (struct sockaddr*)&ca, + &length); + if (clientfd == -1) { + perror("Error: acceptor_thread: accept"); + continue; + } + + /* create Connection object */ + Connection *conn = malloc(sizeof(Connection)); + conn->address = ca; + conn->fd = clientfd; + + /* enqueue the connection */ + listener->session_handler->enqueue_connection( + listener->session_handler, + conn); + + /* ready for new connection */ + } +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/httplistener.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/httplistener.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,82 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTTPLISTENER_H +#define HTTPLISTENER_H + +#include "sessionhandler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _http_listener HttpListener; +typedef struct _acceptor Acceptor; +typedef struct _listener_config ListenerConfig; + +struct _listener_config { + char *name; + char *address; + int port; + int nacceptors; +}; + +struct _acceptor { + pthread_t tid; + HttpListener *listener; +}; + +struct _http_listener { + int server_socket; + Acceptor **acceptors; + int nacceptors; + SessionHandler *session_handler; +}; + +int start_all_listener(); +HttpListener* get_http_listener(char *name); + + +HttpListener* http_listener_new(ListenerConfig *conf); + +int http_listener_start(HttpListener *listener); + + +Acceptor* acceptor_new(HttpListener *listener); + +void acceptor_start(Acceptor *a); + +void* acceptor_thread(Acceptor *a); + + +#ifdef __cplusplus +} +#endif + +#endif /* HTTPLISTENER_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/httpparser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/httpparser.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,196 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "httpparser.h" +#include "nsapi.h" +//include "request.h" + + +HttpParser* http_parser_new(HTTPRequest *request) { + HttpParser *parser = malloc(sizeof(HttpParser)); + parser->request = request; + + parser->state = 0; + parser->start_line.ptr = (char*)request->netbuf->inbuf; + parser->start_line.length = 0; + + return parser; +} + +void http_parser_free(HttpParser *parser) { + free(parser); +} + +int http_parser_process(HttpParser *parser) { + switch(parser->state) { + case 0: { + int r = get_start_line(parser); + switch(r) { + case 0: break; + default: return r; + } + parse_request_line(parser); + parser->state++; + } + case 1: { + return http_parser_parse_header(parser); + } + case 2: { + return 0; + } + } +} + +int get_start_line(HttpParser *parser) { + netbuf *buf = parser->request->netbuf; + while(buf->pos < buf->cursize) { + unsigned char c = buf->inbuf[buf->pos]; + if(c == '\n') { + if(buf->pos <= 1) { + // insufficient chars for request, return error + return 2; + } + if(buf->inbuf[buf->pos - 1] == '\r') { + parser->start_line.length = buf->pos; + } else { + parser->start_line.length = buf->pos + 1; + } + parser->start_line.ptr = (char*)buf->inbuf; + buf->pos++; + return 0; + } + buf->pos++; + } + return 1; +} + +int http_parser_parse_header(HttpParser *parser) { + netbuf *buf = parser->request->netbuf; + + parser->offset = buf->pos; // line offset + parser->name.ptr = NULL; + parser->value.ptr = NULL; + while(1) { + if(buf->pos >= buf->cursize) { + return 1; + } + char c = (char)buf->inbuf[buf->pos++]; + + if(c > 32) { + parser->wl = 0; + if(c == ':' && parser->value.ptr == NULL) { + parser->name.ptr = (char*)buf->inbuf + parser->offset; + buf->inbuf[buf->pos-1] = 0; + } else if(parser->name.ptr != NULL && parser->value.ptr == NULL) { + parser->value.ptr = (char*)buf->inbuf + buf->pos - 1; + } + } else if(c == '\n') { + if(parser->wl) { + // line contains only white space -> end of request + parser->state++; + return 0; + } else { + parser->offset = buf->pos; + if(parser->value.ptr != NULL) { + buf->inbuf[buf->pos-1] = 0; + // add header + header_add( + parser->request->headers, + parser->name.ptr, + parser->value.ptr); + } else { + // error: no value + return 2; + } + parser->name.ptr = NULL; + parser->value.ptr = NULL; + parser->wl = 1; + } + } + } +} + +int parse_request_line(HttpParser *parser) { + sstr_t line = parser->start_line; + parser->request->request_line = line; + + /* + * parse method, url and http version + */ + + int i = 0; + int ns = 0; + + parser->request->method.ptr = line.ptr; + for(;irequest->method.length = i; + } else if(ns) { + if(line.ptr[i] != ' ') { + break; + } + } + } + + parser->request->uri.ptr = line.ptr + i; + ns = 0; + int s = i; + for(;irequest->uri.length = i - s; + } else if(ns) { + if(line.ptr[i] > 32) { + break; + } + } + } + + parser->request->httpv.ptr = line.ptr + i; + ns = 0; + s = i; + for(;irequest->httpv.length = i - s; + } else if(ns) { + if(line.ptr[i] > 32) { + break; + } + } + } + + return 0; +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/httpparser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/httpparser.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,90 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTTPPARSER_H +#define HTTPPARSER_H + + +#include "sstring.h" +#include "httprequest.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * http parser states + * + * 0: start line + * 1: header + * 2: finish + */ + +typedef struct _http_parser { + HTTPRequest *request; + + int state; + sstr_t start_line; + + /* local parser varaibles */ + int wl; /* only white space */ + int tk; /* token: 0: header name 1: header value */ + int offset; /* offset of parsed string */ + int strend; /* end position */ + sstr_t name; + sstr_t value; + +} HttpParser; + +HttpParser* http_parser_new(HTTPRequest *request); +void http_parser_free(HttpParser *parser); + +/* + * process http parsing + * + * return + * 0: finish + * 1: need more data + * 2: error + */ +int http_parser_process(HttpParser *parser); + +int get_start_line(HttpParser *parser); +int http_parser_parse_header(HttpParser *parser); + +int parse_request_line(HttpParser *parser); + + + +#ifdef __cplusplus +} +#endif + + +#endif /* HTTPPARSER_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/httprequest.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/httprequest.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,154 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "nsapi.h" +#include "pool.h" +#include "pblock.h" +#include "io.h" +#include "util.h" +#include "httprequest.h" + +HTTPRequest *http_request_new() { + HTTPRequest *req = malloc(sizeof(HTTPRequest)); + req->connection = NULL; + req->uri.ptr = NULL; + + HeaderArray *hd = malloc(sizeof(HeaderArray)); + hd->next = NULL; + hd->len = 0; + hd->headers = calloc(16, sizeof(Header)); + hd->alloc = 16; + + req->headers = hd; + + return req; +} + +int handle_request(HTTPRequest *request) { + // handle nsapi request + + // create pool + request->pool = pool_create(); + + // create nsapi data structures + NSAPISession *sn = malloc(sizeof(NSAPISession)); + NSAPIRequest *rq = malloc(sizeof(NSAPIRequest)); + request->rq = rq; + + // fill session structure + sn->sn.pool = pool_create(); + sn->sn.csd = stream_new_from_fd(request->connection->fd); + sn->sn.client = NULL; + sn->sn.next = NULL; + sn->sn.fill = 1; + sn->sn.subject = NULL; + + // init NSAPI request structure + if(request_initialize(request->pool, request, rq) != 0) { + return 1; + } + + /* Pass request line as "clf-request" */ + pblock_kvinsert( + pb_key_clf_request, + request->request_line.ptr, + request->request_line.length, + rq->rq.reqpb); + + /* Pass method as "method" in reqpb, and also as method_num */ + pblock_kvinsert( + pb_key_method, + request->method.ptr, + request->method.length, + rq->rq.reqpb); + // TODO: method num + //rqRq.rq.method_num = rqHdr->GetMethodNumber(); + //PR_ASSERT(rqRq.rq.method_num != -1 || iStatus); + + /* Pass protocol as "protocol" in reqpb, and also in protv_num */ + pblock_kvinsert( + pb_key_protocol, + request->httpv.ptr, + request->httpv.length, + rq->rq.reqpb); + // TODO: protocol num + + /* Pass any query as "query" in reqpb */ + // TODO: query + + /* Get abs_path part of request URI, and canonicalize the path */ + sstr_t absPath = request->uri; + // TODO: get abs_path + absPath.ptr = util_canonicalize_uri( + request->pool, + absPath.ptr, + absPath.length, + (int*)&absPath.length); + + /* Decode the abs_path */ + // TODO: decode abs_path + + /* Pass the abs_path as "uri" in reqpb */ + // TODO: pass abs_path to reqpb + // TODO: replace this code + pblock_kvinsert( + pb_key_uri, + absPath.ptr, + absPath.length, + rq->rq.reqpb); + + // pass http header to the NSAPI request structure + + + // Send the request to the NSAPI system + + return 0; +} + + + +void header_add(HeaderArray *hd, char *name, char *value) { + while(hd->len >= hd->alloc) { + if(hd->next == NULL) { + HeaderArray *block = malloc(sizeof(HeaderArray)); + block->next = NULL; + block->len = 0; + block->headers = calloc(16, sizeof(Header)); + block->alloc = 16; + hd->next = block; + } + hd = hd->next; + } + hd->headers[hd->len].name = name; + hd->headers[hd->len].value = value; + hd->len++; +} + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/httprequest.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/httprequest.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,93 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTTPREQUEST_H +#define HTTPREQUEST_H + +#include "sstring.h" +#include "sessionhandler.h" +#include "nsapi.h" +#include "pool.h" +#include "session.h" +#include "sstring.h" +#include "request.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _http_request HTTPRequest; +typedef struct _header Header; +typedef struct _header_array HeaderArray; + +struct _http_request { + Connection *connection; + sstr_t request_line; + sstr_t method; + sstr_t uri; + sstr_t httpv; + HeaderArray *headers; + netbuf *netbuf; + NSAPISession *sn; + NSAPIRequest *rq; + pool_handle_t *pool; +}; + +struct _header { + char *name; + char *value; +}; + +struct _header_array { + HeaderArray *next; + Header *headers; + int len; + int alloc; +}; + +HTTPRequest *http_request_new(); + +int handle_request(HTTPRequest *request); + + + +void header_add(HeaderArray *hd, char *name, char *value); + + +/* request.h functions */ +int request_initialize( + pool_handle_t *pool, + HTTPRequest *hrq, + NSAPIRequest *nrq); + +#ifdef __cplusplus +} +#endif + +#endif /* HTTPREQUEST_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/io.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/io.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,53 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "io.h" + +IOStream native_io_funcs = { + system_write, + system_read +}; + + +IOStream* stream_new_from_fd(int fd) { + SystemIOStream *st = malloc(sizeof(SystemIOStream)); + st->st = native_io_funcs; + st->fd = fd; + return (IOStream*)st; +} + +ssize_t system_write(IOStream *st, void *buf, size_t nbytes) { + return write(((SystemIOStream*)st)->fd, buf, nbytes); +} + +ssize_t system_read(IOStream *st, void *buf, size_t nbytes) { + return read(((SystemIOStream*)st)->fd, buf, nbytes); +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/io.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/io.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,63 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IOSTREAM_H +#define IOSTREAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct io_stream IOStream; + +typedef ssize_t(*io_write_f)(IOStream *, void *, size_t); +typedef ssize_t(*io_read_f)(IOStream *, void *, size_t); + +struct io_stream { + io_write_f write; + io_read_f read; +}; + +typedef struct SystemIOStream { + IOStream st; + int fd; +} SystemIOStream; + + +IOStream* stream_new_from_fd(int fd); + + +ssize_t system_write(IOStream *st, void *buf, size_t nbytes); +ssize_t system_read(IOStream *st, void *buf, size_t nbytes); + +#ifdef __cplusplus +} +#endif + +#endif /* IOSTREAM_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/list.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/list.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,175 @@ +/* + * File: list.c + * Author: olaf + * + * Created on 18. Dezember 2010, 11:23 + */ + +#include +#include + +#include "list.h" + +/* add functions */ +sdlist_t* sdlist_add(sdlist_t *list, void *data) { + sdlist_t *elm = malloc(sizeof(sdlist_t)); + elm->data = data; + elm->next = NULL; + + return sdlist_addl(list, elm); +} + +sdlist_t* sdlist_addl(sdlist_t *list, sdlist_t *l) { + if (list != NULL) { + sdlist_t *end = sdlist_getlast(list); + end->next = l; + return list; + } else { + return l; + } +} + + + +/* remove functions */ +sdlist_t* sdlist_remove(sdlist_t *list, void *data) { + sdlist_t *s = list; + + sdlist_t *prev = NULL; + while (list != NULL) { + if (list->data == data) { + sdlist_t *nl = sdlist_remove_elm(s, prev, list); + free(list); + return nl; + } + + prev = list; + list = list->next; + } + + return s; +} + +sdlist_t* sdlist_removei(sdlist_t *list, int index) { + sdlist_t *s = list; + + sdlist_t *prev = NULL; + int i = 0; + while (list != NULL) { + if (i == index) { + sdlist_t *nl = sdlist_remove_elm(s, prev, list); + free(list); + return nl; + } + + prev = list; + list = list->next; + i++; + } + + return s; +} + +sdlist_t* sdlist_removel(sdlist_t *list, sdlist_t *l) { + sdlist_t *s = list; + + sdlist_t *prev = NULL; + while (list != NULL) { + if (list == l) { + return sdlist_remove_elm(s, prev, list); + } + + prev = list; + list = list->next; + } + + return s; +} + + +sdlist_t *sdlist_remove_elm(sdlist_t *list, sdlist_t *prev, sdlist_t *elm) { + if (elm == NULL) { + return list; + } + + if (prev == NULL) { + return elm->next; + } + + prev->next = elm->next; + + return list; +} + + + +/* insert functions */ +void sdlist_insert(sdlist_t *elm, void *data) { + sdlist_t *newelm = malloc(sizeof(sdlist_t)); + newelm->data = data; + sdlist_insertl(elm, newelm); +} + +void sdlist_insertl(sdlist_t *elm, sdlist_t *l) { + if (elm == NULL || l == NULL) { + return; + } + + l->next = elm->next; + elm->next = l; +} + + +/* get functions */ +sdlist_t* sdlist_get(sdlist_t *list, void *data) { + while (list != NULL) { + if (list->data == data) { + return list; + } + list = list->next; + } + return NULL; +} + +sdlist_t* sdlist_geti(sdlist_t *list, int index) { + for (int i=0;inext; + } + return list; +} + +sdlist_t* sdlist_getlast(sdlist_t *list) { + while(list->next != NULL) { + list = list->next; + } + return list; +} + + + +/* miscellaneous functions */ +size_t sdlist_length(sdlist_t *list) { + int i = 0; + while(list->next != NULL) { + list = list->next; + i++; + } + return i; +} + +void sdlist_free(sdlist_t *elm) { + free(elm); +} + +void sdlist_foreach(sdlist_t *list, sdlist_iterator_func f, void *data) { + while(list != NULL) { + int r = f(list, data); + if (r) { + return; + } + list = list->next; + } +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/list.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/list.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,106 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LIST_H +#define LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _util_slist sdlist_t; + +struct _util_slist { + void *data; + sdlist_t *next; +}; + +typedef int (*sdlist_iterator_func)(sdlist_t*, void*); + + +/* single linked list */ + +/* + * sdlist_add/sdllist_addl + * + * append to the end of the list one element + */ +sdlist_t* sdlist_add(sdlist_t *list, void *data); +sdlist_t* sdlist_addl(sdlist_t *list, sdlist_t *l); + +/* + * sdlist_remove/sdlist_removei + * + * remove one element from the list and free the sdlist_t object + * returns the first element of the new list + */ +sdlist_t* sdlist_remove(sdlist_t *list, void *data); +sdlist_t* sdlist_removei(sdlist_t *list, int index); + +/* + * sdlist_removel + * + * remove element l from the list + * returns the first element of the new list + */ +sdlist_t* sdlist_removel(sdlist_t *list, sdlist_t *l); + +/* + * removes one element from the list + * + * list: list + * prev: previous to elm + * elm: element which should be removed + * + * returns the first element of the new list + */ +sdlist_t *sdlist_remove_elm(sdlist_t *list, sdlist_t *prev, sdlist_t *elm); + + +/* + * sdlist_insert + * + * insert one element after the element elm + */ +void sdlist_insert(sdlist_t *elm, void *data); +void sdlist_insertl(sdlist_t *elm, sdlist_t *l); + +sdlist_t* sdlist_get(sdlist_t *list, void *data); +sdlist_t* sdlist_geti(sdlist_t *list, int index); +sdlist_t* sdlist_getlast(sdlist_t *list); + +size_t sdlist_length(sdlist_t *list); +void sdlist_free(sdlist_t *elm); +void sdlist_foreach(sdlist_t *list, sdlist_iterator_func f, void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* LIST_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/main.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,67 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include + +#include "pool.h" +#include "nsapi.h" +#include "plist.h" + +#include "webserver.h" + +#include "httprequest.h" + +void test() { + exit(0); +} + +int main(int argc, char **argv) { + //test(); + + pool_init(NULL, NULL, NULL); + + int status; + status = webserver_init(); + if(status != 0) { + fprintf(stderr, "Cannot initialize server!\n"); + return EXIT_FAILURE; + } + + status = webserver_run(); + if(status != 0) { + fprintf(stderr, "Cannot run server!\n"); + return EXIT_FAILURE; + } + + getchar(); + + return EXIT_SUCCESS; +} + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/map.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/map.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,134 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "map.h" + +hashmap_t* hashmap_new(size_t size) { + hashmap_t *map = malloc(sizeof(hashmap_t)); + map->map = calloc(size, sizeof(sdlist_t)); + map->len = size; + + return map; +} + +void hashmap_free(hashmap_t *map) { + for(int i=0;ilen;i++) { + sdlist_t *list = map->map[0]; + while(list != NULL) { + hashmap_elm_t *elm = (hashmap_elm_t*)list->data; + free(elm->key.ptr); + sdlist_t *l = list; + list = list->next; + free(elm); + free(l); + } + } + free(map->map); + free(map); +} + + +void hashmap_put(hashmap_t *map, sstr_t key, void *value) { + int hash = hashmap_hash(key.ptr, key.length); + + sdlist_t *list = map->map[hash%map->len]; + + sstr_t k = sstrdub(key); + + hashmap_elm_t *elm = malloc(sizeof(hashmap_elm_t)); + elm->data = value; + elm->hash = hash; + elm->key = k; + + map->map[hash%map->len] = sdlist_add(list, elm); +} + +void* hashmap_get(hashmap_t *map, sstr_t key) { + int hash = hashmap_hash(key.ptr, key.length); + sdlist_t *list = map->map[hash%map->len]; + void *value = NULL; + + while (list != NULL) { + hashmap_elm_t *elm = list->data; + if (elm->hash == hash && + strncmp(key.ptr, elm->key.ptr, key.length) == 0) { + value = elm->data; + break; + } + list = list->next; + } + + return value; +} + + + + +/* hash function */ +int hashmap_hash(char *data, size_t len) { + /* murmur hash 2 */ + + int m = 0x5bd1e995; + int r = 24; + + int h = 25 ^ len; + + int i = 0; + while (len >= 4) { + int k = data[i + 0] & 0xFF; + k |= (data[i + 1] & 0xFF) << 8; + k |= (data[i + 2] & 0xFF) << 16; + k |= (data[i + 3] & 0xFF) << 24; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + i += 4; + len -= 4; + } + + switch (len) { + case 3: h ^= (data[i + 2] & 0xFF) << 16; + case 2: h ^= (data[i + 1] & 0xFF) << 8; + case 1: h ^= (data[i + 0] & 0xFF); h *= m; + } + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/map.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,64 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MAP_H +#define MAP_H + +#include "list.h" +#include "sstring.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _hashmap_elm { + int hash; + sstr_t key; + + void *data; +} hashmap_elm_t; + +typedef struct _util_hashmap { + sdlist_t **map; + size_t len; +} hashmap_t; + +hashmap_t* hashmap_new(size_t size); +void hashmap_free(hashmap_t *map); + +void hashmap_put(hashmap_t *map, sstr_t key, void *value); +void* hashmap_get(hashmap_t *map, sstr_t key); + +int hashmap_hash(char *data, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* MAP_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/netsite.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/netsite.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,173 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NETSITE_H +#define NETSITE_H + +#ifndef NOINTNSAPI +#define INTNSAPI +#endif /* !NOINTNSAPI */ + +/* + * Standard defs for NetSite servers. + */ + +#include + +#ifndef BASE_SYSTEMS_H +#include "systems.h" +#endif /* !BASE_SYSTEMS_H */ + + + +#define MAGNUS_VERSION_STRING INTsystem_version() +#define MAGNUS_VERSION PRODUCT_VERSION_ID + +/* Include the public nsapi.h definitions */ +#ifndef PUBLIC_NETSITE_H +#include "nsapi.h" +#endif /* PUBLIC_NETSITE_H */ + +NSPR_BEGIN_EXTERN_C + +/* + * Only the mainline needs to set the malloc key. + */ + +NSAPI_PUBLIC void InitThreadMallocKey(void); + +NSAPI_PUBLIC void system_set_temp_dir(const char *dir); + +NSAPI_PUBLIC const char *system_get_temp_dir(void); + +/* This probably belongs somewhere else, perhaps with a different name */ +NSAPI_PUBLIC char *INTdns_guess_domain(char * hname); + +/* --- Begin public functions --- */ + +#ifdef INTNSAPI + +NSAPI_PUBLIC char *INTsystem_version(void); + +/* + Depending on the system, memory allocated via these macros may come from + an arena. If these functions are called from within an Init function, they + will be allocated from permanent storage. Otherwise, they will be freed + when the current request is finished. + */ + +#define MALLOC(size) INTsystem_malloc(size) +NSAPI_PUBLIC void *INTsystem_malloc(int size); + +#define CALLOC(size) INTsystem_calloc(size) +NSAPI_PUBLIC void *INTsystem_calloc(int size); + +#define REALLOC(ptr, size) INTsystem_realloc(ptr, size) +NSAPI_PUBLIC void *INTsystem_realloc(void *ptr, int size); + +#define FREE(ptr) INTsystem_free(ptr) +NSAPI_PUBLIC void INTsystem_free(void *ptr); + +#define STRDUP(ptr) INTsystem_strdup(ptr) +NSAPI_PUBLIC char *INTsystem_strdup(const char *ptr); + +/* + These macros always provide permanent storage, for use in global variables + and such. They are checked at runtime to prevent them from returning NULL. + */ + +#define PERM_MALLOC(size) INTsystem_malloc_perm(size) +NSAPI_PUBLIC void *INTsystem_malloc_perm(int size); + +#define PERM_CALLOC(size) INTsystem_calloc_perm(size) +NSAPI_PUBLIC void *INTsystem_calloc_perm(int size); + +#define PERM_REALLOC(ptr, size) INTsystem_realloc_perm(ptr, size) +NSAPI_PUBLIC void *INTsystem_realloc_perm(void *ptr, int size); + +#define PERM_FREE(ptr) INTsystem_free_perm(ptr) +NSAPI_PUBLIC void INTsystem_free_perm(void *ptr); + +#define PERM_STRDUP(ptr) INTsystem_strdup_perm(ptr) +NSAPI_PUBLIC char *INTsystem_strdup_perm(const char *ptr); + +/* Thread-Private data key index for accessing the thread-private memory pool. + * Each thread creates its own pool for allocating data. The MALLOC/FREE/etc + * macros have been defined to check the thread private data area with the + * thread_malloc_key index to find the address for the pool currently in use. + * + * If a thread wants to use a different pool, it must change the thread-local- + * storage[thread_malloc_key]. + */ + +NSAPI_PUBLIC int INTgetThreadMallocKey(void); + +NSAPI_PUBLIC pool_handle_t *INTsystem_pool(void); + +/* Not sure where to put this. */ +NSAPI_PUBLIC void INTmagnus_atrestart(void (*fn)(void *), void *data); + +NSAPI_PUBLIC void INTsystem_setnewhandler(void); + +#endif /* INTNSAPI */ + +/* --- End public functions --- */ + +NSPR_END_EXTERN_C + +#ifdef INTNSAPI + +#define dns_guess_domain INTdns_guess_domain +//define system_version INTsystem_version +#define system_malloc INTsystem_malloc +#define system_calloc INTsystem_calloc +#define system_realloc INTsystem_realloc +#define system_free INTsystem_free +#define system_strdup INTsystem_strdup +#define system_malloc_perm INTsystem_malloc_perm +#define system_calloc_perm INTsystem_calloc_perm +#define system_realloc_perm INTsystem_realloc_perm +#define system_free_perm INTsystem_free_perm +#define system_strdup_perm INTsystem_strdup_perm +#define getThreadMallocKey INTgetThreadMallocKey +#define system_pool INTsystem_pool +#define magnus_atrestart INTmagnus_atrestart +#define system_setnewhandler INTsystem_setnewhandler + +#endif /* INTNSAPI */ + +#ifndef HTTPS_ADMSERV +#define HTTPS_ADMSERV "https-admserv" +#endif + +#endif /* NETSITE_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/nsapi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/nsapi.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,1656 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PUBLIC_NSAPI_H +#define PUBLIC_NSAPI_H + +/* + * File: nsapi.h + * + * Description: + * + * This file defines an interface for extending the server with + * in-process plug-ins. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* NSAPI version defined by this header file */ +#define NSAPI_VERSION 303 + +/* Define USE_NSAPI_VERSION to use a specific NSAPI version at compile time */ +#ifdef USE_NSAPI_VERSION +#if USE_NSAPI_VERSION < 300 || USE_NSAPI_VERSION > NSAPI_VERSION +#error This header file does not support the requested NSAPI version +#else +#undef NSAPI_VERSION +#define NSAPI_VERSION USE_NSAPI_VERSION +#endif +#endif + +/* --- Begin native platform configuration definitions --- */ + +#if !defined(XP_WIN32) && !defined(XP_UNIX) +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#define XP_WIN32 +#else +#define XP_UNIX +#endif +#endif + +#ifdef XP_UNIX +#define NSAPI_PUBLIC +#define ZERO(ptr, len) memset(ptr, 0, len) +#ifdef AIX +#define TCPLEN_T size_t +#endif +#ifdef HPUX +#define TCPLEN_T int +#endif +#ifndef TCPLEN_T +#define TCPLEN_T socklen_t +#endif +#endif /* XP_UNIX */ + +#ifdef XP_WIN32 +#define NSAPI_PUBLIC __declspec(dllexport) +struct iovec { + char *iov_base; + unsigned iov_len; +}; +#ifndef S_ISDIR +#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR) +#endif +#ifndef S_ISREG +#define S_ISREG(mode) ((mode & S_IFMT) == S_IFREG) +#endif +#ifndef S_ISLNK +#define S_ISLNK(x) (0) +#endif +#define caddr_t PCHAR +#define NEED_STRCASECMP +#define NEED_STRNCASECMP +#define ZERO(ptr, len) ZeroMemory(ptr, len) +#define TCPLEN_T int +#endif /* XP_WIN32 */ + +/* --- End native platform configuration definitions --- */ + +/* --- Begin miscellaneous definitions --- */ + +/* Used in some places as a length limit on error messages */ +#define MAGNUS_ERROR_LEN 1024 + +/* Carriage return and line feed */ +#define CR 13 +#define LF 10 +#ifdef XP_WIN32 +#define ENDLINE "\r\n" +#else +#define ENDLINE "\n" +#endif + +/* mime.types file identification line */ +#define NCC_MT_MAGIC "#--Netscape Communications Corporation MIME Information" +#define NCC_MT_MAGIC_LEN 55 + +/* The character which separates extensions with cinfo_find */ +#define CINFO_SEPARATOR '.' + +/* The maximum length of a line in a mime.types file */ +#define CINFO_MAX_LEN 1024 + +/* The maximum length of an error message */ +#define MAX_ERROR_LEN 4096 + +/* + * A warning is a minor mishap, such as a 404 being issued. + */ +#define LOG_WARN 0 + +/* + * A misconfig is when there is a syntax error or permission violation in + * a config file. + */ +#define LOG_MISCONFIG 1 + +/* + * Security warnings are issued when authentication fails, or a host is + * given a 403 return code. + */ +#define LOG_SECURITY 2 + +/* + * A failure is when a request could not be fulfilled due to an internal + * problem, such as a CGI script exiting prematurely, or a filesystem + * permissions problem. + */ +#define LOG_FAILURE 3 + +/* + * A catastrophe is a fatal server error such as running out of + * memory or processes, or a system call failing, or even a server crash. + * The server child cannot recover from a catastrophe. + */ +#define LOG_CATASTROPHE 4 + +/* + * Informational message, of no concern. + */ +#define LOG_INFORM 5 + +/* + * Internal diagnostic message. + */ +#define LOG_VERBOSE 6 + +/* + * The time format to use in the error log + */ +#define ERR_TIMEFMT "[%d/%b/%Y:%H:%M:%S]" + + +/* The fd you will get if you are reporting errors to SYSLOG */ +#define ERRORS_TO_SYSLOG NULL + +/* Return codes from file I/O routines */ +#define IO_OKAY 1 +#define IO_ERROR -1 +#define IO_EOF 0 +#define NETBUF_EOF -1 +#define NETBUF_ERROR -2 +#define NETBUF_FULL -3 + +/* The disk page size on this machine. */ +#define FILE_BUFFERSIZE 4096 + +#ifdef XP_UNIX + +#define FILE_PATHSEP '/' +#define FILE_PARENT "../" + +#elif defined(XP_WIN32) + +#define FILE_PATHSEP '/' +#define FILE_PARENT "..\\" + +#endif /* XP_WIN32 */ + +#define NET_INFINITE_TIMEOUT 0 +#define NET_ZERO_TIMEOUT -1 + +#ifdef USE_REGEX +/* WILDPAT uses regular expressions */ +#define WILDPAT_VALID(exp) regexp_valid(exp) +#define WILDPAT_MATCH(str, exp) regexp_match(str, exp) +#define WILDPAT_CMP(str, exp) regexp_cmp(str, exp) +#define WILDPAT_CASECMP(str, exp) regexp_casecmp(str, exp) +#define WILDPAT_USES_REGEXP 1 +#else +/* WILDPAT uses shell expressions */ +#define WILDPAT_VALID(exp) shexp_valid(exp) +#define WILDPAT_MATCH(str, exp) shexp_match(str, exp) +#define WILDPAT_CMP(str, exp) shexp_cmp(str, exp) +#define WILDPAT_CASECMP(str, exp) shexp_casecmp(str, exp) +#define WILDPAT_USES_SHEXP 1 +#endif + +/* Define return codes from WILDPAT_VALID */ +#define NON_WILDPAT -1 /* exp is ordinary string */ +#define INVALID_WILDPAT -2 /* exp is an invalid pattern */ +#define VALID_WILDPAT 1 /* exp is a valid pattern */ + +/* Define return codes from regexp_valid and shexp_valid */ +#define NON_SXP NON_WILDPAT /* exp is an ordinary string */ +#define INVALID_SXP INVALID_WILDPAT /* exp is an invalid shell exp */ +#define VALID_SXP VALID_WILDPAT /* exp is a valid shell exp */ + +#define NON_REGEXP NON_SXP +#define INVALID_REGEXP INVALID_SXP +#define VALID_REGEXP VALID_SXP + +#define SYSTHREAD_DEFAULT_PRIORITY 16 + +/* The longest line in the configuration file */ +#define CONF_MAXLEN 16384 + +#define HTTP_DATE_LEN 30 +#define HTTP_DATE_FMT "%a, %d %b %Y %T GMT" + +/* HTTP status codes */ +#define PROTOCOL_CONTINUE 100 +#define PROTOCOL_SWITCHING 101 +#define PROTOCOL_OK 200 +#define PROTOCOL_CREATED 201 +#define PROTOCOL_ACCEPTED 202 +#define PROTOCOL_NONAUTHORITATIVE 203 +#define PROTOCOL_NO_RESPONSE 204 +#define PROTOCOL_NO_CONTENT 204 +#define PROTOCOL_RESET_CONTENT 205 +#define PROTOCOL_PARTIAL_CONTENT 206 +#define PROTOCOL_MULTI_STATUS 207 +#define PROTOCOL_MULTIPLE_CHOICES 300 +#define PROTOCOL_MOVED_PERMANENTLY 301 +#define PROTOCOL_REDIRECT 302 +#define PROTOCOL_SEE_OTHER 303 +#define PROTOCOL_NOT_MODIFIED 304 +#define PROTOCOL_USE_PROXY 305 +#define PROTOCOL_TEMPORARY_REDIRECT 307 +#define PROTOCOL_BAD_REQUEST 400 +#define PROTOCOL_UNAUTHORIZED 401 +#define PROTOCOL_PAYMENT_REQUIRED 402 +#define PROTOCOL_FORBIDDEN 403 +#define PROTOCOL_NOT_FOUND 404 +#define PROTOCOL_METHOD_NOT_ALLOWED 405 +#define PROTOCOL_NOT_ACCEPTABLE 406 +#define PROTOCOL_PROXY_UNAUTHORIZED 407 +#define PROTOCOL_REQUEST_TIMEOUT 408 +#define PROTOCOL_CONFLICT 409 +#define PROTOCOL_GONE 410 +#define PROTOCOL_LENGTH_REQUIRED 411 +#define PROTOCOL_PRECONDITION_FAIL 412 +#define PROTOCOL_ENTITY_TOO_LARGE 413 +#define PROTOCOL_URI_TOO_LARGE 414 +#define PROTOCOL_UNSUPPORTED_MEDIA_TYPE 415 +#define PROTOCOL_REQUESTED_RANGE_NOT_SATISFIABLE 416 +#define PROTOCOL_EXPECTATION_FAILED 417 +#define PROTOCOL_LOCKED 423 +#define PROTOCOL_FAILED_DEPENDENCY 424 +#define PROTOCOL_SERVER_ERROR 500 +#define PROTOCOL_NOT_IMPLEMENTED 501 +#define PROTOCOL_BAD_GATEWAY 502 +#define PROTOCOL_SERVICE_UNAVAILABLE 503 +#define PROTOCOL_GATEWAY_TIMEOUT 504 +#define PROTOCOL_VERSION_NOT_SUPPORTED 505 +#define PROTOCOL_INSUFFICIENT_STORAGE 507 + +#define PROTOCOL_VERSION_HTTP09 9 +#define PROTOCOL_VERSION_HTTP10 100 +#define PROTOCOL_VERSION_HTTP11 101 +#define CURRENT_PROTOCOL_VERSION PROTOCOL_VERSION_HTTP11 + +/* Definitions for HTTP over SSL */ +#define HTTPS_PORT 443 +#define HTTPS_URL "https" + +/* Definitions for HTTP over TCP */ +#define HTTP_PORT 80 +#define HTTP_URL "http" + + +#define REQ_MAX_LINE 4096 + +/* + * The REQ_ return codes. These codes are used to determine what the server + * should do after a particular module completes its task. + * + * Func type functions return these as do many internal functions. + */ + +/* The function performed its task, proceed with the request */ +#define REQ_PROCEED 0 +/* The entire request should be aborted: An error occurred */ +#define REQ_ABORTED -1 +/* The function performed no task, but proceed anyway */ +#define REQ_NOACTION -2 +/* Tear down the session and exit */ +#define REQ_EXIT -3 +/* Restart the entire request-response process */ +#define REQ_RESTART -4 +/* Too busy to execute this now */ +#define REQ_TOOBUSY -5 + +/* --- End miscellaneous definitions --- */ + +/* --- Begin native platform includes --- */ + +#ifdef XP_UNIX +#include +#include +#ifndef HPUX +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* XP_UNIX */ + +#ifdef XP_WIN32 +#include +#include +#include +#include +#endif /* XP_WIN32 */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* --- End native platform includes --- */ + +/* --- Begin type definitions --- */ + +/* NOTE: both SYS_FILE and SYS_NETFD are actually NSPR PRFileDesc * and can */ +/* be used with NSPR API calls (after casting them to PRFileDesc *) */ + +#ifndef SYS_FILE_T +typedef void *SYS_FILE; +#define SYS_FILE_T void * +#endif /* !SYS_FILE_T */ + +#define SYS_ERROR_FD ((SYS_FILE)-1) + +#ifndef SYS_NETFD_T +typedef void *SYS_NETFD; +#define SYS_NETFD_T void * +#endif /* !SYS_NETFD_T */ + +/* Error value for a SYS_NETFD */ +#ifndef SYS_NET_ERRORFD +#define SYS_NET_ERRORFD ((SYS_NETFD)-1) +#endif /* !SYS_NET_ERRORFD */ + +/* + * These structures were originally defined in nsapi.h, but those definitions + * were removed in iPlanet Web Server 4.0. The contents of these structures + * are now private to the server implementation and must not be accessed + * directly. Instead, use the objset_*, object_*, directive_table_*, and + * directive_* accessor functions. + */ +typedef struct directive directive; +typedef struct dtable dtable; +typedef struct httpd_object httpd_object; +typedef struct httpd_objset httpd_objset; + +/* + * Type: filebuffer, filebuf_t + * + * Description: + * + * This structure is used to represent a buffered file. On some + * systems the file may be memory-mapped. A filebuffer is created + * by filebuf_open(), and destroyed by filebuf_close(). + * + * Notes: + * + * Direct access to the members of this structure, not using + * macros defined here, is discouraged. + * + * The filebuf alias that used to be defined for this type was + * found to conflict with a C++ class of the same name, so it + * has been renamed to filebuf_t. + */ +typedef struct filebuffer filebuffer; + +/* Version of filebuffer when memory-mapped files are supported */ +struct filebuffer { + SYS_FILE fd; +#ifdef XP_WIN32 + HANDLE fdmap; +#endif + caddr_t fp; + int len; + + unsigned char *inbuf; + int cursize; + + int pos; + const char *errmsg; +}; + +/* Return next character or IO_EOF */ +#define filebuf_getc(b) ((b)->pos == (b)->len ? IO_EOF : (int)((b)->fp)[(b)->pos++]) + +#define filebuf_iseof(b) ((b)->pos == (b)->len) + +/* C++ streamio defines a filebuf class. */ +typedef filebuffer filebuf_t; + +#ifdef XP_WIN32 +/* Use a filebuffer to read data from a pipe */ +#define pipebuf_getc(b) \ + ((b)->pos != (b)->cursize ? (int)((b)->inbuf[(b)->pos++]) : pipebuf_next(b,1)) +#endif /* XP_WIN32 */ + +/* + * Type: netbuf + * + * Description: + * + * This structure is used to represent a buffered network socket. + * It is created by netbuf_open(), and destroyed by netbuf_close(). + * + * Notes: + * + * Direct access to the members of this structure, not using + * macros defined here, is discouraged. + * + * The inbuf field used to be (unsigned char *), but is now + * simply (char *). The value returned by the netbuf_getc() + * macro is (int). + */ +typedef struct netbuf netbuf; +struct netbuf { + SYS_NETFD sd; + + int pos, cursize, maxsize, rdtimeout; +#ifdef XP_WIN32 + CHAR address[64]; +#endif /* XP_WIN32 */ + unsigned char *inbuf; + char *errmsg; +#ifndef XP_WIN32 + char address[64]; +#endif /* !XP_WIN32 */ +}; + +/* + * netbuf_getc gets a character from the given network buffer and returns + * it (as an integer). + * + * It will return (int) IO_ERROR for an error and (int) IO_EOF for + * an error condition or EOF respectively. + */ +#define netbuf_getc(b) \ + ((b)->pos != (b)->cursize ? (int)((b)->inbuf[(b)->pos++]) : netbuf_next(b,1)) + +/* + * buffer_error returns the last error that occurred with buffer. Don't use + * this unless you know an error occurred. Independent of network/file type. + */ +#define buffer_error(b) ((b)->errmsg) + +/* + * Type: sendfiledata + * + * Description: + * + * This structure is used to pass arguments to the net_sendfile() + * function. offset and len may be set to 0 to transmit a file in its + * entirety. + */ +typedef struct sendfiledata sendfiledata; +struct sendfiledata { + SYS_FILE fd; /* file to send */ + size_t offset; /* offset in file to start sending from */ + size_t len; /* number of bytes to send from file */ + const void *header; /* data to send before file */ + int hlen; /* number of bytes to send before file */ + const void *trailer; /* data to send after file */ + int tlen; /* number of bytes to send after file */ +}; + +/* + * Type: NSAPIIOVec + * + * Description: + * + * This structure is used to pass arguments to the net_writev() + * and FilterWritevFunc() functions. + */ +#ifdef _LP64 +typedef struct NSAPIIOVec NSAPIIOVec; +struct NSAPIIOVec { + char *iov_base; + int iov_len; +}; +#else +typedef struct iovec NSAPIIOVec; +#endif /* _LP64 */ + + +/* + * Type: cinfo + * + * Description: + * + * This is a structure that captures the information in the name/value + * pairs on one line of a mime.types file. A cinfo structure is + * stored in the memory-resident database, indexed by each of the + * file extensions specified in the "exts" name/value pair. It + * defines various attributes of resources with names containing + * the specified file extensions. + * + * Notes: + * + * Pointers to cinfo structures returned by this API may or may not + * need to freed by the caller. See the individual function + * descriptions. + * + * The strings referenced by the fields of cinfo structures returned + * by this API should be considered read-only, and do not need to be + * freed by the caller, even when the cinfo structure does. + */ +typedef struct cinfo cinfo; +struct cinfo { + char *type; + char *encoding; + char *language; +}; + + +typedef void* CONDVAR; +typedef void *COUNTING_SEMAPHORE; +typedef void* CRITICAL; + +#ifdef XP_UNIX +typedef DIR* SYS_DIR; +typedef struct dirent SYS_DIRENT; +#endif /* XP_UNIX */ + +#ifdef XP_WIN32 + +typedef struct dirent_s dirent_s; +struct dirent_s { + char *d_name; +}; + +typedef struct dir_s dir_s; +struct dir_s { + HANDLE dp; + WIN32_FIND_DATA fdata; + dirent_s de; +}; + +typedef dir_s* SYS_DIR; +typedef dirent_s SYS_DIRENT; + +#endif /* XP_WIN32 */ + +typedef struct pb_param pb_param; +struct pb_param { + char *name,*value; +}; + +typedef struct pb_entry pb_entry; +struct pb_entry { + pb_param *param; + struct pb_entry *next; +}; + +typedef struct pblock pblock; +struct pblock { + int hsize; + struct pb_entry **ht; +}; + +#ifndef POOL_HANDLE_T +#define POOL_HANDLE_T +typedef void *pool_handle_t; +#endif + +#ifndef SEMAPHORE_T +typedef void *SEMAPHORE; +#define SEMAPHORE_T void * +#endif /* !SEMAPHORE_T */ + +#define SESSION_HASHSIZE 5 + +typedef struct PListStruct_s PListStruct_s; +typedef struct ACLListHandle ACLListHandle; + +#ifndef PR_AF_INET +typedef union PRNetAddr PRNetAddr; +#endif + +typedef struct Session Session; +typedef struct Request Request; +struct Session { + pblock *client; /* client-specific information */ + + SYS_NETFD csd; /* client file descriptor */ + netbuf *inbuf; /* input buffer */ + int csd_open; + + struct in_addr iaddr; + + pool_handle_t *pool; + + void *clauth; /* v2 ACL client authentication information */ + struct Session *next; + int fill; + struct sockaddr_in local_addr; /* local addr for this session */ + + PListStruct_s *subject; + int ssl; /* 0 = SSL OFF, 1 = SSL ON */ + int clientauth; /* 0 = client auth OFF, 1 = client auth ON */ + + PRNetAddr *pr_client_addr; + PRNetAddr *pr_local_addr; +}; + +/* + * FuncPtr is a pointer to an NSAPI SAF function + */ + +#ifdef XP_UNIX +typedef int Func(pblock *, Session *, Request *); +#else /* XP_WIN32 */ +typedef int _cdecl Func(pblock *, Session *, Request *); +#endif /* XP_WIN32 */ + +typedef Func *FuncPtr; + +/* + * FuncStruct is a structure used in the static declaration of the + * functions. This static declaration is parsed into a hash table at + * startup. + */ + +typedef struct FuncStruct FuncStruct; + +struct FuncStruct { + const char * name; + FuncPtr func; + struct FuncStruct *next; + unsigned flags; + unsigned poolID; + unsigned pool_resolved; +}; + +/* + * VSInitFunc, VSDestroyFunc, VSDirectiveInitFunc and VSDirectiveDestroyFunc + */ +typedef struct VirtualServer VirtualServer; +typedef int VSInitFunc(VirtualServer *incoming, const VirtualServer *current); +typedef void VSDestroyFunc(VirtualServer *outgoing); +typedef VSInitFunc *VSInitFuncPtr; +typedef VSDestroyFunc *VSDestroyFuncPtr; +typedef int VSDirectiveInitFunc(const directive *dir, VirtualServer *incoming, const VirtualServer *current); +typedef void VSDirectiveDestroyFunc(const directive *dir, VirtualServer *outgoing); +typedef VSDirectiveInitFunc *VSDirectiveInitFuncPtr; +typedef VSDirectiveDestroyFunc *VSDirectiveDestroyFuncPtr; + +/* + * Filter is an opaque filter identifier + */ +typedef struct Filter Filter; + +/* + * FilterContext stores context associated with a particular filter layer + */ + +typedef struct FilterContext FilterContext; + +struct FilterContext { + pool_handle_t *pool; /* pool context was allocated from */ + Session *sn; /* session being processed */ + Request *rq; /* request being processed */ + void *data; /* filter-defined private data */ +}; + +/* + * FilterLayer represents one layer of a filter stack + */ + +typedef struct FilterLayer FilterLayer; + +struct FilterLayer { + Filter *filter; /* the filter at this layer in the filter stack */ + FilterContext *context; /* context for the filter */ + SYS_NETFD lower; /* access to the next filter layer in the stack */ +}; + +/* + * Function prototypes for filter methods + */ +typedef int (FilterInsertFunc)(FilterLayer *layer, pblock *pb); +typedef void (FilterRemoveFunc)(FilterLayer *layer); +typedef int (FilterFlushFunc)(FilterLayer *layer); +typedef int (FilterReadFunc)(FilterLayer *layer, void *buf, int amount, int timeout); +typedef int (FilterWriteFunc)(FilterLayer *layer, const void *buf, int amount); +typedef int (FilterWritevFunc)(FilterLayer *layer, const NSAPIIOVec *iov, int iov_size); +typedef int (FilterSendfileFunc)(FilterLayer *layer, sendfiledata *sfd); + +/* + * FilterMethods is passed to filter_create() to declare the filter methods for + * a new filter. Each instance of the FilterMethods structure should be + * initialized using the FILTER_METHODS_INITIALIZER macro. + */ + +typedef struct FilterMethods FilterMethods; + +struct FilterMethods { + size_t size; +#if NSAPI_VERSION >= 302 + FilterInsertFunc *insert; + FilterRemoveFunc *remove; + FilterFlushFunc *flush; + FilterReadFunc *read; + FilterWriteFunc *write; + FilterWritevFunc *writev; + FilterSendfileFunc *sendfile; +#else + void *reserved1; + void *reserved2; + void *reserved3; + void *reserved4; + void *reserved5; + void *reserved6; + void *reserved7; +#endif /* NSAPI_VERSION >= 302 */ +}; + +#define FILTER_METHODS_INITIALIZER \ +{ \ + sizeof(FilterMethods), \ + NULL, /* insert */ \ + NULL, /* remove */ \ + NULL, /* flush */ \ + NULL, /* read */ \ + NULL, /* write */ \ + NULL, /* writev */ \ + NULL /* sendfile */ \ +} + +/* + * Filter order definitions for filter_create() + */ +#define FILTER_CONTENT_GENERATION 0xf0000 +#define FILTER_CONTENT_TRANSLATION_HIGH 0xa0000 +#define FILTER_CONTENT_TRANSLATION 0x90000 +#define FILTER_CONTENT_TRANSLATION_LOW 0x80000 +#define FILTER_CONTENT_CODING 0x50000 +#define FILTER_TRANSFER_CODING 0x40000 +#define FILTER_MESSAGE_CODING 0x30000 +#define FILTER_TRANSPORT_CODING 0x20000 +#define FILTER_NETWORK 0x10000 + +typedef struct shmem_s shmem_s; +struct shmem_s { + void *data; /* the data */ +#ifdef XP_WIN32 + HANDLE fdmap; +#endif /* XP_WIN32 */ + int size; /* the maximum length of the data */ + + char *name; /* internal use: filename to unlink if exposed */ + SYS_FILE fd; /* internal use: file descriptor for region */ +}; + +/* Define a handle for a thread */ +typedef void* SYS_THREAD; + +/* Define an error value for the thread handle */ +#define SYS_THREAD_ERROR NULL + + +typedef struct conf_global_vars_s conf_global_vars_s; +struct conf_global_vars_s { + + /* What port we listen to */ + int Vport; /* OBSOLETE */ +#define server_portnum conf_getglobals()->Vport + + /* What address to bind to */ + char *Vaddr; /* OBSOLETE */ + + /* User to run as */ + struct passwd *Vuserpw; + + /* Directory to chroot to */ + char *Vchr; + + /* Where to log our pid to */ + char *Vpidfn; + +#define pool_max conf_getglobals()->Vpool_max + int Vpool_max; +#define pool_min conf_getglobals()->Vpool_min + int Vpool_min; /* OBSOLETE */ +#define pool_life conf_getglobals()->Vpool_life + int Vpool_life; /* OBSOLETE */ + + /* For multiprocess UNIX servers, the maximum threads per process */ +#define pool_maxthreads conf_getglobals()->Vpool_maxthreads + int Vpool_maxthreads; + +#define pool_minthreads conf_getglobals()->Vpool_minthreads + int Vpool_minthreads; /* OBSOLETE */ + + char *Vsecure_keyfn; /* OBSOLETE */ + char *Vsecure_certfn; /* OBSOLETE */ + +#define security_active conf_getglobals()->Vsecurity_active + int Vsecurity_active; + int Vssl3_active; /* OBSOLETE */ + int Vssl2_active; /* OBSOLETE */ + int Vsecure_auth; /* OBSOLETE */ + int Vsecurity_session_timeout; + long Vssl3_session_timeout; + + /* The server's hostname as should be reported in self-ref URLs */ +#define server_hostname conf_getglobals()->Vserver_hostname + char *Vserver_hostname; + + /* The main object from which all are derived */ +#define root_object conf_getglobals()->Vroot_object + char *Vroot_object; + + /* The object set the administrator has asked us to load */ +#define std_os conf_getglobals()->Vstd_os + httpd_objset *Vstd_os; + + /* The root of ACL data structures */ + void *Vacl_root; + + /* The main error log, where all errors are logged */ + char *Vmaster_error_log; + + /* The server root directory (contains instance subdirectories) */ +#define server_root conf_getglobals()->Vserver_root + char *Vserver_root; + + /* This server's id */ +#define server_id conf_getglobals()->Vserver_id + char *Vserver_id; + + /* Admin server users file */ + char *Vadmin_users; + + /* The installation directory (contains bin and lib subdirectories) */ + char *Vnetsite_root; + + /* Digest authentication stale nonce timeout value */ + int digest_stale_timeout; + + int single_accept; /* OBSOLETE */ + int num_keep_alives; /* OBSOLETE */ + int log_verbose; /* OBSOLETE */ + int mmap_flags; /* OBSOLETE */ + int mmap_prots; /* OBSOLETE */ + int unused1; + int unused2; + + /* Begin Enterprise 3.0 fields */ + int accept_language; /* turn accept-language on/off */ + + char *mtahost; + char *nntphost; /* OBSOLETE */ + + /* The root of ACL data structures */ + void *Vacl_root_30; + + char *agentFilePath; /* OBSOLETE */ + + int Allowed; /* OBSOLETE */ + + pblock *genericGlobals; /* OBSOLETE */ + + char *agentsACLFile; /* OBSOLETE */ + + int wait_for_cgi; /* OBSOLETE */ + int cgiwatch_timeout; /* OBSOLETE */ + int started_by_watchdog; + int restarted_by_watchdog; + int old_accel_cache_enabled; /* OBSOLETE */ + int Vssl_cache_entries; + int blocking_listen_socket; /* OBSOLETE */ + pblock **initfns; + char *vs_config_file; /* OBSOLETE */ +}; + +/* Type used for Request rq_attr bit flags */ +#ifdef AIX +#define RQATTR unsigned +#else +#define RQATTR unsigned long +#endif + +struct Request { + /* Server working variables */ + pblock *vars; + + /* The method, URI, and protocol revision of this request */ + pblock *reqpb; + /* Protocol specific headers */ + int loadhdrs; + pblock *headers; + + /* Server's response headers */ + int senthdrs; + pblock *srvhdrs; + + /* The object set constructed to fulfill this request */ + httpd_objset *os; + /* Array of objects that were created from .nsconfig files */ + httpd_objset *tmpos; + + /* The stat last returned by request_stat_path */ + char *statpath; + char *staterr; + struct stat *finfo; + + /* access control state */ + int aclstate; /* ACL decision state */ + int acldirno; /* deciding ACL directive number */ + char *aclname; /* name of deciding ACL */ + pblock *aclpb; /* OBSOLETE */ + /* 3.0 ACL list pointer */ + ACLListHandle *acllist; + + int request_is_cacheable; /* */ + int directive_is_cacheable; /* set by SAFs with no external side effects that make decisions based solely on URI and path */ + + char *cached_headers; /* OBSOLETE */ + int cached_headers_len; /* OBSOLETE */ + char *unused; + + /* HTTP/1.1 features */ +#define REQ_TIME(x) (x)->req_start + time_t req_start; /* time request arrived - used for selecting weak or strong cache validation */ + short protv_num; /* protocol version number */ + short method_num; /* method number */ + struct rq_attr { + RQATTR abs_uri:1; /* set if absolute URI was used */ + RQATTR chunked:1; /* chunked transfer-coding */ + RQATTR keep_alive:1; /* connection keep-alive */ + RQATTR pipelined:1; /* request packet is pipelined */ + RQATTR internal_req:1; /* this was an internal request */ + RQATTR perm_req:1; /* don't FREE() this request */ + RQATTR header_file_present:1; /* OBSOLETE */ + RQATTR footer_file_present:1; /* OBSOLETE */ + RQATTR jvm_attached:1; /* OBSOLETE */ + RQATTR req_restarted:1; /* request was restarted */ + RQATTR jvm_request_locked:1; /* used for first-request serialization on some platforms */ + RQATTR default_type_set:1; /* set if default types were set using set-default-type objecttype function */ + RQATTR is_web_app:1; /* OBSOLETE */ + RQATTR ssl_unclean_shutdown:1; /* set if browser requires unclean SSL shutdown */ + RQATTR vary_accept_language:1; /* set if request was restarted based on an accept-language header */ + RQATTR reserved:17; /* if you add a flag, make sure to subtract from this */ + } rq_attr; + char *hostname; /* hostname used to access server (always non-NULL) */ + int allowed; /* OBSOLETE */ + int byterange; /* OBSOLETE */ + short status_num; /* HTTP status code */ + + int staterrno; /* used for rqstat */ + Request *orig_rq; /* original Request - used for internal redirects */ +}; + +/* Request attribute macros */ +#define ABS_URI(x) (x)->rq_attr.abs_uri +#define CHUNKED(x) (x)->rq_attr.chunked +#define KEEP_ALIVE(x) (x)->rq_attr.keep_alive +#define PIPELINED(x) (x)->rq_attr.pipelined +#define INTERNAL_REQUEST(x) (x)->rq_attr.internal_req +#define RESTARTED_REQUEST(x) (x)->rq_attr.req_restarted +#define PERM_REQUEST(x) (x)->rq_attr.perm_req +#define JVM_REQUEST_LOCKED(x) (x)->rq_attr.jvm_request_locked +#define SSL_UNCLEAN_SHUTDOWN(x) (x)->rq_attr.ssl_unclean_shutdown +#define VARY_ACCEPT_LANGUAGE(x) (x)->rq_attr.vary_accept_language + +/* Define methods for HTTP/1.1 */ +#define METHOD_HEAD 0 +#define METHOD_GET 1 +#define METHOD_PUT 2 +#define METHOD_POST 3 +#define METHOD_DELETE 4 +#define METHOD_TRACE 5 +#define METHOD_OPTIONS 6 +/* The following methods are Netscape method extensions */ +#define METHOD_MOVE 7 +#define METHOD_INDEX 8 +#define METHOD_MKDIR 9 +#define METHOD_RMDIR 10 +#define METHOD_COPY 11 +#define METHOD_MAX 12 /* Number of methods available on this server */ + +#define ISMGET(r) ((r)->method_num == METHOD_GET) +#define ISMHEAD(r) ((r)->method_num == METHOD_HEAD) +#define ISMPUT(r) ((r)->method_num == METHOD_PUT) +#define ISMPOST(r) ((r)->method_num == METHOD_POST) +#define ISMDELETE(r) ((r)->method_num == METHOD_DELETE) +#define ISMMOVE(r) ((r)->method_num == METHOD_MOVE) +#define ISMINDEX(r) ((r)->method_num == METHOD_INDEX) +#define ISMMKDIR(r) ((r)->method_num == METHOD_MKDIR) +#define ISMRMDIR(r) ((r)->method_num == METHOD_RMDIR) +#define ISMCOPY(r) ((r)->method_num == METHOD_COPY) +#define ISMTRACE(r) ((r)->method_num == METHOD_TRACE) +#define ISMOPTIONS(r) ((r)->method_num == METHOD_OPTIONS) + + +/* --- End type definitions --- */ + +/* --- Begin dispatch vector table definition --- */ + +typedef struct nsapi_dispatch_s nsapi_dispatch_t; +struct nsapi_dispatch_s { + char *(*f_system_version)(); + void *(*f_system_malloc)(int size); + void *(*f_system_calloc)(int size); + void *(*f_system_realloc)(void *ptr, int size); + void (*f_system_free)(void *ptr); + char *(*f_system_strdup)(const char *ptr); + void *(*f_system_malloc_perm)(int size); + void *(*f_system_calloc_perm)(int size); + void *(*f_system_realloc_perm)(void *ptr, int size); + void (*f_system_free_perm)(void *ptr); + char *(*f_system_strdup_perm)(const char *ptr); + int (*f_getThreadMallocKey)(void); + void (*f_magnus_atrestart)(void (*fn)(void *), void *data); + filebuf_t *(*f_filebuf_open)(SYS_FILE fd, int sz); + netbuf *(*f_netbuf_open)(SYS_NETFD sd, int sz); + filebuf_t *(*f_filebuf_create)(SYS_FILE fd, caddr_t mmap_ptr, + int mmap_len, int bufsz); + void (*f_filebuf_close_buffer)(filebuf_t *buf, int clean_mmap); + filebuf_t *(*f_filebuf_open_nostat)(SYS_FILE fd, int sz, + struct stat *finfo); +#ifdef XP_WIN32 + filebuf_t *(*f_pipebuf_open)(SYS_FILE fd, int sz, struct stat *finfo); +#else + void *(*f_pipebuf_open)(void); +#endif /* XP_WIN32 */ + int (*f_filebuf_next)(void); + int (*f_netbuf_next)(netbuf *buf, int advance); +#ifdef XP_WIN32 + int (*f_pipebuf_next)(filebuf_t *buf, int advance); +#else + int (*f_pipebuf_next)(void); +#endif /* XP_WIN32 */ + void (*f_filebuf_close)(filebuf_t *buf); + void (*f_netbuf_close)(netbuf *buf); +#ifdef XP_WIN32 + void (*f_pipebuf_close)(filebuf_t *buf); +#else + void (*f_pipebuf_close)(void); +#endif /* XP_WIN32 */ + int (*f_filebuf_grab)(filebuf_t *buf, int sz); + int (*f_netbuf_grab)(netbuf *buf, int sz); +#ifdef XP_WIN32 + int (*f_pipebuf_grab)(filebuf_t *buf, int sz); +#else + int (*f_pipebuf_grab)(void); +#endif /* XP_WIN32 */ + int (*f_netbuf_buf2sd)(netbuf *buf, SYS_NETFD sd, int len); + int (*f_filebuf_buf2sd)(filebuf_t *buf, SYS_NETFD sd); +#ifdef XP_WIN32 + int (*f_pipebuf_buf2sd)(filebuf_t *buf, SYS_NETFD sd, int len); + int (*f_pipebuf_netbuf2sd)(netbuf *buf, SYS_FILE sd, int len); + int (*f_pipebuf_netbuf2pipe)(netbuf *buf, SYS_NETFD sd, int len); +#else + int (*f_pipebuf_buf2sd)(void); + int (*f_pipebuf_netbuf2sd)(void); + int (*f_pipebuf_netbuf2pipe)(void); +#endif /* XP_WIN32 */ + void (*f_cinfo_init)(void); + void (*f_cinfo_terminate)(void); + char *(*f_cinfo_merge)(char *fn); + cinfo *(*f_cinfo_find)(char *uri); + cinfo *(*f_cinfo_lookup)(char *type); + void (*f_cinfo_dump_database)(FILE *dump); + CRITICAL (*f_crit_init)(void); + void (*f_crit_enter)(CRITICAL id); + void (*f_crit_exit)(CRITICAL id); + void (*f_crit_terminate)(CRITICAL id); + CONDVAR (*f_condvar_init)(CRITICAL id); + void (*f_condvar_wait)(CONDVAR cv); + void (*f_condvar_notify)(CONDVAR cv); + void (*f_condvar_notifyAll)(CONDVAR cv); + void (*f_condvar_terminate)(CONDVAR cv); + COUNTING_SEMAPHORE (*f_cs_init)(int initial_count); + void (*f_cs_terminate)(COUNTING_SEMAPHORE csp); + int (*f_cs_wait)(COUNTING_SEMAPHORE csp); + int (*f_cs_trywait)(COUNTING_SEMAPHORE csp); + int (*f_cs_release)(COUNTING_SEMAPHORE csp); + void (*f_daemon_atrestart)(void (*fn)(void *), void *data); + /* Obsolete: servssl_init() */ + void (*f_servssl_init)(void); + int (*f_ereport)(int degree, const char *fmt, ...); + int (*f_ereport_v)(int degree, const char *fmt, va_list args); + char *(*f_ereport_init)(const char *err_fn, const char *email, + struct passwd *pwuser, const char *version, + int restart); + void (*f_ereport_terminate)(void); + SYS_FILE (*f_ereport_getfd)(void); + SYS_FILE (*f_system_fopenRO)(const char *path); + SYS_FILE (*f_system_fopenWA)(const char *path); + SYS_FILE (*f_system_fopenRW)(const char *path); + SYS_FILE (*f_system_fopenWT)(const char *path); + int (*f_system_fread)(SYS_FILE fd, void *buf, int sz); + int (*f_system_fwrite)(SYS_FILE fd, const void *buf,int sz); + int (*f_system_fwrite_atomic)(SYS_FILE fd, const void *buf, int sz); + int (*f_system_lseek)(SYS_FILE fd, int off, int wh); + int (*f_system_fclose)(SYS_FILE fd); + int (*f_system_stat)(const char *name, struct stat *finfo); + int (*f_system_rename)(const char *oldpath, const char *newpath); + int (*f_system_unlink)(const char *path); + int (*f_system_tlock)(SYS_FILE fd); + int (*f_system_flock)(SYS_FILE fd); + int (*f_system_ulock)(SYS_FILE fd); +#ifdef XP_WIN32 + SYS_DIR (*f_dir_open)(const char *path); + SYS_DIRENT *(*f_dir_read)(SYS_DIR ds); + void (*f_dir_close)(SYS_DIR ds); +#else + void *(*f_dir_open)(void); + void *(*f_dir_read)(void); + void (*f_dir_close)(void); +#endif /* XP_WIN32 */ + int (*f_dir_create_all)(char *dir); +#ifdef XP_WIN32 + void *(*f_system_winsockerr)(void); + void *(*f_system_winerr)(void); + int (*f_system_pread)(SYS_FILE fd, void *buf, int sz); + int (*f_system_pwrite)(SYS_FILE fd, const void *buf, int sz); + void (*f_file_unix2local)(const char *path, char *p2); +#else + void *(*f_system_winsockerr)(void); + void *(*f_system_winerr)(void); + int (*f_system_pread)(void); + int (*f_system_pwrite)(void); + void (*f_file_unix2local)(void); +#endif /* XP_WIN32 */ + int (*f_system_nocoredumps)(void); + int (*f_file_setinherit)(SYS_FILE fd, int value); + int (*f_file_notfound)(void); + char *(*f_system_errmsg)(void); + int (*f_system_errmsg_fn)(char **buff, size_t maxlen); + SYS_NETFD (*f_net_socket)(int domain, int type, int protocol); + int (*f_net_listen)(SYS_NETFD s, int backlog); + SYS_NETFD (*f_net_create_listener)(const char *ipaddr, int port); + int (*f_net_connect)(SYS_NETFD s, const void *sockaddr, int namelen); + int (*f_net_getpeername)(SYS_NETFD s, struct sockaddr *name, int *namelen); + int (*f_net_close)(SYS_NETFD s); + int (*f_net_bind)(SYS_NETFD s, const struct sockaddr *name, int namelen); + SYS_NETFD (*f_net_accept)(SYS_NETFD s, struct sockaddr *addr, int *addrlen); + int (*f_net_read)(SYS_NETFD sd, void *buf, int sz, int timeout); + int (*f_net_write)(SYS_NETFD sd, const void *buf, int sz); + int (*f_net_writev)(SYS_NETFD sd, const NSAPIIOVec *iov, int iovlen); + int (*f_net_isalive)(SYS_NETFD sd); + char *(*f_net_ip2host)(const char *ip, int verify); + int (*f_net_getsockopt)(SYS_NETFD s, int level, int optname, + void *optval, int *optlen); + int (*f_net_setsockopt)(SYS_NETFD s, int level, int optname, + const void *optval, int optlen); + int (*f_net_select)(int nfds, fd_set *r, fd_set *w, fd_set *e, + struct timeval *timeout); + int (*f_net_ioctl)(SYS_NETFD s, int tag, void *result); + pb_param *(*f_param_create)(const char *name, const char *value); + int (*f_param_free)(pb_param *pp); + pblock *(*f_pblock_create)(int n); + void (*f_pblock_free)(pblock *pb); + char *(*f_pblock_findval)(const char *name, const pblock *pb); + pb_param *(*f_pblock_nvinsert)(const char *name, const char *value, pblock *pb); + pb_param *(*f_pblock_nninsert)(const char *name, int value, pblock *pb); + void (*f_pblock_pinsert)(pb_param *pp, pblock *pb); + int (*f_pblock_str2pblock)(const char *str, pblock *pb); + char *(*f_pblock_pblock2str)(const pblock *pb, char *str); + int (*f_pblock_copy)(const pblock *src, pblock *dst); + pblock *(*f_pblock_dup)(const pblock *src); + char **(*f_pblock_pb2env)(const pblock *pb, char **env); + pb_param *(*f_pblock_fr)(const char *name, pblock *pb, int remove); + char * (*f_pblock_replace)(const char *name,char * new_value,pblock *pb); + pool_handle_t *(*f_pool_create)(void); + void (*f_pool_destroy)(pool_handle_t *pool_handle); + int (*f_pool_enabled)(void); + void *(*f_pool_malloc)(pool_handle_t *pool_handle, size_t size ); + void (*f_pool_free)(pool_handle_t *pool_handle, void *ptr ); + void *(*f_pool_calloc)(pool_handle_t *pool_handle, size_t nelem, size_t elsize); + void *(*f_pool_realloc)(pool_handle_t *pool_handle, void *ptr, size_t size ); + char *(*f_pool_strdup)(pool_handle_t *pool_handle, const char *orig_str ); + int (*f_regexp_valid)(const char *exp); + int (*f_regexp_match)(const char *str, const char *exp); + int (*f_regexp_cmp)(const char *str, const char *exp); + int (*f_regexp_casecmp)(const char *str, const char *exp); + SEMAPHORE (*f_sem_init)(char *name, int number); + void (*f_sem_terminate)(SEMAPHORE id); + int (*f_sem_grab)(SEMAPHORE id); + int (*f_sem_tgrab)(SEMAPHORE id); + int (*f_sem_release)(SEMAPHORE id); + Session *(*f_session_alloc)(SYS_NETFD csd, struct sockaddr_in *sac); /* internal */ + Session *(*f_session_fill)(Session *sn); /* internal */ + Session *(*f_session_create)(SYS_NETFD csd, struct sockaddr_in *sac); + void (*f_session_free)(Session *sn); + char *(*f_session_dns_lookup)(Session *sn, int verify); + int (*f_shexp_valid)(const char *exp); + int (*f_shexp_match)(const char *str, const char *exp); + int (*f_shexp_cmp)(const char *str, const char *exp); + int (*f_shexp_casecmp)(const char *str, const char *exp); + shmem_s *(*f_shmem_alloc)(char *name, int size, int expose); + void (*f_shmem_free)(shmem_s *region); + SYS_THREAD (*f_systhread_start)(int prio, int stksz, void (*fn)(void *), void *arg); + SYS_THREAD (*f_systhread_current)(void); + void (*f_systhread_yield)(void); + SYS_THREAD (*f_systhread_attach)(void); + void (*f_systhread_detach)(SYS_THREAD thr); + void (*f_systhread_terminate)(SYS_THREAD thr); + void (*f_systhread_sleep)(int milliseconds); + void (*f_systhread_init)(char *name); + void (*f_systhread_timerset)(int usec); + int (*f_systhread_newkey)(void); + void *(*f_systhread_getdata)(int key); + void (*f_systhread_setdata)(int key, void *data); + void (*f_systhread_set_default_stacksize)(unsigned long size); + int (*f_util_getline)(filebuffer *buf, int lineno, int maxlen, char *l); + char **(*f_util_env_create)(char **env, int n, int *pos); + char *(*f_util_env_str)(const char *name, const char *value); + void (*f_util_env_replace)(char **env, const char *name, const char *value); + void (*f_util_env_free)(char **env); + char **(*f_util_env_copy)(char **src, char **dst); + char *(*f_util_env_find)(char **env, const char *name); + char *(*f_util_hostname)(void); + int (*f_util_chdir2path)(char *path); + int (*f_util_is_mozilla)(char *ua, char *major, char *minor); + int (*f_util_is_url)(const char *url); + int (*f_util_later_than)(const struct tm *lms, const char *ims); + int (*f_util_time_equal)(const struct tm *lms, const char *ims); + int (*f_util_str_time_equal)(const char *t1, const char *t2); + int (*f_util_uri_is_evil)(const char *t); + void (*f_util_uri_parse)(char *uri); + void (*f_util_uri_unescape)(char *s); + char *(*f_util_uri_escape)(char *d, const char *s); + char *(*f_util_url_escape)(char *d, const char *s); + char *(*f_util_sh_escape)(char *s); + int (*f_util_mime_separator)(char *sep); + int (*f_util_itoa)(int i, char *a); + int (*f_util_vsprintf)(char *s, register const char *fmt, va_list args); + int (*f_util_sprintf)(char *s, const char *fmt, ...); + int (*f_util_vsnprintf)(char *s, int n, register const char *fmt, + va_list args); + int (*f_util_snprintf)(char *s, int n, const char *fmt, ...); + int (*f_util_strftime)(char *s, const char *format, const struct tm *t); + char *(*f_util_strtok)(char *s1, const char *s2, char **lasts); + struct tm *(*f_util_localtime)(const time_t *clock, struct tm *res); + char *(*f_util_ctime)(const time_t *clock, char *buf, int buflen); + char *(*f_util_strerror)(int errnum, char *msg, int buflen); + struct tm *(*f_util_gmtime)(const time_t *clock, struct tm *res); + char *(*f_util_asctime)(const struct tm *tm,char *buf, int buflen); +#ifdef NEED_STRCASECMP + int (*f_util_strcasecmp)(const char *one, const char *two); +#else + int (*f_util_strcasecmp)(void); +#endif /* NEED_STRCASECMP */ +#ifdef NEED_STRNCASECMP + int (*f_util_strncasecmp)(const char *one, const char *two, int n); +#else + int (*f_util_strncasecmp)(void); +#endif /* NEED_STRNCASECMP */ +#ifdef XP_UNIX + int (*f_util_can_exec)(struct stat *finfo, uid_t uid, gid_t gid); + struct passwd *(*f_util_getpwnam)(const char *name, struct passwd + *result, char *buffer, int buflen); + pid_t (*f_util_waitpid)(pid_t pid, int *statptr, int options); +#else + int (*f_util_can_exec)(void); + void *(*f_util_getpwnam)(void); + int (*f_util_waitpid)(void); +#endif /* XP_UNIX */ +#ifdef XP_WIN32 + VOID (*f_util_delete_directory)(char *FileName, BOOL delete_directory); +#else + void (*f_util_delete_directory)(void); +#endif /* XP_WIN32 */ + void *(*f_conf_init)(void); + void *(*f_conf_run_init_functions)(void); + void (*f_conf_terminate)(void); + conf_global_vars_s *(*f_conf_getglobals)(void); + void (*f_func_init)(struct FuncStruct *func_standard); + FuncPtr (*f_func_find)(char *name); + int (*f_func_exec)(pblock *pb, Session *sn, Request *rq); + struct FuncStruct *(*f_func_insert)(char *name, FuncPtr fn); + int (*f_object_execute)(directive *inst, Session *sn, Request *rq); + void *(*f_http_find_request)(void); + int (*f_http_parse_request)(char *t, Request *rq, Session *sn); + int (*f_http_scan_headers)(void); + int (*f_http_start_response)(Session *sn, Request *rq); + char **(*f_http_hdrs2env)(pblock *pb); + void (*f_http_status)(Session *sn, Request *rq, int n, const char *r); + int (*f_http_set_finfo)(Session *sn, Request *rq, struct stat *finfo); + char *(*f_http_dump822)(pblock *pb, char *t, int *pos, int tsz); + void (*f_http_finish_request)(Session *sn, Request *rq); + void (*f_http_handle_session)(void); + char *(*f_http_uri2url)(const char *prefix, const char *suffix); + char *(*f_http_uri2url_dynamic)(const char *prefix, const char *suffix, + Session *sn, Request *rq); + void (*f_http_set_keepalive_timeout)(int secs); + int (*f_log_error_v)(int degree, const char *func, Session *sn, + Request *rq, const char *fmt, va_list args); + int (*f_log_error)(int degree, const char *func, Session *sn, Request *rq, + const char *fmt, ...); + int (*f_log_ereport_v)(int degree, const char *fmt, va_list args); + int (*f_log_ereport)(int degree, const char *fmt, ...); + httpd_object *(*f_object_create)(int nd, pblock *name); + void (*f_object_free)(httpd_object *obj); + void (*f_object_add_directive)(int dc, pblock *p, pblock *c, + httpd_object *obj); + httpd_objset *(*f_objset_scan_buffer)(filebuffer *buf, char *errstr, + httpd_objset *os); + httpd_objset *(*f_objset_create)(void); + void (*f_objset_free)(httpd_objset *os); + void (*f_objset_free_setonly)(httpd_objset *os); + httpd_object *(*f_objset_new_object)(pblock *name, httpd_objset *os); + void (*f_objset_add_object)(httpd_object *obj, httpd_objset *os); + void (*f_objset_add_init)(pblock *initfn, httpd_objset *os); + httpd_object *(*f_objset_findbyname)(const char *name, httpd_objset *ign, + httpd_objset *os); + httpd_object *(*f_objset_findbyppath)(char *ppath, httpd_objset *ign, + httpd_objset *os); + Request *(*f_request_create)(void); + void (*f_request_free)(Request *req); + Request *(*f_request_restart_internal)(const char *uri, Request *rq); + int (*f_request_header)(char *name, char **value, Session *sn, + Request *rq); + struct stat *(*f_request_stat_path)(const char *path, Request *rq); + const char *(*f_conf_getServerString)(void); + FuncPtr (*f_func_replace)(char *funcname, FuncPtr fn); + int (*f_net_socketpair)(SYS_NETFD *pair); +#ifdef XP_UNIX + SYS_NETFD (*f_net_dup2)(SYS_NETFD prfd, int osfd); + int (*f_net_is_STDOUT)(SYS_NETFD prfd); + int (*f_net_is_STDIN)(SYS_NETFD prfd); +#else + void *(*f_net_dup2)(void); + int (*f_net_is_STDOUT)(void); + int (*f_net_is_STDIN)(void); +#endif /* XP_UNIX */ + int (*f_func_set_native_thread_flag)(char *name, int flags); +#ifdef NET_SSL + void *(*f_random_create)(void); + void (*f_random_update)(void *rctx, unsigned char *inbuf, int length); + void (*f_random_generate)(void *rctx, unsigned char *outbuf, int length); + void (*f_random_destroy)(void *rctx); + void *(*f_md5hash_create)(void); + void *(*f_md5hash_copy)(void *hctx); + void (*f_md5hash_begin)(void *hctx); + void (*f_md5hash_update)(void *hctx, unsigned char *inbuf, int length); + void (*f_md5hash_end)(void *hctx, unsigned char *outbuf); + void (*f_md5hash_destroy)(void *hctx); + void (*f_md5hash_data)(unsigned char *outbuf, unsigned char *src, int length); +#else + void *(*f_random_create)(void); + void (*f_random_update)(void); + void (*f_random_generate)(void); + void (*f_random_destroy)(void); + void *(*f_md5hash_create)(void); + void *(*f_md5hash_copy)(void); + void (*f_md5hash_begin)(void); + void (*f_md5hash_update)(void); + void (*f_md5hash_end)(void); + void (*f_md5hash_destroy)(void); + void (*f_md5hash_data)(void); +#endif + int (*f_ACL_SetupEval)(struct ACLListHandle *acllist, Session *sn, Request *rq, char **rights, char **map_generic, const char *user); + int (*f_netbuf_getbytes)(netbuf *buf, char *buffer, int size); + char *(*f_servact_translate_uri)(char *uri, Session *sn); +#ifdef NET_SSL + int (*f_rsa_set_priv_fn)(void *); +#else + int (*f_rsa_set_priv_fn)(void); +#endif +#ifdef XP_UNIX + int (*f_net_native_handle)(SYS_NETFD s); +#else + HANDLE (*f_net_native_handle)(SYS_NETFD s); +#endif /* XP_UNIX */ + int (*f_internal_request)(Request *rq); + char *(*f_util_cookie_find)(char *cookie, const char *name); + char *(*f_util_cookie_next)(char *cookie, char **name, char **value); + char *(*f_util_cookie_next_av_pair)(char *cookie, char **name, char **value); + int (*f_objset_get_number_objects)(const httpd_objset *objset); + const httpd_object *(*f_objset_get_object)(const httpd_objset *objset, int pos); + const pblock * const *(*f_objset_get_initfns)(const httpd_objset *objset); + const pblock *(*f_object_get_name)(const httpd_object *object); + int (*f_object_get_num_directives)(const httpd_object *object); + const dtable *(*f_object_get_directive_table)(const httpd_object *object, int n); + int (*f_directive_table_get_num_directives)(const dtable *dt); + const directive *(*f_directive_table_get_directive)(const dtable *dt, int pos); + const pblock *(*f_directive_get_pblock)(const directive *); + const FuncStruct *(*f_directive_get_funcstruct)(const directive *); + const pblock *(*f_directive_get_client_pblock)(const directive *); +#if NSAPI_VERSION >= 301 + int (*f_vs_register_cb)(VSInitFunc *vs_init_func, VSDestroyFunc *vs_destroy_func); + const char* (*f_vs_get_id)(const VirtualServer *vs); + const char* (*f_vs_lookup_config_var)(const VirtualServer *vs, const char *name); + int (*f_vs_alloc_slot)(void); + void* (*f_vs_set_data)(const VirtualServer *vs, int *slot, void *data); + void* (*f_vs_get_data)(const VirtualServer *vs, int slot); + const VirtualServer* (*f_request_get_vs)(Request *rq); + httpd_objset* (*f_vs_get_httpd_objset)(VirtualServer *vs); + httpd_object* (*f_vs_get_default_httpd_object)(VirtualServer *vs); + char* (*f_vs_get_doc_root)(const VirtualServer *vs); + char* (*f_vs_translate_uri)(const VirtualServer *vs, const char *uri); + char* (*f_vs_get_mime_type)(const VirtualServer *vs, const char *uri); + int (*f_vs_is_default_vs)(const VirtualServer *vs); + void *(*f_vs_get_acllist)(const VirtualServer *vs); + void (*f_vs_set_acllist)(VirtualServer *vs, void *acllist); + int (*f_file_is_path_abs)(const char *path); + char* (*f_file_canonicalize_path)(const char* path); + int (*f_file_are_files_distinct)(SYS_FILE fd1, SYS_FILE fd2); + int (*f_vs_directive_register_cb)(FuncPtr func, VSDirectiveInitFunc *vs_init_func, VSDirectiveDestroyFunc *vs_destroy_func); + char* (*f_vs_substitute_vars)(const VirtualServer *vs, const char *string); + const char *(*f_conf_getfilename)(void); + const char *(*f_conf_getstring)(const char *name, const char *def); + int (*f_conf_getboolean)(const char *name, int def); + int (*f_conf_getinteger)(const char *name, int def); + int (*f_conf_getboundedinteger)(const char *name, int min, int max, int def); + void (*f_prepare_nsapi_thread)(Request *rq, Session *sn); +#endif /* NSAPI_VERSION >= 301 */ +}; + +#if NSAPI_VERSION >= 302 +typedef struct nsapi302_dispatch_s nsapi302_dispatch_t; +struct nsapi302_dispatch_s { + int (*f_net_flush)(SYS_NETFD sd); + int (*f_net_sendfile)(SYS_NETFD sd, sendfiledata *sfd); + const Filter *(*f_filter_create)(const char *name, int order, const FilterMethods *methods); + const char *(*f_filter_name)(const Filter *filter); + const Filter *(*f_filter_find)(const char *name); + FilterLayer *(*f_filter_layer)(SYS_NETFD sd, const Filter *filter); + int (*f_filter_insert)(SYS_NETFD sd, pblock *pb, Session *sn, Request *rq, void *data, const Filter *filter); + int (*f_filter_remove)(SYS_NETFD sd, const Filter *filter); + SYS_NETFD (*f_filter_create_stack)(Session *sn); +}; +#endif /* NSAPI_VERSION >= 302 */ + +#if NSAPI_VERSION >= 303 +typedef struct nsapi303_dispatch_s nsapi303_dispatch_t; +struct hostent; +struct nsapi303_dispatch_s { + int (*f_dns_set_hostent)(struct hostent *he, Session *sn, Request *rq); +}; +#endif /* NSAPI_VERSION >= 303 */ + +/* --- End dispatch vector table definition --- */ + +/* --- Begin API macro definitions --- */ + +#ifndef INTNSAPI + +#if NSAPI_VERSION >= 301 + +/* + * In Sun ONE Web Server 6.1 and higher, http_parse_request("", NULL, NULL) + * returns the NSAPI version. In previous releases, it returns -1. + */ +#define __NSAPI_RUNTIME_VERSION \ + ((*__nsapi30_table->f_http_parse_request)("", NULL, NULL)) + +/* + * NSAPI_RUNTIME_VERSION returns the NSAPI version the server implements. The + * returned NSAPI version number is reliable only in iPlanet Web Server 6.0, + * Netscape Enterprise Server 6.0, and Sun ONE Web Server 6.0 and higher. + */ +#define NSAPI_RUNTIME_VERSION \ + (__NSAPI_RUNTIME_VERSION > 0 ? __NSAPI_RUNTIME_VERSION : 301) + +#endif /* NSAPI_VERSION >= 301 */ + +#define system_version (*__nsapi30_table->f_system_version) + +/* + * Depending on the system, memory allocated via these macros may come from + * an arena. If these functions are called from within an Init function, they + * will be allocated from permanent storage. Otherwise, they will be freed + * when the current request is finished. + */ + + + +#endif /* !INTNSAPI */ + +#ifdef XP_UNIX +#define dir_open opendir +#define dir_read readdir +#define dir_close closedir +#define dir_create(path) mkdir(path, 0755) +#define dir_remove rmdir +#define system_chdir chdir +#define file_unix2local(path,p2) strcpy(p2,path) +#endif /* XP_UNIX */ + +#ifdef XP_WIN32 +#define dir_create _mkdir +#define dir_remove _rmdir +#define system_chdir SetCurrentDirectory +#endif /* XP_WIN32 */ + +/* + * Thread-safe variants of localtime and gmtime + */ +#define system_localtime(curtime, ret) util_localtime(curtime, ret) +#define system_gmtime(curtime, ret) util_gmtime(curtime, ret) + +/* + * pblock_find finds the entry with the given name in pblock pb. + * + * If it is successful, it returns the param block. If not, it returns NULL. + */ +#define pblock_find(name, pb) (pblock_fr(name,pb,0)) + +/* + * pblock_remove behaves exactly like pblock_find, but removes the given + * entry from pb. + */ +#define pblock_remove(name, pb) (pblock_fr(name,pb,1)) + +/* + * session_dns returns the DNS hostname of the client of this session, + * and inserts it into the client pblock. Returns NULL if unavailable. + */ +#define session_dns(sn) session_dns_lookup(sn, 0) + +/* + * session_maxdns looks up a hostname from an IP address, and then verifies + * that the host is really who they claim to be. + */ +#define session_maxdns(sn) session_dns_lookup(sn, 1) + +#define protocol_start_response http_start_response +#define protocol_status http_status +#define protocol_set_finfo http_set_finfo +#define protocol_finish_request http_finish_request +#define protocol_uri2url http_uri2url +#define protocol_uri2url_dynamic http_uri2url_dynamic + +#define request_translate_uri servact_translate_uri + +/* --- OBSOLETE ---------------------------------------------------------- + * The following macros/functions are obsolete and are only maintained for + * compatibility. Do not use them. + * ----------------------------------------------------------------------- + */ + +#define SYS_STDERR STDERR_FILENO + +#ifdef XP_WIN32 + +typedef HANDLE pid_t; + +#define ERROR_PIPE \ + (ERROR_BROKEN_PIPE | ERROR_BAD_PIPE | \ + ERROR_PIPE_BUSY | ERROR_PIPE_LISTENING | ERROR_PIPE_NOT_CONNECTED) +#define CONVERT_TO_PRINTABLE_FORMAT(Filename) \ +{ \ + register char *s; \ + if (Filename) \ + for (s = Filename; *s; s++) \ + if ( *s == '\\') \ + *s = '/'; \ +} +#define CONVERT_TO_NATIVE_FS(Filename) \ +{ \ + register char *s; \ + if (Filename) \ + for (s = Filename; *s; s++) \ + if ( *s == '/') \ + *s = '\\'; \ +} + +#ifdef INTNSAPI +NSAPI_PUBLIC extern nsapi_dispatch_t *__nsapi30_table; +#if NSAPI_VERSION >= 302 +NSAPI_PUBLIC extern nsapi302_dispatch_t *__nsapi302_table; +#endif /* NSAPI_VERSION >= 302 */ +#if NSAPI_VERSION >= 303 +NSAPI_PUBLIC extern nsapi303_dispatch_t *__nsapi303_table; +#endif /* NSAPI_VERSION >= 303 */ +#else +__declspec(dllimport) nsapi_dispatch_t *__nsapi30_table; +#if NSAPI_VERSION >= 302 +__declspec(dllimport) nsapi302_dispatch_t *__nsapi302_table; +#endif /* NSAPI_VERSION >= 302 */ +#if NSAPI_VERSION >= 303 +__declspec(dllimport) nsapi303_dispatch_t *__nsapi303_table; +#endif /* NSAPI_VERSION >= 303 */ +#endif /* INTNSAPI */ + +#else /* !XP_WIN32 */ + +NSAPI_PUBLIC extern nsapi_dispatch_t *__nsapi30_table; +#if NSAPI_VERSION >= 302 +NSAPI_PUBLIC extern nsapi302_dispatch_t *__nsapi302_table; +#endif /* NSAPI_VERSION >= 302 */ +#if NSAPI_VERSION >= 303 +NSAPI_PUBLIC extern nsapi303_dispatch_t *__nsapi303_table; +#endif /* NSAPI_VERSION >= 303 */ + +#endif /* XP_WIN32 */ + +#ifdef __cplusplus +} +#endif + +#endif /* !PUBLIC_NSAPI_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/objs.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/objs.mk Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,59 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2011 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SRC_DIR = server/ + +OBJPRE = $(OBJ_DIR)$(SRC_DIR) + +MOBJ = main.o +MOBJ += webserver.o +MOBJ += util.o +MOBJ += uri.o +MOBJ += systhr.o +MOBJ += system.o +MOBJ += pool.o +MOBJ += plist.o +MOBJ += pblock.o +MOBJ += sstring.o +MOBJ += list.o +MOBJ += map.o +MOBJ += func.o +MOBJ += ws-fn.o +MOBJ += conf.o +MOBJ += httplistener.o +MOBJ += session.o +MOBJ += request.o +MOBJ += io.o +MOBJ += thrpool.o +MOBJ += sessionhandler.o +MOBJ += httpparser.o +MOBJ += httprequest.o + + +MAINOBJS = $(MOBJ:%=$(OBJPRE)%) + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/pblock.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/pblock.cpp Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,1193 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pblock.c: Handles Parameter Blocks + * + * See pblock.h for public documentation. + * + * Rob McCool + * + * This code uses property lists to implement pblocks. + */ + + +#include +#include "pblock.h" +#include "plist_pvt.h" +#include "plist.h" +#include "LinkedList.hh" +#include "util.h" /* util_itoa */ +#include "pool.h" +#include "systhr.h" + +#define MALLOC_POOL_HANDLE (thread_malloc_key != -1 ? (pool_handle_t *)systhread_getdata(thread_malloc_key) : getThreadMallocPool()) + +static int thread_malloc_key = -1; +static int _pblock_str2pblock(const char* str, pblock* pb, PRBool lowerCase); + +static pool_handle_t *getThreadMallocPool() +{ + pool_handle_t *thread_malloc_pool = 0; + + thread_malloc_key = getThreadMallocKey(); + if (thread_malloc_key != -1) { + thread_malloc_pool = (pool_handle_t *)systhread_getdata(thread_malloc_key); + } + + return thread_malloc_pool; +} + +/* ------------------------------- HashList ------------------------------- */ + +template +class HashList { +public: + HashList(int mask) + : _mask(mask), + _list(new CList[mask + 1]) + { } + + void Insert(Name name, Value *value) + { + _list[name & _mask].Append(value); + } + + const CList& Find(Name name) + { + return _list[name & _mask]; + } + +private: + CList *_list; + unsigned int _mask; +}; + +/* ---------------------- pb_key static initializers ---------------------- */ + +/* + * pb_key + * + * Contains a precomputed hash value for a specific pblock variable name. + */ +typedef struct pb_key pb_key; +struct pb_key { + const char *name; + int namelen; + unsigned int hashval; + int sizendx; + int hashndx; +}; + +static HashList _hashKeys(0x7f); +CList _listKeys; + +static const pb_key *const _create_key(const char *name, int sizendx = 0) +{ + /* Create a the new pb_key */ + pb_key *key = (pb_key*)malloc(sizeof(pb_key)); + key->name = STRDUP(name); + key->namelen = strlen(name); + key->hashval = PListHash(name); + key->sizendx = sizendx; + key->hashndx = key->hashval % PLSIZENDX(sizendx); + + /* Group pb_keys by hashval for later retrieval */ + _hashKeys.Insert(key->hashval, key); + + /* Keep a list of all the registered keys */ + _listKeys.Append(key); + + return key; +} + +const pb_key *const pb_key_accept = _create_key("accept"); +const pb_key *const pb_key_accept_charset = _create_key("accept-charset"); +const pb_key *const pb_key_accept_encoding = _create_key("accept-encoding"); +const pb_key *const pb_key_accept_language = _create_key("accept-language"); +const pb_key *const pb_key_accept_ranges = _create_key("accept-ranges"); +const pb_key *const pb_key_actual_route = _create_key("actual-route"); +const pb_key *const pb_key_age = _create_key("age"); +const pb_key *const pb_key_always_allow_chunked = _create_key("always-allow-chunked"); +const pb_key *const pb_key_always_use_keep_alive = _create_key("always-use-keep-alive"); +const pb_key *const pb_key_auth_cert = _create_key("auth-cert"); +const pb_key *const pb_key_auth_expiring = _create_key("auth-expiring"); +const pb_key *const pb_key_auth_group = _create_key("auth-group"); +const pb_key *const pb_key_auth_type = _create_key("auth-type"); +const pb_key *const pb_key_auth_user = _create_key("auth-user"); +const pb_key *const pb_key_authorization = _create_key("authorization"); +const pb_key *const pb_key_browser = _create_key("browser"); +const pb_key *const pb_key_c2p_cl = _create_key("c2p-cl"); +const pb_key *const pb_key_c2p_hl = _create_key("c2p-hl"); +const pb_key *const pb_key_cache_info = _create_key("cache-info"); +const pb_key *const pb_key_charset = _create_key("charset"); +const pb_key *const pb_key_check_http_server = _create_key("check-http-server"); +const pb_key *const pb_key_ChunkedRequestBufferSize = _create_key("ChunkedRequestBufferSize"); +const pb_key *const pb_key_ChunkedRequestTimeout = _create_key("ChunkedRequestTimeout"); +const pb_key *const pb_key_cipher = _create_key("cipher"); +const pb_key *const pb_key_clf_request = _create_key("clf-request"); +const pb_key *const pb_key_cli_status = _create_key("cli-status"); +const pb_key *const pb_key_client_cert_nickname = _create_key("client-cert-nickname"); +const pb_key *const pb_key_client_ip = _create_key("client-ip"); +const pb_key *const pb_key_close = _create_key("close"); +const pb_key *const pb_key_connect_timeout = _create_key("connect-timeout"); +const pb_key *const pb_key_connection = _create_key("connection"); +const pb_key *const pb_key_cont = _create_key("cont"); +const pb_key *const pb_key_content_encoding = _create_key("content-encoding"); +const pb_key *const pb_key_content_language = _create_key("content-language"); +const pb_key *const pb_key_content_length = _create_key("content-length"); +const pb_key *const pb_key_content_location = _create_key("content-location"); +const pb_key *const pb_key_content_md5 = _create_key("content-md5"); +const pb_key *const pb_key_content_range = _create_key("content-range"); +const pb_key *const pb_key_content_type = _create_key("content-type"); +const pb_key *const pb_key_cookie = _create_key("cookie"); +const pb_key *const pb_key_date = _create_key("date"); +const pb_key *const pb_key_DATE_GMT = _create_key("DATE_GMT"); +const pb_key *const pb_key_DATE_LOCAL = _create_key("DATE_LOCAL"); +const pb_key *const pb_key_dir = _create_key("dir"); +const pb_key *const pb_key_Directive = _create_key("Directive"); +const pb_key *const pb_key_dns = _create_key("dns"); +const pb_key *const pb_key_DOCUMENT_NAME = _create_key("DOCUMENT_NAME"); +const pb_key *const pb_key_DOCUMENT_URI = _create_key("DOCUMENT_URI"); +const pb_key *const pb_key_domain = _create_key("domain"); +const pb_key *const pb_key_enc = _create_key("enc"); +const pb_key *const pb_key_engine = _create_key("engine"); +const pb_key *const pb_key_error_action = _create_key("error-action"); +const pb_key *const pb_key_error_desc = _create_key("error-desc"); +const pb_key *const pb_key_error_fn = _create_key("error-fn"); +const pb_key *const pb_key_escape = _create_key("escape"); +const pb_key *const pb_key_escaped = _create_key("escaped"); +const pb_key *const pb_key_etag = _create_key("etag"); +const pb_key *const pb_key_expect = _create_key("expect"); +const pb_key *const pb_key_expires = _create_key("expires"); +const pb_key *const pb_key_expr = _create_key("expr"); +const pb_key *const pb_key_filter = _create_key("filter"); +const pb_key *const pb_key_find_pathinfo_forward = _create_key("find-pathinfo-forward"); +const pb_key *const pb_key_flushTimer = _create_key("flushTimer"); +const pb_key *const pb_key_fn = _create_key("fn"); +const pb_key *const pb_key_from = _create_key("from"); +const pb_key *const pb_key_full_headers = _create_key("full-headers"); +const pb_key *const pb_key_hdr = _create_key("hdr"); +const pb_key *const pb_key_host = _create_key("host"); +const pb_key *const pb_key_hostname = _create_key("hostname"); +const pb_key *const pb_key_if_match = _create_key("if-match"); +const pb_key *const pb_key_if_modified_since = _create_key("if-modified-since"); +const pb_key *const pb_key_if_none_match = _create_key("if-none-match"); +const pb_key *const pb_key_if_range = _create_key("if-range"); +const pb_key *const pb_key_if_unmodified_since = _create_key("if-unmodified-since"); +const pb_key *const pb_key_ip = _create_key("ip"); +const pb_key *const pb_key_iponly = _create_key("iponly"); +const pb_key *const pb_key_issuer_dn = _create_key("issuer_dn"); +const pb_key *const pb_key_jroute = _create_key("jroute"); +const pb_key *const pb_key_keep_alive = _create_key("keep-alive"); +const pb_key *const pb_key_keep_alive_timeout = _create_key("keep-alive-timeout"); +const pb_key *const pb_key_keysize = _create_key("keysize"); +const pb_key *const pb_key_lang = _create_key("lang"); +const pb_key *const pb_key_LAST_MODIFIED = _create_key("LAST_MODIFIED"); +const pb_key *const pb_key_last_modified = _create_key("last-modified"); +const pb_key *const pb_key_level = _create_key("level"); +const pb_key *const pb_key_location = _create_key("location"); +const pb_key *const pb_key_lock_owner = _create_key("lock-owner"); +const pb_key *const pb_key_magnus_charset = _create_key("magnus-charset"); +const pb_key *const pb_key_magnus_internal = _create_key("magnus-internal"); +const pb_key *const pb_key_magnus_internal_dav_src = _create_key("magnus-internal/dav-src"); +const pb_key *const pb_key_magnus_internal_default_acls_only = _create_key("magnus-internal/default-acls-only"); +const pb_key *const pb_key_magnus_internal_error_j2ee = _create_key("magnus-internal/error-j2ee"); +const pb_key *const pb_key_magnus_internal_j2ee_nsapi = _create_key("magnus-internal/j2ee-nsapi"); +const pb_key *const pb_key_magnus_internal_preserve_srvhdrs = _create_key("magnus-internal/preserve-srvhdrs-after-req-restart"); +const pb_key *const pb_key_magnus_internal_set_request_status = _create_key("magnus-internal/set-request-status"); +const pb_key *const pb_key_magnus_internal_set_response_status = _create_key("magnus-internal/set-response-status"); +const pb_key *const pb_key_magnus_internal_webapp_errordesc = _create_key("magnus-internal/webapp-errordesc"); +const pb_key *const pb_key_matched_browser = _create_key("matched-browser"); +const pb_key *const pb_key_max_age = _create_key("max-age"); +const pb_key *const pb_key_max_forwards = _create_key("max-forwards"); +const pb_key *const pb_key_message = _create_key("message"); +const pb_key *const pb_key_method = _create_key("method"); +const pb_key *const pb_key_name = _create_key("name"); +const pb_key *const pb_key_nocache = _create_key("nocache"); +const pb_key *const pb_key_nostat = _create_key("nostat"); +const pb_key *const pb_key_ntrans_base = _create_key("ntrans-base"); +const pb_key *const pb_key_offline_origin_addr = _create_key("offline-origin-addr"); +const pb_key *const pb_key_offline_proxy_addr = _create_key("offline-proxy-addr"); +const pb_key *const pb_key_origin_addr = _create_key("origin-addr"); +const pb_key *const pb_key_p2c_cl = _create_key("p2c-cl"); +const pb_key *const pb_key_p2c_hl = _create_key("p2c-hl"); +const pb_key *const pb_key_p2r_cl = _create_key("p2r-cl"); +const pb_key *const pb_key_p2r_hl = _create_key("p2r-hl"); +const pb_key *const pb_key_parse_timeout = _create_key("parse-timeout"); +const pb_key *const pb_key_password = _create_key("password"); +const pb_key *const pb_key_path = _create_key("path"); +const pb_key *const pb_key_PATH_INFO = _create_key("PATH_INFO"); +const pb_key *const pb_key_path_info = _create_key("path-info"); +const pb_key *const pb_key_pblock = _create_key("pblock"); +const pb_key *const pb_key_poll_interval = _create_key("poll-interval"); +const pb_key *const pb_key_port = _create_key("port"); +const pb_key *const pb_key_ppath = _create_key("ppath"); +const pb_key *const pb_key_pragma = _create_key("pragma"); +const pb_key *const pb_key_process_request_body = _create_key("process-request-body"); +const pb_key *const pb_key_process_response_body = _create_key("process-response-body"); +const pb_key *const pb_key_protocol = _create_key("protocol"); +const pb_key *const pb_key_proxy_addr = _create_key("proxy-addr"); +const pb_key *const pb_key_proxy_agent = _create_key("proxy-agent"); +const pb_key *const pb_key_proxy_auth_cert = _create_key("proxy-auth-cert"); +const pb_key *const pb_key_proxy_authorization = _create_key("proxy-authorization"); +const pb_key *const pb_key_proxy_cipher = _create_key("proxy-cipher"); +const pb_key *const pb_key_proxy_issuer_dn = _create_key("proxy-issuer-dn"); +const pb_key *const pb_key_proxy_jroute = _create_key("proxy-jroute"); +const pb_key *const pb_key_proxy_keysize = _create_key("proxy-keysize"); +const pb_key *const pb_key_proxy_ping = _create_key("proxy-ping"); +const pb_key *const pb_key_proxy_request = _create_key("proxy-request"); +const pb_key *const pb_key_proxy_secret_keysize = _create_key("proxy-secret-keysize"); +const pb_key *const pb_key_proxy_ssl_id = _create_key("proxy-ssl-id"); +const pb_key *const pb_key_proxy_user_dn = _create_key("proxy-user-dn"); +const pb_key *const pb_key_query = _create_key("query"); +const pb_key *const pb_key_QUERY_STRING = _create_key("QUERY_STRING"); +const pb_key *const pb_key_QUERY_STRING_UNESCAPED = _create_key("QUERY_STRING_UNESCAPED"); +const pb_key *const pb_key_r2p_cl = _create_key("r2p-cl"); +const pb_key *const pb_key_r2p_hl = _create_key("r2p-hl"); +const pb_key *const pb_key_range = _create_key("range"); +const pb_key *const pb_key_referer = _create_key("referer"); +const pb_key *const pb_key_reformat_request_headers = _create_key("reformat-request-headers"); +const pb_key *const pb_key_remote_status = _create_key("remote-status"); +const pb_key *const pb_key_request_jroute = _create_key("request-jroute"); +const pb_key *const pb_key_required_rights = _create_key("required-rights"); +const pb_key *const pb_key_retries = _create_key("retries"); +const pb_key *const pb_key_rewrite_content_location = _create_key("rewrite-content-location"); +const pb_key *const pb_key_rewrite_host = _create_key("rewrite-host"); +const pb_key *const pb_key_rewrite_location = _create_key("rewrite-location"); +const pb_key *const pb_key_rewrite_set_cookie = _create_key("rewrite-set-cookie"); +const pb_key *const pb_key_root = _create_key("root"); +const pb_key *const pb_key_route = _create_key("route"); +const pb_key *const pb_key_route_cookie = _create_key("route-cookie"); +const pb_key *const pb_key_route_hdr = _create_key("route-hdr"); +const pb_key *const pb_key_route_offline = _create_key("route-offline"); +const pb_key *const pb_key_script_name = _create_key("script-name"); +const pb_key *const pb_key_secret_keysize = _create_key("secret-keysize"); +const pb_key *const pb_key_secure = _create_key("secure"); +const pb_key *const pb_key_server = _create_key("server"); +const pb_key *const pb_key_set_cookie = _create_key("set-cookie"); +const pb_key *const pb_key_socks_addr = _create_key("socks_addr"); +const pb_key *const pb_key_ssl_id = _create_key("ssl-id"); +const pb_key *const pb_key_ssl_unclean_shutdown = _create_key("ssl-unclean-shutdown"); +const pb_key *const pb_key_status = _create_key("status"); +const pb_key *const pb_key_sticky_cookie = _create_key("sticky-cookie"); +const pb_key *const pb_key_sticky_param = _create_key("sticky-param"); +const pb_key *const pb_key_suppress_request_headers = _create_key("suppress-request-headers"); +const pb_key *const pb_key_svr_status = _create_key("svr-status"); +const pb_key *const pb_key_timeout = _create_key("timeout"); +const pb_key *const pb_key_to = _create_key("to"); +const pb_key *const pb_key_transfer_encoding = _create_key("transfer-encoding"); +const pb_key *const pb_key_transmit_timeout = _create_key("transmit-timeout"); +const pb_key *const pb_key_tunnel_non_http_response = _create_key("tunnel-non-http-response"); +const pb_key *const pb_key_type = _create_key("type"); +const pb_key *const pb_key_upstream_jroute = _create_key("upstream-jroute"); +const pb_key *const pb_key_uri = _create_key("uri"); +const pb_key *const pb_key_url = _create_key("url"); +const pb_key *const pb_key_url_prefix = _create_key("url-prefix"); +const pb_key *const pb_key_UseOutputStreamSize = _create_key("UseOutputStreamSize"); +const pb_key *const pb_key_user = _create_key("user"); +const pb_key *const pb_key_user_agent = _create_key("user-agent"); +const pb_key *const pb_key_user_dn = _create_key("user_dn"); +const pb_key *const pb_key_validate_server_cert = _create_key("validate-server-cert"); +const pb_key *const pb_key_value = _create_key("value"); +const pb_key *const pb_key_vary = _create_key("vary"); +const pb_key *const pb_key_via = _create_key("via"); +const pb_key *const pb_key_warning = _create_key("warning"); + + +/* ------------------------------ _find_key ------------------------------- */ + +static inline const pb_key *_find_key(const char *name, unsigned int hashval) +{ + /* Check to see if name corresponds to a pb_key */ + CListConstIterator iter(&_hashKeys.Find(hashval)); + const pb_key *key; + while (key = ++iter) { + if (key->hashval == hashval && !strcmp(key->name, name)) + return key; + } + return NULL; +} + + +/* --------------------------- _get_hash_index ---------------------------- */ + +static inline int _get_hash_index(const PListStruct_t *pl, const pb_key *key) +{ + /* Get the hash index from the key. Requires a symbol table. */ + int i; + if (key->sizendx == pl->pl_symtab->pt_sizendx) + i = key->hashndx; + else + i = key->hashval % PLSIZENDX(pl->pl_symtab->pt_sizendx); + return i; +} + + +/* ---------------------------- _param_create ----------------------------- */ + +static inline pb_param *_param_create(pool_handle_t *pool_handle, const char *name, int namelen, const char *value, int valuelen) +{ + PLValueStruct_t *ret; + + ret = (PLValueStruct_t *)pool_malloc(pool_handle, sizeof(PLValueStruct_t)); + + ret->pv_pbentry.param = &ret->pv_pbparam; + ret->pv_pbentry.next = 0; + ret->pv_next = 0; + ret->pv_type = 0; + ret->pv_mempool = pool_handle; + + if (name || namelen) { + ret->pv_name = (char*)pool_malloc(pool_handle, namelen + 1); + if (name) { + memcpy(ret->pv_name, name, namelen); + ret->pv_name[namelen] = '\0'; + } else { + ret->pv_name[0] = '\0'; + } + } else { + ret->pv_name = 0; + } + + if (value || valuelen) { + ret->pv_value = (char*)pool_malloc(pool_handle, valuelen + 1); + if (value) { + memcpy(ret->pv_value, value, valuelen); + ret->pv_value[valuelen] = '\0'; + } else { + ret->pv_value[0] = '\0'; + } + } else { + ret->pv_value = 0; + } + + return &ret->pv_pbparam; +} + + +/* ----------------------- pblock_key_param_create ----------------------- */ + +NSAPI_PUBLIC pb_param *pblock_key_param_create(pblock *pb, const pb_key *key, const char *value, int valuelen) +{ + /* + * Allocate a PLValueStruct_t from the property list's memory pool. + */ + PListStruct_t *pl = PBTOPL(pb); + return _param_create(pl->pl_mempool, key->name, key->namelen, value, valuelen); +} + + +/* ------------------------- pblock_param_create -------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_param_create(pblock *pb, const char *name, const char *value) +{ + /* + * Allocate a PLValueStruct_t from the property list's memory pool. + */ + PListStruct_t *pl = PBTOPL(pb); + return _param_create(pl->pl_mempool, name, name ? strlen(name) : 0, value, value ? strlen(value) : 0); +} + + +/* ----------------------------- param_create ----------------------------- */ + +NSAPI_PUBLIC pb_param *param_create(const char *name, const char *value) +{ + /* + * Allocate a PLValueStruct_t containing the pb_param that will + * be returned. Normally PLValueStruct_ts are allocated from the + * memory pool associated with a property list, but we don't have + * that here, so we just use the thread's pool and indicate we were + * allocated from a specific pool. + */ + return _param_create(system_pool(), name, name ? strlen(name) : 0, value, value ? strlen(value) : 0); +} + + +/* ------------------------------ param_free ------------------------------ */ + +NSAPI_PUBLIC int param_free(pb_param *pp) +{ + if (pp) { + PLValueStruct_t *pv = PATOPV(pp); + + /* Don't bother if the pblock was allocated from a pool */ + if (!pv->pv_mempool) { + pool_free(pv->pv_mempool, pv->pv_name); + pool_free(pv->pv_mempool, pv->pv_value); + pool_free(pv->pv_mempool, pv); + } + + return 1; + } + + return 0; +} + + +/* -------------------------- pblock_create_pool -------------------------- */ + +NSAPI_PUBLIC pblock *pblock_create_pool(pool_handle_t *pool_handle, int n) +{ + /* Create a property list with n property indices */ + PListStruct_t *plist = (PListStruct_t *)PListCreate(pool_handle, n, 0, 0); + if (!plist) + return NULL; + + plist->pl_resvpi = 0; + + return &plist->pl_pb; +} + + +/* ----------------------------- pblock_pool ------------------------------ */ + +NSAPI_PUBLIC pool_handle_t *pblock_pool(pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + return pl->pl_mempool; +} + + +/* ---------------------------- pblock_create ----------------------------- */ + +NSAPI_PUBLIC pblock *pblock_create(int n) +{ + return pblock_create_pool(MALLOC_POOL_HANDLE, n); +} + + +/* ----------------------------- pblock_free ------------------------------ */ + +NSAPI_PUBLIC void pblock_free(pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + int i; + + if (!pb) { + return; + } + + /* If the pools are enabled, this routine has no effect anyway, so + * just return. + */ + if (pl->pl_mempool || pool_enabled()) { + return; + } + + /* Free the property name symbol table if any */ + if (pl->pl_symtab) { + pool_free(pl->pl_mempool, (void *)(pl->pl_symtab)); + } + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Loop over the initialized property indices */ + for (i = 0; i < pl->pl_initpi; ++i) { + + /* Got a property here? */ + pv = ppval[i]; + if (pv) { + + param_free(&pv->pv_pbparam); + } + } + + /* Free the array of pointers to property values */ + pool_free(pl->pl_mempool, (void *)ppval); + + /* Free the property list head */ + pool_free(pl->pl_mempool, (void *)pl); +} + + +/* ------------------------------ pblock_key ------------------------------ */ + +NSAPI_PUBLIC const pb_key *pblock_key(const char *name) +{ + if (!name) + return NULL; + + return _find_key(name, PListHash(name)); +} + + +/* --------------------------- pblock_kpinsert ---------------------------- */ + +NSAPI_PUBLIC void pblock_kpinsert(const pb_key *key, pb_param *pp, pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + PLValueStruct_t *pv = PATOPV(pp); + + PR_ASSERT(pv->pv_mempool == pl->pl_mempool); + + /* Check to see if the name corresponds to a pb_key */ + unsigned int hashval; + if (!key) { + hashval = PListHash(pv->pv_name); + key = _find_key(pv->pv_name, hashval); + } + + /* Find property index */ + int pindex = PListGetFreeIndex(pl); + if (pindex < 1) { + /* Error - invalid property index */ + return; + } + + /* Allocate/grow the symbol table as needed */ + PLSymbolTable_t *pt = PListSymbolTable(pl); + if (!pt) { + return; + } + + /* Add PLValueStruct_t to the property list */ + PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval); + pv->pv_pbkey = key; + pv->pv_pi = pindex; + ppval[pv->pv_pi - 1] = pv; + + /* Add name to symbol table */ + int i = key ? _get_hash_index(pl, key) : (hashval % PLSIZENDX(pt->pt_sizendx)); + pv->pv_next = pt->pt_hash[i]; + pt->pt_hash[i] = pv; + pt->pt_nsyms++; + + PR_ASSERT(param_key(pp) == key); +} + + +/* ---------------------------- pblock_pinsert ---------------------------- */ + +NSAPI_PUBLIC void pblock_pinsert(pb_param *pp, pblock *pb) +{ + pblock_kpinsert(NULL, pp, pb); +} + + +/* --------------------------- pblock_nvinsert ---------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_nvinsert(const char *name, const char *value, pblock *pb) +{ + pb_param *pp = pblock_param_create(pb, name, value); + if (pp) + pblock_kpinsert(NULL, pp, pb); + return pp; +} + + +/* --------------------------- pblock_kvinsert ---------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_kvinsert(const pb_key *key, const char *value, int valuelen, pblock *pb) +{ + pb_param *pp = pblock_key_param_create(pb, key, value, valuelen); + if (pp) + pblock_kpinsert(key, pp, pb); + return pp; +} + + +/* --------------------------- pblock_nninsert ---------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_nninsert(const char *name, int value, pblock *pb) +{ + char num[UTIL_ITOA_SIZE]; + + util_itoa(value, num); + return pblock_nvinsert(name, num, pb); +} + + +/* --------------------------- pblock_kninsert ---------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_kninsert(const pb_key *key, int value, pblock *pb) +{ + pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_ITOA_SIZE); + if (pp) { + util_itoa(value, pp->value); + pblock_kpinsert(key, pp, pb); + } + return pp; +} + + +/* --------------------------- pblock_kllinsert --------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_kllinsert(const pb_key *key, PRInt64 value, pblock *pb) +{ + pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_I64TOA_SIZE); + if (pp) { + util_i64toa(value, pp->value); + pblock_kpinsert(key, pp, pb); + } + return pp; +} + + +/* ---------------------------- pblock_findkey ---------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_findkey(const pb_key *key, const pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + + /* Lookup key by examining symbol table */ + if (pl->pl_symtab) { + int i = _get_hash_index(pl, key); + PLValueStruct_t *pv; + + /* Search hash collision list for matching name */ + for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) { + if (pv->pv_pbkey == key) + return &pv->pv_pbparam; + } + } + + return NULL; +} + + +/* -------------------------- pblock_findkeyval --------------------------- */ + +NSAPI_PUBLIC char *pblock_findkeyval(const pb_key *key, const pblock *pb) +{ + pb_param *pp = pblock_findkey(key, pb); + return pp ? pp->value : NULL; +} + + +/* ---------------------------- pblock_findval ---------------------------- */ + +NSAPI_PUBLIC char *pblock_findval(const char *name, const pblock *pb) +{ + void *pvalue = 0; + + (void)PListFindValue((PList_t)(PBTOPL(pb)), name, &pvalue, 0); + + return (char *)pvalue; +} + + +/* ------------------------------ pblock_fr ------------------------------ */ + +NSAPI_PUBLIC pb_param *pblock_fr(const char *name, pblock *pb, int remove) +{ + PListStruct_t *pl = PBTOPL(pb); + PLValueStruct_t **ppval; + PLValueStruct_t **pvp; + PLValueStruct_t *pv = NULL; + int pindex; + int i; + + if (pl->pl_symtab) { + + /* Compute hash index of specified property name */ + i = PListHashName(pl->pl_symtab, name); + + /* Search hash collision list for matching name */ + for (pvp = &pl->pl_symtab->pt_hash[i]; + (pv = *pvp); pvp = &(*pvp)->pv_next) { + + if (!strcmp(name, pv->pv_name)) { + + if (remove) { + /* Remove PLValueStruct_t from symbol table */ + *pvp = pv->pv_next; + pl->pl_symtab->pt_nsyms--; + + /* Remove it from pl_ppval too */ + ppval = (PLValueStruct_t **)(pl->pl_ppval); + pindex = pv->pv_pi; + ppval[pindex - 1] = 0; + } + break; + } + } + } + + return (pv) ? &pv->pv_pbparam : NULL; +} + + +/* --------------------------- pblock_removekey --------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_removekey(const pb_key *key, pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + PLValueStruct_t **ppval; + PLValueStruct_t **pvp; + PLValueStruct_t *pv = NULL; + int pindex; + int i; + + if (pl->pl_symtab) { + /* Lookup hash index for specified property key */ + i = _get_hash_index(pl, key); + + /* Search hash collision list for matching key */ + for (pvp = &pl->pl_symtab->pt_hash[i]; (pv = *pvp); pvp = &pv->pv_next) { + /* If this value has the requested key... */ + if (pv->pv_pbkey == key) { + /* Remove PLValueStruct_t from symbol table */ + *pvp = pv->pv_next; + pl->pl_symtab->pt_nsyms--; + + /* Remove it from pl_ppval too */ + ppval = (PLValueStruct_t **)(pl->pl_ppval); + pindex = pv->pv_pi; + ppval[pindex - 1] = 0; + + break; + } + } + } + + return (pv) ? &pv->pv_pbparam : NULL; +} + + +/* -------------------------- pblock_removeone --------------------------- */ + +NSAPI_PUBLIC pb_param *pblock_removeone(pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + + if (pl && pl->pl_symtab) { + /* Search hash buckets */ + for (int i = 0; i < PLSIZENDX(pl->pl_symtab->pt_sizendx); i++) { + /* Search hash collision list */ + PLValueStruct_t *pv = pl->pl_symtab->pt_hash[i]; + if (pv) { + /* Remove PLValueStruct_t from symbol table */ + pl->pl_symtab->pt_hash[i] = pv->pv_next; + pl->pl_symtab->pt_nsyms--; + + /* Remove it from pl_ppval too */ + PLValueStruct_t **ppval = (PLValueStruct_t**)pl->pl_ppval; + ppval[pv->pv_pi - 1] = 0; + + return &pv->pv_pbparam; + } + } + } + + return NULL; +} + + +/* -------------------------- pblock_str2pblock --------------------------- */ + + +int _verify_pbstr(const char *str) +{ + const char *cp; + const char *scp; + int np; + int state; + int quote; + + for(cp = str, np = 0, state = 0; *cp; ) { + switch (state) { + case 0: /* skipping leading spaces */ + + while (*cp && isspace(*cp)) ++cp; + if (*cp == '=') { + return -1; + } + if (*cp) state = 1; + break; + + case 1: /* scanning parameter name */ + + scp = cp; + while (*cp && (*cp != '=') && !isspace(*cp)) ++cp; + if (*cp == '=') ++cp; + else cp = scp; + state = 2; + break; + + case 2: /* scanning parameter value */ + quote = 0; + if (*cp == '\"') { + quote = 1; + ++cp; + } + for (;;) { + if (*cp == '\\') { + ++cp; + if (*cp == 0) { + return -1; + } + } + else if (*cp == '\"') { + if (!quote) { + return -1; + } + ++np; + ++cp; + quote = 0; + state = 0; + break; + } + else if (!quote && (!*cp || isspace(*cp))) { + ++np; + if (*cp) ++cp; + state = 0; + break; + } + else if (*cp == 0) { + return -1; + } + ++cp; + } + if (quote) { + return -1; + } + break; + } + } + + return (state == 0) ? np : -1; +} + +NSAPI_PUBLIC int +INTpblock_str2pblock_lowercasename(const char *str, pblock *pb) +{ + return _pblock_str2pblock(str, pb, PR_TRUE); +} + +NSAPI_PUBLIC int pblock_str2pblock(const char *str, pblock *pb) +{ + return _pblock_str2pblock(str, pb, PR_FALSE); +} + +int +_pblock_str2pblock(const char* str, pblock* pb, PRBool lowerCase) +{ + char *cpy; + char *cp; + char *dp; + char *pname; + char *pvalue; + int np; + int quote; + int state; + char numbuf[UTIL_ITOA_SIZE]; + + if((np = _verify_pbstr(str)) < 1) + return -1; + + while (*str && isspace(*str)) ++str; + + cpy = STRDUP(str); + + for (np = 0, cp = cpy, state = 0; *cp; ) { + switch (state) { + + case 0: /* skipping leading spaces */ + + while (*cp && isspace(*cp)) ++cp; + if (*cp) state = 1; + break; + + case 1: /* scanning parameter name */ + + pname = cp; + while (*cp && (*cp != '=') && !isspace(*cp)) ++cp; + if (*cp == '=') { + *cp++ = 0; + } + else { + cp = pname; + pname = numbuf; + util_itoa(np+1, numbuf); + } + state = 2; + break; + + case 2: /* scanning parameter value */ + quote = 0; + if (*cp == '\"') { + quote = 1; + ++cp; + } + for (pvalue = cp, dp = cp; ; ++cp, ++dp) { + if (*cp == '\\') { + ++cp; + } + else if (*cp == '\"') { + ++np; + ++cp; + *dp = 0; + quote = 0; + state = 0; + break; + } + else if (!quote && ((*cp == 0) || isspace(*cp))) { + ++np; + if (*cp != 0) { + ++cp; + } + *dp = 0; + state = 0; + break; + } + if (cp != dp) *dp = *cp; + } + if (lowerCase == PR_TRUE) { + for (char* p = pname; *p; p++) { + *p = tolower(*p); + } + } + pblock_nvinsert(pname, pvalue, pb); + break; + } + } + + FREE(cpy); + + return np; +} + + +/* -------------------------- pblock_pblock2str --------------------------- */ + + +NSAPI_PUBLIC char *pblock_pblock2str(const pblock *pb, char *str) +{ + register char *s = str, *t, *u; + PListStruct_t *pl = PBTOPL(pb); + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + int i; + int sl; + int xlen; + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Loop over the initialized property indices */ + for (i = 0, xlen = 0; i < pl->pl_initpi; ++i) { + + /* Got a property here? */ + pv = ppval[i]; + if (pv && pv->pv_name) { + + int ln = strlen(pv->pv_name); + int lv = strlen((char *)(pv->pv_value)); + + /* Check for " or \ because we'll have to escape them */ + for (t = (char *)(pv->pv_value); *t; ++t) { + if ((*t == '\"') || (*t == '\\')) ++lv; + } + + /* 4: two quotes, =, and a null */ + xlen += (ln + lv + 4); + } + } + + /* Allocate string to hold parameter settings, or increase size */ + if (!s) { + s = (char *)MALLOC(xlen); + s[0] = '\0'; + t = &s[0]; + sl = xlen; + } + else { + sl = strlen(s); + t = &s[sl]; + sl += xlen; + s = (char *)REALLOC(s, sl); + } + + /* Loop over the initialized property indices */ + for (i = 0; i < pl->pl_initpi; ++i) { + + /* Got a property here? */ + pv = ppval[i]; + if (pv && pv->pv_name) { + + if (t != s) *t++ = ' '; + + for (u = pv->pv_name; *u; ) *t++ = *u++; + + *t++ = '='; + *t++ = '\"'; + + for (u = (char *)(pv->pv_value); *u; ) { + if ((*u == '\\') || (*u == '\"')) *t++ = '\\'; + *t++ = *u++; + } + + *t++ = '\"'; + *t = '\0'; + } + } + + return s; +} + + +/* ----------------------------- pblock_copy ------------------------------ */ + + +NSAPI_PUBLIC int pblock_copy(const pblock *src, pblock *dst) +{ + PListStruct_t *pl = PBTOPL(src); + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + int rv = 0; + int i; + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + for (i = 0; i < pl->pl_initpi; ++i) { + pv = ppval[i]; + if (pv) { + if (pv->pv_pbkey) { + if (pv->pv_pbkey != pb_key_magnus_internal) { + if (!pblock_kvinsert(pv->pv_pbkey, (char *)(pv->pv_value), strlen(pv->pv_value), dst)) + rv = -1; + } + } else { + if (!pblock_nvinsert(pv->pv_name, (char *)(pv->pv_value), dst)) + rv = -1; + } + } + } + + return rv; +} + +/* ---------------------------- pblock_dup -------------------------------- */ + +NSAPI_PUBLIC pblock *pblock_dup(const pblock *src) +{ + pblock *dst; + + if (!src) + return NULL; + + if ( (dst = pblock_create(src->hsize)) ) + pblock_copy(src, dst); + + return dst; +} + + +/* ---------------------------- pblock_pb2env ----------------------------- */ + +/* +NSAPI_PUBLIC char **pblock_pb2env(const pblock *pb, char **env) +{ + PListStruct_t *pl = PBTOPL(pb); + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + int i; + int nval; + int pos; + + /* Find out how many there are. */ + /* + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + for (i = 0, nval = 0; i < pl->pl_initpi; ++i) { + if (ppval[i]) ++nval; + } + + env = util_env_create(env, nval, &pos); + + for (i = 0; i < pl->pl_initpi; ++i) { + pv = ppval[i]; + if (pv) { + env[pos++] = util_env_str(pv->pv_name, (char *)(pv->pv_value)); + } + } + env[pos] = NULL; + + return env; +} +*/ + +/* ---------------------------- pblock_replace ---------------------------- */ + +NSAPI_PUBLIC char * pblock_replace(const char *name, + char * new_value, pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + + /* Replace an existing value */ + pb_param *pp = pblock_find(name, pb); + if (!pp) + return NULL; + pool_free(pl->pl_mempool, pp->value); + pp->value = new_value; + + return new_value; +} + + +/* --------------------------- pblock_nvreplace --------------------------- */ + +NSAPI_PUBLIC void pblock_nvreplace (const char *name, const char *value, pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + + /* Replace an existing value or insert a new value */ + pb_param *pp = pblock_find(name, pb); + if (pp) { + pool_free(pl->pl_mempool, pp->value); + pp->value = pool_strdup(pl->pl_mempool, value); + } else { + pblock_nvinsert(name, value, pb); + } +} + + +/* --------------------------- pblock_kvreplace --------------------------- */ + +NSAPI_PUBLIC void pblock_kvreplace(const pb_key *key, const char *value, int valuelen, pblock *pb) +{ + PListStruct_t *pl = PBTOPL(pb); + + /* Replace an existing value or insert a new value */ + pb_param *pp = pblock_findkey(key, pb); + if (pp) { + pool_free(pl->pl_mempool, pp->value); + pp->value = (char*)pool_malloc(pl->pl_mempool, valuelen + 1); + memcpy(pp->value, value, valuelen + 1); + } else { + pblock_kvinsert(key, value, valuelen, pb); + } +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/pblock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/pblock.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,362 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_PBLOCK_H +#define BASE_PBLOCK_H + +#ifndef NOINTNSAPI +#define INTNSAPI +#endif /* !NOINTNSAPI */ + +/* + * pblock.h: Header for Parameter Block handling functions + * + * + * A parameter block is a set of name=value pairs which are generally used + * as parameters, but can be anything. They are kept in a hash table for + * reasonable speed, but if you are doing any intensive modification or + * access of them you should probably make a local copy of each parameter + * while working. + * + * Rob McCool + * + */ + +#ifndef NETSITE_H +#include "nsapi.h" +#include "netsite.h" +#endif /* !NETSITE_H */ + +#ifdef XP_WIN32 +#ifdef BUILD_DLL +#define BASE_DLL _declspec(dllexport) +#else +#define BASE_DLL _declspec(dllimport) +#endif +#else +#define BASE_DLL +#endif + +#ifdef INTNSAPI + +/* --- Begin function prototypes --- */ + +NSPR_BEGIN_EXTERN_C + +NSAPI_PUBLIC pb_param *INTparam_create(const char *name, const char *value); + +NSAPI_PUBLIC int INTparam_free(pb_param *pp); + +NSAPI_PUBLIC pblock *INTpblock_create(int n); + +NSAPI_PUBLIC void INTpblock_free(pblock *pb); + +NSAPI_PUBLIC char *INTpblock_findval(const char *name, const pblock *pb); + +NSAPI_PUBLIC pb_param *INTpblock_nvinsert(const char *name, const char *value, pblock *pb); + +NSAPI_PUBLIC pb_param *INTpblock_nninsert(const char *name, int value, pblock *pb); + +NSAPI_PUBLIC void INTpblock_pinsert(pb_param *pp, pblock *pb); + +NSAPI_PUBLIC int INTpblock_str2pblock(const char *str, pblock *pb); + +NSAPI_PUBLIC char *INTpblock_pblock2str(const pblock *pb, char *str); + +NSAPI_PUBLIC int INTpblock_copy(const pblock *src, pblock *dst); + +NSAPI_PUBLIC pblock *INTpblock_dup(const pblock *src); + +NSAPI_PUBLIC char **INTpblock_pb2env(const pblock *pb, char **env); + +NSAPI_PUBLIC void pblock_nvreplace (const char *name, const char *value, pblock *pb); + +/* --------------------------- Internal things ---------------------------- */ + +typedef struct pb_key pb_key; + +BASE_DLL extern const pb_key *const pb_key_accept; +BASE_DLL extern const pb_key *const pb_key_accept_charset; +BASE_DLL extern const pb_key *const pb_key_accept_encoding; +BASE_DLL extern const pb_key *const pb_key_accept_language; +BASE_DLL extern const pb_key *const pb_key_accept_ranges; +BASE_DLL extern const pb_key *const pb_key_actual_route; +BASE_DLL extern const pb_key *const pb_key_age; +BASE_DLL extern const pb_key *const pb_key_always_allow_chunked; +BASE_DLL extern const pb_key *const pb_key_always_use_keep_alive; +BASE_DLL extern const pb_key *const pb_key_auth_cert; +BASE_DLL extern const pb_key *const pb_key_auth_expiring; +BASE_DLL extern const pb_key *const pb_key_auth_group; +BASE_DLL extern const pb_key *const pb_key_auth_type; +BASE_DLL extern const pb_key *const pb_key_auth_user; +BASE_DLL extern const pb_key *const pb_key_authorization; +BASE_DLL extern const pb_key *const pb_key_browser; +BASE_DLL extern const pb_key *const pb_key_c2p_cl; +BASE_DLL extern const pb_key *const pb_key_c2p_hl; +BASE_DLL extern const pb_key *const pb_key_cache_info; +BASE_DLL extern const pb_key *const pb_key_charset; +BASE_DLL extern const pb_key *const pb_key_check_http_server; +BASE_DLL extern const pb_key *const pb_key_ChunkedRequestBufferSize; +BASE_DLL extern const pb_key *const pb_key_ChunkedRequestTimeout; +BASE_DLL extern const pb_key *const pb_key_cipher; +BASE_DLL extern const pb_key *const pb_key_clf_request; +BASE_DLL extern const pb_key *const pb_key_cli_status; +BASE_DLL extern const pb_key *const pb_key_client_cert_nickname; +BASE_DLL extern const pb_key *const pb_key_client_ip; +BASE_DLL extern const pb_key *const pb_key_close; +BASE_DLL extern const pb_key *const pb_key_connect_timeout; +BASE_DLL extern const pb_key *const pb_key_connection; +BASE_DLL extern const pb_key *const pb_key_cont; +BASE_DLL extern const pb_key *const pb_key_content_encoding; +BASE_DLL extern const pb_key *const pb_key_content_language; +BASE_DLL extern const pb_key *const pb_key_content_length; +BASE_DLL extern const pb_key *const pb_key_content_location; +BASE_DLL extern const pb_key *const pb_key_content_md5; +BASE_DLL extern const pb_key *const pb_key_content_range; +BASE_DLL extern const pb_key *const pb_key_content_type; +BASE_DLL extern const pb_key *const pb_key_cookie; +BASE_DLL extern const pb_key *const pb_key_date; +BASE_DLL extern const pb_key *const pb_key_DATE_GMT; +BASE_DLL extern const pb_key *const pb_key_DATE_LOCAL; +BASE_DLL extern const pb_key *const pb_key_dir; +BASE_DLL extern const pb_key *const pb_key_Directive; +BASE_DLL extern const pb_key *const pb_key_dns; +BASE_DLL extern const pb_key *const pb_key_DOCUMENT_NAME; +BASE_DLL extern const pb_key *const pb_key_DOCUMENT_URI; +BASE_DLL extern const pb_key *const pb_key_domain; +BASE_DLL extern const pb_key *const pb_key_enc; +BASE_DLL extern const pb_key *const pb_key_engine; +BASE_DLL extern const pb_key *const pb_key_error_action; +BASE_DLL extern const pb_key *const pb_key_error_desc; +BASE_DLL extern const pb_key *const pb_key_error_fn; +BASE_DLL extern const pb_key *const pb_key_escape; +BASE_DLL extern const pb_key *const pb_key_escaped; +BASE_DLL extern const pb_key *const pb_key_etag; +BASE_DLL extern const pb_key *const pb_key_expect; +BASE_DLL extern const pb_key *const pb_key_expires; +BASE_DLL extern const pb_key *const pb_key_expr; +BASE_DLL extern const pb_key *const pb_key_filter; +BASE_DLL extern const pb_key *const pb_key_find_pathinfo_forward; +BASE_DLL extern const pb_key *const pb_key_flushTimer; +BASE_DLL extern const pb_key *const pb_key_fn; +BASE_DLL extern const pb_key *const pb_key_from; +BASE_DLL extern const pb_key *const pb_key_full_headers; +BASE_DLL extern const pb_key *const pb_key_hdr; +BASE_DLL extern const pb_key *const pb_key_host; +BASE_DLL extern const pb_key *const pb_key_hostname; +BASE_DLL extern const pb_key *const pb_key_if_match; +BASE_DLL extern const pb_key *const pb_key_if_modified_since; +BASE_DLL extern const pb_key *const pb_key_if_none_match; +BASE_DLL extern const pb_key *const pb_key_if_range; +BASE_DLL extern const pb_key *const pb_key_if_unmodified_since; +BASE_DLL extern const pb_key *const pb_key_ip; +BASE_DLL extern const pb_key *const pb_key_iponly; +BASE_DLL extern const pb_key *const pb_key_issuer_dn; +BASE_DLL extern const pb_key *const pb_key_jroute; +BASE_DLL extern const pb_key *const pb_key_keep_alive; +BASE_DLL extern const pb_key *const pb_key_keep_alive_timeout; +BASE_DLL extern const pb_key *const pb_key_keysize; +BASE_DLL extern const pb_key *const pb_key_lang; +BASE_DLL extern const pb_key *const pb_key_LAST_MODIFIED; +BASE_DLL extern const pb_key *const pb_key_last_modified; +BASE_DLL extern const pb_key *const pb_key_level; +BASE_DLL extern const pb_key *const pb_key_location; +BASE_DLL extern const pb_key *const pb_key_lock_owner; +BASE_DLL extern const pb_key *const pb_key_magnus_charset; +BASE_DLL extern const pb_key *const pb_key_magnus_internal; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_dav_src; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_default_acls_only; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_error_j2ee; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_j2ee_nsapi; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_preserve_srvhdrs; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_set_request_status; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_set_response_status; +BASE_DLL extern const pb_key *const pb_key_magnus_internal_webapp_errordesc; +BASE_DLL extern const pb_key *const pb_key_matched_browser; +BASE_DLL extern const pb_key *const pb_key_max_age; +BASE_DLL extern const pb_key *const pb_key_max_forwards; +BASE_DLL extern const pb_key *const pb_key_message; +BASE_DLL extern const pb_key *const pb_key_method; +BASE_DLL extern const pb_key *const pb_key_name; +BASE_DLL extern const pb_key *const pb_key_nocache; +BASE_DLL extern const pb_key *const pb_key_nostat; +BASE_DLL extern const pb_key *const pb_key_ntrans_base; +BASE_DLL extern const pb_key *const pb_key_offline_origin_addr; +BASE_DLL extern const pb_key *const pb_key_offline_proxy_addr; +BASE_DLL extern const pb_key *const pb_key_origin_addr; +BASE_DLL extern const pb_key *const pb_key_p2c_cl; +BASE_DLL extern const pb_key *const pb_key_p2c_hl; +BASE_DLL extern const pb_key *const pb_key_p2r_cl; +BASE_DLL extern const pb_key *const pb_key_p2r_hl; +BASE_DLL extern const pb_key *const pb_key_parse_timeout; +BASE_DLL extern const pb_key *const pb_key_password; +BASE_DLL extern const pb_key *const pb_key_path; +BASE_DLL extern const pb_key *const pb_key_PATH_INFO; +BASE_DLL extern const pb_key *const pb_key_path_info; +BASE_DLL extern const pb_key *const pb_key_pblock; +BASE_DLL extern const pb_key *const pb_key_poll_interval; +BASE_DLL extern const pb_key *const pb_key_port; +BASE_DLL extern const pb_key *const pb_key_ppath; +BASE_DLL extern const pb_key *const pb_key_pragma; +BASE_DLL extern const pb_key *const pb_key_process_request_body; +BASE_DLL extern const pb_key *const pb_key_process_response_body; +BASE_DLL extern const pb_key *const pb_key_protocol; +BASE_DLL extern const pb_key *const pb_key_proxy_addr; +BASE_DLL extern const pb_key *const pb_key_proxy_agent; +BASE_DLL extern const pb_key *const pb_key_proxy_auth_cert; +BASE_DLL extern const pb_key *const pb_key_proxy_authorization; +BASE_DLL extern const pb_key *const pb_key_proxy_cipher; +BASE_DLL extern const pb_key *const pb_key_proxy_issuer_dn; +BASE_DLL extern const pb_key *const pb_key_proxy_jroute; +BASE_DLL extern const pb_key *const pb_key_proxy_keysize; +BASE_DLL extern const pb_key *const pb_key_proxy_ping; +BASE_DLL extern const pb_key *const pb_key_proxy_request; +BASE_DLL extern const pb_key *const pb_key_proxy_secret_keysize; +BASE_DLL extern const pb_key *const pb_key_proxy_ssl_id; +BASE_DLL extern const pb_key *const pb_key_proxy_user_dn; +BASE_DLL extern const pb_key *const pb_key_query; +BASE_DLL extern const pb_key *const pb_key_QUERY_STRING; +BASE_DLL extern const pb_key *const pb_key_QUERY_STRING_UNESCAPED; +BASE_DLL extern const pb_key *const pb_key_r2p_cl; +BASE_DLL extern const pb_key *const pb_key_r2p_hl; +BASE_DLL extern const pb_key *const pb_key_range; +BASE_DLL extern const pb_key *const pb_key_referer; +BASE_DLL extern const pb_key *const pb_key_reformat_request_headers; +BASE_DLL extern const pb_key *const pb_key_remote_status; +BASE_DLL extern const pb_key *const pb_key_request_jroute; +BASE_DLL extern const pb_key *const pb_key_required_rights; +BASE_DLL extern const pb_key *const pb_key_retries; +BASE_DLL extern const pb_key *const pb_key_rewrite_content_location; +BASE_DLL extern const pb_key *const pb_key_rewrite_host; +BASE_DLL extern const pb_key *const pb_key_rewrite_location; +BASE_DLL extern const pb_key *const pb_key_rewrite_set_cookie; +BASE_DLL extern const pb_key *const pb_key_root; +BASE_DLL extern const pb_key *const pb_key_route; +BASE_DLL extern const pb_key *const pb_key_route_cookie; +BASE_DLL extern const pb_key *const pb_key_route_hdr; +BASE_DLL extern const pb_key *const pb_key_route_offline; +BASE_DLL extern const pb_key *const pb_key_script_name; +BASE_DLL extern const pb_key *const pb_key_secret_keysize; +BASE_DLL extern const pb_key *const pb_key_secure; +BASE_DLL extern const pb_key *const pb_key_server; +BASE_DLL extern const pb_key *const pb_key_set_cookie; +BASE_DLL extern const pb_key *const pb_key_socks_addr; +BASE_DLL extern const pb_key *const pb_key_ssl_id; +BASE_DLL extern const pb_key *const pb_key_ssl_unclean_shutdown; +BASE_DLL extern const pb_key *const pb_key_status; +BASE_DLL extern const pb_key *const pb_key_sticky_cookie; +BASE_DLL extern const pb_key *const pb_key_sticky_param; +BASE_DLL extern const pb_key *const pb_key_suppress_request_headers; +BASE_DLL extern const pb_key *const pb_key_svr_status; +BASE_DLL extern const pb_key *const pb_key_timeout; +BASE_DLL extern const pb_key *const pb_key_to; +BASE_DLL extern const pb_key *const pb_key_transfer_encoding; +BASE_DLL extern const pb_key *const pb_key_transmit_timeout; +BASE_DLL extern const pb_key *const pb_key_tunnel_non_http_response; +BASE_DLL extern const pb_key *const pb_key_type; +BASE_DLL extern const pb_key *const pb_key_upstream_jroute; +BASE_DLL extern const pb_key *const pb_key_uri; +BASE_DLL extern const pb_key *const pb_key_url; +BASE_DLL extern const pb_key *const pb_key_url_prefix; +BASE_DLL extern const pb_key *const pb_key_UseOutputStreamSize; +BASE_DLL extern const pb_key *const pb_key_user; +BASE_DLL extern const pb_key *const pb_key_user_agent; +BASE_DLL extern const pb_key *const pb_key_user_dn; +BASE_DLL extern const pb_key *const pb_key_validate_server_cert; +BASE_DLL extern const pb_key *const pb_key_value; +BASE_DLL extern const pb_key *const pb_key_vary; +BASE_DLL extern const pb_key *const pb_key_via; +BASE_DLL extern const pb_key *const pb_key_warning; + +NSAPI_PUBLIC pool_handle_t *pblock_pool(pblock *pb); + +NSAPI_PUBLIC pb_param *pblock_param_create(pblock *pb, const char *name, const char *value); + +NSAPI_PUBLIC pblock *pblock_create_pool(pool_handle_t *pool_handle, int n); + +NSAPI_PUBLIC pb_param *INTpblock_fr(const char *name, pblock *pb, int remove); + +NSAPI_PUBLIC char *INTpblock_replace(const char *name,char * new_value,pblock *pb); + +NSAPI_PUBLIC int INTpblock_str2pblock_lowercasename(const char *str, pblock *pb); + +NSAPI_PUBLIC pb_param *pblock_removeone(pblock *pb); + +NSAPI_PUBLIC const pb_key *pblock_key(const char *name); + +NSAPI_PUBLIC pb_param *pblock_key_param_create(pblock *pb, const pb_key *key, const char *value, int valuelen); + +NSAPI_PUBLIC char *pblock_findkeyval(const pb_key *key, const pblock *pb); + +NSAPI_PUBLIC pb_param *pblock_findkey(const pb_key *key, const pblock *pb); + +NSAPI_PUBLIC pb_param *pblock_removekey(const pb_key *key, pblock *pb); + +NSAPI_PUBLIC pb_param *pblock_kvinsert(const pb_key *key, const char *value, int valuelen, pblock *pb); + +NSAPI_PUBLIC void pblock_kpinsert(const pb_key *key, pb_param *pp, pblock *pb); + +NSAPI_PUBLIC void pblock_kvreplace(const pb_key *key, const char *value, int valuelen, pblock *pb); + +NSAPI_PUBLIC pb_param *pblock_kninsert(const pb_key *key, int value, pblock *pb); + +NSAPI_PUBLIC pb_param *pblock_kllinsert(const pb_key *key, PRInt64 value, pblock *pb); + +#ifdef __cplusplus +inline const pb_key *param_key(pb_param *pp) +{ + return *(const pb_key **)(pp + 1); /* XXX see plist_pvt.h */ +} +#endif + +NSPR_END_EXTERN_C + +#define param_create INTparam_create +#define param_free INTparam_free +#define pblock_create INTpblock_create +#define pblock_free INTpblock_free +#define pblock_findval INTpblock_findval +#define pblock_nvinsert INTpblock_nvinsert +#define pblock_nninsert INTpblock_nninsert +#define pblock_pinsert INTpblock_pinsert +#define pblock_str2pblock INTpblock_str2pblock +#define pblock_pblock2str INTpblock_pblock2str +#define pblock_copy INTpblock_copy +#define pblock_dup INTpblock_dup +#define pblock_pb2env INTpblock_pb2env +#define pblock_fr INTpblock_fr +#define pblock_replace INTpblock_replace + +#endif /* INTNSAPI */ + +#endif /* !BASE_PBLOCK_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/plist.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/plist.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,1273 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MODULE: plist.c + * + * DESCRIPTION: + * + * This module implements property lists. A property list is an + * ordered array of property values. Each property value has an + * handle for some data item, and may have a reference to + * another property list which describes the type of the data + * item. Each property value has a property index which specifies + * its position in the property list. A property value may also + * have a name. Since the data item associated with a property + * value may reference another property list, it is possible to + * construct arbitrary linked structures of property lists. + * + * IMPLEMENTATION NOTES: + */ + +#include "netsite.h" +#include "plist.h" +#include "plist_pvt.h" + +int plistHashSizes[] = PLSTSIZES; + +/* + * FUNCTION: PListAssignValue + * + * DESCRIPTION: + * + * This function sets the value and/or type of a defined property + * in given property list. If the property type is specified as + * NULL, it is unchanged. However, the property value is always + * set to the specified value. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pname - the property name + * pvalue - the new property value + * ptype - the new property type, or NULL + * + * RETURNS: + * + * If successful, the property index of the referenced property is + * returned as the function value. Errors are indicated by a + * negative return code as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListAssignValue(PList_t plist, const char *pname, + const void *pvalue, PList_t ptype) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t *pv; + int pindex; + int i; + + if (!plist) return ERRPLUNDEF; + + /* Got a symbol table for this property list? */ + if (pl->pl_symtab) { + + /* Yes, compute hash of specified name */ + i = PListHashName(pl->pl_symtab, pname); + + /* Search hash collision list for matching name */ + for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) { + + if (!strcmp(pname, pv->pv_name)) { + + /* Name match, get property index */ + pindex = pv->pv_pi; + + /* Set the new value */ + pv->pv_value = (char *)pvalue; + + /* Set type if type is given */ + if (ptype) pv->pv_type = (PListStruct_t *)ptype; + + /* Return the property index */ + return pindex; + } + } + } + + /* Error - specified property name is undefined */ + return ERRPLUNDEF; +} + +/* + * FUNCTION: PListCreate + * + * DESCRIPTION: + * + * This function creates a new property list and returns a handle for + * it. It allows the caller to reserve a specified number of + * property indices at the beginning of the list, and also to limit + * the total number of property values that may be added to the list. + * + * ARGUMENTS: + * + * mempool - handle for a memory pool to be associated + * with the new property list + * resvprop - number of reserved property indices + * maxprop - maximum number of properties in list + * (zero or negative imposes no limit) + * flags - unused, reserved, must be zero + * + * RETURNS: + * + * If successful, the function return value is a handle for the new + * property list. Otherwise NULL is returned. + */ + +NSAPI_PUBLIC PList_t +PListCreate(pool_handle_t *mempool, int resvprop, int maxprop, int flags) +{ + PListStruct_t *plist; /* pointer to property list structure */ + int i; + + plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t)); + if (plist) { + + /* Negative maxprop is the same as zero, i.e. no limit */ + if (maxprop < 0) maxprop = 0; + + /* If resvprop and maxprop are both specified, limit resvprop */ + if (resvprop > 0) { + if (maxprop && (resvprop > maxprop)) resvprop = maxprop; + } + else resvprop = 0; + + /* Initialize property list structure */ + plist->pl_mempool = mempool; + plist->pl_symtab = NULL; + plist->pl_maxprop = maxprop; + plist->pl_resvpi = resvprop; + plist->pl_initpi = resvprop; + plist->pl_lastpi = resvprop; + + /* Set initialize size for array of property value pointers */ + plist->pl_cursize = (resvprop) ? resvprop : PLIST_DEFSIZE; + + /* Allocate the initial array of property value pointers */ + plist->pl_ppval = (pb_entry **)pool_malloc(mempool, + (plist->pl_cursize * + sizeof(PLValueStruct_t *))); + if (!plist->pl_ppval) { + + /* Failed - insufficient memory */ + pool_free(mempool, (void *)plist); + plist = NULL; + } + else { + /* NULL out pointers in the reserved index range, if any */ + for (i = 0; i < plist->pl_lastpi; ++i) { + plist->pl_ppval[i] = 0; + } + } + } + + return (PList_t)plist; +} + +/* + * FUNCTION: PListDefProp + * + * DESCRIPTION: + * + * This function creates a new property in a specified property list. + * The 'pindex' argument may be used to request a particular property + * index for the new property. If 'pindex' is greater than zero, + * the specified value is used as the new property's index, provided + * there is no property at that index already. If 'pindex' is zero, + * then the next available property index is assigned to the new + * property. A name may optionally be specified for the new property. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pindex - new property index (or zero) + * pname - new property name (or NULL) + * + * RETURNS: + * + * If successful, the index of the new property is returned as the + * function value. Errors are indicated by a negative return code + * as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListDefProp(PList_t plist, int pindex, const char *pname, const int flags) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t *pv; + + if (!plist) return ERRPLUNDEF; + + /* Is pindex specified? */ + if (pindex > 0) { + + /* Yes, is it in the reserved range? */ + if (flags != PLFLG_IGN_RES && pindex > pl->pl_resvpi) { + /* No, error */ + return ERRPLINVPI; + } + + PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval); + if (ppval[pindex - 1]) { + /* Error - property already exists at specified index */ + return ERRPLEXIST; + } + } + else { + + /* Look for a free property index */ + pindex = PListGetFreeIndex(pl); + if (pindex < 1) { + /* Error - no free property index */ + return pindex; + } + } + + /* We have a property index. Create a new property value */ + pv = (PLValueStruct_t *)pool_calloc(pl->pl_mempool, + 1, sizeof(PLValueStruct_t)); + if (!pv) { + + /* Error - insufficient memory */ + return ERRPLNOMEM; + } + + PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval); + pv->pv_pbentry.param = &pv->pv_pbparam; + pv->pv_pi = pindex; + pv->pv_mempool = pl->pl_mempool; + ppval[pindex - 1] = pv; + + /* Name the property if the name was specified */ + if (pname) { + + /* XXX Maybe should delete property if naming fails */ + return PListNameProp(plist, pindex, pname); + } + + /* Return the property index of the new property */ + return pindex; +} + +/* + * FUNCTION: PListDeleteProp + * + * DESCRIPTION: + * + * This function deletes a property from a specified property list. + * The property can be specified by its property index, using a + * pindex value greater than zero, or by its name, by specifying + * pindex as zero and pname as the property name. This does not + * have any effect on the data referenced by the property value, + * if any, nor does it have any effect on the property list that + * describes the property value's type, if any. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pindex - the property index, or zero + * pname - the property name, or NULL + */ + +NSAPI_PUBLIC const void * +PListDeleteProp(PList_t plist, int pindex, const char *pname_in) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t **ppval; + PLValueStruct_t **pvp; + PLValueStruct_t *pv = NULL; + int i; + const void *pvalue = NULL; + char *pname = (char *)pname_in; + + if (!plist) return NULL; + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Check for valid property index */ + if ((pindex > 0) && (pindex <= pl->pl_initpi)) { + + /* Get the pointer to the property structure */ + pv = ppval[pindex - 1]; + pname = 0; + if (pv) { + pname = pv->pv_name; + } + } + + if (pname && pl->pl_symtab) { + + /* Compute hash of specified property name */ + i = PListHashName(pl->pl_symtab, pname); + + /* Search hash collision list for matching name */ + for (pvp = &pl->pl_symtab->pt_hash[i]; *pvp; pvp = &(*pvp)->pv_next) { + + pv = *pvp; + if (!strcmp(pname, pv->pv_name)) { + + /* Found it. Get its index and remove it. */ + pindex = pv->pv_pi; + *pvp = pv->pv_next; + pl->pl_symtab->pt_nsyms--; + break; + } + pv = NULL; + } + } + + /* Found the indicated property by index or name? */ + if (pv) { + + /* Yes, remove it from the property list */ + ppval[pindex - 1] = NULL; + + /* Free the property name, if any */ + if (pv->pv_name) { + pool_free(pv->pv_mempool, (void *)(pv->pv_name)); + } + pvalue = pv->pv_value; + + /* Free the property */ + pool_free(pv->pv_mempool, (void *)pv); + } + return(pvalue); +} + +/* + * FUNCTION: PListFindValue + * + * DESCRIPTION: + * + * This function retrieves the value and type of a property with a + * specified property name. If the pvalue argument is non-NULL, + * it specifies a location in which to return the property value. + * Similarly, if ptype is non-NULL, it specifies where the property + * list describing the property type is to be returned. If a + * property has no value, the value returned for pvalue is NULL. + * If a property has no type, the value returned for ptype is NULL. + * A property can have a value, a type, both, or neither. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pname - pointer to property name string + * pvalue - property value return pointer + * ptype - property type return pointer + * + * RETURNS: + * + * If successful, the index of the referenced property is returned + * as the function value. Errors are indicated by a negative + * return code as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListFindValue(PList_t plist, const char *pname, void **pvalue, PList_t *ptype) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t *pv; + int pindex; + int i; + + if (!plist) return ERRPLUNDEF; + + /* Got a symbol table for this property list? */ + if (pl->pl_symtab) { + + /* Yes, compute hash of specified name */ + i = PListHashName(pl->pl_symtab, pname); + + /* Search hash collision list for matching name */ + for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) { + + if (!strcmp(pname, pv->pv_name)) { + + /* Name match, get property index */ + pindex = pv->pv_pi; + + /* Return the value if requested */ + if (pvalue) *pvalue = (void *)(pv->pv_value); + + /* Return the type if requested */ + if (ptype) *ptype = (PList_t)(pv->pv_type); + + /* Return the property index */ + return pindex; + } + } + } + + /* Error - specified property name is undefined */ + return ERRPLUNDEF; +} + +/* + * FUNCTION: PListInitProp + * + * DESCRIPTION: + * + * This function combines the functions of PListDefProp() and + * PListSetValue(), defining a new property and assigning it an + * initial value and optionally a type and/or a name. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pindex - a reserved property index, or zero + * pname - the new property name, or NULL + * pvalue - the new property value + * ptype - the new property type, or NULL + * + * RETURNS: + * + * If successful, the property index (pindex) is returned as the + * function value. Errors are indicated by a negative return code + * as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListInitProp(PList_t plist, int pindex, const char *pname, + const void *pvalue, PList_t ptype) +{ + int rv; + + if (!plist) return ERRPLUNDEF; + + /* Create the property */ + rv = PListDefProp(plist, pindex, pname, PLFLG_USE_RES); + if (rv > 0) { + + /* If that worked, set the value and type */ + rv = PListSetValue(plist, rv, pvalue, ptype); + } + + return rv; +} + +/* + * FUNCTION: PListNew + * + * DESCRIPTION: + * + * This function creates a new property list, using the specified + * memory pool for allocating the internal data structures used to + * represent it. If the mempool argument is NULL, the default + * memory pool is used. + * + * ARGUMENTS: + * + * mempool - handle for a memory pool to be associated + * with the new property list + * + * RETURNS: + * + * If successful, the function return value is a handle for the new + * property list. Otherwise NULL is returned. + */ + +NSAPI_PUBLIC PList_t +PListNew(pool_handle_t *mempool) +{ + /* Just call PListCreate with default parameters */ + return PListCreate(mempool, 0, 0, 0); +} + +/* + * FUNCTION: PListDestroy + * + * DESCRIPTION: + * + * This function destroys a specified property list. This means + * that any dynamic memory which was allocated as a result of calls + * to the property list API is freed to the memory pool from which + * it was allocated. Property value data is not freed, nor are + * any property lists associated with property types. + * + * ARGUMENTS: + * + * plist - handle for the property list + */ + +void +PListDestroy(PList_t plist) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + int i; + + if (!plist) return; + + /* Free the property name symbol table if any */ + if (pl->pl_symtab) { + pool_free(pl->pl_mempool, (void *)(pl->pl_symtab)); + } + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Loop over the initialized property indices */ + for (i = 0; i < pl->pl_initpi; ++i) { + + /* Got a property here? */ + pv = ppval[i]; + if (pv) { + + /* Free the property name string if any */ + if (pv->pv_name) { + pool_free(pv->pv_mempool, (void *)(pv->pv_name)); + } + + /* Free the property value structure */ + pool_free(pv->pv_mempool, (void *)pv); + } + } + + /* Free the array of pointers to property values */ + pool_free(pl->pl_mempool, (void *)ppval); + + /* Free the property list head */ + pool_free(pl->pl_mempool, (void *)pl); +} + +/* + * FUNCTION: PListGetValue + * + * DESCRIPTION: + * + * This function retrieves the value and type of the property with + * the property index given by pindex in the specified property + * list. The pindex argument must specify the index of a defined + * property. If the pvalue argument is non-NULL, it specifies a + * location in which to return the property value. Similarly, if + * ptype is non-NULL, it specifies where the property list + * describing the property type is to be returned. If a property + * has no value, the value returned for pvalue is NULL. If a + * property has no type, the value returned for ptype is NULL. A + * property can have a value, a type, both, or neither. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pindex - the property index + * pvalue - property value return pointer + * ptype - property type return pointer + * + * RETURNS: + * + * If successful, the property index (pindex) is returned as the + * function value. Errors are indicated by a negative return code + * as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListGetValue(PList_t plist, int pindex, void **pvalue, PList_t *ptype) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + + if (!plist) return ERRPLUNDEF; + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Check for valid property index */ + if ((pindex > 0) && (pindex <= pl->pl_initpi)) { + + /* Does the property exist? */ + pv = ppval[pindex - 1]; + if (pv) { + + /* Yes, return the value if requested */ + if (pvalue) *pvalue = (void *)(pv->pv_value); + + /* Return the type if requested */ + if (ptype) *ptype = (PList_t)(pv->pv_type); + + /* Successful return */ + return pindex; + } + } + + /* Error - invalid property index or non-existent property */ + return ERRPLINVPI; +} + +/* + * FUNCTION: PListHash + * + * DESCRIPTION: + * + * This function hashes a given string. + * + * ARGUMENTS: + * + * string - pointer to the string to hash + * + * RETURNS: + * + * The hash value is returned as the function value. + */ + +unsigned int +PListHash(const char *string) +{ + unsigned int hashval = 0; /* hash value */ + + while (*string) { + hashval = (hashval<<5) ^ (*string++ & 0x7f); + } + + return hashval; +} + +/* + * FUNCTION: PListHashName + * + * DESCRIPTION: + * + * This function hashes a given property name for a specified + * symbol table. It produces a value that can be used as an + * index in the pt_hash array associated with the symbol table. + * + * ARGUMENTS: + * + * symtab - pointer to the symbol table + * pname - pointer to the property name string + * + * RETURNS: + * + * The hash index is returned as the function value. + */ + +int +PListHashName(PLSymbolTable_t *symtab, const char *pname) +{ + return PListHash(pname) % PLSIZENDX(symtab->pt_sizendx); +} + +/* + * FUNCTION: PListNameProp + * + * DESCRIPTION: + * + * This function assigns a name to a defined property with the + * property index, pindex. If the property has an existing name, + * it will be replaced with the name specified by pname. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pindex - the property index + * pname - the new property name + * + * RETURNS: + * + * If successful, the property index (pindex) is returned as the + * function value. Errors are indicated by a negative return code + * as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListNameProp(PList_t plist, int pindex, const char *pname) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t *pv; + PLSymbolTable_t *pt; + int i; + + if (!plist) return ERRPLUNDEF; + + pt = pl->pl_symtab; + + /* Check for valid property index */ + if ((pindex > 0) && (pindex <= pl->pl_initpi)) { + + /* Does the property exist? */ + pv = ((PLValueStruct_t **)(pl->pl_ppval))[pindex - 1]; + if (pv) { + + /* If it has a name already, unname it */ + if (pv->pv_name) { + PLValueStruct_t **pvp; + + /* Get hash bucket index */ + i = PListHashName(pt, pv->pv_name); + + /* Seach hash collision list for this property */ + for (pvp = &pt->pt_hash[i]; + *pvp; pvp = &(*pvp)->pv_next) { + + if (*pvp == pv) { + + /* Remove it from the list */ + *pvp = pv->pv_next; + pt->pt_nsyms--; + break; + } + } + + /* Free the current name string */ + pool_free(pv->pv_mempool, (void *)(pv->pv_name)); + } + + /* Got a new name? */ + if (pname) { + + /* Allocate/grow the symbol table as needed */ + pt = PListSymbolTable(pl); + if (!pt) { + return ERRPLNOMEM; + } + + /* Duplicate the name string */ + pv->pv_name = pool_strdup(pv->pv_mempool, (char *)pname); + + /* Add name to symbol table */ + i = PListHashName(pt, pname); + pv->pv_next = pt->pt_hash[i]; + pt->pt_hash[i] = pv; + pt->pt_nsyms++; + } + + /* Successful return */ + return pindex; + } + } + + /* Error - invalid property index or non-existent property */ + return ERRPLINVPI; +} + +/* + * FUNCTION: PListSetType + * + * DESCRIPTION: + * + * This function sets the property type of the defined property + * with the property index, pindex. The property list describing + * the property type is specified by ptype. If ptype is NULL, + * the property type will be set to be undefined (NULL). + * + * + * ARGUMENTS: + * + * plist - handle for the property list + * pindex - the property index + * ptype - the new property type, or NULL + * + * RETURNS: + * + * If successful, the property index (pindex) is returned as the + * function value. Errors are indicated by a negative return code + * as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListSetType(PList_t plist, int pindex, PList_t ptype) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + + if (!plist) return ERRPLUNDEF; + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Check for valid property index */ + if ((pindex > 0) && (pindex <= pl->pl_initpi)) { + + /* Does the property exist? */ + pv = ppval[pindex - 1]; + if (pv) { + + /* Yes, set the new type */ + pv->pv_type = ptype; + + /* Successful return */ + return pindex; + } + } + + /* Error - invalid property index or non-existent property */ + return ERRPLINVPI; +} + +/* + * FUNCTION: PListSetValue + * + * DESCRIPTION: + * + * This function sets the value and optionally the type of a + * defined property in a given property list. The pindex argument + * specifies the property index, which must be greater than zero. + * The ptype argument specifies a property list that describes the + * property type. If ptype is NULL, the property type, if any, is + * unchanged by this function. However, the property value is + * always set to the value given by pvalue. + * + * ARGUMENTS: + * + * plist - handle for the property list + * pindex - the property index + * pvalue - the new property value + * ptype - the new property type, or NULL + * + * RETURNS: + * + * If successful, the property index (pindex) is returned as the + * function value. Errors are indicated by a negative return code + * as defined in plist.h. + */ + +NSAPI_PUBLIC int +PListSetValue(PList_t plist, int pindex, const void *pvalue, PList_t ptype) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + + if (!plist) return ERRPLUNDEF; + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Check for valid property index */ + if ((pindex > 0) && (pindex <= pl->pl_initpi)) { + + /* Does the property exist? */ + pv = ppval[pindex - 1]; + if (pv) { + + /* Yes, set the new value */ + pv->pv_value = (char *)pvalue; + + /* Set type if type is given */ + if (ptype) pv->pv_type = (PListStruct_t *)ptype; + + /* Successful return */ + return pindex; + } + } + + /* Error - invalid property index or non-existent property */ + return ERRPLINVPI; +} + +/* + * FUNCTION: PListEnumerate + * + * DESCRIPTION: + * + * This function walks through a specified property list + * calling a user supplied function with the property + * name and value as parameters. + * + * ARGUMENTS: + * + * plist - handle for the property list + * user_func - handle for the user function + */ + +NSAPI_PUBLIC void +PListEnumerate(PList_t plist, PListFunc_t *user_func, void *user_data) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + int i; + + if (!plist) return; + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Loop over the initialized property indices */ + for (i = 0; i < pl->pl_initpi; ++i) { + + /* Got a property here? */ + pv = ppval[i]; + if (pv) { + (*user_func)(pv->pv_name, pv->pv_value, user_data); + } + + } + +} + +/* + * FUNCTION: PListCreateDuplicate + * + * DESCRIPTION: + * + * This function creates a new property list and returns a handle for + * it. The source plist provides the new plists parameters. + * + * ARGUMENTS: + * + * src_plist - source plist to duplicate + * mempool - handle for a memory pool to be associated + * with the new property list, only + * used if flags is set to PLFLG_NEW_MPOOL + * flags - if PLFLG_NEW_MPOOL uses new_mempool + * parameter + * + * RETURNS: + * + * If successful, the function return value is a handle for the new + * property list. Otherwise NULL is returned. + */ + +static PList_t +PListCreateDuplicate(PList_t src_plist, pool_handle_t *new_mempool, int flags) +{ + PListStruct_t *plist; /* pointer to property list structure */ + int i; + pool_handle_t *mempool; + + mempool = (flags == PLFLG_NEW_MPOOL) ? new_mempool : src_plist->pl_mempool; + + plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t)); + if (plist) { + + /* Initialize property list structure */ + plist->pl_mempool = mempool; + plist->pl_symtab = NULL; + plist->pl_maxprop = src_plist->pl_maxprop; + plist->pl_resvpi = src_plist->pl_resvpi; + plist->pl_initpi = src_plist->pl_initpi; + plist->pl_lastpi = src_plist->pl_lastpi; + + /* Set initialize size for array of property value pointers */ + plist->pl_cursize = src_plist->pl_cursize; + + /* Allocate the initial array of property value pointers */ + plist->pl_ppval = (pb_entry **)pool_malloc(mempool, + (plist->pl_cursize * + sizeof(PLValueStruct_t *))); + if (!plist->pl_ppval) { + + /* Failed - insufficient memory */ + pool_free(mempool, (void *)plist); + plist = NULL; + } + else { + /* NULL out pointers in the reserved index range, if any */ + for (i = 0; i < plist->pl_lastpi; ++i) { + plist->pl_ppval[i] = 0; + } + } + } + + return (PList_t)plist; +} + + +/* + * FUNCTION: PListDuplicate + * + * DESCRIPTION: + * + * This function duplicates a specified PList_t. + * + * ARGUMENTS: + * + * plist - handle for the property list + * mempool - handle for a memory pool to be associated + * with the new property list + * resvprop - number of reserved property indices + * maxprop - maximum number of properties in list + * (zero or negative imposes no limit) + * flags - unused, reserved, must be zero + * + * RETURNS: + * + * If successful, the function return value is a handle for the new + * property list. Otherwise NULL is returned. + */ + +NSAPI_PUBLIC PList_t +PListDuplicate(PList_t plist, pool_handle_t *new_mempool, int flags) +{ + PListStruct_t *pl = (PListStruct_t *)plist; + PLValueStruct_t **ppval; + PLValueStruct_t *pv; + int i; + int rv = 0; + PList_t new_plist; + + if (!plist) return NULL; + + new_plist = PListCreateDuplicate(plist, new_mempool, flags); + if (new_plist == NULL) { + return(NULL); + } + + ppval = (PLValueStruct_t **)(pl->pl_ppval); + + /* Loop over the initialized property indices */ + for (i = 0; i < pl->pl_initpi; ++i) { + + /* Got a property here? */ + pv = ppval[i]; + if (pv) { + /* Create the property */ + rv = PListDefProp(new_plist, i + 1, pv->pv_name, PLFLG_IGN_RES); + if (rv > 0) { + + /* If that worked, set the value and type */ + rv = PListSetValue(new_plist, rv, pv->pv_value, pv->pv_type); + } + + if ( rv <= 0 ) { + PListDestroy(new_plist); + return(NULL); + } + } + + } + + return(new_plist); +} + +/* + * FUNCTION: PListGetPool + * + * DESCRIPTION: + * + * This function returns the memory pool the PList is allocated from. + * + * ARGUMENTS: + * + * plist - handle for the property list + * + * RETURNS: + * + * The memory pool address, which can be NULL. + */ + +NSAPI_PUBLIC pool_handle_t * +PListGetPool(PList_t plist) +{ + if (!plist) return NULL; + + return(plist->pl_mempool); +} + +/* + * FUNCTION: PListGetFreeIndex + * + * DESCRIPTION: + * + * This function returns an available property index. + * + * ARGUMENTS: + * + * plist - handle for the property list + * + * RETURNS: + * + * If successful, an available property index is returned as the + * function value. Errors are indicated by a negative return code + * as defined in plist.h. + */ + +int +PListGetFreeIndex(PListStruct_t *pl) +{ + PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval); + int wrapped; + int i; + + /* + * Look for a free property index, starting at pl_lastpi + 1. + * (Note that i is the property index - 1) + */ + for (wrapped = 0, i = pl->pl_lastpi; ;) { + + /* Are we in an initialized part of the array? */ + if (i < pl->pl_initpi) { + + /* Yes, use this index if it's free */ + if (ppval[i] == 0) break; + + /* Otherwise step to the next one */ + ++i; + } + else { + + /* Have we reached the end yet? */ + if (i < pl->pl_cursize) { + + /* + * We are above the highest initialized index, but + * still within the allocated size. An index in + * this range can be used with no further checks. + */ + ppval[i] = 0; + } + else { + + /* + * It's looking like time to grow the array, but + * first go back and look for an unused, unreserved + * index that might have been freed. + */ + if (!wrapped) { + + i = pl->pl_resvpi; + wrapped = 1; + continue; + } + + /* + * Grow the array unless there is a specified maximum + * size and we've reached it. + */ + i = pl->pl_cursize; + if (pl->pl_maxprop && (i > pl->pl_maxprop)) { + + /* Error - property list is full */ + return ERRPLFULL; + } + + /* Increase planned size of list */ + int cursize = i + PLIST_DEFGROW; + + /* Reallocate the array of property value pointers */ + ppval = (PLValueStruct_t **)pool_realloc(pl->pl_mempool, + (void *)ppval, + (cursize * sizeof(PLValueStruct_t *))); + if (!ppval) { + + /* Error - insufficient memory */ + return ERRPLNOMEM; + } + + /* Initialize the first new entry and select it */ + ppval[i] = NULL; + pl->pl_ppval = (pb_entry **)ppval; + pl->pl_cursize = cursize; + } + + /* Update the highest initialized index value */ + pl->pl_initpi = i + 1; + break; + } + } + + /* Set the starting point for the next allocation */ + pl->pl_lastpi = i + 1; + + return i + 1; +} + +/* + * FUNCTION: PListSymbolTable + * + * DESCRIPTION: + * + * This function allocates or grows a property list's symbol table as + * needed. + * + * ARGUMENTS: + * + * plist - handle for the property list + * + * RETURNS: + * + * If successful, a pointer to the symbol table is returned as the + * function value. Errors are indicated by a NULL return code. + */ + +PLSymbolTable_t * +PListSymbolTable(PListStruct_t *pl) +{ + PLSymbolTable_t *pt; + int i; + + pt = pl->pl_symtab; + + /* Is there a hash table? */ + if (!pl->pl_symtab) { + + /* No, create one */ + pt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1, PLHASHSIZE(0)); + + pl->pl_symtab = pt; + } + else { + + /* Is it time to grow the hash table? */ + i = PLSIZENDX(pt->pt_sizendx); + if ((pt->pt_sizendx < PLMAXSIZENDX) && pt->pt_nsyms >= (i + i)) { + + PLSymbolTable_t *npt; + + /* Yes, allocate the new table */ + npt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1, + PLHASHSIZE(pt->pt_sizendx+1)); + if (npt) { + npt->pt_sizendx = pt->pt_sizendx + 1; + npt->pt_nsyms = pt->pt_nsyms; + + /* Rehash all the names into the new table, preserving order */ + for (i = 0; i < PLSIZENDX(pt->pt_sizendx); ++i) { + /* While there are names at this hash index... */ + while (pt->pt_hash[i]) { + PLValueStruct_t **pvp; + int j; + + /* Find the last name at this hash index */ + for (pvp = &pt->pt_hash[i]; (*pvp)->pv_next; pvp = &(*pvp)->pv_next); + + /* Move the name to the new table */ + j = PListHashName(npt, (*pvp)->pv_name); + (*pvp)->pv_next = npt->pt_hash[j]; + npt->pt_hash[j] = (*pvp); + + /* Remove the name from the old table */ + *pvp = NULL; + } + } + + pl->pl_symtab = npt; + + /* Free the old symbol table */ + pool_free(pl->pl_mempool, (void *)pt); + pt = npt; + } + } + } + + return pl->pl_symtab; +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/plist.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/plist.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,94 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PLIST_H +#define _PLIST_H + +#ifndef NOINTNSACL +#define INTNSACL +#endif /* !NOINTNSACL */ + +/* + * TYPE: PList_t + * + * DESCRIPTION: + * + * This type defines a handle for a property list. + */ + +#include "pool.h" +#include "mps/nspr.h" +#include "nsapi.h" +#include "plist_pvt.h" + +#ifndef PUBLIC_NSACL_PLISTDEF_H +#include "plistdef.h" +#endif /* !PUBLIC_NSACL_PLISTDEF_H */ + +#ifdef INTNSACL + +/* Functions in plist.c */ +NSPR_BEGIN_EXTERN_C + +NSAPI_PUBLIC extern int PListAssignValue(PList_t plist, const char *pname, + const void *pvalue, PList_t ptype); +NSAPI_PUBLIC extern PList_t PListCreate(pool_handle_t *mempool, + int resvprop, int maxprop, int flags); +NSAPI_PUBLIC extern int PListDefProp(PList_t plist, int pindex, + const char *pname, const int flags); +NSAPI_PUBLIC extern const void * PListDeleteProp(PList_t plist, int pindex, const char *pname); +NSAPI_PUBLIC extern int PListFindValue(PList_t plist, + const char *pname, void **pvalue, PList_t *type); +NSAPI_PUBLIC extern int PListInitProp(PList_t plist, int pindex, const char *pname, + const void *pvalue, PList_t ptype); +NSAPI_PUBLIC extern PList_t PListNew(pool_handle_t *mempool); +NSAPI_PUBLIC extern void PListDestroy(PList_t plist); +NSAPI_PUBLIC extern int PListGetValue(PList_t plist, + int pindex, void **pvalue, PList_t *type); +NSAPI_PUBLIC extern int PListNameProp(PList_t plist, int pindex, const char *pname); +NSAPI_PUBLIC extern int PListSetType(PList_t plist, int pindex, PList_t type); +NSAPI_PUBLIC extern int PListSetValue(PList_t plist, + int pindex, const void *pvalue, PList_t type); +NSAPI_PUBLIC extern void PListEnumerate(PList_t plist, PListFunc_t *user_func, + void *user_data); +NSAPI_PUBLIC extern PList_t +PListDuplicate(PList_t plist, pool_handle_t *new_mempool, int flags); +NSAPI_PUBLIC extern pool_handle_t *PListGetPool(PList_t plist); +NSAPI_PUBLIC extern int PListDefKey(PList_t plist, pb_key *key, const char *pname, const int flags); +NSAPI_PUBLIC extern int PListInitKey(PList_t plist, pb_key *key, const void *pvalue, PList_t ptype); + +NSPR_END_EXTERN_C + +#endif /* INTNSACL */ + +#endif /* _PLIST_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/plist_pvt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/plist_pvt.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,162 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PLIST_PVT_H +#define _PLIST_PVT_H + +/* + * FILE: plist_pvt.h + * + * DESCRIPTION: + * + * This file contains private definitions for the property list + * utility implementation. + */ + +#include "nsapi.h" +#include "pool.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +typedef struct PLValueStruct_s PLValueStruct_t; +typedef struct PLSymbol_s PLSymbol_t; +typedef struct PLSymbolTable_s PLSymbolTable_t; +typedef struct PListStruct_s PListStruct_t; + +/* + * TYPE: PLValueStruct_t + * + * DESCRIPTION: + * + * This type represents a property value. It is dynamically + * allocated when a new property is added to a property list. + * It contains a reference to a property list that contains + * information about the property value, and a reference to + * the property value data. + */ + +#ifndef PBLOCK_H +#include "pblock.h" +#endif /* PBLOCK_H */ + +struct PLValueStruct_s { + pb_entry pv_pbentry; /* used for pblock compatibility */ + pb_param pv_pbparam; /* property name and value pointers */ + const pb_key *pv_pbkey; /* property pb_key pointer (optional) */ + PLValueStruct_t *pv_next; /* property name hash collision link */ + PListStruct_t *pv_type; /* property value type reference */ + int pv_pi; /* property index */ + pool_handle_t *pv_mempool; /* pool we were allocated from */ +}; + +#define pv_name pv_pbparam.name +#define pv_value pv_pbparam.value + +/* Offset to pv_pbparam in PLValueStruct_t */ +#define PVPBOFFSET ((char *)&((PLValueStruct_t *)0)->pv_pbparam) + +/* Convert pb_param pointer to PLValueStruct_t pointer */ +#define PATOPV(p) ((PLValueStruct_t *)((char *)(p) - PVPBOFFSET)) + +/* + * TYPE: PLSymbolTable_t + * + * DESCRIPTION: + * + * This type represents a symbol table that maps property names + * to properties. It is dynamically allocated the first time a + * property is named. + */ + +#define PLSTSIZES {7, 19, 31, 67, 123, 257, 513} +#define PLMAXSIZENDX (sizeof(plistHashSizes)/sizeof(plistHashSizes[0]) - 1) + +struct PLSymbolTable_s { + int pt_sizendx; /* pt_hash size, as an index in PLSTSIZES */ + int pt_nsyms; /* number of symbols in table */ + PLValueStruct_t *pt_hash[1];/* variable-length array */ +}; + +/* + * TYPE: PListStruct_t + * + * DESCRIPTION: + * + * This type represents the top-level of a property list structure. + * It is dynamically allocated when a property list is created, and + * freed when the property list is destroyed. It references a + * dynamically allocated array of pointers to property value + * structures (PLValueStruct_t). + */ + +#define PLIST_DEFSIZE 8 /* default initial entries in pl_ppval */ +#define PLIST_DEFGROW 16 /* default incremental entries for pl_ppval */ + +struct PListStruct_s { + pblock pl_pb; /* pblock subset of property list head */ + PLSymbolTable_t *pl_symtab; /* property name to index symbol table */ + pool_handle_t *pl_mempool; /* associated memory pool handle */ + int pl_maxprop; /* maximum number of properties */ + int pl_resvpi; /* number of reserved property indices */ + int pl_lastpi; /* last allocated property index */ + int pl_cursize; /* current size of pl_ppval in entries */ +}; + +#define pl_initpi pl_pb.hsize /* number of pl_ppval entries initialized */ +#define pl_ppval pl_pb.ht /* pointer to array of value pointers */ + +/* Convert pblock pointer to PListStruct_t pointer */ +#define PBTOPL(p) ((PListStruct_t *)(p)) + +#define PLSIZENDX(i) (plistHashSizes[i]) +#define PLHASHSIZE(i) (sizeof(PLSymbolTable_t) + \ + (PLSIZENDX(i) - 1)*sizeof(PLValueStruct_t *)) + +extern int plistHashSizes[7]; + +unsigned int PListHash(const char *string); + +int PListHashName(PLSymbolTable_t *symtab, const char *pname); + +int PListGetFreeIndex(PListStruct_t *pl); + +PLSymbolTable_t *PListSymbolTable(PListStruct_t *pl); + +#ifdef __cplusplus +} +#endif + +#endif /* _PLIST_PVT_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/plistdef.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/plistdef.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,77 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PUBLIC_NSACL_PLISTDEF_H +#define PUBLIC_NSACL_PLISTDEF_H + +/* + * File: plistdef.h + * + * Description: + * + * This file defines the interface to property lists. Property + * lists are a generalization of parameter blocks (pblocks). + */ + +#ifndef PUBLIC_NSAPI_H +#include "nsapi.h" +#endif /* !PUBLIC_NSAPI_H */ + +typedef struct PListStruct_s *PList_t; + +/* Define error codes returned from property list routines */ + +#define ERRPLINVPI -1 /* invalid property index */ +#define ERRPLEXIST -2 /* property already exists */ +#define ERRPLFULL -3 /* property list is full */ +#define ERRPLNOMEM -4 /* insufficient dynamic memory */ +#define ERRPLUNDEF -5 /* undefined property name */ + +#define PLFLG_OLD_MPOOL 0 /* use the plist memory pool */ +#define PLFLG_NEW_MPOOL 1 /* use the input memory pool */ +#define PLFLG_IGN_RES 2 /* ignore the reserved properties */ +#define PLFLG_USE_RES 3 /* use the reserved properties */ + +#ifdef __cplusplus +typedef void (PListFunc_t)(char*, const void*, void*); +#else +typedef void (PListFunc_t)(); +#endif + +#ifndef INTNSACL + + + +#endif /* !INTNSACL */ + +#endif /* !PUBLIC_NSACL_PLISTDEF_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/pool.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/pool.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,699 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Generic pool handling routines. + * + * These routines reduce contention on the heap and guard against + * memory leaks. + * + * Thread warning: + * This implementation is thread safe. However, simultaneous + * mallocs/frees to the same "pool" are not safe. Do not share + * pools across multiple threads without providing your own + * synchronization. + * + * Mike Belshe + * 11-20-95 + * + */ + +//include "netsite.h" +//include "systems.h" +#include "systhr.h" +#include "pool_pvt.h" +#include "ereport.h" +//include "base/session.h" +//include "frame/req.h" +//include "frame/http.h" +#include "util.h" +//include "base/crit.h" + +//include "base/dbtbase.h" + + + +#include +#include +//define PERM_MALLOC malloc +//define PERM_FREE free +//define PERM_REALLOC realloc +//define PERM_CALLOC calloc +//define PERM_STRDUP strdup + +/* Pool configuration parameters */ +static pool_config_t pool_config = POOL_CONFIG_INIT; + +/* Pool global statistics */ +static pool_global_stats_t pool_global_stats; + +static int +pool_internal_init() +{ + if (pool_global_stats.lock == NULL) { + pool_global_stats.lock = PR_NewLock(); + } + + if (pool_config.block_size == 0) { + //ereport(LOG_INFORM, XP_GetAdminStr(DBT_poolInitInternalAllocatorDisabled_)); + } + + return 0; +} + +NSAPI_PUBLIC int +pool_init(pblock *pb, Session *sn, Request *rq) +{ + //char *str_block_size = pblock_findval("block-size", pb); + //char *str_pool_disable = pblock_findval("disable", pb); + char *str_block_size = "16384"; + char *str_pool_disable = "false"; + int n; + + //printf("standard block size: %d\n", pool_config.block_size); + + if (str_block_size != NULL) { + n = atoi(str_block_size); + if (n > 0) + pool_config.block_size = n; + } + + if (str_pool_disable && util_getboolean(str_pool_disable, PR_TRUE)) { + /* We'll call PERM_MALLOC() on each pool_malloc() call */ + pool_config.block_size = 0; + pool_config.retain_size = 0; + pool_config.retain_num = 0; + } + + pool_internal_init(); + + return REQ_PROCEED; +} + +static block_t * +_create_block(pool_t *pool, int size) +{ + block_t *newblock; + char *newdata; + block_t **blk_ptr; + long blen; + + /* Does the pool have any retained blocks on its free list? */ + for (blk_ptr = &pool->free_blocks; + (newblock = *blk_ptr) != NULL; blk_ptr = &newblock->next) { + + /* Yes, is this block large enough? */ + blen = newblock->end - newblock->data; + if (blen >= size) { + + /* Yes, take it off the free list */ + *blk_ptr = newblock->next; + pool->free_size -= blen; + --pool->free_num; + + /* Give the block to the caller */ + newblock->start = newblock->data; + goto done; + } + } + + newblock = (block_t *)PERM_MALLOC(sizeof(block_t)); + newdata = (char *)PERM_MALLOC(size); + if (newblock == NULL || (newdata == NULL && size != 0)) { + //ereport(LOG_CATASTROPHE, + // XP_GetAdminStr(DBT_poolCreateBlockOutOfMemory_)); + PERM_FREE(newblock); + PERM_FREE(newdata); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; + } + newblock->data = newdata; + newblock->start = newblock->data; + newblock->end = newblock->data + size; + newblock->next = NULL; + blen = size; + +#ifdef POOL_GLOBAL_STATISTICS + PR_AtomicIncrement((PRInt32 *)&pool_global_stats.blkAlloc); +#endif /* POOL_GLOBAL_STATISTICS */ + + done: + +#ifdef PER_POOL_STATISTICS + ++pool->stats.blkAlloc; +#endif /* PER_POOL_STATISTICS */ + + return newblock; +} + +static void +_free_block(block_t *block) +{ + long blen = block->end - block->data; + +#ifdef POOL_ZERO_DEBUG + memset(block->data, POOL_ZERO_DEBUG, blen); +#endif /* POOL_ZERO_DEBUG */ + + PERM_FREE(block->data); + +#ifdef POOL_ZERO_DEBUG + memset(block, POOL_ZERO_DEBUG, sizeof(block)); +#endif /* POOL_ZERO_DEBUG */ + + PERM_FREE(block); + +#ifdef POOL_GLOBAL_STATISTICS + PR_AtomicIncrement((PRInt32 *)&pool_global_stats.blkFree); +#endif /* POOL_GLOBAL_STATISTICS */ +} + +/* ptr_in_pool() + * Checks to see if the given pointer is in the given pool. + * If true, returns a ptr to the block_t containing the ptr; + * otherwise returns NULL + */ +block_t * +_ptr_in_pool(pool_t *pool, const void *ptr) +{ + block_t *block_ptr = NULL; + + /* try to find a block which contains this ptr */ + + if (POOL_PTR_IN_BLOCK(pool->curr_block, ptr)) { + block_ptr = pool->curr_block; + } + else { + for (block_ptr = pool->used_blocks; block_ptr; block_ptr = block_ptr->next) { + if (POOL_PTR_IN_BLOCK(block_ptr, ptr)) + break; + } + } + return block_ptr; +} + + +NSAPI_PUBLIC pool_handle_t * +pool_create() +{ + pool_t *newpool; + + newpool = (pool_t *)PERM_MALLOC(sizeof(pool_t)); + + if (newpool) { + /* Have to initialize now, as pools get created sometimes + * before pool_init can be called... + */ + if (pool_global_stats.lock == NULL) { + pool_internal_init(); + } + + newpool->used_blocks = NULL; + newpool->free_blocks = NULL; + newpool->free_size = 0; + newpool->free_num = 0; + newpool->size = 0; + newpool->next = NULL; + +#ifdef PER_POOL_STATISTICS + /* Initial per pool statistics */ + memset((void *)(&newpool->stats), 0, sizeof(newpool->stats)); + newpool->stats.thread = PR_GetCurrentThread(); + newpool->stats.created = PR_Now(); +#endif /* PER_POOL_STATISTICS */ + + /* No need to lock, since pool has not been exposed yet */ + newpool->curr_block =_create_block(newpool, pool_config.block_size); + if (newpool->curr_block == NULL) { + //ereport(LOG_CATASTROPHE, XP_GetAdminStr(DBT_poolCreateOutOfMemory_)); + pool_destroy((pool_handle_t *)newpool); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; + } + + /* Add to known pools list */ + PR_Lock(pool_global_stats.lock); + newpool->next = pool_global_stats.poolList; + pool_global_stats.poolList = newpool; + ++pool_global_stats.createCnt; +#ifdef PER_POOL_STATISTICS + newpool->stats.poolId = pool_global_stats.createCnt; +#endif /* PER_POOL_STATISTICS */ + PR_Unlock(pool_global_stats.lock); + + } + else { + //ereport(LOG_CATASTROPHE, XP_GetAdminStr(DBT_poolCreateOutOfMemory_1)); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + + return (pool_handle_t *)newpool; +} + +/* + * pool_mark - get mark for subsequent recycle + * + * This function returns a value that can be used to free all pool + * memory which is subsequently allocated, without freeing memory + * that has already been allocated when pool_mark() is called. + * The pool_recycle() function is used to free the memory allocated + * since pool_mark() was called. + * + * This function may be called several times before pool_recycle() + * is called, but some care must be taken not to pass an invalid + * mark value to pool_recycle(), which would cause all pool memory + * to be freed. A mark value becomes invalid when pool_recycle is + * called with a previously returned mark value. + */ +NSAPI_PUBLIC void * +pool_mark(pool_handle_t *pool_handle) +{ + pool_t *pool = (pool_t *)pool_handle; + + PR_ASSERT(pool != NULL); + + if (pool == NULL) + return NULL; + +#ifdef PER_POOL_STATISTICS + pool->stats.thread = PR_GetCurrentThread(); +#endif /* PER_POOL_STATISTICS */ + + /* Never return end as it points outside the block */ + if (pool->curr_block->start == pool->curr_block->end) + return pool->curr_block; + + return (void *)(pool->curr_block->start); +} + +/* + * pool_recycle - recycle memory in a pool + * + * This function returns all the allocated memory for a pool back to + * a free list associated with the pool. It is like pool_destroy() in + * the sense that all data structures previously allocated from the + * pool are freed, but it keeps the memory associated with the pool, + * and doesn't actually destroy the pool. + * + * The "mark" argument can be a value previously returned by + * pool_mark(), in which case the pool is returned to the state it + * was in when pool_mark() was called, or it can be NULL, in which + * case the pool is completely recycled. + */ +NSAPI_PUBLIC void +pool_recycle(pool_handle_t *pool_handle, void *mark) +{ + pool_t *pool = (pool_t *)pool_handle; + block_t *tmp_blk; + unsigned long blen; + + PR_ASSERT(pool != NULL); + + if (pool == NULL) + return; + + /* Fix up curr_block. There should always be a curr_block. */ + tmp_blk = pool->curr_block; + PR_ASSERT(tmp_blk != NULL); + + /* Start with curr_block, then scan blocks on used_blocks list */ + for (;;) { + + /* Check if the mark is at the end of this block */ + if (tmp_blk == mark) { + pool->curr_block = tmp_blk; + break; + } + + /* Look for a block containing the mark */ + if (POOL_PTR_IN_BLOCK(tmp_blk, mark)) { + + /* Reset block start pointer to marked spot */ + if (tmp_blk == pool->curr_block) { + blen = tmp_blk->start - (char *)mark; + } else { + blen = tmp_blk->end - (char *)mark; + } + pool->size -= blen; + PR_ASSERT(pool->size >= 0); + tmp_blk->start = (char *)mark; + pool->curr_block = tmp_blk; + break; + } + + /* Reset block start pointer to base of block */ + if (tmp_blk == pool->curr_block) { + /* Count just the allocated length in the current block */ + blen = tmp_blk->start - tmp_blk->data; + } + else { + /* Count the entire size of a used_block */ + blen = tmp_blk->end - tmp_blk->data; + } + tmp_blk->start = tmp_blk->data; + pool->size -= blen; + PR_ASSERT(pool->size >= 0); + + /* + * If there are no more used blocks after this one, then set + * this block up as the current block and return. + */ + if (pool->used_blocks == NULL) { + PR_ASSERT(mark == NULL); + pool->curr_block = tmp_blk; + break; + } + + /* Otherwise free this block one way or another */ + + /* Add block length to total retained length and check limit */ + if ((pool->free_size + blen) <= pool_config.retain_size && + pool->free_num < pool_config.retain_num) { + + /* Retain block on pool free list */ + /* + * XXX hep - could sort blocks on free list in order + * ascending size to get "best fit" allocation in + * _create_block(), but the default block size is large + * enough that fit should rarely be an issue. + */ + tmp_blk->next = pool->free_blocks; + pool->free_blocks = tmp_blk; + pool->free_size += blen; + ++pool->free_num; + } + else { + /* Limit exceeded - free block */ + _free_block(tmp_blk); + } + +#ifdef PER_POOL_STATISTICS + ++pool->stats.blkFree; +#endif /* PER_POOL_STATISTICS */ + + /* Remove next block from used blocks list */ + tmp_blk = pool->used_blocks; + pool->used_blocks = tmp_blk->next; + } +} + +NSAPI_PUBLIC void +pool_destroy(pool_handle_t *pool_handle) +{ + pool_t *pool = (pool_t *)pool_handle; + block_t *tmp_blk; + + PR_ASSERT(pool != NULL); + + if (pool == NULL) + return; + + if (pool->curr_block) + _free_block(pool->curr_block); + + while(pool->used_blocks) { + tmp_blk = pool->used_blocks; + pool->used_blocks = tmp_blk->next; + _free_block(tmp_blk); + } + + while(pool->free_blocks) { + tmp_blk = pool->free_blocks; + pool->free_blocks = tmp_blk->next; + _free_block(tmp_blk); + } + + { + pool_t **ppool; + + /* Remove from the known pools list */ + PR_Lock(pool_global_stats.lock); + for (ppool = &pool_global_stats.poolList; + *ppool; ppool = &(*ppool)->next) { + if (*ppool == pool) { + ++pool_global_stats.destroyCnt; + *ppool = pool->next; + break; + } + } + PR_Unlock(pool_global_stats.lock); + } + +#ifdef POOL_ZERO_DEBUG + memset(pool, POOL_ZERO_DEBUG, sizeof(pool)); +#endif /* POOL_ZERO_DEBUG */ + + PERM_FREE(pool); + + return; +} + + +NSAPI_PUBLIC void * +pool_malloc(pool_handle_t *pool_handle, size_t size) +{ + pool_t *pool = (pool_t *)pool_handle; + block_t *curr_block; + long reqsize, blocksize; + char *ptr; + + if (pool == NULL) + return PERM_MALLOC(size); + + reqsize = ALIGN(size); + if (reqsize == 0) { + /* Assign a unique address to each 0-byte allocation */ + reqsize = WORD_SIZE; + } + + curr_block = pool->curr_block; + ptr = curr_block->start; + curr_block->start += reqsize; + + /* does this fit into the last allocated block? */ + if (curr_block->start > curr_block->end) { + + /* Did not fit; time to allocate a new block */ + + curr_block->start -= reqsize; /* keep structs in tact */ + + /* Count unallocated bytes in current block in pool size */ + pool->size += curr_block->end - curr_block->start; + PR_ASSERT(pool->size >= 0); +#ifdef PER_POOL_STATISTICS + if (pool->size > pool->stats.maxAlloc) { + pool->stats.maxAlloc = pool->size; + } +#endif /* PER_POOL_STATISTICS */ + + /* Move current block to used block list */ + curr_block->next = pool->used_blocks; + pool->used_blocks = curr_block; + + /* Allocate a chunk of memory which is at least block_size bytes */ + blocksize = reqsize; + if (blocksize < pool_config.block_size) + blocksize = pool_config.block_size; + + curr_block = _create_block(pool, blocksize); + pool->curr_block = curr_block; + + if (curr_block == NULL) { + //ereport(LOG_CATASTROPHE, + // XP_GetAdminStr(DBT_poolMallocOutOfMemory_)); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; + } + + ptr = curr_block->start; + curr_block->start += reqsize; + } + + pool->size += reqsize; + PR_ASSERT(pool->size >= 0); + +#ifdef PER_POOL_STATISTICS + if (pool->size > pool->stats.maxAlloc) { + pool->stats.maxAlloc = pool->size; + } + ++pool->stats.allocCnt; + pool->stats.thread = PR_GetCurrentThread(); +#endif /* PER_POOL_STATISTICS */ + + return ptr; +} + +NSAPI_PUBLIC void +pool_free(pool_handle_t *pool_handle, void *ptr) +{ + pool_t *pool = (pool_t *)pool_handle; + + if (ptr == NULL) + return; + + if (pool == NULL) { + PERM_FREE(ptr); + return; + } + + PR_ASSERT(_ptr_in_pool(pool, ptr)); + +#ifdef PER_POOL_STATISTICS + + ++pool->stats.freeCnt; + pool->stats.thread = PR_GetCurrentThread(); + +#endif /* PER_POOL_STATISTICS */ + + return; +} + +NSAPI_PUBLIC void * +pool_calloc(pool_handle_t *pool_handle, size_t nelem, size_t elsize) +{ + void *ptr; + + if (pool_handle == NULL) + return calloc(1, elsize * nelem); + + ptr = pool_malloc(pool_handle, elsize * nelem); + if (ptr) + memset(ptr, 0, elsize * nelem); + return ptr; +} + +NSAPI_PUBLIC void * +pool_realloc(pool_handle_t *pool_handle, void *ptr, size_t size) +{ + pool_t *pool = (pool_t *)pool_handle; + void *newptr; + block_t *block_ptr; + size_t oldsize; + + if (pool == NULL) + return PERM_REALLOC(ptr, size); + + if ( (newptr = pool_malloc(pool_handle, size)) == NULL) + return NULL; + + /* With our structure we don't know exactly where the end + * of the original block is. But we do know an upper bound + * which is a valid ptr. Search the outstanding blocks + * for the block which contains this ptr, and copy... + */ + + if ( !(block_ptr = _ptr_in_pool(pool, ptr)) ) { + /* User is trying to realloc nonmalloc'd space! */ + return newptr; + } + + oldsize = block_ptr->end - (char *)ptr ; + if (oldsize > size) + oldsize = size; + memmove((char *)newptr, (char *)ptr, oldsize); + + return newptr; +} + +NSAPI_PUBLIC char * +pool_strdup(pool_handle_t *pool_handle, const char *orig_str) +{ + char *new_str; + int len = strlen(orig_str); + + if (pool_handle == NULL) + return PERM_STRDUP(orig_str); + + new_str = (char *)pool_malloc(pool_handle, len+1); + + if (new_str) + memcpy(new_str, orig_str, len+1); + + return new_str; +} + +NSAPI_PUBLIC long +pool_space(pool_handle_t *pool_handle) +{ + pool_t *pool = (pool_t *)pool_handle; + + return pool->size; +} + +NSAPI_PUBLIC int pool_enabled() +{ + if (getThreadMallocKey() == -1) + return 0; + + if (!systhread_getdata(getThreadMallocKey())) + return 0; + + return 1; +} + +#ifdef DEBUG +NSAPI_PUBLIC void INTpool_assert(pool_handle_t *pool_handle, const void *ptr) +{ + pool_t *pool = (pool_t *)pool_handle; + + if (pool == NULL) + return; + + PR_ASSERT(_ptr_in_pool(pool, ptr)); +} +#endif + +NSAPI_PUBLIC pool_config_t *pool_getConfig(void) +{ + return &pool_config; +} + +#ifdef POOL_GLOBAL_STATISTICS +NSAPI_PUBLIC pool_global_stats_t *pool_getGlobalStats(void) +{ + return &pool_global_stats; +} +#endif /* POOL_GLOBAL_STATISTICS */ + +#ifdef PER_POOL_STATISTICS +NSAPI_PUBLIC pool_stats_t *pool_getPoolStats(pool_handle_t *pool_handle) +{ + pool_t *pool = (pool_t *)pool_handle; + + if (pool == NULL) + return NULL; + + return &pool->stats; +} +#endif /* PER_POOL_STATISTICS */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/pool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/pool.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,139 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_POOL_H +#define BASE_POOL_H + +#ifndef NOINTNSAPI +#define INTNSAPI +#endif /* !NOINTNSAPI */ + +/* + * pool.h + * + * Module for handling memory allocations. + * + * Notes: + * This module is used instead of the NSPR prarena module because the prarenas + * did not fit as cleanly into the existing server. + * + * Mike Belshe + * 10-02-95 + * + */ + +#ifndef NETSITE_H +//include "netsite.h" +#include "nsapi.h" +#include "nspr.h" +#endif /* !NETSITE_H */ + +#ifndef BASE_PBLOCK_H +//include "pblock.h" +#endif /* !BASE_PBLOCK_H */ + +#ifndef BASE_SESSION_H +//#include "session.h" +#endif /* !BASE_SESSION_H */ + +#ifndef FRAME_REQ_H +//include "frame/req.h" +#endif /* !FRAME_REQ_H */ + +/* --- Begin function prototypes --- */ + +#ifdef INTNSAPI + +NSPR_BEGIN_EXTERN_C + +NSAPI_PUBLIC int INTpool_init(pblock *pb, Session *sn, Request *rq); + +#ifdef DEBUG_CACHES +NSAPI_PUBLIC int INTpool_service_debug(pblock *pb, Session *sn, Request *rq); +#endif + +NSAPI_PUBLIC pool_handle_t *INTpool_create(void); + +NSAPI_PUBLIC void *INTpool_mark(pool_handle_t *pool_handle); + +NSAPI_PUBLIC void INTpool_recycle(pool_handle_t *pool_handle, void *mark); + +NSAPI_PUBLIC void INTpool_destroy(pool_handle_t *pool_handle); + +NSAPI_PUBLIC int INTpool_enabled(void); + +NSAPI_PUBLIC void *INTpool_malloc(pool_handle_t *pool_handle, size_t size ); + +NSAPI_PUBLIC void INTpool_free(pool_handle_t *pool_handle, void *ptr ); + +NSAPI_PUBLIC +void *INTpool_calloc(pool_handle_t *pool_handle, size_t nelem, size_t elsize); + +NSAPI_PUBLIC +void *INTpool_realloc(pool_handle_t *pool_handle, void *ptr, size_t size ); + +NSAPI_PUBLIC +char *INTpool_strdup(pool_handle_t *pool_handle, const char *orig_str ); + +#ifdef DEBUG +NSAPI_PUBLIC void INTpool_assert(pool_handle_t *pool_handle, const void *ptr); +#endif + +NSPR_END_EXTERN_C + +#define pool_init INTpool_init + +#ifdef DEBUG_CACHES +#define pool_service_debug INTpool_service_debug +#endif /* DEBUG_CACHES */ + +#ifdef DEBUG +#define POOL_ASSERT(pool, ptr) INTpool_assert(pool, ptr); +#else +#define POOL_ASSERT(pool, ptr) +#endif + +#define pool_create INTpool_create +#define pool_mark INTpool_mark +#define pool_recycle INTpool_recycle +#define pool_destroy INTpool_destroy +#define pool_enabled INTpool_enabled +#define pool_malloc INTpool_malloc +#define pool_free INTpool_free +#define pool_calloc INTpool_calloc +#define pool_realloc INTpool_realloc +#define pool_strdup INTpool_strdup + +#endif /* INTNSAPI */ + +#endif /* !BASE_POOL_H_ */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/pool_pvt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/pool_pvt.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,183 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_POOL_PVT_H +#define BASE_POOL_PVT_H + +#ifndef BASE_POOL_H +#include "pool.h" +#endif /* BASE_POOL_H */ + +/* + * pool_pvt.h - private definitions for memory pools + */ + +/* Definitions */ + +/* + * Define PER_POOL_STATISTICS to get detailed statistics for each + * pool. + */ +#ifdef DEBUG +#define PER_POOL_STATISTICS +#endif + +/* Define POOL_GLOBAL_STATISTICS to get global pool statistics */ +#define POOL_GLOBAL_STATISTICS + +/* + * When POOL_ZERO_DEBUG is defined, overwrite the contents of freed + * pool data structures and memory with the POOL_ZERO_DEBUG byte value. + */ +#ifdef DEBUG +#define POOL_ZERO_DEBUG 0xa +#endif + +/* + * DEFAULT_BLOCK_SIZE specifies the minimum granularity, in bytes, used + * in allocating memory from the heap for use with a pool. A request + * for more than DEFAULT_BLOCK_SIZE bytes from a pool will cause a block + * of that size to be allocated from the heap. + */ +#define DEFAULT_BLOCK_SIZE (32 * 1024) + +/* + * The pool_recycle() mechanism keeps a list of free blocks associated + * with each pool, in order to avoid global locking when doing the + * pool_recycle() operation, or when subsequently allocating memory + * from the pool. DEFAULT_RETENTION_SIZE and DEFAULT_RETENTION_NUM + * specify the maximum number of bytes and blocks, respectively, that + * will be kept on a per-pool free list. + */ +#define DEFAULT_RETENTION_SIZE (DEFAULT_BLOCK_SIZE * 2) +#define DEFAULT_RETENTION_NUM 2 + +/* WORD_SIZE 8 sets us up for 8 byte alignment. */ +#define WORD_SIZE 8 +#undef ALIGN +#define ALIGN(x) ( (x + WORD_SIZE-1) & (~(WORD_SIZE-1)) ) + +/* Types */ + +/* + * pool_stats_t + * This structure contains per pool statistics. + */ +#ifdef PER_POOL_STATISTICS +typedef struct pool_stats_t pool_stats_t; +struct pool_stats_t { + PRUint32 poolId; /* pool id */ + PRUint32 maxAlloc; /* maximum bytes ever used from pool */ + PRUint32 allocCnt; /* count of memory allocations from pool */ + PRUint32 freeCnt; /* count of pool memory free operations */ + PRUint32 blkAlloc; /* count of block allocations */ + PRUint32 blkFree; /* count of blocks freed (on pool_recycle) */ + PRThread *thread; /* last thread to use pool */ + PRTime created; /* time of pool creation */ +}; +#endif /* PER_POOL_STATISTICS */ + +typedef struct pool_config_t pool_config_t; +struct pool_config_t { + PRUint32 block_size; /* size of blocks to allocate */ + PRUint32 retain_size; /* maximum bytes kept on per-pool free list */ + PRUint32 retain_num; /* maximum blocks kept on per-pool free list */ +}; + +#define POOL_CONFIG_INIT { \ + DEFAULT_BLOCK_SIZE, /* block_size */ \ + DEFAULT_RETENTION_SIZE, /* retain_size */ \ + DEFAULT_RETENTION_NUM, /* retain_num */ \ + } + +/* + * block_t + * When the user allocates space, a DEFAULT_BLOCK_SIZE (or larger) block + * is created in the pool. This block is used until all the space is + * eaten within it. When all the space is gone, a new block is created. + */ +typedef struct block_t block_t; +struct block_t { + char *data; /* the real alloc'd space */ + char *start; /* first free byte in block */ + char *end; /* ptr to end of block */ + block_t *next; /* ptr to next block */ +}; + +#define POOL_PTR_IN_BLOCK(blk, ptr) \ + (((char *)(ptr) < (blk)->end) && ((char *)(ptr) >= (blk)->data)) + +/* + * pool_t + * A pool is a collection of blocks. The blocks consist of multiple + * allocations of memory, but a single allocation cannot be freed by + * itself. Once the memory is allocated it is allocated until the + * entire pool is freed. + */ +typedef struct pool_t pool_t; +struct pool_t { + block_t *curr_block; /* current block being used */ + block_t *used_blocks; /* blocks that are all used up */ + block_t *free_blocks; /* blocks that are free */ + PRUint32 free_size; /* number of bytes in free_blocks */ + PRUint32 free_num; /* number of blocks in free_blocks */ + size_t size; /* size of memory in pool */ + pool_t *next; /* known_pools list */ +#ifdef PER_POOL_STATISTICS + pool_stats_t stats; /* statistics for this pool */ +#endif /* PER_POOL_STATISTICS */ +}; + +typedef struct pool_global_stats_t pool_global_stats_t; +struct pool_global_stats_t { + PRLock *lock; /* lock for access to poolList */ + pool_t *poolList; /* list of known pools */ + PRUint32 createCnt; /* count of pools created */ + PRUint32 destroyCnt; /* count of pools destroyed */ +#ifdef POOL_GLOBAL_STATISTICS + PRUint32 blkAlloc; /* count of block allocations from heap */ + PRUint32 blkFree; /* count of blocks freed to heap */ +#endif /* POOL_GLOBAL_STATISTICS */ +}; + +/* Private functions for inspecting pool configuration/statistics */ + +NSAPI_PUBLIC pool_config_t *pool_getConfig(void); + +NSAPI_PUBLIC pool_global_stats_t *pool_getGlobalStats(void); + +#ifdef PER_POOL_STATISTICS +NSAPI_PUBLIC pool_stats_t *pool_getPoolStats(pool_handle_t *pool_handle); +#endif + +#endif /* BASE_POOL_PVT_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/request.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/request.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,91 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "request.h" + +#include "pblock.h" +#include "httprequest.h" + + +/* Code from req.cpp */ + +/* -------------------------- request_initialize -------------------------- */ + +int request_initialize( + pool_handle_t *pool, + HTTPRequest *hrq, + NSAPIRequest *nrq) +{ + Request *rq = &nrq->rq; + + rq->vars = pblock_create_pool(pool, REQ_HASHSIZE); + if (!rq->vars) + return 1; + rq->reqpb = pblock_create_pool(pool, REQ_HASHSIZE); + if (!rq->reqpb) + return 1; + rq->loadhdrs = 0; + rq->headers = pblock_create_pool(pool, REQ_HASHSIZE); + if (!rq->headers) + return 1; + rq->senthdrs = 0; + rq->srvhdrs = pblock_create_pool(pool, REQ_HASHSIZE); + if (!rq->srvhdrs) + return 1; + + rq->os = NULL; + rq->tmpos = NULL; + rq->statpath = NULL; + rq->staterr = NULL; + rq->finfo = NULL; + rq->aclstate = 0; + rq->acldirno = 0; + rq->aclname = NULL; + rq->aclpb = NULL; + rq->acllist = NULL; + rq->request_is_cacheable = 0; + rq->directive_is_cacheable = 0; + rq->cached_headers = NULL; + rq->cached_headers_len = 0; + rq->unused = NULL; + //rq->req_start = ft_time(); // TODO: ft_time + rq->protv_num = 0; + rq->method_num = -1; + //PR_ASSERT(sizeof(rq->rq_attr) == sizeof(RQATTR)); // TODO: assert + *(RQATTR *) &rq->rq_attr = 0; + //rq->hostname = pool_strdup(pool, hostname); // TODO: hostname + rq->allowed = 0; + rq->byterange = 0; + rq->status_num = 0; + rq->staterrno = 0; + rq->orig_rq = rq; + + // TODO: nrq + + return 0; +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/request.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/request.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,53 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef REQUEST_H +#define REQUEST_H + +#include "nsapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NSAPIRequest NSAPIRequest; + + +struct NSAPIRequest { + Request rq; +}; + +#define REQ_HASHSIZE 10 + + +#ifdef __cplusplus +} +#endif + +#endif /* REQUEST_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/session.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/session.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,33 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "nsapi.h" + +#include "session.h" + + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/session.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/session.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,51 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SESSION_H +#define SESSION_H + +#include "nsapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NSAPISession NSAPISession; + +struct NSAPISession { + Session sn; /* public session structure */ + int sys_fd; /* system file descriptor */ +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSION_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/sessionhandler.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/sessionhandler.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,103 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "nsapi.h" + +#include "sessionhandler.h" +#include "httprequest.h" +#include "httpparser.h" + +SessionHandler* create_basic_session_handler() { + BasicSessionHandler *handler = malloc(sizeof(BasicSessionHandler)); + handler->threadpool = threadpool_new(8); + handler->sh.enqueue_connection = basic_enq_conn; + + + return (SessionHandler*)handler; +} + +void basic_enq_conn(SessionHandler *handler, Connection *conn) { + BasicSessionHandler *sh = (BasicSessionHandler*)handler; + conn->session_handler = handler; + threadpool_run(sh->threadpool, basic_run_session, conn); +} + +void* basic_run_session(void *data) { + Connection *conn = (Connection*)data; + + HTTPRequest *request = http_request_new(); + request->connection = conn; + + // read request + netbuf *buf = malloc(sizeof(netbuf)); + buf->rdtimeout = 120; + buf->pos = 0; + buf->cursize = 0; + buf->maxsize = 2048; + buf->sd = &conn->fd; + buf->inbuf = malloc(2048); + buf->errmsg = NULL; + + request->netbuf = buf; + + HttpParser *parser = http_parser_new(request); + int state; + int r; + r = read(conn->fd, buf->inbuf + buf->pos, buf->maxsize - buf->pos); + if(r == -1) { + // TODO: error handling + fprintf(stderr, "%s\n", "Error: Cannot read from socket"); + return NULL; + } + buf->cursize += r; + while((state = http_parser_process(parser)) != 0) { + if(state == 2) { + // TODO: error handling + fprintf(stderr, "%s\n", "Error: Cannot parse http request"); + return NULL; + } + r = read(conn->fd, buf->inbuf + buf->pos, buf->maxsize - buf->pos); + if(r == -1) { + // TODO: error handling + fprintf(stderr, "%s\n", "Error: Cannot read from socket"); + return NULL; + } + buf->cursize += r; + } + + // process request + r = handle_request(request); + + + return NULL; +} + + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/sessionhandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/sessionhandler.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,79 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SESSIONHANDLER_H +#define SESSIONHANDLER_H + +#include "thrpool.h" +#include "nsapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _session_handler SessionHandler; +typedef struct _connection Connection; + +struct _connection { + int fd; + struct sockaddr_in address; + SessionHandler *session_handler; +}; + +typedef void(*enqueue_connection_f)(SessionHandler*, Connection*); +struct _session_handler { + enqueue_connection_f enqueue_connection; +}; + +/* + * BasicSessionHandler + * + * The BasicSessionHandler enqueues the connections to a threadpool. IO and + * request processing is handled by one thread. + */ +typedef struct _basic_session_handler { + SessionHandler sh; + threadpool_t *threadpool; + +} BasicSessionHandler; + + +SessionHandler* create_basic_session_handler(); + +void basic_enq_conn(SessionHandler *handler, Connection *conn); + +void* basic_run_session(void *data); + + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONHANDLER_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/sstring.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/sstring.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,120 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "sstring.h" + +sstr_t sstr (char *s) { + sstr_t string; + string.ptr = s; + string.length = strlen(s); + return string; +} + +sstr_t sstrn (char *s, size_t n) { + sstr_t string; + string.ptr = s; + string.length = n; + return string; +} + +size_t sstrnlen (size_t n, sstr_t s, ...) { + va_list ap; + size_t size = s.length; + va_start(ap, s); + + for (int i=0;i= s.length || length < 0) { + return s; + } + if (length > s.length-start) { + length = s.length-start; + } + new_sstr.ptr = &s.ptr[start]; + new_sstr.length = length; + return new_sstr; +} + +int sstrcmp(sstr_t s1, sstr_t s2) { + return strncmp(s1.ptr, s2.ptr, s1.length>s2.length ? s2.length: s1.length); +} + +sstr_t sstrdub(sstr_t s) { + sstr_t newstring; + newstring.ptr = malloc(s.length + 1); + newstring.length = s.length; + newstring.ptr[newstring.length] = 0; + + memcpy(newstring.ptr, s.ptr, s.length); + + return newstring; +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/sstring.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/sstring.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,100 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SSTRING_H +#define _SSTRING_H + +#define S(s) { s, sizeof(s)-1 } +#define ST(s) sstrn(s, sizeof(s)-1) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct sstring { + char *ptr; + size_t length; +} sstr_t; + +/* + * creates a new sstr_t from a null terminated string + * + * s null terminated string + */ +sstr_t sstr (char *s); + +/* + * creates a new sstr_t from a string and length + * + * s string + * n length of string + */ +sstr_t sstrn (char *s, size_t n); + + +/* + * gets the length of n sstr_t strings + * + * n number of strings + * s string + * ... strings + */ +size_t sstrnlen (size_t n, sstr_t s, ...); + + +/* + * concatenates n strings + * + * n number of strings + * s new string with enough memory allocated + * ... strings + */ +sstr_t sstrncat (size_t n, sstr_t s, sstr_t c1, ...); + + +/* + * + */ +sstr_t sstrsubs (sstr_t s, size_t start); + +/* + * + */ +sstr_t sstrsubsl (sstr_t s, size_t start, size_t end); + + +int sstrcmp(sstr_t s1, sstr_t s2); + +sstr_t sstrdub(sstr_t s); + +#ifdef __cplusplus +} +#endif + +#endif /* _SSTRING_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/system.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/system.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,387 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * system.c: A grab bag of system-level abstractions + * + * Many authors + */ + +#if (defined(__GNUC__) && (__GNUC__ > 2)) +#include +using namespace std; +#else +//include +#endif +#include "netsite.h" +#include "ereport.h" + +#ifdef XP_WIN32 +#include +#include +#endif + +static int thread_malloc_key = -1; + +static char* temp_dir = NULL; + +#ifdef XP_WIN32 +_PNH original_newhandler = 0; +#else +typedef void (newhandler)(void); +static newhandler *original_newhandler = 0; +#endif + +#include "pool.h" +#include "systhr.h" + +#define MALLOC_KEY \ + ((pool_handle_t *)(thread_malloc_key != -1 ? systhread_getdata(thread_malloc_key) : NULL)) + + +#ifdef MCC_DEBUG +#define DEBUG_MALLOC +#endif + +#ifdef DEBUG_MALLOC + +/* The debug malloc routines provide several functions: + * + * - detect allocated memory overflow/underflow + * - detect multiple frees + * - intentionally clobbers malloc'd buffers + * - intentionally clobbers freed buffers + */ +#define DEBUG_MAGIC 0x12345678 +#define DEBUG_MARGIN 32 +#define DEBUG_MARGIN_CHAR '*' +#define DEBUG_MALLOC_CHAR '.' +#define DEBUG_FREE_CHAR 'X' +#endif /* DEBUG_MALLOC */ + +NSAPI_PUBLIC char *system_version() +{ + //return PRODUCT_ID"/"PRODUCT_VERSION_ID; + return "Solaris 11 Express"; +} + +NSAPI_PUBLIC pool_handle_t *system_pool(void) +{ + return MALLOC_KEY; +} + +NSAPI_PUBLIC void *system_malloc(int size) +{ + void *ret; + ret = pool_malloc(MALLOC_KEY, size); + if (!ret) { + //ereport_outofmemory(); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + return ret; +} + + +NSAPI_PUBLIC void *system_calloc(int size) +{ + void *ret; + ret = pool_malloc(MALLOC_KEY, size); + if(ret) { + ZERO(ret, size); + } else { + //ereport_outofmemory(); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + return ret; +} + + +NSAPI_PUBLIC void *system_realloc(void *ptr, int size) +{ + void *ret; + ret = pool_realloc(MALLOC_KEY, ptr, size); + if (!ret) { + //ereport_outofmemory(); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + return ret; +} + + +NSAPI_PUBLIC void system_free(void *ptr) +{ + pool_free(MALLOC_KEY, ptr); +} + +NSAPI_PUBLIC char *system_strdup(const char *ptr) +{ + //NS_ASSERT(ptr); + char *ret; + ret = pool_strdup(MALLOC_KEY, ptr); + if (!ret) { + //ereport_outofmemory(); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + return ret; +} + + +NSAPI_PUBLIC void *system_malloc_perm(int size) +{ + void *ret; +#ifndef DEBUG_MALLOC + ret = malloc(size); +#else + char *ptr = (char *)malloc(size + 2*DEBUG_MARGIN+2*sizeof(int)); + char *real_ptr; + int *magic; + int *length; + + magic = (int *)ptr; + *magic = DEBUG_MAGIC; + ptr += sizeof(int); + length = (int *)ptr; + *length = size; + ptr += sizeof(int); + memset(ptr, DEBUG_MARGIN_CHAR, DEBUG_MARGIN); + ptr += DEBUG_MARGIN; + memset(ptr, DEBUG_MALLOC_CHAR, size); + real_ptr = ptr; + ptr += size; + memset(ptr, DEBUG_MARGIN_CHAR, DEBUG_MARGIN); + + ret = real_ptr; +#endif + if (!ret) { + //ereport_outofmemory(); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + return ret; +} + +NSAPI_PUBLIC void *system_calloc_perm(int size) +{ + void *ret = system_malloc_perm(size); + if(ret) + ZERO(ret, size); + return ret; +} + +NSAPI_PUBLIC void *system_realloc_perm(void *ptr, int size) +{ + void *ret; + +#ifndef DEBUG_MALLOC + ret = realloc(ptr, size); +#else + int *magic, *length; + char *baseptr; + char *cptr; + + /* realloc semantics allow realloc(NULL, size) */ + if (ptr == NULL) + return system_malloc_perm(size); + + cptr = (char *)ptr - DEBUG_MARGIN - 2 * sizeof(int); + magic = (int *)cptr; + if (*magic == DEBUG_MAGIC) { + cptr += sizeof(int); + length = (int *)cptr; + if (*length < size) { + char *newptr = (char *)system_malloc_perm(size); + memcpy(newptr, ptr, *length); + system_free_perm(ptr); + + ret = newptr; + }else { + ret = ptr; + } + } else { + ereport(LOG_WARN, XP_GetAdminString(DBT_systemReallocSmallerSize)); + ret = realloc(ptr, size); + } +#endif + + if (!ret) { + //ereport_outofmemory(); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + + return ret; +} + +NSAPI_PUBLIC void system_free_perm(void *ptr) +{ +#ifdef DEBUG_MALLOC + int *length, *magic; + char *baseptr, *cptr; + int index; + + NS_ASSERT(ptr); + + cptr = baseptr = ((char *)ptr) - DEBUG_MARGIN - 2*sizeof(int); + + magic = (int *)cptr; + if (*magic == DEBUG_MAGIC) { + cptr += sizeof(int); + + length = (int *)cptr; + + cptr += sizeof(int); + for (index=0; index + +#ifndef NOINTNSAPI +#define INTNSAPI +#endif /* !NOINTNSAPI */ + +/* + * systems.h: Lists of defines for systems + * + * This sets what general flavor the system is (UNIX, etc.), + * and defines what extra functions your particular system needs. + */ + + +/* --- Begin common definitions for all supported platforms --- */ + +#define DAEMON_ANY +#define DAEMON_STATS + +/* --- End common definitions for all supported platforms --- */ + +/* --- Begin platform-specific definitions --- */ + +#if defined(AIX) + +#define HAS_IPV6 +#define AUTH_DBM +#define BSD_RLIMIT +#undef BSD_SIGNALS +//define DAEMON_NEEDS_SEMAPHORE +//define DAEMON_UNIX_MOBRULE +//define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW|RTLD_GLOBAL +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATFS +#define HAVE_ATEXIT +#define HAVE_STRERROR_R +#define HAVE_STRTOK_R +#define HAVE_TIME_R 2 /* arg count */ +#define HAVE_STRFTIME /* no cftime */ +#define JAVA_STATIC_LINK +#undef NEED_CRYPT_H +#define NEED_STRINGS_H /* for strcasecmp */ +#define NET_SOCKETS +#define SA_HANDLER_T(x) (void (*)(int))x +#ifdef NS_OLDES3X +#define SA_NOCLDWAIT 0 /* AIX don't got this */ +#endif +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED +#ifdef HW_THREADS +#define THREAD_ANY +#endif +#elif defined(BSDI) + +#define AUTH_DBM +#define BSD_MAIL +#define BSD_RLIMIT +#define BSD_SIGNALS +#define BSD_TIME +#define DAEMON_UNIX_MOBRULE +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS (MAP_FILE | MAP_SHARED) +#define HAS_STATFS +#define HAVE_ATEXIT +#undef NEED_CRYPT_PROTO +#define NET_SOCKETS +#define NO_DOMAINNAME +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED +#define JAVA_STATIC_LINK + +#elif defined(HPUX) + +#define HAVE_TIME_R 2 /* arg count */ +#define AUTH_DBM +#undef BSD_RLIMIT +#undef BSD_SIGNALS +#ifdef MCC_PROXY +#define DAEMON_NEEDS_SEMAPHORE +#else +#define DAEMON_NEEDS_SEMAPHORE +#endif +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_HPSHL +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_PRIVATE +#define HAS_STATFS +#define HAVE_ATEXIT +#define HAVE_STRFTIME +#define JAVA_STATIC_LINK +#undef NEED_CRYPT_H +#define NET_SOCKETS +#define SA_HANDLER_T(x) (void (*)(int))x +#define SEM_FLOCK +/* warning: mmap doesn't work under 9.04 */ +#define SHMEM_MMAP_FLAGS MAP_FILE | MAP_VARIABLE | MAP_SHARED + +#elif defined (IRIX) + +#define AUTH_DBM +#define BSD_RLIMIT +#undef BSD_SIGNALS +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#define HAVE_STRTOK_R +#define HAVE_TIME_R 2 /* arg count */ +#define JAVA_STATIC_LINK +#define NEED_CRYPT_H +#define NET_SOCKETS +#define SA_HANDLER_T(x) (void (*)(int))x +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED +#define THROW_HACK throw() + +#elif defined(Linux) + +#define HAS_IPV6 +#define AUTH_DBM +#define BSD_RLIMIT +#undef BSD_SIGNALS +#define DAEMON_NEEDS_SEMAPHORE +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#define HAVE_STRTOK_R +#define HAVE_TIME_R 2 /* arg count */ +#define NEED_CRYPT_H +#undef NEED_FILIO +#define NEED_GHN_PROTO +#define NET_SOCKETS +#define SA_HANDLER_T(x) (void (*)(int))x +#undef NEED_GHN_PROTO + +#elif defined(NCR) + +#define AUTH_DBM +#undef BSD_RLIMIT +/* #define DAEMON_NEEDS_SEMAPHORE */ +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#define HAVE_STRTOK_R +#define JAVA_STATIC_LINK +#define NEED_CRYPT_H +#define NEED_FILIO +#define NEED_GHN_PROTO +#define NET_SOCKETS +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED + +#elif defined(NEC) + +#define DNS_CACHE +#define AUTH_DBM +#undef BSD_RLIMIT +#define DAEMON_NEEDS_SEMAPHORE +#define DAEMON_UNIX_MOBRULE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DLL_CAPABLE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#define HAVE_STRTOK_R +#define HAVE_TIME_R 2 /* arg count */ +#define JAVA_STATIC_LINK +#define NEED_CRYPT_H +#define NEED_FILIO +#define NET_SOCKETS +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED + +#elif defined(OSF1) + +#define HAS_IPV6 +#define AUTH_DBM +#define BSD_RLIMIT +#undef BSD_SIGNALS +#define BSD_TIME +#define DAEMON_UNIX_MOBRULE +#define DAEMON_NEEDS_SEMAPHORE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAVE_ATEXIT +#define HAVE_STRFTIME /* no cftime */ +#define HAVE_TIME_R 2 /* ctime_r arg count */ +#define NET_SOCKETS +#define SA_HANDLER_T(x) (void (*)(int))x +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED + +#elif defined(SCO) + +#define AUTH_DBM +#undef BSD_RLIMIT +#undef BSD_SIGNALS +#define DAEMON_NEEDS_SEMAPHORE +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#undef NEED_CRYPT_H +#undef NEED_FILIO +#undef NEED_GHN_PROTO +#undef NEED_SETEID_PROTO /* setegid, seteuid */ +#define NET_SOCKETS +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED +#define SA_HANDLER_T(x) (void (*)(int))x + + +#elif defined(SNI) + +#define AUTH_DBM +#undef BSD_RLIMIT +#define DAEMON_NEEDS_SEMAPHORE +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#define JAVA_STATIC_LINK +#define NEED_CRYPT_H +#define NEED_FILIO +#define NET_SOCKETS +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED +#define USE_PIPE + +#elif defined(SOLARIS) + +#if defined(ENABLE_IPV6) +#define HAS_IPV6 +#endif +#define AUTH_DBM +#define BSD_RLIMIT +#undef BSD_SIGNALS +#define DAEMON_NEEDS_SEMAPHORE +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW|RTLD_FIRST +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#define HAVE_STRTOK_R +#define HAVE_TIME_R 3 /* arg count */ +#define NEED_CRYPT_H +#define NEED_FILIO +#define NEED_GHN_PROTO +#define NET_SOCKETS +#if OSVERSION > 504 +#define SA_HANDLER_T(x) x +#endif +#if OSVERSION >= 506 +#undef NEED_GHN_PROTO +#endif +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED + +#elif defined (SONY) + +#define AUTH_DBM +#undef BSD_RLIMIT +#define DAEMON_NEEDS_SEMAPHORE +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAVE_ATEXIT +#define NEED_CRYPT_H +#define NEED_FILIO +#define NET_SOCKETS +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED + +#elif defined(SUNOS4) + +#define AUTH_DBM +#define BSD_MAIL +#define BSD_RLIMIT +#define BSD_SIGNALS +#define BSD_TIME +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS 1 +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATFS +#undef HAVE_ATEXIT +#undef NEED_CRYPT_H +#define NEED_CRYPT_PROTO +#define NEED_FILIO +#define NET_SOCKETS +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED + +#elif defined(UNIXWARE) + +#define AUTH_DBM +#undef BSD_RLIMIT +#define DAEMON_UNIX_MOBRULE +#define DLL_CAPABLE +#define DLL_DLOPEN +#define DLL_DLOPEN_FLAGS RTLD_NOW +#define DNS_CACHE +#define FILE_INHERIT_FCNTL +#define FILE_MMAP_FLAGS MAP_SHARED +#define HAS_STATVFS +#define HAVE_ATEXIT +#define NEED_CRYPT_H +#define NEED_FILIO +#define NEED_GHN_PROTO +#define NEED_SETEID_PROTO /* setegid, seteuid */ +#define NET_SOCKETS +#define SEM_FLOCK +#define SHMEM_MMAP_FLAGS MAP_SHARED + +#ifndef boolean +#define boolean boolean +#endif + +#elif defined (XP_WIN32) /* Windows NT */ + +#include +#include + +#define AUTH_DBM +#define DAEMON_WIN32 +#define DLL_CAPABLE +#define DLL_WIN32 +#define DNS_CACHE +#define LOG_BUFFERING +#define HAVE_STRFTIME /* no cftime */ +#define NEED_CRYPT_PROTO +#define NEEDS_WRITEV +#define NET_SOCKETS +#define NO_DOMAINNAME +#ifdef BUILD_DLL +#if defined (NSAPI_PUBLIC) +#undef NSAPI_PUBLIC +#endif +#define NSAPI_PUBLIC __declspec(dllexport) +#else +#if defined (NSAPI_PUBLIC) +#undef NSAPI_PUBLIC +#endif +#define NSAPI_PUBLIC +#endif /* BUILD_DLL */ +#define SEM_WIN32 +#define THREAD_ANY +#define THREAD_NSPR_KERNEL +#define USE_NSPR +#define USE_STRFTIME /* no cftime */ +#define FILE_DEV_NULL "\\\\.\NUL" + +#endif /* Windows NT */ + +/* --- Begin defaults for values not defined above --- */ + +#ifndef DAEMON_LISTEN_SIZE +#define DAEMON_LISTEN_SIZE 128 +#endif /* !DAEMON_LISTEN_SIZE */ + +#ifndef NSAPI_PUBLIC +#define NSAPI_PUBLIC +#endif + +#ifndef SA_HANDLER_T +#define SA_HANDLER_T(x) (void (*)())x +#endif + +#ifndef THROW_HACK +#define THROW_HACK /* as nothing */ +#endif + +#ifndef FILE_DEV_NULL +#define FILE_DEV_NULL "/dev/null" +#endif + +/* --- End defaults for values not defined above --- */ + +/* --- Begin the great debate --- */ + +/* NS_MAIL builds sec-key.c which calls systhread_init, which requires */ +/* that USE_NSPR is defined when systhr.c is compiled. --lachman */ +/* MCC_PROXY does the same thing now --nbreslow -- LIKE HELL --ari */ +#if (defined(MCC_HTTPD) || defined(MCC_ADMSERV) || defined(MCC_PROXY) || defined(NS_MAIL)) && defined(XP_UNIX) +#define USE_NSPR +/* XXXrobm This is UNIX-only for the moment */ +#define LOG_BUFFERING +#ifdef SW_THREADS +#define THREAD_NSPR_USER +#else +#define THREAD_NSPR_KERNEL +#endif +#define THREAD_ANY +#endif + +/* --- End the great debate --- */ + +#ifndef APSTUDIO_READONLY_SYMBOLS + +#ifndef NSPR_PRIO_H +//include "prio.h" +#define NSPR_PRIO_H +#endif /* !NSPR_PRIO_H */ + +/* + * These types have to be defined early, because they are defined + * as (void *) in the public API. + */ + +#ifndef SYS_FILE_T +typedef PRFileDesc *SYS_FILE; +#define SYS_FILE_T PRFileDesc * +#endif /* !SYS_FILE_T */ + +#ifndef SYS_NETFD_T +typedef PRFileDesc *SYS_NETFD; +#define SYS_NETFD_T PRFileDesc * +#endif /* !SYS_NETFD_T */ + +#ifdef SEM_WIN32 + +typedef HANDLE SEMAPHORE; +#define SEMAPHORE_T HANDLE +#define SEM_ERROR NULL +/* That oughta hold them (I hope) */ +#define SEM_MAXVALUE 32767 + +#elif defined(SEM_FLOCK) + +//define SEMAPHORE_T int +//typedef int SEMAPHORE; +//define SEM_ERROR -1 + +#elif defined(SEM_POSIX) + +#define SEM_ERROR ((void *)(-1)) +typedef void* SEMAPHORE_T; + +#else /* ! SEM_WIN32 */ + +typedef int SEMAPHORE; +#define SEMAPHORE_T int +#define SEM_ERROR -1 + +#endif /* SEM_WIN32 */ + +#endif /* !APSTUDIO_READONLY_SYMBOLS */ + +#ifndef XP_CPLUSPLUS +#ifdef __cplusplus +#define XP_CPLUSPLUS +#endif /* __cplusplus */ +#endif /* !XP_CPLUSPLUS */ + +#endif /* BASE_SYSTEMS_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/systhr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/systhr.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,182 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * systhr.c: Abstracted threading mechanisms + * + * Rob McCool + */ + + +#include "systhr.h" +#include "ereport.h" + +#include "prinit.h" +#include "prthread.h" +#include "private/pprthred.h" + +#include "systems.h" + +#ifdef XP_UNIX +#include +#endif + +#ifdef THREAD_WIN32 +#include + +typedef struct { + HANDLE hand; + DWORD id; +} sys_thread_s; + +#endif + +#define DEFAULT_STACKSIZE (64*1024) + +static unsigned long _systhr_stacksize = DEFAULT_STACKSIZE; + +NSAPI_PUBLIC +void systhread_set_default_stacksize(unsigned long size) +{ + _systhr_stacksize = size; +} + +NSAPI_PUBLIC +SYS_THREAD systhread_start(int prio, int stksz, thrstartfunc fn, void *arg) +{ + PRThread *ret = PR_CreateThread(PR_USER_THREAD, (void (*)(void *))fn, + (void *)arg, (PRThreadPriority)prio, + PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + stksz ? stksz : _systhr_stacksize); + return (void *) ret; +} + + +NSAPI_PUBLIC SYS_THREAD systhread_current(void) +{ + return PR_GetCurrentThread(); +} + +NSAPI_PUBLIC void systhread_yield(void) +{ + PR_Sleep(PR_INTERVAL_NO_WAIT); +} + + +NSAPI_PUBLIC void systhread_timerset(int usec) +{ + /* This is an interesting problem. If you ever do turn on interrupts + * on the server, you're in for lots of fun with NSPR Threads + PR_StartEvents(usec); */ +} + + +NSAPI_PUBLIC +SYS_THREAD systhread_attach(void) +{ + PRThread *ret; + ret = PR_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL); + + return (void *) ret; +} + +NSAPI_PUBLIC +void systhread_detach(SYS_THREAD thr) +{ + /* XXXMB - this is not correct! */ + PR_DetachThread(); +} + +NSAPI_PUBLIC void systhread_terminate(SYS_THREAD thr) +{ + PR_Interrupt((PRThread *)thr); +} + +NSAPI_PUBLIC void systhread_sleep(int milliseconds) +{ +#ifdef XP_WIN32 + PR_Sleep(PR_MillisecondsToInterval(milliseconds)); +#else + /* poll() is more efficient than PR_Sleep() */ + if (milliseconds > 0) + poll(NULL, NULL, milliseconds); +#endif +} + +NSAPI_PUBLIC void systhread_init(char *name) +{ + if (!PR_Initialized()) { + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); + } + // XXX: ruslan - this bug can potentially exist on all plafroms due to + // possible priority inversion on NSPR spin locks. This code will + // need to be remove as we get new NSPR drop + // + /* VB: This is to fix bug# 364813 coupled with NSPR not wanting to patch + their problems. The fix is to prevent NSPR itself from + using atomic stacks. + */ + // ruslan: this problem exists on DEC also. We will roll it back when + // we have the right fix from NSPR group. It has smth. to do with + // atomic operations on DEC, it's an assembly code which is different + // for every platform. NSPR_FD_CACHE_SIZE_HIGH env var will cause the + // same effect as this fix. Debug version of NSPR always works as it doesn't + // have FD stack. + + int maxPRFdCache = 8192; + PR_SetFDCacheSize(0, maxPRFdCache); + // +} + + +NSAPI_PUBLIC int systhread_newkey() +{ + uintn newkey; + + PR_NewThreadPrivateIndex(&newkey, NULL); + return (newkey); +} + +NSAPI_PUBLIC void *systhread_getdata(int key) +{ + return PR_GetThreadPrivate(key); +} + +NSAPI_PUBLIC void systhread_setdata(int key, void *data) +{ + PR_SetThreadPrivate(key, data); +} + +NSAPI_PUBLIC void systhread_dummy(void) +{ +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/systhr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/systhr.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,114 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_SYSTHR_H +#define BASE_SYSTHR_H + +#ifndef NOINTNSAPI +#define INTNSAPI +#endif /* !NOINTNSAPI */ + +/* + * systhr.h: Abstracted threading mechanisms + * + * Rob McCool + */ + +#ifndef NETSITE_H +#include "netsite.h" +#include "nsapi.h" +#include "nspr.h" +#endif /* !NETSITE_H */ + +#define THREAD_ANY +#ifdef THREAD_ANY + +/* --- Begin function prototypes --- */ + +#define INTNSAPI +#ifdef INTNSAPI + +NSPR_BEGIN_EXTERN_C + +typedef void (*thrstartfunc)(void *); +NSAPI_PUBLIC +SYS_THREAD INTsysthread_start(int prio, int stksz, thrstartfunc fn, void *arg); + +NSAPI_PUBLIC SYS_THREAD INTsysthread_current(void); + +NSAPI_PUBLIC void INTsysthread_yield(void); + +NSAPI_PUBLIC SYS_THREAD INTsysthread_attach(void); + +NSAPI_PUBLIC void INTsysthread_detach(SYS_THREAD thr); + +NSAPI_PUBLIC void INTsysthread_terminate(SYS_THREAD thr); + +NSAPI_PUBLIC void INTsysthread_sleep(int milliseconds); + +NSAPI_PUBLIC void INTsysthread_init(char *name); + +NSAPI_PUBLIC void INTsysthread_timerset(int usec); + +NSAPI_PUBLIC int INTsysthread_newkey(void); + +NSAPI_PUBLIC void *INTsysthread_getdata(int key); + +NSAPI_PUBLIC void INTsysthread_setdata(int key, void *data); + +NSAPI_PUBLIC +void INTsysthread_set_default_stacksize(unsigned long size); + +NSPR_END_EXTERN_C + +/* --- End function prototypes --- */ + +#define systhread_start INTsysthread_start +#define systhread_current INTsysthread_current +#define systhread_yield INTsysthread_yield +#define systhread_attach INTsysthread_attach +#define systhread_detach INTsysthread_detach +#define systhread_terminate INTsysthread_terminate +#define systhread_sleep INTsysthread_sleep +#define systhread_init INTsysthread_init +#define systhread_timerset INTsysthread_timerset +#define systhread_newkey INTsysthread_newkey +#define systhread_getdata INTsysthread_getdata +#define systhread_setdata INTsysthread_setdata +#define systhread_set_default_stacksize INTsysthread_set_default_stacksize + +#endif /* INTNSAPI */ + +#endif /* THREAD_ANY */ + +#endif /* !BASE_SYSTHR_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/thrpool.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/thrpool.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,122 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "thrpool.h" + + + +threadpool_t* threadpool_new(int n) { + threadpool_t *pool = malloc(sizeof(threadpool_t)); + pool->queue = NULL; + pool->queue_len = 0; + + pthread_mutex_init(&pool->queue_lock, NULL); + pthread_mutex_init(&pool->avlbl_lock, NULL); + pthread_cond_init(&pool->available, NULL); + + /* create pool threads */ + for(int i=0;icallback(job->data); + + free(job); + } + return NULL; +} + +threadpool_job* threadpool_get_job(threadpool_t *pool) { + pthread_mutex_lock(&pool->queue_lock); + + threadpool_job *job = NULL; + while(job == NULL) { + if(pool->queue_len == 0) { + pthread_cond_wait(&pool->available, &pool->queue_lock); + continue; + } else { + pool_queue_t *q = pool->queue; + job = q->job; + pool->queue = q->next; + pool->queue_len--; + free(q); + } + } + + pthread_mutex_unlock(&pool->queue_lock); + + return job; +} + +void threadpool_run(threadpool_t *pool, job_callback_f func, void *data) { + threadpool_job *job = malloc(sizeof(threadpool_job)); + job->callback = func; + job->data = data; + + pool_queue_t *q = malloc(sizeof(pool_queue_t)); + q->job = job; + q->next = NULL; + + pthread_mutex_lock(&pool->queue_lock); + if(pool->queue == NULL) { + pool->queue = q; + } else { + pool_queue_t *last_elem = pool->queue; + while(last_elem->next != NULL) { + last_elem = last_elem->next; + } + last_elem->next = q; + } + pool->queue_len++; + + if(pool->queue_len == 1) { + pthread_cond_signal(&pool->available); + } + + pthread_mutex_unlock(&pool->queue_lock); + +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/thrpool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/thrpool.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,71 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THREADPOOL_H +#define THREADPOOL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _pool_queue pool_queue_t; +typedef struct _thread_pool { + pthread_mutex_t queue_lock; + pthread_mutex_t avlbl_lock; + pthread_cond_t available; + int queue_len; + pool_queue_t *queue; +} threadpool_t; + +typedef void*(*job_callback_f)(void *data); +typedef struct _threadpool_job { + job_callback_f callback; + void *data; +} threadpool_job; + +struct _pool_queue { + threadpool_job *job; + pool_queue_t *next; +}; + + +threadpool_t* threadpool_new(int n); + +void* threadpool_func(void *data); + +threadpool_job* threadpool_get_job(threadpool_t *pool); + +void threadpool_run(threadpool_t *pool, job_callback_f func, void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* THREADPOOL_H */ diff -r 4c89c7683fb6 -r 3c066d52342d src/server/uri.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/uri.cpp Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,561 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef XP_WIN32 +#define _MBCS +#include +#include +#endif + +#include "util.h" +#include "pool.h" +//include "frame/conf_api.h" +//include "support/stringvalue.h" + +#ifdef XP_WIN32 +static PRBool _getfullpathname = -1; +#endif /* XP_WIN32 */ + +/* --------------------------- util_uri_is_evil --------------------------- */ + +static inline int allow_dbcs_uri() +{ + /* + static int flagDbcsUri = -1; + if (flagDbcsUri == -1) { + flagDbcsUri = StringValue::getBoolean(conf_findGlobal("DbcsUri")); + } + return flagDbcsUri; + */ + return PR_FALSE; +} + +#ifdef XP_WIN32 +void set_fullpathname(PRBool b) +{ + _getfullpathname = b; +} +#endif /*XP_WIN32*/ + +NSAPI_PUBLIC int util_uri_is_evil_internal(const char *t, int allow_tilde, int allow_dot_dir) +{ +#ifdef XP_WIN32 + int flagDbcsUri = allow_dbcs_uri(); +#endif // XP_WIN32 + PRBool flagEmptySegment = PR_FALSE; + register int x; + + for (x = 0; t[x]; ++x) { + if (t[x] == '/') { + if (flagEmptySegment) + return 1; // "/;a/b" +#ifdef XP_WIN32 + if (t[x+1] == '/' && x != 0) +#else + if (t[x+1] == '/') +#endif + return 1; + if (t[x+1] == ';') + flagEmptySegment = PR_TRUE; // "/;a/b" is evil, "/a/;b" is not + if (t[x+1] == '.') { + /* "." at end of line is always prohibited */ + if (t[x+2] == '\0') + return 1; + + /* "." as a path segment is prohibited conditionally */ + if (!allow_dot_dir && (t[x+2] == '/' || t[x+2] == ';')) + return 1; + + /* ".." as a path segment is always prohibited */ + if (t[x+2] == '.' && (t[x+3] == '/' || t[x+3] == ';' || t[x+3] == '\0')) + return 1; + } + } +#ifdef XP_WIN32 + // Don't allow '~' in the filename. On some filesystems a long name + // (e.g. longfilename.htm) can be accessed using '~' bypassing any ACL + // checks (e.g. longfi~1.htm). + if (!allow_tilde && (t[x] == '~')) { + return 1; + } + + // Do not allow ':' apart from drive letter. Windows filestream + // will treat filename::$DATA as a plain file & display content. + // So block it to prevent source viewing vulnerability. + if ((t[x] == ':') && x > 1) { + return 1; + } + + // On NT, the directory "abc...." is the same as "abc" + // The only cheap way to catch this globally is to disallow + // names with the trailing "."s. Hopefully this is not over + // restrictive. + // Also trailing spaces in names can wreak havoc on ACL checks + // and name resolution. Therefore, ban them on the end of a + // name. + if (((t[x] == '.') || (t[x] == ' ')) && + ((t[x+1] == ';') || (t[x+1] == '/') || (t[x+1] == '\0'))) + { + return 1; + } + + // Skip past the second byte of two byte DBCS characters. Bug 353999 + if (flagDbcsUri && t[x+1] && IsDBCSLeadByte(t[x])) x++; +#endif // XP_WIN32 + } + return 0; +} + +NSAPI_PUBLIC int util_uri_is_evil(const char *t) +{ + return util_uri_is_evil_internal(t, 0, 0); +} + + +/* -------------------- util_uri_unescape_and_normalize -------------------- */ + +#ifdef XP_WIN32 +/* The server calls this function to unescape the URI and also normalize + * the uri. Normalizing the uri converts all "\" characters in the URI + * and pathinfo portion to "/". Does not touch "\" in query strings. + */ +NSAPI_PUBLIC +int util_uri_unescape_and_normalize(pool_handle_t *pool, char *s, char *unnormalized) +{ + if(!(util_uri_unescape_strict(s))) + return 0; + + if (unnormalized) strcpy(unnormalized, s); + + if (_getfullpathname == -1) + _getfullpathname = (_getmbcp() != 0); + + /* Get canonical filename Bugid: 4672869 */ + if(_getfullpathname && strcmp(s, "*") && (*s == '/' ) ) { + char *pzAbsPath = NULL; + int pathlen = 0; + int len = 0; + int ret = 0; + if(!(pzAbsPath = util_canonicalize_uri(pool, s, strlen(s), NULL))) { + //Error canonicalizing; possibly pointing out of docroot + return 0; + } + char *pzPath = (char *)MALLOC(MAX_PATH + 1); /* reserved byte for trailing slash */ + char *pzFilename = NULL; + + /* If required length of the buffer(pzPath) is more than the allocated one i.e. MAX_PATH(neglecting the reserved byte for trailing slash), return BAD REQUEST. This will happen if length of uri is more than the specified uri length(257) for MBCS windows */ + if(!(ret = GetFullPathName(pzAbsPath, MAX_PATH, pzPath, &pzFilename)) || ( ret > MAX_PATH)){ + FREE(pzAbsPath); + FREE(pzPath); + return 0; + } + len = strlen(pzAbsPath); + pathlen = strlen( pzPath ); + + /* GetFullPathName behaves differently in case of WINNT and WIN2K */ + /* o/p string doesn't contain the trailing slash in case of WINNT */ + /* if i/p is /foo/, we get o/p as c:\foo instead of c:\foo\ */ + /* Checking if i/p has trailing slash and o/p doesn't have, then */ + /* adding slash */ + if ( pzAbsPath[len-1] == '/' && pzPath[pathlen-1] != '\\') + strcat( pzPath, "\\"); + FREE(pzAbsPath); + pzFilename = strchr(pzPath, '\\'); + if(!pzFilename) { + FREE(pzPath); + return 0; + } + strcpy(s, pzFilename); + FREE(pzPath); + } + + util_uri_normalize_slashes(s); + + return 1; +} +#endif /* XP_WIN32 */ + + +/* ---------------------- util_uri_normalize_slashes ---------------------- */ + +void util_uri_normalize_slashes(char *s) +{ +#ifdef XP_WIN32 + int flagDbcsUri = allow_dbcs_uri(); + + while (*s) { + if (*s == '\\') { + // Normalize '\\' to '/' + *s = '/'; + } else if (flagDbcsUri && s[1] && IsDBCSLeadByte(s[0])) { + // Skip past two byte DBCS characters. Bug 353999 + s++; + } + s++; + } +#endif +} + + +/* --------------------------- util_uri_escape ---------------------------- */ +/* +NSAPI_PUBLIC char *util_uri_escape(char *od, const char *s) +{ + int flagDbcsUri = allow_dbcs_uri(); + char *d; + + if (!od) + od = (char *) MALLOC((strlen(s)*3) + 1); + d = od; + + while (*s) { + if (strchr("% ?#:+&*\"'<>\r\n", *s)) { + util_sprintf(d, "%%%02x", (unsigned char)*s); + ++s; d += 3; + } +#ifdef XP_WIN32 + else if (flagDbcsUri && s[1] && IsDBCSLeadByte(s[0])) +#else + // Treat any character with the high bit set as a DBCS lead byte + else if (flagDbcsUri && s[1] && (s[0] & 0x80)) +#endif + { + // Escape the second byte of DBCS characters. The first byte will + // have been escaped already. IE translates all unescaped '\\'s + // into '/'. + // Bug 353999 + util_sprintf(d, "%%%02x%%%02x", (unsigned char)s[0], (unsigned char)s[1]); + s += 2; d += 6; + } + else if (0x80 & *s) { + util_sprintf(d, "%%%02x", (unsigned char)*s); + ++s; d += 3; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return od; +} +*/ + + +/* --------------------------- util_url_escape ---------------------------- */ +/* +NSAPI_PUBLIC char *util_url_escape(char *od, const char *s) +{ + int flagDbcsUri = allow_dbcs_uri(); + char *d; + + if (!od) + od = (char *) MALLOC((strlen(s)*3) + 1); + d = od; + + while (*s) { + if (strchr("% +*\"'<>\r\n", *s)) { + util_sprintf(d, "%%%02x", (unsigned char)*s); + ++s; d += 3; + } +#ifdef XP_WIN32 + else if (flagDbcsUri && s[1] && IsDBCSLeadByte(s[0])) +#else + // Treat any character with the high bit set as a DBCS lead byte + else if (flagDbcsUri && s[1] && (s[0] & 0x80)) +#endif + { + // Escape the second byte of DBCS characters. The first byte will + // have been escaped already. IE translates all unescaped '\\'s + // into '/'. + // Bug 353999 + util_sprintf(d, "%%%02x%%%02x", (unsigned char)s[0], (unsigned char)s[1]); + s += 2; d += 6; + } + else if (0x80 & *s) { + util_sprintf(d, "%%%02x", (unsigned char)*s); + ++s; d += 3; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return od; +} +*/ + +/* ------------------------- util_uri_strip_params ------------------------- */ + +NSAPI_PUBLIC char* util_uri_strip_params(char *uri) +{ + // As per RFC2396, URI path segments can contain parameters beginning with + // ';'. These parameters must be removed from the ppath. Bug 418271 + char* out; + if (out = strchr(uri, ';')) { + char* in = out; + while (*in) { + if (*in == ';') { + // Skip past parameter + do in++; while (*in && *in != '/'); + } else { + // Copy non-parameter path data + *out++ = *in++; + } + } + *out = 0; + } + return uri; +} + + +/* ------------------------ util_canonicalize_uri ------------------------- */ + +/* + * rewrite rules: + * // -> '/' + * /./ -> '/' + * /.\0 -> '/' + * /foo/../ -> '/' + * /foo/..\0 -> '/' + * + * Allocate a new string, as otherwise replacing in-line would impact the + * RequestURI, i.e. original URI in the request. + * Some guidelines in: http://www.ietf.org/rfc/rfc2396.txt + * Uniform Resource Identifiers (URI): Generic Syntax + */ +NSAPI_PUBLIC char* util_canonicalize_uri(pool_handle_t *pool, const char *uri, int len, int *pcanonlen) +{ + PRBool success = PR_TRUE; + const char *in_ptr = uri; + int in = 0; + int in_len = len; + + PR_ASSERT(uri != NULL); + + char* canonPath = (char *)pool_malloc(pool, in_len+1); + char* out_ptr = canonPath; + + if (!canonPath) { + success = PR_FALSE; + goto done; + } + + + /* in goes from 0 .. sURIPath.len-1; out_ptr points to + * space where next char from input would be copied to + */ + while (in < in_len) { + + /* If the character isn't '/' then copy it out and move on*/ + if (in_ptr[0] != '/') { + *out_ptr++ = *in_ptr++; + in++; + continue; + } + + /* found '/' and reached end of sURIPath, done */ + if (in+1 >= in_len) { + *out_ptr++ = *in_ptr++; + in++; + break; + } + + /* we have '/' and there are more chars in the string */ + switch(in_ptr[1]) { + case '/': + /* '//' => '/' */ + in_ptr++; + in++; + break; + + case '.': + /* we have "/." so far */ + if (in+2 >= in_len) { + /* the string ends after this; basically ignore '.' + * make sure the ending / is transferred to output. + */ + *out_ptr++ = *in_ptr++; + goto done; + } + + /* more chars after "/."; see if it is a '/' */ + if (in_ptr[2] == '/') { + /* in deed, compact "/./" => "/"; */ + in_ptr += 2; + in += 2; + break; + } + + if (in_ptr[2] != '.') { + /* "/.x" where x is not '.'; copy as is */ + *out_ptr++ = *in_ptr++; + in++; + break; + } + + /* we have "/.." so far. see if we have either string + * ending after this or '/' following. + */ + if (in+3 < in_len && in_ptr[3] != '/' && in_ptr[3] != ';') { + /* we have "/..x" here; so copy as is */ + *out_ptr++ = *in_ptr++; + in++; + } + else { + /* we have "foo/../" or "foo/.." at the end; */ + if (out_ptr == canonPath) { + /* oops, we found "/../" pointing out of docroot */ + success = PR_FALSE; + goto done; + } + + /* remove the previous segment in the output */ + for (out_ptr--; + out_ptr != canonPath && out_ptr[0] != '/'; + out_ptr--); /* Empty Loop */ + + /* point to '/' if the last segment ended with .. then + * leave the '/' before the previous segment. + */ + if(in+3 == in_len) + out_ptr++; + + /* skip the input as well */ + in_ptr += 3; + in += 3; + } + break; + + default: + /* If we already have '/' at out_ptr we donot need to copy */ + if (out_ptr == canonPath || *(out_ptr-1) != '/') + *out_ptr++ = *in_ptr; + in_ptr++; in++; + break; + } + } + +done: + int canonLen = 0; + + if (success) { + /* the path looks fine; return the canonicalized form */ + canonLen = out_ptr - canonPath; + canonPath[canonLen] = '\0'; + } else { + /* error canonicalizing */ + pool_free(pool, canonPath); + canonPath = NULL; + } + + if (pcanonlen) + *pcanonlen = canonLen; + + return canonPath; +} + + +/* ---------------------- util_canonicalize_redirect ---------------------- */ + +NSAPI_PUBLIC char* util_canonicalize_redirect(pool_handle_t *pool, const char *baseUri, const char *newUri) +{ + PR_ASSERT(baseUri != NULL); + + if (*newUri == '/') + return util_canonicalize_uri(pool, newUri, strlen(newUri), NULL); + + int bLen = strlen(baseUri); + if (bLen > 0 && baseUri[bLen - 1] != '/') { + while (bLen > 0 && baseUri[bLen - 1] != '/') + bLen--; + } + + int pLen = strlen(newUri) + bLen + 1; // 1 for slash + char *pUri = (char *)pool_malloc(pool, pLen + 1); + if (!pUri) + return PR_FALSE; + + memcpy(pUri, baseUri, bLen); + pUri[bLen] = '/'; + strcpy(pUri + bLen + 1, newUri); + + char *rval = util_canonicalize_uri(pool, pUri, pLen, NULL); + pool_free(pool, pUri); + + return rval; +} + + +/* ------------------------ util_host_port_suffix ------------------------- */ + +NSAPI_PUBLIC char *util_host_port_suffix(char *h) +{ + return (char *)util_host_port_suffix((const char *)h); +} + +const char *util_host_port_suffix(const char *h) +{ + /* Return a pointer to the colon preceding the port number in a hostname. + * + * util_host_port_suffix("foo.com:80") = ":80" + * util_host_port_suffix("foo.com") = NULL + * util_host_port_suffix("[::]:80") = ":80" + * util_host_port_suffix("[::]") = NULL + */ + + if (h == NULL) + return h; + + for (;;) { + /* Find end of host, beginning of ":port", or an IPv6 address */ + for (;;) { + register char c = *h; + + if (c == '\0') + return NULL; /* end of host, no port found */ + + if (c == '/') + return NULL; /* end of host, no port found */ + + if (c == ':') + return h; /* found port */ + + if (c == '[') + break; /* skip IPv6 address */ + + h++; + } + + /* Skip IPv6 address */ + while (*h != '\0' && *h != ']') + h++; + } +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/util.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,133 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * util.c: A hodge podge of utility functions and standard functions which + * are unavailable on certain systems + * + * Rob McCool + */ + +#ifdef XP_UNIX +#include +#include +#include +#include +#include +#include "prthread.h" +#endif /* XP_UNIX */ + + +#include "nspr.h" +#include "nsapi.h" + +#include "util.h" + +/* +NSAPI_PUBLIC int util_getboolean(const char *v, int def) { + if(v[0] == 'T' || v[0] == 't') { + return 1; + } + if(v[0] == 'F' || v[0] == 'f') { + return 0; + } + return def; +} +*/ + +NSAPI_PUBLIC int INTutil_getboolean(const char *v, int def) { + if(v[0] == 'T' || v[0] == 't') { + return 1; + } + if(v[0] == 'F' || v[0] == 'f') { + return 0; + } + return def; +} + + +/* ------------------------------ util_itoa ------------------------------- */ +/* +NSAPI_PUBLIC int util_itoa(int i, char *a) +{ + int len = util_i64toa(i, a); + + PR_ASSERT(len < UTIL_ITOA_SIZE); + + return len; +} +*/ +NSAPI_PUBLIC int INTutil_itoa(int i, char *a) { + return INTutil_i64toa(i, a); +} + + +/* ----------------------------- util_i64toa ------------------------------ */ + +/* + * Assumption: Reversing the digits will be faster in the general case + * than doing a log10 or some nasty trick to find the # of digits. + */ + +NSAPI_PUBLIC int INTutil_i64toa(PRInt64 i, char *a) +{ + register int x, y, p; + register char c; + int negative; + + negative = 0; + if(i < 0) { + *a++ = '-'; + negative = 1; + i = -i; + } + p = 0; + while(i > 9) { + a[p++] = (i%10) + '0'; + i /= 10; + } + a[p++] = i + '0'; + + if(p > 1) { + for(x = 0, y = p - 1; x < y; ++x, --y) { + c = a[x]; + a[x] = a[y]; + a[y] = c; + } + } + a[p] = '\0'; + + //PR_ASSERT(p + negative < UTIL_I64TOA_SIZE); + + return p + negative; +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/util.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,356 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_UTIL_H +#define BASE_UTIL_H + +#include "netsite.h" + +#ifndef NOINTNSAPI +#define INTNSAPI +#endif /* !NOINTNSAPI */ + +/* + * util.h: A hodge podge of utility functions and standard functions which + * are unavailable on certain systems + * + * Rob McCool + */ + +/* Needed for various reentrant functions */ +#define DEF_CTIMEBUF 26 +#define DEF_ERRBUF 256 +#define DEF_PWBUF 1024 + +#ifndef BASE_BUFFER_H +//include "buffer.h" /* filebuf for getline */ +#endif /* !BASE_BUFFER_H */ + +/* + * UTIL_ITOA_SIZE is the minimum size for buffers passed to util_itoa(). + */ +#define UTIL_ITOA_SIZE 12 + +/* + * UTIL_I64TOA_SIZE is the minimum size for buffers passed to util_i64toa(). + */ +#define UTIL_I64TOA_SIZE 21 + +/* --- Begin common function prototypes --- */ + +#ifdef INTNSAPI + +NSPR_BEGIN_EXTERN_C + +NSAPI_PUBLIC +int INTutil_init_PRNetAddr(PRNetAddr * naddr, char * ipstr, int iplen, int type); + +NSAPI_PUBLIC +int INTutil_getline(filebuffer *buf, int lineno, int maxlen, char *l); + +NSAPI_PUBLIC char **INTutil_env_create(char **env, int n, int *pos); + +NSAPI_PUBLIC char *INTutil_env_str(const char *name, const char *value); + +NSAPI_PUBLIC void INTutil_env_replace(char **env, const char *name, const char *value); + +NSAPI_PUBLIC void INTutil_env_free(char **env); + +NSAPI_PUBLIC char **INTutil_env_copy(char **src, char **dst); + +NSAPI_PUBLIC char *INTutil_env_find(char **env, const char *name); + +NSAPI_PUBLIC char **util_argv_parse(const char *cmdline); + +NSAPI_PUBLIC char *INTutil_hostname(void); + +NSAPI_PUBLIC int INTutil_chdir2path(char *path); + +NSAPI_PUBLIC int INTutil_chdir(const char *path); + +NSAPI_PUBLIC char *INTutil_getcwd(void); + +NSAPI_PUBLIC int INTutil_is_mozilla(char *ua, char *major, char *minor); + +NSAPI_PUBLIC int INTutil_is_url(const char *url); + +NSAPI_PUBLIC int INTutil_mstr2num(const char *s); + +NSAPI_PUBLIC int INTutil_later_than(const struct tm *lms, const char *ims); + +NSAPI_PUBLIC int INTutil_time_equal(const struct tm *lms, const char *ims); + +NSAPI_PUBLIC int INTutil_str_time_equal(const char *t1, const char *t2); + +NSAPI_PUBLIC int INTutil_uri_is_evil(const char *t); + +NSAPI_PUBLIC int INTutil_uri_is_evil_internal(const char *t, int, int); + +NSAPI_PUBLIC void INTutil_uri_parse(char *uri); + +#ifdef XP_WIN32 +NSAPI_PUBLIC int INTutil_uri_unescape_and_normalize(pool_handle_t *pool, char *s, char *unnormalized); +#endif /* XP_WIN32 */ + +NSAPI_PUBLIC void INTutil_uri_normalize_slashes(char *s); + +NSAPI_PUBLIC void INTutil_uri_unescape (char *s); + +NSAPI_PUBLIC int INTutil_uri_unescape_strict (char *s); + +NSAPI_PUBLIC int INTutil_uri_unescape_plus (const char *src, char *trg, int len); + +NSAPI_PUBLIC char *INTutil_uri_escape(char *d, const char *s); + +NSAPI_PUBLIC char *INTutil_uri_strip_params(char *uri); + +NSAPI_PUBLIC char* util_canonicalize_uri(pool_handle_t *pool, const char *uri, int len, int *pcanonlen); + +NSAPI_PUBLIC char* util_canonicalize_redirect(pool_handle_t *pool, const char *baseUri, const char *newUri); + +NSAPI_PUBLIC char *INTutil_url_escape(char *d, const char *s); + +NSAPI_PUBLIC char *INTutil_sh_escape(char *s); + +NSAPI_PUBLIC int INTutil_mime_separator(char *sep); + +NSAPI_PUBLIC int INTutil_itoa(int i, char *a); + +NSAPI_PUBLIC int INTutil_i64toa(PRInt64 i, char *a); + + +NSAPI_PUBLIC +int INTutil_vsprintf(char *s, register const char *fmt, va_list args); + +NSAPI_PUBLIC int INTutil_sprintf(char *s, const char *fmt, ...); + +NSAPI_PUBLIC int INTutil_vsnprintf(char *s, int n, register const char *fmt, + va_list args); + +NSAPI_PUBLIC int INTutil_snprintf(char *s, int n, const char *fmt, ...); + +NSAPI_PUBLIC int util_strlftime(char *dst, size_t dstsize, const char *format, const struct tm *t); + +NSAPI_PUBLIC int INTutil_strftime(char *s, const char *format, const struct tm *t); + +NSAPI_PUBLIC char *INTutil_strtok(char *s1, const char *s2, char **lasts); + +NSAPI_PUBLIC struct tm *INTutil_localtime(const time_t *clock, struct tm *res); + +NSAPI_PUBLIC char *INTutil_ctime(const time_t *clock, char *buf, int buflen); + +NSAPI_PUBLIC char *INTutil_strerror(int errnum, char *msg, int buflen); + +NSAPI_PUBLIC struct tm *INTutil_gmtime(const time_t *clock, struct tm *res); + +NSAPI_PUBLIC char *INTutil_asctime(const struct tm *tm,char *buf, int buflen); + +NSAPI_PUBLIC char *INTutil_cookie_find(char *cookie, const char *name); + +NSAPI_PUBLIC char *INTutil_cookie_next(char *cookie, char **name, char **value); + +NSAPI_PUBLIC char *INTutil_cookie_next_av_pair(char *cookie, char **name, char **value); + +NSAPI_PUBLIC void INTutil_random(void *buf, size_t sz); + +NSAPI_PUBLIC PRBool INTutil_format_http_version(const char *v, int *protv_num, char *buffer, int size); + +NSAPI_PUBLIC int INTutil_getboolean(const char *v, int def); +NSAPI_PUBLIC PRIntervalTime INTutil_getinterval(const char *v, PRIntervalTime def); + +#ifdef NEED_STRCASECMP +NSAPI_PUBLIC int INTutil_strcasecmp(const char *one, const char *two); +#endif /* NEED_STRCASECMP */ + +#ifdef NEED_STRNCASECMP +NSAPI_PUBLIC int INTutil_strncasecmp(const char *one, const char *two, int n); +#endif /* NEED_STRNCASECMP */ + +NSAPI_PUBLIC char *INTutil_strcasestr(char *str, const char *substr); + +NSAPI_PUBLIC size_t util_strlcpy(char *dst, const char *src, size_t dstsize); + +NSAPI_PUBLIC size_t util_strlcat(char *dst, const char *src, size_t dstsize); + +NSAPI_PUBLIC char *INTutil_uuencode(const char *src, int len); + +NSAPI_PUBLIC char *INTutil_uudecode(const char *src); + +NSAPI_PUBLIC char *util_strlower(char *s); + +NSAPI_PUBLIC char *util_decrement_string(char *s); + +NSAPI_PUBLIC PRInt64 util_atoi64(const char *a); + +NSAPI_PUBLIC char *util_html_escape(const char *s); + +NSAPI_PUBLIC int util_qtoi(const char *q, const char **p); + +/* --- End common function prototypes --- */ + +/* --- Begin Unix-only function prototypes --- */ + +#ifdef XP_UNIX + +NSAPI_PUBLIC int INTutil_can_exec(struct stat *finfo, uid_t uid, gid_t gid); + +NSAPI_PUBLIC +struct passwd *INTutil_getpwnam(const char *name, struct passwd *result, + char *buffer, int buflen); + +NSAPI_PUBLIC +struct passwd *INTutil_getpwuid(uid_t uid, struct passwd *result, + char *buffer, int buflen); + +NSAPI_PUBLIC pid_t INTutil_waitpid(pid_t pid, int *statptr, int options); + +#endif /* XP_UNIX */ + +/* --- End Unix-only function prototypes --- */ + +/* --- Begin Windows-only function prototypes --- */ + +#ifdef XP_WIN32 + +NSAPI_PUBLIC +VOID INTutil_delete_directory(char *FileName, BOOL delete_directory); + +#endif /* XP_WIN32 */ + +/* --- End Windows-only function prototypes --- */ + +NSPR_END_EXTERN_C + +#ifdef __cplusplus + +NSAPI_PUBLIC char *util_host_port_suffix(char *h); + +NSAPI_PUBLIC const char *util_host_port_suffix(const char *h); + +#endif + +#define util_init_PRNetAddr INTutil_init_PRNetAddr +#define util_getline INTutil_getline +#define util_env_create INTutil_env_create +#define util_env_str INTutil_env_str +#define util_env_replace INTutil_env_replace +#define util_env_free INTutil_env_free +#define util_env_copy INTutil_env_copy +#define util_env_find INTutil_env_find +#define util_hostname INTutil_hostname +#define util_chdir2path INTutil_chdir2path +#define util_chdir INTutil_chdir +#define util_getcwd INTutil_getcwd +#define util_is_mozilla INTutil_is_mozilla +#define util_is_url INTutil_is_url +#define util_mstr2num INTutil_mstr2num +#define util_later_than INTutil_later_than +#define util_time_equal INTutil_time_equal +#define util_str_time_equal INTutil_str_time_equal +#define util_uri_is_evil INTutil_uri_is_evil +#define util_uri_is_evil_internal INTutil_uri_is_evil_internal +#define util_uri_parse INTutil_uri_parse +#ifdef XP_WIN32 +#define util_uri_unescape_and_normalize INTutil_uri_unescape_and_normalize +#endif /* XP_WIN32 */ +#define util_uri_normalize_slashes INTutil_uri_normalize_slashes +#define util_uri_unescape INTutil_uri_unescape +#define util_uri_unescape_strict INTutil_uri_unescape_strict +#define util_uri_unescape_plus INTutil_uri_unescape_plus + +#define util_uri_escape INTutil_uri_escape +#define util_uri_strip_params INTutil_uri_strip_params +#define util_url_escape INTutil_url_escape +#define util_sh_escape INTutil_sh_escape +#define util_mime_separator INTutil_mime_separator +#define util_itoa INTutil_itoa +#define util_i64toa INTutil_i64toa +#define util_vsprintf INTutil_vsprintf +#define util_sprintf INTutil_sprintf +#define util_vsnprintf INTutil_vsnprintf +#define util_snprintf INTutil_snprintf +#define util_strftime INTutil_strftime +#define util_strcasecmp INTutil_strcasecmp +#define util_strncasecmp INTutil_strncasecmp +#define util_strcasestr INTutil_strcasestr +#define util_strtok INTutil_strtok +#define util_localtime INTutil_localtime +#define util_ctime INTutil_ctime +#define util_strerror INTutil_strerror +#define util_gmtime INTutil_gmtime +#define util_asctime INTutil_asctime +#define util_uuencode INTutil_uuencode +#define util_uudecode INTutil_uudecode + +#ifdef XP_UNIX +#define util_can_exec INTutil_can_exec +#define util_getpwnam INTutil_getpwnam +#define util_getpwuid INTutil_getpwuid +#define util_waitpid INTutil_waitpid +#endif /* XP_UNIX */ + +#ifdef XP_WIN32 +#define util_delete_directory INTutil_delete_directory +#endif /* XP_WIN32 */ + +#ifdef NEED_STRCASECMP +#define util_strcasecmp INTutil_strcasecmp +#define strcasecmp INTutil_strcasecmp +#endif /* NEED_STRCASECMP */ + +#ifdef NEED_STRINGS_H /* usually for strcasecmp */ +#include +#endif + +#ifdef NEED_STRNCASECMP +#define util_strncasecmp INTutil_strncasecmp +#define strncasecmp INTutil_strncasecmp +#endif /* NEED_STRNCASECMP */ + +#define util_cookie_find INTutil_cookie_find +#define util_cookie_next INTutil_cookie_next +#define util_cookie_next_av_pair INTutil_cookie_next_av_pair + +#define util_random INTutil_random +#define util_format_http_version INTutil_format_http_version +#define util_getboolean INTutil_getboolean +#define util_getinterval INTutil_getinterval + +#ifdef XP_WIN32 +void set_fullpathname(PRBool b); +#endif /* XP_WIN32 */ +#endif /* INTNSAPI */ + +#endif /* !BASE_UTIL_H */ + + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/webserver.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/webserver.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,76 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "nsapi.h" +#include "systhr.h" + +#include "func.h" +#include "conf.h" +#include "httplistener.h" +#include "webserver.h" + + +extern struct FuncStruct webserver_funcs[]; + + +int webserver_init() { + // init NSPR + systhread_init("webserver"); + + // init NSAPI functions + func_init(); + add_functions(webserver_funcs); + + // load init.conf + load_init_conf(NULL); + + // load server.conf + load_server_conf(NULL); + + // load obj.conf + + // init NSAPI functions + + + + return 0; +} + +int webserver_run() { + printf("webserver_run\n"); + + // start all http listener + if(start_all_listener() != 0) { + fprintf(stderr, "Error: Cannot start http listener\n"); + } + + return 0; +} diff -r 4c89c7683fb6 -r 3c066d52342d src/server/webserver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/webserver.h Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,48 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WEBSERVER_H +#define WEBSERVER_H + +#include "nsapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int webserver_init(); +int webserver_run(); + + + +#ifdef __cplusplus +} +#endif + +#endif /* WEBSERVER_H */ + diff -r 4c89c7683fb6 -r 3c066d52342d src/server/ws-fn.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/ws-fn.c Tue Sep 06 22:27:32 2011 +0200 @@ -0,0 +1,33 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "nsapi.h" + +struct FuncStruct webserver_funcs[] = { + {NULL, NULL, NULL, 0} +};