#ifndef CESSPOOL_H #define CESSPOOL_H #include #include #include "keys.h" #include "dat_net.h" // bootstrap node // dht // discovery // lookup (key) ↳ lookup1 // announce // ping // holepunch udp #define CESSPOOL_TOPIC_BYTES 32u #define CESSPOOL_PEER_BYTES 32u enum cesspool_message_type { CESSPOOL_LOOKUP = 0, CESSPOOL_ANNOUNCE = 1, CESSPOOL_UNANNOUNCE = 2, CESSPOOL_REPLY = 3, CESSPOOL_PING = 4, CESSPOOL_PONG = 5, CESSPOOL_HOLEPUNCH = 6 }; typedef struct cesspool_message { uint8_t type; uint8_t topic[CESSPOOL_TOPIC_BYTES]; uint8_t peer_id[CESSPOOL_PEER_BYTES]; uint16_t port; uint8_t payload[2048]; size_t payload_len; } cesspool_message_t; typedef struct cesspool_request { uint32_t type; uint16_t port; uint8_t local_address[6]; size_t local_address_len; } cesspool_request_t; typedef struct cesspool_response { uint8_t peers[1024]; size_t peers_len; uint8_t local_peers[1024]; size_t local_peers_len; /* Cesspool rendezvous records: IPv4(4), UDP port(2), peer key(32). */ uint8_t peer_info[2048]; size_t peer_info_len; } cesspool_response_t; #define CESSPOOL_MAX_BOOTSTRAP 16u #define CESSPOOL_MAX_PEERS 256u #define CESSPOOL_MAX_TOPICS 64u #define CESSPOOL_MAX_ANNOUNCEMENTS 1024u #define CESSPOOL_MAX_TRANSACTIONS 64u typedef struct cesspool_peer { dat_peer_t address; uint8_t public_key[32]; uint8_t discovery_topic[CESSPOOL_TOPIC_BYTES]; uint64_t last_seen; unsigned failures; int local; int discovered; } cesspool_peer_t; typedef struct cesspool_topic { uint8_t key[32]; uint16_t port; int announcing; int looking_up; uint64_t refresh_at; } cesspool_topic_t; typedef struct cesspool_transaction { uint16_t id; uint8_t target[32]; uint8_t type; uint64_t expires_at; int active; } cesspool_transaction_t; typedef struct cesspool_announcement { uint8_t topic[CESSPOOL_TOPIC_BYTES]; uint8_t peer_id[CESSPOOL_PEER_BYTES]; dat_peer_t address; uint64_t last_seen; } cesspool_announcement_t; struct cesspool; typedef void (*cesspool_transport_packet_fn)(struct cesspool *pool, const dat_peer_t *source, const uint8_t *packet, size_t packet_len); typedef struct cesspool { datnet_t net; dat_peer_t bootstrap_nodes[CESSPOOL_MAX_BOOTSTRAP]; size_t bootstrap_count; uint16_t port; int ready; int bootstrap_server; cesspool_peer_t peers[CESSPOOL_MAX_PEERS]; size_t peer_count; cesspool_topic_t topics[CESSPOOL_MAX_TOPICS]; size_t topic_count; /* A peer may announce many topics; keep each membership independently. */ cesspool_announcement_t announcements[CESSPOOL_MAX_ANNOUNCEMENTS]; size_t announcement_count; uint64_t bootstrap_last_seen; uint64_t bootstrap_probe_at; int bootstrap_reachable; cesspool_transaction_t transactions[CESSPOOL_MAX_TRANSACTIONS]; uint16_t next_transaction; void (*on_peer)(struct cesspool *, const cesspool_peer_t *); void (*on_holepunch)(struct cesspool *, const dat_peer_t *); cesspool_transport_packet_fn on_transport_packet; void *transport_context; } cesspool_t; int cesspool_discovery_key(const uint8_t public_key[32], uint8_t topic[32]); int cesspool_encode(const cesspool_message_t *message, uint8_t *out, size_t capacity, size_t *written); int cesspool_decode(cesspool_message_t *message, const uint8_t *input, size_t input_len); int cesspool_request_encode(const cesspool_request_t *request, uint8_t *out, size_t capacity, size_t *written); int cesspool_request_decode(cesspool_request_t *request, const uint8_t *input, size_t input_len); int cesspool_response_encode(const cesspool_response_t *response, uint8_t *out, size_t capacity, size_t *written); int cesspool_response_decode(cesspool_response_t *response, const uint8_t *input, size_t input_len); int cesspool_process_response(cesspool_t *pool, const cesspool_response_t *response, const uint8_t local_prefix[2]); int cesspool_init(cesspool_t *pool, const uint8_t peer_id[32]); int cesspool_add_bootstrap(cesspool_t *pool, const char *host, uint16_t port); /* Load Cesspool bootstrap endpoints from DDAT_BOOTSTRAP and the per-user * config/dat-gpt/bootstrap file. */ int cesspool_configure_bootstraps(cesspool_t *pool); int cesspool_bootstrap_config_add(const char *endpoint); int cesspool_bootstrap_config_set(const char *endpoint); int cesspool_bootstrap_config_get(char *endpoint, size_t capacity); int cesspool_bootstrap_config_list(char *contents, size_t capacity); int cesspool_bootstrap(cesspool_t *pool); int cesspool_listen(cesspool_t *pool, const char *host, uint16_t port); int cesspool_set_bootstrap_server(cesspool_t *pool, int enabled); int cesspool_announce(cesspool_t *pool, const uint8_t topic[32], uint16_t port); int cesspool_lookup(cesspool_t *pool, const uint8_t topic[32]); int cesspool_unannounce(cesspool_t *pool, const uint8_t topic[32], uint16_t port); int cesspool_ping(cesspool_t *pool, const dat_peer_t *peer); int cesspool_holepunch(cesspool_t *pool, const dat_peer_t *peer); int cesspool_poll(cesspool_t *pool, int timeout_ms); int cesspool_add_peer(cesspool_t *pool, const cesspool_peer_t *peer); int cesspool_remove_peer(cesspool_t *pool, const uint8_t public_key[32]); cesspool_peer_t *cesspool_find_peer(cesspool_t *pool, const uint8_t public_key[32]); int cesspool_join(cesspool_t *pool, const uint8_t topic[32], uint16_t port, int announce, int lookup); int cesspool_leave(cesspool_t *pool, const uint8_t topic[32]); int cesspool_tick(cesspool_t *pool, uint64_t now_ms); size_t cesspool_closest(cesspool_t *pool, const uint8_t target[32], cesspool_peer_t **out, size_t capacity); size_t cesspool_topic_peers(cesspool_t *pool, const uint8_t topic[CESSPOOL_TOPIC_BYTES], cesspool_peer_t **out, size_t capacity); size_t cesspool_announced_peer_count(const cesspool_t *pool); size_t cesspool_announced_topic_count(const cesspool_t *pool); int cesspool_transaction_begin(cesspool_t *pool, uint8_t type, const uint8_t target[32], uint64_t expires_at, uint16_t *transaction_id); int cesspool_transaction_finish(cesspool_t *pool, uint16_t transaction_id); int cesspool_destroy(cesspool_t *pool); #endif /* CESSPOOL_H */