mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge branch 'master' of https://github.com/JamoBox/ProjectTox-Core into JamoBox-master
Conflicts: toxcore/LAN_discovery.h
This commit is contained in:
commit
ea994606fe
|
@ -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])
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -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``
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
148
toxcore/DHT.c
148
toxcore/DHT.c
|
@ -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)
|
||||
{
|
||||
|
|
107
toxcore/DHT.h
107
toxcore/DHT.h
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
237
toxcore/tox.c
237
toxcore/tox.c
|
@ -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;
|
||||
|
|
261
toxcore/tox.h
261
toxcore/tox.h
|
@ -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);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user