tuyau

Client/server for transfering files (like cp)
git clone https://noulin.net/git/tuyau.git
Log | Files | Refs | README

rateLimiter.c (6618B)


      1 
      2 
      3 /* Add class methods and modify the base functions (free, duplicate, ...) where there are the TODOs (TODO)*/
      4 
      5 #include "libsheepyObject.h"
      6 #include "rateLimiter.h"
      7 #include "rateLimiterInternal.h"
      8 
      9 #include <stdlib.h>
     10 #include <string.h>
     11 #include <stdio.h>
     12 
     13 void initiateRateLimiter(rateLimitert *self);
     14 void registerMethodsRateLimiter(rateLimiterFunctionst *f);
     15 void initiateAllocateRateLimiter(rateLimitert **self);
     16 void finalizeRateLimiter(void);
     17 rateLimitert* allocRateLimiter(void);
     18 internal void freeRateLimiter(rateLimitert *self);
     19 internal void terminateRateLimiter(rateLimitert **self);
     20 internal char* toStringRateLimiter(rateLimitert *self);
     21 internal rateLimitert* duplicateRateLimiter(rateLimitert *self);
     22 internal void smashRateLimiter(rateLimitert **self);
     23 internal void finishRateLimiter(rateLimitert **self);
     24 internal bool setupRateLimiter(rateLimitert *self, u32 maxClients, u64 window, u32 maxAccessCount);
     25 internal size_t countRateLimiter(rateLimitert *self);
     26 internal bool incomingRateLimiter(rateLimitert *self, u32 ip);
     27 internal bool hasRateLimiter(rateLimitert *self, u32 ip);
     28 internal time_t getTime(void);
     29 internal void prune(rateLimitert *self);
     30 internal int cmprateL(u32 k1, u32 k2);
     31 internal void freerateLKV(u32* k, u32* v);
     32 /* TODO add prototypes */
     33 
     34 /* enable/disable logging */
     35 #undef pLog
     36 #define pLog(...)
     37 
     38 #define RATELIMA self->rateLimiterA
     39 #define RATELIMIX self->rateLimiterIx
     40 #define RATELIMH self->rateLimiterH
     41 
     42 #define RATELIM(index) RATELIMA[indexerRef(RATELIMIX, index)]
     43 #define RATELIMFirst RATELIMA[indexerFirst(RATELIMIX)]
     44 #define RATELIMLast RATELIMA[indexerLast(RATELIMIX)]
     45 
     46 internal int cmprateL(u32 k1, u32 k2) {
     47   return k1 == k2 ? 0 : 1;
     48 }
     49 
     50 internal void freerateLKV(u32* k, u32* v) {
     51   // nothing to free, the data is stored in rateLimiterA
     52 }
     53 
     54 #define HASHFUNC u32Hash // hash function from the hashfunctions spm package
     55 #define CMPFUNC  cmprateL
     56 #define FREEFUNC freerateLKV
     57 
     58 hashTbFunctions(, rateL, rateL, u32, u32);
     59 
     60 #undef HASHFUNC
     61 #undef CMPFUNC
     62 #undef FREEFUNC
     63 
     64 void initiateRateLimiter(rateLimitert *self) {
     65 
     66   self->type = "rateLimiter";
     67   if (!rateLimiterF) {
     68     rateLimiterF            = malloc(sizeof(rateLimiterFunctionst));
     69     registerMethodsRateLimiter(rateLimiterF);
     70     pErrorNot0(atexit(finalizeRateLimiter));
     71   }
     72   self->f = rateLimiterF;
     73 
     74   RATELIMA = NULL;
     75   initrateL(&RATELIMH);
     76   /* TODO Initialize object data */
     77 }
     78 
     79 void registerMethodsRateLimiter(rateLimiterFunctionst *f) {
     80 
     81   f->free      = freeRateLimiter;
     82   f->terminate = terminateRateLimiter;
     83   f->toString  = toStringRateLimiter;
     84   f->duplicate = duplicateRateLimiter;
     85   f->smash     = smashRateLimiter;
     86   f->finish    = finishRateLimiter;
     87   f->setup     = setupRateLimiter;
     88   f->count     = countRateLimiter;
     89   f->incoming  = incomingRateLimiter;
     90   f->has       = hasRateLimiter;
     91   /* TODO add class functions */
     92 }
     93 
     94 void initiateAllocateRateLimiter(rateLimitert **self) {
     95 
     96   if (self) {
     97     (*self) = malloc(sizeof(rateLimitert));
     98     if (*self) {
     99       initiateRateLimiter(*self);
    100     }
    101   }
    102 }
    103 
    104 void finalizeRateLimiter(void) {
    105 
    106   if (rateLimiterF) {
    107     free(rateLimiterF);
    108     rateLimiterF = NULL;
    109   }
    110 }
    111 
    112 rateLimitert* allocRateLimiter(void) {
    113   rateLimitert *r = NULL;
    114 
    115   initiateAllocateRateLimiter(&r);
    116   /* TODO copy data given in parameter to the object */
    117   return(r);
    118 }
    119 
    120 
    121 internal void freeRateLimiter(rateLimitert *self) {
    122 
    123   free(RATELIMA);
    124   freerateL(&RATELIMH);
    125   /* TODO free internal data (not the structure holding the function pointers) */
    126   return;
    127 }
    128 
    129 internal void terminateRateLimiter(rateLimitert **self) {
    130 
    131   freeRateLimiter(*self);
    132   free(*self);
    133   *self = NULL;
    134 }
    135 
    136 
    137 internal char* toStringRateLimiter(rateLimitert *self) {
    138 
    139   /* TODO convert object data to string */
    140   return(strdup("TODO - rateLimiter"));
    141 }
    142 
    143 internal rateLimitert* duplicateRateLimiter(rateLimitert *self) {
    144 
    145   createAllocateRateLimiter(dup);
    146   /* TODO COPY data */
    147   return(dup);
    148 }
    149 
    150 internal void smashRateLimiter(rateLimitert **self) {
    151 
    152   finishRateLimiter(self);
    153 }
    154 
    155 internal void finishRateLimiter(rateLimitert **self) {
    156 
    157   free(*self);
    158   *self = NULL;
    159 }
    160 
    161 
    162 internal bool setupRateLimiter(rateLimitert *self, u32 maxClients, u64 window, u32 maxAccessCount) {
    163 
    164   if (RATELIMA) free(RATELIMA);
    165   emptyrateL(&RATELIMH);
    166 
    167   RATELIMA = malloc(sizeof(rateLimterE) * maxClients);
    168   if (!RATELIMA) return false;
    169 
    170   indexerInit(RATELIMIX, maxClients);
    171 
    172   self->window         = window;
    173   self->maxAccessCount = maxAccessCount;
    174   return true;
    175 }
    176 
    177 internal time_t getTime(void) {
    178   return getCurrentUnixTime();
    179   /* static time_t tim = 0; */
    180   /* return tim++; */
    181 }
    182 
    183 internal void prune(rateLimitert *self) {
    184   time_t now = getTime();
    185 
    186   range (p, indexerCount(RATELIMIX)) {
    187     if ((u64)(now - RATELIMFirst.time) < self->window)
    188       break;
    189     delrateL(&RATELIMH, RATELIMFirst.ip);
    190     logI("removed %x", RATELIMFirst.ip);
    191     indexerDequeue(RATELIMIX);
    192   }
    193 }
    194 
    195 internal size_t countRateLimiter(rateLimitert *self) {
    196   prune(self);
    197   return indexerCount(RATELIMIX);
    198 }
    199 
    200 internal bool incomingRateLimiter(rateLimitert *self, u32 ip) {
    201   time_t now = getTime();
    202   logVarG(now);
    203 
    204   u32 *value;
    205   if ((value = findrateL(&RATELIMH, ip))) { // assign value and test NULL
    206     u32 i = *value;
    207     RATELIM(i).count++;
    208     logI("found ip in rateLimiterA %x i %d, count %d time %d", ip, i, RATELIM(i).count, RATELIM(i).time);
    209 
    210     if ((u64)(now - RATELIM(i).time) < self->window) {
    211     //if ((now - RATELIM(i).time) < self->window) {
    212       if (RATELIM(i).count < self->maxAccessCount) {
    213         // limit not yet reached
    214         return true;
    215       }
    216       else {
    217         logI("too many connections from ip %x", ip);
    218         return false;
    219       }
    220     }
    221     else {
    222       // remove connections older than self->window
    223       prune(self);
    224       size_t cnt = indexerCount(RATELIMIX);
    225       logVarG(cnt);
    226       return true;
    227     }
    228   }
    229   else {
    230     if (indexerIsFull(RATELIMIX)) {
    231       if ((u64)(now - RATELIMFirst.time) >= self->window) {
    232         // free first slot since it is older than self->window
    233         delrateL(&RATELIMH, RATELIMFirst.ip);
    234         indexerDequeue(RATELIMIX);
    235       }
    236       else {
    237         logI("too many connections");
    238         return false;
    239       }
    240     }
    241 
    242     indexerPush(RATELIMIX);
    243     /* u32 i = indexerLast(RATELIMIX); */
    244     /* logI("new ip %x, i %d", ip, i); */
    245     addrateL(&RATELIMH, ip, indexerLast(RATELIMIX));
    246     RATELIMLast.ip    = ip;
    247     RATELIMLast.count = 1;
    248     RATELIMLast.time  = now;
    249     return true;
    250   }
    251 }
    252 
    253 internal bool hasRateLimiter(rateLimitert *self, u32 ip) {
    254   prune(self);
    255   ret findrateL(&RATELIMH, ip) ? true : false;
    256 }
    257 /* TODO add method implementations */