Merge branch 'master' of https://github.com/JamoBox/ProjectTox-Core into JamoBox-master

Conflicts:
	toxcore/LAN_discovery.h
This commit is contained in:
irungentoo 2013-08-29 17:55:58 -04:00
commit ea994606fe
23 changed files with 1170 additions and 984 deletions

View File

@ -91,7 +91,7 @@ AC_ARG_WITH(libsodium-headers,
[search for libsodium header files in DIR]),
[
LIBSODIUM_SEARCH_HEADERS="$withval"
AC_MSG_NOTICE([Will search for libsodium header files in $withval])
AC_MSG_NOTICE([will search for libsodium header files in $withval])
]
)
@ -100,7 +100,7 @@ AC_ARG_WITH(libsodium-libs,
[search for libsodium libraries in DIR]),
[
LIBSODIUM_SEARCH_LIBS="$withval"
AC_MSG_NOTICE([Will search for libsodium libraries in $withval])
AC_MSG_NOTICE([will search for libsodium libraries in $withval])
]
)

View File

@ -19,7 +19,7 @@ guide for how you *use* Tox. Here's a user-friendly attempt at it.
- You need to connect to a bootstrapping server, to give you a
public key.
- Where can I find a public server? Right here, as of now: (the help
message from running ``nTox`` with no args will help)
message from running ``nTox`` with no args will help).
- ``198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854``
- ``192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858``

View File

@ -31,7 +31,7 @@
#include "../toxcore/friend_requests.h"
#include "../testing/misc_tools.h"
//Sleep function (x = milliseconds)
/* Sleep function (x = milliseconds) */
#ifdef WIN32
#define c_sleep(x) Sleep(1*x)
#else
@ -52,7 +52,8 @@ void manage_keys(DHT *dht)
FILE *keys_file = fopen("key", "r");
if (keys_file != NULL) {
//if file was opened successfully -- load keys
/* If file was opened successfully -- load keys,
otherwise save new keys */
size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
if (read_size != KEYS_SIZE) {
@ -61,9 +62,8 @@ void manage_keys(DHT *dht)
}
load_keys(dht->c, keys);
printf("Keys loaded successfully\n");
printf("Keys loaded successfully.\n");
} else {
//otherwise save new keys
new_keys(dht->c);
save_keys(dht->c, keys);
keys_file = fopen("key", "w");
@ -73,7 +73,7 @@ void manage_keys(DHT *dht)
exit(1);
}
printf("Keys saved successfully\n");
printf("Keys saved successfully.\n");
}
fclose(keys_file);
@ -81,8 +81,8 @@ void manage_keys(DHT *dht)
int main(int argc, char *argv[])
{
//initialize networking
//bind to ip 0.0.0.0:PORT
/* Initialize networking -
Bind to ip 0.0.0.0:PORT */
IP ip;
ip.i = 0;
DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
@ -106,7 +106,7 @@ int main(int argc, char *argv[])
printf("\n");
printf("Port: %u\n", PORT);
perror("Initialization");
perror("Initialization.");
if (argc > 3) {
printf("Trying to bootstrap into the network...\n");

View File

@ -74,7 +74,7 @@ int b16_to_key(char b16_string[], uint8_t *bs_pubkey)
/*
resolve_addr():
address should represent IPv4 or a hostname with A record
address should represent IPv4 or a hostname with a record
returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
returns 0 on failure
@ -91,7 +91,7 @@ uint32_t resolve_addr(const char *address)
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; // IPv4 only right now.
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
hints.ai_socktype = SOCK_DGRAM; // Type of socket Tox uses.
rc = getaddrinfo(address, "echo", &hints, &server);
@ -113,7 +113,7 @@ uint32_t resolve_addr(const char *address)
return addr;
}
/* This unction connects to all specified servers
/* This function connects to all specified servers
and connect to them.
returns 1 if the connection to the DHT is up
returns -1 if all attempts failed
@ -178,7 +178,7 @@ void manage_keys(DHT *dht, char *keys_file)
load_keys(dht->c, keys);
} else {
/* otherwise save new keys */
/* Otherwise save new keys */
/* Silly work-around to ignore any errors coming from new_keys() */
new_keys(dht->c);
save_keys(dht->c, keys);
@ -273,7 +273,7 @@ struct server_conf_s configure_server(char *cfg_file)
for (i = 0; i < count; ++i) {
config_setting_t *server = config_setting_get_elem(server_list, i);
/* Get a pointer on the key aray */
/* Get a pointer on the key array */
uint8_t *bs_pk_p = server_conf.info[i].bs_pk;
/* Only output the record if all of the expected fields are present. */
@ -288,17 +288,17 @@ struct server_conf_s configure_server(char *cfg_file)
if (resolve_addr(strcpy(tmp_ip, bs_ip)) == 0) {
server_conf.info[i].valid = 0;
printf("bootstrap_server %d: Invalid IP\n", i);
printf("bootstrap_server %d: Invalid IP.\n", i);
}
if (strlen(bs_pk) != 64) {
server_conf.info[i].valid = 0;
printf("bootstrap_server %d: Invalid public key\n", i);
printf("bootstrap_server %d: Invalid public key.\n", i);
}
if (!bs_port) {
server_conf.info[i].valid = 0;
printf("bootstrap_server %d: Invalid port\n", i);
printf("bootstrap_server %d: Invalid port.\n", i);
}
server_conf.info[i].conn.ip.i = resolve_addr(strcpy(tmp_ip, bs_ip));
@ -337,7 +337,7 @@ int main(int argc, char *argv[])
server_conf = configure_server(argv[1]);
/* initialize networking
/* Initialize networking
bind to ip 0.0.0.0:PORT */
IP ip;
ip.i = 0;
@ -412,7 +412,7 @@ int main(int argc, char *argv[])
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
printf("Forked successfully: %d\n", pid);
printf("Forked successfully: %d.\n", pid);
/* Write the PID file */
fprintf(pidf, "%d\n", pid);

View File

@ -1,5 +1,5 @@
/* Binary signer/checker using ed25519
*
*
* Compile with:
* gcc -o sign sign.c -lsodium
*
@ -60,6 +60,7 @@ int main(int argc, char *argv[])
{
unsigned char pk[crypto_sign_ed25519_PUBLICKEYBYTES];
unsigned char sk[crypto_sign_ed25519_SECRETKEYBYTES];
if (argc == 2 && argv[1][0] == 'g') {
crypto_sign_ed25519_keypair(pk, sk);
printf("Public key:\n");
@ -89,19 +90,22 @@ int main(int argc, char *argv[])
unsigned long long smlen;
char *sm = malloc(size + crypto_sign_ed25519_BYTES * 2);
crypto_sign_ed25519(sm, &smlen, data, size, secret_key);
if (smlen - size != crypto_sign_ed25519_BYTES)
goto fail;
FILE *f = fopen(argv[4], "wb");
if (f == NULL)
goto fail;
memcpy(sm + smlen, sm, crypto_sign_ed25519_BYTES); //Move signature from beginning to end of file.
memcpy(sm + smlen, sm, crypto_sign_ed25519_BYTES); // Move signature from beginning to end of file.
if (fwrite(sm + (smlen - size), 1, smlen, f) != smlen)
goto fail;
fclose(f);
printf("Signed successfully\n");
printf("Signed successfully.\n");
}
if (argc == 4 && argv[1][0] == 'c') {
@ -113,22 +117,24 @@ int main(int argc, char *argv[])
goto fail;
char *signe = malloc(size + crypto_sign_ed25519_BYTES);
memcpy(signe, data + size - crypto_sign_ed25519_BYTES, crypto_sign_ed25519_BYTES);//Move signature from end to beginning of file.
memcpy(signe, data + size - crypto_sign_ed25519_BYTES,
crypto_sign_ed25519_BYTES); // Move signature from end to beginning of file.
memcpy(signe + crypto_sign_ed25519_BYTES, data, size - crypto_sign_ed25519_BYTES);
unsigned long long smlen;
char *m = malloc(size);
unsigned long long mlen;
if (crypto_sign_ed25519_open(m, &mlen, signe, size, public_key) == -1) {
printf("Failed checking sig\n");
printf("Failed checking sig.\n");
goto fail;
}
printf("Checked successfully\n");
printf("Checked successfully.\n");
}
return 0;
fail:
printf("FAIL\n");
return 1;
fail:
printf("FAIL\n");
return 1;
}

View File

@ -27,30 +27,30 @@
#include "packets.h"
#include "ping.h"
/* the number of seconds for a non responsive node to become bad. */
/* The number of seconds for a non responsive node to become bad. */
#define BAD_NODE_TIMEOUT 70
/* the max number of nodes to send with send nodes. */
/* The max number of nodes to send with send nodes. */
#define MAX_SENT_NODES 8
/* ping timeout in seconds */
/* Ping timeout in seconds */
#define PING_TIMEOUT 5
/* The timeout after which a node is discarded completely. */
#define Kill_NODE_TIMEOUT 300
/* ping interval in seconds for each node in our lists. */
/* Ping interval in seconds for each node in our lists. */
#define PING_INTERVAL 60
/* ping interval in seconds for each random sending of a get nodes request. */
/* Ping interval in seconds for each random sending of a get nodes request. */
#define GET_NODE_INTERVAL 10
#define MAX_PUNCHING_PORTS 32
/*Interval in seconds between punching attempts*/
/* Interval in seconds between punching attempts*/
#define PUNCH_INTERVAL 10
/*Ping newly announced nodes to ping per TIME_TOPING seconds*/
/* Ping newly announced nodes to ping per TIME_TOPING seconds*/
#define TIME_TOPING 5
#define NAT_PING_REQUEST 0
@ -102,9 +102,9 @@ static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout)
return timestamp + timeout <= time_now;
}
/* check if client with client_id is already in list of length length.
* if it is then set its corresponding timestamp to current time.
* if the id is already in the list with a different ip_port, update it.
/* Check if client with client_id is already in list of length length.
* If it is then set its corresponding timestamp to current time.
* If the id is already in the list with a different ip_port, update it.
* return True(1) or False(0)
*
* TODO: maybe optimize this.
@ -115,7 +115,7 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id
uint64_t temp_time = unix_time();
for (i = 0; i < length; ++i) {
/*If ip_port is assigned to a different client_id replace it*/
/* If ip_port is assigned to a different client_id replace it */
if (ipport_equal(list[i].ip_port, ip_port)) {
memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
}
@ -132,7 +132,7 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id
return 0;
}
/* check if client with client_id is already in node format list of length length.
/* Check if client with client_id is already in node format list of length length.
* return True(1) or False(0)
*/
static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *client_id)
@ -176,7 +176,7 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
/* if node isn't good or is already in list. */
/* If node isn't good or is already in list. */
if (tout || inlist)
continue;
@ -216,7 +216,7 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
MAX_SENT_NODES,
dht->friends_list[i].client_list[j].client_id);
/* if node isn't good or is already in list. */
/* If node isn't good or is already in list. */
if (tout || inlist)
continue;
@ -251,7 +251,7 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
return num_nodes;
}
/* replace first bad (or empty) node with this one
/* Replace first bad (or empty) node with this one
* return 0 if successful
* return 1 if not (list contains no bad nodes)
*/
@ -264,7 +264,7 @@ static int replace_bad( Client_data *list,
uint64_t temp_time = unix_time();
for (i = 0; i < length; ++i) {
/* if node is bad */
/* If node is bad */
if (is_timeout(temp_time, list[i].timestamp, BAD_NODE_TIMEOUT)) {
memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
list[i].ip_port = ip_port;
@ -278,8 +278,8 @@ static int replace_bad( Client_data *list,
return 1;
}
/*Sort the list. It will be sorted from furthest to closest.
TODO: this is innefficient and needs to be optimized.*/
/* Sort the list. It will be sorted from furthest to closest.
TODO: this is innefficient and needs to be optimized. */
static void sort_list(Client_data *list, uint32_t length, uint8_t *comp_client_id)
{
if (length == 0)
@ -305,7 +305,7 @@ static void sort_list(Client_data *list, uint32_t length, uint8_t *comp_client_i
}
/* replace the first good node that is further to the comp_client_id than that of the client_id in the list */
/* Replace the first good node that is further to the comp_client_id than that of the client_id in the list */
static int replace_good( Client_data *list,
uint32_t length,
uint8_t *client_id,
@ -337,12 +337,12 @@ void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
{
uint32_t i;
/* NOTE: current behavior if there are two clients with the same id is
/* NOTE: Current behavior if there are two clients with the same id is
* to replace the first ip by the second.
*/
if (!client_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
/* if we can't replace bad nodes we try replacing good ones */
/* If we can't replace bad nodes we try replacing good ones */
replace_good( dht->close_clientlist,
LCLIENT_LIST,
client_id,
@ -361,7 +361,7 @@ void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
MAX_FRIEND_CLIENTS,
client_id,
ip_port )) {
/* if we can't replace bad nodes we try replacing good ones. */
/* If we can't replace bad nodes we try replacing good ones. */
replace_good( dht->friends_list[i].client_list,
MAX_FRIEND_CLIENTS,
client_id,
@ -373,7 +373,7 @@ void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
}
/* If client_id is a friend or us, update ret_ip_port
* nodeclient_id is the id of the node that sent us this info
* nodeclient_id is the id of the node that sent us this info.
*/
static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id)
{
@ -433,7 +433,7 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id)
return 0;
}
/* Same but for get node requests */
/* Same but for get node requests. */
static uint64_t add_gettingnodes(DHT *dht, IP_Port ip_port)
{
uint32_t i, j;
@ -454,10 +454,10 @@ static uint64_t add_gettingnodes(DHT *dht, IP_Port ip_port)
return 0;
}
/* send a getnodes request */
/* Send a getnodes request. */
static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id)
{
/* check if packet is gonna be sent to ourself */
/* Check if packet is going to be sent to ourself. */
if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0))
return 1;
@ -493,10 +493,10 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data));
}
/* send a send nodes response */
/* Send a send nodes response. */
static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
{
/* check if packet is gonna be sent to ourself */
/* Check if packet is going to be sent to ourself. */
if (id_equal(public_key, dht->c->self_public_key))
return 1;
@ -544,7 +544,7 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
+ sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING ))
return 1;
/* check if packet is from ourself. */
/* Check if packet is from ourself. */
if (id_equal(packet + 1, dht->c->self_public_key))
return 1;
@ -563,7 +563,7 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
memcpy(&ping_id, plain, sizeof(ping_id));
sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
//send_ping_request(dht, source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */
// send_ping_request(dht, source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */
return 0;
}
@ -618,7 +618,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
int DHT_addfriend(DHT *dht, uint8_t *client_id)
{
if (friend_number(dht, client_id) != -1) /*Is friend already in DHT?*/
if (friend_number(dht, client_id) != -1) /* Is friend already in DHT? */
return 1;
DHT_Friend *temp;
@ -709,7 +709,7 @@ static void do_DHT_friends(DHT *dht)
uint32_t num_nodes = 0;
for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
/* if node is not dead. */
/* If node is not dead. */
if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) {
if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) {
send_ping_request(dht->ping, dht->c, dht->friends_list[i].client_list[j].ip_port,
@ -717,7 +717,7 @@ static void do_DHT_friends(DHT *dht)
dht->friends_list[i].client_list[j].last_pinged = temp_time;
}
/* if node is good. */
/* If node is good. */
if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
index[num_nodes] = j;
++num_nodes;
@ -747,7 +747,7 @@ static void do_Close(DHT *dht)
uint32_t index[LCLIENT_LIST];
for (i = 0; i < LCLIENT_LIST; ++i) {
/* if node is not dead. */
/* If node is not dead. */
if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
send_ping_request(dht->ping, dht->c, dht->close_clientlist[i].ip_port,
@ -755,7 +755,7 @@ static void do_Close(DHT *dht)
dht->close_clientlist[i].last_pinged = temp_time;
}
/* if node is good. */
/* If node is good. */
if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) {
index[num_nodes] = i;
++num_nodes;
@ -778,8 +778,8 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
send_ping_request(dht->ping, dht->c, ip_port, (clientid_t *) public_key);
}
/* send the given packet to node with client_id
* returns -1 if failure
/* Send the given packet to node with client_id
* returns -1 if failure.
*/
int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
{
@ -814,7 +814,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
client = &friend->client_list[i];
/*If ip is not zero and node is good */
/* If ip is not zero and node is good */
if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
if (id_equal(client->client_id, friend->client_id))
@ -829,8 +829,8 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
}
/* Send the following packet to everyone who tells us they are connected to friend_id
* returns the number of nodes it sent the packet to
/* Send the following packet to everyone who tells us they are connected to friend_id.
* returns the number of nodes it sent the packet to.
*
* Only works if more than (MAX_FRIEND_CLIENTS / 2) return an ip for friend.
*/
@ -856,7 +856,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
client = &friend->client_list[i];
/*If ip is not zero and node is good */
/* If ip is not zero and node is good */
if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
if (sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length) == length)
++sent;
@ -866,7 +866,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
return sent;
}
/* Send the following packet to one random person who tells us they are connected to friend_id
/* Send the following packet to one random person who tells us they are connected to friend_id.
* returns the number of nodes it sent the packet to
*/
static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length)
@ -887,7 +887,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
client = &friend->client_list[i];
/*If ip is not zero and node is good */
/* If ip is not zero and node is good. */
if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
ip_list[n] = client->ip_port;
++n;
@ -903,8 +903,8 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
return 0;
}
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist
* ip_portlist must be at least MAX_FRIEND_CLIENTS big
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist.
* ip_portlist must be at least MAX_FRIEND_CLIENTS big.
* returns the number of ips returned
* return 0 if we are connected to friend or if no ips were found.
* returns -1 if no such friend
@ -941,9 +941,9 @@ static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t
if (len == -1)
return -1;
if (type == 0) /*If packet is request use many people to route it*/
if (type == 0) /* If packet is request use many people to route it. */
num = route_tofriend(dht, public_key, packet, len);
else if (type == 1) /*If packet is response use only one person to route it*/
else if (type == 1) /* If packet is response use only one person to route it */
num = routeone_tofriend(dht, public_key, packet, len);
if (num == 0)
@ -952,7 +952,7 @@ static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t
return num;
}
/* Handle a received ping request for */
/* Handle a received ping request for. */
static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length)
{
DHT *dht = object;
@ -982,10 +982,10 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey,
return 1;
}
/* Get the most common ip in the ip_portlist
* Only return ip if it appears in list min_num or more
* len must not be bigger than MAX_FRIEND_CLIENTS
* return ip of 0 if failure
/* Get the most common ip in the ip_portlist.
* Only return ip if it appears in list min_num or more.
* len must not be bigger than MAX_FRIEND_CLIENTS.
* return ip of 0 if failure.
*/
static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
{
@ -1010,10 +1010,10 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
return zero;
}
/* Return all the ports for one ip in a list
/* Return all the ports for one ip in a list.
* portlist must be at least len long
* where len is the length of ip_portlist
* returns the number of ports and puts the list of ports in portlist
* returns the number of ports and puts the list of ports in portlist.
*/
static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip)
{
@ -1039,7 +1039,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
uint32_t top = dht->friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS;
for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
/*TODO: improve port guessing algorithm*/
/* TODO: improve port guessing algorithm */
uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
IP_Port pinging = {ip, htons(port)};
send_ping_request(dht->ping, dht->c, pinging, (clientid_t *) &dht->friends_list[friend_num].client_id);
@ -1057,7 +1057,7 @@ static void do_NAT(DHT *dht)
IP_Port ip_list[MAX_FRIEND_CLIENTS];
int num = friend_iplist(dht, ip_list, i);
/*If already connected or friend is not online don't try to hole punch*/
/* If already connected or friend is not online don't try to hole punch */
if (num < MAX_FRIEND_CLIENTS / 2)
continue;
@ -1089,14 +1089,15 @@ static void do_NAT(DHT *dht)
/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
/* Add nodes to the toping list
all nodes in this list are pinged every TIME_TOPING seconds
and are then removed from the list.
if the list is full the nodes farthest from our client_id are replaced
the purpose of this list is to enable quick integration of new nodes into the
network while preventing amplification attacks.
return 0 if node was added
return -1 if node was not added */
/* Add nodes to the toping list.
* All nodes in this list are pinged every TIME_TOPING seconds
* and are then removed from the list.
* If the list is full the nodes farthest from our client_id are replaced.
* The purpose of this list is to enable quick integration of new nodes into the
* network while preventing amplification attacks.
* return 0 if node was added.
* return -1 if node was not added.
*/
int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
{
if (ip_port.ip.i == 0)
@ -1125,8 +1126,9 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
return -1;
}
/*Ping all the valid nodes in the toping list every TIME_TOPING seconds
this function must be run at least once every TIME_TOPING seconds*/
/* Ping all the valid nodes in the toping list every TIME_TOPING seconds.
* This function must be run at least once every TIME_TOPING seconds
*/
static void do_toping(DHT *dht)
{
uint64_t temp_time = unix_time();
@ -1188,22 +1190,22 @@ void kill_DHT(DHT *dht)
free(dht);
}
/* get the size of the DHT (for saving) */
/* Get the size of the DHT (for saving). */
uint32_t DHT_size(DHT *dht)
{
return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends;
}
/* save the DHT in data where data is an array of size DHT_size() */
/* Save the DHT in data where data is an array of size DHT_size(). */
void DHT_save(DHT *dht, uint8_t *data)
{
memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist));
memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends);
}
/* load the DHT from data of size size;
* return -1 if failure
* return 0 if success
/* Load the DHT from data of size size.
* return -1 if failure.
* return 0 if success.
*/
int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
{
@ -1247,8 +1249,8 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
return 0;
}
/* returns 0 if we are not connected to the DHT
* returns 1 if we are
/* returns 0 if we are not connected to the DHT.
* returns 1 if we are.
*/
int DHT_isconnected(DHT *dht)
{

View File

@ -27,21 +27,21 @@
#include "net_crypto.h"
/* size of the client_id in bytes */
/* Size of the client_id in bytes. */
#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
/* maximum number of clients stored per friend. */
/* Maximum number of clients stored per friend. */
#define MAX_FRIEND_CLIENTS 8
/* A list of the clients mathematically closest to ours. */
#define LCLIENT_LIST 32
/* The list of ip ports along with the ping_id of what we sent them and a timestamp */
#define LPING_ARRAY 256 //NOTE Deprecated (doesn't do anything)
/* The list of ip ports along with the ping_id of what we sent them and a timestamp. */
#define LPING_ARRAY 256 // NOTE: Deprecated (doesn't do anything).
#define LSEND_NODES_ARRAY LPING_ARRAY/2
/*Maximum newly announced nodes to ping per TIME_TOPING seconds*/
/* Maximum newly announced nodes to ping per TIME_TOPING seconds. */
#define MAX_TOPING 16
typedef struct {
@ -50,7 +50,7 @@ typedef struct {
uint64_t timestamp;
uint64_t last_pinged;
/* Returned by this node. Either our friend or us */
/* Returned by this node. Either our friend or us. */
IP_Port ret_ip_port;
uint64_t ret_timestamp;
} Client_data;
@ -61,10 +61,10 @@ typedef struct {
uint8_t client_id[CLIENT_ID_SIZE];
Client_data client_list[MAX_FRIEND_CLIENTS];
/* time at which the last get_nodes request was sent. */
/* Time at which the last get_nodes request was sent. */
uint64_t lastgetnode;
/* Symetric NAT hole punching stuff */
/* Symetric NAT hole punching stuff. */
/* 1 if currently hole punching, otherwise 0 */
uint8_t hole_punching;
@ -102,82 +102,91 @@ typedef struct {
Client_data *DHT_get_close_list(DHT *dht);
/* Add a new friend to the friends list
client_id must be CLIENT_ID_SIZE bytes long.
returns 0 if success
returns 1 if failure (friends list is full) */
/* Add a new friend to the friends list.
* client_id must be CLIENT_ID_SIZE bytes long.
* returns 0 if success.
* returns 1 if failure (friends list is full).
*/
int DHT_addfriend(DHT *dht, uint8_t *client_id);
/* Delete a friend from the friends list
client_id must be CLIENT_ID_SIZE bytes long.
returns 0 if success
returns 1 if failure (client_id not in friends list) */
/* Delete a friend from the friends list.
* client_id must be CLIENT_ID_SIZE bytes long.
* returns 0 if success.
* returns 1 if failure (client_id not in friends list).
*/
int DHT_delfriend(DHT *dht, uint8_t *client_id);
/* Get ip of friend
client_id must be CLIENT_ID_SIZE bytes long.
ip must be 4 bytes long.
port must be 2 bytes long.
returns ip if success
returns ip of 0 if failure (This means the friend is either offline or we have not found him yet.)
returns ip of 1 if friend is not in list. */
/* Get ip of friend.
* client_id must be CLIENT_ID_SIZE bytes long.
* ip must be 4 bytes long.
* port must be 2 bytes long.
* returns ip if success.
* returns ip of 0 if failure (This means the friend is either offline or we have not found him yet).
* returns ip of 1 if friend is not in list.
*/
IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id);
/* Run this function at least a couple times per second (It's the main loop) */
/* Run this function at least a couple times per second (It's the main loop). */
void do_DHT(DHT *dht);
/* Use this function to bootstrap the client
Sends a get nodes request to the given node with ip port and public_key */
/* Use this function to bootstrap the client.
* Sends a get nodes request to the given node with ip port and public_key.
*/
void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
/* Add nodes to the toping list
all nodes in this list are pinged every TIME_TOPING seconds
and are then removed from the list.
if the list is full the nodes farthest from our client_id are replaced
the purpose of this list is to enable quick integration of new nodes into the
network while preventing amplification attacks.
return 0 if node was added
return -1 if node was not added */
/* Add nodes to the toping list.
* All nodes in this list are pinged every TIME_TOPING seconds
* and are then removed from the list.
* If the list is full the nodes farthest from our client_id are replaced.
* The purpose of this list is to enable quick integration of new nodes into the
* network while preventing amplification attacks.
* return 0 if node was added.
* return -1 if node was not added.
*/
int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port);
/* ROUTING FUNCTIONS */
/* send the given packet to node with client_id
returns -1 if failure */
/* Send the given packet to node with client_id.
returns -1 if failure. */
int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length);
/* Send the following packet to everyone who tells us they are connected to friend_id
returns the number of nodes it sent the packet to */
/* Send the following packet to everyone who tells us they are connected to friend_id.
* returns the number of nodes it sent the packet to.
*/
int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length);
/* NAT PUNCHING FUNCTIONS */
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist
ip_portlist must be at least MAX_FRIEND_CLIENTS big
returns the number of ips returned
returns -1 if no such friend*/
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist.
* ip_portlist must be at least MAX_FRIEND_CLIENTS big.
* returns the number of ips returned.
* returns -1 if no such friend.
*/
int friend_ips(DHT *dht, IP_Port *ip_portlist, uint8_t *friend_id);
/* SAVE/LOAD functions */
/* get the size of the DHT (for saving) */
/* Get the size of the DHT (for saving). */
uint32_t DHT_size(DHT *dht);
/* save the DHT in data where data is an array of size DHT_size() */
/* Save the DHT in data where data is an array of size DHT_size(). */
void DHT_save(DHT *dht, uint8_t *data);
/* init DHT */
/* Initialize DHT. */
DHT *new_DHT(Net_Crypto *c);
void kill_DHT(DHT *dht);
/* load the DHT from data of size size;
return -1 if failure
return 0 if success */
/* Load the DHT from data of size size.
* return -1 if failure.
* return 0 if success.
*/
int DHT_load(DHT *dht, uint8_t *data, uint32_t size);
/* returns 0 if we are not connected to the DHT
returns 1 if we are */
* returns 1 if we are
*/
int DHT_isconnected(DHT *dht);
void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id);

