mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Added/updated some basic docs and cleaned up some things.
This commit is contained in:
parent
d078c5e9c2
commit
1c45e59938
@ -122,6 +122,16 @@ START_TEST(test_ip_equal)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_struct_sizes)
|
||||
{
|
||||
ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4));
|
||||
ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6));
|
||||
ck_assert_msg(sizeof(IP) == 20, "sizeof(IP): expected result 20, got %u.", sizeof(IP));
|
||||
ck_assert_msg(sizeof(IP_Port) == 24, "sizeof(IP_Port): expected result 24, got %u.", sizeof(IP_Port));
|
||||
ck_assert_msg(sizeof(IP4_Port) == 8, "sizeof(IP4_Port): expected result 8, got %u.", sizeof(IP4_Port));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#define DEFTESTCASE(NAME) \
|
||||
TCase *tc_##NAME = tcase_create(#NAME); \
|
||||
tcase_add_test(tc_##NAME, test_##NAME); \
|
||||
@ -133,6 +143,7 @@ Suite *network_suite(void)
|
||||
|
||||
DEFTESTCASE(addr_resolv_localhost);
|
||||
DEFTESTCASE(ip_equal);
|
||||
DEFTESTCASE(struct_sizes);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
21
docs/Hardening_docs.txt
Normal file
21
docs/Hardening_docs.txt
Normal file
@ -0,0 +1,21 @@
|
||||
Hardening request packets are sent as crypto request packets (see crypto docs.)
|
||||
NOTE: currently only get nodes requests are tested in the code which is why there is only one test (more will be added soon.)
|
||||
|
||||
All hardening requests must contain exactly 768 bytes of data. (The data sent must be padded with zeros if it is smaller than that.)
|
||||
|
||||
1. Get the information (IP_port, client_id) of the node we want to test.
|
||||
2. Find a couple random nodes that is not that node (one for each test.)
|
||||
3. Send crypto request packets to each of these random nodes with the data being:
|
||||
|
||||
[byte with value: 02 (get nodes test request)][struct Node_format (the node to test.)][client_id(32 bytes) the id to query the node with.][padding]
|
||||
|
||||
4. The random node receives a packet.
|
||||
-The packet is a get nodes test request:
|
||||
send a get_node request to that node with the id to query in the request.
|
||||
when a send_node response is received, send the following response to the person who sent us the get nodes test request packet:
|
||||
[byte with value: 03 (get nodes test response)][client_id(32 bytes): the id that the node was queried with][The list of nodes it responded with in IPv6 Node format (struct Node_Format)]
|
||||
PROTIP: (get node requests and response contain an encrypted part that you can use to store information so that you don't
|
||||
have to store in your memory where/if to send back the response from the send node)
|
||||
|
||||
5. Receive the test responses.
|
||||
-If the test(s) pass (the nodes behave in a satisfactory manner), make these nodes have priority over those who don't pass the test(s).
|
113
docs/updates/DHT.md
Normal file
113
docs/updates/DHT.md
Normal file
@ -0,0 +1,113 @@
|
||||
DHT protocol
|
||||
============
|
||||
|
||||
Follows pretty much the principle of the torrent DHT: http://www.bittorrent.org/beps/bep_0005.html (READ IT)
|
||||
|
||||
But:
|
||||
Vastly simplified packet format and encryption.
|
||||
|
||||
Boostrapping:
|
||||
The first time you install the client we bootstrap it with a node on our servers.(bandwidth should not be a problem as the client only needs to be sent one reply.)
|
||||
|
||||
|
||||
Basics
|
||||
------
|
||||
(All the numbers here are just guesses and are probably not optimal values)
|
||||
|
||||
client list: A list of node ids closest (mathematically see bittorrent doc) to ours matched with ip addresses + port number corresponding to that id and a timestamp containing the time or time since the client was successfully pinged.
|
||||
|
||||
"friends" list: A list containing the node_ids of all our "friends" or clients we want to connect to.
|
||||
Also contains the ip addresses + port + node_ids + timestamp(of last ping like in the client list) of the 8 clients closest (mathematically see bittorrent doc) to each "friend"
|
||||
|
||||
One pinged lists:
|
||||
-One for storing a list of ips along with their ping_ids and a timestamp for the ping requests
|
||||
Entries in the pinged lists expire after 5 seconds.
|
||||
If one of the lists becomes full, the expire rate reduces itself one second or the new ping takes the place of the oldest one.
|
||||
|
||||
|
||||
Entries in client list and "friends" list expire after 300 seconds without ping response.
|
||||
Each client stores a maximum of 32 entries in its client list.
|
||||
Each client in the client list and "friends" list is pinged every 60 seconds.
|
||||
Each client in the client list and "friends" list has a timestamp which denote the last time it was successfully pinged.
|
||||
If the corresponding clients timestamp is more than 130 seconds old it is considered bad.
|
||||
Send a get nodes request every 20 seconds to a random good node for each "friend" in our "friends" list.
|
||||
Send a get nodes request every 20 seconds to a random good node in the client list.
|
||||
|
||||
|
||||
When a client receives any request from another
|
||||
-----------------------------------------------
|
||||
-Respond to the request
|
||||
-Ping request is replied to with with a ping response containing the same encrypted data
|
||||
-Get nodes request is replied with a send nodes reply containing the same encrypted data and the good nodes from the client list and/or the "friends" list that are closest to the requested_node_id
|
||||
|
||||
-If the requesting client is not in the client list:
|
||||
-If there are no bad clients in the list and the list is full:
|
||||
-If the id of the other client is closer (mathematically see bittorrent doc) than at least one of the clients in the list or our "friends" list:
|
||||
-Send a ping request to the client.
|
||||
-if not forget about the client.
|
||||
|
||||
-If there are bad clients and/or the list isn't full:
|
||||
-Send a ping request to the client
|
||||
|
||||
When a client receives a response
|
||||
---------------------------------
|
||||
-Ping response
|
||||
-If the node was previously pinged with a matching ping_id (check in the corresponding pinged list.)
|
||||
-If the node is in the client list the matching client's timestamp is set to current time.
|
||||
-If the node is in the "friends" list the matching client's timestamp is set to current time for every occurrence.
|
||||
-If the node is not in the client list:
|
||||
-If the list isn't full, add it to the list.
|
||||
-If the list is full, the furthest away (mathematically see bittorrent doc) bad client is replaced by the new one.
|
||||
-If the list is filled with good nodes replace the furthest client with it only if it is closer than the replaced node.
|
||||
-for each friend in the "friends" list:
|
||||
-If that friend's client list isn't full, add that client to it
|
||||
-If that friend's client list contains bad clients, replace the furthest one with that client.
|
||||
-If that friend's client list contains only good clients
|
||||
-If the client is closer to the friend than one of the other clients, it replaces the farthest one
|
||||
-If not, nothing happens.
|
||||
|
||||
-Send nodes
|
||||
-If the ping_id matches what we sent previously (check in the corresponding pinged list.):
|
||||
-Each node in the response is pinged.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Protocol
|
||||
--------
|
||||
|
||||
Node format:
|
||||
```
|
||||
[char array (node_id), length=32 bytes][ip (in network byte order), length=4 bytes][port (in network byte order), length=2 bytes][Padding , length=2 bytes]
|
||||
```
|
||||
see also: DHT.h (Node4_format struct)
|
||||
|
||||
IPv6 Node format:
|
||||
see: DHT.h (Node_format struct)
|
||||
|
||||
Valid queries and Responses:
|
||||
|
||||
Ping(Request and response):
|
||||
```
|
||||
[byte with value: 00 for request, 01 for response][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender: [random 8 byte (ping_id)]]
|
||||
```
|
||||
ping_id = a random integer, the response must contain the exact same number as the request
|
||||
|
||||
|
||||
Get nodes (Request):
|
||||
Packet contents:
|
||||
```
|
||||
[byte with value: 02][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[char array: requested_node_id (node_id of which we want the ip), length=32 bytes][Encrypted data (must be sent back unmodified by in the response), length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
|
||||
```
|
||||
Valid replies: a send_nodes packet
|
||||
|
||||
Send_nodes (response (for ipv4 addresses)):
|
||||
```
|
||||
[byte with value: 03][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=40 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
|
||||
```
|
||||
|
||||
Send_nodes_IPv6 (response (for ipv6 addresses)):
|
||||
```
|
||||
[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in ipv6_node format, length=56 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
|
||||
```
|
@ -351,7 +351,8 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
|
||||
*
|
||||
* want_good : do we want only good nodes as checked with the hardening returned or not?
|
||||
*/
|
||||
static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN, uint8_t want_good)
|
||||
static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family,
|
||||
uint8_t is_LAN, uint8_t want_good)
|
||||
{
|
||||
uint32_t num_nodes = 0, i;
|
||||
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
||||
@ -365,7 +366,8 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN, uint8_t want_good)
|
||||
static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN,
|
||||
uint8_t want_good)
|
||||
{
|
||||
if (!dht->assoc)
|
||||
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good);
|
||||
@ -650,6 +652,7 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
|
||||
if (!replace_good(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
|
||||
client_id, ip_port, dht->friends_list[i].client_id))
|
||||
used++;
|
||||
|
||||
/*} else
|
||||
used++;*/
|
||||
} else
|
||||
@ -801,7 +804,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
|
||||
new_nonce(nonce);
|
||||
|
||||
Node4_format *nodes4_list = (Node4_format *)(plain);
|
||||
int i, num_nodes_ok = 0;
|
||||
uint32_t i, num_nodes_ok = 0;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
|
||||
@ -1042,6 +1045,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
|
||||
|
||||
memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
|
||||
ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port);
|
||||
|
||||
if (dht->assoc)
|
||||
Assoc_add_entry(dht->assoc, nodes4_list[i].client_id, &ippts, NULL, used ? 1 : 0);
|
||||
}
|
||||
|
@ -720,6 +720,7 @@ static uint8_t groupnumber_not_valid(Messenger *m, int groupnumber)
|
||||
|
||||
if (m->chats[groupnumber] == NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -785,7 +786,8 @@ void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int,
|
||||
* It gets called every time the name list changes(new peer/name, deleted peer)
|
||||
* Function(Tox *tox, int groupnumber, void *userdata)
|
||||
*/
|
||||
void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *), void *userdata)
|
||||
void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *),
|
||||
void *userdata)
|
||||
{
|
||||
m->group_namelistchange = function;
|
||||
m->group_namelistchange_userdata = userdata;
|
||||
@ -794,10 +796,12 @@ void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m
|
||||
static int get_chat_num(Messenger *m, Group_Chat *chat)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < m->numchats; ++i) { //TODO: remove this
|
||||
if (m->chats[i] == chat)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -805,6 +809,7 @@ static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *m
|
||||
{
|
||||
Messenger *m = userdata;
|
||||
int i = get_chat_num(m, chat);
|
||||
|
||||
if (i == -1)
|
||||
return;
|
||||
|
||||
@ -816,6 +821,7 @@ static void group_namelistchange_function(Group_Chat *chat, int peer, uint8_t ch
|
||||
{
|
||||
Messenger *m = userdata;
|
||||
int i = get_chat_num(m, chat);
|
||||
|
||||
if (i == -1)
|
||||
return;
|
||||
|
||||
@ -1528,6 +1534,7 @@ void kill_messenger(Messenger *m)
|
||||
* This requires the other modules to expose cleanup functions.
|
||||
*/
|
||||
uint32_t i, numchats = m->numchats;
|
||||
|
||||
for (i = 0; i < numchats; ++i)
|
||||
del_groupchat(m, i);
|
||||
|
||||
|
@ -462,7 +462,8 @@ void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int,
|
||||
* It gets called every time the name list changes(new peer/name, deleted peer)
|
||||
* Function(Tox *tox, int groupnumber, void *userdata)
|
||||
*/
|
||||
void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *), void *userdata);
|
||||
void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *),
|
||||
void *userdata);
|
||||
|
||||
/* Creates a new groupchat and puts it in the chats array.
|
||||
*
|
||||
|
@ -236,6 +236,7 @@ static int delpeer(Group_Chat *chat, int peernum)
|
||||
return -1;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* If peer is in close list, time it out forcefully. */
|
||||
if (id_equal(chat->close[i].client_id, chat->group[peernum].client_id)) {
|
||||
chat->close[i].last_recv = 0;
|
||||
@ -641,7 +642,8 @@ void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat,
|
||||
chat->group_message_userdata = userdata;
|
||||
}
|
||||
|
||||
void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *), void *userdata)
|
||||
void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *),
|
||||
void *userdata)
|
||||
{
|
||||
chat->peer_namelistchange = function;
|
||||
chat->group_namelistchange_userdata = userdata;
|
||||
@ -655,9 +657,11 @@ uint32_t group_numpeers(Group_Chat *chat)
|
||||
uint32_t group_client_names(Group_Chat *chat, uint8_t names[][MAX_NICK_BYTES], uint16_t length)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < chat->numpeers && i < length; ++i) {
|
||||
group_peername(chat, i, names[i]);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,8 @@ typedef enum {
|
||||
CHAT_CHANGE_PEER_NAME,
|
||||
} CHAT_CHANGE;
|
||||
|
||||
void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *), void *userdata);
|
||||
void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *),
|
||||
void *userdata);
|
||||
|
||||
/*
|
||||
* Send a message to the group.
|
||||
|
@ -129,7 +129,7 @@ typedef union {
|
||||
} IP6;
|
||||
|
||||
typedef struct {
|
||||
sa_family_t family;
|
||||
uint16_t family;
|
||||
union {
|
||||
IP4 ip4;
|
||||
IP6 ip6;
|
||||
@ -238,9 +238,9 @@ typedef struct {
|
||||
typedef struct {
|
||||
Packet_Handles packethandlers[256];
|
||||
|
||||
/* Our UDP socket. */
|
||||
sa_family_t family;
|
||||
uint16_t port;
|
||||
/* Our UDP socket. */
|
||||
sock_t sock;
|
||||
uint64_t send_fail_eagain;
|
||||
} Networking_Core;
|
||||
|
@ -374,7 +374,8 @@ typedef enum {
|
||||
TOX_CHAT_CHANGE_PEER_NAME,
|
||||
} TOX_CHAT_CHANGE;
|
||||
|
||||
void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *), void *userdata);
|
||||
void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *),
|
||||
void *userdata);
|
||||
|
||||
/* Creates a new groupchat and puts it in the chats array.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user