#pragma once #include #include #include #ifdef RATELIMIT_THREADSAFE #include #endif typedef struct { ratelimit_table_type value; int count; double window_start; } ratelimit_t; static struct { ratelimit_t data[256]; size_t next; #ifdef RATELIMIT_THREADSAFE pthread_mutex_t lock; #endif } ratelimit_table = { {0}, 0 #ifdef RATELIMIT_THREADSAFE , PTHREAD_MUTEX_INITIALIZER #endif }; static int rate_limited(ratelimit_table_type value, float window, int rate_limit) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); double now = ts.tv_sec + ts.tv_nsec * 1e-9; #ifdef RATELIMIT_THREADSAFE pthread_mutex_lock(&ratelimit_table.lock); #endif ratelimit_t* e = (void*)0; for (size_t i = 0; i < 256; i++) { if (memcmp(ratelimit_table.data[i].value, value, sizeof(ratelimit_table_type)) == 0) { e = &ratelimit_table.data[i]; break; } } if (!e) { e = &ratelimit_table.data[ratelimit_table.next++]; memcpy(e->value, value, sizeof(ratelimit_table_type)); e->window_start = now; e->count = 0; } if (now - e->window_start >= window) { e->window_start = now; e->count = 0; } const int allowed = e->count < rate_limit; if (allowed) e->count++; #ifdef RATELIMIT_THREADSAFE pthread_mutex_unlock(&ratelimit_table.lock); #endif return allowed ? 0 : 1; }