diff options
| author | Sascha Schumann <sas@php.net> | 1999-08-27 21:03:22 +0000 |
|---|---|---|
| committer | Sascha Schumann <sas@php.net> | 1999-08-27 21:03:22 +0000 |
| commit | 49824ee8cbcfcc9bc66e4a21db90cb9e63009650 (patch) | |
| tree | e689be2de0dad0f57b61c0f1dfb711e9e539a4fe | |
| parent | aa8b27ba1d6867e367416a02a6c47489dc3bbc76 (diff) | |
| download | php-git-49824ee8cbcfcc9bc66e4a21db90cb9e63009650.tar.gz | |
- fix potential buffer problem in send_cookie
- fix gc probability algorithm
- don't access mod_data directly
- initial version of mm support for session data storage
This works pretty good, but we need to create the initial mm pool
from the parent process/thread. Still looking for a clean way to do that.
| -rw-r--r-- | ext/session/Makefile.am | 2 | ||||
| -rw-r--r-- | ext/session/config.h.stub | 3 | ||||
| -rw-r--r-- | ext/session/config.m4 | 25 | ||||
| -rw-r--r-- | ext/session/mod_files.c | 4 | ||||
| -rw-r--r-- | ext/session/mod_mm.c | 277 | ||||
| -rw-r--r-- | ext/session/mod_mm.h | 46 | ||||
| -rw-r--r-- | ext/session/modules.c | 3 | ||||
| -rw-r--r-- | ext/session/php_session.h | 2 | ||||
| -rw-r--r-- | ext/session/session.c | 19 |
9 files changed, 369 insertions, 12 deletions
diff --git a/ext/session/Makefile.am b/ext/session/Makefile.am index bb35d2e5b9..b1a8250d50 100644 --- a/ext/session/Makefile.am +++ b/ext/session/Makefile.am @@ -2,5 +2,5 @@ INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend noinst_LIBRARIES=libphpext_session.a -libphpext_session_a_SOURCES=session.c mod_files.c +libphpext_session_a_SOURCES=session.c mod_files.c mod_mm.c diff --git a/ext/session/config.h.stub b/ext/session/config.h.stub index bce855c110..4dc5ec115c 100644 --- a/ext/session/config.h.stub +++ b/ext/session/config.h.stub @@ -1,2 +1,3 @@ /* define if you want to use the session extension */ -/* #undef HAVE_LIBSESSION */ + +#undef HAVE_LIBMM diff --git a/ext/session/config.m4 b/ext/session/config.m4 index 30b8226bd3..a85c321f24 100644 --- a/ext/session/config.m4 +++ b/ext/session/config.m4 @@ -2,4 +2,29 @@ dnl $Id$ dnl config.m4 for extension session dnl don't forget to call PHP_EXTENSION(session) + +MM_RESULT=no +AC_MSG_CHECKING(for mm support) +AC_ARG_WITH(mm, +[ --with-mm[=DIR] Include mm support], +[ + if test "$withval" != "no"; then + for i in /usr/local /usr $withval; do + if test -f "$i/include/mm.h"; then + MM_DIR="$i" + fi + done + + if test -z "$MM_DIR" ; then + AC_MSG_ERROR(cannot find mm library) + fi + + AC_ADD_LIBRARY_WITH_PATH(mm, $MM_DIR/lib) + AC_ADD_INCLUDE($MM_DIR/include) + AC_DEFINE(HAVE_LIBMM, 1) + MM_RESULT=yes + fi +]) +AC_MSG_RESULT($MM_RESULT) + PHP_EXTENSION(session) diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 77e6ccd5ec..32bd760f88 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -43,7 +43,7 @@ ps_module ps_mod_files = { PS_MOD(files) }; -#define PS_FILES_DATA ps_files *data = *mod_data +#define PS_FILES_DATA ps_files *data = PS_GET_MOD_DATA() PS_OPEN_FUNC(files) { @@ -51,7 +51,7 @@ PS_OPEN_FUNC(files) char *p; data = ecalloc(sizeof(*data), 1); - *mod_data = data; + PS_SET_MOD_DATA(data); data->fd = -1; if((p = strchr(save_path, ':'))) { diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c new file mode 100644 index 0000000000..5361dc38ff --- /dev/null +++ b/ext/session/mod_mm.c @@ -0,0 +1,277 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Sascha Schumann <ss@2ns.de> | + +----------------------------------------------------------------------+ + */ + + +#include "php.h" + +#ifdef HAVE_LIBMM + +#include <mm.h> +#include <time.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> + +#include "php_session.h" +#include "mod_mm.h" + +typedef struct ps_sd { + time_t ctime; + char *key; + void *data; + size_t datalen; + struct ps_sd *next, *prev; +} ps_sd; + +typedef struct { + MM *mm; + ps_sd **hash; +} ps_mm; + +static ps_mm *ps_mm_instance = NULL; + +/* should be a prime */ +#define HASH_SIZE 11 + +#if 0 +#define ps_mm_debug(a...) fprintf(stderr, a) +#else +#define ps_mm_debug(a...) +#endif + +#define BITS_IN_int (sizeof(int) * CHAR_BIT) +#define THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4)) +#define ONE_EIGTH ((int) (BITS_IN_int / 8)) +#define HIGH_BITS (~((unsigned int)(~0) >> ONE_EIGTH)) + +static unsigned int ps_sd_hash(const char *data) +{ + unsigned int val, i; + + for(val = 0; *data; data++) { + val = (val << ONE_EIGTH) + *data; + if((i = val & HIGH_BITS) != 0) { + val = (val ^ (i >> THREE_QUARTERS)) & -HIGH_BITS; + } + } + + return val; +} + + +static ps_sd *ps_sd_new(ps_mm *data, const char *key, const void *sdata, size_t sdatalen) +{ + unsigned int h; + ps_sd *sd; + + h = ps_sd_hash(key) % HASH_SIZE; + + sd = mm_malloc(data->mm, sizeof(*sd)); + sd->ctime = 0; + + sd->data = mm_malloc(data->mm, sdatalen); + memcpy(sd->data, sdata, sdatalen); + sd->datalen = sdatalen; + + sd->key = mm_strdup(data->mm, key); + + if((sd->next = data->hash[h])) + sd->next->prev = sd; + sd->prev = NULL; + + ps_mm_debug("inserting %s(%x) into %d\n", key, sd, h); + + data->hash[h] = sd; + + return sd; +} + +static void ps_sd_destroy(ps_mm *data, ps_sd *sd) +{ + unsigned int h; + + h = ps_sd_hash(sd->key) % HASH_SIZE; + + if(sd->next) + sd->next->prev = sd->prev; + if(sd->prev) + sd->prev->next = sd->next; + + if(data->hash[h] == sd) + data->hash[h] = sd->next; + + mm_free(data->mm, sd->key); + mm_free(data->mm, sd->data); + mm_free(data->mm, sd); +} + +static ps_sd *ps_sd_lookup(ps_mm *data, const char *key, int rw) +{ + unsigned int h; + ps_sd *ret; + + h = ps_sd_hash(key) % HASH_SIZE; + + for(ret = data->hash[h]; ret; ret = ret->next) + if(!strcmp(ret->key, key)) break; + + if(ret && rw && ret != data->hash[h]) { + data->hash[h]->prev = ret; + ret->next = data->hash[h]; + data->hash[h] = ret; + ps_mm_debug("optimizing\n"); + } + + ps_mm_debug(stderr, "lookup(%s): ret=%x,h=%d\n", key, ret, h); + + return ret; +} + +ps_module ps_mod_mm = { + PS_MOD(mm) +}; + +#define PS_MM_DATA ps_mm *data = PS_GET_MOD_DATA() + +static int ps_mm_initialize(ps_mm *data, const char *path) +{ + data->mm = mm_create(0, path); + + data->hash = mm_calloc(data->mm, HASH_SIZE, sizeof(*data->hash)); + + return SUCCESS; +} + +static void ps_mm_destroy(ps_mm *data) +{ + mm_free(data->mm, data->hash); + mm_destroy(data->mm); +} + +PS_OPEN_FUNC(mm) +{ + if(!ps_mm_instance) { + ps_mm_instance = calloc(sizeof(*data), 1); + ps_mm_initialize(ps_mm_instance, save_path); + } + + PS_SET_MOD_DATA(ps_mm_instance); + + return SUCCESS; +} + +PS_CLOSE_FUNC(mm) +{ + PS_SET_MOD_DATA(NULL); + + return SUCCESS; +} + +PS_READ_FUNC(mm) +{ + PS_MM_DATA; + ps_sd *sd; + int ret = FAILURE; + + mm_lock(data->mm, MM_LOCK_RD); + + sd = ps_sd_lookup(data, key, 0); + if(sd) { + *vallen = sd->datalen; + *val = emalloc(sd->datalen); + memcpy(*val, sd->data, sd->datalen); + ret = SUCCESS; + } + + mm_unlock(data->mm); + + return ret; +} + +PS_WRITE_FUNC(mm) +{ + PS_MM_DATA; + ps_sd *sd; + + mm_lock(data->mm, MM_LOCK_RW); + + sd = ps_sd_lookup(data, key, 1); + if(!sd) { + sd = ps_sd_new(data, key, val, vallen); + ps_mm_debug(stderr, "new one for %s\n", key); + } else { + ps_mm_debug(stderr, "found existing one for %s\n", key); + mm_free(data->mm, sd->data); + sd->datalen = vallen; + sd->data = mm_malloc(data->mm, vallen); + memcpy(sd->data, val, vallen); + } + + time(&sd->ctime); + + mm_unlock(data->mm); + + return SUCCESS; +} + +PS_DESTROY_FUNC(mm) +{ + PS_MM_DATA; + ps_sd *sd; + + mm_lock(data->mm, MM_LOCK_RW); + + sd = ps_sd_lookup(data, key, 0); + if(sd) { + ps_sd_destroy(data, sd); + } + + mm_unlock(data->mm); + + return SUCCESS; +} + +PS_GC_FUNC(mm) +{ + PS_MM_DATA; + int h; + time_t now; + ps_sd *sd, *next; + + ps_mm_debug("gc\n"); + + mm_lock(data->mm, MM_LOCK_RW); + + time(&now); + + for(h = 0; h < HASH_SIZE; h++) { + for(sd = data->hash[h]; sd; sd = next) { + next = sd->next; + ps_mm_debug("looking at %s\n", sd->key); + if((now - sd->ctime) > maxlifetime) { + ps_sd_destroy(data, sd); + } + } + } + + mm_unlock(data->mm); + + return SUCCESS; +} + +#endif diff --git a/ext/session/mod_mm.h b/ext/session/mod_mm.h new file mode 100644 index 0000000000..e3cfe2db1f --- /dev/null +++ b/ext/session/mod_mm.h @@ -0,0 +1,46 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) the GNU General Public License as published by the Free Software | + | Foundation; either version 2 of the License, or (at your option) | + | any later version. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Authors: Sascha Schumann <ss@2ns.de> | + +----------------------------------------------------------------------+ + */ + +#ifndef MOD_MM_H +#define MOD_MM_H + +#ifdef HAVE_LIBMM + +extern ps_module ps_mod_mm; +#define ps_mm_ptr &ps_mod_mm + +PS_FUNCS(mm); + +#else + +#define ps_mm_ptr NULL + +#endif + +#endif diff --git a/ext/session/modules.c b/ext/session/modules.c index 50d2062854..86613696bb 100644 --- a/ext/session/modules.c +++ b/ext/session/modules.c @@ -4,9 +4,10 @@ */ #include "mod_files.h" +#include "mod_mm.h" static ps_module *ps_modules[] = { ps_files_ptr, - 0, + ps_mm_ptr, }; diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 5964d69d82..c543f800d8 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -57,6 +57,8 @@ typedef struct ps_module_struct { int (*gc)(PS_GC_ARGS); } ps_module; +#define PS_GET_MOD_DATA() *mod_data +#define PS_SET_MOD_DATA(a) *mod_data = (a) #define PS_OPEN_FUNC(x) int _ps_open_##x(PS_OPEN_ARGS) #define PS_CLOSE_FUNC(x) int _ps_close_##x(PS_CLOSE_ARGS) diff --git a/ext/session/session.c b/ext/session/session.c index 272a27a467..7b4bb8988d 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -21,7 +21,6 @@ * TODO: * - add complete support for objects (partially implemented) * - userland callback functions for ps_module - * - write ps_module utilizing shared memory (mm) */ #if !(WIN32|WINNT) #include <sys/time.h> @@ -279,9 +278,10 @@ static void _php_session_send_cookie(PSLS_D) date_fmt = php3_std_date(time(NULL) + PS(lifetime)); len += sizeof(COOKIE_EXPIRES) + strlen(date_fmt); } - cookie = emalloc(len + 1); + cookie = ecalloc(len + 1, 1); snprintf(cookie, len, COOKIE_FMT, PS(session_name), PS(id)); + cookie[len] = '\0'; if (PS(lifetime) > 0) { strcat(cookie, COOKIE_EXPIRES); strcat(cookie, date_fmt); @@ -295,8 +295,9 @@ static ps_module *_php_find_ps_module(char *name PSLS_DC) { ps_module *ret = NULL; ps_module **mod; + ps_module **end = ps_modules + (sizeof(ps_modules)/sizeof(ps_module*)); - for(mod = ps_modules; ((*mod && (*mod)->name) || !*mod); mod++) { + for(mod = ps_modules; mod < end; mod++) { if(*mod && !strcasecmp(name, (*mod)->name)) { ret = *mod; break; @@ -333,7 +334,7 @@ static void _php_session_start(PSLS_D) int lensess; ELS_FETCH(); - if (PS(nr_open_sessions) > 0) return; + if (PS(nr_open_sessions) != 0) return; lensess = strlen(PS(session_name)); @@ -419,7 +420,7 @@ static void _php_session_start(PSLS_D) if(PS(mod_data) && PS(gc_probability) > 0) { srand(time(NULL)); nrand = (int) (100.0*rand()/RAND_MAX); - if(nrand >= PS(gc_probability)) + if(nrand < PS(gc_probability)) PS(mod)->gc(&PS(mod_data), PS(gc_maxlifetime)); } } @@ -694,11 +695,15 @@ int php_rinit_session(INIT_FUNC_ARGS) php_rinit_session_globals(PSLS_C); + if(PS(mod) == NULL) { + /* current status is unusable */ + PS(nr_open_sessions) = -1; + return FAILURE; + } + if(INI_INT("session_auto_start")) { _php_session_start(PSLS_C); } - if(PS(mod) == NULL) - return FAILURE; return SUCCESS; } |