View File

@ -26,13 +26,15 @@
#define MAX_INTERFACES 16
#ifdef __linux
/* get the first working broadcast address that's not from "lo"
* returns higher than 0 on success
* returns 0 on error */
/* Get the first working broadcast address that's not from "lo".
* returns higher than 0 on success.
* returns 0 on error.
*/
static uint32_t get_broadcast(void)
{
/* not sure how many platforms this will
* run on, so it's wrapped in __linux for now */
/* Not sure how many platforms this will run on,
* so it's wrapped in __linux for now.
*/
struct sockaddr_in *sock_holder = NULL;
struct ifreq i_faces[MAX_INTERFACES];
struct ifconf ifconf;
@ -40,7 +42,7 @@ static uint32_t get_broadcast(void)
int sock = 0;
int i = 0;
/* configure ifconf for the ioctl call */
/* Configure ifconf for the ioctl call. */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("[!] get_broadcast: socket() error");
return 0;
@ -58,14 +60,14 @@ static uint32_t get_broadcast(void)
}
for (i = 0; i < count; i++) {
/* skip the loopback interface, as it's useless */
/* Skip the loopback interface, as it's useless. */
if (strcmp(i_faces[i].ifr_name, "lo") != 0) {
if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
perror("[!] get_broadcast: ioctl error");
return 0;
}
/* just to clarify where we're getting the values from */
/* Just to clarify where we're getting the values from. */
sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
break;
}
@ -82,7 +84,7 @@ static uint32_t get_broadcast(void)
}
#endif
/* Return the broadcast ip */
/* Return the broadcast ip. */
static IP broadcast_ip(void)
{
IP ip;
@ -90,7 +92,7 @@ static IP broadcast_ip(void)
ip.i = get_broadcast();
if (ip.i == 0)
/* error errored, but try anyway? */
/* Error occured, but try anyway? */
ip.i = ~0;
#else
@ -99,23 +101,24 @@ static IP broadcast_ip(void)
return ip;
}
/*return 0 if ip is a LAN ip
return -1 if it is not */
/* return 0 if ip is a LAN ip.
* return -1 if it is not.
*/
static int LAN_ip(IP ip)
{
if (ip.c[0] == 127)/* Loopback */
if (ip.c[0] == 127) /* Loopback. */
return 0;
if (ip.c[0] == 10)/* 10.0.0.0 to 10.255.255.255 range */
if (ip.c[0] == 10) /* 10.0.0.0 to 10.255.255.255 range. */
return 0;
if (ip.c[0] == 172 && ip.c[1] >= 16 && ip.c[1] <= 31)/* 172.16.0.0 to 172.31.255.255 range */
if (ip.c[0] == 172 && ip.c[1] >= 16 && ip.c[1] <= 31) /* 172.16.0.0 to 172.31.255.255 range. */
return 0;
if (ip.c[0] == 192 && ip.c[1] == 168) /* 192.168.0.0 to 192.168.255.255 range */
if (ip.c[0] == 192 && ip.c[1] == 168) /* 192.168.0.0 to 192.168.255.255 range. */
return 0;
if (ip.c[0] == 169 && ip.c[1] == 254 && ip.c[2] != 0 && ip.c[2] != 255)/* 169.254.1.0 to 169.254.254.255 range */
if (ip.c[0] == 169 && ip.c[1] == 254 && ip.c[2] != 0 && ip.c[2] != 255)/* 169.254.1.0 to 169.254.254.255 range. */
return 0;
return -1;

View File

@ -28,18 +28,19 @@
#include "DHT.h"
/* used for get_broadcast() */
/* used for get_broadcast(). */
#ifdef __linux
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/netdevice.h>
#endif
/*Send a LAN discovery pcaket to the broadcast address with port port*/
/* Send a LAN discovery pcaket to the broadcast address with port port. */
int send_LANdiscovery(uint16_t port, Net_Crypto *c);
/* sets up packet handlers */
/* Sets up packet handlers. */
void LANdiscovery_init(DHT *dht);

View File

@ -32,9 +32,9 @@
/* Functions */
/*
* Get connection id from IP_Port
* Return -1 if there are no connections like we are looking for
* Return id if it found it
* Get connection id from IP_Port.
* return -1 if there are no connections like we are looking for.
* return id if it found it.
*/
int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
{
@ -68,16 +68,17 @@ static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
id ^= ludp->randtable[i][((uint8_t *)&source)[i]];
}
if (id == 0) /* id can't be zero */
/* id can't be zero. */
if (id == 0)
id = 1;
return id;
}
/*
* Change the hanshake id associated with that ip_port
* Change the handshake id associated with that ip_port.
*
* TODO: make this better
* TODO: Make this better
*/
static void change_handshake(Lossless_UDP *ludp, IP_Port source)
{
@ -86,9 +87,9 @@ static void change_handshake(Lossless_UDP *ludp, IP_Port source)
}
/*
* Initialize a new connection to ip_port
* Returns an integer corresponding to the connection idt
* Return -1 if it could not initialize the connectiont
* Initialize a new connection to ip_port.
* return an integer corresponding to the connection idt.
* return -1 if it could not initialize the connectiont
* If there already was an existing connection to that ip_port return its number.
*/
int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
@ -131,7 +132,7 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
.last_sent = current_time(),
.killat = ~0,
.send_counter = 0,
/* add randomness to timeout to prevent connections getting stuck in a loop. */
/* Add randomness to timeout to prevent connections getting stuck in a loop. */
.timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT
};
++ludp->connections_number;
@ -144,9 +145,9 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
}
/*
* Initialize a new inbound connection from ip_port
* Returns an integer corresponding to the connection id.
* Return -1 if it could not initialize the connection.
* Initialize a new inbound connection from ip_port.
* return an integer corresponding to the connection id.
* return -1 if it could not initialize the connection.
*/
static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
{
@ -182,10 +183,10 @@ static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
.last_sent = current_time(),
.send_counter = 127,
/* add randomness to timeout to prevent connections getting stuck in a loop. */
/* Add randomness to timeout to prevent connections getting stuck in a loop. */
.timeout = timeout,
/* if this connection isn't handled within the timeout kill it. */
/* If this connection isn't handled within the timeout kill it. */
.killat = current_time() + 1000000UL * timeout
};
++ludp->connections_number;
@ -197,8 +198,8 @@ static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
}
/*
* Returns an integer corresponding to the next connection in our incoming connection list.
* Return -1 if there are no new incoming connections in the list.
* return an integer corresponding to the next connection in our incoming connection list.
* return -1 if there are no new incoming connections in the list.
*/
int incoming_connection(Lossless_UDP *ludp)
{
@ -244,8 +245,8 @@ static void free_connections(Lossless_UDP *ludp)
}
/*
* Return -1 if it could not kill the connection.
* Return 0 if killed successfully
* return -1 if it could not kill the connection.
* return 0 if killed successfully.
*/
int kill_connection(Lossless_UDP *ludp, int connection_id)
{
@ -264,8 +265,8 @@ int kill_connection(Lossless_UDP *ludp, int connection_id)
/*
* Kill connection in seconds.
* Return -1 if it can not kill the connection.
* Return 0 if it will kill it.
* return -1 if it can not kill the connection.
* return 0 if it will kill it.
*/
int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds)
{
@ -281,11 +282,11 @@ int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds)
/*
* Check if connection is connected:
* Return 0 no.
* Return 1 if attempting handshake.
* Return 2 if handshake is done.
* Return 3 if fully connected.
* Return 4 if timed out and waiting to be killed.
* return 0 no.
* return 1 if attempting handshake.
* return 2 if handshake is done.
* return 3 if fully connected.
* return 4 if timed out and waiting to be killed.
*/
int is_connected(Lossless_UDP *ludp, int connection_id)
{
@ -295,7 +296,7 @@ int is_connected(Lossless_UDP *ludp, int connection_id)
return 0;
}
/* returns the ip_port of the corresponding connection. */
/* return the ip_port of the corresponding connection. */
IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
{
if (connection_id >= 0 && connection_id < ludp->connections_length)
@ -314,7 +315,7 @@ uint32_t sendqueue(Lossless_UDP *ludp, int connection_id)
return ludp->connections[connection_id].sendbuff_packetnum - ludp->connections[connection_id].successful_sent;
}
/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */
/* returns the number of packets in the queue waiting to be successfully read with read_packet(...). */
uint32_t recvqueue(Lossless_UDP *ludp, int connection_id)
{
if (connection_id < 0 || connection_id >= ludp->connections_length)
@ -323,8 +324,9 @@ uint32_t recvqueue(Lossless_UDP *ludp, int connection_id)
return ludp->connections[connection_id].recv_packetnum - ludp->connections[connection_id].successful_read;
}
/* returns the id of the next packet in the queue
return -1 if no packet in queue */
/* returns the id of the next packet in the queue.
* return -1 if no packet in queue.
*/
char id_packet(Lossless_UDP *ludp, int connection_id)
{
if (connection_id < 0 || connection_id >= ludp->connections_length)
@ -338,7 +340,8 @@ char id_packet(Lossless_UDP *ludp, int connection_id)
}
/* return 0 if there is no received data in the buffer.
return length of received packet if successful */
* return length of received packet if successful.
*/
int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data)
{
if (recvqueue(ludp, connection_id) != 0) {
@ -354,8 +357,8 @@ int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data)
}
/*
* Return 0 if data could not be put in packet queue
* Return 1 if data was put into the queue
* return 0 if data could not be put in packet queue.
* return 1 if data was put into the queue.
*/
int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length)
{
@ -373,14 +376,14 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t
return 0;
}
/* put the packet numbers the we are missing in requested and return the number */
/* Put the packet numbers the we are missing in requested and return the number. */
uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested)
{
uint32_t number = 0;
uint32_t i;
uint32_t temp;
/* don't request packets if the buffer is full. */
/* Don't request packets if the buffer is full. */
if (recvqueue(ludp, connection_id) >= (BUFFER_PACKET_NUM - 1))
return 0;
@ -399,9 +402,9 @@ uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *reques
}
/*
* BEGIN Packet sending functions
* BEGIN Packet sending functions.
* One per packet type.
* see http://wiki.tox.im/index.php/Lossless_UDP for more information.
* See http://wiki.tox.im/index.php/Lossless_UDP for more information.
*/
static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
@ -459,7 +462,7 @@ static int send_data_packet(Lossless_UDP *ludp, uint32_t connection_id, uint32_t
1 + 4 + ludp->connections[connection_id].sendbuffer[index].size);
}
/* sends 1 data packet */
/* Sends 1 data packet. */
static int send_DATA(Lossless_UDP *ludp, uint32_t connection_id)
{
int ret;
@ -483,15 +486,17 @@ static int send_DATA(Lossless_UDP *ludp, uint32_t connection_id)
}
/*
* END of packet sending functions
* END of packet sending functions.
*
*
* BEGIN Packet handling functions
* One to handle each type of packets we receive
* BEGIN Packet handling functions.
* One to handle each type of packets we receive.
*/
/* Return 0 if handled correctly, 1 if packet is bad. */
/* return 0 if handled correctly.
* return 1 if packet is bad.
*/
static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint32_t length)
{
Lossless_UDP *ludp = object;
@ -516,11 +521,12 @@ static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint3
if (is_connected(ludp, connection) != 1)
return 1;
/* if handshake_id2 is what we sent previously as handshake_id1 */
/* If handshake_id2 is what we sent previously as handshake_id1. */
if (handshake_id2 == ludp->connections[connection].handshake_id1) {
ludp->connections[connection].status = 2;
/* NOTE: is this necessary?
ludp->connections[connection].handshake_id2 = handshake_id1; */
* ludp->connections[connection].handshake_id2 = handshake_id1;
*/
ludp->connections[connection].orecv_packetnum = handshake_id2;
ludp->connections[connection].osent_packetnum = handshake_id1;
ludp->connections[connection].recv_packetnum = handshake_id1;
@ -593,7 +599,7 @@ static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter,
uint32_t comp_1 = (recv_packetnum - ludp->connections[connection_id].orecv_packetnum);
uint32_t comp_2 = (sent_packetnum - ludp->connections[connection_id].osent_packetnum);
/* packet valid */
/* Packet valid. */
if (comp_1 <= BUFFER_PACKET_NUM &&
comp_2 <= BUFFER_PACKET_NUM &&
comp_counter < 10 && comp_counter != 0) {
@ -657,7 +663,9 @@ static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t l
/*
* Add a packet to the received buffer and set the recv_packetnum of the
* connection to its proper value. Return 1 if data was too big, 0 if not.
* connection to its proper value.
* return 1 if data was too big.
* return 0 if not.
*/
static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
{
@ -719,7 +727,7 @@ static int handle_data(void *object, IP_Port source, uint8_t *packet, uint32_t l
}
/*
* END of packet handling functions
* END of packet handling functions.
*/
Lossless_UDP *new_lossless_udp(Networking_Core *net)
@ -740,8 +748,8 @@ Lossless_UDP *new_lossless_udp(Networking_Core *net)
}
/*
* Send handshake requests
* handshake packets are sent at the same rate as SYNC packets
* Send handshake requests.
* Handshake packets are sent at the same rate as SYNC packets.
*/
static void do_new(Lossless_UDP *ludp)
{
@ -755,7 +763,7 @@ static void do_new(Lossless_UDP *ludp)
ludp->connections[i].last_sent = temp_time;
}
/* kill all timed out connections */
/* Kill all timed out connections. */
if (ludp->connections[i].status > 0 &&
(ludp->connections[i].last_recvSYNC + ludp->connections[i].timeout * 1000000UL) < temp_time &&
ludp->connections[i].status != 4) {
@ -803,7 +811,7 @@ static void do_data(Lossless_UDP *ludp)
/*
* Automatically adjusts send rates of packets for optimal transmission.
*
* TODO: flow control.
* TODO: Flow control.
*/
static void adjust_rates(Lossless_UDP *ludp)
{

View File

@ -27,22 +27,22 @@
#include "network.h"
/* maximum length of the data in the data packets */
/* Maximum length of the data in the data packets. */
#define MAX_DATA_SIZE 1024
/* maximum data packets in sent and receive queues. */
/* Maximum data packets in sent and receive queues. */
#define MAX_QUEUE_NUM 16
/* maximum number of data packets in the buffer */
/* Maximum number of data packets in the buffer. */
#define BUFFER_PACKET_NUM (16-1)
/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
/* Timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT. */
#define CONNEXION_TIMEOUT 5
/* initial amount of sync/hanshake packets to send per second. */
/* Initial amount of sync/hanshake packets to send per second. */
#define SYNC_RATE 2
/* initial send rate of data. */
/* Initial send rate of data. */
#define DATA_SYNC_RATE 30
typedef struct {
@ -54,27 +54,29 @@ typedef struct {
IP_Port ip_port;
/*
* 0 if connection is dead, 1 if attempting handshake,
* 2 if handshake is done (we start sending SYNC packets)
* 3 if we are sending SYNC packets and can send data
* 4 if the connection has timed out.
* return 0 if connection is dead.
* return 1 if attempting handshake.
* return 2 if handshake is done (we start sending SYNC packets).
* return 3 if we are sending SYNC packets and can send data.
* return 4 if the connection has timed out.
*/
uint8_t status;
/*
* 1 or 2 if connection was initiated by someone else, 0 if not.
* 2 if incoming_connection() has not returned it yet, 1 if it has.
* return 0 if connection was not initiated by someone else.
* return 1 if incoming_connection() has returned.
* return 2 if it has not.
*/
uint8_t inbound;
uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */
uint16_t data_rate; /* current data packet send rate packets per second. */
uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */
uint16_t data_rate; /* Current data packet send rate packets per second. */
uint64_t last_SYNC; /* time our last SYNC packet was sent. */
uint64_t last_sent; /* time our last data or handshake packet was sent. */
uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */
uint64_t last_recvdata; /* time we last received a DATA packet from the other */
uint64_t killat; /* time to kill the connection */
uint64_t last_SYNC; /* Time our last SYNC packet was sent. */
uint64_t last_sent; /* Time our last data or handshake packet was sent. */
uint64_t last_recvSYNC; /* Time we last received a SYNC packet from the other. */
uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */
uint64_t killat; /* Time to kill the connection. */
Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */
Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */
@ -82,31 +84,31 @@ typedef struct {
uint32_t handshake_id1;
uint32_t handshake_id2;
/* number of data packets received (also used as handshake_id1) */
/* Number of data packets received (also used as handshake_id1). */
uint32_t recv_packetnum;
/* number of packets received by the other peer */
/* Number of packets received by the other peer. */
uint32_t orecv_packetnum;
/* number of data packets sent */
/* Number of data packets sent. */
uint32_t sent_packetnum;
/* number of packets sent by the other peer. */
/* Number of packets sent by the other peer. */
uint32_t osent_packetnum;
/* number of latest packet written onto the sendbuffer */
/* Number of latest packet written onto the sendbuffer. */
uint32_t sendbuff_packetnum;
/* we know all packets before that number were successfully sent */
/* We know all packets before that number were successfully sent. */
uint32_t successful_sent;
/* packet number of last packet read with the read_packet function */
/* Packet number of last packet read with the read_packet function. */
uint32_t successful_read;
/* list of currently requested packet numbers(by the other person) */
/* List of currently requested packet numbers(by the other person). */
uint32_t req_packets[BUFFER_PACKET_NUM];
/* total number of currently requested packets(by the other person) */
/* Total number of currently requested packets(by the other person). */
uint16_t num_req_paquets;
uint8_t recv_counter;
@ -118,96 +120,94 @@ typedef struct {
Networking_Core *net;
Connection *connections;
uint32_t connections_length; /* Length of connections array */
uint32_t connections_number; /* Number of connections in connections array */
uint32_t connections_length; /* Length of connections array. */
uint32_t connections_number; /* Number of connections in connections array. */
/* table of random numbers used in handshake_id. */
/* Table of random numbers used in handshake_id. */
uint32_t randtable[6][256];
} Lossless_UDP;
/*
* Initialize a new connection to ip_port
* Returns an integer corresponding to the connection id.
* Return -1 if it could not initialize the connection.
* Return number if there already was an existing connection to that ip_port.
* Initialize a new connection to ip_port.
* return an integer corresponding to the connection id.
* return -1 if it could not initialize the connection.
* return number if there already was an existing connection to that ip_port.
*/
int new_connection(Lossless_UDP *ludp, IP_Port ip_port);
/*
* Get connection id from IP_Port.
* Return -1 if there are no connections like we are looking for.
* Return id if it found it .
* return -1 if there are no connections like we are looking for.
* return id if it found it .
*/
int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port);
/*
* Returns an int corresponding to the next connection in our imcoming connection list
* Return -1 if there are no new incoming connections in the list.
* return an integer corresponding to the next connection in our imcoming connection list.
* return -1 if there are no new incoming connections in the list.
*/
int incoming_connection(Lossless_UDP *ludp);
/*
* Return -1 if it could not kill the connection.
* Return 0 if killed successfully
* return -1 if it could not kill the connection.
* return 0 if killed successfully.
*/
int kill_connection(Lossless_UDP *ludp, int connection_id);
/*
* Kill connection in seconds seconds.
* Return -1 if it can not kill the connection.
* Return 0 if it will kill it
* return -1 if it can not kill the connection.
* return 0 if it will kill it.
*/
int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds);
/*
* Returns the ip_port of the corresponding connection.
* Return 0 if there is no such connection.
* returns the ip_port of the corresponding connection.
* return 0 if there is no such connection.
*/
IP_Port connection_ip(Lossless_UDP *ludp, int connection_id);
/*
* Returns the id of the next packet in the queue
* Return -1 if no packet in queue
* returns the id of the next packet in the queue.
* return -1 if no packet in queue.
*/
char id_packet(Lossless_UDP *ludp, int connection_id);
/*
* Return 0 if there is no received data in the buffer.
* Return length of received packet if successful
* return 0 if there is no received data in the buffer.
* return length of received packet if successful.
*/
int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data);
/*
* Return 0 if data could not be put in packet queue
* Return 1 if data was put into the queue
* return 0 if data could not be put in packet queue.
* return 1 if data was put into the queue.
*/
int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length);
/* Returns the number of packets in the queue waiting to be successfully sent. */
/* returns the number of packets in the queue waiting to be successfully sent. */
uint32_t sendqueue(Lossless_UDP *ludp, int connection_id);
/*
* returns the number of packets in the queue waiting to be successfully
* read with read_packet(...)
* return the number of packets in the queue waiting to be successfully
* read with read_packet(...).
*/
uint32_t recvqueue(Lossless_UDP *ludp, int connection_id);
/* Check if connection is connected:
* Return 0 no.
* Return 1 if attempting handshake.
* Return 2 if handshake is done.
* Return 3 if fully connected.
* Return 4 if timed out and wating to be killed.
* return 0 not.
* return 1 if attempting handshake.
* return 2 if handshake is done.
* return 3 if fully connected.
* return 4 if timed out and wating to be killed.
*/
int is_connected(Lossless_UDP *ludp, int connection_id);
/* Call this function a couple times per second It's the main loop. */
void do_lossless_udp(Lossless_UDP *ludp);
/*
* This function sets up LosslessUDP packet handling.
*/
/* This function sets up LosslessUDP packet handling. */
Lossless_UDP *new_lossless_udp(Networking_Core *net);
void kill_lossless_udp(Lossless_UDP *ludp);

View File

@ -28,12 +28,14 @@
static void set_friend_status(Messenger *m, int friendnumber, uint8_t status);
static int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length);
/* 1 if we are online
0 if we are offline
static uint8_t online; */
/* return 1 if we are online.
* return 0 if we are offline.
* static uint8_t online;
*/
/* set the size of the friend list to numfriends
return -1 if realloc fails */
/* Set the size of the friend list to numfriends.
* return -1 if realloc fails.
*/
int realloc_friendlist(Messenger *m, uint32_t num)
{
if (num == 0) {
@ -52,7 +54,8 @@ int realloc_friendlist(Messenger *m, uint32_t num)
}
/* return the friend id associated to that public key.
return -1 if no such friend */
* return -1 if no such friend.
*/
int getfriend_id(Messenger *m, uint8_t *client_id)
{
uint32_t i;
@ -66,10 +69,11 @@ int getfriend_id(Messenger *m, uint8_t *client_id)
return -1;
}
/* copies the public key associated to that friend id into client_id buffer.
make sure that client_id is of size CLIENT_ID_SIZE.
return 0 if success
return -1 if failure. */
/* Copies the public key associated to that friend id into client_id buffer.
* Make sure that client_id is of size CLIENT_ID_SIZE.
* return 0 if success.
* return -1 if failure.
*/
int getclient_id(Messenger *m, int friend_id, uint8_t *client_id)
{
if (friend_id >= m->numfriends || friend_id < 0)
@ -83,7 +87,7 @@ int getclient_id(Messenger *m, int friend_id, uint8_t *client_id)
return -1;
}
/*
* returns a uint16_t that represents the checksum of address of length len
* return a uint16_t that represents the checksum of address of length len.
*
* TODO: Another checksum algorithm might be better.
*/
@ -101,8 +105,8 @@ static uint16_t address_checksum(uint8_t *address, uint32_t len)
}
/*
* returns a FRIEND_ADDRESS_SIZE byte address to give to others.
* format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
* return FRIEND_ADDRESS_SIZE byte address to give to others.
* Format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
*
*/
void getaddress(Messenger *m, uint8_t *address)
@ -115,20 +119,21 @@ void getaddress(Messenger *m, uint8_t *address)
}
/*
* add a friend
* set the data that will be sent along with friend request
* address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. TODO: add checksum.
* data is the data and length is the length
* returns the friend number if success
* return FA_TOOLONG if message length is too long
* return FAERR_NOMESSAGE if no message (message length must be >= 1 byte)
* return FAERR_OWNKEY if user's own key
* return FAERR_ALREADYSENT if friend request already sent or already a friend
* return FAERR_UNKNOWN for unknown error
* return FAERR_BADCHECKSUM if bad checksum in address
* return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different
* (the nospam for that friend was set to the new one)
* return FAERR_NOMEM if increasing the friend list size fails
* Add a friend.
* Set the data that will be sent along with friend request.
* Address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes.
* TODO: add checksum.
* data is the data and length is the length.
* return the friend number if success.
* return FA_TOOLONG if message length is too long.
* return FAERR_NOMESSAGE if no message (message length must be >= 1 byte).
* return FAERR_OWNKEY if user's own key.
* return FAERR_ALREADYSENT if friend request already sent or already a friend.
* return FAERR_UNKNOWN for unknown error.
* return FAERR_BADCHECKSUM if bad checksum in address.
* return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different.
* (the nospam for that friend was set to the new one).
* return FAERR_NOMEM if increasing the friend list size fails.
*/
int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length)
{
@ -164,7 +169,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length)
return FAERR_SETNEWNOSPAM;
}
/* resize the friend list if necessary */
/* Resize the friend list if necessary. */
if (realloc_friendlist(m, m->numfriends + 1) != 0)
return FAERR_NOMEM;
@ -186,7 +191,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length)
memcpy(m->friendlist[i].info, data, length);
m->friendlist[i].info_size = length;
m->friendlist[i].message_id = 0;
m->friendlist[i].receives_read_receipts = 1; /* default: YES */
m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
if (m->numfriends == i)
@ -204,7 +209,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id)
if (getfriend_id(m, client_id) != -1)
return -1;
/* resize the friend list if necessary */
/* Resize the friend list if necessary. */
if (realloc_friendlist(m, m->numfriends + 1) != 0)
return FAERR_NOMEM;
@ -223,7 +228,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id)
m->friendlist[i].statusmessage_length = 1;
m->friendlist[i].userstatus = USERSTATUS_NONE;
m->friendlist[i].message_id = 0;
m->friendlist[i].receives_read_receipts = 1; /* default: YES */
m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
if (m->numfriends == i)
++ m->numfriends;
@ -235,9 +240,10 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id)
return -1;
}
/* remove a friend
return 0 if success
return -1 if failure */
/* Remove a friend.
* return 0 if success.
* return -1 if failure.
*/
int m_delfriend(Messenger *m, int friendnumber)
{
if (friendnumber >= m->numfriends || friendnumber < 0)
@ -262,11 +268,12 @@ int m_delfriend(Messenger *m, int friendnumber)
return 0;
}
/* return FRIEND_ONLINE if friend is online
return FRIEND_CONFIRMED if friend is confirmed
return FRIEND_REQUESTED if the friend request was sent
return FRIEND_ADDED if the friend was added
return NOFRIEND if there is no friend with that number */
/* return FRIEND_ONLINE if friend is online.
* return FRIEND_CONFIRMED if friend is confirmed.
* return FRIEND_REQUESTED if the friend request was sent.
* return FRIEND_ADDED if the friend was added.
* return NOFRIEND if there is no friend with that number.
*/
int m_friendstatus(Messenger *m, int friendnumber)
{
if (friendnumber < 0 || friendnumber >= m->numfriends)
@ -275,9 +282,10 @@ int m_friendstatus(Messenger *m, int friendnumber)
return m->friendlist[friendnumber].status;
}
/* send a text chat message to an online friend
return the message id if packet was successfully put into the send queue
return 0 if it was not */
/* Send a text chat message to an online friend.
* return the message id if packet was successfully put into the send queue.
* return 0 if it was not.
*/
uint32_t m_sendmessage(Messenger *m, int friendnumber, uint8_t *message, uint32_t length)
{
if (friendnumber < 0 || friendnumber >= m->numfriends)
@ -286,7 +294,7 @@ uint32_t m_sendmessage(Messenger *m, int friendnumber, uint8_t *message, uint32_
uint32_t msgid = ++m->friendlist[friendnumber].message_id;
if (msgid == 0)
msgid = 1; /* otherwise, false error */
msgid = 1; // Otherwise, false error
if (m_sendmessage_withid(m, friendnumber, msgid, message, length)) {
return msgid;
@ -307,16 +315,18 @@ uint32_t m_sendmessage_withid(Messenger *m, int friendnumber, uint32_t theid, ui
return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE, temp, length + sizeof(theid));
}
/* send an action to an online friend
return 1 if packet was successfully put into the send queue
return 0 if it was not */
/* Send an action to an online friend.
* return 1 if packet was successfully put into the send queue.
* return 0 if it was not.
*/
int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t length)
{
return write_cryptpacket_id(m, friendnumber, PACKET_ID_ACTION, action, length);
}
/* send a name packet to friendnumber
length is the length with the NULL terminator*/
/* Send a name packet to friendnumber.
* length is the length with the NULL terminator.
*/
static int m_sendname(Messenger *m, int friendnumber, uint8_t *name, uint16_t length)
{
if (length > MAX_NAME_LENGTH || length == 0)
@ -325,9 +335,10 @@ static int m_sendname(Messenger *m, int friendnumber, uint8_t *name, uint16_t le
return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length);
}
/* set the name of a friend
return 0 if success
return -1 if failure */
/* Set the name of a friend.
* return 0 if success.
* return -1 if failure.
*/
static int setfriendname(Messenger *m, int friendnumber, uint8_t *name)
{
if (friendnumber >= m->numfriends || friendnumber < 0)
@ -338,11 +349,12 @@ static int setfriendname(Messenger *m, int friendnumber, uint8_t *name)
}
/* Set our nickname
name must be a string of maximum MAX_NAME_LENGTH length.
length must be at least 1 byte
length is the length of name with the NULL terminator
return 0 if success
return -1 if failure */
* name must be a string of maximum MAX_NAME_LENGTH length.
* length must be at least 1 byte.
* length is the length of name with the NULL terminator.
* return 0 if success.
* return -1 if failure.
*/
int setname(Messenger *m, uint8_t *name, uint16_t length)
{
if (length > MAX_NAME_LENGTH || length == 0)
@ -358,10 +370,10 @@ int setname(Messenger *m, uint8_t *name, uint16_t length)
return 0;
}
/* get our nickname
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
return the length of the name */
/* Get our nickname and put it in name.
* Name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
* return the length of the name.
*/
uint16_t getself_name(Messenger *m, uint8_t *name, uint16_t nlen)
{
uint16_t len;
@ -376,11 +388,11 @@ uint16_t getself_name(Messenger *m, uint8_t *name, uint16_t nlen)
return len;
}
/* get name of friendnumber
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
return 0 if success
return -1 if failure */
/* Get name of friendnumber and put it in name.
* Name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
* return 0 if success.
* return -1 if failure.
*/
int getname(Messenger *m, int friendnumber, uint8_t *name)
{
if (friendnumber >= m->numfriends || friendnumber < 0)
@ -421,8 +433,9 @@ int m_set_userstatus(Messenger *m, USERSTATUS status)
return 0;
}
/* return the size of friendnumber's user status
guaranteed to be at most MAX_STATUSMESSAGE_LENGTH */
/* return the size of friendnumber's user status.
* Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH.
*/
int m_get_statusmessage_size(Messenger *m, int friendnumber)
{
if (friendnumber >= m->numfriends || friendnumber < 0)
@ -431,8 +444,9 @@ int m_get_statusmessage_size(Messenger *m, int friendnumber)
return m->friendlist[friendnumber].statusmessage_length;
}
/* copy the user status of friendnumber into buf, truncating if needed to maxlen
bytes, use m_get_statusmessage_size to find out how much you need to allocate */
/* Copy the user status of friendnumber into buf, truncating if needed to maxlen
* bytes, use m_get_statusmessage_size to find out how much you need to allocate.
*/
int m_copy_statusmessage(Messenger *m, int friendnumber, uint8_t *buf, uint32_t maxlen)
{
if (friendnumber >= m->numfriends || friendnumber < 0)
@ -517,13 +531,13 @@ void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno)
}
/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); */
/* set the function that will be executed when a friend request is received. */
/* Set the function that will be executed when a friend request is received. */
void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata)
{
callback_friendrequest(&(m->fr), function, userdata);
}
/* set the function that will be executed when a message from a friend is received. */
/* Set the function that will be executed when a message from a friend is received. */
void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *),
void *userdata)
{
@ -607,11 +621,11 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint
return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1);
}
/*Interval in seconds between LAN discovery packet sending*/
/* Interval in seconds between LAN discovery packet sending. */
#define LAN_DISCOVERY_INTERVAL 60
#define PORT 33445
/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
static void LANdiscovery(Messenger *m)
{
if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
@ -620,7 +634,7 @@ static void LANdiscovery(Messenger *m)
}
}
/* run this at startup */
/* Run this at startup. */
Messenger *initMessenger(void)
{
Messenger *m = calloc(1, sizeof(Messenger));
@ -664,11 +678,11 @@ Messenger *initMessenger(void)
return m;
}
/* run this before closing shop */
/* Run this before closing shop. */
void cleanupMessenger(Messenger *m)
{
/* FIXME TODO ideally cleanupMessenger will mirror initMessenger
* this requires the other modules to expose cleanup functions
/* FIXME TODO: ideally cleanupMessenger will mirror initMessenger.
* This requires the other modules to expose cleanup functions.
*/
kill_DHT(m->dht);
kill_net_crypto(m->net_crypto);
@ -677,10 +691,10 @@ void cleanupMessenger(Messenger *m)
free(m);
}
//TODO: make this function not suck.
/* TODO: Make this function not suck. */
void doFriends(Messenger *m)
{
/* TODO: add incoming connections and some other stuff. */
/* TODO: Add incoming connections and some other stuff. */
uint32_t i;
int len;
uint8_t temp[MAX_DATA_SIZE];
@ -699,14 +713,16 @@ void doFriends(Messenger *m)
}
if (m->friendlist[i].status == FRIEND_REQUESTED
|| m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
|| m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */
if (m->friendlist[i].status == FRIEND_REQUESTED) {
/* If we didn't connect to friend after successfully sending him a friend request the request is deemed
unsuccessful so we set the status back to FRIEND_ADDED and try again.*/
* unsuccessful so we set the status back to FRIEND_ADDED and try again.
*/
if (m->friendlist[i].friendrequest_lastsent + m->friendlist[i].friendrequest_timeout < temp_time) {
set_friend_status(m, i, FRIEND_ADDED);
/* Double the default timeout everytime if friendrequest is assumed to have been
sent unsuccessfully. */
* sent unsuccessfully.
*/
m->friendlist[i].friendrequest_timeout *= 2;
}
}
@ -720,7 +736,7 @@ void doFriends(Messenger *m)
break;
case 3: /* Connection is established */
case 3: /* Connection is established. */
set_friend_status(m, i, FRIEND_ONLINE);
m->friendlist[i].name_sent = 0;
m->friendlist[i].userstatus_sent = 0;
@ -738,7 +754,7 @@ void doFriends(Messenger *m)
}
}
while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
if (m->friendlist[i].name_sent == 0) {
if (m_sendname(m, i, m->name, m->name_length))
m->friendlist[i].name_sent = 1;
@ -778,7 +794,7 @@ void doFriends(Messenger *m)
m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata);
memcpy(m->friendlist[i].name, data, data_length);
m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
m->friendlist[i].name[data_length - 1] = 0; /* Make sure the NULL terminator is present. */
break;
}
@ -851,7 +867,7 @@ void doFriends(Messenger *m)
}
} else {
if (is_cryptoconnected(m->net_crypto,
m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
m->friendlist[i].crypt_connection_id) == 4) { /* If the connection timed out, kill it. */
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
m->friendlist[i].crypt_connection_id = -1;
set_friend_status(m, i, FRIEND_CONFIRMED);
@ -861,7 +877,7 @@ void doFriends(Messenger *m)
}
if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
/* if we stopped recieving ping packets kill it */
/* If we stopped recieving ping packets, kill it. */
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
m->friendlist[i].crypt_connection_id = -1;
set_friend_status(m, i, FRIEND_CONFIRMED);
@ -890,7 +906,7 @@ void doInbound(Messenger *m)
}
}
/* the main loop that needs to be run at least 20 times per second. */
/* The main loop that needs to be run at least 20 times per second. */
void doMessenger(Messenger *m)
{
networking_poll(m->net);
@ -902,21 +918,21 @@ void doMessenger(Messenger *m)
LANdiscovery(m);
}
/* returns the size of the messenger data (for saving) */
/* return the size of the messenger data (for saving) */
uint32_t Messenger_size(Messenger *m)
{
return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
+ sizeof(uint32_t) // nospam
+ sizeof(uint32_t) // DHT size
+ DHT_size(m->dht) // DHT itself
+ sizeof(uint32_t) // Friendlist size
+ sizeof(Friend) * m->numfriends // Friendlist itself
+ sizeof(uint16_t) // Own nickname length
+ m->name_length // Own nickname
+ sizeof(uint32_t) // nospam.
+ sizeof(uint32_t) // DHT size.
+ DHT_size(m->dht) // DHT itself.
+ sizeof(uint32_t) // Friendlist size.
+ sizeof(Friend) * m->numfriends // Friendlist itself.
+ sizeof(uint16_t) // Own nickname length.
+ m->name_length // Own nickname.
;
}
/* save the messenger in data of size Messenger_size() */
/* Save the messenger in data of size Messenger_size(). */
void Messenger_save(Messenger *m, uint8_t *data)
{
save_keys(m->net_crypto, data);
@ -940,7 +956,7 @@ void Messenger_save(Messenger *m, uint8_t *data)
memcpy(data, m->name, small_size);
}
/* load the messenger from data of size length. */
/* Load the messenger from data of size length. */
int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
{
if (length == ~0)
@ -988,7 +1004,7 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
setfriendname(m, fnum, temp[i].name);
/* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */
} else if (temp[i].status != 0) {
/* TODO: this is not a good way to do this. */
/* TODO: This is not a good way to do this. */
uint8_t address[FRIEND_ADDRESS_SIZE];
memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES);
memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t));

