mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-30 15:14:17 +00:00
FS-10165: Removed dependancy and autoconf check for libsodium from libks. Moved DHT, bencode, and related tests into libblade. Still requires refactoring in blade from ks_* to blade_*.
This commit is contained in:
1 parent
716f02897a
commit
5cff01b2a8
28 files changed
+48
-59
No files matched your search
@@ -131,12 +131,10 @@ KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set);
|
||||
#include "ks_time.h"
|
||||
#include "ks_socket.h"
|
||||
#include "ks_dso.h"
|
||||
//#include "ks_dht.h"
|
||||
#include "ks_utp.h"
|
||||
#include "simclist.h"
|
||||
#include "ks_ssl.h"
|
||||
#include "kws.h"
|
||||
#include "ks_bencode.h"
|
||||
#include "ks_rng.h"
|
||||
#include "ks_acl.h"
|
||||
#include "ks_base64.h"
|
||||
|
||||
@@ -1,730 +0,0 @@
|
||||
/*
|
||||
* libbencodetools
|
||||
*
|
||||
* Written by Heikki Orsila <heikki.orsila@iki.fi> and
|
||||
* Janne Kulmala <janne.t.kulmala@tut.fi> in 2011.
|
||||
*/
|
||||
|
||||
#ifndef TYPEVALIDATOR_BENCODE_H
|
||||
#define TYPEVALIDATOR_BENCODE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Used to verify format strings in compile time */
|
||||
#ifdef __GNUC__
|
||||
#define BEN_CHECK_FORMAT(...) __attribute__ ((format( __VA_ARGS__ )))
|
||||
#else
|
||||
#define BEN_CHECK_FORMAT(args)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
BENCODE_BOOL = 1,
|
||||
BENCODE_DICT,
|
||||
BENCODE_INT,
|
||||
BENCODE_LIST,
|
||||
BENCODE_STR,
|
||||
BENCODE_USER,
|
||||
};
|
||||
|
||||
enum {
|
||||
BEN_OK = 0, /* No errors. Set to zero. Non-zero implies an error. */
|
||||
BEN_INVALID, /* Invalid data was given to decoder */
|
||||
BEN_INSUFFICIENT, /* Insufficient amount of data for decoding */
|
||||
BEN_NO_MEMORY, /* Memory allocation failed */
|
||||
BEN_MISMATCH, /* A given structure did not match unpack format */
|
||||
};
|
||||
|
||||
struct bencode {
|
||||
char type;
|
||||
};
|
||||
|
||||
struct bencode_bool {
|
||||
char type;
|
||||
char b;
|
||||
};
|
||||
|
||||
struct bencode_dict_node {
|
||||
long long hash;
|
||||
struct bencode *key;
|
||||
struct bencode *value;
|
||||
size_t next;
|
||||
};
|
||||
|
||||
struct bencode_dict {
|
||||
char type;
|
||||
char shared; /* non-zero means that the internal data is shared with
|
||||
other instances and should not be freed */
|
||||
size_t n;
|
||||
size_t alloc;
|
||||
size_t *buckets;
|
||||
struct bencode_dict_node *nodes;
|
||||
};
|
||||
|
||||
struct bencode_int {
|
||||
char type;
|
||||
long long ll;
|
||||
};
|
||||
|
||||
struct bencode_list {
|
||||
char type;
|
||||
char shared; /* non-zero means that the internal data is shared with
|
||||
other instances and should not be freed */
|
||||
size_t n;
|
||||
size_t alloc;
|
||||
struct bencode **values;
|
||||
};
|
||||
|
||||
struct bencode_str {
|
||||
char type;
|
||||
size_t len;
|
||||
char *s;
|
||||
};
|
||||
|
||||
struct ben_decode_ctx;
|
||||
struct ben_encode_ctx;
|
||||
|
||||
struct bencode_type {
|
||||
size_t size;
|
||||
struct bencode *(*decode) (struct ben_decode_ctx *ctx);
|
||||
int (*encode) (struct ben_encode_ctx *ctx, const struct bencode *b);
|
||||
size_t (*get_size) (const struct bencode *b);
|
||||
void (*free) (struct bencode *b);
|
||||
int (*cmp) (const struct bencode *a, const struct bencode *b);
|
||||
};
|
||||
|
||||
struct bencode_user {
|
||||
char type;
|
||||
struct bencode_type *info;
|
||||
};
|
||||
|
||||
struct bencode_error {
|
||||
int error; /* 0 if no errors */
|
||||
int line; /* Error line: 0 is the first line */
|
||||
size_t off; /* Error offset in bytes from the start */
|
||||
};
|
||||
|
||||
/* Allocate an instance of a user-defined type */
|
||||
void *ben_alloc_user(struct bencode_type *type);
|
||||
|
||||
/*
|
||||
* Try to set capacity of a list or a dict to 'n' objects.
|
||||
* The function does nothing if 'n' is less than or equal to the number of
|
||||
* objects in 'b'. That is, nothing happens if n <= ben_{dict|list}_len(b).
|
||||
*
|
||||
* This function is used only for advice. The implementation need not obey it.
|
||||
*
|
||||
* The function returns 0 if the new capacity is used, otherwise -1.
|
||||
*
|
||||
* Note: This can be used to make construction of lists and dicts
|
||||
* more efficient when the number of inserted items is known in advance.
|
||||
*/
|
||||
int ben_allocate(struct bencode *b, size_t n);
|
||||
|
||||
/*
|
||||
* Returns an identical but a separate copy of structure b. Returns NULL if
|
||||
* there is no memory to make a copy. The copy is made recursively.
|
||||
*/
|
||||
struct bencode *ben_clone(const struct bencode *b);
|
||||
|
||||
/*
|
||||
* Returns a weak reference copy of structure b. Only a minimum amount of
|
||||
* data is copied because the returned structure references to the same
|
||||
* internal data as the original structure. As a result, the original
|
||||
* structure must remain valid until the copy is destroyed.
|
||||
*
|
||||
* This function is used for optimization for special cases.
|
||||
*/
|
||||
struct bencode *ben_shared_clone(const struct bencode *b);
|
||||
|
||||
/*
|
||||
* ben_cmp() is similar to strcmp(). It compares integers, strings and lists
|
||||
* similar to Python. User-defined types can be also compared.
|
||||
* Note: an integer is always less than a string.
|
||||
*
|
||||
* ben_cmp(a, b) returns a negative value if "a < b", 0 if "a == b",
|
||||
* or a positive value if "a > b".
|
||||
*
|
||||
* Algorithm for comparing dictionaries is:
|
||||
* If 'a' and 'b' have different number of keys or keys have different values,
|
||||
* a non-zero value is returned. Otherwise, they have the exact same keys
|
||||
* and comparison is done in ben_cmp() order of keys. The value for each key
|
||||
* is compared, and the first inequal value (ben_cmp() != 0) defines the
|
||||
* return value of the comparison.
|
||||
*
|
||||
* Note: recursive dictionaries in depth have the same issues.
|
||||
*/
|
||||
int ben_cmp(const struct bencode *a, const struct bencode *b);
|
||||
|
||||
/* Same as ben_cmp(), but the second argument is a C string */
|
||||
int ben_cmp_with_str(const struct bencode *a, const char *s);
|
||||
|
||||
/*
|
||||
* Comparison function suitable for qsort(). Uses ben_cmp(), so this can be
|
||||
* used to order both integer and string arrays.
|
||||
*/
|
||||
int ben_cmp_qsort(const void *a, const void *b);
|
||||
|
||||
/*
|
||||
* Decode 'data' with 'len' bytes of data. Returns NULL on error.
|
||||
* The encoded data must be exactly 'len' bytes (not less), otherwise NULL
|
||||
* is returned. ben_decode2() function supports partial decoding ('len' is
|
||||
* larger than actual decoded message) and gives more accurate error reports.
|
||||
*/
|
||||
struct bencode *ben_decode(const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Same as ben_decode(), but allows one to set start offset for decoding with
|
||||
* 'off' and reports errors more accurately.
|
||||
*
|
||||
* '*off' must point to decoding start offset inside 'data'.
|
||||
* If decoding is successful, '*off' is updated to point to the next byte
|
||||
* after the decoded message.
|
||||
*
|
||||
* If 'error != NULL', it is updated according to the success and error of
|
||||
* the decoding. BEN_OK is success, BEN_INVALID means invalid data.
|
||||
* BEN_INSUFFICIENT means data is invalid but could be valid if more data
|
||||
* was given for decoding. BEN_NO_MEMORY means decoding ran out of memory.
|
||||
*/
|
||||
struct bencode *ben_decode2(const void *data, size_t len, size_t *off, int *error);
|
||||
|
||||
/*
|
||||
* Same as ben_decode2(), but allows one to define user types.
|
||||
*/
|
||||
struct bencode *ben_decode3(const void *data, size_t len, size_t *off, int *error, struct bencode_type *types[128]);
|
||||
|
||||
/*
|
||||
* Same as ben_decode(), but decodes data encoded with ben_print(). This is
|
||||
* whitespace tolerant, so intended Python syntax can also be read.
|
||||
* The decoder skips comments that begin with a '#' character.
|
||||
* The comment starts from '#' character and ends at the end of the same line.
|
||||
*
|
||||
* For example, this can be used to read in config files written as a Python
|
||||
* dictionary.
|
||||
*
|
||||
* ben_decode_printed2() fills information about the error in
|
||||
* struct bencode_error.
|
||||
* error->error is 0 on success, otherwise it is an error code
|
||||
* (see ben_decode2()).
|
||||
* error->line is the line number where error occured.
|
||||
* error->off is the byte offset of error (approximation).
|
||||
*/
|
||||
struct bencode *ben_decode_printed(const void *data, size_t len);
|
||||
struct bencode *ben_decode_printed2(const void *data, size_t len, size_t *off, struct bencode_error *error);
|
||||
|
||||
/* Get the serialization size of bencode structure 'b' */
|
||||
size_t ben_encoded_size(const struct bencode *b);
|
||||
|
||||
/* encode 'b'. Return encoded data with a pointer, and length in '*len' */
|
||||
void *ben_encode(size_t *len, const struct bencode *b);
|
||||
|
||||
/*
|
||||
* encode 'b' into 'data' buffer with at most 'maxlen' bytes.
|
||||
* Returns the size of encoded data.
|
||||
*/
|
||||
size_t ben_encode2(char *data, size_t maxlen, const struct bencode *b);
|
||||
|
||||
/*
|
||||
* You must use ben_free() for all allocated bencode structures after use.
|
||||
* If b == NULL, ben_free does nothing.
|
||||
*
|
||||
* ben_free() frees all the objects contained within the bencoded structure.
|
||||
* It recursively iterates over lists and dictionaries and frees objects.
|
||||
*/
|
||||
void ben_free(struct bencode *b);
|
||||
|
||||
long long ben_str_hash(const struct bencode *b);
|
||||
long long ben_int_hash(const struct bencode *b);
|
||||
long long ben_hash(const struct bencode *b);
|
||||
|
||||
/* Create a string from binary data with len bytes */
|
||||
struct bencode *ben_blob(const void *data, size_t len);
|
||||
|
||||
/* Create a boolean from integer */
|
||||
struct bencode *ben_bool(int b);
|
||||
|
||||
/* Create an empty dictionary */
|
||||
struct bencode *ben_dict(void);
|
||||
|
||||
/*
|
||||
* Try to locate 'key' in dictionary. Returns the associated value, if found.
|
||||
* Returns NULL if the key does not exist.
|
||||
*/
|
||||
struct bencode *ben_dict_get(const struct bencode *d, const struct bencode *key);
|
||||
|
||||
struct bencode *ben_dict_get_by_str(const struct bencode *d, const char *key);
|
||||
struct bencode *ben_dict_get_by_int(const struct bencode *d, long long key);
|
||||
|
||||
struct bencode_keyvalue {
|
||||
struct bencode *key;
|
||||
struct bencode *value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns an array of key-value pairs in key order as defined by ben_cmp().
|
||||
* Array elements are struct bencode_keyvalue members. Returns NULL if
|
||||
* the array can not be allocated or the bencode object is not a dictionary.
|
||||
* The returned array must be freed by using free(). The length of the
|
||||
* array can be determined with ben_dict_len(d).
|
||||
*
|
||||
* Warning: key and value pointers in the array are pointers to exact same
|
||||
* objects in the dictionary. Therefore, the dictionary and its key-values
|
||||
* must exist while the same keys and values are accessed from the array.
|
||||
*/
|
||||
struct bencode_keyvalue *ben_dict_ordered_items(const struct bencode *d);
|
||||
|
||||
/*
|
||||
* Try to locate 'key' in dictionary. Returns the associated value, if found.
|
||||
* The value must be later freed with ben_free(). Returns NULL if the key
|
||||
* does not exist.
|
||||
*/
|
||||
struct bencode *ben_dict_pop(struct bencode *d, const struct bencode *key);
|
||||
|
||||
struct bencode *ben_dict_pop_by_str(struct bencode *d, const char *key);
|
||||
struct bencode *ben_dict_pop_by_int(struct bencode *d, long long key);
|
||||
|
||||
/*
|
||||
* Set 'key' in dictionary to be 'value'. An old value exists for the key
|
||||
* is freed if it exists. 'key' and 'value' are owned by the dictionary
|
||||
* after a successful call (one may not call ben_free() for 'key' or
|
||||
* 'value'). One may free 'key' and 'value' if the call is unsuccessful.
|
||||
*
|
||||
* Returns 0 on success, -1 on failure (no memory).
|
||||
*/
|
||||
int ben_dict_set(struct bencode *d, struct bencode *key, struct bencode *value);
|
||||
|
||||
/* Same as ben_dict_set(), but the key is a C string */
|
||||
int ben_dict_set_by_str(struct bencode *d, const char *key, struct bencode *value);
|
||||
|
||||
/* Same as ben_dict_set(), but the key and value are C strings */
|
||||
int ben_dict_set_str_by_str(struct bencode *d, const char *key, const char *value);
|
||||
|
||||
struct bencode *ben_int(long long ll);
|
||||
|
||||
/* Create an empty list */
|
||||
struct bencode *ben_list(void);
|
||||
|
||||
/*
|
||||
* Append 'b' to 'list'. Returns 0 on success, -1 on failure (no memory).
|
||||
* One may not call ben_free(b) after a successful call, because the list owns
|
||||
* the object 'b'.
|
||||
*/
|
||||
int ben_list_append(struct bencode *list, struct bencode *b);
|
||||
|
||||
int ben_list_append_str(struct bencode *list, const char *s);
|
||||
int ben_list_append_int(struct bencode *list, long long ll);
|
||||
|
||||
/* Remove and return value at position 'pos' in list */
|
||||
struct bencode *ben_list_pop(struct bencode *list, size_t pos);
|
||||
|
||||
/*
|
||||
* Returns a Python formatted C string representation of 'b' on success,
|
||||
* NULL on failure. The returned string should be freed with free().
|
||||
*
|
||||
* Note: The string is terminated with '\0'. All instances of '\0' bytes in
|
||||
* the bencoded data are escaped so that there is only one '\0' byte
|
||||
* in the generated string at the end.
|
||||
*/
|
||||
char *ben_print(const struct bencode *b);
|
||||
|
||||
/* Create a string from C string (note bencode string may contain '\0'. */
|
||||
struct bencode *ben_str(const char *s);
|
||||
|
||||
/* Return a human readable explanation of error returned with ben_decode2() */
|
||||
const char *ben_strerror(int error);
|
||||
|
||||
/*
|
||||
* Unpack a Bencoded structure similar to scanf(). Takes a format string and
|
||||
* a list of pointers as variable arguments. The given b structure is checked
|
||||
* against the format and values are unpacked using the given specifiers.
|
||||
* A specifier begins with a percent (%) that follows a string of specifier
|
||||
* characters documented below.
|
||||
* The syntax is similar to Python format for recursive data structures, and
|
||||
* consists of tokens {, }, [, ] with any number of spaces between them.
|
||||
* The keys of a dictionary are given as literal strings or integers and
|
||||
* matched against the keys of the Bencoded structure.
|
||||
*
|
||||
* Unpack modifiers:
|
||||
* l The integer is of type long or unsigned long, and the type of the
|
||||
* argument is expected to be long * or unsigned long *.
|
||||
* ll The integer is a long long or an unsigned long long, and the
|
||||
* argument is long long * or unsigned long long *.
|
||||
* L Same as ll.
|
||||
* q Same as ll.
|
||||
*
|
||||
* Unpack specifiers:
|
||||
* %ps The Bencode value must be a string and a pointer to a string
|
||||
* (char **) is expected to be given as arguments. Note, returns a
|
||||
* reference to the internal string buffer. The returned memory should
|
||||
* not be freed and it has the same life time as the Bencode string.
|
||||
*
|
||||
* %pb Takes any structure and writes a pointer given as an argument.
|
||||
* The argument is expected to be "struct bencode **". Note, returns a
|
||||
* reference to the value inside the structure passed to ben_unpack().
|
||||
* The returned memory should not be freed and it has the same life
|
||||
* time as the original structure.
|
||||
*
|
||||
* %d The bencode value is expected to be a (signed) integer. The
|
||||
* preceeding conversion modifiers define the type of the given
|
||||
* pointer.
|
||||
|
||||
* %u The bencode value is expected to be an unsigned integer. The
|
||||
* preceeding conversion modifiers define the type of the given
|
||||
* pointer.
|
||||
*/
|
||||
int ben_unpack(const struct bencode *b, const char *fmt, ...)
|
||||
BEN_CHECK_FORMAT(scanf, 2, 3);
|
||||
|
||||
int ben_unpack2(const struct bencode *b, size_t *off, struct bencode_error *error, const char *fmt, ...)
|
||||
BEN_CHECK_FORMAT(scanf, 4, 5);
|
||||
|
||||
/*
|
||||
* Pack a Bencoded structure similar to printf(). Takes a format string and
|
||||
* a list of values as variable arguments.
|
||||
* Works similarly to ben_decode_printed(), but allows the string to values
|
||||
* specifiers which are replaced with values given as arguments.
|
||||
* A specifier begins with a percent (%) that follows a string of specifier
|
||||
* characters documented below.
|
||||
*
|
||||
* Value modifiers:
|
||||
* l The integer is of type long or unsigned long.
|
||||
* ll The integer is a long long or an unsigned long long.
|
||||
* L Same as ll.
|
||||
* q Same as ll.
|
||||
*
|
||||
* Value specifiers:
|
||||
* %s A string pointer (char *) expected to be given as argument. A new
|
||||
* Bencode string is constructed from the given string.
|
||||
*
|
||||
* %pb A Bencode structure (struct bencode *) is expected to be given as
|
||||
* argument. Note, takes ownership of the structure, even when an
|
||||
* error is returned.
|
||||
*
|
||||
* %d Constructs a new integer from the given (signed) integer. The
|
||||
* preceeding conversion modifiers define the type of the value.
|
||||
*
|
||||
* %u Constructs a new integer from the given unsigned integer. The
|
||||
* preceeding conversion modifiers define the type of the value.
|
||||
*/
|
||||
struct bencode *ben_pack(const char *fmt, ...)
|
||||
BEN_CHECK_FORMAT(printf, 1, 2);
|
||||
|
||||
/* ben_is_bool() returns 1 iff b is a boolean, 0 otherwise */
|
||||
static inline int ben_is_bool(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_BOOL;
|
||||
}
|
||||
static inline int ben_is_dict(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_DICT;
|
||||
}
|
||||
static inline int ben_is_int(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_INT;
|
||||
}
|
||||
static inline int ben_is_list(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_LIST;
|
||||
}
|
||||
static inline int ben_is_str(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_STR;
|
||||
}
|
||||
static inline int ben_is_user(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_USER;
|
||||
}
|
||||
|
||||
/*
|
||||
* ben_bool_const_cast(b) returns "(const struct bencode_bool *) b" if the
|
||||
* underlying object is a boolean, NULL otherwise.
|
||||
*/
|
||||
static inline const struct bencode_bool *ben_bool_const_cast(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_BOOL ? ((const struct bencode_bool *) b) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ben_bool_cast(b) returns "(struct bencode_bool *) b" if the
|
||||
* underlying object is a boolean, NULL otherwise.
|
||||
*/
|
||||
static inline struct bencode_bool *ben_bool_cast(struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_BOOL ? ((struct bencode_bool *) b) : NULL;
|
||||
}
|
||||
|
||||
static inline const struct bencode_dict *ben_dict_const_cast(const struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_DICT ? ((const struct bencode_dict *) b) : NULL;
|
||||
}
|
||||
static inline struct bencode_dict *ben_dict_cast(struct bencode *b)
|
||||
{
|
||||
return b->type == BENCODE_DICT ? ((struct bencode_dict *) b) : NULL;
|
||||
}
|
||||
|
||||
static inline const struct bencode_int *ben_int_const_cast(const struct bencode *i)
|
||||
{
|
||||
return i->type == BENCODE_INT ? ((const struct bencode_int *) i) : NULL;
|
||||
}
|
||||
static inline struct bencode_int *ben_int_cast(struct bencode *i)
|
||||
{
|
||||
return i->type == BENCODE_INT ? ((struct bencode_int *) i) : NULL;
|
||||
}
|
||||
|
||||
static inline const struct bencode_list *ben_list_const_cast(const struct bencode *list)
|
||||
{
|
||||
return list->type == BENCODE_LIST ? ((const struct bencode_list *) list) : NULL;
|
||||
}
|
||||
static inline struct bencode_list *ben_list_cast(struct bencode *list)
|
||||
{
|
||||
return list->type == BENCODE_LIST ? ((struct bencode_list *) list) : NULL;
|
||||
}
|
||||
|
||||
static inline const struct bencode_str *ben_str_const_cast(const struct bencode *str)
|
||||
{
|
||||
return str->type == BENCODE_STR ? ((const struct bencode_str *) str) : NULL;
|
||||
}
|
||||
static inline struct bencode_str *ben_str_cast(struct bencode *str)
|
||||
{
|
||||
return str->type == BENCODE_STR ? ((struct bencode_str *) str) : NULL;
|
||||
}
|
||||
|
||||
static inline const struct bencode_user *ben_user_const_cast(const struct bencode *user)
|
||||
{
|
||||
return user->type == BENCODE_USER ? ((const struct bencode_user *) user) : NULL;
|
||||
}
|
||||
static inline struct bencode_user *ben_user_cast(struct bencode *user)
|
||||
{
|
||||
return user->type == BENCODE_USER ? ((struct bencode_user *) user) : NULL;
|
||||
}
|
||||
|
||||
static inline int ben_is_user_type(const struct bencode *b, struct bencode_type *type)
|
||||
{
|
||||
return b->type == BENCODE_USER ? ((const struct bencode_user *) b)->info == type : 0;
|
||||
}
|
||||
|
||||
static inline const void *ben_user_type_const_cast(const struct bencode *b, struct bencode_type *type)
|
||||
{
|
||||
return (b->type == BENCODE_USER && ((const struct bencode_user *) b)->info == type) ? b : NULL;
|
||||
}
|
||||
static inline void *ben_user_type_cast(struct bencode *b, struct bencode_type *type)
|
||||
{
|
||||
return (b->type == BENCODE_USER && ((const struct bencode_user *) b)->info == type) ? b : NULL;
|
||||
}
|
||||
|
||||
/* Return the number of keys in a dictionary 'b' */
|
||||
static inline size_t ben_dict_len(const struct bencode *b)
|
||||
{
|
||||
return ben_dict_const_cast(b)->n;
|
||||
}
|
||||
|
||||
/* Return the number of items in a list 'b' */
|
||||
static inline size_t ben_list_len(const struct bencode *b)
|
||||
{
|
||||
return ben_list_const_cast(b)->n;
|
||||
}
|
||||
|
||||
/* ben_list_get(list, i) returns object at position i in list */
|
||||
static inline struct bencode *ben_list_get(const struct bencode *list, size_t i)
|
||||
{
|
||||
const struct bencode_list *l = ben_list_const_cast(list);
|
||||
if (i >= l->n) {
|
||||
fprintf(stderr, "bencode: List index out of bounds\n");
|
||||
abort();
|
||||
}
|
||||
return l->values[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* ben_list_set(list, i, b) sets object b to list at position i.
|
||||
* The old value at position i is freed.
|
||||
* The program aborts if position i is out of bounds.
|
||||
*/
|
||||
void ben_list_set(struct bencode *list, size_t i, struct bencode *b);
|
||||
|
||||
/* Return the number of bytes in a string 'b' */
|
||||
static inline size_t ben_str_len(const struct bencode *b)
|
||||
{
|
||||
return ben_str_const_cast(b)->len;
|
||||
}
|
||||
|
||||
/* Return boolean value (0 or 1) of 'b' */
|
||||
static inline int ben_bool_val(const struct bencode *b)
|
||||
{
|
||||
return ben_bool_const_cast(b)->b ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Return integer value of 'b' */
|
||||
static inline long long ben_int_val(const struct bencode *b)
|
||||
{
|
||||
return ben_int_const_cast(b)->ll;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the string is always zero terminated. Also, the string may
|
||||
* contain more than one zero.
|
||||
* bencode strings are not compatible with C strings.
|
||||
*/
|
||||
static inline const char *ben_str_val(const struct bencode *b)
|
||||
{
|
||||
return ben_str_const_cast(b)->s;
|
||||
}
|
||||
|
||||
/*
|
||||
* ben_list_for_each() is an iterator macro for bencoded lists.
|
||||
*
|
||||
* Note, it is not allowed to change the list while iterating except by
|
||||
* using ben_list_pop_current().
|
||||
*
|
||||
* pos is a size_t.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* size_t pos;
|
||||
* struct bencode *list = xxx;
|
||||
* struct bencode *value;
|
||||
* ben_list_for_each(value, pos, list) {
|
||||
* inspect(value);
|
||||
* }
|
||||
*/
|
||||
#define ben_list_for_each(value, pos, l) \
|
||||
for ((pos) = (size_t) 0; \
|
||||
(pos) < (ben_list_const_cast(l))->n && \
|
||||
((value) = ((const struct bencode_list *) (l))->values[(pos)]) != NULL ; \
|
||||
(pos)++)
|
||||
|
||||
/*
|
||||
* ben_list_pop_current() returns and removes the current item at 'pos'
|
||||
* while iterating the list with ben_list_for_each().
|
||||
* It can be used more than once per walk, but only once per item.
|
||||
* Example below:
|
||||
*
|
||||
* Filter out all items from list whose string value does not begin with "foo".
|
||||
*
|
||||
* ben_list_for_each(value, pos, list) {
|
||||
* if (strncmp(ben_str_val(value), "foo", 3) != 0)
|
||||
* ben_free(ben_list_pop_current(&pos, list));
|
||||
* }
|
||||
*/
|
||||
static inline struct bencode *ben_list_pop_current(struct bencode *list,
|
||||
size_t *pos)
|
||||
{
|
||||
struct bencode *value = ben_list_pop(list, *pos);
|
||||
(*pos)--;
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* ben_dict_for_each() is an iterator macro for bencoded dictionaries.
|
||||
*
|
||||
* Note, it is not allowed to change the dictionary while iterating except
|
||||
* by using ben_dict_pop_current().
|
||||
*
|
||||
* struct bencode *dict = ben_dict();
|
||||
* size_t pos;
|
||||
* struct bencode *key;
|
||||
* struct bencode *value;
|
||||
* ben_dict_set_str_by_str(dict, "foo", "bar");
|
||||
*
|
||||
* ben_dict_for_each(key, value, pos, dict) {
|
||||
* use(key, value);
|
||||
* }
|
||||
*
|
||||
* pos is a size_t.
|
||||
*/
|
||||
#define ben_dict_for_each(bkey, bvalue, pos, d) \
|
||||
for ((pos) = 0; \
|
||||
(pos) < (ben_dict_const_cast(d))->n && \
|
||||
((bkey) = ((const struct bencode_dict *) (d))->nodes[(pos)].key) != NULL && \
|
||||
((bvalue) = ((const struct bencode_dict *) (d))->nodes[(pos)].value) != NULL; \
|
||||
(pos)++)
|
||||
|
||||
/*
|
||||
* ben_dict_pop_current() deletes the current item at 'pos' while iterating
|
||||
* the dictionary with ben_dict_for_each(). It can be used more than once
|
||||
* per walk, but only once per item. Example below:
|
||||
*
|
||||
* Filter out all items from dictionary whose key does not begin with "foo".
|
||||
*
|
||||
* ben_dict_for_each(key, value, pos, dict) {
|
||||
* if (strncmp(ben_str_val(key), "foo", 3) != 0)
|
||||
* ben_free(ben_dict_pop_current(dict, &pos));
|
||||
* }
|
||||
*/
|
||||
struct bencode *ben_dict_pop_current(struct bencode *dict, size_t *pos);
|
||||
|
||||
/* Report an error while decoding. Returns NULL. */
|
||||
void *ben_insufficient_ptr(struct ben_decode_ctx *ctx);
|
||||
void *ben_invalid_ptr(struct ben_decode_ctx *ctx);
|
||||
void *ben_oom_ptr(struct ben_decode_ctx *ctx);
|
||||
|
||||
/*
|
||||
* Decode from the current position of 'ctx'.
|
||||
*
|
||||
* This function is used to implement decoders for user-defined types.
|
||||
*/
|
||||
struct bencode *ben_ctx_decode(struct ben_decode_ctx *ctx);
|
||||
|
||||
/*
|
||||
* Test whether the input of 'ctx' has at least n bytes left.
|
||||
* Returns 0 when there is enough bytes left and -1 when there isn't.
|
||||
*
|
||||
* This function is used to implement decoders for user-defined types.
|
||||
*/
|
||||
int ben_need_bytes(const struct ben_decode_ctx *ctx, size_t n);
|
||||
|
||||
/*
|
||||
* Returns the character in current position of 'ctx'.
|
||||
*
|
||||
* This function is used to implement decoders for user-defined types.
|
||||
*/
|
||||
char ben_current_char(const struct ben_decode_ctx *ctx);
|
||||
|
||||
/*
|
||||
* Get the next n bytes from input.
|
||||
* Returns pointer to the data or NULL when there aren't enough bytes left.
|
||||
*
|
||||
* This function is used to implement decoders for user-defined types.
|
||||
*/
|
||||
const char *ben_current_buf(const struct ben_decode_ctx *ctx, size_t n);
|
||||
|
||||
/*
|
||||
* Increments current position by n.
|
||||
*
|
||||
* This function is used to implement decoders for user-defined types.
|
||||
*/
|
||||
void ben_skip(struct ben_decode_ctx *ctx, size_t n);
|
||||
|
||||
/*
|
||||
* Encode to the output of 'ctx'. The size of the encoded data can be obtained
|
||||
* with ben_encoded_size().
|
||||
*
|
||||
* This function is used to implement encoders for user-defined types.
|
||||
*/
|
||||
int ben_ctx_encode(struct ben_encode_ctx *ctx, const struct bencode *b);
|
||||
|
||||
/*
|
||||
* Append one character to output of 'ctx'. The amount of bytes written to the
|
||||
* output must be the same as returned by get_size().
|
||||
*
|
||||
* This function is used to implement encoders for user-defined types.
|
||||
*/
|
||||
int ben_put_char(struct ben_encode_ctx *ctx, char c);
|
||||
|
||||
/*
|
||||
* Append data to output of 'ctx'. The amount of bytes written to the output
|
||||
* must be the same as returned by get_size().
|
||||
*
|
||||
* This function is used to implement encoders for user-defined types.
|
||||
*/
|
||||
int ben_put_buffer(struct ben_encode_ctx *ctx, const void *buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,447 +0,0 @@
|
||||
#ifndef KS_DHT_INT_H
|
||||
#define KS_DHT_INT_H
|
||||
|
||||
#include "ks.h"
|
||||
|
||||
KS_BEGIN_EXTERN_C
|
||||
|
||||
/**
|
||||
* Determines the appropriate endpoint to reach a remote address.
|
||||
* If an endpoint is provided, nothing more needs to be done.
|
||||
* If no endpoint is provided, first it will check for an active endpoint it can route though.
|
||||
* If no active endpoint is available and autorouting is enabled it will attempt to bind a usable endpoint.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param raddr pointer to the remote address
|
||||
* @param endpoint dereferenced in/out pointer to the endpoint, if populated then returns immediately
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
||||
* @see ks_ip_route
|
||||
* @see ks_hash_read_unlock
|
||||
* @see ks_addr_set
|
||||
* @see ks_dht_bind
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_autoroute_check(ks_dht_t *dht, const ks_sockaddr_t *raddr, ks_dht_endpoint_t **endpoint);
|
||||
|
||||
/**
|
||||
* Called internally to receive datagrams from endpoints.
|
||||
* Handles datagrams by dispatching each through a threadpool.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param timeout time in ms to wait for an incoming datagram on any endpoint
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_endpoints(ks_dht_t *dht, int32_t timeout);
|
||||
|
||||
/**
|
||||
* Called internally to expire or reannounce storage item data.
|
||||
* Handles reannouncing and purging of expiring storage items.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_storageitems(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to process job state machine.
|
||||
* Handles completing and purging of finished jobs.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_jobs(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to send queued messages.
|
||||
* Handles throttling of message sending to ensure system buffers are not overloaded and messages are not dropped.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_send(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to expire transactions.
|
||||
* Handles purging of expired and finished transactions.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_transactions(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to expire and cycle tokens.
|
||||
* Handles cycling new secret entropy for token generation.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_tokens(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Converts a ks_dht_nodeid_t into it's hex string representation.
|
||||
* @param id pointer to the nodeid
|
||||
* @param buffer pointer to the buffer able to contain at least (KS_DHT_NODEID_SIZE * 2) + 1 characters
|
||||
* @return The pointer to the front of the populated string buffer
|
||||
*/
|
||||
KS_DECLARE(char *) ks_dht_hex(const uint8_t *data, char *buffer, ks_size_t len);
|
||||
|
||||
/**
|
||||
* Compacts address information as per the DHT specifications.
|
||||
* @param address pointer to the address being compacted from
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_compact_addressinfo(const ks_sockaddr_t *address,
|
||||
uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Expands address information as per the DHT specifications.
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @param address pointer to the address being expanded into
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM, ...
|
||||
* @see ks_addr_set_raw
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_expand_addressinfo(const uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size,
|
||||
ks_sockaddr_t *address);
|
||||
|
||||
/**
|
||||
* Compacts node information as per the DHT specifications.
|
||||
* Compacts address information after the nodeid.
|
||||
* @param nodeid pointer to the nodeid being compacted from
|
||||
* @param address pointer to the address being compacted from
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM, ...
|
||||
* @see ks_dht_utility_compact_addressinfo
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_compact_nodeinfo(const ks_dht_nodeid_t *nodeid,
|
||||
const ks_sockaddr_t *address,
|
||||
uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Expands address information as per the DHT specifications.
|
||||
* Expands compacted address information after the nodeid.
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @param address pointer to the address being expanded into
|
||||
* @param nodeid pointer to the nodeid being expanded into
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM, ...
|
||||
* @see ks_dht_utility_expand_addressinfo
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_expand_nodeinfo(const uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size,
|
||||
ks_dht_nodeid_t *nodeid,
|
||||
ks_sockaddr_t *address);
|
||||
|
||||
/**
|
||||
* Extracts a ks_dht_nodeid_t from a bencode dictionary given a string key.
|
||||
* @param args pointer to the bencode dictionary
|
||||
* @param key string key in the bencode dictionary to extract the value from
|
||||
* @param nodeid dereferenced out pointer to the nodeid
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_ARG_INVALID
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_extract_nodeid(struct bencode *args, const char *key, ks_dht_nodeid_t **nodeid);
|
||||
|
||||
/**
|
||||
* Extracts a ks_dht_token_t from a bencode dictionary given a string key.
|
||||
* @param args pointer to the bencode dictionary
|
||||
* @param key string key in the bencode dictionary to extract the value from
|
||||
* @param nodeid dereferenced out pointer to the token
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_ARG_INVALID
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_extract_token(struct bencode *args, const char *key, ks_dht_token_t **token);
|
||||
|
||||
/**
|
||||
* Generates an opaque write token based on a shifting secret value, the remote address and target nodeid of interest.
|
||||
* This token ensures that future operations can be verified to the remote peer and target id requested.
|
||||
* @param secret rotating secret portion of the token hash
|
||||
* @param raddr pointer to the remote address used for the ip and port in the token hash
|
||||
* @param target pointer to the nodeid of the target used for the token hash
|
||||
* @param token pointer to the output token being generated
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_token_generate(uint32_t secret, const ks_sockaddr_t *raddr, ks_dht_nodeid_t *target, ks_dht_token_t *token);
|
||||
|
||||
/**
|
||||
* Verify an opaque write token matches the provided remote address and target nodeid.
|
||||
* Handles checking against the last two secret values for the token hash.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param raddr pointer to the remote address used for the ip and port in the token hash
|
||||
* @param target pointer to the nodeid of the target used for the token hash
|
||||
* @param token pointer to the input token being compared
|
||||
* @return Either KS_TRUE if verification passes, otherwise KS_FALSE
|
||||
*/
|
||||
KS_DECLARE(ks_bool_t) ks_dht_token_verify(ks_dht_t *dht, const ks_sockaddr_t *raddr, ks_dht_nodeid_t *target, ks_dht_token_t *token);
|
||||
|
||||
/**
|
||||
* Encodes a message for transmission as a UDP datagram and sends it.
|
||||
* Uses the internally tracked local endpoint and remote address to route the UDP datagram.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param message pointer to the message being sent
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
||||
* @see ks_socket_sendto
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_send(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
|
||||
/**
|
||||
* Sets up the common parts of a query message.
|
||||
* Determines the local endpoint aware of autorouting, assigns the remote address, generates a transaction, and queues a callback.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param job pointer to the job
|
||||
* @param query string value of the query type, for example "ping"
|
||||
* @param callback callback to be called when response to transaction is received
|
||||
* @param transaction dereferenced out pointer to the allocated transaction, may be NULL to ignore output
|
||||
* @param message dereferenced out pointer to the allocated message
|
||||
* @param args dereferenced out pointer to the allocated bencode args, may be NULL to ignore output
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL, ...
|
||||
* @see ks_dht_autoroute_check
|
||||
* @see ks_dht_transaction_alloc
|
||||
* @see ks_dht_transaction_init
|
||||
* @see ks_dht_message_alloc
|
||||
* @see ks_dht_message_init
|
||||
* @see ks_dht_message_query
|
||||
* @see ks_hash_insert
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_setup(ks_dht_t *dht,
|
||||
ks_dht_job_t *job,
|
||||
const char *query,
|
||||
ks_dht_job_callback_t callback,
|
||||
ks_dht_transaction_t **transaction,
|
||||
ks_dht_message_t **message,
|
||||
struct bencode **args);
|
||||
|
||||
/**
|
||||
* Sets up the common parts of a response message.
|
||||
* Determines the local endpoint aware of autorouting, assigns the remote address, and assigns the transaction.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param ep pointer to the endpoint, may be NULL to find an endpoint or autoroute one
|
||||
* @param raddr pointer to the remote address
|
||||
* @param transactionid pointer to the buffer containing the transactionid, may be of variable size depending on the querying node
|
||||
* @param transactionid_length length of the transactionid buffer
|
||||
* @param message dereferenced out pointer to the allocated message
|
||||
* @param args dereferenced out pointer to the allocated bencode args, may be NULL to ignore output
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
||||
* @see ks_dht_autoroute_check
|
||||
* @see ks_dht_message_alloc
|
||||
* @see ks_dht_message_init
|
||||
* @see ks_dht_message_response
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_response_setup(ks_dht_t *dht,
|
||||
ks_dht_endpoint_t *ep,
|
||||
const ks_sockaddr_t *raddr,
|
||||
uint8_t *transactionid,
|
||||
ks_size_t transactionid_length,
|
||||
ks_dht_message_t **message,
|
||||
struct bencode **args);
|
||||
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_error(ks_dht_t *dht,
|
||||
ks_dht_endpoint_t *ep,
|
||||
const ks_sockaddr_t *raddr,
|
||||
uint8_t *transactionid,
|
||||
ks_size_t transactionid_length,
|
||||
long long errorcode,
|
||||
const char *errorstr);
|
||||
|
||||
KS_DECLARE(void) ks_dht_pulse_jobs(ks_dht_t *dht);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_ping(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_findnode(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_get(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_put(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(void *)ks_dht_process(ks_thread_t *thread, void *data);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_error(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_ping(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_ping(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_findnode(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_findnode(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_get(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_get(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_put(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_put(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_datagram_create(ks_dht_datagram_t **datagram,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_t *dht,
|
||||
ks_dht_endpoint_t *endpoint,
|
||||
const ks_sockaddr_t *raddr);
|
||||
KS_DECLARE(void) ks_dht_datagram_destroy(ks_dht_datagram_t **datagram);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_job_create(ks_dht_job_t **job,
|
||||
ks_pool_t *pool,
|
||||
const ks_sockaddr_t *raddr,
|
||||
int32_t attempts,
|
||||
void *data);
|
||||
KS_DECLARE(void) ks_dht_job_build_ping(ks_dht_job_t *job, ks_dht_job_callback_t query_callback, ks_dht_job_callback_t finish_callback);
|
||||
KS_DECLARE(void) ks_dht_job_build_findnode(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_nodeid_t *target);
|
||||
KS_DECLARE(void) ks_dht_job_build_get(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length);
|
||||
KS_DECLARE(void) ks_dht_job_build_put(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_token_t *token,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
KS_DECLARE(void) ks_dht_job_build_search(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback);
|
||||
KS_DECLARE(void) ks_dht_job_build_search_findnode(ks_dht_job_t *job,
|
||||
ks_dht_nodeid_t *target,
|
||||
uint32_t family,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback);
|
||||
KS_DECLARE(void) ks_dht_job_destroy(ks_dht_job_t **job);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_endpoint_create(ks_dht_endpoint_t **endpoint,
|
||||
ks_pool_t *pool,
|
||||
const ks_sockaddr_t *addr,
|
||||
ks_socket_t sock);
|
||||
KS_DECLARE(void) ks_dht_endpoint_destroy(ks_dht_endpoint_t **endpoint);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_message_create(ks_dht_message_t **message,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_endpoint_t *endpoint,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_bool_t alloc_data);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_message_destroy(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_search_create(ks_dht_search_t **search,
|
||||
ks_pool_t *pool,
|
||||
ks_dhtrt_routetable_t *table,
|
||||
const ks_dht_nodeid_t *target,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data);
|
||||
KS_DECLARE(void) ks_dht_search_destroy(ks_dht_search_t **search);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_publish_create(ks_dht_publish_t **publish,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
KS_DECLARE(void) ks_dht_publish_destroy(ks_dht_publish_t **publish);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_distribute_create(ks_dht_distribute_t **distribute,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_storageitem_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
KS_DECLARE(void) ks_dht_distribute_destroy(ks_dht_distribute_t **distribute);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_immutable_internal(struct bencode *value, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_mutable_internal(ks_dht_storageitem_pkey_t *pk, struct bencode *salt, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable_internal(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
struct bencode *v,
|
||||
ks_bool_t clone_v);
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length);
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable_internal(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
struct bencode *v,
|
||||
ks_bool_t clone_v,
|
||||
ks_dht_storageitem_pkey_t *pk,
|
||||
struct bencode *salt,
|
||||
ks_bool_t clone_salt,
|
||||
int64_t sequence,
|
||||
ks_dht_storageitem_signature_t *signature);
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length,
|
||||
ks_dht_storageitem_pkey_t *pk,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length,
|
||||
int64_t sequence,
|
||||
ks_dht_storageitem_signature_t *signature);
|
||||
KS_DECLARE(void) ks_dht_storageitem_update_mutable(ks_dht_storageitem_t *item, struct bencode *v, int64_t sequence, ks_dht_storageitem_signature_t *signature);
|
||||
KS_DECLARE(void) ks_dht_storageitem_destroy(ks_dht_storageitem_t **item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_transaction_create(ks_dht_transaction_t **transaction,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_job_t *job,
|
||||
uint32_t transactionid,
|
||||
ks_dht_job_callback_t callback);
|
||||
KS_DECLARE(void) ks_dht_transaction_destroy(ks_dht_transaction_t **transaction);
|
||||
|
||||
KS_END_EXTERN_C
|
||||
|
||||
#endif /* KS_DHT_INT_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:
|
||||
*/
|
||||
@@ -1,596 +0,0 @@
|
||||
#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_TPOOL_MIN 2
|
||||
#define KS_DHT_TPOOL_MAX 8
|
||||
#define KS_DHT_TPOOL_STACK (1024 * 256)
|
||||
#define KS_DHT_TPOOL_IDLE 10
|
||||
|
||||
#define KS_DHT_DATAGRAM_BUFFER_SIZE 1000
|
||||
|
||||
//#define KS_DHT_RECV_BUFFER_SIZE 0xFFFF
|
||||
|
||||
#define KS_DHT_NODEID_SIZE 20
|
||||
|
||||
#define KS_DHT_RESPONSE_NODES_MAX_SIZE 8
|
||||
|
||||
#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 10
|
||||
#define KS_DHT_TRANSACTIONS_PULSE 1
|
||||
|
||||
#define KS_DHT_SEARCH_RESULTS_MAX_SIZE 8 // @todo replace with KS_DHTRT_BUCKET_SIZE
|
||||
|
||||
#define KS_DHT_STORAGEITEM_PKEY_SIZE crypto_sign_PUBLICKEYBYTES
|
||||
#define KS_DHT_STORAGEITEM_SKEY_SIZE crypto_sign_SECRETKEYBYTES
|
||||
#define KS_DHT_STORAGEITEM_SALT_MAX_SIZE 64
|
||||
#define KS_DHT_STORAGEITEM_SIGNATURE_SIZE crypto_sign_BYTES
|
||||
#define KS_DHT_STORAGEITEM_EXPIRATION 7200
|
||||
#define KS_DHT_STORAGEITEM_KEEPALIVE 300
|
||||
#define KS_DHT_STORAGEITEMS_PULSE 10
|
||||
|
||||
#define KS_DHT_TOKEN_SIZE SHA_DIGEST_LENGTH
|
||||
#define KS_DHT_TOKEN_EXPIRATION 300
|
||||
#define KS_DHT_TOKENS_PULSE 1
|
||||
|
||||
#define KS_DHTRT_MAXQUERYSIZE 20
|
||||
|
||||
typedef struct ks_dht_s ks_dht_t;
|
||||
typedef struct ks_dht_datagram_s ks_dht_datagram_t;
|
||||
typedef struct ks_dht_job_s ks_dht_job_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_pkey_s ks_dht_storageitem_pkey_t;
|
||||
typedef struct ks_dht_storageitem_skey_s ks_dht_storageitem_skey_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_search_s ks_dht_search_t;
|
||||
typedef struct ks_dht_publish_s ks_dht_publish_t;
|
||||
typedef struct ks_dht_distribute_s ks_dht_distribute_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_job_callback_t)(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
typedef ks_status_t (*ks_dht_message_callback_t)(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
//typedef ks_status_t (*ks_dht_search_callback_t)(ks_dht_t *dht, ks_dht_search_t *search);
|
||||
typedef ks_status_t (*ks_dht_storageitem_callback_t)(ks_dht_t *dht, ks_dht_storageitem_t *item);
|
||||
|
||||
|
||||
struct ks_dht_datagram_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_t *dht;
|
||||
ks_dht_endpoint_t *endpoint;
|
||||
ks_sockaddr_t raddr;
|
||||
uint8_t buffer[KS_DHT_DATAGRAM_BUFFER_SIZE];
|
||||
ks_size_t buffer_length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Note: This must remain a structure for casting from raw data
|
||||
*/
|
||||
struct ks_dht_nodeid_s {
|
||||
uint8_t id[KS_DHT_NODEID_SIZE];
|
||||
};
|
||||
|
||||
enum ks_afflags_t { ifv4=AF_INET, ifv6=AF_INET6, ifboth=AF_INET+AF_INET6};
|
||||
enum ks_dht_nodetype_t { KS_DHT_REMOTE=0x01,
|
||||
KS_DHT_LOCAL=0x02,
|
||||
KS_DHT_BOTH=KS_DHT_REMOTE+KS_DHT_LOCAL };
|
||||
|
||||
enum ks_create_node_flags_t {
|
||||
KS_DHTRT_CREATE_DEFAULT=0,
|
||||
KS_DHTRT_CREATE_PING,
|
||||
KS_DHTRT_CREATE_TOUCH
|
||||
};
|
||||
|
||||
struct ks_dht_node_s {
|
||||
ks_dht_nodeid_t nodeid;
|
||||
ks_sockaddr_t addr;
|
||||
enum ks_dht_nodetype_t type; /* local or remote */
|
||||
ks_dhtrt_routetable_t* table;
|
||||
ks_rwl_t *reflock;
|
||||
};
|
||||
|
||||
struct ks_dht_token_s {
|
||||
uint8_t token[KS_DHT_TOKEN_SIZE];
|
||||
};
|
||||
|
||||
enum ks_dht_job_state_t {
|
||||
KS_DHT_JOB_STATE_QUERYING,
|
||||
KS_DHT_JOB_STATE_RESPONDING,
|
||||
KS_DHT_JOB_STATE_EXPIRING,
|
||||
KS_DHT_JOB_STATE_COMPLETING,
|
||||
};
|
||||
|
||||
enum ks_dht_job_result_t {
|
||||
KS_DHT_JOB_RESULT_SUCCESS = 0,
|
||||
KS_DHT_JOB_RESULT_EXPIRED,
|
||||
KS_DHT_JOB_RESULT_ERROR,
|
||||
KS_DHT_JOB_RESULT_FAILURE,
|
||||
};
|
||||
|
||||
struct ks_dht_job_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_t *dht;
|
||||
ks_dht_job_t *next;
|
||||
|
||||
enum ks_dht_job_state_t state;
|
||||
enum ks_dht_job_result_t result;
|
||||
|
||||
ks_sockaddr_t raddr; // will obtain local endpoint node id when creating message using raddr
|
||||
int32_t attempts;
|
||||
|
||||
//enum ks_dht_job_type_t type;
|
||||
ks_dht_job_callback_t query_callback;
|
||||
ks_dht_job_callback_t finish_callback;
|
||||
|
||||
void *data;
|
||||
ks_dht_message_t *response;
|
||||
|
||||
// job specific query parameters
|
||||
ks_dht_nodeid_t query_target;
|
||||
struct bencode *query_salt;
|
||||
int64_t query_cas;
|
||||
ks_dht_token_t query_token;
|
||||
ks_dht_storageitem_t *query_storageitem;
|
||||
|
||||
// error response parameters
|
||||
int64_t error_code;
|
||||
struct bencode *error_description;
|
||||
|
||||
// job specific response parameters
|
||||
ks_dht_node_t *response_id;
|
||||
ks_dht_node_t *response_nodes[KS_DHT_RESPONSE_NODES_MAX_SIZE];
|
||||
ks_size_t response_nodes_count;
|
||||
ks_dht_node_t *response_nodes6[KS_DHT_RESPONSE_NODES_MAX_SIZE];
|
||||
ks_size_t response_nodes6_count;
|
||||
|
||||
ks_dht_token_t response_token;
|
||||
int64_t response_seq;
|
||||
ks_bool_t response_hasitem;
|
||||
ks_dht_storageitem_t *response_storageitem;
|
||||
};
|
||||
|
||||
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 ks_afflags_t 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_DHTRT_MAXQUERYSIZE ]; /* out: array of peers (ks_dht_node_t* nodes[incount]) */
|
||||
};
|
||||
|
||||
struct ks_dht_storageitem_pkey_s {
|
||||
uint8_t key[KS_DHT_STORAGEITEM_PKEY_SIZE];
|
||||
};
|
||||
|
||||
struct ks_dht_storageitem_skey_s {
|
||||
uint8_t key[KS_DHT_STORAGEITEM_SKEY_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;
|
||||
ks_dht_transaction_t *transaction;
|
||||
char type[KS_DHT_MESSAGE_TYPE_MAX_SIZE];
|
||||
struct bencode *args;
|
||||
ks_dht_nodeid_t args_id;
|
||||
};
|
||||
|
||||
struct ks_dht_endpoint_s {
|
||||
ks_pool_t *pool;
|
||||
ks_sockaddr_t addr;
|
||||
ks_socket_t sock;
|
||||
};
|
||||
|
||||
struct ks_dht_transaction_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_job_t *job;
|
||||
uint32_t transactionid;
|
||||
//ks_dht_nodeid_t target; // @todo look at moving this into job now
|
||||
ks_dht_job_callback_t callback;
|
||||
ks_time_t expiration;
|
||||
ks_bool_t finished;
|
||||
};
|
||||
|
||||
struct ks_dht_search_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dhtrt_routetable_t *table;
|
||||
ks_dht_nodeid_t target;
|
||||
ks_dht_job_callback_t callback;
|
||||
void *data;
|
||||
ks_mutex_t *mutex;
|
||||
ks_hash_t *searched;
|
||||
int32_t searching;
|
||||
ks_dht_node_t *results[KS_DHT_SEARCH_RESULTS_MAX_SIZE];
|
||||
ks_dht_nodeid_t distances[KS_DHT_SEARCH_RESULTS_MAX_SIZE];
|
||||
ks_size_t results_length;
|
||||
};
|
||||
|
||||
struct ks_dht_publish_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_job_callback_t callback;
|
||||
void *data;
|
||||
int64_t cas;
|
||||
ks_dht_storageitem_t *item;
|
||||
};
|
||||
|
||||
struct ks_dht_distribute_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_storageitem_callback_t callback;
|
||||
void *data;
|
||||
ks_mutex_t *mutex;
|
||||
int32_t publishing;
|
||||
int64_t cas;
|
||||
ks_dht_storageitem_t *item;
|
||||
};
|
||||
|
||||
struct ks_dht_storageitem_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_nodeid_t id;
|
||||
ks_time_t expiration;
|
||||
ks_time_t keepalive;
|
||||
struct bencode *v;
|
||||
|
||||
ks_mutex_t *mutex;
|
||||
volatile int32_t refc;
|
||||
ks_dht_storageitem_callback_t callback;
|
||||
|
||||
ks_bool_t mutable;
|
||||
ks_dht_storageitem_pkey_t pk;
|
||||
ks_dht_storageitem_skey_t sk;
|
||||
struct bencode *salt;
|
||||
int64_t seq;
|
||||
ks_dht_storageitem_signature_t sig;
|
||||
};
|
||||
|
||||
struct ks_dht_s {
|
||||
ks_pool_t *pool;
|
||||
ks_bool_t pool_alloc;
|
||||
|
||||
ks_thread_pool_t *tpool;
|
||||
ks_bool_t tpool_alloc;
|
||||
|
||||
ks_dht_nodeid_t nodeid;
|
||||
// @todo make sure this node is unlocked, and never gets destroyed, should also never use local nodes in search results as they can be internal
|
||||
// network addresses, not what others have contacted through
|
||||
ks_dht_node_t *node;
|
||||
|
||||
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_dht_endpoint_t **endpoints;
|
||||
int32_t endpoints_length;
|
||||
int32_t endpoints_size;
|
||||
ks_hash_t *endpoints_hash;
|
||||
struct pollfd *endpoints_poll;
|
||||
|
||||
ks_q_t *send_q;
|
||||
ks_dht_message_t *send_q_unsent;
|
||||
uint8_t recv_buffer[KS_DHT_DATAGRAM_BUFFER_SIZE + 1]; // Add 1, if we receive it then overflow error
|
||||
ks_size_t recv_buffer_length;
|
||||
|
||||
ks_mutex_t *jobs_mutex;
|
||||
ks_dht_job_t *jobs_first;
|
||||
ks_dht_job_t *jobs_last;
|
||||
|
||||
ks_time_t transactions_pulse;
|
||||
ks_mutex_t *transactionid_mutex;
|
||||
volatile uint32_t transactionid_next;
|
||||
ks_hash_t *transactions_hash;
|
||||
|
||||
ks_dhtrt_routetable_t *rt_ipv4;
|
||||
ks_dhtrt_routetable_t *rt_ipv6;
|
||||
|
||||
ks_time_t tokens_pulse;
|
||||
volatile uint32_t token_secret_current;
|
||||
volatile uint32_t token_secret_previous;
|
||||
ks_time_t token_secret_expiration;
|
||||
|
||||
ks_time_t storageitems_pulse;
|
||||
ks_hash_t *storageitems_hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor function for ks_dht_t.
|
||||
* Will allocate and initialize internal state including registration of message handlers.
|
||||
* @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 memory pool internally
|
||||
* @param tpool pointer to a thread pool used by the dht instance, may be NULL to create a new thread pool internally
|
||||
* @param nodeid pointer to the nodeid for this dht instance
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_create(ks_dht_t **dht, ks_pool_t *pool, ks_thread_pool_t *tpool, ks_dht_nodeid_t *nodeid);
|
||||
|
||||
/**
|
||||
* Destructor function for ks_dht_t.
|
||||
* Will deinitialize and deallocate internal state.
|
||||
* @param dht dereferenced in/out pointer to the dht instance, NULL upon return
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_destroy(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
|
||||
*/
|
||||
KS_DECLARE(void) 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
|
||||
*/
|
||||
KS_DECLARE(void) 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
|
||||
*/
|
||||
KS_DECLARE(void) 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 addr pointer to the local address information
|
||||
* @param endpoint dereferenced out pointer to the allocated endpoint, may be NULL to ignore endpoint output
|
||||
* @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_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(char *) ks_dht_hex(const uint8_t *data, char *buffer, ks_size_t len);
|
||||
KS_DECLARE(uint8_t *) ks_dht_dehex(uint8_t *data, const char *buffer, ks_size_t len);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_immutable(const uint8_t *value, ks_size_t value_length, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_mutable(ks_dht_storageitem_pkey_t *pk, const uint8_t *salt, ks_size_t salt_length, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_signature_generate(ks_dht_storageitem_signature_t *sig,
|
||||
ks_dht_storageitem_skey_t *sk,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length,
|
||||
int64_t sequence,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitem_reference(ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitem_dereference(ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitem_callback(ks_dht_storageitem_t *item, ks_dht_storageitem_callback_t callback);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_read_lock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_read_unlock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_write_lock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_write_unlock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_dht_storageitem_t *) ks_dht_storageitems_find(ks_dht_t *dht, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitems_insert(ks_dht_t *dht, ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_ping(ks_dht_t *dht, const ks_sockaddr_t *raddr, ks_dht_job_callback_t callback, void *data);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_findnode(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_get(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_put(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dht_token_t *token,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
* Create a network search of the closest nodes to a target.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param family either AF_INET or AF_INET6 for the appropriate network to search
|
||||
* @param target pointer to the nodeid for the target to be searched
|
||||
* @param callback an optional callback to add to the search when it is finished
|
||||
* @param search dereferenced out pointer to the allocated search, may be NULL to ignore search output
|
||||
* @see ks_dht_search_create
|
||||
* @see ks_hash_insert
|
||||
* @see ks_dht_findnode
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_search(ks_dht_t *dht,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dhtrt_routetable_t *table,
|
||||
ks_dht_nodeid_t *target);
|
||||
|
||||
KS_DECLARE(void) ks_dht_publish(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
|
||||
KS_DECLARE(void) ks_dht_distribute(ks_dht_t *dht,
|
||||
ks_dht_storageitem_callback_t callback,
|
||||
void *data,
|
||||
ks_dhtrt_routetable_t *table,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
* route table methods
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_initroute(ks_dhtrt_routetable_t **tableP,
|
||||
ks_dht_t *dht,
|
||||
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,
|
||||
enum ks_create_node_flags_t flags,
|
||||
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(ks_status_t) ks_dhtrt_sharelock_node(ks_dht_node_t* node);
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_release_node(ks_dht_node_t* node);
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_release_querynodes(ks_dhtrt_querynodes_t* query);
|
||||
|
||||
KS_DECLARE(void) ks_dhtrt_process_table(ks_dhtrt_routetable_t* table);
|
||||
|
||||
KS_DECLARE(uint32_t) ks_dhtrt_serialize(ks_dhtrt_routetable_t* table, void** ptr);
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_deserialize(ks_dhtrt_routetable_t* table, void* ptr);
|
||||
|
||||
/* 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:
|
||||
*/
|
||||
Reference in new issue
Block a user