/* 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 && inext) { if(ACLmatches(be->ace, param)){ if(be->ace->action == NOBANDLIM) { break; } param->bandlims[i++] = be; param->bandlimfunc = conf.bandlimfunc; } } if(ibandlims[i] = NULL; for(i=0, be = conf.bandlimiterout; be && inext) { if(ACLmatches(be->ace, param)){ if(be->ace->action == NOBANDLIM) { break; } param->bandlimsout[i++] = be; param->bandlimfunc = conf.bandlimfunc; } } if(ibandlimsout[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&& ibandlims[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 && ibandlimsout[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); }