mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-13 13:07:06 +00:00
420 lines
13 KiB
C
420 lines
13 KiB
C
#ifndef KS_DHT_H
|
|
#define KS_DHT_H
|
|
|
|
#include "ks.h"
|
|
#include "ks_bencode.h"
|
|
#include "sodium.h"
|
|
|
|
KS_BEGIN_EXTERN_C
|
|
|
|
|
|
#define KS_DHT_DEFAULT_PORT 5309
|
|
#define KS_DHT_RECV_BUFFER_SIZE 0xFFFF
|
|
#define KS_DHT_PULSE_EXPIRATIONS 10
|
|
|
|
#define KS_DHT_NODEID_SIZE 20
|
|
|
|
#define KS_DHT_MESSAGE_TRANSACTIONID_MAX_SIZE 20
|
|
#define KS_DHT_MESSAGE_TYPE_MAX_SIZE 20
|
|
#define KS_DHT_MESSAGE_QUERY_MAX_SIZE 20
|
|
#define KS_DHT_MESSAGE_ERROR_MAX_SIZE 256
|
|
|
|
#define KS_DHT_TRANSACTION_EXPIRATION_DELAY 30
|
|
#define KS_DHT_SEARCH_EXPIRATION 10
|
|
|
|
#define KS_DHT_STORAGEITEM_KEY_SIZE crypto_sign_PUBLICKEYBYTES
|
|
#define KS_DHT_STORAGEITEM_SALT_MAX_SIZE 64
|
|
#define KS_DHT_STORAGEITEM_SIGNATURE_SIZE crypto_sign_BYTES
|
|
|
|
#define KS_DHT_TOKEN_SIZE SHA_DIGEST_LENGTH
|
|
#define KS_DHT_TOKENSECRET_EXPIRATION 300
|
|
|
|
typedef struct ks_dht_s ks_dht_t;
|
|
typedef struct ks_dht_nodeid_s ks_dht_nodeid_t;
|
|
typedef struct ks_dht_token_s ks_dht_token_t;
|
|
typedef struct ks_dht_storageitem_key_s ks_dht_storageitem_key_t;
|
|
typedef struct ks_dht_storageitem_signature_s ks_dht_storageitem_signature_t;
|
|
typedef struct ks_dht_message_s ks_dht_message_t;
|
|
typedef struct ks_dht_endpoint_s ks_dht_endpoint_t;
|
|
typedef struct ks_dht_transaction_s ks_dht_transaction_t;
|
|
typedef struct ks_dht_node_s ks_dht_node_t;
|
|
typedef struct ks_dhtrt_routetable_s ks_dhtrt_routetable_t;
|
|
typedef struct ks_dhtrt_querynodes_s ks_dhtrt_querynodes_t;
|
|
typedef struct ks_dht_storageitem_s ks_dht_storageitem_t;
|
|
|
|
|
|
typedef ks_status_t (*ks_dht_message_callback_t)(ks_dht_t *dht, ks_dht_message_t *message);
|
|
|
|
/**
|
|
* Note: This must remain a structure for casting from raw data
|
|
*/
|
|
struct ks_dht_nodeid_s {
|
|
uint8_t id[KS_DHT_NODEID_SIZE];
|
|
};
|
|
|
|
enum ipfamily { ifv4=AF_INET, ifv6=AF_INET6, ifboth=AF_INET+AF_INET6};
|
|
enum ks_dht_nodetype_t { ks_dht_remote_t=0x01,
|
|
ks_dht_local_t=0x02,
|
|
ks_dht_both_t=ks_dht_remote_t+ks_dht_local_t };
|
|
|
|
struct ks_dht_node_s {
|
|
ks_dht_nodeid_t nodeid;
|
|
ks_sockaddr_t addr;
|
|
enum ipfamily family; /* AF_INET or AF_INET6 */
|
|
enum ks_dht_nodetype_t type; /* local or remote */
|
|
ks_dhtrt_routetable_t* table;
|
|
};
|
|
|
|
struct ks_dhtrt_routetable_s {
|
|
void* internal;
|
|
ks_pool_t* pool;
|
|
ks_logger_t logger;
|
|
};
|
|
|
|
struct ks_dhtrt_querynodes_s {
|
|
ks_dht_nodeid_t nodeid; /* in: id to query */
|
|
enum ipfamily family; /* in: AF_INET or AF_INET6 or both */
|
|
enum ks_dht_nodetype_t type; /* remote, local, or both */
|
|
uint8_t max; /* in: maximum to return */
|
|
uint8_t count; /* out: number returned */
|
|
ks_dht_node_t* nodes[ KS_DHT_MESSAGE_QUERY_MAX_SIZE]; /* out: array of peers (ks_dht_node_t* nodes[incount]) */
|
|
};
|
|
|
|
struct ks_dht_token_s {
|
|
uint8_t token[KS_DHT_TOKEN_SIZE];
|
|
};
|
|
|
|
struct ks_dht_storageitem_key_s {
|
|
uint8_t key[KS_DHT_STORAGEITEM_KEY_SIZE];
|
|
};
|
|
|
|
struct ks_dht_storageitem_signature_s {
|
|
uint8_t sig[KS_DHT_STORAGEITEM_SIGNATURE_SIZE];
|
|
};
|
|
|
|
struct ks_dht_message_s {
|
|
ks_pool_t *pool;
|
|
ks_dht_endpoint_t *endpoint;
|
|
ks_sockaddr_t raddr;
|
|
struct bencode *data;
|
|
uint8_t transactionid[KS_DHT_MESSAGE_TRANSACTIONID_MAX_SIZE];
|
|
ks_size_t transactionid_length;
|
|
char type[KS_DHT_MESSAGE_TYPE_MAX_SIZE];
|
|
struct bencode *args;
|
|
};
|
|
|
|
struct ks_dht_endpoint_s {
|
|
ks_pool_t *pool;
|
|
ks_dht_nodeid_t nodeid;
|
|
ks_sockaddr_t addr;
|
|
ks_socket_t sock;
|
|
ks_dht_node_t *node;
|
|
};
|
|
|
|
struct ks_dht_transaction_s {
|
|
ks_pool_t *pool;
|
|
ks_sockaddr_t raddr;
|
|
uint32_t transactionid;
|
|
ks_dht_message_callback_t callback;
|
|
ks_time_t expiration;
|
|
ks_bool_t finished;
|
|
};
|
|
|
|
struct ks_dht_storageitem_s {
|
|
ks_pool_t *pool;
|
|
ks_dht_nodeid_t id;
|
|
|
|
struct bencode *v;
|
|
|
|
ks_bool_t mutable;
|
|
ks_dht_storageitem_key_t pk;
|
|
ks_dht_storageitem_key_t sk;
|
|
uint8_t salt[KS_DHT_STORAGEITEM_SALT_MAX_SIZE];
|
|
ks_size_t salt_length;
|
|
int64_t seq;
|
|
ks_dht_storageitem_signature_t sig;
|
|
};
|
|
|
|
struct ks_dht_s {
|
|
ks_pool_t *pool;
|
|
ks_bool_t pool_alloc;
|
|
|
|
ks_bool_t autoroute;
|
|
ks_port_t autoroute_port;
|
|
|
|
ks_hash_t *registry_type;
|
|
ks_hash_t *registry_query;
|
|
ks_hash_t *registry_error;
|
|
|
|
ks_bool_t bind_ipv4;
|
|
ks_bool_t bind_ipv6;
|
|
|
|
ks_dht_endpoint_t **endpoints;
|
|
int32_t endpoints_size;
|
|
ks_hash_t *endpoints_hash;
|
|
struct pollfd *endpoints_poll;
|
|
|
|
ks_time_t pulse_expirations;
|
|
|
|
ks_q_t *send_q;
|
|
ks_dht_message_t *send_q_unsent;
|
|
uint8_t recv_buffer[KS_DHT_RECV_BUFFER_SIZE];
|
|
ks_size_t recv_buffer_length;
|
|
|
|
volatile uint32_t transactionid_next;
|
|
ks_hash_t *transactions_hash;
|
|
|
|
ks_dhtrt_routetable_t *rt_ipv4;
|
|
ks_dhtrt_routetable_t *rt_ipv6;
|
|
|
|
volatile uint32_t token_secret_current;
|
|
volatile uint32_t token_secret_previous;
|
|
ks_time_t token_secret_expiration;
|
|
ks_hash_t *storage_hash;
|
|
};
|
|
|
|
/**
|
|
* Allocator function for ks_dht_t.
|
|
* Should be used when a ks_dht_t is allocated on the heap, and may provide an external memory pool or allocate one internally.
|
|
* @param dht dereferenced out pointer to the allocated dht instance
|
|
* @param pool pointer to the memory pool used by the dht instance, may be NULL to create a new pool internally
|
|
* @param The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_alloc(ks_dht_t **dht, ks_pool_t *pool);
|
|
|
|
/**
|
|
* Preallocator function for ks_dht_t.
|
|
* Should be used when a ks_dht_t is preallocated on the stack or within another structure, and must provide an external memory pool.
|
|
* @param dht pointer to the dht instance
|
|
* @param pool pointer to the memory pool used by the dht instance
|
|
*/
|
|
KS_DECLARE(void) ks_dht_prealloc(ks_dht_t *dht, ks_pool_t *pool);
|
|
|
|
/**
|
|
* Deallocator function for ks_dht_t.
|
|
* Must be used when a ks_dht_t is allocated using ks_dht_alloc, will also destroy memory pool if it was created internally.
|
|
* @param dht dereferenced in/out pointer to the dht instance, NULL upon return
|
|
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
|
* @see ks_dht_deinit
|
|
* @see ks_pool_free
|
|
* @see ks_pool_close
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_free(ks_dht_t **dht);
|
|
|
|
/**
|
|
* Constructor function for ks_dht_t.
|
|
* Must be used regardless of how ks_dht_t is allocated, will allocate and initialize internal state including registration of message handlers.
|
|
* @param dht pointer to the dht instance
|
|
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
|
* @see ks_hash_create
|
|
* @see ks_dht_register_type
|
|
* @see ks_q_create
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_init(ks_dht_t *dht);
|
|
|
|
/**
|
|
* Destructor function for ks_dht_t.
|
|
* Must be used regardless of how ks_dht_t is allocated, will deallocate and deinitialize internal state.
|
|
* @param dht pointer to the dht instance
|
|
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
|
* @see ks_dht_storageitem_deinit
|
|
* @see ks_dht_storageitem_free
|
|
* @see ks_hash_destroy
|
|
* @see ks_dht_message_deinit
|
|
* @see ks_dht_message_free
|
|
* @see ks_q_destroy
|
|
* @see ks_dht_endpoint_deinit
|
|
* @see ks_dht_endpoint_free
|
|
* @see ks_pool_free
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_deinit(ks_dht_t *dht);
|
|
|
|
/**
|
|
* Enable or disable (default) autorouting support.
|
|
* When enabled, autorouting will allow sending to remote addresses on interfaces which are not yet bound.
|
|
* The address will be bound with the provided autoroute port when this occurs.
|
|
* @param dht pointer to the dht instance
|
|
* @param autoroute enable or disable autorouting
|
|
* @param port when enabling autorouting this port will be used to bind new addresses, may be 0 to use the default DHT port
|
|
*/
|
|
KS_DECLARE(void) ks_dht_autoroute(ks_dht_t *dht, ks_bool_t autoroute, ks_port_t port);
|
|
|
|
/**
|
|
* Register a callback for a specific message type.
|
|
* Will overwrite any duplicate handlers.
|
|
* @param dht pointer to the dht instance
|
|
* @param value string of the type text under the 'y' key of a message
|
|
* @param callback the callback to be called when a message matches
|
|
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_register_type(ks_dht_t *dht, const char *value, ks_dht_message_callback_t callback);
|
|
|
|
/**
|
|
* Register a callback for a specific message query.
|
|
* Will overwrite any duplicate handlers.
|
|
* @param dht pointer to the dht instance
|
|
* @param value string of the type text under the 'q' key of a message
|
|
* @param callback the callback to be called when a message matches
|
|
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_register_query(ks_dht_t *dht, const char *value, ks_dht_message_callback_t callback);
|
|
|
|
/**
|
|
* Register a callback for a specific message error.
|
|
* Will overwrite any duplicate handlers.
|
|
* @param dht pointer to the dht instance
|
|
* @param value string of the errorcode under the first item of the 'e' key of a message
|
|
* @param callback the callback to be called when a message matches
|
|
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_register_error(ks_dht_t *dht, const char *value, ks_dht_message_callback_t callback);
|
|
|
|
/**
|
|
* Bind a local address and port for receiving UDP datagrams.
|
|
* @param dht pointer to the dht instance
|
|
* @param nodeid pointer to a nodeid for this endpoint, may be NULL to generate one randomly
|
|
* @param addr pointer to the remote address information
|
|
* @param dereferenced out pointer to the allocated endpoint, may be NULL to ignore endpoint
|
|
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL, ...
|
|
* @see ks_socket_option
|
|
* @see ks_addr_bind
|
|
* @see ks_dht_endpoint_alloc
|
|
* @see ks_dht_endpoint_init
|
|
* @see ks_hash_insert
|
|
* @see ks_dhtrt_initroute
|
|
* @see ks_dhtrt_create_node
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_bind(ks_dht_t *dht, const ks_dht_nodeid_t *nodeid, const ks_sockaddr_t *addr, ks_dht_endpoint_t **endpoint);
|
|
|
|
/**
|
|
* Pulse the internals of dht.
|
|
* Handles receiving UDP datagrams, dispatching processing, handles expirations, throttled message sending, route table pulsing, etc.
|
|
* @param dht pointer to the dht instance
|
|
* @param timeout timeout value used when polling sockets for new UDP datagrams
|
|
*/
|
|
KS_DECLARE(void) ks_dht_pulse(ks_dht_t *dht, int32_t timeout);
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_alloc(ks_dht_message_t **message, ks_pool_t *pool);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_prealloc(ks_dht_message_t *message, ks_pool_t *pool);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_free(ks_dht_message_t **message);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_init(ks_dht_message_t *message, ks_dht_endpoint_t *ep, ks_sockaddr_t *raddr, ks_bool_t alloc_data);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_deinit(ks_dht_message_t *message);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_parse(ks_dht_message_t *message, const uint8_t *buffer, ks_size_t buffer_length);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_query(ks_dht_message_t *message,
|
|
uint32_t transactionid,
|
|
const char *query,
|
|
struct bencode **args);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_response(ks_dht_message_t *message,
|
|
uint8_t *transactionid,
|
|
ks_size_t transactionid_length,
|
|
struct bencode **args);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_message_error(ks_dht_message_t *message,
|
|
uint8_t *transactionid,
|
|
ks_size_t transactionid_length,
|
|
struct bencode **args);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_transaction_alloc(ks_dht_transaction_t **transaction, ks_pool_t *pool);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_transaction_prealloc(ks_dht_transaction_t *transaction, ks_pool_t *pool);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_transaction_free(ks_dht_transaction_t **transaction);
|
|
|
|
KS_DECLARE(ks_status_t) ks_dht_transaction_init(ks_dht_transaction_t *transaction,
|
|
ks_sockaddr_t *raddr,
|
|
uint32_t transactionid,
|
|
ks_dht_message_callback_t callback);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dht_transaction_deinit(ks_dht_transaction_t *transaction);
|
|
|
|
|
|
|
|
/**
|
|
* route table methods
|
|
*
|
|
*/
|
|
KS_DECLARE(ks_status_t) ks_dhtrt_initroute(ks_dhtrt_routetable_t **tableP, ks_pool_t *pool);
|
|
KS_DECLARE(void) ks_dhtrt_deinitroute(ks_dhtrt_routetable_t **table);
|
|
|
|
KS_DECLARE(ks_status_t) ks_dhtrt_create_node(ks_dhtrt_routetable_t* table,
|
|
ks_dht_nodeid_t nodeid,
|
|
enum ks_dht_nodetype_t type,
|
|
char* ip, unsigned short port,
|
|
ks_dht_node_t** node);
|
|
|
|
KS_DECLARE(ks_status_t) ks_dhtrt_delete_node(ks_dhtrt_routetable_t* table, ks_dht_node_t* node);
|
|
|
|
KS_DECLARE(ks_status_t) ks_dhtrt_touch_node(ks_dhtrt_routetable_t* table, ks_dht_nodeid_t nodeid);
|
|
KS_DECLARE(ks_status_t) ks_dhtrt_expire_node(ks_dhtrt_routetable_t* table, ks_dht_nodeid_t nodeid);
|
|
|
|
KS_DECLARE(uint8_t) ks_dhtrt_findclosest_nodes(ks_dhtrt_routetable_t* table, ks_dhtrt_querynodes_t* query);
|
|
KS_DECLARE(ks_dht_node_t*) ks_dhtrt_find_node(ks_dhtrt_routetable_t* table, ks_dht_nodeid_t id);
|
|
|
|
KS_DECLARE(void) ks_dhtrt_process_table(ks_dhtrt_routetable_t* table);
|
|
|
|
/* debugging aids */
|
|
KS_DECLARE(void) ks_dhtrt_dump(ks_dhtrt_routetable_t* table, int level);
|
|
|
|
|
|
KS_END_EXTERN_C
|
|
|
|
#endif /* KS_DHT_H */
|
|
|
|
/* For Emacs:
|
|
* Local Variables:
|
|
* mode:c
|
|
* indent-tabs-mode:t
|
|
* tab-width:4
|
|
* c-basic-offset:4
|
|
* End:
|
|
* For VIM:
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
|
*/
|