mirror of
https://github.com/3proxy/3proxy.git
synced 2026-04-28 15:10:12 +08:00
196 lines
5.1 KiB
C
196 lines
5.1 KiB
C
/*
|
|
3APA3A simplest proxy server
|
|
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org>
|
|
|
|
please read License Agreement
|
|
|
|
*/
|
|
|
|
#include "proxy.h"
|
|
|
|
int startconnlims (struct clientparam *param){
|
|
struct connlim * ce;
|
|
time_t delta;
|
|
uint64_t rating;
|
|
int ret = 0;
|
|
|
|
param->connlim = 1;
|
|
pthread_mutex_lock(&connlim_mutex);
|
|
for(ce = conf.connlimiter; ce; ce = ce->next) {
|
|
if(ACLmatches(ce->ace, param)){
|
|
if(ce->ace->action == NOCONNLIM)break;
|
|
if(!ce->period){
|
|
if(ce->rate <= ce->rating) {
|
|
ret = 1;
|
|
break;
|
|
}
|
|
ce->rating++;
|
|
continue;
|
|
}
|
|
delta = conf.time - ce->basetime;
|
|
if(ce->period <= delta || ce->basetime > conf.time){
|
|
ce->basetime = conf.time;
|
|
ce->rating = 0x100000;
|
|
continue;
|
|
}
|
|
rating = delta? ((ce->rating * (ce->period - delta)) / ce->period) + 0x100000 : ce->rating + 0x100000;
|
|
if (rating > (ce->rate<<20)) {
|
|
ret = 2;
|
|
break;
|
|
}
|
|
ce->rating = rating;
|
|
ce->basetime = conf.time;
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&connlim_mutex);
|
|
return ret;
|
|
}
|
|
|
|
void stopconnlims (struct clientparam *param){
|
|
struct connlim * ce;
|
|
|
|
pthread_mutex_lock(&connlim_mutex);
|
|
for(ce = conf.connlimiter; ce; ce = ce->next) {
|
|
if(ACLmatches(ce->ace, param)){
|
|
if(ce->ace->action == NOCONNLIM)break;
|
|
if(!ce->period && ce->rating){
|
|
ce->rating--;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&connlim_mutex);
|
|
}
|
|
|
|
void initbandlims (struct clientparam *param){
|
|
struct bandlim * be;
|
|
int i;
|
|
|
|
param->bandlimfunc = NULL;
|
|
param->bandlims[0] = NULL;
|
|
param->bandlimsout[0] = NULL;
|
|
if(!conf.bandlimfunc || (!conf.bandlimiter && !conf.bandlimiterout)) return;
|
|
for(i=0, be = conf.bandlimiter; be && i<MAXBANDLIMS; be = be->next) {
|
|
if(ACLmatches(be->ace, param)){
|
|
if(be->ace->action == NOBANDLIM) {
|
|
break;
|
|
}
|
|
param->bandlims[i++] = be;
|
|
param->bandlimfunc = conf.bandlimfunc;
|
|
}
|
|
}
|
|
if(i<MAXBANDLIMS)param->bandlims[i] = NULL;
|
|
for(i=0, be = conf.bandlimiterout; be && i<MAXBANDLIMS; be = be->next) {
|
|
if(ACLmatches(be->ace, param)){
|
|
if(be->ace->action == NOBANDLIM) {
|
|
break;
|
|
}
|
|
param->bandlimsout[i++] = be;
|
|
param->bandlimfunc = conf.bandlimfunc;
|
|
}
|
|
}
|
|
if(i<MAXBANDLIMS)param->bandlimsout[i] = NULL;
|
|
param->bandlimver = conf.bandlimver;
|
|
}
|
|
|
|
unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nbytesout){
|
|
unsigned sleeptime = 0, nsleeptime;
|
|
time_t sec;
|
|
unsigned msec;
|
|
unsigned now;
|
|
int i;
|
|
|
|
#ifdef _WIN32
|
|
struct timeb tb;
|
|
|
|
ftime(&tb);
|
|
sec = (unsigned)tb.time;
|
|
msec = (unsigned)tb.millitm*1000;
|
|
#else
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
|
|
sec = tv.tv_sec;
|
|
msec = tv.tv_usec;
|
|
#endif
|
|
|
|
if(!nbytesin && !nbytesout) return 0;
|
|
pthread_mutex_lock(&bandlim_mutex);
|
|
if(param->bandlimver != conf.bandlimver){
|
|
initbandlims(param);
|
|
param->bandlimver = conf.bandlimver;
|
|
}
|
|
for(i=0; nbytesin&& i<MAXBANDLIMS && param->bandlims[i]; i++){
|
|
if( !param->bandlims[i]->basetime ||
|
|
param->bandlims[i]->basetime > sec ||
|
|
param->bandlims[i]->basetime < (sec - 120)
|
|
)
|
|
{
|
|
param->bandlims[i]->basetime = sec;
|
|
param->bandlims[i]->nexttime = 0;
|
|
continue;
|
|
}
|
|
now = (unsigned)((sec - param->bandlims[i]->basetime) * 1000000) + msec;
|
|
nsleeptime = (param->bandlims[i]->nexttime > now)?
|
|
param->bandlims[i]->nexttime - now : 0;
|
|
sleeptime = (nsleeptime > sleeptime)? nsleeptime : sleeptime;
|
|
param->bandlims[i]->basetime = sec;
|
|
param->bandlims[i]->nexttime = msec + nsleeptime + (((uint64_t)nbytesin * 8 * 1000000) / param->bandlims[i]->rate);
|
|
}
|
|
for(i=0; nbytesout && i<MAXBANDLIMS && param->bandlimsout[i]; i++){
|
|
if( !param->bandlimsout[i]->basetime ||
|
|
param->bandlimsout[i]->basetime > sec ||
|
|
param->bandlimsout[i]->basetime < (sec - 120)
|
|
)
|
|
{
|
|
param->bandlimsout[i]->basetime = sec;
|
|
param->bandlimsout[i]->nexttime = 0;
|
|
continue;
|
|
}
|
|
now = (unsigned)((sec - param->bandlimsout[i]->basetime) * 1000000) + msec;
|
|
nsleeptime = (param->bandlimsout[i]->nexttime > now)?
|
|
param->bandlimsout[i]->nexttime - now : 0;
|
|
sleeptime = (nsleeptime > sleeptime)? nsleeptime : sleeptime;
|
|
param->bandlimsout[i]->basetime = sec;
|
|
param->bandlimsout[i]->nexttime = msec + nsleeptime + ((nbytesout > 512)? ((nbytesout+32)/64)*((64*8*1000000)/param->bandlimsout[i]->rate) : ((nbytesout+1)* (8*1000000))/param->bandlimsout[i]->rate);
|
|
}
|
|
pthread_mutex_unlock(&bandlim_mutex);
|
|
return sleeptime/1000;
|
|
}
|
|
|
|
void trafcountfunc(struct clientparam *param){
|
|
struct trafcount * tc;
|
|
int countout = 0;
|
|
|
|
pthread_mutex_lock(&tc_mutex);
|
|
for(tc = conf.trafcounter; tc; tc = tc->next) {
|
|
if(ACLmatches(tc->ace, param)){
|
|
|
|
if(tc->ace->action == NOCOUNTIN) {
|
|
countout = 1;
|
|
break;
|
|
}
|
|
if(tc->ace->action == NOCOUNTALL) break;
|
|
if(tc->ace->action != COUNTIN && tc->ace->action != COUNTALL) {
|
|
countout = 1;
|
|
continue;
|
|
}
|
|
tc->traf64 += param->statssrv64;
|
|
tc->updated = conf.time;
|
|
}
|
|
}
|
|
if(countout) for(tc = conf.trafcounter; tc; tc = tc->next) {
|
|
if(ACLmatches(tc->ace, param)){
|
|
if(tc->ace->action == NOCOUNTOUT || tc->ace->action == NOCOUNTALL) break;
|
|
if(tc->ace->action != COUNTOUT && tc->ace->action != COUNTALL ) {
|
|
continue;
|
|
}
|
|
tc->traf64 += param->statscli64;
|
|
tc->updated = conf.time;
|
|
}
|
|
}
|
|
|
|
pthread_mutex_unlock(&tc_mutex);
|
|
}
|
|
|