View File

@ -45,7 +45,7 @@
#define PACKET_ID_ACTION 63
/* status definitions */
/* Status definitions. */
enum {
NOFRIEND,
FRIEND_ADDED,
@ -54,8 +54,9 @@ enum {
FRIEND_ONLINE,
};
/* errors for m_addfriend
* FAERR - Friend Add Error */
/* Errors for m_addfriend
* FAERR - Friend Add Error
*/
enum {
FAERR_TOOLONG = -1,
FAERR_NOMESSAGE = -2,
@ -67,20 +68,22 @@ enum {
FAERR_NOMEM = -8
};
/* don't assume MAX_STATUSMESSAGE_LENGTH will stay at 128, it may be increased
to an absurdly large number later */
/* Don't assume MAX_STATUSMESSAGE_LENGTH will stay at 128, it may be increased
* to an absurdly large number later.
*/
/* Default start timeout in seconds between friend requests */
/* Default start timeout in seconds between friend requests. */
#define FRIENDREQUEST_TIMEOUT 5;
/* interval between the sending of ping packets.*/
/* Interval between the sending of ping packets. */
#define FRIEND_PING_INTERVAL 5
/* If no packets are recieved from friend in this time interval, kill the connection.*/
/* If no packets are recieved from friend in this time interval, kill the connection. */
#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 2)
/* USERSTATUS
* Represents userstatuses someone can have. */
/* USERSTATUS -
* Represents userstatuses someone can have.
*/
typedef enum {
USERSTATUS_NONE,
@ -93,21 +96,21 @@ USERSTATUS;
typedef struct {
uint8_t client_id[CLIENT_ID_SIZE];
int crypt_connection_id;
uint64_t friendrequest_lastsent; /* time at which the last friend request was sent. */
uint32_t friendrequest_timeout; /* The timeout between successful friendrequest sending attempts */
uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */
uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */
uint64_t friendrequest_lastsent; // Time at which the last friend request was sent.
uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts.
uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online.
uint8_t info[MAX_DATA_SIZE]; // the data that is sent during the friend requests we do.
uint8_t name[MAX_NAME_LENGTH];
uint8_t name_sent; /* 0 if we didn't send our name to this friend 1 if we have. */
uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have.
uint8_t *statusmessage;
uint16_t statusmessage_length;
uint8_t statusmessage_sent;
USERSTATUS userstatus;
uint8_t userstatus_sent;
uint16_t info_size; /* length of the info */
uint32_t message_id; /* a semi-unique id used in read receipts */
uint8_t receives_read_receipts; /* shall we send read receipts to this person? */
uint32_t friendrequest_nospam; /*The nospam number used in the friend request*/
uint16_t info_size; // Length of the info.
uint32_t message_id; // a semi-unique id used in read receipts.
uint8_t receives_read_receipts; // shall we send read receipts to this person?
uint32_t friendrequest_nospam; // The nospam number used in the friend request.
uint64_t ping_lastrecv;
uint64_t ping_lastsent;
} Friend;
@ -152,192 +155,221 @@ typedef struct Messenger {
} Messenger;
/*
* returns a FRIEND_ADDRESS_SIZE byte address to give to others.
* format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
* return FRIEND_ADDRESS_SIZE byte address to give to others.
* Format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
*
*/
void getaddress(Messenger *m, uint8_t *address);
/*
* add a friend
* set the data that will be sent along with friend request
* Add a friend.
* Set the data that will be sent along with friend request.
* address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. TODO: add checksum.
* data is the data and length is the length
* returns the friend number if success
* return -1 if message length is too long
* return -2 if no message (message length must be >= 1 byte)
* return -3 if user's own key
* return -4 if friend request already sent or already a friend
* return -5 for unknown error
* return -6 if bad checksum in address
* return -7 if the friend was already there but the nospam was different
* (the nospam for that friend was set to the new one)
* return -8 if increasing the friend list size fails
* data is the data and length is the length.
* returns the friend number if success.
* return -1 if message length is too long.
* return -2 if no message (message length must be >= 1 byte).
* return -3 if user's own key.
* return -4 if friend request already sent or already a friend.
* return -5 for unknown error.
* return -6 if bad checksum in address.
* return -7 if the friend was already there but the nospam was different.
* (the nospam for that friend was set to the new one).
* return -8 if increasing the friend list size fails.
*/
int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length);
/* add a friend without sending a friendrequest.
returns the friend number if success
return -1 if failure. */
/* Add a friend without sending a friendrequest.
* return the friend number if success.
* return -1 if failure.
*/
int m_addfriend_norequest(Messenger *m, uint8_t *client_id);
/* return the friend id associated to that client id.
return -1 if no such friend */
* return -1 if no such friend.
*/
int getfriend_id(Messenger *m, uint8_t *client_id);
/* copies the public key associated to that friend id into client_id buffer.
make sure that client_id is of size CLIENT_ID_SIZE.
return 0 if success
return -1 if failure */
/* Copies the public key associated to that friend id into client_id buffer.
* Make sure that client_id is of size CLIENT_ID_SIZE.
* return 0 if success
* return -1 if failure
*/
int getclient_id(Messenger *m, int friend_id, uint8_t *client_id);
/* remove a friend */
/* Remove a friend. */
int m_delfriend(Messenger *m, int friendnumber);
/* return 4 if friend is online
return 3 if friend is confirmed
return 2 if the friend request was sent
return 1 if the friend was added
return 0 if there is no friend with that number */
/* return 4 if friend is online.
* return 3 if friend is confirmed.
* return 2 if the friend request was sent.
* return 1 if the friend was added.
* return 0 if there is no friend with that number.
*/
int m_friendstatus(Messenger *m, int friendnumber);
/* send a text chat message to an online friend
returns the message id if packet was successfully put into the send queue
return 0 if it was not
you will want to retain the return value, it will be passed to your read receipt callback
if one is received.
m_sendmessage_withid will send a message with the id of your choosing,
however we can generate an id for you by calling plain m_sendmessage. */
/* Send a text chat message to an online friend.
* return the message id if packet was successfully put into the send queue.
* return 0 if it was not.
*
* You will want to retain the return value, it will be passed to your read receipt callback
* if one is received.
* m_sendmessage_withid will send a message with the id of your choosing,
* however we can generate an id for you by calling plain m_sendmessage.
*/
uint32_t m_sendmessage(Messenger *m, int friendnumber, uint8_t *message, uint32_t length);
uint32_t m_sendmessage_withid(Messenger *m, int friendnumber, uint32_t theid, uint8_t *message, uint32_t length);
/* send an action to an online friend
returns 1 if packet was successfully put into the send queue
return 0 if it was not */
/* Send an action to an online friend.
* return 1 if packet was successfully put into the send queue.
* return 0 if it was not.
*/
int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t length);
/* Set our nickname
name must be a string of maximum MAX_NAME_LENGTH length.
length must be at least 1 byte
length is the length of name with the NULL terminator
return 0 if success
return -1 if failure */
/* Set our nickname.
* name must be a string of maximum MAX_NAME_LENGTH length.
* length must be at least 1 byte.
* length is the length of name with the NULL terminator.
* return 0 if success.
* return -1 if failure.
*/
int setname(Messenger *m, uint8_t *name, uint16_t length);
/*
Get your nickname.
m The messanger context to use.
name Pointer to a string for the name.
nlen The length of the string buffer.
returns Return the length of the name, 0 on error.
*/
* Get your nickname.
* m - The messanger context to use.
* name - Pointer to a string for the name.
* nlen - The length of the string buffer.
* return length of the name.
* return 0 on error.
*/
uint16_t getself_name(Messenger *m, uint8_t *name, uint16_t nlen);
/* get name of friendnumber
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
return 0 if success
return -1 if failure */
/* Get name of friendnumber and put it in name.
* name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
* return 0 if success.
* return -1 if failure.
*/
int getname(Messenger *m, int friendnumber, uint8_t *name);
/* set our user status
you are responsible for freeing status after
returns 0 on success, -1 on failure */
/* Set our user status.
* You are responsible for freeing status after.
* returns 0 on success.
* returns -1 on failure.
*/
int m_set_statusmessage(Messenger *m, uint8_t *status, uint16_t length);
int m_set_userstatus(Messenger *m, USERSTATUS status);
/* return the length of friendnumber's status message,
including null
pass it into malloc */
* including null.
* Pass it into malloc.
*/
int m_get_statusmessage_size(Messenger *m, int friendnumber);
/* copy friendnumber's status message into buf, truncating if size is over maxlen
get the size you need to allocate from m_get_statusmessage_size
The self variant will copy our own status message. */
/* Copy friendnumber's status message into buf, truncating if size is over maxlen.
* Get the size you need to allocate from m_get_statusmessage_size.
* The self variant will copy our own status message.
*/
int m_copy_statusmessage(Messenger *m, int friendnumber, uint8_t *buf, uint32_t maxlen);
int m_copy_self_statusmessage(Messenger *m, uint8_t *buf, uint32_t maxlen);
/* Return one of USERSTATUS values.
/* return one of USERSTATUS values.
* Values unknown to your application should be represented as USERSTATUS_NONE.
* As above, the self variant will return our own USERSTATUS.
* If friendnumber is invalid, this shall return USERSTATUS_INVALID. */
* If friendnumber is invalid, this shall return USERSTATUS_INVALID.
*/
USERSTATUS m_get_userstatus(Messenger *m, int friendnumber);
USERSTATUS m_get_self_userstatus(Messenger *m);
/* Sets whether we send read receipts for friendnumber.
* This function is not lazy, and it will fail if yesno is not (0 or 1).*/
* This function is not lazy, and it will fail if yesno is not (0 or 1).
*/
void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno);
/* set the function that will be executed when a friend request is received.
function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
/* Set the function that will be executed when a friend request is received.
* Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length)
*/
void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata);
/* set the function that will be executed when a message from a friend is received.
function format is: function(int friendnumber, uint8_t * message, uint32_t length) */
/* Set the function that will be executed when a message from a friend is received.
* Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
*/
void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *),
void *userdata);
/* 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) */
/* 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)
*/
void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), void *userdata);
/* set the callback for name changes
function(int friendnumber, uint8_t *newname, uint16_t length)
you are not responsible for freeing newname */
/* Set the callback for name changes.
* Function(int friendnumber, uint8_t *newname, uint16_t length)
* You are not responsible for freeing newname.
*/
void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *),
void *userdata);
/* set the callback for status message changes
function(int friendnumber, uint8_t *newstatus, uint16_t length)
you are not responsible for freeing newstatus */
/* Set the callback for status message changes.
* function(int friendnumber, uint8_t *newstatus, uint16_t length)
*
* You are not responsible for freeing newstatus
*/
void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *),
void *userdata);
/* set the callback for status type changes
function(int friendnumber, USERSTATUS kind) */
/* Set the callback for status type changes.
* function(int friendnumber, USERSTATUS kind)
*/
void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void *), void *userdata);
/* set the callback for read receipts
function(int friendnumber, uint32_t receipt)
if you are keeping a record of returns from m_sendmessage,
receipt might be one of those values, and that means the message
has been received on the other side. since core doesn't
track ids for you, receipt may not correspond to any message
in that case, you should discard it. */
/* Set the callback for read receipts.
* function(int friendnumber, uint32_t receipt)
*
* If you are keeping a record of returns from m_sendmessage,
* receipt might be one of those values, meaning the message
* has been received on the other side.
* Since core doesn't track ids for you, receipt may not correspond to any message.
* In that case, you should discard it.
*/
void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void *), void *userdata);
/* set the callback for connection status changes
function(int friendnumber, uint8_t status)
status:
0 -- friend went offline after being previously online
1 -- friend went online
note that this callback is not called when adding friends, thus the "after
being previously online" part. it's assumed that when adding friends,
their connection status is offline. */
/* Set the callback for connection status changes.
* function(int friendnumber, uint8_t status)
*
* Status:
* 0 -- friend went offline after being previously online.
* 1 -- friend went online.
*
* Note that this callback is not called when adding friends, thus the "after
* being previously online" part.
* It's assumed that when adding friends, their connection status is offline.
*/
void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *), void *userdata);
/* run this at startup
* returns allocated instance of Messenger on success
* returns 0 if there are problems */
/* Run this at startup.
* returns allocated instance of Messenger on success.
* returns 0 if there are problems.
*/
Messenger *initMessenger(void);
/* run this before closing shop
* free all datastructures */
/* Run this before closing shop
* Free all datastructures.
*/
void cleanupMessenger(Messenger *M);
/* the main loop that needs to be run at least 200 times per second */
/* The main loop that needs to be run at least 20 times per second. */
void doMessenger(Messenger *m);
/* SAVING AND LOADING FUNCTIONS: */
/* returns the size of the messenger data (for saving) */
/* return size of the messenger data (for saving). */
uint32_t Messenger_size(Messenger *m);
/* save the messenger in data (must be allocated memory of size Messenger_size()) */
/* Save the messenger in data (must be allocated memory of size Messenger_size()) */
void Messenger_save(Messenger *m, uint8_t *data);
/* load the messenger from data of size length */
/* Load the messenger from data of size length. */
int Messenger_load(Messenger *m, uint8_t *data, uint32_t length);

