blob: a63116d9cb94c0e5e24a240ba0281e286831c3ea [file] [log] [blame]
/*
* AppSession functions.
*
* Copyright 2004-2006 Alexander Lazic, Klaus Wagner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of 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.
*
*/
#include <stdio.h>
#include <string.h>
#include <common/appsession.h>
#include <common/chtbl.h>
#include <common/config.h>
#include <common/list.h>
#include <common/time.h>
#include <types/buffers.h>
#include <types/global.h>
#include <types/proxy.h>
#include <types/server.h>
#include <proto/task.h>
void **pool_appsess = NULL;
struct app_pool apools;
int have_appsession;
#if defined(DEBUG_HASH)
void print_table(const CHTbl *htbl)
{
ListElmt *element;
int i;
appsess *asession;
/*********************************************************************
* *
* Display the chained hash table. *
* *
*********************************************************************/
fprintf(stdout, "Table size is %d\n", chtbl_size(htbl));
for (i = 0; i < TBLSIZ; i++) {
fprintf(stdout, "Bucket[%03d]\n", i);
for (element = list_head(&htbl->table[i]);
element != NULL; element = list_next(element)) {
//fprintf(stdout, "%c", *(char *)list_data(element));
asession = (appsess *)list_data(element);
fprintf(stdout, "ELEM :%s:", asession->sessid);
fprintf(stdout, " Server :%s: \n", asession->serverid);
//fprintf(stdout, " Server request_count :%li:\n",asession->request_count);
}
fprintf(stdout, "\n");
}
return;
} /* end print_table */
#endif
int appsession_init(void)
{
static int initialized = 0;
int idlen;
struct server *s;
struct proxy *p = proxy;
if (!initialized) {
if (!appsession_task_init()) {
apools.sessid = NULL;
apools.serverid = NULL;
apools.ser_waste = 0;
apools.ser_use = 0;
apools.ser_msize = sizeof(void *);
apools.ses_waste = 0;
apools.ses_use = 0;
apools.ses_msize = sizeof(void *);
while (p) {
s = p->srv;
if (apools.ses_msize < p->appsession_len)
apools.ses_msize = p->appsession_len;
while (s) {
idlen = strlen(s->id);
if (apools.ser_msize < idlen)
apools.ser_msize = idlen;
s = s->next;
}
p = p->next;
}
/* we use strings, so reserve space for '\0' */
apools.ser_msize ++;
apools.ses_msize ++;
}
else {
fprintf(stderr, "appsession_task_init failed\n");
return -1;
}
initialized ++;
}
return 0;
}
int appsession_task_init(void)
{
static int initialized = 0;
struct task *t;
if (!initialized) {
if ((t = pool_alloc(task)) == NULL)
return -1;
t->next = t->prev = t->rqnext = NULL;
t->wq = LIST_HEAD(wait_queue[0]);
t->state = TASK_IDLE;
t->context = NULL;
tv_delayfrom(&t->expire, &now, TBLCHKINT);
task_queue(t);
t->process = appsession_refresh;
initialized ++;
}
return 0;
}
int appsession_refresh(struct task *t)
{
struct proxy *p = proxy;
CHTbl *htbl;
ListElmt *element, *last;
int i;
appsess *asession;
void *data;
while (p) {
if (p->appsession_name != NULL) {
htbl = &p->htbl_proxy;
/* if we ever give up the use of TBLSIZ, we need to change this */
for (i = 0; i < TBLSIZ; i++) {
last = NULL;
for (element = list_head(&htbl->table[i]);
element != NULL; element = list_next(element)) {
asession = (appsess *)list_data(element);
if (tv_cmp2_ms(&asession->expire, &now) <= 0) {
if ((global.mode & MODE_DEBUG) &&
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
int len;
/*
on Linux NULL pointers are catched by sprintf, on solaris -> segfault
*/
len = sprintf(trash, "appsession_refresh: cleaning up expired Session '%s' on Server %s\n",
asession->sessid, asession->serverid?asession->serverid:"(null)");
write(1, trash, len);
}
/* delete the expired element from within the hash table */
if ((list_rem_next(&htbl->table[i], last, (void **)&data) == 0)
&& (htbl->table[i].destroy != NULL)) {
htbl->table[i].destroy(data);
}
if (last == NULL) {/* patient lost his head, get a new one */
element = list_head(&htbl->table[i]);
if (element == NULL) break; /* no heads left, go to next patient */
}
else
element = last;
}/* end if (tv_cmp2_ms(&asession->expire, &now) <= 0) */
else
last = element;
}/* end for (element = list_head(&htbl->table[i]); element != NULL; element = list_next(element)) */
}
}
p = p->next;
}
tv_delayfrom(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
return TBLCHKINT;
} /* end appsession_refresh */
int match_str(const void *key1, const void *key2)
{
appsess *temp1,*temp2;
temp1 = (appsess *)key1;
temp2 = (appsess *)key2;
//fprintf(stdout,">>>>>>>>>>>>>>temp1->sessid :%s:\n",temp1->sessid);
//fprintf(stdout,">>>>>>>>>>>>>>temp2->sessid :%s:\n",temp2->sessid);
return (strcmp(temp1->sessid,temp2->sessid) == 0);
}/* end match_str */
void destroy(void *data) {
appsess *temp1;
//printf("destroy called\n");
temp1 = (appsess *)data;
if (temp1->sessid)
pool_free_to(apools.sessid, temp1->sessid);
if (temp1->serverid)
pool_free_to(apools.serverid, temp1->serverid);
pool_free(appsess, temp1);
} /* end destroy */
void appsession_cleanup( void )
{
struct proxy *p = proxy;
while(p) {
chtbl_destroy(&(p->htbl_proxy));
p = p->next;
}
}/* end appsession_cleanup() */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/