#pragma once
#include "common.hpp"
#include "acl.hpp"
#include "poll.hpp"
#include "pool.hpp"
#include "hash.hpp"
#include "hooks.hpp"
#include "sock.hpp"
class AccessControlResult {
friend class AccessControl;
private:
int fd; ///< client fd
tristate_t result;
AccessControlResult** handle;
AccessControlResult(int, AccessControlResult**); ///< enqueued operation
AccessControlResult(int, bool); ///< immediate result/cache-hit
void set(bool); ///< enqueued operation finished
public:
INLINE tristate_t get() { return result; } ///< none: in progress, true: allowed (or error), false: denied
~AccessControlResult(); ///< abort or frees unfetched result
};
class AccessControl {
public:
typedef struct {
sockaddr_t src;
char dst[MAX_SNI_LEN+1];
} key_t;
typedef struct {
time_t last_result;
bool result; ///< valid if #upstream_fd != -1 (and #last_result conforms with AC_CACHE_TTL)
int upstream_fd;
} val_t;
private:
typedef struct {
key_t key;
Stack<AccessControlResult*> pending; ///< waiting clients (NULL if already aborted)
} work_t;
static CPool<work_t> pool;
static void cb(int, event_t, unsigned, void*); // @see poll_handler_t
public:
static AccessControlResult* getInst(int, const char*, size_t, const sockaddr_t&, const sockaddr_t&); ///< not NULL
};