View File

@ -23,11 +23,12 @@
#include "friend_requests.h"
/* Try to send a friendrequest to peer with public_key
data is the data in the request and length is the length.
return -1 if failure.
return 0 if it sent the friend request directly to the friend.
return the number of peers it was routed through if it did not send it directly.*/
/* Try to send a friend request to peer with public_key.
* data is the data in the request and length is the length.
* return -1 if failure.
* return 0 if it sent the friend request directly to the friend.
* return the number of peers it was routed through if it did not send it directly.
*/
int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length)
{
if (length + sizeof(nospam_num) > MAX_DATA_SIZE)
@ -65,9 +66,7 @@ int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8
}
/*
* Set and get the nospam variable used to prevent one type of friend request spam
*/
/* Set and get the nospam variable used to prevent one type of friend request spam. */
void set_nospam(Friend_Requests *fr, uint32_t num)
{
fr->nospam = num;
@ -79,7 +78,7 @@ uint32_t get_nospam(Friend_Requests *fr)
}
/* set the function that will be executed when a friend request is received. */
/* Set the function that will be executed when a friend request is received. */
void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uint8_t *, uint16_t, void *),
void *userdata)
{
@ -88,7 +87,7 @@ void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uin
fr->handle_friendrequest_userdata = userdata;
}
/*Add to list of received friend requests*/
/* Add to list of received friend requests. */
static void addto_receivedlist(Friend_Requests *fr, uint8_t *client_id)
{
if (fr->received_requests_index >= MAX_RECEIVED_STORED)
@ -98,8 +97,10 @@ static void addto_receivedlist(Friend_Requests *fr, uint8_t *client_id)
++fr->received_requests_index;
}
/* Check if a friend request was already received
return 0 if not, 1 if we did */
/* Check if a friend request was already received.
* return 0 if it did not.
* return 1 if it did.
*/
static int request_received(Friend_Requests *fr, uint8_t *client_id)
{
uint32_t i;

View File

@ -34,8 +34,9 @@ typedef struct {
uint8_t handle_friendrequest_isset;
void *handle_friendrequest_userdata;
/*NOTE: the following is just a temporary fix for the multiple friend requests received at the same time problem
TODO: Make this better (This will most likely tie in with the way we will handle spam.)*/
/* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.
* TODO: Make this better (This will most likely tie in with the way we will handle spam.)
*/
#define MAX_RECEIVED_STORED 32
@ -43,21 +44,21 @@ typedef struct {
uint16_t received_requests_index;
} Friend_Requests;
/* Try to send a friendrequest to peer with public_key
data is the data in the request and length is the length. */
int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length);
/*
* Set and get the nospam variable used to prevent one type of friend request spam
/* Try to send a friendrequest to peer with public_key.
* data is the data in the request and length is the length.
*/
int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length);
/* Set and get the nospam variable used to prevent one type of friend request spam. */
void set_nospam(Friend_Requests *fr, uint32_t num);
uint32_t get_nospam(Friend_Requests *fr);
/* set the function that will be executed when a friend request for us is received.
function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
/* Set the function that will be executed when a friend request for us is received.
* Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length)
*/
void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uint8_t *, uint16_t, void *),
void *userdata);
/* sets up friendreq packet handlers */
/* Sets up friendreq packet handlers. */
void friendreq_init(Friend_Requests *fr, Net_Crypto *c);

