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
|
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) \
|
#define DEFTESTCASE(NAME) \
|
||||||
TCase *tc_##NAME = tcase_create(#NAME); \
|
TCase *tc_##NAME = tcase_create(#NAME); \
|
||||||
tcase_add_test(tc_##NAME, test_##NAME); \
|
tcase_add_test(tc_##NAME, test_##NAME); \
|
||||||
@ -133,6 +143,7 @@ Suite *network_suite(void)
|
|||||||
|
|
||||||
DEFTESTCASE(addr_resolv_localhost);
|
DEFTESTCASE(addr_resolv_localhost);
|
||||||
DEFTESTCASE(ip_equal);
|
DEFTESTCASE(ip_equal);
|
||||||
|
DEFTESTCASE(struct_sizes);
|
||||||
|
|
||||||
return s;
|
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?
|
* 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;
|
uint32_t num_nodes = 0, i;
|
||||||
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
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;
|
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)
|
if (!dht->assoc)
|
||||||
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good);
|
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good);
|
||||||
@ -492,10 +494,10 @@ static void sort_list(Client_data *list, uint32_t length, uint8_t *comp_client_i
|
|||||||
* return 1 if not (list contains no bad nodes).
|
* return 1 if not (list contains no bad nodes).
|
||||||
*/
|
*/
|
||||||
static int replace_possible_bad( Client_data *list,
|
static int replace_possible_bad( Client_data *list,
|
||||||
uint32_t length,
|
uint32_t length,
|
||||||
uint8_t *client_id,
|
uint8_t *client_id,
|
||||||
IP_Port ip_port,
|
IP_Port ip_port,
|
||||||
uint8_t *comp_client_id )
|
uint8_t *comp_client_id )
|
||||||
{
|
{
|
||||||
if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
|
if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
|
||||||
return 1;
|
return 1;
|
||||||
@ -626,10 +628,10 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
|
|||||||
if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
|
if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
|
||||||
if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
|
if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
|
||||||
if (replace_possible_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
|
if (replace_possible_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
|
||||||
dht->c->self_public_key)) {
|
dht->c->self_public_key)) {
|
||||||
/* If we can't replace bad nodes we try replacing good ones. */
|
/* If we can't replace bad nodes we try replacing good ones. */
|
||||||
if (!replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
|
if (!replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
|
||||||
dht->c->self_public_key))
|
dht->c->self_public_key))
|
||||||
used++;
|
used++;
|
||||||
} else
|
} else
|
||||||
used++;
|
used++;
|
||||||
@ -647,9 +649,10 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
|
|||||||
/*if (replace_possible_bad(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
|
/*if (replace_possible_bad(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
|
||||||
client_id, ip_port, dht->friends_list[i].client_id)) {*/
|
client_id, ip_port, dht->friends_list[i].client_id)) {*/
|
||||||
/* If we can't replace bad nodes we try replacing good ones. */
|
/* If we can't replace bad nodes we try replacing good ones. */
|
||||||
if (!replace_good(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
|
if (!replace_good(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
|
||||||
client_id, ip_port, dht->friends_list[i].client_id))
|
client_id, ip_port, dht->friends_list[i].client_id))
|
||||||
used++;
|
used++;
|
||||||
|
|
||||||
/*} else
|
/*} else
|
||||||
used++;*/
|
used++;*/
|
||||||
} else
|
} else
|
||||||
@ -801,7 +804,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
|
|||||||
new_nonce(nonce);
|
new_nonce(nonce);
|
||||||
|
|
||||||
Node4_format *nodes4_list = (Node4_format *)(plain);
|
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++) {
|
for (i = 0; i < num_nodes; i++) {
|
||||||
memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
|
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);
|
memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
|
||||||
ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port);
|
ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port);
|
||||||
|
|
||||||
if (dht->assoc)
|
if (dht->assoc)
|
||||||
Assoc_add_entry(dht->assoc, nodes4_list[i].client_id, &ippts, NULL, used ? 1 : 0);
|
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)
|
if (m->chats[groupnumber] == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
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)
|
* It gets called every time the name list changes(new peer/name, deleted peer)
|
||||||
* Function(Tox *tox, int groupnumber, void *userdata)
|
* 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 = function;
|
||||||
m->group_namelistchange_userdata = userdata;
|
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)
|
static int get_chat_num(Messenger *m, Group_Chat *chat)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < m->numchats; ++i) { //TODO: remove this
|
for (i = 0; i < m->numchats; ++i) { //TODO: remove this
|
||||||
if (m->chats[i] == chat)
|
if (m->chats[i] == chat)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,6 +809,7 @@ static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *m
|
|||||||
{
|
{
|
||||||
Messenger *m = userdata;
|
Messenger *m = userdata;
|
||||||
int i = get_chat_num(m, chat);
|
int i = get_chat_num(m, chat);
|
||||||
|
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -816,6 +821,7 @@ static void group_namelistchange_function(Group_Chat *chat, int peer, uint8_t ch
|
|||||||
{
|
{
|
||||||
Messenger *m = userdata;
|
Messenger *m = userdata;
|
||||||
int i = get_chat_num(m, chat);
|
int i = get_chat_num(m, chat);
|
||||||
|
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1528,6 +1534,7 @@ void kill_messenger(Messenger *m)
|
|||||||
* This requires the other modules to expose cleanup functions.
|
* This requires the other modules to expose cleanup functions.
|
||||||
*/
|
*/
|
||||||
uint32_t i, numchats = m->numchats;
|
uint32_t i, numchats = m->numchats;
|
||||||
|
|
||||||
for (i = 0; i < numchats; ++i)
|
for (i = 0; i < numchats; ++i)
|
||||||
del_groupchat(m, 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)
|
* It gets called every time the name list changes(new peer/name, deleted peer)
|
||||||
* Function(Tox *tox, int groupnumber, void *userdata)
|
* 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.
|
/* Creates a new groupchat and puts it in the chats array.
|
||||||
*
|
*
|
||||||
@ -512,7 +513,7 @@ int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t
|
|||||||
int group_number_peers(Messenger *m, int groupnumber);
|
int group_number_peers(Messenger *m, int groupnumber);
|
||||||
|
|
||||||
/* List all the peers in the group chat.
|
/* List all the peers in the group chat.
|
||||||
*
|
*
|
||||||
* Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
|
* Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
|
||||||
*
|
*
|
||||||
* returns the number of peers on success.
|
* returns the number of peers on success.
|
||||||
|
@ -908,8 +908,8 @@ void Assoc_status(Assoc *assoc)
|
|||||||
entry->used_at ? (int)(unix_time() - entry->used_at) : 0,
|
entry->used_at ? (int)(unix_time() - entry->used_at) : 0,
|
||||||
entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0,
|
entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0,
|
||||||
entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?',
|
entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?',
|
||||||
entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0,
|
entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0,
|
||||||
entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?');
|
entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?');
|
||||||
loglog(logbuffer);
|
loglog(logbuffer);
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,7 @@ static int delpeer(Group_Chat *chat, int peernum)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* If peer is in close list, time it out forcefully. */
|
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)) {
|
if (id_equal(chat->close[i].client_id, chat->group[peernum].client_id)) {
|
||||||
chat->close[i].last_recv = 0;
|
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;
|
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->peer_namelistchange = function;
|
||||||
chat->group_namelistchange_userdata = userdata;
|
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 group_client_names(Group_Chat *chat, uint8_t names[][MAX_NICK_BYTES], uint16_t length)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < chat->numpeers && i < length; ++i) {
|
for (i = 0; i < chat->numpeers && i < length; ++i) {
|
||||||
group_peername(chat, i, names[i]);
|
group_peername(chat, i, names[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +109,8 @@ typedef enum {
|
|||||||
CHAT_CHANGE_PEER_NAME,
|
CHAT_CHANGE_PEER_NAME,
|
||||||
} CHAT_CHANGE;
|
} 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.
|
* Send a message to the group.
|
||||||
|
@ -129,7 +129,7 @@ typedef union {
|
|||||||
} IP6;
|
} IP6;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sa_family_t family;
|
uint16_t family;
|
||||||
union {
|
union {
|
||||||
IP4 ip4;
|
IP4 ip4;
|
||||||
IP6 ip6;
|
IP6 ip6;
|
||||||
@ -238,9 +238,9 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
Packet_Handles packethandlers[256];
|
Packet_Handles packethandlers[256];
|
||||||
|
|
||||||
/* Our UDP socket. */
|
|
||||||
sa_family_t family;
|
sa_family_t family;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
|
/* Our UDP socket. */
|
||||||
sock_t sock;
|
sock_t sock;
|
||||||
uint64_t send_fail_eagain;
|
uint64_t send_fail_eagain;
|
||||||
} Networking_Core;
|
} Networking_Core;
|
||||||
|
@ -314,7 +314,7 @@ void tox_callback_friend_request(Tox *tox, void (*function)(uint8_t *, uint8_t *
|
|||||||
* Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
|
* Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
|
||||||
*/
|
*/
|
||||||
void tox_callback_friend_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
|
void tox_callback_friend_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
|
||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
m_callback_friendmessage(m, function, userdata);
|
m_callback_friendmessage(m, function, userdata);
|
||||||
@ -334,7 +334,7 @@ void tox_callback_action(Tox *tox, void (*function)(Messenger *tox, int, uint8_t
|
|||||||
* You are not responsible for freeing newname.
|
* You are not responsible for freeing newname.
|
||||||
*/
|
*/
|
||||||
void tox_callback_name_change(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
|
void tox_callback_name_change(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
|
||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
m_callback_namechange(m, function, userdata);
|
m_callback_namechange(m, function, userdata);
|
||||||
@ -345,7 +345,7 @@ void tox_callback_name_change(Tox *tox, void (*function)(Messenger *tox, int, ui
|
|||||||
* You are not responsible for freeing newstatus.
|
* You are not responsible for freeing newstatus.
|
||||||
*/
|
*/
|
||||||
void tox_callback_status_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
|
void tox_callback_status_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
|
||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
m_callback_statusmessage(m, function, userdata);
|
m_callback_statusmessage(m, function, userdata);
|
||||||
@ -542,8 +542,8 @@ uint32_t tox_get_chatlist(Tox *tox, int *out_list, uint32_t list_size)
|
|||||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||||
*/
|
*/
|
||||||
void tox_callback_file_send_request(Tox *tox, void (*function)(Messenger *tox, int, uint8_t, uint64_t, uint8_t *,
|
void tox_callback_file_send_request(Tox *tox, void (*function)(Messenger *tox, int, uint8_t, uint64_t, uint8_t *,
|
||||||
uint16_t,
|
uint16_t,
|
||||||
void *), void *userdata)
|
void *), void *userdata)
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
callback_file_sendrequest(m, function, userdata);
|
callback_file_sendrequest(m, function, userdata);
|
||||||
@ -589,7 +589,7 @@ int tox_new_file_sender(Tox *tox, int friendnumber, uint64_t filesize, uint8_t *
|
|||||||
* return -1 on failure
|
* return -1 on failure
|
||||||
*/
|
*/
|
||||||
int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
||||||
uint8_t *data, uint16_t length)
|
uint8_t *data, uint16_t length)
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
return file_control(m, friendnumber, send_receive, filenumber, message_id, data, length);
|
return file_control(m, friendnumber, send_receive, filenumber, message_id, data, length);
|
||||||
|
@ -298,7 +298,7 @@ void tox_callback_friend_request(Tox *tox, void (*function)(uint8_t *, uint8_t *
|
|||||||
* Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
|
* Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
|
||||||
*/
|
*/
|
||||||
void tox_callback_friend_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
|
void tox_callback_friend_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
|
||||||
void *userdata);
|
void *userdata);
|
||||||
|
|
||||||
/* Set the function that will be executed when an action from a friend is received.
|
/* Set the function that will be executed when an action from a friend is received.
|
||||||
* Function format is: function(int friendnumber, uint8_t * action, uint32_t length)
|
* Function format is: function(int friendnumber, uint8_t * action, uint32_t length)
|
||||||
@ -310,14 +310,14 @@ void tox_callback_action(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, ui
|
|||||||
* You are not responsible for freeing newname
|
* You are not responsible for freeing newname
|
||||||
*/
|
*/
|
||||||
void tox_callback_name_change(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
|
void tox_callback_name_change(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
|
||||||
void *userdata);
|
void *userdata);
|
||||||
|
|
||||||
/* Set the callback for status message changes.
|
/* Set the callback for status message changes.
|
||||||
* function(int friendnumber, uint8_t *newstatus, uint16_t length)
|
* function(int friendnumber, uint8_t *newstatus, uint16_t length)
|
||||||
* You are not responsible for freeing newstatus.
|
* You are not responsible for freeing newstatus.
|
||||||
*/
|
*/
|
||||||
void tox_callback_status_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
|
void tox_callback_status_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
|
||||||
void *userdata);
|
void *userdata);
|
||||||
|
|
||||||
/* Set the callback for status type changes.
|
/* Set the callback for status type changes.
|
||||||
* function(int friendnumber, USERSTATUS kind)
|
* function(int friendnumber, USERSTATUS kind)
|
||||||
@ -374,7 +374,8 @@ typedef enum {
|
|||||||
TOX_CHAT_CHANGE_PEER_NAME,
|
TOX_CHAT_CHANGE_PEER_NAME,
|
||||||
} TOX_CHAT_CHANGE;
|
} 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.
|
/* Creates a new groupchat and puts it in the chats array.
|
||||||
*
|
*
|
||||||
@ -485,7 +486,7 @@ enum {
|
|||||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||||
*/
|
*/
|
||||||
void tox_callback_file_send_request(Tox *tox, void (*function)(Tox *m, int, uint8_t, uint64_t, uint8_t *, uint16_t,
|
void tox_callback_file_send_request(Tox *tox, void (*function)(Tox *m, int, uint8_t, uint64_t, uint8_t *, uint16_t,
|
||||||
void *), void *userdata);
|
void *), void *userdata);
|
||||||
|
|
||||||
/* Set the callback for file control requests.
|
/* Set the callback for file control requests.
|
||||||
*
|
*
|
||||||
@ -523,7 +524,7 @@ int tox_new_file_sender(Tox *tox, int friendnumber, uint64_t filesize, uint8_t *
|
|||||||
* return -1 on failure
|
* return -1 on failure
|
||||||
*/
|
*/
|
||||||
int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
||||||
uint8_t *data, uint16_t length);
|
uint8_t *data, uint16_t length);
|
||||||
|
|
||||||
/* Send file data.
|
/* Send file data.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user