netsukuku/src/accept.c

277 lines
6.2 KiB
C
Raw Normal View History

2013-09-16 09:53:25 +00:00
/* This file is part of Netsukuku
* (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
*
* This source code 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.
*
* This source code 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.
* Please refer to the GNU Public License for more details.
*
* You should have received a copy of the GNU Public License along with
* this source code; if not, write to:
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* --
* accept.c: This is how it works:
*
* When a new accept is made add_accept is called. It first updates the accept
* table and then, if the accept_tbl isn't full add the new accept in the tbl.
* If the accept_tbl is full the connection is dropped.
* Each accept in the table last for free_accept_time after the close of that
* connection, so if an host has fulled the accept_tbl has to wait
* free_accept_time of seconds to be able to reconnect again.
*/
#include "includes.h"
#include "request.h"
#include "inet.h"
#include "accept.h"
#include "xmalloc.h"
#include "log.h"
void init_accept_tbl(int startups, int accepts, int time)
{
/* TODO: activate and test it !! */
#if 0
int i;
max_connections=startups;
max_accepts_per_host=accepts;
free_accept_time=time;
accept_idx=accept_sidx=0;
pthread_mutex_init(&mtx_acpt_idx, NULL);
pthread_mutex_init(&mtx_acpt_sidx, NULL);
accept_tbl=(struct accept_table *)xmalloc(sizeof(struct accept_table)*max_connections);
memset(accept_tbl, '\0', sizeof(struct accept_table)*max_connections);
for(i=0; i<max_connections; i++) {
accept_tbl[i].pid=(pid_t *)xmalloc(sizeof(pid_t)*max_accepts_per_host);
memset(accept_tbl[i].pid, '\0', sizeof(pid_t)*max_accepts_per_host);
accept_tbl[i].closed=(unsigned char *)xmalloc(sizeof(unsigned char)*max_accepts_per_host);
memset(accept_tbl[i].closed, '\0', sizeof(unsigned char)*max_accepts_per_host);
accept_tbl[i].acp_t=(time_t *)xmalloc(sizeof(time_t)*max_accepts_per_host);
memset(accept_tbl[i].acp_t, '\0', sizeof(time_t)*max_accepts_per_host);
}
#endif
}
void destroy_accept_tbl(void)
{
/* TODO: activate and test it !! */
#if 0
int i;
if(!accept_tbl)
return;
for(i=0; i<max_connections; i++) {
xfree(accept_tbl[i].pid);
xfree(accept_tbl[i].closed);
xfree(accept_tbl[i].acp_t);
}
xfree(accept_tbl);
accept_tbl=0;
#endif
}
void update_accept_tbl(void)
{
time_t cur_t, passed_time;
int i,e,k,ee, pid_exists;
if(update_accept_tbl_mutex)
return;
else
update_accept_tbl_mutex=1;
time(&cur_t);
for(i=0; i < max_connections; i++) {
if(!accept_tbl[i].ip.len)
continue;
if(accept_tbl[i].accepts) {
for(e=0; e<max_accepts_per_host; e++) {
if(!accept_tbl[i].acp_t[e])
continue;
if(accept_tbl[i].pid[e]) {
k=kill(accept_tbl[i].pid[e], 0);
pid_exists = !(k==-1 && errno==ESRCH);
} else
pid_exists=0;
#if 0
debug(DBG_NOISE, "ACPT: Updating tbl: cur_t: %d, "
"accept_tbl[%d].acp_t[%d]:%d+%d, "
"accept_tbl[i].pid[e]: %d, "
"kill=%d (ESRCH=%d)",
cur_t, i,e, accept_tbl[i].acp_t[e],
free_accept_time, accept_tbl[i].pid[e],
k, ESRCH);
#endif
passed_time=accept_tbl[i].acp_t[e]+free_accept_time;
if((accept_tbl[i].closed[e] || !pid_exists) &&
passed_time <= cur_t) {
ee=e;
del_accept(i, &ee);
}
}
}
}
update_accept_tbl_mutex=0;
}
int find_ip_acpt(inet_prefix ip)
{
int i;
for(i=0; i<max_accepts_per_host; i++) {
if(!memcmp(accept_tbl[i].ip.data, &ip.data, MAX_IP_SZ))
return i;
}
return -1;
}
int find_first_free(void)
{
int i;
for(i=0; i<max_connections; i++)
if(!accept_tbl[i].accepts)
return i;
return -1;
}
int is_ip_acpt_free(inet_prefix ip, int *index)
{
int idx;
update_accept_tbl();
if((idx=find_ip_acpt(ip))==-1)
if((idx=find_first_free())==-1)
return E_TOO_MANY_CONN;
/*debug(DBG_NOISE, "ACPT: accept_tbl[%d].accepts: %d, max_acp: %d", idx,
accept_tbl[idx].accepts, max_accepts_per_host); */
if(accept_tbl[idx].accepts >= max_accepts_per_host)
return E_ACCEPT_TBL_FULL;
*index=idx;
return 0;
}
int find_free_acp_t(int idx)
{
int e;
for(e=0; e < max_accepts_per_host; e++) {
if(!accept_tbl[idx].acp_t[e])
return e;
}
return -1; /*This happens if the rq_tbl is full for the "rq" request*/
}
int new_accept(int idx, inet_prefix ip)
{
int cl=0;
/* TODO: activate and test it !! */
#if 0
time_t cur_t;
time(&cur_t);
if((cl=find_free_acp_t(idx))==-1)
return -1;
accept_tbl[idx].accepts++;
accept_tbl[idx].acp_t[cl]=cur_t;
accept_tbl[idx].closed[cl]=0;
inet_copy(&accept_tbl[idx].ip, &ip);
#endif
return cl;
}
/*
* add_accept: It adds a new accept of `ip'. If `replace' is not 0 the `ip's
* accepts are not incremented and accept_sidx is set to 0.
*/
int add_accept(inet_prefix ip, int replace)
{
/* TODO: activate and test it !! */
#if 0
int err, idx, cl;
if((err=is_ip_acpt_free(ip, &idx)))
return err;
if(!replace || !accept_tbl[idx].accepts) {
cl=new_accept(idx, ip);
if(cl < 0)
return -1;
} else
cl=0;
/*This global var will be given to the thread*/
pthread_mutex_lock(&mtx_acpt_idx);
accept_idx=idx;
pthread_mutex_unlock(&mtx_acpt_idx);
pthread_mutex_lock(&mtx_acpt_sidx);
accept_sidx=cl;
pthread_mutex_unlock(&mtx_acpt_sidx);
#endif
return 0;
}
void del_accept(int idx, int *sidx)
{
#if 0
if(!accept_tbl[idx].accepts)
return;
if(accept_tbl[idx].acp_t[*sidx]) {
accept_tbl[idx].accepts--;
accept_tbl[idx].acp_t[*sidx]=0;
accept_tbl[idx].closed[*sidx]=0;
if(!accept_tbl[idx].accepts)
memset(&accept_tbl[idx].ip, '\0', sizeof(inet_prefix));
(*sidx)--;
}
#endif
}
int close_accept(int idx, int sidx)
{
#if 0
if(!accept_tbl[idx].accepts)
return -1;
accept_tbl[idx].closed[sidx]=1;
#endif
return 0;
}
void add_accept_pid(pid_t pid, int idx, int sidx)
{
/* TODO: activate and test it !! */
#if 0
accept_tbl[idx].pid[sidx]=pid;
/* debug(DBG_NOISE, "ACPT: Added pig %d in accept_tbl[%d].pid[%d]",
accept_tbl[idx].pid[sidx], idx, sidx);
*/
#endif
}