View File

@ -46,9 +46,10 @@ uint8_t crypto_iszero(uint8_t *mem, uint32_t length)
}
/* Precomputes the shared key from their public_key and our secret_key.
This way we can avoid an expensive elliptic curve scalar multiply for each
encrypt/decrypt operation.
enc_key has to be crypto_box_BEFORENMBYTES bytes long. */
* This way we can avoid an expensive elliptic curve scalar multiply for each
* encrypt/decrypt operation.
* enc_key has to be crypto_box_BEFORENMBYTES bytes long.
*/
void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key)
{
crypto_box_beforenm(enc_key, public_key, secret_key);
@ -64,14 +65,14 @@ int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0};
uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */
memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes.
crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, enc_key);
if (crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0)
return -1;
/* unpad the encrypted message */
/* Unpad the encrypted message. */
memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
}
@ -86,18 +87,19 @@ int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES];
uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */
memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes.
if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES,
nonce, enc_key) == -1)
return -1;
/* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero
apparently memcmp should not be used so we do this instead:*/
/* If decryption is successful the first crypto_box_ZEROBYTES of the message will be zero.
* Apparently memcmp should not be used so we do this instead:
*/
if (crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0)
return -1;
/* unpad the plain message */
/* Unpad the plain message. */
memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
}
@ -118,7 +120,7 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
return decrypt_data_fast(k, nonce, encrypted, length, plain);
}
/* increment the given nonce by 1 */
/* Increment the given nonce by 1. */
static void increment_nonce(uint8_t *nonce)
{
uint32_t i;
@ -131,7 +133,7 @@ static void increment_nonce(uint8_t *nonce)
}
}
/* fill the given nonce with random bytes. */
/* Fill the given nonce with random bytes. */
void random_nonce(uint8_t *nonce)
{
uint32_t i, temp;
@ -142,9 +144,10 @@ void random_nonce(uint8_t *nonce)
}
}
/* return 0 if there is no received data in the buffer
return -1 if the packet was discarded.
return length of received data if successful */
/* return 0 if there is no received data in the buffer.
* return -1 if the packet was discarded.
* return length of received data if successful.
*/
int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data)
{
if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length)
@ -174,8 +177,9 @@ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data)
return -1;
}
/* return 0 if data could not be put in packet queue
return 1 if data was put into the queue */
/* return 0 if data could not be put in packet queue.
* return 1 if data was put into the queue.
*/
int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length)
{
if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length)
@ -204,14 +208,16 @@ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uin
return 1;
}
/* create a request to peer.
send_public_key and send_secret_key are the pub/secret keys of the sender
recv_public_key is public key of reciever
packet must be an array of MAX_DATA_SIZE big.
Data represents the data we send with the request with length being the length of the data.
request_id is the id of the request (32 = friend request, 254 = ping request)
returns -1 on failure
returns the length of the created packet on success */
/* Ceate a request to peer.
* send_public_key and send_secret_key are the pub/secret keys of the sender.
* recv_public_key is public key of reciever.
* packet must be an array of MAX_DATA_SIZE big.
* Data represents the data we send with the request with length being the length of the data.
* request_id is the id of the request (32 = friend request, 254 = ping request).
*
* returns -1 on failure.
* returns the length of the created packet on success.
*/
int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key,
uint8_t *data, uint32_t length, uint8_t request_id)
{
@ -237,10 +243,11 @@ int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *
return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES;
}
/* puts the senders public key in the request in public_key, the data from the request
in data if a friend or ping request was sent to us and returns the length of the data.
packet is the request packet and length is its length
return -1 if not valid request. */
/* Puts the senders public key in the request in public_key, the data from the request
* in data if a friend or ping request was sent to us and returns the length of the data.
* packet is the request packet and length is its length.
* return -1 if not valid request.
*/
static int handle_request(Net_Crypto *c, uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet,
uint16_t length)
{
@ -282,7 +289,7 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui
length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
return 1;
if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us.
if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us.
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
uint8_t data[MAX_DATA_SIZE];
uint8_t number;
@ -296,8 +303,8 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui
dht->c->cryptopackethandlers[number].function(dht->c->cryptopackethandlers[number].object, source, public_key, data,
len);
} else { /* if request is not for us, try routing it. */
if (route_packet(dht, packet + 1, packet, length) == length) //NOTE
} else { /* If request is not for us, try routing it. */
if (route_packet(dht, packet + 1, packet, length) == length)
return 0;
}
}
@ -306,8 +313,9 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui
}
/* Send a crypto handshake packet containing an encrypted secret nonce and session public key
to peer with connection_id and public_key
the packet is encrypted with a random nonce which is sent in plain text with the packet */
* to peer with connection_id and public_key.
* The packet is encrypted with a random nonce which is sent in plain text with the packet.
*/
static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
uint8_t *session_key)
{
@ -332,9 +340,10 @@ static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *publi
len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
}
/* Extract secret nonce, session public key and public_key from a packet(data) with length length
return 1 if successful
return 0 if failure */
/* Extract secret nonce, session public key and public_key from a packet(data) with length length.
* return 1 if successful.
* return 0 if failure.
*/
static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce,
uint8_t *session_key, uint8_t *data, uint16_t length)
{
@ -364,9 +373,10 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s
return 1;
}
/* get crypto connection id from public key of peer
return -1 if there are no connections like we are looking for
return id if it found it */
/* Get crypto connection id from public key of peer.
* return -1 if there are no connections like we are looking for.
* return id if it found it.
*/
static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key)
{
uint32_t i;
@ -380,8 +390,9 @@ static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key)
return -1;
}
/* set the size of the friend list to numfriends
return -1 if realloc fails */
/* Set the size of the friend list to numfriends.
* return -1 if realloc fails.
*/
int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
{
if (num == 0) {
@ -399,9 +410,10 @@ int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
return 0;
}
/* Start a secure connection with other peer who has public_key and ip_port
returns -1 if failure
returns crypt_connection_id of the initialized connection if everything went well. */
/* Start a secure connection with other peer who has public_key and ip_port.
* returns -1 if failure.
* returns crypt_connection_id of the initialized connection if everything went well.
*/
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
{
uint32_t i;
@ -442,20 +454,22 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
return i;
}
return -1; /* this should never happen. */
return -1; /* This should never happen. */
}
}
return -1;
}
/* handle an incoming connection
return -1 if no crypto inbound connection
return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection
Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
and the session public key for the connection in session_key
to accept it see: accept_crypto_inbound(...)
to refuse it just call kill_connection(...) on the connection id */
/* Handle an incoming connection.
* return -1 if no crypto inbound connection.
* return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection.
*
* Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
* and the session public key for the connection in session_key.
* to accept it see: accept_crypto_inbound(...).
* to refuse it just call kill_connection(...) on the connection id.
*/
int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
{
uint32_t i;
@ -475,7 +489,7 @@ int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, ui
if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
int connection_id = c->incoming_connections[i];
c->incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */
c->incoming_connections[i] = -1; /* Remove this connection from the incoming connection list. */
return connection_id;
}
}
@ -485,9 +499,10 @@ int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, ui
return -1;
}
/* kill a crypto connection
return 0 if killed successfully
return 1 if there was a problem. */
/* Kill a crypto connection.
* return 0 if killed successfully.
* return 1 if there was a problem.
*/
int crypto_kill(Net_Crypto *c, int crypt_connection_id)
{
if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length)
@ -513,9 +528,10 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)
return 1;
}
/* accept an incoming connection using the parameters provided by crypto_inbound
return -1 if not successful
returns the crypt_connection_id if successful */
/* Accept an incoming connection using the parameters provided by crypto_inbound.
* return -1 if not successful.
* returns the crypt_connection_id if successful.
*/
int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
uint8_t *session_key)
{
@ -525,10 +541,11 @@ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key,
return -1;
/*
if(getcryptconnection_id(public_key) != -1)
{
return -1;
}*/
* if(getcryptconnection_id(public_key) != -1)
* {
* return -1;
* }
*/
if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1)
return -1;
@ -558,22 +575,25 @@ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key,
c->crypto_connections[i].sessionsecret_key,
c->crypto_connections[i].shared_key);
c->crypto_connections[i].status =
CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
return i;
}
return -1; /* this should never happen. */
return -1; /* This should never happen. */
}
}
return -1;
}
/* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet
(we have received a handshake but no empty data packet), 3 if the connection is established.
4 if the connection is timed out and waiting to be killed */
/* return 0 if no connection.
* return 1 we have sent a handshake.
* return 2 if connection is not confirmed yet (we have received a handshake but no empty data packet).
* return 3 if the connection is established.
* return 4 if the connection is timed out and waiting to be killed.
*/
int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id)
{
if (crypt_connection_id >= 0 && crypt_connection_id < c->crypto_connections_length)
@ -587,26 +607,29 @@ void new_keys(Net_Crypto *c)
crypto_box_keypair(c->self_public_key, c->self_secret_key);
}
/* save the public and private keys to the keys array
Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
/* Save the public and private keys to the keys array.
* Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
*/
void save_keys(Net_Crypto *c, uint8_t *keys)
{
memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES);
memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES);
}
/* load the public and private keys from the keys array
Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
/* Load the public and private keys from the keys array.
* Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
*/
void load_keys(Net_Crypto *c, uint8_t *keys)
{
memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES);
memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES);
}
/* TODO: optimize this
adds an incoming connection to the incoming_connection list.
returns 0 if successful
returns 1 if failure */
/* Adds an incoming connection to the incoming_connection list.
* returns 0 if successful
* returns 1 if failure.
* TODO: Optimize this.
*/
static int new_incoming(Net_Crypto *c, int id)
{
uint32_t i;
@ -621,8 +644,9 @@ static int new_incoming(Net_Crypto *c, int id)
return 1;
}
/* TODO: optimize this
handle all new incoming connections. */
/* Handle all new incoming connections.
* TODO: Optimize this.
*/
static void handle_incomings(Net_Crypto *c)
{
int income;
@ -635,7 +659,7 @@ static void handle_incomings(Net_Crypto *c)
}
}
/* handle received packets for not yet established crypto connections. */
/* Handle received packets for not yet established crypto connections. */
static void receive_crypto(Net_Crypto *c)
{
uint32_t i;
@ -648,7 +672,7 @@ static void receive_crypto(Net_Crypto *c)
uint8_t session_key[crypto_box_PUBLICKEYBYTES];
uint16_t len;
if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* handle handshake packet. */
if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */
len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
@ -661,13 +685,13 @@ static void receive_crypto(Net_Crypto *c)
c->crypto_connections[i].sessionsecret_key,
c->crypto_connections[i].shared_key);
c->crypto_connections[i].status =
CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
}
}
} else if (id_packet(c->lossless_udp,
c->crypto_connections[i].number) != -1) { // This should not happen kill the connection if it does
c->crypto_connections[i].number) != -1) { // This should not happen, kill the connection if it does.
crypto_kill(c, i);
return;
}
@ -690,15 +714,15 @@ static void receive_crypto(Net_Crypto *c)
c->crypto_connections[i].shared_key);
c->crypto_connections[i].status = CONN_ESTABLISHED;
/* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
/* Connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
kill_connection_in(c->lossless_udp, c->crypto_connections[i].number, 3000000);
} else {
crypto_kill(c, i); // This should not happen kill the connection if it does
/* This should not happen, kill the connection if it does. */
crypto_kill(c, i);
return;
}
} else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != -1)
/* This should not happen
kill the connection if it does */
/* This should not happen, kill the connection if it does. */
crypto_kill(c, i);
return;
@ -706,8 +730,9 @@ static void receive_crypto(Net_Crypto *c)
}
}
/* run this to (re)initialize net_crypto
sets all the global connection variables to their default values. */
/* Run this to (re)initialize net_crypto.
* Sets all the global connection variables to their default values.
*/
Net_Crypto *new_net_crypto(Networking_Core *net)
{
if (net == NULL)
@ -748,7 +773,7 @@ static void kill_timedout(Net_Crypto *c)
}
}
/* main loop */
/* Main loop. */
void do_net_crypto(Net_Crypto *c)
{
do_lossless_udp(c->lossless_udp);

View File

@ -28,20 +28,21 @@
#define MAX_INCOMING 64
#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID */
#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID */
#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
typedef struct {
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */
uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* nonce of received packets */
uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* nonce of sent packets. */
uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */
uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* Our public key for this session. */
uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* Our private key for this session. */
uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* the precomputed shared key from encrypt_precompute */
uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* The precomputed shared key from encrypt_precompute. */
uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
(we have received a handshake but no empty data packet), 3 if the connection is established.
4 if the connection is timed out. */
* (we have received a handshake but no empty data packet), 3 if the connection is established.
* 4 if the connection is timed out.
*/
uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */
} Crypto_Connection;
@ -59,13 +60,13 @@ typedef struct {
Crypto_Connection *crypto_connections;
uint32_t crypto_connections_length; /* Length of connections array */
uint32_t crypto_connections_length; /* Length of connections array. */
/* Our public and secret keys. */
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
/* keeps track of the connection numbers for friends request so we can check later if they were sent */
/* keeps track of the connection numbers for friends request so we can check later if they were sent. */
int incoming_connections[MAX_INCOMING];
Cryptopacket_Handles cryptopackethandlers[256];
@ -75,21 +76,23 @@ typedef struct {
#define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
/* returns zero if the buffer contains only zeros */
/* return zero if the buffer contains only zeros. */
uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen);
/* encrypts plain of length length to encrypted of length + 16 using the
public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce
return -1 if there was a problem.
return length of encrypted data if everything was fine. */
/* Encrypts plain of length length to encrypted of length + 16 using the
* public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce.
* return -1 if there was a problem.
* return length of encrypted data if everything was fine.
*/
int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
uint8_t *plain, uint32_t length, uint8_t *encrypted);
/* decrypts encrypted of length length to plain of length length - 16 using the
public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce
return -1 if there was a problem(decryption failed)
return length of plain data if everything was fine. */
/* Decrypts encrypted of length length to plain of length length - 16 using the
* public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce.
* return -1 if there was a problem (decryption failed).
* return length of plain data if everything was fine.
*/
int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
uint8_t *encrypted, uint32_t length, uint8_t *plain);
@ -107,86 +110,102 @@ int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
uint8_t *encrypted, uint32_t length, uint8_t *plain);
/* fill the given nonce with random bytes. */
/* Fill the given nonce with random bytes. */
void random_nonce(uint8_t *nonce);
/* return 0 if there is no received data in the buffer
return -1 if the packet was discarded.
return length of received data if successful */
/* return 0 if there is no received data in the buffer.
* return -1 if the packet was discarded.
* return length of received data if successful.
*/
int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data);
/* return 0 if data could not be put in packet queue
return 1 if data was put into the queue */
* return 1 if data was put into the queue
*/
int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length);
/* create a request to peer.
send_public_key and send_secret_key are the pub/secret keys of the sender
recv_public_key is public key of reciever
packet must be an array of MAX_DATA_SIZE big.
Data represents the data we send with the request with length being the length of the data.
request_id is the id of the request (32 = friend request, 254 = ping request)
returns -1 on failure
returns the length of the created packet on success */
/* Create a request to peer.
* send_public_key and send_secret_key are the pub/secret keys of the sender.
* recv_public_key is public key of reciever.
* packet must be an array of MAX_DATA_SIZE big.
* Data represents the data we send with the request with length being the length of the data.
* request_id is the id of the request (32 = friend request, 254 = ping request).
*
* returns -1 on failure.
* returns the length of the created packet on success.
*/
int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key,
uint8_t *data, uint32_t length, uint8_t request_id);
/* Function to call when request beginning with byte is received */
/* Function to call when request beginning with byte is received. */
void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object);
/* Start a secure connection with other peer who has public_key and ip_port
returns -1 if failure
returns crypt_connection_id of the initialized connection if everything went well. */
/* Start a secure connection with other peer who has public_key and ip_port.
* returns -1 if failure.
* returns crypt_connection_id of the initialized connection if everything went well.
*/
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port);
/* kill a crypto connection
return 0 if killed successfully
return 1 if there was a problem. */
/* Kill a crypto connection.
* return 0 if killed successfully.
* return 1 if there was a problem.
*/
int crypto_kill(Net_Crypto *c, int crypt_connection_id);
/* handle an incoming connection
return -1 if no crypto inbound connection
return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection
Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
and the session public key for the connection in session_key
to accept it see: accept_crypto_inbound(...)
to refuse it just call kill_connection(...) on the connection id */
/* Handle an incoming connection.
* return -1 if no crypto inbound connection.
* return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection.
*
* Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
* and the session public key for the connection in session_key.
* to accept it see: accept_crypto_inbound(...).
* to refuse it just call kill_connection(...) on the connection id.
*/
int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key);
/* accept an incoming connection using the parameters provided by crypto_inbound
return -1 if not successful
returns the crypt_connection_id if successful */
/* Accept an incoming connection using the parameters provided by crypto_inbound.
* return -1 if not successful.
* returns the crypt_connection_id if successful.
*/
int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
uint8_t *session_key);
/* return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
(we have received a handshake but no empty data packet), 3 if the connection is established.
4 if the connection is timed out and waiting to be killed */
/* return 0 if no connection.
* return 1 we have sent a handshake
* return 2 if connexion is not confirmed yet (we have received a handshake but no empty data packet).
* return 3 if the connection is established.
* return 4 if the connection is timed out and waiting to be killed.
*/
int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id);
/* Generate our public and private keys
Only call this function the first time the program starts. */
/* Generate our public and private keys.
* Only call this function the first time the program starts.
*/
void new_keys(Net_Crypto *c);
/* save the public and private keys to the keys array
Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
/* Save the public and private keys to the keys array.
* Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
*/
void save_keys(Net_Crypto *c, uint8_t *keys);
/* load the public and private keys from the keys array
Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
/* Load the public and private keys from the keys array.
* Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
*/
void load_keys(Net_Crypto *c, uint8_t *keys);
/* create new instance of Net_Crypto
sets all the global connection variables to their default values. */
/* Create new instance of Net_Crypto.
* Sets all the global connection variables to their default values.
*/
Net_Crypto *new_net_crypto(Networking_Core *net);
/* main loop */
/* Main loop. */
void do_net_crypto(Net_Crypto *c);
void kill_net_crypto(Net_Crypto *c);
/* Init the cryptopacket handling */
/* Initialize the cryptopacket handling. */
void init_cryptopackets(void *dht);

