💾 Archived View for gmi.noulin.net › gitRepositories › tuyau › file › rateLimiter › rateLimiter.c.gm… captured on 2023-01-29 at 13:27:42. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

tuyau

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 */