blob: 86b959fd03563e2315d515dec07cf0d7f0ac7d31 (
plain) (
tree)
|
|
// Copyright (c) 2022 Johannes Stoelp
#ifndef LEASE_DB_H
#define LEASE_DB_H
#include "types.h"
#include <array>
#include <optional>
struct lease {
u32 client_hash;
usize lease_end;
};
// Lease database, for managing client leases, which includes
// - allocation of new leases
// - lookup of existing leases
// - update of existing leases
// - flushing of expired leases
//
// The database supports 'LEASE' number of clients.
//
// The lease APIs return an idx which represents the allocated client lease and
// should be interpreted as offset to the start address of the dhcp address
// range.
//
// For example, the dhcp server starts to assing addresses starting with
// 10.0.0.100, and the lease database returns idx=4, this would represent the
// allocated client address 10.0.0.104.
template<usize LEASES>
class lease_db {
public:
constexpr lease_db() = default;
lease_db(const lease_db&) = delete;
lease_db& operator=(const lease_db&) = delete;
// Try to allocate a new client lease for the client represented by
// 'client_hash'.
//
// If a lease could be allocated return the corresponding idx.
//
// If a lease for the client already exist or all leases are allocated,
// return nullopt.
//
// 'lease_end' sets the expiration time of the lease (should be absolute time).
std::optional<usize> new_lease(u32 client_hash, usize lease_end) {
if (get_lease(client_hash)) {
return std::nullopt;
}
for (usize l = 0; client_hash != 0 && l < LEASES; ++l) {
if (leases[l].client_hash == 0) {
leases[l].client_hash = client_hash;
leases[l].lease_end = lease_end;
return l;
}
}
return std::nullopt;
}
// Try to get the lease for the client if it exists.
std::optional<usize> get_lease(u32 client_hash) const {
for (usize l = 0; client_hash != 0 && l < LEASES; ++l) {
if (leases[l].client_hash == client_hash) {
return l;
}
}
return std::nullopt;
}
// Update expiration time for client if the client has an allocated lease.
// Similar to 'new_lease' the 'lease_end' should be an absolute time value.
bool update_lease(u32 client_hash, usize lease_end) {
for (usize l = 0; client_hash != 0 && l < LEASES; ++l) {
if (leases[l].client_hash == client_hash) {
leases[l].lease_end = lease_end;
return true;
}
}
return false;
}
// Check for expired leases and free them accordingly.
// 'curr_time' should be the current time as absolute time value.
void flush_expired(usize curr_time) {
for (lease& l : leases) {
if (l.lease_end <= curr_time) {
l.client_hash = 0;
l.lease_end = 0;
}
}
}
// Get the number of active leases.
usize active_leases() const {
usize cnt = 0;
for (const lease& l : leases) {
if (l.client_hash != 0) {
++cnt;
}
}
return cnt;
}
private:
std::array<lease, LEASES> leases = {0, 0};
};
#endif
|