View File

@ -23,7 +23,7 @@
#include "network.h"
/* returns current UNIX time in microseconds (us). */
/* return current UNIX time in microseconds (us). */
uint64_t current_time(void)
{
uint64_t time;
@ -44,12 +44,13 @@ uint64_t current_time(void)
#endif
}
/* return a random number
NOTE: this function should probably not be used where cryptographic randomness is absolutely necessary */
/* return a random number.
* NOTE: This function should probably not be used where cryptographic randomness is absolutely necessary.
*/
uint32_t random_int(void)
{
#ifndef VANILLA_NACL
//NOTE: this function comes from libsodium
/* NOTE: this function comes from libsodium. */
return randombytes_random();
#else
return random();
@ -57,17 +58,20 @@ uint32_t random_int(void)
}
/* Basic network functions:
Function to send packet(data) of length length to ip_port */
* Function to send packet(data) of length length to ip_port.
*/
int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length)
{
ADDR addr = {AF_INET, ip_port.port, ip_port.ip};
return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr));
}
/* Function to receive data, ip and port of sender is put into ip_port
the packet data into data
the packet length into length.
dump all empty packets. */
/* Function to receive data
* ip and port of sender is put into ip_port.
* Packet data is put into data.
* Packet length is put into length.
* Dump all empty packets.
*/
static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
{
ADDR addr;
@ -79,7 +83,7 @@ static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *le
(*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
if (*(int32_t *)length <= 0)
return -1; /* nothing received or empty packet */
return -1; /* Nothing received or empty packet. */
ip_port->ip = addr.ip;
ip_port->port = addr.port;
@ -127,7 +131,7 @@ static int at_startup(void)
return 0;
}
/* TODO: put this somewhere
/* TODO: Put this somewhere
static void at_shutdown(void)
{
#ifdef WIN32
@ -136,18 +140,20 @@ static void at_shutdown(void)
}
*/
/* initialize networking
bind to ip and port
ip must be in network order EX: 127.0.0.1 = (7F000001)
port is in host byte order (this means don't worry about it)
returns Networking_Core object if no problems
returns NULL if there are problems */
/* Initialize networking.
* Bind to ip and port.
* ip must be in network order EX: 127.0.0.1 = (7F000001).
* port is in host byte order (this means don't worry about it).
*
* returns Networking_Core object if no problems
* returns NULL if there are problems.
*/
Networking_Core *new_networking(IP ip, uint16_t port)
{
if (at_startup() != 0)
return NULL;
/* initialize our socket */
/* Initialize our socket. */
Networking_Core *temp = calloc(1, sizeof(Networking_Core));
if (temp == NULL)
@ -155,10 +161,10 @@ Networking_Core *new_networking(IP ip, uint16_t port)
temp->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/* Check for socket error */
/* Check for socket error. */
#ifdef WIN32
if (temp->sock == INVALID_SOCKET) { /* MSDN recommends this */
if (temp->sock == INVALID_SOCKET) { /* MSDN recommends this. */
free(temp);
return NULL;
}
@ -172,8 +178,9 @@ Networking_Core *new_networking(IP ip, uint16_t port)
#endif
/* Functions to increase the size of the send and receive UDP buffers
NOTE: uncomment if necessary */
/* Functions to increase the size of the send and receive UDP buffers.
* NOTE: Uncomment if necessary.
*/
/*
int n = 1024 * 1024 * 2;
if(setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&n, sizeof(n)) == -1)
@ -185,13 +192,13 @@ Networking_Core *new_networking(IP ip, uint16_t port)
return -1;
*/
/* Enable broadcast on socket */
/* Enable broadcast on socket. */
int broadcast = 1;
setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast));
/* Set socket nonblocking */
/* Set socket nonblocking. */
#ifdef WIN32
/* I think this works for windows */
/* I think this works for Windows. */
u_long mode = 1;
/* ioctl(sock, FIONBIO, &mode); */
ioctlsocket(temp->sock, FIONBIO, &mode);
@ -205,7 +212,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
return temp;
}
/* function to cleanup networking stuff */
/* Function to cleanup networking stuff. */
void kill_networking(Networking_Core *net)
{
#ifdef WIN32

View File

@ -39,9 +39,9 @@
#include <windows.h>
#include <ws2tcpip.h>
#undef VANILLA_NACL /* make sure on windows we use libsodium */
#undef VANILLA_NACL /* Make sure on Windows we use libsodium. */
#else //Linux includes
#else // Linux includes
#include <fcntl.h>
#include <sys/socket.h>
@ -55,7 +55,7 @@
#endif
#ifndef VANILLA_NACL
/* we use libsodium by default */
/* We use libsodium by default. */
#include <sodium.h>
#else
#include <crypto_box.h>
@ -65,15 +65,15 @@
#define MAX_UDP_PACKET_SIZE 65507
#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID */
#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID */
#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID */
#define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID */
#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID */
#define NET_PACKET_SYNC 17 /* SYNC packet ID */
#define NET_PACKET_DATA 18 /* Data packet ID */
#define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID */
#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID */
#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */
#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */
#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */
#define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID. */
#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */
#define NET_PACKET_SYNC 17 /* SYNC packet ID. */
#define NET_PACKET_DATA 18 /* Data packet ID. */
#define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */
#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */
/* Current time, unix format */
@ -89,7 +89,7 @@ typedef union {
typedef struct {
IP ip;
uint16_t port;
/* not used for anything right now */
/* Not used for anything right now. */
uint16_t padding;
} IP_Port;
@ -103,9 +103,10 @@ typedef struct {
#endif
} ADDR;
/* Function to receive data, ip and port of sender is put into ip_port
the packet data into data
the packet length into length. */
/* Function to receive data, ip and port of sender is put into ip_port.
* Packet data is put into data.
* Packet length is put into length.
*/
typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, uint8_t *data, uint32_t len);
typedef struct {
@ -115,37 +116,40 @@ typedef struct {
typedef struct {
Packet_Handles packethandlers[256];
/* our UDP socket */
/* Our UDP socket. */
int sock;
} Networking_Core;
/* returns current time in milleseconds since the epoch. */
/* return current time in milleseconds since the epoch. */
uint64_t current_time(void);
/* return a random number
NOTE: this function should probably not be used where cryptographic randomness is absolutely necessary */
/* return a random number.
* NOTE: this function should probably not be used where cryptographic randomness is absolutely necessary.
*/
uint32_t random_int(void);
/* Basic network functions: */
/* Function to send packet(data) of length length to ip_port */
/* Function to send packet(data) of length length to ip_port. */
int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length);
/* Function to call when packet beginning with byte is received */
/* Function to call when packet beginning with byte is received. */
void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
/* call this several times a second */
/* Call this several times a second. */
void networking_poll(Networking_Core *net);
/* initialize networking
bind to ip and port
ip must be in network order EX: 127.0.0.1 = (7F000001)
port is in host byte order (this means don't worry about it)
returns 0 if no problems
returns -1 if there were problems */
/* Initialize networking.
* bind to ip and port.
* ip must be in network order EX: 127.0.0.1 = (7F000001).
* port is in host byte order (this means don't worry about it).
*
* returns 0 if no problems.
* returns -1 if there were problems.
*/
Networking_Core *new_networking(IP ip, uint16_t port);
/* function to cleanup networking stuff(doesn't do much right now) */
/* Function to cleanup networking stuff (doesn't do much right now). */
void kill_networking(Networking_Core *net);

View File

@ -10,7 +10,7 @@ typedef struct {
} __attribute__((packed)) clientid_t;
// Ping packet
// Ping packet.
typedef struct {
uint8_t packet_id;
clientid_t client_id;
@ -20,7 +20,7 @@ typedef struct {
} __attribute__((packed)) pingreq_t;
// Pong packet
// Pong packet.
typedef struct {
uint8_t packet_id;
clientid_t client_id;

View File

@ -51,7 +51,7 @@ static void remove_timeouts(void *ping) // O(n)
size_t new_pos = png->pos_pings;
size_t new_num = png->num_pings;
// Loop through buffer, oldest first
// Loop through buffer, oldest first.
for (i = 0; i < png->num_pings; i++) {
id = (png->pos_pings + i) % PING_NUM_MAX;
@ -76,13 +76,13 @@ uint64_t add_ping(void *ping, IP_Port ipp) // O(n)
remove_timeouts(ping);
// Remove oldest ping if full buffer
/* Remove oldest ping if full buffer. */
if (png->num_pings == PING_NUM_MAX) {
png->num_pings--;
png->pos_pings = (png->pos_pings + 1) % PING_NUM_MAX;
}
// Insert new ping at end of list
/* Insert new ping at end of list. */
p = (png->pos_pings + png->num_pings) % PING_NUM_MAX;
png->pings[p].ipp = ipp;
@ -93,7 +93,7 @@ uint64_t add_ping(void *ping, IP_Port ipp) // O(n)
return png->pings[p].id;
}
bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with something else.
bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Replace this with something else.
{
PING *png = ping;
@ -107,7 +107,7 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: repl
for (i = 0; i < png->num_pings; i++) {
id = (png->pos_pings + i) % PING_NUM_MAX;
// ping_id = 0 means match any id
/* ping_id = 0 means match any id. */
if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.i == 0) && (png->pings[id].id == ping_id || ping_id == 0)) {
return true;
}
@ -125,14 +125,14 @@ int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, clientid_t *client
if (is_pinging(ping, ipp, 0) || id_eq(client_id, (clientid_t *)c->self_public_key))
return 1;
// Generate random ping_id
// Generate random ping_id.
ping_id = add_ping(ping, ipp);
pk.packet_id = NET_PACKET_PING_REQUEST;
id_cpy(&pk.client_id, (clientid_t *)c->self_public_key); // Our pubkey
random_nonce((uint8_t *) &pk.nonce); // Generate random nonce
id_cpy(&pk.client_id, (clientid_t *)c->self_public_key); // Our pubkey.
random_nonce((uint8_t *) &pk.nonce); // Generate random nonce.
// Encrypt ping_id using recipient privkey
/* Encrypt ping_id using recipient privkey. */
rc = encrypt_data((uint8_t *) client_id,
c->self_secret_key,
(uint8_t *) &pk.nonce,
@ -154,10 +154,10 @@ int send_ping_response(Net_Crypto *c, IP_Port ipp, clientid_t *client_id, uint64
return 1;
pk.packet_id = NET_PACKET_PING_RESPONSE;
id_cpy(&pk.client_id, (clientid_t *)c->self_public_key); // Our pubkey
random_nonce((uint8_t *) &pk.nonce); // Generate random nonce
id_cpy(&pk.client_id, (clientid_t *)c->self_public_key); // Our pubkey.
random_nonce((uint8_t *) &pk.nonce); // Generate random nonce.
// Encrypt ping_id using recipient privkey
/* Encrypt ping_id using recipient privkey */
rc = encrypt_data((uint8_t *) client_id,
c->self_secret_key,
(uint8_t *) &pk.nonce,
@ -180,7 +180,7 @@ int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t
if (length != sizeof(pingreq_t) || id_eq(&p->client_id, (clientid_t *)dht->c->self_public_key))
return 1;
// Decrypt ping_id
/* Decrypt ping_id. */
rc = decrypt_data((uint8_t *) &p->client_id,
dht->c->self_secret_key,
(uint8_t *) &p->nonce,
@ -191,7 +191,7 @@ int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t
if (rc != sizeof(ping_id))
return 1;
// Send response
/* Send response. */
send_ping_response(dht->c, source, &p->client_id, ping_id);
add_toping(dht, (uint8_t *) &p->client_id, source);
@ -208,7 +208,7 @@ int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t
if (length != sizeof(pingres_t) || id_eq(&p->client_id, (clientid_t *)dht->c->self_public_key))
return 1;
// Decrypt ping_id
/* Decrypt ping_id. */
rc = decrypt_data((uint8_t *) &p->client_id,
dht->c->self_secret_key,
(uint8_t *) &p->nonce,
@ -219,11 +219,11 @@ int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t
if (rc != sizeof(ping_id))
return 1;
// Make sure ping_id is correct
/* Make sure ping_id is correct. */
if (!is_pinging(dht->ping, source, ping_id))
return 1;
// Associate source ip with client_id
/* Associate source ip with client_id. */
addto_lists(dht, source, (uint8_t *) &p->client_id);
return 0;
}

View File

@ -24,7 +24,7 @@
#include "Messenger.h"
/*
* returns a FRIEND_ADDRESS_SIZE byte address to give to others.
* format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
* Format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
*
*/
void tox_getaddress(void *tox, uint8_t *address)
@ -34,20 +34,20 @@ void tox_getaddress(void *tox, uint8_t *address)
}
/*
* add a friend
* set the data that will be sent along with friend request
* Add a friend.
* Set the data that will be sent along with friend request.
* address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. TODO: add checksum.
* data is the data and length is the length
* returns the friend number if success
* return FA_TOOLONG if message length is too long
* return FAERR_NOMESSAGE if no message (message length must be >= 1 byte)
* return FAERR_OWNKEY if user's own key
* return FAERR_ALREADYSENT if friend request already sent or already a friend
* return FAERR_UNKNOWN for unknown error
* return FAERR_BADCHECKSUM if bad checksum in address
* return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different
* (the nospam for that friend was set to the new one)
* return FAERR_NOMEM if increasing the friend list size fails
* data is the data and length is the length.
* returns the friend number if success.
* return FA_TOOLONG if message length is too long.
* return FAERR_NOMESSAGE if no message (message length must be >= 1 byte).
* return FAERR_OWNKEY if user's own key.
* return FAERR_ALREADYSENT if friend request already sent or already a friend.
* return FAERR_UNKNOWN for unknown error.
* return FAERR_BADCHECKSUM if bad checksum in address.
* return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different.
* (the nospam for that friend was set to the new one).
* return FAERR_NOMEM if increasing the friend list size fails.
*/
int tox_addfriend(void *tox, uint8_t *address, uint8_t *data, uint16_t length)
{
@ -55,9 +55,10 @@ int tox_addfriend(void *tox, uint8_t *address, uint8_t *data, uint16_t length)
return m_addfriend(m, address, data, length);
}
/* add a friend without sending a friendrequest.
returns the friend number if success
return -1 if failure. */
/* Add a friend without sending a friendrequest.
* returns the friend number if success.
* return -1 if failure.
*/
int tox_addfriend_norequest(void *tox, uint8_t *client_id)
{
Messenger *m = tox;
@ -65,48 +66,53 @@ int tox_addfriend_norequest(void *tox, uint8_t *client_id)
}
/* return the friend id associated to that client id.
return -1 if no such friend */
* return -1 if no such friend.
*/
int tox_getfriend_id(void *tox, uint8_t *client_id)
{
Messenger *m = tox;
return getfriend_id(m, client_id);
}
/* copies the public key associated to that friend id into client_id buffer.
make sure that client_id is of size CLIENT_ID_SIZE.
return 0 if success
return -1 if failure */
/* Copies the public key associated to that friend id into client_id buffer.
* Make sure that client_id is of size CLIENT_ID_SIZE.
* return 0 if success.
* return -1 if failure.
*/
int tox_getclient_id(void *tox, int friend_id, uint8_t *client_id)
{
Messenger *m = tox;
return getclient_id(m, friend_id, client_id);
}
/* remove a friend */
/* Remove a friend. */
int tox_delfriend(void *tox, int friendnumber)
{
Messenger *m = tox;
return m_delfriend(m, friendnumber);
}
/* return 4 if friend is online
return 3 if friend is confirmed
return 2 if the friend request was sent
return 1 if the friend was added
return 0 if there is no friend with that number */
/* return 4 if friend is online.
* return 3 if friend is confirmed.
* return 2 if the friend request was sent.
* return 1 if the friend was added.
* return 0 if there is no friend with that number.
*/
int tox_friendstatus(void *tox, int friendnumber)
{
Messenger *m = tox;
return m_friendstatus(m, friendnumber);
}
/* send a text chat message to an online friend
returns the message id if packet was successfully put into the send queue
return 0 if it was not
you will want to retain the return value, it will be passed to your read receipt callback
if one is received.
m_sendmessage_withid will send a message with the id of your choosing,
however we can generate an id for you by calling plain m_sendmessage. */
/* Send a text chat message to an online friend.
* returns the message id if packet was successfully put into the send queue.
* return 0 if it was not.
*
* You will want to retain the return value, it will be passed to your read receipt callback
* if one is received.
* m_sendmessage_withid will send a message with the id of your choosing,
* however we can generate an id for you by calling plain m_sendmessage.
*/
uint32_t tox_sendmessage(void *tox, int friendnumber, uint8_t *message, uint32_t length)
{
Messenger *m = tox;
@ -119,45 +125,47 @@ uint32_t tox_sendmessage_withid(void *tox, int friendnumber, uint32_t theid, uin
return m_sendmessage_withid(m, friendnumber, theid, message, length);
}
/* send an action to an online friend
returns 1 if packet was successfully put into the send queue
return 0 if it was not */
/* Send an action to an online friend.
* returns 1 if packet was successfully put into the send queue.
* return 0 if it was not.
*/
int tox_sendaction(void *tox, int friendnumber, uint8_t *action, uint32_t length)
{
Messenger *m = tox;
return m_sendaction(m, friendnumber, action, length);
}
/* Set our nickname
name must be a string of maximum MAX_NAME_LENGTH length.
length must be at least 1 byte
length is the length of name with the NULL terminator
return 0 if success
return -1 if failure */
/* Set our nickname.
* name must be a string of maximum MAX_NAME_LENGTH length.
* length must be at least 1 byte.
* length is the length of name with the NULL terminator.
* return 0 if success.
* return -1 if failure.
*/
int tox_setname(void *tox, uint8_t *name, uint16_t length)
{
Messenger *m = tox;
return setname(m, name, length);
}
/*
Get your nickname.
m The messanger context to use.
name Pointer to a string for the name.
nlen The length of the string buffer.
returns Return the length of the name, 0 on error.
*/
/* Get your nickname.
* m - The messanger context to use.
* name - Pointer to a string for the name.
* nlen - The length of the string buffer.
* return length of the name.
* return 0 on error.
*/
uint16_t tox_getselfname(void *tox, uint8_t *name, uint16_t nlen)
{
Messenger *m = tox;
return getself_name(m, name, nlen);
}
/* get name of friendnumber
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
return 0 if success
return -1 if failure */
/* Get name of friendnumber and put it in name.
* name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
* return 0 if success.
* return -1 if failure.
*/
int tox_getname(void *tox, int friendnumber, uint8_t *name)
{
Messenger *m = tox;
@ -179,18 +187,19 @@ int tox_set_userstatus(void *tox, USERSTATUS status)
return m_set_userstatus(m, status);
}
/* return the length of friendnumber's status message,
including null
pass it into malloc */
/* return the length of friendnumber's status message, including null.
* Pass it into malloc.
*/
int tox_get_statusmessage_size(void *tox, int friendnumber)
{
Messenger *m = tox;
return m_get_statusmessage_size(m, friendnumber);
}
/* copy friendnumber's status message into buf, truncating if size is over maxlen
get the size you need to allocate from m_get_statusmessage_size
The self variant will copy our own status message. */
/* Copy friendnumber's status message into buf, truncating if size is over maxlen.
* Get the size you need to allocate from m_get_statusmessage_size.
* The self variant will copy our own status message.
*/
int tox_copy_statusmessage(void *tox, int friendnumber, uint8_t *buf, uint32_t maxlen)
{
Messenger *m = tox;
@ -206,7 +215,8 @@ int tox_copy_self_statusmessage(void *tox, uint8_t *buf, uint32_t maxlen)
/* Return one of USERSTATUS values.
* Values unknown to your application should be represented as USERSTATUS_NONE.
* As above, the self variant will return our own USERSTATUS.
* If friendnumber is invalid, this shall return USERSTATUS_INVALID. */
* If friendnumber is invalid, this shall return USERSTATUS_INVALID.
*/
USERSTATUS tox_get_userstatus(void *tox, int friendnumber)
{
Messenger *m = tox;
@ -221,7 +231,8 @@ USERSTATUS tox_get_selfuserstatus(void *tox)
/* Sets whether we send read receipts for friendnumber.
* This function is not lazy, and it will fail if yesno is not (0 or 1).*/
* This function is not lazy, and it will fail if yesno is not (0 or 1).
*/
void tox_set_sends_receipts(void *tox, int friendnumber, int yesno)
{
Messenger *m = tox;
@ -229,8 +240,9 @@ void tox_set_sends_receipts(void *tox, int friendnumber, int yesno)
}
/* set the function that will be executed when a friend request is received.
function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
/* Set the function that will be executed when a friend request is received.
* Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length)
*/
void tox_callback_friendrequest(void *tox, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata)
{
Messenger *m = tox;
@ -238,8 +250,9 @@ void tox_callback_friendrequest(void *tox, void (*function)(uint8_t *, uint8_t *
}
/* set the function that will be executed when a message from a friend is received.
function format is: function(int friendnumber, uint8_t * message, uint32_t length) */
/* Set the function that will be executed when a message from a friend is received.
* Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
*/
void tox_callback_friendmessage(void *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
void *userdata)
{
@ -247,17 +260,19 @@ void tox_callback_friendmessage(void *tox, void (*function)(Messenger *tox, int,
m_callback_friendmessage(m, function, userdata);
}
/* 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) */
/* 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)
*/
void tox_callback_action(void *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *), void *userdata)
{
Messenger *m = tox;
m_callback_action(m, function, userdata);
}
/* set the callback for name changes
function(int friendnumber, uint8_t *newname, uint16_t length)
you are not responsible for freeing newname */
/* Set the callback for name changes.
* function(int friendnumber, uint8_t *newname, uint16_t length)
* You are not responsible for freeing newname.
*/
void tox_callback_namechange(void *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
void *userdata)
{
@ -265,9 +280,10 @@ void tox_callback_namechange(void *tox, void (*function)(Messenger *tox, int, ui
m_callback_namechange(m, function, userdata);
}
/* set the callback for status message changes
function(int friendnumber, uint8_t *newstatus, uint16_t length)
you are not responsible for freeing newstatus */
/* Set the callback for status message changes.
* function(int friendnumber, uint8_t *newstatus, uint16_t length)
* You are not responsible for freeing newstatus.
*/
void tox_callback_statusmessage(void *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
void *userdata)
{
@ -275,74 +291,83 @@ void tox_callback_statusmessage(void *tox, void (*function)(Messenger *tox, int,
m_callback_statusmessage(m, function, userdata);
}
/* set the callback for status type changes
function(int friendnumber, USERSTATUS kind) */
/* Set the callback for status type changes.
* function(int friendnumber, USERSTATUS kind)
*/
void tox_callback_userstatus(void *tox, void (*function)(Messenger *tox, int, USERSTATUS, void *), void *userdata)
{
Messenger *m = tox;
m_callback_userstatus(m, function, userdata);
}
/* set the callback for read receipts
function(int friendnumber, uint32_t receipt)
if you are keeping a record of returns from m_sendmessage,
receipt might be one of those values, and that means the message
has been received on the other side. since core doesn't
track ids for you, receipt may not correspond to any message
in that case, you should discard it. */
/* Set the callback for read receipts.
* function(int friendnumber, uint32_t receipt)
*
* If you are keeping a record of returns from m_sendmessage;
* receipt might be one of those values, meaning the message
* has been received on the other side.
* Since core doesn't track ids for you, receipt may not correspond to any message.
* in that case, you should discard it.
*/
void tox_callback_read_receipt(void *tox, void (*function)(Messenger *tox, int, uint32_t, void *), void *userdata)
{
Messenger *m = tox;
m_callback_read_receipt(m, function, userdata);
}
/* set the callback for connection status changes
function(int friendnumber, uint8_t status)
status:
0 -- friend went offline after being previously online
1 -- friend went online
note that this callback is not called when adding friends, thus the "after
being previously online" part. it's assumed that when adding friends,
their connection status is offline. */
/* Set the callback for connection status changes.
* function(int friendnumber, uint8_t status)
* Status:
* 0 -- friend went offline after being previously online
* 1 -- friend went online
*
* NOTE: this callback is not called when adding friends, thus the "after
* being previously online" part. It's assumed that when adding friends,
* their connection status is offline.
*/
void tox_callback_connectionstatus(void *tox, void (*function)(Messenger *tox, int, uint8_t, void *), void *userdata)
{
Messenger *m = tox;
m_callback_connectionstatus(m, function, userdata);
}
/* Use this function to bootstrap the client
Sends a get nodes request to the given node with ip port and public_key */
/* Use this function to bootstrap the client.
* Sends a get nodes request to the given node with ip port and public_key.
*/
void tox_bootstrap(void *tox, IP_Port ip_port, uint8_t *public_key)
{
Messenger *m = tox;
DHT_bootstrap(m->dht, ip_port, public_key);
}
/* returns 0 if we are not connected to the DHT
returns 1 if we are */
/* returns 0 if we are not connected to the DHT.
* returns 1 if we are.
*/
int tox_isconnected(void *tox)
{
Messenger *m = tox;
return DHT_isconnected(m->dht);
}
/* run this at startup
* returns allocated instance of tox on success
* returns 0 if there are problems */
/* Run this at startup.
* returns allocated instance of tox on success.
* returns 0 if there are problems.
*/
void *tox_new(void)
{
return initMessenger();
}
/* run this before closing shop
* free all datastructures */
/* Run this before closing shop.
* Free all datastructures.
*/
void tox_kill(void *tox)
{
Messenger *m = tox;
cleanupMessenger(m);
}
/* the main loop that needs to be run at least 20 times per second */
/* The main loop that needs to be run at least 20 times per second. */
void tox_do(void *tox)
{
Messenger *m = tox;
@ -351,21 +376,21 @@ void tox_do(void *tox)
/* SAVING AND LOADING FUNCTIONS: */
/* returns the size of the messenger data (for saving) */
/* returns the size of the messenger data (for saving). */
uint32_t tox_size(void *tox)
{
Messenger *m = tox;
return Messenger_size(m);
}
/* save the messenger in data (must be allocated memory of size Messenger_size()) */
/* Save the messenger in data (must be allocated memory of size Messenger_size()). */
void tox_save(void *tox, uint8_t *data)
{
Messenger *m = tox;
Messenger_save(m, data);
}
/* load the messenger from data of size length */
/* Load the messenger from data of size length. */
int tox_load(void *tox, uint8_t *data, uint32_t length)
{
Messenger *m = tox;

View File

@ -46,11 +46,11 @@ typedef union {
typedef struct {
tox_IP ip;
uint16_t port;
/* not used for anything right now */
/* Not used for anything right now. */
uint16_t padding;
} tox_IP_Port;
/* status definitions */
/* Status definitions. */
enum {
TOX_NOFRIEND,
TOX_FRIEND_ADDED,
@ -59,8 +59,9 @@ enum {
TOX_FRIEND_ONLINE,
};
/* errors for m_addfriend
* FAERR - Friend Add Error */
/* Errors for m_addfriend
* FAERR - Friend Add Error
*/
enum {
TOX_FAERR_TOOLONG = -1,
TOX_FAERR_NOMESSAGE = -2,
@ -71,9 +72,10 @@ enum {
TOX_FAERR_SETNEWNOSPAM = -7,
TOX_FAERR_NOMEM = -8
};
/* USERSTATUS
* Represents userstatuses someone can have. */
/* USERSTATUS -
* Represents userstatuses someone can have.
*/
typedef enum {
TOX_USERSTATUS_NONE,
TOX_USERSTATUS_AWAY,
@ -84,201 +86,226 @@ TOX_USERSTATUS;
typedef void Tox;
/*
* returns a FRIEND_ADDRESS_SIZE byte address to give to others.
/* returns FRIEND_ADDRESS_SIZE byte address to give to others.
* format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
*
*/
void tox_getaddress(Tox *tox, uint8_t *address);
/*
* add a friend
* set the data that will be sent along with friend request
/* Add a friend.
* Set the data that will be sent along with friend request.
* address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. TODO: add checksum.
* data is the data and length is the length
* returns the friend number if success
* return TOX_FA_TOOLONG if message length is too long
* return TOX_FAERR_NOMESSAGE if no message (message length must be >= 1 byte)
* return TOX_FAERR_OWNKEY if user's own key
* return TOX_FAERR_ALREADYSENT if friend request already sent or already a friend
* return TOX_FAERR_UNKNOWN for unknown error
* return TOX_FAERR_BADCHECKSUM if bad checksum in address
* return TOX_FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different
* (the nospam for that friend was set to the new one)
* return TOX_FAERR_NOMEM if increasing the friend list size fails
* data is the data and length is the length.
* returns the friend number if success.
* return TOX_FA_TOOLONG if message length is too long.
* return TOX_FAERR_NOMESSAGE if no message (message length must be >= 1 byte).
* return TOX_FAERR_OWNKEY if user's own key.
* return TOX_FAERR_ALREADYSENT if friend request already sent or already a friend.
* return TOX_FAERR_UNKNOWN for unknown error.
* return TOX_FAERR_BADCHECKSUM if bad checksum in address.
* return TOX_FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different.
* (the nospam for that friend was set to the new one).
* return TOX_FAERR_NOMEM if increasing the friend list size fails.
*/
int tox_addfriend(Tox *tox, uint8_t *address, uint8_t *data, uint16_t length);
/* add a friend without sending a friendrequest.
returns the friend number if success
return -1 if failure. */
/* Add a friend without sending a friendrequest.
* returns the friend number if success.
* return -1 if failure.
*/
int tox_addfriend_norequest(Tox *tox, uint8_t *client_id);
/* return the friend id associated to that client id.
return -1 if no such friend */
int tox_getfriend_id(Tox *tox, uint8_t *client_id);
/* copies the public key associated to that friend id into client_id buffer.
make sure that client_id is of size CLIENT_ID_SIZE.
return 0 if success
return -1 if failure */
/* Copies the public key associated to that friend id into client_id buffer.
* Make sure that client_id is of size CLIENT_ID_SIZE.
* return 0 if success.
* return -1 if failure.
*/
int tox_getclient_id(Tox *tox, int friend_id, uint8_t *client_id);
/* remove a friend */
/* Remove a friend. */
int tox_delfriend(Tox *tox, int friendnumber);
/* return TOX_FRIEND_ONLINE if friend is online
return TOX_FRIEND_CONFIRMED if friend is confirmed
return TOX_FRIEND_REQUESTED if the friend request was sent
return TOX_FRIEND_ADDED if the friend was added
return TOX_NOFRIEND if there is no friend with that number */
/* return TOX_FRIEND_ONLINE if friend is online.
* return TOX_FRIEND_CONFIRMED if friend is confirmed.
* return TOX_FRIEND_REQUESTED if the friend request was sent.
* return TOX_FRIEND_ADDED if the friend was added.
* return TOX_NOFRIEND if there is no friend with that number.
*/
int tox_friendstatus(Tox *tox, int friendnumber);
/* send a text chat message to an online friend
returns the message id if packet was successfully put into the send queue
return 0 if it was not
you will want to retain the return value, it will be passed to your read receipt callback
if one is received.
m_sendmessage_withid will send a message with the id of your choosing,
however we can generate an id for you by calling plain m_sendmessage. */
/* Send a text chat message to an online friend.
* returns the message id if packet was successfully put into the send queue.
* return 0 if it was not.
*
* You will want to retain the return value, it will be passed to your read receipt callback
* if one is received.
* m_sendmessage_withid will send a message with the id of your choosing,
* however we can generate an id for you by calling plain m_sendmessage.
*/
uint32_t tox_sendmessage(Tox *tox, int friendnumber, uint8_t *message, uint32_t length);
uint32_t tox_sendmessage_withid(Tox *tox, int friendnumber, uint32_t theid, uint8_t *message, uint32_t length);
/* send an action to an online friend
returns 1 if packet was successfully put into the send queue
return 0 if it was not */
/* Send an action to an online friend.
* returns 1 if packet was successfully put into the send queue.
* return 0 if it was not.
*/
int tox_sendaction(Tox *tox, int friendnumber, uint8_t *action, uint32_t length);
/* Set our nickname
name must be a string of maximum MAX_NAME_LENGTH length.
length must be at least 1 byte
length is the length of name with the NULL terminator
return 0 if success
return -1 if failure */
/* Set our nickname.
* name must be a string of maximum MAX_NAME_LENGTH length.
* length must be at least 1 byte.
* length is the length of name with the NULL terminator.
*
* return 0 if success.
* return -1 if failure.
*/
int tox_setname(Tox *tox, uint8_t *name, uint16_t length);
/*
Get your nickname.
m The messanger context to use.
name Pointer to a string for the name.
nlen The length of the string buffer.
returns Return the length of the name, 0 on error.
*/
* Get your nickname.
* m - The messanger context to use.
* name - Pointer to a string for the name.
* nlen - The length of the string buffer.
*
* returns Return the length of the name, 0 on error.
*/
uint16_t tox_getselfname(Tox *tox, uint8_t *name, uint16_t nlen);
/* get name of friendnumber
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
return 0 if success
return -1 if failure */
/* Get name of friendnumber and put it in name.
* name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
*
* return 0 if success.
* return -1 if failure.
*/
int tox_getname(Tox *tox, int friendnumber, uint8_t *name);
/* set our user status
you are responsible for freeing status after
returns 0 on success, -1 on failure */
/* Set our user status.
* You are responsible for freeing status after.
* returns 0 on success.
* returns -1 on failure.
*/
int tox_set_statusmessage(Tox *tox, uint8_t *status, uint16_t length);
int tox_set_userstatus(Tox *tox, TOX_USERSTATUS status);
/* return the length of friendnumber's status message,
including null
pass it into malloc */
/* return the length of friendnumber's status message, including null.
* Pass it into malloc
*/
int tox_get_statusmessage_size(Tox *tox, int friendnumber);
/* copy friendnumber's status message into buf, truncating if size is over maxlen
get the size you need to allocate from m_get_statusmessage_size
The self variant will copy our own status message. */
/* Copy friendnumber's status message into buf, truncating if size is over maxlen.
* Get the size you need to allocate from m_get_statusmessage_size.
* The self variant will copy our own status message.
*/
int tox_copy_statusmessage(Tox *tox, int friendnumber, uint8_t *buf, uint32_t maxlen);
int tox_copy_self_statusmessage(Tox *tox, uint8_t *buf, uint32_t maxlen);
/* Return one of USERSTATUS values.
/* return one of USERSTATUS values.
* Values unknown to your application should be represented as USERSTATUS_NONE.
* As above, the self variant will return our own USERSTATUS.
* If friendnumber is invalid, this shall return USERSTATUS_INVALID. */
* If friendnumber is invalid, this shall return USERSTATUS_INVALID.
*/
TOX_USERSTATUS tox_get_userstatus(Tox *tox, int friendnumber);
TOX_USERSTATUS tox_get_selfuserstatus(Tox *tox);
/* Sets whether we send read receipts for friendnumber.
* This function is not lazy, and it will fail if yesno is not (0 or 1).*/
* This function is not lazy, and it will fail if yesno is not (0 or 1).
*/
void tox_set_sends_receipts(Tox *tox, int friendnumber, int yesno);
/* set the function that will be executed when a friend request is received.
function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
/* Set the function that will be executed when a friend request is received.
* Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length)
*/
void tox_callback_friendrequest(Tox *tox, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata);
/* set the function that will be executed when a message from a friend is received.
function format is: function(int friendnumber, uint8_t * message, uint32_t length) */
/* Set the function that will be executed when a message from a friend is received.
* Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
*/
void tox_callback_friendmessage(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
void *userdata);
/* 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) */
/* 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)
*/
void tox_callback_action(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *), void *userdata);
/* set the callback for name changes
function(int friendnumber, uint8_t *newname, uint16_t length)
you are not responsible for freeing newname */
/* Set the callback for name changes.
* function(int friendnumber, uint8_t *newname, uint16_t length)
* You are not responsible for freeing newname
*/
void tox_callback_namechange(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
void *userdata);
/* set the callback for status message changes
function(int friendnumber, uint8_t *newstatus, uint16_t length)
you are not responsible for freeing newstatus */
/* Set the callback for status message changes.
* function(int friendnumber, uint8_t *newstatus, uint16_t length)
* You are not responsible for freeing newstatus.
*/
void tox_callback_statusmessage(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
void *userdata);
/* set the callback for status type changes
function(int friendnumber, USERSTATUS kind) */
/* Set the callback for status type changes.
* function(int friendnumber, USERSTATUS kind)
*/
void tox_callback_userstatus(Tox *tox, void (*function)(Tox *tox, int, TOX_USERSTATUS, void *), void *userdata);
/* set the callback for read receipts
function(int friendnumber, uint32_t receipt)
if you are keeping a record of returns from m_sendmessage,
receipt might be one of those values, and that means the message
has been received on the other side. since core doesn't
track ids for you, receipt may not correspond to any message
in that case, you should discard it. */
/* Set the callback for read receipts.
* function(int friendnumber, uint32_t receipt)
*
* If you are keeping a record of returns from m_sendmessage;
* receipt might be one of those values, meaning the message
* has been received on the other side.
* Since core doesn't track ids for you, receipt may not correspond to any message.
* In that case, you should discard it.
*/
void tox_callback_read_receipt(Tox *tox, void (*function)(Tox *tox, int, uint32_t, void *), void *userdata);
/* set the callback for connection status changes
function(int friendnumber, uint8_t status)
status:
0 -- friend went offline after being previously online
1 -- friend went online
note that this callback is not called when adding friends, thus the "after
being previously online" part. it's assumed that when adding friends,
their connection status is offline. */
/* Set the callback for connection status changes.
* function(int friendnumber, uint8_t status)
* Status:
* 0 -- friend went offline after being previously online
* 1 -- friend went online
*
* NOTE: This callback is not called when adding friends, thus the "after
* being previously online" part. it's assumed that when adding friends,
* their connection status is offline.
*/
void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata);
/* Use this function to bootstrap the client
Sends a get nodes request to the given node with ip port and public_key */
/* Use this function to bootstrap the client.
* Sends a get nodes request to the given node with ip port and public_key.
*/
void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
/* returns 0 if we are not connected to the DHT
returns 1 if we are */
/* returns 0 if we are not connected to the DHT.
* returns 1 if we are.
*/
int tox_isconnected(Tox *tox);
/* run this at startup
* returns allocated instance of tox on success
* returns 0 if there are problems */
/* Run this at startup.
* returns allocated instance of tox on success.
* returns 0 if there are problems.
*/
Tox *tox_new(void);
/* run this before closing shop
* free all datastructures */
/* Run this before closing shop.
* Free all datastructures. */
void tox_kill(Tox *tox);
/* the main loop that needs to be run at least 20 times per second */
/* The main loop that needs to be run at least 20 times per second. */
void tox_do(Tox *tox);
/* SAVING AND LOADING FUNCTIONS: */
/* returns the size of the messenger data (for saving) */
/* returns the size of the messenger data (for saving). */
uint32_t tox_size(Tox *tox);
/* save the messenger in data (must be allocated memory of size Messenger_size()) */
/* Save the messenger in data (must be allocated memory of size Messenger_size()). */
void tox_save(Tox *tox, uint8_t *data);
/* load the messenger from data of size length */
/* Load the messenger from data of size length. */
int tox_load(Tox *tox, uint8_t *data, uint32_t length);