root/eaccelerator/tags/0.9.4-rc2/session.c

Revision 123, 12.2 kB (checked in by zoeloelip, 3 years ago)

* Renamed some macros from MMC (mmcache) to EA (eg MMCG is now EAG)
* Added eA file header to mm.c, mm.h and x86-spinlocks.h
* Readded a hack to the loader to prevent zend2 segfaults

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2    +----------------------------------------------------------------------+
3    | eAccelerator project                                                 |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 2004 - 2005 eAccelerator                               |
6    | http://eaccelerator.net                                              |
7    +----------------------------------------------------------------------+
8    | This program is free software; you can redistribute it and/or        |
9    | modify it under the terms of the GNU General Public License          |
10    | as published by the Free Software Foundation; either version 2       |
11    | of the License, or (at your option) any later version.               |
12    |                                                                      |
13    | This program is distributed in the hope that it will be useful,      |
14    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
16    | GNU General Public License for more details.                         |
17    |                                                                      |
18    | You should have received a copy of the GNU General Public License    |
19    | along with this program; if not, write to the Free Software          |
20    | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
21    | MA  02111-1307, USA.                                                 |
22    |                                                                      |
23    | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
24    +----------------------------------------------------------------------+
25    | Author(s): Dmitry Stogov <dstogov@users.sourceforge.net>             |
26    +----------------------------------------------------------------------+
27    $Id$
28 */
29
30 #include "eaccelerator.h"
31 #include "session.h"
32
33 #ifdef WITH_EACCELERATOR_SESSIONS
34
35 #include "cache.h"
36 #include "ext/standard/md5.h"
37 #include <fcntl.h>
38
39 #ifdef WIN32
40 #       include "win32/time.h"
41 #endif
42
43 #if defined(HAVE_PHP_SESSIONS_SUPPORT) && defined(PS_CREATE_SID_ARGS)
44 #       include "ext/standard/php_lcg.h"
45 #endif
46
47 eaccelerator_cache_place eaccelerator_sessions_cache_place =
48         eaccelerator_shm_and_disk;
49 int eaccelerator_sessions_registered = 0;
50 extern eaccelerator_mm *eaccelerator_mm_instance;
51
52 /* set the updated ini value of the cache place */
53 PHP_INI_MH (eaccelerator_OnUpdateSessionCachePlace)
54 {
55         if (strncasecmp ("shm_and_disk", new_value, sizeof ("shm_and_disk")) == 0) {
56                 eaccelerator_sessions_cache_place = eaccelerator_shm_and_disk;
57         } else if (strncasecmp ("shm", new_value, sizeof ("shm")) == 0) {
58                 eaccelerator_sessions_cache_place = eaccelerator_shm;
59         } else if (strncasecmp ("shm_only", new_value, sizeof ("shm_only")) == 0) {
60                 eaccelerator_sessions_cache_place = eaccelerator_shm_only;
61         } else if (strncasecmp ("disk_only", new_value, sizeof ("disk_only")) == 0) {
62                 eaccelerator_sessions_cache_place = eaccelerator_disk_only;
63         } else if (strncasecmp ("none", new_value, sizeof ("none")) == 0) {
64                 eaccelerator_sessions_cache_place = eaccelerator_none;
65         }
66         return SUCCESS;
67 }
68
69 /* session unlock */
70 static int do_session_unlock (TSRMLS_D)
71 {
72         if (EAG (session) != NULL) {
73                 eaccelerator_unlock (EAG (session), strlen (EAG (session)) TSRMLS_CC);
74                 efree (EAG (session));
75                 EAG (session) = NULL;
76         }
77         return 1;
78 }
79
80 /* session locking */
81 static int do_session_lock (const char *sess_name TSRMLS_DC)
82 {
83         if (EAG (session) != NULL) {
84                 if (strcmp (EAG (session), sess_name) == 0) {
85                         return 1;
86                 } else {
87                         do_session_unlock (TSRMLS_C);
88                 }
89         }
90         if (eaccelerator_lock (sess_name, strlen (sess_name) TSRMLS_CC)) {
91                 EAG (session) = estrdup (sess_name);
92                 return 1;
93         } else {
94                 return 0;
95         }
96 }
97
98 #ifdef HAVE_PHP_SESSIONS_SUPPORT        /* PHP_SESSION_API >= 20020306 */
99 /******************************************************************************/
100 /* Session api functions                                                                                                          */
101 /******************************************************************************/
102
103 PS_OPEN_FUNC (eaccelerator)
104 {
105         if (eaccelerator_mm_instance == NULL) {
106                 return FAILURE;
107         }
108         PS_SET_MOD_DATA ((void *) 1);
109         return SUCCESS;
110 }
111
112 PS_CLOSE_FUNC (eaccelerator)
113 {
114         if (eaccelerator_mm_instance == NULL) {
115                 return FAILURE;
116         }
117         do_session_unlock (TSRMLS_C);
118         return SUCCESS;
119 }
120
121 PS_READ_FUNC (eaccelerator)
122 {
123         char *skey;
124         int len;
125         zval ret;
126
127         len = sizeof ("sess_") + strlen (key);
128         skey = do_alloca (len + 1);
129         strcpy (skey, "sess_");
130         strcat (skey, key);
131         do_session_lock (skey TSRMLS_CC);
132         if (eaccelerator_get
133                 (skey, len, &ret, eaccelerator_sessions_cache_place TSRMLS_CC)
134                 && ret.type == IS_STRING) {
135                 *val = estrdup (ret.value.str.val);
136                 *vallen = ret.value.str.len;
137                 zval_dtor (&ret);
138         } else {
139                 *val = emalloc (1);
140                 (*val)[0] = '\0';
141                 *vallen = 0;
142         }
143         free_alloca (skey);
144         return SUCCESS;
145 }
146
147 PS_WRITE_FUNC (eaccelerator)
148 {
149         char *skey;
150         int len;
151         time_t ttl;
152         zval sval;
153         char *tmp;
154
155         len = sizeof ("sess_") + strlen (key);
156         skey = do_alloca (len + 1);
157         strcpy (skey, "sess_");
158         strcat (skey, key);
159         if (cfg_get_string ("session.gc_maxlifetime", &tmp) == FAILURE) {
160                 ttl = 1440;
161         } else {
162                 ttl = atoi (tmp);
163         }
164         sval.type = IS_STRING;
165         sval.value.str.val = (char *) val;
166         sval.value.str.len = vallen;
167
168         do_session_lock (skey TSRMLS_CC);
169         if (eaccelerator_put
170                 (skey, len, &sval, ttl, eaccelerator_sessions_cache_place TSRMLS_CC)) {
171                 free_alloca (skey);
172                 return SUCCESS;
173         } else {
174                 free_alloca (skey);
175                 return FAILURE;
176         }
177 }
178
179 PS_DESTROY_FUNC (eaccelerator)
180 {
181         char *skey;
182         int len;
183
184         len = sizeof ("sess_") + strlen (key);
185         skey = do_alloca (len + 1);
186         strcpy (skey, "sess_");
187         strcat (skey, key);
188         if (eaccelerator_rm
189                 (skey, len, eaccelerator_sessions_cache_place TSRMLS_CC)) {
190                 free_alloca (skey);
191                 return SUCCESS;
192         } else {
193                 free_alloca (skey);
194                 return FAILURE;
195         }
196 }
197
198 PS_GC_FUNC (eaccelerator)
199 {
200         if (eaccelerator_mm_instance == NULL) {
201                 return FAILURE;
202         }
203         eaccelerator_gc (TSRMLS_C);
204         return SUCCESS;
205 }
206
207 #ifdef PS_CREATE_SID_ARGS
208 PS_CREATE_SID_FUNC (eaccelerator)
209 {
210         static char hexconvtab[] = "0123456789abcdef";
211         PHP_MD5_CTX context;
212         unsigned char digest[16];
213         char buf[256];
214         struct timeval tv;
215         int i;
216         int j = 0;
217         unsigned char c;
218
219         long entropy_length;
220         char *entropy_file;
221
222         if (cfg_get_string ("session.entropy_length", &entropy_file) == FAILURE) {
223                 entropy_length = 0;
224         } else {
225                 entropy_length = atoi (entropy_file);
226         }
227         if (cfg_get_string ("session.entropy_file", &entropy_file) == FAILURE) {
228                 entropy_file = empty_string;
229         }
230
231         gettimeofday (&tv, NULL);
232         PHP_MD5Init (&context);
233
234         sprintf (buf, "%ld%ld%0.8f", tv.tv_sec, tv.tv_usec,
235                          php_combined_lcg (TSRMLS_C) * 10);
236         PHP_MD5Update (&context, (unsigned char *) buf, strlen (buf));
237
238         if (entropy_length > 0) {
239                 int fd;
240
241                 fd = VCWD_OPEN (entropy_file, O_RDONLY);
242                 if (fd >= 0) {
243                         unsigned char buf[2048];
244                         int n;
245                         size_t to_read = entropy_length;
246
247                         while (to_read > 0) {
248                                 n = read (fd, buf, MIN (to_read, sizeof (buf)));
249                                 if (n <= 0)
250                                         break;
251                                 PHP_MD5Update (&context, buf, n);
252                                 to_read -= n;
253                         }
254                         close (fd);
255                 }
256         }
257
258         PHP_MD5Final (digest, &context);
259
260         for (i = 0; i < 16; i++) {
261                 c = digest[i];
262                 buf[j++] = hexconvtab[c >> 4];
263                 buf[j++] = hexconvtab[c & 15];
264         }
265         buf[j] = '\0';
266
267         if (newlen)
268                 *newlen = j;
269         return estrdup (buf);
270 }
271 #endif
272
273 #else
274 /******************************************************************************/
275 /* PHP function to register as user session handlers when the session api         */
276 /* available.                                                                                                                             */
277 /******************************************************************************/
278
279 PHP_FUNCTION (_eaccelerator_session_open)
280 {
281         if (eaccelerator_mm_instance == NULL) {
282                 RETURN_FALSE;
283         }
284         RETURN_TRUE;
285 }
286
287 PHP_FUNCTION (_eaccelerator_session_close)
288 {
289         if (eaccelerator_mm_instance == NULL) {
290                 RETURN_FALSE;
291         }
292         do_session_unlock (TSRMLS_C);
293         RETURN_TRUE;
294 }
295
296 PHP_FUNCTION (_eaccelerator_session_read)
297 {
298         zval **arg_key;
299         char *key;
300         int len;
301
302         if (ZEND_NUM_ARGS () != 1
303                 || zend_get_parameters_ex (1, &arg_key) == FAILURE) {
304                 WRONG_PARAM_COUNT;
305         }
306         len = sizeof ("sess_") + (*arg_key)->value.str.len;
307         key = do_alloca (len + 1);
308         strcpy (key, "sess_");
309         strcat (key, (*arg_key)->value.str.val);
310         do_session_lock (key TSRMLS_CC);
311         if (eaccelerator_get
312                 (key, len, return_value, eaccelerator_sessions_cache_place TSRMLS_CC)) {
313                 free_alloca (key);
314                 return;
315         } else {
316                 free_alloca (key);
317                 RETURN_EMPTY_STRING ();
318         }
319 }
320
321 PHP_FUNCTION (_eaccelerator_session_write)
322 {
323         zval **arg_key, **arg_val;
324         char *key;
325         int len;
326         time_t ttl;
327
328         if (ZEND_NUM_ARGS () != 2
329                 || zend_get_parameters_ex (2, &arg_key, &arg_val) == FAILURE) {
330                 WRONG_PARAM_COUNT;
331         }
332         len = sizeof ("sess_") + (*arg_key)->value.str.len;
333         key = do_alloca (len + 1);
334         strcpy (key, "sess_");
335         strcat (key, (*arg_key)->value.str.val);
336         ttl = PS (gc_maxlifetime);
337         if (ttl < 0)
338                 ttl = 1440;
339         do_session_lock (key TSRMLS_CC);
340         if (eaccelerator_put
341                 (key, len, *arg_val, ttl,
342                  eaccelerator_sessions_cache_place TSRMLS_CC)) {
343                 free_alloca (key);
344                 RETURN_TRUE;
345         } else {
346                 free_alloca (key);
347                 RETURN_FALSE;
348         }
349 }
350
351 PHP_FUNCTION (_eaccelerator_session_destroy)
352 {
353         zval **arg_key;
354         char *key;
355         int len;
356
357         if (ZEND_NUM_ARGS () != 1
358                 || zend_get_parameters_ex (1, &arg_key) == FAILURE) {
359                 WRONG_PARAM_COUNT;
360         }
361         len = sizeof ("sess_") + (*arg_key)->value.str.len;
362         key = do_alloca (len + 1);
363         strcpy (key, "sess_");
364         strcat (key, (*arg_key)->value.str.val);
365         if (eaccelerator_rm (key, len, eaccelerator_sessions_cache_place TSRMLS_CC)) {
366                 free_alloca (key);
367                 RETURN_TRUE;
368         } else {
369                 free_alloca (key);
370                 RETURN_FALSE;
371         }
372 }
373
374 PHP_FUNCTION (_eaccelerator_session_gc)
375 {
376         if (eaccelerator_mm_instance == NULL) {
377                 RETURN_FALSE;
378         }
379         eaccelerator_gc (TSRMLS_C);
380         RETURN_TRUE;
381 }
382 #endif /* ELSE HAVE_PHP_SESSIONS_SUPPORT */
383
384 ps_module ps_mod_eaccelerator = {
385 #ifdef PS_CREATE_SID_ARGS
386         PS_MOD_SID (eaccelerator)
387 #else
388         PS_MOD (eaccelerator)
389 #endif
390 };
391
392 /* is the eA registered as session handler */
393 int eaccelerator_session_registered ()
394 {
395         return !(eaccelerator_sessions_cache_place != eaccelerator_none &&
396                          eaccelerator_sessions_registered == 0);
397 }
398
399 /* register ea as session handler */
400 void eaccelerator_register_session ()
401 {
402         php_session_register_module (&ps_mod_eaccelerator);
403         eaccelerator_sessions_registered = 1;
404 }
405
406 /* register ea as the custom session handler */
407 int eaccelerator_set_session_handlers (TSRMLS_D)
408 {
409         zval func;
410         zval retval;
411         int ret = 1;
412 #ifdef HAVE_PHP_SESSIONS_SUPPORT        // do it with the session api
413         zval param;
414         zval *params[1];
415 /*
416   if (php_session_register_module(&ps_mod_eaccelerator) != 0) {
417     return 0;
418   }
419 */
420         if (eaccelerator_sessions_cache_place == eaccelerator_none) {
421                 return 0;
422         }
423         ZVAL_STRING (&func, "session_module_name", 0);
424         INIT_ZVAL (param);
425         params[0] = &param;
426         ZVAL_STRING (params[0], "eaccelerator", 0);
427         if (call_user_function (EG (function_table), NULL, &func, &retval,
428                                                         1, params TSRMLS_CC) == FAILURE) {
429                 ret = 0;
430         }
431         zval_dtor (&retval);
432         return ret;
433 #else // register the functions as custom user functions
434         zval *params[6];
435         int i;
436
437         if (eaccelerator_sessions_cache_place == eaccelerator_none) {
438                 return 0;
439         }
440         if (eaccelerator_mm_instance == NULL) {
441                 return 0;
442         }
443         if (!zend_hash_exists
444                 (EG (function_table), "session_set_save_handler",
445                  sizeof ("session_set_save_handler"))) {
446                 return 0;
447         }
448
449         ZVAL_STRING (&func, "session_set_save_handler", 0);
450         MAKE_STD_ZVAL (params[0]);
451         ZVAL_STRING (params[0], "_eaccelerator_session_open", 1);
452         MAKE_STD_ZVAL (params[1]);
453         ZVAL_STRING (params[1], "_eaccelerator_session_close", 1);
454         MAKE_STD_ZVAL (params[2]);
455         ZVAL_STRING (params[2], "_eaccelerator_session_read", 1);
456         MAKE_STD_ZVAL (params[3]);
457         ZVAL_STRING (params[3], "_eaccelerator_session_write", 1);
458         MAKE_STD_ZVAL (params[4]);
459         ZVAL_STRING (params[4], "_eaccelerator_session_destroy", 1);
460         MAKE_STD_ZVAL (params[5]);
461         ZVAL_STRING (params[5], "_eaccelerator_session_gc", 1);
462         if (call_user_function (EG (function_table), NULL, &func, &retval,
463                                                         6, params TSRMLS_CC) == FAILURE) {
464                 ret = 0;
465         }
466         zval_dtor (&retval);
467         for (i = 0; i < 6; i++)
468                 zval_ptr_dtor (&params[i]);
469         return ret;
470 #endif
471 }
472
473 /* function to call from a php script to register ea as session handler */
474 PHP_FUNCTION (eaccelerator_set_session_handlers)
475 {
476         if (eaccelerator_set_session_handlers (TSRMLS_C)) {
477                 RETURN_TRUE;
478         } else {
479                 RETURN_FALSE;
480         }
481 }
482
483 #endif /* HAVE_EACCELERATOR_SESSIONS */
Note: See TracBrowser for help on using the browser.