Concord - C Discord API library
A Discord API wrapper library written in C

Enforce ratelimiting per the official Discord Documentation. More...

Collaboration diagram for Ratelimiting:

Data Structures

struct  discord_ratelimiter
 The ratelimiter struct for handling ratelimiting. More...
 
struct  discord_bucket
 The Discord bucket for handling per-group ratelimits. More...
 

Macros

#define DISCORD_BUCKET_TIMEOUT   (void *)(0xf)
 Value assigned to discord_bucket busy_req field in case it's being timed-out. More...
 

Functions

void discord_ratelimiter_init (struct discord_ratelimiter *rl, struct logconf *conf)
 Initialize ratelimiter handle. More...
 
void discord_ratelimiter_cleanup (struct discord_ratelimiter *rl)
 Cleanup all buckets that have been discovered. More...
 
void discord_ratelimiter_build_key (enum http_method method, char key[256], const char endpoint_fmt[], va_list args)
 Build unique key formed from the HTTP method and endpoint. More...
 
void discord_ratelimiter_build (struct discord_ratelimiter *rl, struct discord_bucket *bucket, const char key[], struct ua_info *info)
 Update the bucket with response header data. More...
 
void discord_ratelimiter_set_global_timeout (struct discord_ratelimiter *rl, struct discord_bucket *bucket, u64unix_ms wait_ms)
 Update global ratelimiting value. More...
 
void discord_bucket_set_timeout (struct discord_bucket *bucket, u64unix_ms wait_ms)
 Set bucket timeout. More...
 
struct discord_bucketdiscord_bucket_get (struct discord_ratelimiter *rl, const char key[])
 Get a struct discord_bucket assigned to key More...
 
void discord_bucket_insert (struct discord_ratelimiter *rl, struct discord_bucket *b, struct discord_request *req, bool high_priority)
 Insert into bucket's next requests queue. More...
 
void discord_bucket_request_selector (struct discord_ratelimiter *rl, void *data, void(*iter)(void *data, struct discord_request *req))
 Iterate and select next requests. More...
 
void discord_bucket_request_unselect (struct discord_ratelimiter *rl, struct discord_bucket *b, struct discord_request *req)
 Unselect a request provided at discord_ratelimiter_request_selector() More...
 

Detailed Description

Enforce ratelimiting per the official Discord Documentation.

Macro Definition Documentation

◆ DISCORD_BUCKET_TIMEOUT

#define DISCORD_BUCKET_TIMEOUT   (void *)(0xf)

Value assigned to discord_bucket busy_req field in case it's being timed-out.

Function Documentation

◆ discord_ratelimiter_init()

void discord_ratelimiter_init ( struct discord_ratelimiter rl,
struct logconf conf 
)

Initialize ratelimiter handle.

A hashtable shall be used for storage and retrieval of discovered buckets

Parameters
rlthe ratelimiter handle to be initialized
confpointer to discord_rest logging module

◆ discord_ratelimiter_cleanup()

void discord_ratelimiter_cleanup ( struct discord_ratelimiter rl)

Cleanup all buckets that have been discovered.

Note
pending requests will be moved to rest.queues->recycling
Parameters
rlthe handle initialized with discord_ratelimiter_init()

◆ discord_ratelimiter_build_key()

void discord_ratelimiter_build_key ( enum http_method  method,
char  key[256],
const char  endpoint_fmt[],
va_list  args 
)

Build unique key formed from the HTTP method and endpoint.

See also
https://discord.com/developers/docs/topics/rate-limits
Parameters
[in]methodthe request method
[out]keyunique key for matching to buckets
[in]endpoint_fmtthe printf-like endpoint formatting string
[in]argsvariadic arguments matched to endpoint_fmt

◆ discord_ratelimiter_build()

void discord_ratelimiter_build ( struct discord_ratelimiter rl,
struct discord_bucket bucket,
const char  key[],
struct ua_info *  info 
)

Update the bucket with response header data.

Parameters
rlthe handle initialized with discord_ratelimiter_init()
bucketNULL when bucket is first discovered
keyobtained from discord_ratelimiter_build_key()
infoinformational struct containing details on the current transfer
Note
If the bucket was just discovered it will be created here.

◆ discord_ratelimiter_set_global_timeout()

void discord_ratelimiter_set_global_timeout ( struct discord_ratelimiter rl,
struct discord_bucket bucket,
u64unix_ms  wait_ms 
)

Update global ratelimiting value.

Todo:
check if all pending buckets must be unset
Parameters
rlthe handle initialized with discord_ratelimiter_init()
bucketbucket that received the global ratelimiting notice
wait_msthe amount of time that all buckets should wait for

◆ discord_bucket_set_timeout()

void discord_bucket_set_timeout ( struct discord_bucket bucket,
u64unix_ms  wait_ms 
)

Set bucket timeout.

Parameters
bucketthe bucket to be checked for time out
wait_mshow long the bucket should wait for

◆ discord_bucket_get()

struct discord_bucket * discord_bucket_get ( struct discord_ratelimiter rl,
const char  key[] 
)

Get a struct discord_bucket assigned to key

Parameters
rlthe handle initialized with discord_ratelimiter_init()
keyobtained from discord_ratelimiter_build_key()
Returns
bucket matched to key

◆ discord_bucket_insert()

void discord_bucket_insert ( struct discord_ratelimiter rl,
struct discord_bucket b,
struct discord_request req,
bool  high_priority 
)

Insert into bucket's next requests queue.

Parameters
rlthe handle initialized with discord_ratelimiter_init()
bthe bucket to insert the request to
reqthe request to be inserted to bucket
high_priorityif high priority then request shall be prioritized over already enqueued requests

◆ discord_bucket_request_selector()

void discord_bucket_request_selector ( struct discord_ratelimiter rl,
void *  data,
void(*)(void *data, struct discord_request *req)  iter 
)

Iterate and select next requests.

Note
discord_bucket_unselect() must be called once bucket's current request is done and its next one should be selected
Parameters
rlthe handle initialized with discord_ratelimiter_init()
datauser arbitrary data
iterthe user callback to be called per bucket

◆ discord_bucket_request_unselect()

void discord_bucket_request_unselect ( struct discord_ratelimiter rl,
struct discord_bucket b,
struct discord_request req 
)

Unselect a request provided at discord_ratelimiter_request_selector()

Note
counterpart to discord_ratelimiter_request_selector()
Parameters
rlthe handle initialized with discord_ratelimiter_init()
bthe request's bucket
reqthe request to unslect