mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge upstream and other stuff
This commit is contained in:
parent
ea96c1758a
commit
a1f2a18ae4
|
@ -15,6 +15,7 @@ AUTOTEST_LDADD = \
|
|||
$(NACL_LDFLAGS) \
|
||||
libtoxcore.la \
|
||||
$(LIBSODIUM_LIBS) \
|
||||
$(NACL_OBJECTS) \
|
||||
$(NACL_LIBS) \
|
||||
$(CHECK_LIBS)
|
||||
|
||||
|
|
11
configure.ac
11
configure.ac
|
@ -427,6 +427,17 @@ AC_C_BIGENDIAN
|
|||
# Checks for library functions.
|
||||
AC_FUNC_FORK
|
||||
AC_CHECK_FUNCS([gettimeofday memset socket strchr malloc])
|
||||
if test "x$WIN32" != "xyes"; then
|
||||
AC_CHECK_LIB(rt, clock_gettime,
|
||||
[
|
||||
RT_LIBS="-lrt"
|
||||
AC_SUBST(RT_LIBS)
|
||||
],
|
||||
[
|
||||
AC_MSG_ERROR([required library rt was not found on your system])
|
||||
]
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$BUILD_AV" = "xyes"; then
|
||||
AX_PTHREAD(
|
||||
|
|
|
@ -31,6 +31,12 @@
|
|||
#include "../toxcore/friend_requests.h"
|
||||
#include "../toxcore/util.h"
|
||||
|
||||
#define TCP_RELAY_ENABLED
|
||||
|
||||
#ifdef TCP_RELAY_ENABLED
|
||||
#include "../toxcore/TCP_server.h"
|
||||
#endif
|
||||
|
||||
#include "../testing/misc_tools.c"
|
||||
|
||||
#ifdef DHT_NODE_EXTRA_PACKETS
|
||||
|
@ -69,11 +75,12 @@ void manage_keys(DHT *dht)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
load_keys(dht->c, keys);
|
||||
memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES);
|
||||
printf("Keys loaded successfully.\n");
|
||||
} else {
|
||||
new_keys(dht->c);
|
||||
save_keys(dht->c, keys);
|
||||
memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES);
|
||||
keys_file = fopen("key", "w");
|
||||
|
||||
if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) {
|
||||
|
@ -107,7 +114,7 @@ int main(int argc, char *argv[])
|
|||
IP ip;
|
||||
ip_init(&ip, ipv6enabled);
|
||||
|
||||
DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
|
||||
DHT *dht = new_DHT(new_networking(ip, PORT));
|
||||
Onion *onion = new_onion(dht);
|
||||
Onion_Announce *onion_a = new_onion_announce(dht);
|
||||
|
||||
|
@ -123,27 +130,33 @@ int main(int argc, char *argv[])
|
|||
perror("Initialization");
|
||||
|
||||
manage_keys(dht);
|
||||
/* We want our DHT public key to be the same as our internal one since this is a bootstrap node */
|
||||
memcpy(dht->self_public_key, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(dht->self_secret_key, dht->c->self_secret_key, crypto_box_SECRETKEYBYTES);
|
||||
printf("Public key: ");
|
||||
uint32_t i;
|
||||
|
||||
#ifdef TCP_RELAY_ENABLED
|
||||
#define NUM_PORTS 3
|
||||
uint16_t ports[NUM_PORTS] = {443, 3389, PORT};
|
||||
TCP_Server *tcp_s = new_TCP_server(ipv6enabled, NUM_PORTS, ports, dht->self_public_key, dht->self_secret_key, onion);
|
||||
|
||||
if (tcp_s == NULL) {
|
||||
printf("TCP server failed to initialize.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FILE *file;
|
||||
file = fopen("PUBLIC_ID.txt", "w");
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (dht->c->self_public_key[i] < 16)
|
||||
printf("0");
|
||||
|
||||
printf("%hhX", dht->c->self_public_key[i]);
|
||||
fprintf(file, "%hhX", dht->c->self_public_key[i]);
|
||||
printf("%02hhX", dht->self_public_key[i]);
|
||||
fprintf(file, "%02hhX", dht->self_public_key[i]);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
printf("\n");
|
||||
printf("Port: %u\n", ntohs(dht->c->lossless_udp->net->port));
|
||||
printf("Port: %u\n", ntohs(dht->net->port));
|
||||
|
||||
if (argc > argvoffset + 3) {
|
||||
printf("Trying to bootstrap into the network...\n");
|
||||
|
@ -177,7 +190,10 @@ int main(int argc, char *argv[])
|
|||
last_LANdiscovery = unix_time();
|
||||
}
|
||||
|
||||
networking_poll(dht->c->lossless_udp->net);
|
||||
#ifdef TCP_RELAY_ENABLED
|
||||
do_TCP_server(tcp_s);
|
||||
#endif
|
||||
networking_poll(dht->net);
|
||||
|
||||
c_sleep(1);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
As maintaining 2 seperate lists of the same information seemed redundant, this list has been phased out.
|
||||
As maintaining 2 separate lists of the same information seemed redundant, this list has been phased out.
|
||||
|
||||
For a current DHT node list please visit http://wiki.tox.im/nodes
|
||||
|
|
|
@ -187,9 +187,7 @@ int main(int argc, char *argv[])
|
|||
IP ip;
|
||||
ip_init(&ip, ipv6enabled);
|
||||
|
||||
DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
|
||||
|
||||
new_keys(dht->c);
|
||||
DHT *dht = new_DHT(new_networking(ip, PORT));
|
||||
printf("OUR ID: ");
|
||||
uint32_t i;
|
||||
|
||||
|
@ -245,7 +243,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
*/
|
||||
networking_poll(dht->c->lossless_udp->net);
|
||||
networking_poll(dht->net);
|
||||
|
||||
print_clientlist(dht);
|
||||
print_friendlist(dht);
|
||||
|
|
|
@ -1,260 +0,0 @@
|
|||
/* Lossless_UDP testclient
|
||||
* A program that connects and sends a file using our lossless UDP algorithm.
|
||||
* NOTE: this program simulates a 33% packet loss.
|
||||
*
|
||||
* Best used in combination with Lossless_UDP_testserver
|
||||
*
|
||||
* Compile with: gcc -O2 -Wall -lsodium -o testclient ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testclient.c
|
||||
*
|
||||
* Command line arguments are the ip and port to connect and send the file to.
|
||||
* EX: ./testclient --ipv4 127.0.0.1 33445 filename.txt
|
||||
*
|
||||
* Copyright (C) 2013 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "../toxcore/network.h"
|
||||
#include "../toxcore/Lossless_UDP.h"
|
||||
#include "../toxcore/util.h"
|
||||
#include "misc_tools.c"
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
|
||||
#define c_sleep(x) Sleep(1*x)
|
||||
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#define c_sleep(x) usleep(1000*x)
|
||||
|
||||
#endif
|
||||
|
||||
#define PORT 33446
|
||||
|
||||
void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
|
||||
{
|
||||
uint32_t i;
|
||||
printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
|
||||
printf("--------------------BEGIN-----------------------------\n");
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (data[i] < 16)
|
||||
printf("0");
|
||||
|
||||
printf("%hhX", data[i]);
|
||||
}
|
||||
|
||||
printf("\n--------------------END-----------------------------\n\n\n");
|
||||
}
|
||||
|
||||
void printip(IP_Port ip_port)
|
||||
{
|
||||
printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
|
||||
}
|
||||
/*
|
||||
void printpackets(Data test)
|
||||
{
|
||||
int i;
|
||||
if(test.size == 0)
|
||||
return;
|
||||
printf("SIZE: %u\n", test.size);
|
||||
for(i =0; i < test.size; i++)
|
||||
{
|
||||
printf("%hhX", test.data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printconnection(int connection_id)
|
||||
{
|
||||
printf("--------------------BEGIN---------------------\n");
|
||||
IP_Port ip_port = connections[connection_id].ip_port;
|
||||
printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port));
|
||||
printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status,
|
||||
connections[connection_id].inbound, connections[connection_id].SYNC_rate);
|
||||
printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate,
|
||||
connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv);
|
||||
int i;
|
||||
for(i =0; i < MAX_QUEUE_NUM; i++)
|
||||
{
|
||||
printf(" %u ",i);
|
||||
printpackets(connections[connection_id].sendbuffer[i]);
|
||||
}
|
||||
for(i =0; i < MAX_QUEUE_NUM; i++)
|
||||
{
|
||||
printf(" %u ",i);
|
||||
printpackets(connections[connection_id].recvbuffer[i]);
|
||||
}
|
||||
Data sendbuffer[MAX_QUEUE_NUM];
|
||||
Data recvbuffer[MAX_QUEUE_NUM];
|
||||
printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n",
|
||||
connections[connection_id].recv_packetnum,
|
||||
connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum,
|
||||
connections[connection_id].successful_sent,
|
||||
connections[connection_id].successful_read);
|
||||
|
||||
printf("req packets: \n");
|
||||
for(i = 0; i < BUFFER_PACKET_NUM; i++)
|
||||
{
|
||||
printf(" %u ", connections[connection_id].req_packets[i]);
|
||||
}
|
||||
printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets,
|
||||
connections[connection_id].recv_counter, connections[connection_id].send_counter);
|
||||
|
||||
printf("--------------------END---------------------\n");
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/*( receive packets and send them to the packethandler */
|
||||
/*run doLossless_UDP(); */
|
||||
//void Lossless_UDP()
|
||||
//{
|
||||
/* IP_Port ip_port;
|
||||
uint8_t data[MAX_UDP_PACKET_SIZE];
|
||||
uint32_t length;
|
||||
while (receivepacket(&ip_port, data, &length) != -1) {
|
||||
printf("packet with length: %u\n", length); */
|
||||
/* if(rand() % 3 != 1)//add packet loss
|
||||
{ */
|
||||
/*
|
||||
if (LosslessUDP_handlepacket(data, length, ip_port))
|
||||
printpacket(data, length, ip_port);
|
||||
else
|
||||
printf("Received handled packet with length: %u\n", length); //printconnection(0); */
|
||||
|
||||
/* } */
|
||||
/* }*/
|
||||
|
||||
//networking_poll();
|
||||
|
||||
//doLossless_UDP();
|
||||
|
||||
//}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* let user override default by cmdline */
|
||||
uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
|
||||
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
|
||||
|
||||
if (argvoffset < 0)
|
||||
exit(1);
|
||||
|
||||
if (argc < argvoffset + 4) {
|
||||
printf("Usage: %s [--ipv4|--ipv6] ip port filename\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uint8_t buffer[MAX_DATA_SIZE];
|
||||
int read;
|
||||
|
||||
FILE *file = fopen(argv[argvoffset + 3], "rb");
|
||||
|
||||
if (file == NULL) {
|
||||
printf("Failed to open file \"%s\".\n", argv[argvoffset + 3]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* initialize networking */
|
||||
/* bind to ip 0.0.0.0:PORT */
|
||||
IP ip;
|
||||
ip_init(&ip, ipv6enabled);
|
||||
|
||||
Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
|
||||
perror("Initialization");
|
||||
|
||||
IP_Port serverip;
|
||||
ip_init(&serverip.ip, ipv6enabled);
|
||||
|
||||
if (!addr_resolve(argv[argvoffset + 1], &serverip.ip, NULL)) {
|
||||
printf("Failed to convert \"%s\" into an IP address.\n", argv[argvoffset + 1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
serverip.port = htons(atoi(argv[argvoffset + 2]));
|
||||
printip(serverip);
|
||||
|
||||
int connection = new_connection(ludp, serverip);
|
||||
uint64_t timer = current_time();
|
||||
|
||||
while (1) {
|
||||
/* printconnection(connection); */
|
||||
networking_poll(ludp->net);
|
||||
do_lossless_udp(ludp);
|
||||
|
||||
if (is_connected(ludp, connection) == LUDP_ESTABLISHED) {
|
||||
printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer));
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_connected(ludp, connection) == LUDP_NO_CONNECTION) {
|
||||
printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer));
|
||||
return 1;
|
||||
}
|
||||
|
||||
c_sleep(1);
|
||||
}
|
||||
|
||||
timer = current_time();
|
||||
unsigned long long bytes_sent = 0;
|
||||
|
||||
/*read first part of file */
|
||||
read = fread(buffer, 1, MAX_DATA_SIZE, file);
|
||||
|
||||
while (1) {
|
||||
/* printconnection(connection); */
|
||||
networking_poll(ludp->net);
|
||||
do_lossless_udp(ludp);
|
||||
|
||||
if (is_connected(ludp, connection) == LUDP_ESTABLISHED) {
|
||||
|
||||
while (write_packet(ludp, connection, buffer, read)) {
|
||||
bytes_sent += read;
|
||||
/* printf("Wrote data.\n"); */
|
||||
read = fread(buffer, 1, MAX_DATA_SIZE, file);
|
||||
|
||||
}
|
||||
|
||||
/* printf("%u\n", sendqueue(connection)); */
|
||||
if (sendqueue(ludp, connection) == 0) {
|
||||
if (read == 0) {
|
||||
unsigned long long us = (unsigned long long)(current_time() - timer);
|
||||
printf("Sent file successfully in: %llu us = %llu seconds. Average speed: %llu KB/s\n", us, us / 1000000UL,
|
||||
bytes_sent / (us / 1024UL));
|
||||
//printf("Total bytes sent: %llu B, Total data sent: %llu B, overhead: %llu B\n", total_bytes_sent, bytes_sent, total_bytes_sent-bytes_sent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%u Client Connecting Lost after: %llu us\n", is_connected(ludp, connection),
|
||||
(unsigned long long)(current_time() - timer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c_sleep(25);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,237 +0,0 @@
|
|||
/* Lossless_UDP testserver
|
||||
* A program that waits for a lossless UDP connection and then saves all the data received to a file.
|
||||
* NOTE: this program simulates a 33% packet loss.
|
||||
*
|
||||
* Best used in combination with Lossless_UDP_testclient
|
||||
*
|
||||
* Compile with: gcc -O2 -Wall -lsodium -o testserver ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testserver.c
|
||||
*
|
||||
* Command line argument is the name of the file to save what we receive to.
|
||||
* EX: ./testserver filename1.txt
|
||||
*
|
||||
* Copyright (C) 2013 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "../toxcore/network.h"
|
||||
#include "../toxcore/Lossless_UDP.h"
|
||||
#include "../toxcore/util.h"
|
||||
#include "misc_tools.c"
|
||||
|
||||
//Sleep function (x = milliseconds)
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
|
||||
#define c_sleep(x) Sleep(1*x)
|
||||
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#define c_sleep(x) usleep(1000*x)
|
||||
|
||||
#endif
|
||||
|
||||
#define PORT 33445
|
||||
|
||||
void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
|
||||
{
|
||||
uint32_t i;
|
||||
printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
|
||||
printf("--------------------BEGIN-----------------------------\n");
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (data[i] < 16)
|
||||
printf("0");
|
||||
|
||||
printf("%hhX", data[i]);
|
||||
}
|
||||
|
||||
printf("\n--------------------END-----------------------------\n\n\n");
|
||||
}
|
||||
|
||||
/*
|
||||
void printpackets(Data test)
|
||||
{
|
||||
int i;
|
||||
if(test.size == 0)
|
||||
return;
|
||||
printf("SIZE: %u\n", test.size);
|
||||
for(i =0; i < test.size; i++)
|
||||
{
|
||||
printf("%hhX", test.data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printconnection(int connection_id)
|
||||
{
|
||||
printf("--------------------BEGIN---------------------\n");
|
||||
IP_Port ip_port = connections[connection_id].ip_port;
|
||||
printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port));
|
||||
printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status,
|
||||
connections[connection_id].inbound, connections[connection_id].SYNC_rate);
|
||||
printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate,
|
||||
connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv);
|
||||
int i;
|
||||
for(i =0; i < MAX_QUEUE_NUM; i++)
|
||||
{
|
||||
printf(" %u ",i);
|
||||
printpackets(connections[connection_id].sendbuffer[i]);
|
||||
}
|
||||
for(i =0; i < MAX_QUEUE_NUM; i++)
|
||||
{
|
||||
printf(" %u ",i);
|
||||
printpackets(connections[connection_id].recvbuffer[i]);
|
||||
}
|
||||
Data sendbuffer[MAX_QUEUE_NUM];
|
||||
Data recvbuffer[MAX_QUEUE_NUM];
|
||||
printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n",
|
||||
connections[connection_id].recv_packetnum,
|
||||
connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum,
|
||||
connections[connection_id].successful_sent,
|
||||
connections[connection_id].successful_read);
|
||||
|
||||
printf("req packets: \n");
|
||||
for(i = 0; i < BUFFER_PACKET_NUM; i++)
|
||||
{
|
||||
printf(" %u ", connections[connection_id].req_packets[i]);
|
||||
}
|
||||
printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets,
|
||||
connections[connection_id].recv_counter, connections[connection_id].send_counter);
|
||||
|
||||
printf("--------------------END---------------------\n");
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/* receive packets and send them to the packethandler
|
||||
* run doLossless_UDP(); */
|
||||
//void Lossless_UDP()
|
||||
//{
|
||||
// IP_Port ip_port;
|
||||
// uint8_t data[MAX_UDP_PACKET_SIZE];
|
||||
// uint32_t length;
|
||||
// while (receivepacket(&ip_port, data, &length) != -1) {
|
||||
//if(rand() % 3 != 1)//add packet loss
|
||||
//{
|
||||
// if (LosslessUDP_handlepacket(data, length, ip_port)) {
|
||||
// printpacket(data, length, ip_port);
|
||||
// } else {
|
||||
//printconnection(0);
|
||||
// printf("Received handled packet with length: %u\n", length);
|
||||
// }
|
||||
//}
|
||||
// }
|
||||
|
||||
// networking_poll();
|
||||
|
||||
//doLossless_UDP();
|
||||
//}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* let user override default by cmdline */
|
||||
uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
|
||||
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
|
||||
|
||||
if (argvoffset < 0)
|
||||
exit(1);
|
||||
|
||||
if (argc < argvoffset + 2) {
|
||||
printf("Usage: %s [--ipv4|--ipv6] filename\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uint8_t buffer[MAX_DATA_SIZE];
|
||||
int read;
|
||||
|
||||
FILE *file = fopen(argv[argvoffset + 1], "wb");
|
||||
|
||||
if (file == NULL) {
|
||||
printf("Failed to open file \"%s\".\n", argv[argvoffset + 1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//initialize networking
|
||||
//bind to ip 0.0.0.0:PORT
|
||||
IP ip;
|
||||
ip_init(&ip, ipv6enabled);
|
||||
|
||||
Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
|
||||
perror("Initialization");
|
||||
|
||||
int connection;
|
||||
uint64_t timer = current_time();
|
||||
|
||||
while (1) {
|
||||
networking_poll(ludp->net);
|
||||
do_lossless_udp(ludp);
|
||||
connection = incoming_connection(ludp, 0);
|
||||
|
||||
if (connection != -1) {
|
||||
if (is_connected(ludp, connection) == LUDP_NOT_CONFIRMED) {
|
||||
printf("Received the connection.\n");
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
c_sleep(1);
|
||||
}
|
||||
|
||||
timer = current_time();
|
||||
|
||||
while (1) {
|
||||
//printconnection(0);
|
||||
networking_poll(ludp->net);
|
||||
|
||||
if (is_connected(ludp, connection) >= LUDP_NOT_CONFIRMED) {
|
||||
confirm_connection(ludp, connection);
|
||||
|
||||
while (1) {
|
||||
read = read_packet(ludp, connection, buffer);
|
||||
|
||||
if (read != 0) {
|
||||
// printf("Received data.\n");
|
||||
if (!fwrite(buffer, read, 1, file))
|
||||
printf("file write error\n");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_lossless_udp(ludp);
|
||||
|
||||
if (is_connected(ludp, connection) == LUDP_TIMED_OUT) {
|
||||
printf("Server Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer));
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
c_sleep(25);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -22,8 +22,6 @@ endif
|
|||
if BUILD_TESTING
|
||||
|
||||
noinst_PROGRAMS += DHT_test \
|
||||
Lossless_UDP_testclient \
|
||||
Lossless_UDP_testserver \
|
||||
Messenger_test \
|
||||
crypto_speed_test
|
||||
|
||||
|
@ -41,40 +39,6 @@ DHT_test_LDADD = $(LIBSODIUM_LDFLAGS) \
|
|||
$(WINSOCK2_LIBS)
|
||||
|
||||
|
||||
Lossless_UDP_testclient_SOURCES = \
|
||||
../testing/Lossless_UDP_testclient.c
|
||||
|
||||
Lossless_UDP_testclient_CFLAGS = \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS)
|
||||
|
||||
Lossless_UDP_testclient_LDADD = \
|
||||
$(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
libtoxcore.la \
|
||||
$(LIBSODIUM_LIBS) \
|
||||
$(NACL_OBJECTS) \
|
||||
$(NACL_LIBS) \
|
||||
$(WINSOCK2_LIBS)
|
||||
|
||||
|
||||
Lossless_UDP_testserver_SOURCES = \
|
||||
../testing/Lossless_UDP_testserver.c
|
||||
|
||||
Lossless_UDP_testserver_CFLAGS = \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS)
|
||||
|
||||
Lossless_UDP_testserver_LDADD = \
|
||||
$(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
libtoxcore.la \
|
||||
$(LIBSODIUM_LIBS) \
|
||||
$(NACL_OBJECTS) \
|
||||
$(NACL_LIBS) \
|
||||
$(WINSOCK2_LIBS)
|
||||
|
||||
|
||||
Messenger_test_SOURCES = \
|
||||
../testing/Messenger_test.c
|
||||
|
||||
|
|
|
@ -97,8 +97,8 @@ int main(int argc, char *argv[])
|
|||
starttime = get_time();
|
||||
|
||||
for (trialno = 0; trialno < numtrials; trialno++) {
|
||||
encrypt_data_fast(k1, n, m, sizeof(m), c);
|
||||
decrypt_data_fast(k2, n, c, sizeof(c), m);
|
||||
encrypt_data_symmetric(k1, n, m, sizeof(m), c);
|
||||
decrypt_data_symmetric(k2, n, c, sizeof(c), m);
|
||||
}
|
||||
|
||||
endtime = get_time();
|
||||
|
|
|
@ -18,15 +18,18 @@ libtoxav_la_SOURCES = ../toxav/event.h \
|
|||
|
||||
libtoxav_la_CFLAGS = -I../toxcore \
|
||||
-I../toxav \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS) \
|
||||
$(AV_CFLAGS) \
|
||||
$(PTHREAD_CFLAGS)
|
||||
|
||||
libtoxav_la_LDFLAGS = $(TOXAV_LT_LDFLAGS) \
|
||||
$(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
$(EXTRA_LT_LDFLAGS)
|
||||
|
||||
libtoxav_la_LIBADD = libtoxcore.la \
|
||||
$(LIBSODIUM_LIBS) \
|
||||
$(NACL_LIBS) \
|
||||
$(PTHREAD_LIBS) \
|
||||
$(AV_LIBS)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "../toxcore/network.h" /* current_time_monotonic() */
|
||||
#include "event.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
@ -199,7 +200,7 @@ void *event_poll( void *arg )
|
|||
|
||||
if ( _event_handler->timed_events ) {
|
||||
|
||||
uint32_t _time = ((uint32_t)(current_time() / 1000));
|
||||
uint32_t _time = ((uint32_t)current_time_monotonic());
|
||||
|
||||
if ( _event_handler->timed_events[0].timeout < _time ) {
|
||||
|
||||
|
@ -249,7 +250,7 @@ int throw_timer_event ( void * (func)(void *), void *arg, unsigned timeout)
|
|||
|
||||
size_t _counter = event_handler.timed_events_count;
|
||||
|
||||
event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)(current_time() / 1000));
|
||||
event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)current_time_monotonic());
|
||||
event_handler.timed_events[_counter - 1].id = _unique_id;
|
||||
++_unique_id;
|
||||
|
||||
|
@ -330,7 +331,7 @@ int reset_timer_event ( int id, uint32_t timeout )
|
|||
/* Find it and change */
|
||||
for ( ; _i; _i-- ) {
|
||||
if ( _it->id == id ) {
|
||||
_it->timeout = timeout + ((uint32_t)(current_time() / 1000));
|
||||
_it->timeout = timeout + ((uint32_t)current_time_monotonic());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#define VIDEO_CODEC_ENCODER_INTERFACE (vpx_codec_vp8_cx())
|
||||
|
||||
/* Audio encoding/decoding */
|
||||
#include <opus/opus.h>
|
||||
#include <opus.h>
|
||||
|
||||
typedef enum _Capabilities
|
||||
{
|
||||
|
|
22
toxav/msi.c
22
toxav/msi.c
|
@ -28,8 +28,6 @@
|
|||
|
||||
#include "../toxcore/logger.h"
|
||||
|
||||
/*#define _BSD_SOURCE*/
|
||||
|
||||
#include "msi.h"
|
||||
#include "event.h"
|
||||
|
||||
|
@ -219,7 +217,7 @@ static inline__ const uint8_t *stringify_response ( MSIResponse response )
|
|||
* @param msg Container.
|
||||
* @param data The data.
|
||||
* @return int
|
||||
* @retval -1 Error occured.
|
||||
* @retval -1 Error occurred.
|
||||
* @retval 0 Success.
|
||||
*/
|
||||
int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length )
|
||||
|
@ -354,7 +352,7 @@ void free_message ( MSIMessage *msg )
|
|||
* @param type Request or response.
|
||||
* @param type_id Type of request/response.
|
||||
* @return MSIMessage* Created message.
|
||||
* @retval NULL Error occured.
|
||||
* @retval NULL Error occurred.
|
||||
*/
|
||||
MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id )
|
||||
{
|
||||
|
@ -387,7 +385,7 @@ MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id )
|
|||
*
|
||||
* @param data The data.
|
||||
* @return MSIMessage* Parsed message.
|
||||
* @retval NULL Error occured.
|
||||
* @retval NULL Error occurred.
|
||||
*/
|
||||
MSIMessage *parse_message ( const uint8_t *data, uint16_t length )
|
||||
{
|
||||
|
@ -495,7 +493,7 @@ uint8_t *append_header_to_string (
|
|||
|
||||
*dest = field_byte; /* Set the first byte */
|
||||
|
||||
uint8_t *_getback_byte = dest + 1; /* remeber the byte we were on */
|
||||
uint8_t *_getback_byte = dest + 1; /* remember the byte we were on */
|
||||
dest += 3; /* swith to 4th byte where field value starts */
|
||||
|
||||
/* Now set the field value and calculate it's length */
|
||||
|
@ -685,7 +683,7 @@ static inline__ const uint8_t *stringify_error_code ( MSICallError error_code )
|
|||
* @param msg The message.
|
||||
* @param to Where to.
|
||||
* @return int
|
||||
* @retval -1 Error occured.
|
||||
* @retval -1 Error occurred.
|
||||
* @retval 0 Success.
|
||||
*/
|
||||
int send_message ( MSISession *session, MSICall* call, MSIMessage *msg, uint32_t to )
|
||||
|
@ -838,7 +836,7 @@ int handle_error ( MSISession *session, MSICall* call, MSICallError errid, uint3
|
|||
* @param msg The message.
|
||||
* @return int
|
||||
* @retval -1 No error.
|
||||
* @retval 0 Error occured and response sent.
|
||||
* @retval 0 Error occurred and response sent.
|
||||
*/
|
||||
int has_call_error ( MSISession *session, MSICall* call, MSIMessage *msg )
|
||||
{
|
||||
|
@ -951,7 +949,7 @@ MSICall *init_call ( MSISession *session, int peers, int ringing_timeout )
|
|||
*
|
||||
* @param session Control session.
|
||||
* @return int
|
||||
* @retval -1 Error occured.
|
||||
* @retval -1 Error occurred.
|
||||
* @retval 0 Success.
|
||||
*/
|
||||
int terminate_call ( MSISession *session, MSICall *call )
|
||||
|
@ -1031,7 +1029,7 @@ int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg )
|
|||
* B calls A. Who has advantage is set bey calculating
|
||||
* 'bigger' Call id and then that call id is being used in
|
||||
* future. User with 'bigger' Call id has the advantage
|
||||
* as in he will wait the reponse from the other.
|
||||
* as in he will wait the response from the other.
|
||||
*/
|
||||
|
||||
if ( call_id_bigger (call->id, msg->callid.header_value) == 1 ) { /* Peer has advantage */
|
||||
|
@ -1408,7 +1406,7 @@ void msi_register_callback ( MSICallback callback, MSICallbackID id, void* userd
|
|||
* @param messenger Tox* object.
|
||||
* @param max_calls Amount of calls possible
|
||||
* @return MSISession* The created session.
|
||||
* @retval NULL Error occured.
|
||||
* @retval NULL Error occurred.
|
||||
*/
|
||||
MSISession *msi_init_session ( Messenger* messenger, int32_t max_calls )
|
||||
{
|
||||
|
@ -1530,7 +1528,7 @@ int msi_invite ( MSISession* session, int32_t* call_index, MSICallType call_type
|
|||
* @param session Control session.
|
||||
* @param call_id To which call is this action handled.
|
||||
* @return int
|
||||
* @retval -1 Error occured.
|
||||
* @retval -1 Error occurred.
|
||||
* @retval 0 Success.
|
||||
*/
|
||||
int msi_hangup ( MSISession* session, int32_t call_index )
|
||||
|
|
|
@ -84,7 +84,7 @@ typedef struct _MSICall { /* Call info structure */
|
|||
int ringing_timer_id; /* Timer id for ringing timeout */
|
||||
|
||||
pthread_mutex_t mutex; /* It's to be assumed that call will have
|
||||
* seperate thread so add mutex
|
||||
* separate thread so add mutex
|
||||
*/
|
||||
uint32_t *peers;
|
||||
uint16_t peer_count;
|
||||
|
@ -156,7 +156,7 @@ void msi_register_callback(MSICallback callback, MSICallbackID id, void* userdat
|
|||
* @param messenger Tox* object.
|
||||
* @param max_calls Amount of calls possible
|
||||
* @return MSISession* The created session.
|
||||
* @retval NULL Error occured.
|
||||
* @retval NULL Error occurred.
|
||||
*/
|
||||
MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls );
|
||||
|
||||
|
@ -189,7 +189,7 @@ int msi_invite ( MSISession *session, int32_t* call_index, MSICallType call_type
|
|||
* @param session Control session.
|
||||
* @param call_index To which call is this action handled.
|
||||
* @return int
|
||||
* @retval -1 Error occured.
|
||||
* @retval -1 Error occurred.
|
||||
* @retval 0 Success.
|
||||
*/
|
||||
int msi_hangup ( MSISession *session, int32_t call_index );
|
||||
|
|
45
toxav/rtp.c
45
toxav/rtp.c
|
@ -170,8 +170,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target)
|
|||
uint16_t _nonce_counter;
|
||||
|
||||
uint8_t _reverse_bytes[2];
|
||||
_reverse_bytes[0] = nonce[crypto_secretbox_NONCEBYTES - 1];
|
||||
_reverse_bytes[1] = nonce[crypto_secretbox_NONCEBYTES - 2];
|
||||
_reverse_bytes[0] = nonce[crypto_box_NONCEBYTES - 1];
|
||||
_reverse_bytes[1] = nonce[crypto_box_NONCEBYTES - 2];
|
||||
|
||||
bytes_to_U16(&_nonce_counter, _reverse_bytes );
|
||||
|
||||
|
@ -179,8 +179,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target)
|
|||
if (_nonce_counter > UINT16_MAX - target ) { /* 2 bytes are not long enough */
|
||||
uint8_t _it = 3;
|
||||
|
||||
while ( _it <= crypto_secretbox_NONCEBYTES ) _it += ++nonce[crypto_secretbox_NONCEBYTES - _it] ?
|
||||
crypto_secretbox_NONCEBYTES : 1;
|
||||
while ( _it <= crypto_box_NONCEBYTES ) _it += ++nonce[crypto_box_NONCEBYTES - _it] ?
|
||||
crypto_box_NONCEBYTES : 1;
|
||||
|
||||
_nonce_counter = _nonce_counter - (UINT16_MAX - target ); /* Assign the rest of it */
|
||||
} else { /* Increase nonce */
|
||||
|
@ -191,8 +191,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target)
|
|||
/* Assign the last bytes */
|
||||
|
||||
U16_to_bytes( _reverse_bytes, _nonce_counter);
|
||||
nonce [crypto_secretbox_NONCEBYTES - 1] = _reverse_bytes[0];
|
||||
nonce [crypto_secretbox_NONCEBYTES - 2] = _reverse_bytes[1];
|
||||
nonce [crypto_box_NONCEBYTES - 1] = _reverse_bytes[0];
|
||||
nonce [crypto_box_NONCEBYTES - 2] = _reverse_bytes[1];
|
||||
|
||||
}
|
||||
|
||||
|
@ -416,7 +416,7 @@ RTPHeader *build_header ( RTPSession *session )
|
|||
ADD_SETTING_PAYLOAD ( _retu, session->payload_type );
|
||||
|
||||
_retu->sequnum = session->sequnum;
|
||||
_retu->timestamp = ((uint32_t)(current_time() / 1000)); /* micro to milli */
|
||||
_retu->timestamp = current_time_monotonic(); /* milliseconds */
|
||||
_retu->ssrc = session->ssrc;
|
||||
|
||||
int i;
|
||||
|
@ -505,7 +505,7 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
|
|||
RTPSession *_session = object;
|
||||
RTPMessage *_msg;
|
||||
|
||||
if ( !_session || length < 13 + crypto_secretbox_MACBYTES) { /* 12 is the minimum length for rtp + desc. byte */
|
||||
if ( !_session || length < 13 + crypto_box_MACBYTES) { /* 12 is the minimum length for rtp + desc. byte */
|
||||
LOGGER_WARNING("No session or invalid length of received buffer!");
|
||||
return -1;
|
||||
}
|
||||
|
@ -521,12 +521,13 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
|
|||
bytes_to_U16(&_sequnum, data + 1);
|
||||
|
||||
/* Clculate the right nonce */
|
||||
uint8_t _calculated[crypto_secretbox_NONCEBYTES];
|
||||
memcpy(_calculated, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES);
|
||||
uint8_t _calculated[crypto_box_NONCEBYTES];
|
||||
memcpy(_calculated, _session->decrypt_nonce, crypto_box_NONCEBYTES);
|
||||
increase_nonce ( _calculated, _sequnum );
|
||||
|
||||
/* Decrypt message */
|
||||
int _decrypted_length = decrypt_data_symmetric((uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain );
|
||||
int _decrypted_length = decrypt_data_symmetric(
|
||||
(uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain );
|
||||
|
||||
/* This packet is either not encrypted properly or late
|
||||
*/
|
||||
|
@ -557,8 +558,8 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
|
|||
}
|
||||
|
||||
/* A new cycle setting. */
|
||||
memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(_session->decrypt_nonce, _calculated, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(_session->decrypt_nonce, _calculated, crypto_box_NONCEBYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -774,8 +775,8 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
|
|||
_send_data[0] = session->prefix;
|
||||
|
||||
/* Generate the right nonce */
|
||||
uint8_t _calculated[crypto_secretbox_NONCEBYTES];
|
||||
memcpy(_calculated, session->encrypt_nonce, crypto_secretbox_NONCEBYTES);
|
||||
uint8_t _calculated[crypto_box_NONCEBYTES];
|
||||
memcpy(_calculated, session->encrypt_nonce, crypto_box_NONCEBYTES);
|
||||
increase_nonce ( _calculated, msg->header->sequnum );
|
||||
|
||||
/* Need to skip 2 bytes that are for sequnum */
|
||||
|
@ -798,7 +799,7 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
|
|||
/* Set sequ number */
|
||||
if ( session->sequnum >= MAX_SEQU_NUM ) {
|
||||
session->sequnum = 0;
|
||||
memcpy(session->encrypt_nonce, _calculated, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(session->encrypt_nonce, _calculated, crypto_box_NONCEBYTES);
|
||||
} else {
|
||||
session->sequnum++;
|
||||
}
|
||||
|
@ -888,16 +889,16 @@ RTPSession *rtp_init_session ( int payload_type,
|
|||
_retu->decrypt_key = decrypt_key;
|
||||
|
||||
/* Need to allocate new memory */
|
||||
_retu->encrypt_nonce = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) );
|
||||
_retu->encrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) );
|
||||
assert(_retu->encrypt_nonce);
|
||||
_retu->decrypt_nonce = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) );
|
||||
_retu->decrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) );
|
||||
assert(_retu->decrypt_nonce);
|
||||
_retu->nonce_cycle = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) );
|
||||
_retu->nonce_cycle = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) );
|
||||
assert(_retu->nonce_cycle);
|
||||
|
||||
memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_box_NONCEBYTES);
|
||||
|
||||
_retu->csrc = calloc(1, sizeof (uint32_t));
|
||||
assert(_retu->csrc);
|
||||
|
|
599
toxcore/DHT.c
599
toxcore/DHT.c
|
@ -165,15 +165,15 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secr
|
|||
}
|
||||
}
|
||||
|
||||
/* Copy shared_key to decrypt DHT packet from client_id into shared_key
|
||||
* for packets that we recieve.
|
||||
/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key
|
||||
* for packets that we receive.
|
||||
*/
|
||||
void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id)
|
||||
{
|
||||
return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id);
|
||||
}
|
||||
|
||||
/* Copy shared_key to decrypt DHT packet from client_id into shared_key
|
||||
/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key
|
||||
* for packets that we send.
|
||||
*/
|
||||
void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id)
|
||||
|
@ -181,6 +181,155 @@ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id)
|
|||
return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id);
|
||||
}
|
||||
|
||||
void to_net_family(IP *ip)
|
||||
{
|
||||
if (ip->family == AF_INET)
|
||||
ip->family = TOX_AF_INET;
|
||||
else if (ip->family == AF_INET6)
|
||||
ip->family = TOX_AF_INET6;
|
||||
}
|
||||
|
||||
void to_host_family(IP *ip)
|
||||
{
|
||||
if (ip->family == TOX_AF_INET)
|
||||
ip->family = AF_INET;
|
||||
else if (ip->family == TOX_AF_INET6)
|
||||
ip->family = AF_INET6;
|
||||
}
|
||||
|
||||
/* Pack number of nodes into data of maxlength length.
|
||||
*
|
||||
* return length of packed nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number)
|
||||
{
|
||||
uint32_t i, packed_length = 0;
|
||||
|
||||
for (i = 0; i < number; ++i) {
|
||||
int ipv6 = -1;
|
||||
uint8_t net_family;
|
||||
|
||||
if (nodes[i].ip_port.ip.family == AF_INET) {
|
||||
ipv6 = 0;
|
||||
net_family = TOX_AF_INET;
|
||||
} else if (nodes[i].ip_port.ip.family == TCP_INET) {
|
||||
ipv6 = 0;
|
||||
net_family = TOX_TCP_INET;
|
||||
} else if (nodes[i].ip_port.ip.family == AF_INET6) {
|
||||
ipv6 = 1;
|
||||
net_family = TOX_AF_INET6;
|
||||
} else if (nodes[i].ip_port.ip.family == TCP_INET6) {
|
||||
ipv6 = 1;
|
||||
net_family = TOX_TCP_INET6;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ipv6 == 0) {
|
||||
uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (packed_length + size > length)
|
||||
return -1;
|
||||
|
||||
data[packed_length] = net_family;
|
||||
memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE);
|
||||
packed_length += size;
|
||||
} else if (ipv6 == 1) {
|
||||
uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (packed_length + size > length)
|
||||
return -1;
|
||||
|
||||
data[packed_length] = net_family;
|
||||
memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE);
|
||||
packed_length += size;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return packed_length;
|
||||
}
|
||||
|
||||
/* Unpack data of length into nodes of size max_num_nodes.
|
||||
* Put the length of the data processed in processed_data_len.
|
||||
* tcp_enabled sets if TCP nodes are expected (true) or not (false).
|
||||
*
|
||||
* return number of unpacked nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data,
|
||||
uint16_t length, uint8_t tcp_enabled)
|
||||
{
|
||||
uint32_t num = 0, len_processed = 0;
|
||||
|
||||
while (num < max_num_nodes && len_processed < length) {
|
||||
int ipv6 = -1;
|
||||
uint8_t host_family;
|
||||
|
||||
if (data[len_processed] == TOX_AF_INET) {
|
||||
ipv6 = 0;
|
||||
host_family = AF_INET;
|
||||
} else if (data[len_processed] == TOX_TCP_INET) {
|
||||
if (!tcp_enabled)
|
||||
return -1;
|
||||
|
||||
ipv6 = 0;
|
||||
host_family = TCP_INET;
|
||||
} else if (data[len_processed] == TOX_AF_INET6) {
|
||||
ipv6 = 1;
|
||||
host_family = AF_INET6;
|
||||
} else if (data[len_processed] == TOX_TCP_INET6) {
|
||||
if (!tcp_enabled)
|
||||
return -1;
|
||||
|
||||
ipv6 = 1;
|
||||
host_family = TCP_INET6;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ipv6 == 0) {
|
||||
uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (len_processed + size > length)
|
||||
return -1;
|
||||
|
||||
nodes[num].ip_port.ip.family = host_family;
|
||||
memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4));
|
||||
memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t));
|
||||
memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), CLIENT_ID_SIZE);
|
||||
len_processed += size;
|
||||
++num;
|
||||
} else if (ipv6 == 1) {
|
||||
uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (len_processed + size > length)
|
||||
return -1;
|
||||
|
||||
nodes[num].ip_port.ip.family = host_family;
|
||||
memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6));
|
||||
memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t));
|
||||
memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), CLIENT_ID_SIZE);
|
||||
len_processed += size;
|
||||
++num;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (processed_data_len)
|
||||
*processed_data_len = len_processed;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Check if client with client_id is already in list of length length.
|
||||
* If it is then set its corresponding timestamp to current time.
|
||||
|
@ -266,7 +415,7 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
|
|||
/* Check if client with client_id is already in node format list of length length.
|
||||
*
|
||||
* return 1 if true.
|
||||
* return 2 if false.
|
||||
* return 0 if false.
|
||||
*/
|
||||
static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *client_id)
|
||||
{
|
||||
|
@ -310,15 +459,15 @@ static uint8_t hardening_correct(Hardening *h)
|
|||
/*
|
||||
* helper for get_close_nodes(). argument list is a monster :D
|
||||
*/
|
||||
static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list,
|
||||
static void get_close_nodes_inner(uint8_t *client_id, Node_format *nodes_list,
|
||||
sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length,
|
||||
uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good)
|
||||
{
|
||||
if ((sa_family != AF_INET) && (sa_family != AF_INET6))
|
||||
if ((sa_family != AF_INET) && (sa_family != AF_INET6) && (sa_family != 0))
|
||||
return;
|
||||
|
||||
uint32_t num_nodes = *num_nodes_ptr;
|
||||
int ipv46x, j, closest;
|
||||
int j, closest;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < client_list_length; i++) {
|
||||
|
@ -330,39 +479,22 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
|
|||
|
||||
IPPTsPng *ipptp = NULL;
|
||||
|
||||
if (sa_family == AF_INET)
|
||||
if (sa_family == AF_INET) {
|
||||
ipptp = &client->assoc4;
|
||||
else
|
||||
} else if (sa_family == AF_INET6) {
|
||||
ipptp = &client->assoc6;
|
||||
} else {
|
||||
if (client->assoc4.timestamp >= client->assoc6.timestamp) {
|
||||
ipptp = &client->assoc4;
|
||||
} else {
|
||||
ipptp = &client->assoc6;
|
||||
}
|
||||
}
|
||||
|
||||
/* node not in a good condition? */
|
||||
if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT))
|
||||
continue;
|
||||
|
||||
IP *client_ip = &ipptp->ip_port.ip;
|
||||
|
||||
/*
|
||||
* Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for
|
||||
* our connections, instead we have to look if it is an embedded
|
||||
* IPv4-in-IPv6 here and convert it down in sendnodes().
|
||||
*/
|
||||
sa_family_t ip_treat_as_family = client_ip->family;
|
||||
|
||||
if ((dht->net->family == AF_INET6) &&
|
||||
(client_ip->family == AF_INET6)) {
|
||||
/* socket is AF_INET6, address claims AF_INET6:
|
||||
* check for embedded IPv4-in-IPv6 (shouldn't happen anymore,
|
||||
* all storing functions should already convert down to IPv4) */
|
||||
if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr))
|
||||
ip_treat_as_family = AF_INET;
|
||||
}
|
||||
|
||||
ipv46x = !(sa_family == ip_treat_as_family);
|
||||
|
||||
/* node address of the wrong family? */
|
||||
if (ipv46x)
|
||||
continue;
|
||||
|
||||
/* don't send LAN ips to non LAN peers */
|
||||
if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN)
|
||||
continue;
|
||||
|
@ -416,7 +548,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
|
|||
uint8_t is_LAN, uint8_t want_good)
|
||||
{
|
||||
uint32_t num_nodes = 0, i;
|
||||
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
||||
get_close_nodes_inner(client_id, nodes_list, sa_family,
|
||||
dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good);
|
||||
|
||||
/*TODO uncomment this when hardening is added to close friend clients
|
||||
|
@ -426,7 +558,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
|
|||
&num_nodes, is_LAN, want_good);
|
||||
*/
|
||||
for (i = 0; i < dht->num_friends; ++i)
|
||||
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
||||
get_close_nodes_inner(client_id, nodes_list, sa_family,
|
||||
dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
|
||||
&num_nodes, is_LAN, 0);
|
||||
|
||||
|
@ -444,6 +576,7 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa
|
|||
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good);
|
||||
|
||||
#ifdef ENABLE_ASSOC_DHT
|
||||
//TODO: assoc, sa_family 0 (don't care if ipv4 or ipv6) support.
|
||||
Client_data *result[MAX_SENT_NODES];
|
||||
|
||||
Assoc_close_entries request;
|
||||
|
@ -581,7 +714,7 @@ static int replace_possible_bad( Client_data *list,
|
|||
|
||||
sort_list(list, length, comp_client_id);
|
||||
|
||||
/* TODO: decide if the folowing lines should stay commented or not.
|
||||
/* TODO: decide if the following lines should stay commented or not.
|
||||
if (id_closest(comp_client_id, list[0].client_id, client_id) == 1)
|
||||
return 0;*/
|
||||
|
||||
|
@ -823,7 +956,7 @@ end:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define NODES_ENCRYPTED_MESSAGE_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint64_t) + sizeof(Node_format) + sizeof(Node_format) + crypto_secretbox_MACBYTES)
|
||||
#define NODES_ENCRYPTED_MESSAGE_LENGTH (crypto_box_NONCEBYTES + sizeof(uint64_t) + sizeof(Node_format) + sizeof(Node_format) + crypto_box_MACBYTES)
|
||||
|
||||
/* Send a getnodes request.
|
||||
sendback_node is the node that it will send back the response to (set to NULL to disable this) */
|
||||
|
@ -842,23 +975,23 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
|
|||
|
||||
uint64_t temp_time = unix_time();
|
||||
memcpy(plain_message, &temp_time, sizeof(temp_time));
|
||||
Node_format reciever;
|
||||
memcpy(reciever.client_id, public_key, CLIENT_ID_SIZE);
|
||||
reciever.ip_port = ip_port;
|
||||
memcpy(plain_message + sizeof(temp_time), &reciever, sizeof(reciever));
|
||||
Node_format receiver;
|
||||
memcpy(receiver.client_id, public_key, CLIENT_ID_SIZE);
|
||||
receiver.ip_port = ip_port;
|
||||
memcpy(plain_message + sizeof(temp_time), &receiver, sizeof(receiver));
|
||||
|
||||
if (sendback_node != NULL)
|
||||
memcpy(plain_message + sizeof(temp_time) + sizeof(reciever), sendback_node, sizeof(Node_format));
|
||||
memcpy(plain_message + sizeof(temp_time) + sizeof(receiver), sendback_node, sizeof(Node_format));
|
||||
else
|
||||
memset(plain_message + sizeof(temp_time) + sizeof(reciever), 0, sizeof(Node_format));
|
||||
memset(plain_message + sizeof(temp_time) + sizeof(receiver), 0, sizeof(Node_format));
|
||||
|
||||
int len_m = encrypt_data_symmetric(dht->secret_symmetric_key,
|
||||
nonce,
|
||||
plain_message,
|
||||
sizeof(temp_time) + sizeof(reciever) + sizeof(Node_format),
|
||||
encrypted_message + crypto_secretbox_NONCEBYTES);
|
||||
sizeof(temp_time) + sizeof(receiver) + sizeof(Node_format),
|
||||
encrypted_message + crypto_box_NONCEBYTES);
|
||||
|
||||
if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES)
|
||||
if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_box_NONCEBYTES)
|
||||
return -1;
|
||||
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
|
@ -871,11 +1004,11 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
|
|||
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
DHT_get_shared_key_sent(dht, shared_key, public_key);
|
||||
int len = encrypt_data_fast( shared_key,
|
||||
nonce,
|
||||
plain,
|
||||
CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH,
|
||||
encrypt );
|
||||
int len = encrypt_data_symmetric( shared_key,
|
||||
nonce,
|
||||
plain,
|
||||
CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH,
|
||||
encrypt );
|
||||
|
||||
if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
@ -888,132 +1021,46 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
|
|||
return sendpacket(dht->net, ip_port, data, sizeof(data));
|
||||
}
|
||||
|
||||
/* Send a send nodes response. */
|
||||
/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
|
||||
* IPv6 nodes are sent in a different message
|
||||
* encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */
|
||||
static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data,
|
||||
uint8_t *shared_encryption_key)
|
||||
{
|
||||
/* Check if packet is going to be sent to ourself. */
|
||||
if (id_equal(public_key, dht->self_public_key))
|
||||
return -1;
|
||||
|
||||
size_t Node4_format_size = sizeof(Node4_format);
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
|
||||
+ Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET, LAN_ip(ip_port.ip) == 0, 1);
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
||||
uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint8_t encrypt[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
new_nonce(nonce);
|
||||
|
||||
Node4_format *nodes4_list = (Node4_format *)(plain);
|
||||
uint32_t i, num_nodes_ok = 0;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
|
||||
nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
|
||||
|
||||
IP *node_ip = &nodes_list[i].ip_port.ip;
|
||||
|
||||
if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6.in6_addr))
|
||||
/* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */
|
||||
nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.uint32[3];
|
||||
else if (node_ip->family == AF_INET)
|
||||
nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32;
|
||||
else /* shouldn't happen */
|
||||
continue;
|
||||
|
||||
num_nodes_ok++;
|
||||
}
|
||||
|
||||
if (num_nodes_ok < num_nodes) {
|
||||
/* shouldn't happen */
|
||||
num_nodes = num_nodes_ok;
|
||||
}
|
||||
|
||||
memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH);
|
||||
int len = encrypt_data_fast( shared_encryption_key,
|
||||
nonce,
|
||||
plain,
|
||||
num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH,
|
||||
encrypt );
|
||||
|
||||
if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH +
|
||||
crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
data[0] = NET_PACKET_SEND_NODES;
|
||||
memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE);
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
|
||||
|
||||
return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
|
||||
}
|
||||
|
||||
void to_net_family(IP *ip)
|
||||
{
|
||||
ip->padding[0] = 0;
|
||||
ip->padding[1] = 0;
|
||||
ip->padding[2] = 0;
|
||||
|
||||
if (ip->family == AF_INET)
|
||||
ip->family = TOX_AF_INET;
|
||||
else if (ip->family == AF_INET6)
|
||||
ip->family = TOX_AF_INET6;
|
||||
}
|
||||
|
||||
void to_host_family(IP *ip)
|
||||
{
|
||||
if (ip->family == TOX_AF_INET)
|
||||
ip->family = AF_INET;
|
||||
else if (ip->family == TOX_AF_INET6)
|
||||
ip->family = AF_INET6;
|
||||
}
|
||||
/* Send a send nodes response: message for IPv6 nodes */
|
||||
static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data,
|
||||
uint8_t *shared_encryption_key)
|
||||
static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *sendback_data,
|
||||
uint16_t length, uint8_t *shared_encryption_key)
|
||||
{
|
||||
/* Check if packet is going to be sent to ourself. */
|
||||
if (id_equal(public_key, dht->self_public_key))
|
||||
return -1;
|
||||
|
||||
if (length > NODES_ENCRYPTED_MESSAGE_LENGTH || length == 0)
|
||||
return -1;
|
||||
|
||||
size_t Node_format_size = sizeof(Node_format);
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
|
||||
+ Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
+ Node_format_size * MAX_SENT_NODES + length + crypto_box_MACBYTES];
|
||||
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6, LAN_ip(ip_port.ip) == 0, 1);
|
||||
uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1);
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
||||
uint8_t plain[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint8_t encrypt[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
uint8_t plain[1 + Node_format_size * MAX_SENT_NODES + length];
|
||||
uint8_t encrypt[sizeof(plain) + crypto_box_MACBYTES];
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
new_nonce(nonce);
|
||||
|
||||
uint32_t i;
|
||||
int nodes_length = pack_nodes(plain + 1, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes);
|
||||
|
||||
for (i = 0; i < num_nodes; ++i)
|
||||
to_net_family(&nodes_list[i].ip_port.ip);
|
||||
if (nodes_length <= 0)
|
||||
return -1;
|
||||
|
||||
memcpy(plain, nodes_list, num_nodes * Node_format_size);
|
||||
memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH);
|
||||
int len = encrypt_data_fast( shared_encryption_key,
|
||||
nonce,
|
||||
plain,
|
||||
num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH,
|
||||
encrypt );
|
||||
plain[0] = num_nodes;
|
||||
memcpy(plain + 1 + nodes_length, sendback_data, length);
|
||||
int len = encrypt_data_symmetric( shared_encryption_key,
|
||||
nonce,
|
||||
plain,
|
||||
1 + nodes_length + length,
|
||||
encrypt );
|
||||
|
||||
if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES)
|
||||
if (len != 1 + nodes_length + length + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
data[0] = NET_PACKET_SEND_NODES_IPV6;
|
||||
|
@ -1026,35 +1073,38 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_
|
|||
|
||||
static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
uint32_t cmp_len = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + crypto_box_MACBYTES;
|
||||
|
||||
if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH +
|
||||
crypto_box_MACBYTES ))
|
||||
if (length <= cmp_len)
|
||||
return 1;
|
||||
|
||||
if (length > cmp_len + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
return 1;
|
||||
|
||||
uint16_t sendback_data_length = length - cmp_len;
|
||||
|
||||
DHT *dht = object;
|
||||
|
||||
/* Check if packet is from ourself. */
|
||||
if (id_equal(packet + 1, dht->self_public_key))
|
||||
return 1;
|
||||
|
||||
uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint8_t plain[CLIENT_ID_SIZE + sendback_data_length];
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
|
||||
DHT_get_shared_key_recv(dht, shared_key, packet + 1);
|
||||
int len = decrypt_data_fast( shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
|
||||
plain );
|
||||
int len = decrypt_data_symmetric( shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
CLIENT_ID_SIZE + sendback_data_length + crypto_box_MACBYTES,
|
||||
plain );
|
||||
|
||||
if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
if (len != CLIENT_ID_SIZE + sendback_data_length)
|
||||
return 1;
|
||||
|
||||
sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key);
|
||||
sendnodes_ipv6(dht, source, packet + 1, plain,
|
||||
plain + CLIENT_ID_SIZE, shared_key); /* TODO: prevent possible amplification attacks */
|
||||
sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, sendback_data_length, shared_key);
|
||||
|
||||
add_to_ping(dht->ping, packet + 1, source);
|
||||
//send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1066,8 +1116,8 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i
|
|||
{
|
||||
uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
|
||||
if (decrypt_data_symmetric(dht->secret_symmetric_key, encrypted_data, encrypted_data + crypto_secretbox_NONCEBYTES,
|
||||
NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES,
|
||||
if (decrypt_data_symmetric(dht->secret_symmetric_key, encrypted_data, encrypted_data + crypto_box_NONCEBYTES,
|
||||
NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_box_NONCEBYTES,
|
||||
plain_message) != sizeof(uint64_t) + sizeof(Node_format) * 2)
|
||||
return 0;
|
||||
|
||||
|
@ -1089,44 +1139,58 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i
|
|||
}
|
||||
|
||||
/* Function is needed in following functions. */
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list,
|
||||
uint16_t num_nodes);
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data,
|
||||
uint16_t nodes_data_length);
|
||||
|
||||
static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length,
|
||||
size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node)
|
||||
Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
|
||||
{
|
||||
if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
return 1;
|
||||
|
||||
DHT *dht = object;
|
||||
uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES;
|
||||
uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + 1 + NODES_ENCRYPTED_MESSAGE_LENGTH +
|
||||
crypto_box_MACBYTES;
|
||||
|
||||
if (length <= cid_size) /* too short */
|
||||
return 1;
|
||||
|
||||
uint32_t data_size = length - cid_size;
|
||||
|
||||
if ((data_size % node_format_size) != 0) /* invalid length */
|
||||
if (data_size == 0)
|
||||
return 1;
|
||||
|
||||
uint32_t num_nodes = data_size / node_format_size;
|
||||
|
||||
if (num_nodes > MAX_SENT_NODES) /* too long */
|
||||
if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */
|
||||
return 1;
|
||||
|
||||
uint8_t plain[1 + data_size + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
DHT_get_shared_key_sent(dht, shared_key, packet + 1);
|
||||
int len = decrypt_data_fast(
|
||||
int len = decrypt_data_symmetric(
|
||||
shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
|
||||
1 + data_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
|
||||
plain);
|
||||
|
||||
if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
if ((unsigned int)len != sizeof(plain))
|
||||
return 1;
|
||||
|
||||
if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node))
|
||||
if (plain[0] > size_plain_nodes || plain[0] == 0)
|
||||
return 1;
|
||||
|
||||
Node_format sendback_node;
|
||||
|
||||
if (!sent_getnode_to_node(dht, packet + 1, source, plain + 1 + data_size, &sendback_node))
|
||||
return 1;
|
||||
|
||||
uint16_t length_nodes = 0;
|
||||
int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0);
|
||||
|
||||
if (length_nodes != data_size)
|
||||
return 1;
|
||||
|
||||
if (num_nodes != plain[0])
|
||||
return 1;
|
||||
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
/* store the address the *request* was sent to */
|
||||
|
@ -1134,79 +1198,28 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet,
|
|||
|
||||
*num_nodes_out = num_nodes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
size_t node4_format_size = sizeof(Node4_format);
|
||||
uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint32_t num_nodes;
|
||||
|
||||
Node_format sendback_node;
|
||||
|
||||
if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes,
|
||||
&sendback_node))
|
||||
return 1;
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
||||
Node4_format *nodes4_list = (Node4_format *)(plain);
|
||||
|
||||
uint64_t time_now = unix_time();
|
||||
IPPTs ippts;
|
||||
ippts.ip_port.ip.family = AF_INET;
|
||||
ippts.timestamp = time_now;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
|
||||
for (i = 0; i < num_nodes; i++)
|
||||
if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) {
|
||||
ippts.ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||
ippts.ip_port.port = nodes4_list[i].ip_port.port;
|
||||
|
||||
send_ping_request(dht->ping, ippts.ip_port, nodes4_list[i].client_id);
|
||||
returnedip_ports(dht, ippts.ip_port, nodes4_list[i].client_id, packet + 1);
|
||||
|
||||
memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
|
||||
ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port);
|
||||
|
||||
}
|
||||
|
||||
send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes);
|
||||
send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain + 1, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
size_t node_format_size = sizeof(Node_format);
|
||||
uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
Node_format plain_nodes[MAX_SENT_NODES];
|
||||
uint32_t num_nodes;
|
||||
|
||||
Node_format sendback_node;
|
||||
|
||||
if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes,
|
||||
&sendback_node))
|
||||
if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes))
|
||||
return 1;
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
||||
Node_format *nodes_list = (Node_format *)(plain);
|
||||
uint32_t i;
|
||||
send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes);
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
to_host_family(&nodes_list[i].ip_port.ip);
|
||||
|
||||
if (ipport_isset(&nodes_list[i].ip_port)) {
|
||||
send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id);
|
||||
returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
|
||||
if (ipport_isset(&plain_nodes[i].ip_port)) {
|
||||
send_ping_request(dht->ping, plain_nodes[i].ip_port, plain_nodes[i].client_id);
|
||||
returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].client_id, packet + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1595,7 +1608,7 @@ 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.
|
||||
*
|
||||
* return ip for friend.
|
||||
* return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 2).
|
||||
* return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 4).
|
||||
*/
|
||||
int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
|
@ -1724,7 +1737,7 @@ int friend_ips(DHT *dht, IP_Port *ip_portlist, uint8_t *friend_id)
|
|||
static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t type)
|
||||
{
|
||||
uint8_t data[sizeof(uint64_t) + 1];
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
|
||||
|
||||
int num = 0;
|
||||
|
||||
|
@ -1935,7 +1948,7 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8
|
|||
if (length > HARDREQ_DATA_SIZE - 1)
|
||||
return -1;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
|
||||
uint8_t data[HARDREQ_DATA_SIZE] = {0};
|
||||
data[0] = type;
|
||||
memcpy(data + 1, contents, length);
|
||||
|
@ -1958,17 +1971,17 @@ static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *
|
|||
}
|
||||
|
||||
/* Send a get node hardening response */
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list,
|
||||
uint16_t num_nodes)
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data,
|
||||
uint16_t nodes_data_length)
|
||||
{
|
||||
if (!ip_isset(&sendto->ip_port.ip))
|
||||
return -1;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + num_nodes * sizeof(Node_format)];
|
||||
uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + nodes_data_length];
|
||||
data[0] = CHECK_TYPE_GETNODE_RES;
|
||||
memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE);
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE, list, num_nodes * sizeof(Node_format));
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE, nodes_data, nodes_data_length);
|
||||
int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data,
|
||||
sizeof(data), CRYPTO_PACKET_HARDENING);
|
||||
|
||||
|
@ -2056,28 +2069,22 @@ static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey
|
|||
if (length <= CLIENT_ID_SIZE + 1)
|
||||
return 1;
|
||||
|
||||
if ((length - 1 - CLIENT_ID_SIZE) % sizeof(Node_format) != 0)
|
||||
if (length > 1 + CLIENT_ID_SIZE + sizeof(Node_format) * MAX_SENT_NODES)
|
||||
return 1;
|
||||
|
||||
uint16_t num = (length - 1 - CLIENT_ID_SIZE) / sizeof(Node_format);
|
||||
uint16_t length_nodes = length - 1 - CLIENT_ID_SIZE;
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + CLIENT_ID_SIZE, length_nodes, 0);
|
||||
|
||||
/* TODO: MAX_SENT_NODES nodes should be returned at all times
|
||||
(right now we have a small network size so it could cause problems for testing and etc..) */
|
||||
if (num > MAX_SENT_NODES || num == 0)
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
Node_format nodes[num];
|
||||
memcpy(nodes, packet + 1 + CLIENT_ID_SIZE, sizeof(Node_format)*num);
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
to_host_family(&nodes[i].ip_port.ip);
|
||||
|
||||
/* NOTE: This should work for now but should be changed to something better. */
|
||||
if (have_nodes_closelist(dht, nodes, num) < (uint32_t)((num + 2) / 2))
|
||||
if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2))
|
||||
return 1;
|
||||
|
||||
|
||||
IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family);
|
||||
|
||||
if (temp == NULL)
|
||||
|
@ -2204,6 +2211,8 @@ static int random_node_fromlist(Client_data *list, uint16_t list_size, Node_form
|
|||
* return the number of nodes.
|
||||
*
|
||||
* NOTE:this is used to pick nodes for paths.
|
||||
*
|
||||
* TODO: remove the LAN stuff from this.
|
||||
*/
|
||||
uint16_t random_nodes_path(DHT *dht, Node_format *nodes, uint16_t max_num)
|
||||
{
|
||||
|
@ -2287,12 +2296,54 @@ void do_hardening(DHT *dht)
|
|||
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
|
||||
DHT *new_DHT(Net_Crypto *c)
|
||||
void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object)
|
||||
{
|
||||
dht->cryptopackethandlers[byte].function = cb;
|
||||
dht->cryptopackethandlers[byte].object = object;
|
||||
}
|
||||
|
||||
static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
|
||||
if (packet[0] == NET_PACKET_CRYPTO) {
|
||||
if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES ||
|
||||
length > MAX_CRYPTO_REQUEST_SIZE + crypto_box_MACBYTES)
|
||||
return 1;
|
||||
|
||||
if (memcmp(packet + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us.
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
|
||||
uint8_t number;
|
||||
int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length);
|
||||
|
||||
if (len == -1 || len == 0)
|
||||
return 1;
|
||||
|
||||
if (!dht->cryptopackethandlers[number].function) return 1;
|
||||
|
||||
return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key,
|
||||
data, len);
|
||||
|
||||
} else { /* If request is not for us, try routing it. */
|
||||
int retval = route_packet(dht, packet + 1, packet, length);
|
||||
|
||||
if ((unsigned int)retval == length)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
|
||||
DHT *new_DHT(Networking_Core *net)
|
||||
{
|
||||
/* init time */
|
||||
unix_time_update();
|
||||
|
||||
if (c == NULL)
|
||||
if (net == NULL)
|
||||
return NULL;
|
||||
|
||||
DHT *dht = calloc(1, sizeof(DHT));
|
||||
|
@ -2300,8 +2351,7 @@ DHT *new_DHT(Net_Crypto *c)
|
|||
if (dht == NULL)
|
||||
return NULL;
|
||||
|
||||
dht->c = c;
|
||||
dht->net = c->lossless_udp->net;
|
||||
dht->net = net;
|
||||
dht->ping = new_ping(dht);
|
||||
|
||||
if (dht->ping == NULL) {
|
||||
|
@ -2310,11 +2360,10 @@ DHT *new_DHT(Net_Crypto *c)
|
|||
}
|
||||
|
||||
networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
|
||||
networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht);
|
||||
networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);
|
||||
init_cryptopackets(dht);
|
||||
cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
|
||||
cryptopacket_registerhandler(c, CRYPTO_PACKET_HARDENING, &handle_hardening, dht);
|
||||
networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht);
|
||||
cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
|
||||
cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht);
|
||||
|
||||
new_symmetric_key(dht->secret_symmetric_key);
|
||||
crypto_box_keypair(dht->self_public_key, dht->self_secret_key);
|
||||
|
@ -2361,8 +2410,8 @@ void kill_DHT(DHT *dht)
|
|||
networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL);
|
||||
networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, NULL, NULL);
|
||||
networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL);
|
||||
cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_NAT_PING, NULL, NULL);
|
||||
cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_HARDENING, NULL, NULL);
|
||||
cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL);
|
||||
cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL);
|
||||
kill_ping(dht->ping);
|
||||
free(dht->friends_list);
|
||||
free(dht);
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
#ifndef DHT_H
|
||||
#define DHT_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
#include "crypto_core.h"
|
||||
#include "network.h"
|
||||
|
||||
/* Size of the client_id in bytes. */
|
||||
#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
|
||||
|
@ -36,7 +37,7 @@
|
|||
#define LCLIENT_LIST 32
|
||||
|
||||
/* The max number of nodes to send with send nodes. */
|
||||
#define MAX_SENT_NODES 8
|
||||
#define MAX_SENT_NODES 4
|
||||
|
||||
/* Ping timeout in seconds */
|
||||
#define PING_TIMEOUT 3
|
||||
|
@ -52,6 +53,8 @@
|
|||
/* Redefinitions of variables for safe transfer over wire. */
|
||||
#define TOX_AF_INET 2
|
||||
#define TOX_AF_INET6 10
|
||||
#define TOX_TCP_INET 130
|
||||
#define TOX_TCP_INET6 138
|
||||
|
||||
/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
|
||||
#define DHT_FAKE_FRIEND_NUMBER 4
|
||||
|
@ -128,16 +131,30 @@ typedef struct {
|
|||
NAT nat;
|
||||
} DHT_Friend;
|
||||
|
||||
/* this must be kept even if IP_Port is expanded: wire compatibility */
|
||||
typedef struct {
|
||||
uint8_t client_id[CLIENT_ID_SIZE];
|
||||
IP4_Port ip_port;
|
||||
} Node4_format;
|
||||
|
||||
typedef struct {
|
||||
typedef struct __attribute__ ((__packed__))
|
||||
{
|
||||
uint8_t client_id[CLIENT_ID_SIZE];
|
||||
IP_Port ip_port;
|
||||
} Node_format;
|
||||
}
|
||||
Node_format;
|
||||
|
||||
/* Pack number of nodes into data of maxlength length.
|
||||
*
|
||||
* return length of packed nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number);
|
||||
|
||||
/* Unpack data of length into nodes of size max_num_nodes.
|
||||
* Put the length of the data processed in processed_data_len.
|
||||
* tcp_enabled sets if TCP nodes are expected (true) or not (false).
|
||||
*
|
||||
* return number of unpacked nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data,
|
||||
uint16_t length, uint8_t tcp_enabled);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
/* struct to store some shared keys so we don't have to regenerate them for each request. */
|
||||
|
@ -155,8 +172,15 @@ typedef struct {
|
|||
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
|
||||
typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data,
|
||||
uint32_t len);
|
||||
|
||||
typedef struct {
|
||||
cryptopacket_handler_callback function;
|
||||
void *object;
|
||||
} Cryptopacket_Handles;
|
||||
|
||||
typedef struct {
|
||||
Net_Crypto *c;
|
||||
Networking_Core *net;
|
||||
|
||||
Client_data close_clientlist[LCLIENT_LIST];
|
||||
|
@ -164,7 +188,7 @@ typedef struct {
|
|||
uint32_t close_bootstrap_times;
|
||||
|
||||
/* Note: this key should not be/is not used to transmit any sensitive materials */
|
||||
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
|
||||
uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
|
||||
/* DHT keypair */
|
||||
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
|
@ -180,6 +204,8 @@ typedef struct {
|
|||
struct Assoc *assoc;
|
||||
#endif
|
||||
uint64_t last_run;
|
||||
|
||||
Cryptopacket_Handles cryptopackethandlers[256];
|
||||
} DHT;
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -191,12 +217,12 @@ typedef struct {
|
|||
*/
|
||||
void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id);
|
||||
|
||||
/* Copy shared_key to decrypt DHT packet from client_id into shared_key
|
||||
* for packets that we recieve.
|
||||
/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key
|
||||
* for packets that we receive.
|
||||
*/
|
||||
void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id);
|
||||
|
||||
/* Copy shared_key to decrypt DHT packet from client_id into shared_key
|
||||
/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key
|
||||
* for packets that we send.
|
||||
*/
|
||||
void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id);
|
||||
|
@ -251,7 +277,7 @@ int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2);
|
|||
/* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know
|
||||
* and put them in nodes_list (must be MAX_SENT_NODES big).
|
||||
*
|
||||
* sa_family = family (IPv4 or IPv6)?
|
||||
* sa_family = family (IPv4 or IPv6) (0 if we don't care)?
|
||||
* is_LAN = return some LAN ips (true or false)
|
||||
* want_good = do we want tested nodes or not? (TODO)
|
||||
*
|
||||
|
@ -315,6 +341,10 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
|
|||
*/
|
||||
int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length);
|
||||
|
||||
/* Function to handle crypto packets.
|
||||
*/
|
||||
void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object);
|
||||
|
||||
/* NAT PUNCHING FUNCTIONS */
|
||||
|
||||
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist.
|
||||
|
@ -341,7 +371,7 @@ void DHT_save(DHT *dht, uint8_t *data);
|
|||
int DHT_load(DHT *dht, uint8_t *data, uint32_t length);
|
||||
|
||||
/* Initialize DHT. */
|
||||
DHT *new_DHT(Net_Crypto *c);
|
||||
DHT *new_DHT(Networking_Core *net);
|
||||
|
||||
void kill_DHT(DHT *dht);
|
||||
|
||||
|
|
|
@ -78,8 +78,10 @@ static void fetch_broadcast_info(uint16_t port)
|
|||
|
||||
struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
|
||||
|
||||
if (broadcast_count >= MAX_INTERFACES)
|
||||
if (broadcast_count >= MAX_INTERFACES) {
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
IP_Port *ip_port = &broadcast_ip_port[broadcast_count];
|
||||
ip_port->ip.family = AF_INET;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,261 +0,0 @@
|
|||
/* Lossless_UDP.h
|
||||
*
|
||||
* An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP
|
||||
*
|
||||
* Copyright (C) 2013 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOSSLESS_UDP_H
|
||||
#define LOSSLESS_UDP_H
|
||||
|
||||
#include "network.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
|
||||
/* Maximum length of the data in the data packets. */
|
||||
#define MAX_DATA_SIZE 1024
|
||||
|
||||
/* Maximum data packets in sent and receive queues. */
|
||||
#define MAX_QUEUE_NUM 1024
|
||||
#define DEFAULT_QUEUE_NUM 4
|
||||
|
||||
/* Maximum number of data packets in the buffer. */
|
||||
#define MAX_REQUESTED_PACKETS 256
|
||||
|
||||
/* Timeout per connection is randomly set between CONNECTION_TIMEOUT and 2*CONNECTION_TIMEOUT. */
|
||||
#define CONNECTION_TIMEOUT 5
|
||||
|
||||
/* Initial amount of sync/handshake packets to send per second. */
|
||||
#define SYNC_RATE 2
|
||||
|
||||
/* Initial send rate of data. */
|
||||
#define DATA_SYNC_RATE 30
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[MAX_DATA_SIZE];
|
||||
uint16_t size;
|
||||
} Data;
|
||||
|
||||
#define LUDP_NO_CONNECTION 0
|
||||
#define LUDP_HANDSHAKE_SENDING 1
|
||||
#define LUDP_NOT_CONFIRMED 2
|
||||
#define LUDP_ESTABLISHED 3
|
||||
#define LUDP_TIMED_OUT 4
|
||||
|
||||
typedef struct {
|
||||
IP_Port ip_port;
|
||||
|
||||
/*
|
||||
* return LUDP_NO_CONNECTION if connection is dead.
|
||||
* return LUDP_HANDSHAKE_SENDING if attempting handshake.
|
||||
* return LUDP_NOT_CONFIRMED if handshake is done (we start sending SYNC packets).
|
||||
* return LUDP_ESTABLISHED if we are sending SYNC packets and can send data.
|
||||
* return LUDP_TIMED_OUT if the connection has timed out.
|
||||
*/
|
||||
uint8_t status;
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
uint32_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. */
|
||||
|
||||
Data *sendbuffer; /* packet send buffer. */
|
||||
uint32_t sendbuffer_length;
|
||||
Data *recvbuffer; /* packet receive buffer. */
|
||||
uint32_t recvbuffer_length;
|
||||
uint32_t handshake_id1;
|
||||
uint32_t handshake_id2;
|
||||
|
||||
/* Number of data packets received (also used as handshake_id1). */
|
||||
uint32_t recv_packetnum;
|
||||
|
||||
/* Number of packets received by the other peer. */
|
||||
uint32_t orecv_packetnum;
|
||||
|
||||
/* Number of data packets sent. */
|
||||
uint32_t sent_packetnum;
|
||||
|
||||
/* Number of packets sent by the other peer. */
|
||||
uint32_t osent_packetnum;
|
||||
|
||||
/* Number of latest packet written onto the sendbuffer. */
|
||||
uint32_t sendbuff_packetnum;
|
||||
|
||||
/* 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. */
|
||||
uint32_t successful_read;
|
||||
|
||||
/* List of currently requested packet numbers(by the other person). */
|
||||
uint32_t req_packets[MAX_REQUESTED_PACKETS];
|
||||
|
||||
/* Total number of currently requested packets(by the other person). */
|
||||
uint16_t num_req_paquets;
|
||||
|
||||
uint8_t recv_counter;
|
||||
uint8_t send_counter;
|
||||
uint8_t timeout; /* connection timeout in seconds. */
|
||||
|
||||
/* Is the connection confirmed or not? 1 if yes, 0 if no */
|
||||
uint8_t confirmed;
|
||||
} Connection;
|
||||
|
||||
typedef struct {
|
||||
Networking_Core *net;
|
||||
|
||||
tox_array connections;
|
||||
|
||||
/* Table of random numbers used in handshake_id. */
|
||||
/* IPv6 (16) + port (2)*/
|
||||
uint32_t randtable[18][256];
|
||||
} Lossless_UDP;
|
||||
|
||||
/*
|
||||
* 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 .
|
||||
*/
|
||||
int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port);
|
||||
|
||||
/*
|
||||
* return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue.
|
||||
* return -1 if there are no new incoming connections in the list.
|
||||
*/
|
||||
int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets);
|
||||
|
||||
/* return -1 if it could not kill the connection.
|
||||
* return 0 if killed successfully.
|
||||
*/
|
||||
int kill_connection(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/*
|
||||
* timeout connection in seconds seconds.
|
||||
*
|
||||
* return -1 if it can not kill the connection.
|
||||
* return 0 if it will kill it.
|
||||
*/
|
||||
int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds);
|
||||
|
||||
|
||||
/* Check if connection is confirmed.
|
||||
*
|
||||
* returns 1 if yes.
|
||||
* returns 0 if no.
|
||||
*/
|
||||
int connection_confirmed(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/* Confirm an incoming connection.
|
||||
* Also disables the auto kill timeout on incomming connections.
|
||||
*
|
||||
* return 0 on success
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int confirm_connection(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
uint8_t 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.
|
||||
*/
|
||||
int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data);
|
||||
|
||||
/* Like read_packet() but does leaves the queue as is.
|
||||
* return 0 if there is no received data in the buffer.
|
||||
* return length of received packet if successful.
|
||||
*/
|
||||
int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data);
|
||||
|
||||
/* Discard the next packet to be read from the queue
|
||||
* return 0 if success.
|
||||
* return -1 if failure.
|
||||
*/
|
||||
int discard_packet(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
*/
|
||||
uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* return number of packets in the queue waiting to be successfully sent. */
|
||||
uint32_t sendqueue(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/* return number of packets in all queues waiting to be successfully sent. */
|
||||
uint32_t sendqueue_total(Lossless_UDP *ludp);
|
||||
|
||||
/*
|
||||
* return 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 LUDP_NO_CONNECTION if not.
|
||||
* return LUDP_HANDSHAKE_SENDING if attempting handshake.
|
||||
* return LUDP_NOT_CONFIRMED if handshake is done.
|
||||
* return LUDP_ESTABLISHED if fully connected.
|
||||
* return LUDP_TIMED_OUT 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 is the main loop. */
|
||||
void do_lossless_udp(Lossless_UDP *ludp);
|
||||
|
||||
/* This function sets up LosslessUDP packet handling. */
|
||||
Lossless_UDP *new_lossless_udp(Networking_Core *net);
|
||||
|
||||
void kill_lossless_udp(Lossless_UDP *ludp);
|
||||
|
||||
|
||||
#endif
|
|
@ -9,8 +9,10 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \
|
|||
../toxcore/DHT.c \
|
||||
../toxcore/network.h \
|
||||
../toxcore/network.c \
|
||||
../toxcore/Lossless_UDP.h \
|
||||
../toxcore/Lossless_UDP.c \
|
||||
../toxcore/crypto_core.h \
|
||||
../toxcore/crypto_core.c \
|
||||
../toxcore/ping_array.h \
|
||||
../toxcore/ping_array.c \
|
||||
../toxcore/net_crypto.h \
|
||||
../toxcore/net_crypto.c \
|
||||
../toxcore/friend_requests.h \
|
||||
|
@ -52,6 +54,7 @@ libtoxcore_la_LDFLAGS = $(TOXCORE_LT_LDFLAGS) \
|
|||
$(EXTRA_LT_LDFLAGS) \
|
||||
$(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
$(RT_LIBS) \
|
||||
$(WINSOCK2_LIBS)
|
||||
|
||||
libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,18 +34,20 @@
|
|||
#include "onion_client.h"
|
||||
|
||||
#define MAX_NAME_LENGTH 128
|
||||
/* TODO: this must depend on other variable. */
|
||||
#define MAX_STATUSMESSAGE_LENGTH 1007
|
||||
|
||||
#define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t))
|
||||
|
||||
#define PACKET_ID_PING 0
|
||||
/* NOTE: Packet ids below 16 must never be used. */
|
||||
#define PACKET_ID_ALIVE 16
|
||||
#define PACKET_ID_NICKNAME 48
|
||||
#define PACKET_ID_STATUSMESSAGE 49
|
||||
#define PACKET_ID_USERSTATUS 50
|
||||
#define PACKET_ID_TYPING 51
|
||||
#define PACKET_ID_RECEIPT 65
|
||||
#define PACKET_ID_RECEIPT 63
|
||||
#define PACKET_ID_MESSAGE 64
|
||||
#define PACKET_ID_ACTION 63
|
||||
#define PACKET_ID_ACTION 65
|
||||
#define PACKET_ID_MSI 69
|
||||
#define PACKET_ID_FILE_SENDREQUEST 80
|
||||
#define PACKET_ID_FILE_CONTROL 81
|
||||
|
@ -80,17 +82,13 @@ enum {
|
|||
FAERR_NOMEM = -8
|
||||
};
|
||||
|
||||
/* 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. */
|
||||
#define FRIENDREQUEST_TIMEOUT 5;
|
||||
|
||||
/* 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 received from friend in this time interval, kill the connection. */
|
||||
#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 2)
|
||||
|
||||
/* USERSTATUS -
|
||||
|
@ -137,7 +135,7 @@ typedef struct {
|
|||
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 info[MAX_FRIEND_REQUEST_DATA_SIZE]; // the data that is sent during the friend requests we do.
|
||||
uint8_t name[MAX_NAME_LENGTH];
|
||||
uint16_t name_length;
|
||||
uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have.
|
||||
|
@ -354,7 +352,7 @@ int setname(Messenger *m, uint8_t *name, uint16_t length);
|
|||
|
||||
/*
|
||||
* Get your nickname.
|
||||
* m - The messanger context to use.
|
||||
* m - The messenger context to use.
|
||||
* name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
|
||||
*
|
||||
* return length of the name.
|
||||
|
@ -376,11 +374,6 @@ int getname(Messenger *m, int32_t friendnumber, uint8_t *name);
|
|||
int m_get_name_size(Messenger *m, int32_t friendnumber);
|
||||
int m_get_self_name_size(Messenger *m);
|
||||
|
||||
/* returns valid ip port of connected friend on success
|
||||
* returns zeroed out IP_Port on failure
|
||||
*/
|
||||
IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber);
|
||||
|
||||
/* Set our user status.
|
||||
* You are responsible for freeing status after.
|
||||
*
|
||||
|
@ -739,24 +732,6 @@ void messenger_save(Messenger *m, uint8_t *data);
|
|||
/* Load the messenger from data of size length. */
|
||||
int messenger_load(Messenger *m, uint8_t *data, uint32_t length);
|
||||
|
||||
/* return the size of data to pass to messenger_save_encrypted(...)
|
||||
*/
|
||||
uint32_t messenger_size_encrypted(Messenger *m);
|
||||
|
||||
/* Save the messenger, encrypting the data with key of length key_length
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int messenger_save_encrypted(Messenger *m, uint8_t *data, uint8_t *key, uint16_t key_length);
|
||||
|
||||
/* Load the messenger from data of size length encrypted with key of key_length.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length);
|
||||
|
||||
/* Return the number of friends in the instance m.
|
||||
* You should use this to determine how much memory to allocate
|
||||
* for copy_friendlist. */
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "TCP_client.h"
|
||||
|
||||
|
@ -71,8 +74,8 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_pub
|
|||
memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(TCP_conn->last_packet, self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES);
|
||||
int len = encrypt_data_fast(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain,
|
||||
sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
|
||||
int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain,
|
||||
sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
|
||||
|
||||
if (len != sizeof(plain) + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
@ -90,8 +93,8 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_pub
|
|||
static int handle_handshake(TCP_Client_Connection *TCP_conn, uint8_t *data)
|
||||
{
|
||||
uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES];
|
||||
int len = decrypt_data_fast(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES,
|
||||
TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain);
|
||||
int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES,
|
||||
TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain);
|
||||
|
||||
if (len != sizeof(plain))
|
||||
return -1;
|
||||
|
@ -130,6 +133,206 @@ static int send_pending_data(TCP_Client_Connection *con)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE)
|
||||
return -1;
|
||||
|
||||
if (send_pending_data(con) == -1)
|
||||
return 0;
|
||||
|
||||
uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES];
|
||||
|
||||
uint16_t c_length = htons(length + crypto_box_MACBYTES);
|
||||
memcpy(packet, &c_length, sizeof(uint16_t));
|
||||
int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
|
||||
|
||||
if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t)))
|
||||
return -1;
|
||||
|
||||
increment_nonce(con->sent_nonce);
|
||||
|
||||
len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
|
||||
if ((unsigned int)len == sizeof(packet))
|
||||
return 1;
|
||||
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
memcpy(con->last_packet, packet, length);
|
||||
con->last_packet_length = sizeof(packet);
|
||||
con->last_packet_sent = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key)
|
||||
{
|
||||
uint8_t packet[1 + crypto_box_PUBLICKEYBYTES];
|
||||
packet[0] = TCP_PACKET_ROUTING_REQUEST;
|
||||
memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
|
||||
return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
|
||||
uint8_t *public_key), void *object)
|
||||
{
|
||||
con->response_callback = response_callback;
|
||||
con->response_callback_object = object;
|
||||
}
|
||||
|
||||
void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number,
|
||||
uint8_t connection_id, uint8_t status), void *object)
|
||||
{
|
||||
con->status_callback = status_callback;
|
||||
con->status_callback_object = object;
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (con_id >= NUM_CLIENT_CONNECTIONS)
|
||||
return -1;
|
||||
|
||||
if (con->connections[con_id].status != 2)
|
||||
return -1;
|
||||
|
||||
uint8_t packet[1 + length];
|
||||
packet[0] = con_id + NUM_RESERVED_PORTS;
|
||||
memcpy(packet + 1, data, length);
|
||||
return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH)
|
||||
return -1;
|
||||
|
||||
uint8_t packet[1 + crypto_box_PUBLICKEYBYTES + length];
|
||||
packet[0] = TCP_PACKET_OOB_SEND;
|
||||
memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length);
|
||||
return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
|
||||
/* Set the number that will be used as an argument in the callbacks related to con_id.
|
||||
*
|
||||
* When not set by this function, the number is ~0.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number)
|
||||
{
|
||||
if (con_id >= NUM_CLIENT_CONNECTIONS)
|
||||
return -1;
|
||||
|
||||
if (con->connections[con_id].status == 0)
|
||||
return -1;
|
||||
|
||||
con->connections[con_id].number = number;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
|
||||
uint8_t connection_id, uint8_t *data, uint16_t length), void *object)
|
||||
{
|
||||
con->data_callback = data_callback;
|
||||
con->data_callback_object = object;
|
||||
}
|
||||
|
||||
void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key,
|
||||
uint8_t *data, uint16_t length), void *object)
|
||||
{
|
||||
con->oob_data_callback = oob_data_callback;
|
||||
con->oob_data_callback_object = object;
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id)
|
||||
{
|
||||
uint8_t packet[1 + 1];
|
||||
packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;
|
||||
packet[1] = id;
|
||||
return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
static int send_ping_request(TCP_Client_Connection *con, uint64_t ping_id)
|
||||
{
|
||||
uint8_t packet[1 + sizeof(uint64_t)];
|
||||
packet[0] = TCP_PACKET_PING;
|
||||
memcpy(packet + 1, &ping_id, sizeof(uint64_t));
|
||||
return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id)
|
||||
{
|
||||
uint8_t packet[1 + sizeof(uint64_t)];
|
||||
packet[0] = TCP_PACKET_PONG;
|
||||
memcpy(packet + 1, &ping_id, sizeof(uint64_t));
|
||||
return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id)
|
||||
{
|
||||
if (con_id >= NUM_CLIENT_CONNECTIONS)
|
||||
return -1;
|
||||
|
||||
con->connections[con_id].status = 0;
|
||||
con->connections[con_id].number = 0;
|
||||
return send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS);
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length)
|
||||
{
|
||||
uint8_t packet[1 + length];
|
||||
packet[0] = TCP_PACKET_ONION_REQUEST;
|
||||
memcpy(packet + 1, data, length);
|
||||
return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, uint8_t *data,
|
||||
uint16_t length), void *object)
|
||||
{
|
||||
con->onion_callback = onion_callback;
|
||||
con->onion_callback_object = object;
|
||||
}
|
||||
|
||||
/* Create new TCP connection to ip_port/public_key
|
||||
*/
|
||||
TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key,
|
||||
|
@ -149,6 +352,11 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!set_socket_nosigpipe(sock)) {
|
||||
kill_sock(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port))) {
|
||||
kill_sock(sock);
|
||||
return NULL;
|
||||
|
@ -164,6 +372,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key,
|
|||
temp->status = TCP_CLIENT_CONNECTING;
|
||||
temp->sock = sock;
|
||||
memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES);
|
||||
temp->ip_port = ip_port;
|
||||
|
||||
if (generate_handshake(temp, self_public_key, self_secret_key) == -1) {
|
||||
kill_sock(sock);
|
||||
|
@ -176,8 +385,181 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key,
|
|||
return temp;
|
||||
}
|
||||
|
||||
static int do_confirmed_TCP(TCP_Client_Connection *TCP_connection)
|
||||
/* return 0 on success
|
||||
* return -1 on failure
|
||||
*/
|
||||
static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length <= 1)
|
||||
return -1;
|
||||
|
||||
switch (data[0]) {
|
||||
case TCP_PACKET_ROUTING_RESPONSE: {
|
||||
if (length != 1 + 1 + crypto_box_PUBLICKEYBYTES)
|
||||
return -1;
|
||||
|
||||
if (data[1] < NUM_RESERVED_PORTS)
|
||||
return 0;
|
||||
|
||||
uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
|
||||
|
||||
if (conn->connections[con_id].status != 0)
|
||||
return 0;
|
||||
|
||||
conn->connections[con_id].status = 1;
|
||||
conn->connections[con_id].number = ~0;
|
||||
memcpy(conn->connections[con_id].public_key, data + 2, crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if (conn->response_callback)
|
||||
conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TCP_PACKET_CONNECTION_NOTIFICATION: {
|
||||
if (length != 1 + 1)
|
||||
return -1;
|
||||
|
||||
if (data[1] < NUM_RESERVED_PORTS)
|
||||
return -1;
|
||||
|
||||
uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
|
||||
|
||||
if (conn->connections[con_id].status != 1)
|
||||
return -1;
|
||||
|
||||
conn->connections[con_id].status = 2;
|
||||
|
||||
if (conn->status_callback)
|
||||
conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
|
||||
conn->connections[con_id].status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TCP_PACKET_DISCONNECT_NOTIFICATION: {
|
||||
if (length != 1 + 1)
|
||||
return -1;
|
||||
|
||||
if (data[1] < NUM_RESERVED_PORTS)
|
||||
return -1;
|
||||
|
||||
uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
|
||||
|
||||
if (conn->connections[con_id].status == 0)
|
||||
return 0;
|
||||
|
||||
if (conn->connections[con_id].status != 2)
|
||||
return -1;
|
||||
|
||||
conn->connections[con_id].status = 1;
|
||||
|
||||
if (conn->status_callback)
|
||||
conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
|
||||
conn->connections[con_id].status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TCP_PACKET_PING: {
|
||||
if (length != 1 + sizeof(uint64_t))
|
||||
return -1;
|
||||
|
||||
uint64_t ping_id;
|
||||
memcpy(&ping_id, data + 1, sizeof(uint64_t));
|
||||
send_ping_response(conn, ping_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TCP_PACKET_PONG: {
|
||||
if (length != 1 + sizeof(uint64_t))
|
||||
return -1;
|
||||
|
||||
uint64_t ping_id;
|
||||
memcpy(&ping_id, data + 1, sizeof(uint64_t));
|
||||
|
||||
if (ping_id) {
|
||||
if (ping_id == conn->ping_id) {
|
||||
conn->ping_id = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
case TCP_PACKET_OOB_RECV: {
|
||||
if (length <= 1 + crypto_box_PUBLICKEYBYTES)
|
||||
return -1;
|
||||
|
||||
if (conn->oob_data_callback)
|
||||
conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_PUBLICKEYBYTES));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TCP_PACKET_ONION_RESPONSE: {
|
||||
conn->onion_callback(conn->onion_callback_object, data + 1, length - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (data[0] < NUM_RESERVED_PORTS)
|
||||
return -1;
|
||||
|
||||
uint8_t con_id = data[0] - NUM_RESERVED_PORTS;
|
||||
|
||||
if (conn->data_callback)
|
||||
conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_confirmed_TCP(TCP_Client_Connection *conn)
|
||||
{
|
||||
send_pending_data(conn);
|
||||
uint8_t packet[MAX_PACKET_SIZE];
|
||||
int len;
|
||||
|
||||
if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
|
||||
uint64_t ping_id = random_64b();
|
||||
|
||||
if (!ping_id)
|
||||
++ping_id;
|
||||
|
||||
int ret = send_ping_request(conn, ping_id);
|
||||
|
||||
if (ret == 1) {
|
||||
conn->last_pinged = unix_time();
|
||||
conn->ping_id = ping_id;
|
||||
} else {
|
||||
if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) {
|
||||
conn->status = TCP_CLIENT_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
|
||||
conn->status = TCP_CLIENT_DISCONNECTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
|
||||
conn->recv_nonce, packet, sizeof(packet)))) {
|
||||
if (len == -1) {
|
||||
conn->status = TCP_CLIENT_DISCONNECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (handle_TCP_packet(conn, packet, len) == -1) {
|
||||
conn->status = TCP_CLIENT_DISCONNECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -204,6 +586,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
|
|||
|
||||
if (sizeof(data) == len) {
|
||||
if (handle_handshake(TCP_connection, data) == 0) {
|
||||
TCP_connection->kill_at = ~0;
|
||||
TCP_connection->status = TCP_CLIENT_CONFIRMED;
|
||||
} else {
|
||||
TCP_connection->kill_at = 0;
|
||||
|
@ -225,7 +608,10 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
|
|||
*/
|
||||
void kill_TCP_connection(TCP_Client_Connection *TCP_connection)
|
||||
{
|
||||
if (TCP_connection == NULL)
|
||||
return;
|
||||
|
||||
kill_sock(TCP_connection->sock);
|
||||
memset(TCP_connection, 0, sizeof(TCP_Client_Connection));
|
||||
free(TCP_connection);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef TCP_CLIENT_H
|
||||
#define TCP_CLIENT_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
#include "crypto_core.h"
|
||||
#include "TCP_server.h"
|
||||
|
||||
#define TCP_CONNECTION_TIMEOUT 10
|
||||
|
@ -40,6 +40,7 @@ typedef struct {
|
|||
uint8_t status;
|
||||
sock_t sock;
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* public key of the server */
|
||||
IP_Port ip_port; /* The ip and port of the server */
|
||||
uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
|
||||
uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
|
@ -55,6 +56,25 @@ typedef struct {
|
|||
|
||||
uint64_t last_pinged;
|
||||
uint64_t ping_id;
|
||||
|
||||
void *net_crypto_pointer;
|
||||
uint32_t net_crypto_location;
|
||||
struct {
|
||||
uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint32_t number;
|
||||
} connections[NUM_CLIENT_CONNECTIONS];
|
||||
int (*response_callback)(void *object, uint8_t connection_id, uint8_t *public_key);
|
||||
void *response_callback_object;
|
||||
int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status);
|
||||
void *status_callback_object;
|
||||
int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length);
|
||||
void *data_callback_object;
|
||||
int (*oob_data_callback)(void *object, uint8_t *public_key, uint8_t *data, uint16_t length);
|
||||
void *oob_data_callback_object;
|
||||
|
||||
int (*onion_callback)(void *object, uint8_t *data, uint16_t length);
|
||||
void *onion_callback_object;
|
||||
} TCP_Client_Connection;
|
||||
|
||||
/* Create new TCP connection to ip_port/public_key
|
||||
|
@ -70,9 +90,54 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection);
|
|||
*/
|
||||
void kill_TCP_connection(TCP_Client_Connection *TCP_connection);
|
||||
|
||||
int get_TCP_connection_status(TCP_Client_Connection *TCP_connection);
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length);
|
||||
void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, uint8_t *data,
|
||||
uint16_t length), void *object);
|
||||
|
||||
int read_TCP_connection(TCP_Client_Connection *TCP_connection, uint8_t *data);
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key);
|
||||
void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
|
||||
uint8_t *public_key), void *object);
|
||||
void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number,
|
||||
uint8_t connection_id, uint8_t status), void *object);
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id);
|
||||
|
||||
/* Set the number that will be used as an argument in the callbacks related to con_id.
|
||||
*
|
||||
* When not set by this function, the number is ~0.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number);
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_t length);
|
||||
void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
|
||||
uint8_t connection_id, uint8_t *data, uint16_t length), void *object);
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if could not send packet.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length);
|
||||
void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key,
|
||||
uint8_t *data, uint16_t length), void *object);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "TCP_server.h"
|
||||
|
||||
#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
|
||||
|
@ -69,17 +73,46 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (num == TCP_server->size_accepted_connections) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TCP_Secure_Connection *new_connections = realloc(TCP_server->accepted_connection_array,
|
||||
num * sizeof(TCP_Secure_Connection));
|
||||
|
||||
if (new_connections == NULL)
|
||||
return -1;
|
||||
|
||||
if (num > TCP_server->size_accepted_connections) {
|
||||
uint32_t old_size = TCP_server->size_accepted_connections;
|
||||
uint32_t size_new_entries = (num - old_size) * sizeof(TCP_Secure_Connection);
|
||||
memset(new_connections + old_size, 0, size_new_entries);
|
||||
}
|
||||
|
||||
TCP_server->accepted_connection_array = new_connections;
|
||||
TCP_server->size_accepted_connections = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return index corresponding to connection with peer on success
|
||||
* return -1 on failure.
|
||||
*/
|
||||
static int get_TCP_connection_index(TCP_Server *TCP_server, uint8_t *public_key)
|
||||
{
|
||||
//TODO optimize this function.
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < TCP_server->size_accepted_connections; ++i) {
|
||||
if (memcmp(TCP_server->accepted_connection_array[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int kill_accepted(TCP_Server *TCP_server, int index);
|
||||
|
||||
/* Add accepted TCP connection to the list.
|
||||
*
|
||||
* return index on success
|
||||
|
@ -87,7 +120,12 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num)
|
|||
*/
|
||||
static int add_accepted(TCP_Server *TCP_server, TCP_Secure_Connection *con)
|
||||
{
|
||||
int index = -1;
|
||||
int index = get_TCP_connection_index(TCP_server, con->public_key);
|
||||
|
||||
if (index != -1) { /* If an old connection to the same public key exists, kill it. */
|
||||
kill_accepted(TCP_server, index);
|
||||
index = -1;
|
||||
}
|
||||
|
||||
if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) {
|
||||
if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1)
|
||||
|
@ -141,22 +179,6 @@ static int del_accepted(TCP_Server *TCP_server, int index)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* return index corresponding to connection with peer on success
|
||||
* return -1 on failure.
|
||||
*/
|
||||
static int get_TCP_connection_index(TCP_Server *TCP_server, uint8_t *public_key)
|
||||
{
|
||||
//TODO optimize this function.
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < TCP_server->size_accepted_connections; ++i) {
|
||||
if (memcmp(TCP_server->accepted_connection_array[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the next two bytes in TCP stream then convert them to
|
||||
* length (host byte order).
|
||||
*
|
||||
|
@ -224,14 +246,15 @@ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* return length of recieved packet on success.
|
||||
/* return length of received packet on success.
|
||||
* return 0 if could not read any packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t max_len)
|
||||
int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key,
|
||||
uint8_t *recv_nonce, uint8_t *data, uint16_t max_len)
|
||||
{
|
||||
if (con->next_packet_length == 0) {
|
||||
uint16_t len = read_TCP_length(con->sock);
|
||||
if (*next_packet_length == 0) {
|
||||
uint16_t len = read_TCP_length(sock);
|
||||
|
||||
if (len == (uint16_t)~0)
|
||||
return -1;
|
||||
|
@ -239,26 +262,26 @@ static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t
|
|||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
con->next_packet_length = len;
|
||||
*next_packet_length = len;
|
||||
}
|
||||
|
||||
if (max_len + crypto_box_MACBYTES < con->next_packet_length)
|
||||
if (max_len + crypto_box_MACBYTES < *next_packet_length)
|
||||
return -1;
|
||||
|
||||
uint8_t data_encrypted[con->next_packet_length];
|
||||
int len_packet = read_TCP_packet(con->sock, data_encrypted, con->next_packet_length);
|
||||
uint8_t data_encrypted[*next_packet_length];
|
||||
int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length);
|
||||
|
||||
if (len_packet != con->next_packet_length)
|
||||
if (len_packet != *next_packet_length)
|
||||
return 0;
|
||||
|
||||
con->next_packet_length = 0;
|
||||
*next_packet_length = 0;
|
||||
|
||||
int len = decrypt_data_fast(con->shared_key, con->recv_nonce, data_encrypted, len_packet, data);
|
||||
int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data);
|
||||
|
||||
if (len + crypto_box_MACBYTES != len_packet)
|
||||
return -1;
|
||||
|
||||
increment_nonce(con->recv_nonce);
|
||||
increment_nonce(recv_nonce);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -308,7 +331,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_
|
|||
|
||||
uint16_t c_length = htons(length + crypto_box_MACBYTES);
|
||||
memcpy(packet, &c_length, sizeof(uint16_t));
|
||||
int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
|
||||
int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
|
||||
|
||||
if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t)))
|
||||
return -1;
|
||||
|
@ -337,6 +360,33 @@ static void kill_TCP_connection(TCP_Secure_Connection *con)
|
|||
memset(con, 0, sizeof(TCP_Secure_Connection));
|
||||
}
|
||||
|
||||
static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number);
|
||||
|
||||
/* Kill an accepted TCP_Secure_Connection
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
static int kill_accepted(TCP_Server *TCP_server, int index)
|
||||
{
|
||||
if ((uint32_t)index >= TCP_server->size_accepted_connections)
|
||||
return -1;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
|
||||
rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i);
|
||||
}
|
||||
|
||||
sock_t sock = TCP_server->accepted_connection_array[index].sock;
|
||||
|
||||
if (del_accepted(TCP_server, index) != 0)
|
||||
return -1;
|
||||
|
||||
kill_sock(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return 1 if everything went well.
|
||||
* return -1 if the connection must be killed.
|
||||
*/
|
||||
|
@ -351,8 +401,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1
|
|||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
encrypt_precompute(data, self_secret_key, shared_key);
|
||||
uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
|
||||
int len = decrypt_data_fast(shared_key, data + crypto_box_PUBLICKEYBYTES,
|
||||
data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain);
|
||||
int len = decrypt_data_symmetric(shared_key, data + crypto_box_PUBLICKEYBYTES,
|
||||
data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain);
|
||||
|
||||
if (len != TCP_HANDSHAKE_PLAIN_SIZE)
|
||||
return -1;
|
||||
|
@ -368,7 +418,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1
|
|||
uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
|
||||
new_nonce(response);
|
||||
|
||||
len = encrypt_data_fast(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, response + crypto_box_NONCEBYTES);
|
||||
len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
|
||||
response + crypto_box_NONCEBYTES);
|
||||
|
||||
if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
@ -449,9 +500,16 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, uint8
|
|||
}
|
||||
|
||||
for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
|
||||
if (con->connections[i].status == 0) {
|
||||
if (con->connections[i].status != 0) {
|
||||
if (memcmp(public_key, con->connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (index == (uint32_t)~0) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,7 +560,37 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, uint8
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number)
|
||||
/* return 0 on success.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, uint8_t *public_key, uint8_t *data,
|
||||
uint16_t length)
|
||||
{
|
||||
if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH)
|
||||
return -1;
|
||||
|
||||
TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
|
||||
|
||||
int other_index = get_TCP_connection_index(TCP_server, public_key);
|
||||
|
||||
if (other_index != -1) {
|
||||
uint8_t resp_packet[1 + crypto_box_PUBLICKEYBYTES + length];
|
||||
resp_packet[0] = TCP_PACKET_OOB_RECV;
|
||||
memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length);
|
||||
write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet,
|
||||
sizeof(resp_packet));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove connection with con_number from the connections array of con.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number)
|
||||
{
|
||||
if (con_number >= NUM_CLIENT_CONNECTIONS)
|
||||
return -1;
|
||||
|
@ -526,8 +614,6 @@ static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connect
|
|||
con->connections[con_number].index = 0;
|
||||
con->connections[con_number].other_id = 0;
|
||||
con->connections[con_number].status = 0;
|
||||
//TODO: return values?
|
||||
send_disconnect_notification(con, con_number);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
|
@ -586,7 +672,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d
|
|||
if (length != 2)
|
||||
return -1;
|
||||
|
||||
return disconnect_conection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS);
|
||||
return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS);
|
||||
}
|
||||
|
||||
case TCP_PACKET_PING: {
|
||||
|
@ -618,6 +704,14 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d
|
|||
}
|
||||
}
|
||||
|
||||
case TCP_PACKET_OOB_SEND: {
|
||||
if (length <= 1 + crypto_box_PUBLICKEYBYTES)
|
||||
return -1;
|
||||
|
||||
return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_PUBLICKEYBYTES));
|
||||
}
|
||||
|
||||
case TCP_PACKET_ONION_REQUEST: {
|
||||
if (TCP_server->onion) {
|
||||
if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2)
|
||||
|
@ -642,22 +736,22 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d
|
|||
if (data[0] < NUM_RESERVED_PORTS)
|
||||
return -1;
|
||||
|
||||
uint8_t con_id = data[0] - NUM_RESERVED_PORTS;
|
||||
uint8_t c_id = data[0] - NUM_RESERVED_PORTS;
|
||||
|
||||
if (con_id >= NUM_CLIENT_CONNECTIONS)
|
||||
if (c_id >= NUM_CLIENT_CONNECTIONS)
|
||||
return -1;
|
||||
|
||||
if (con->connections[con_id].status == 0)
|
||||
if (con->connections[c_id].status == 0)
|
||||
return -1;
|
||||
|
||||
if (con->connections[con_id].status != 2)
|
||||
if (con->connections[c_id].status != 2)
|
||||
return 0;
|
||||
|
||||
uint32_t index = con->connections[con_id].index;
|
||||
uint8_t other_con_id = con->connections[con_id].other_id + NUM_RESERVED_PORTS;
|
||||
uint32_t index = con->connections[c_id].index;
|
||||
uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS;
|
||||
uint8_t new_data[length];
|
||||
memcpy(new_data, data, length);
|
||||
new_data[0] = other_con_id;
|
||||
new_data[0] = other_c_id;
|
||||
int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length);
|
||||
|
||||
if (ret == -1)
|
||||
|
@ -678,11 +772,8 @@ static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection
|
|||
if (index == -1)
|
||||
return -1;
|
||||
|
||||
TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[index];
|
||||
|
||||
if (handle_TCP_packet(TCP_server, index, data, length) == -1) {
|
||||
kill_TCP_connection(conn);
|
||||
del_accepted(TCP_server, index);
|
||||
kill_accepted(TCP_server, index);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -701,6 +792,11 @@ static int accept_connection(TCP_Server *TCP_server, sock_t sock)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!set_socket_nosigpipe(sock)) {
|
||||
kill_sock(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TCP_Secure_Connection *conn =
|
||||
&TCP_server->incomming_connection_queue[TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS];
|
||||
|
||||
|
@ -848,7 +944,8 @@ static void do_TCP_unconfirmed(TCP_Server *TCP_server)
|
|||
continue;
|
||||
|
||||
uint8_t packet[MAX_PACKET_SIZE];
|
||||
int len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet));
|
||||
int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce,
|
||||
packet, sizeof(packet));
|
||||
|
||||
if (len == 0) {
|
||||
continue;
|
||||
|
@ -889,12 +986,16 @@ static void do_TCP_confirmed(TCP_Server *TCP_server)
|
|||
if (ret == 1) {
|
||||
conn->last_pinged = unix_time();
|
||||
conn->ping_id = ping_id;
|
||||
} else {
|
||||
if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) {
|
||||
kill_accepted(TCP_server, i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
|
||||
kill_TCP_connection(conn);
|
||||
del_accepted(TCP_server, i);
|
||||
kill_accepted(TCP_server, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -902,16 +1003,15 @@ static void do_TCP_confirmed(TCP_Server *TCP_server)
|
|||
uint8_t packet[MAX_PACKET_SIZE];
|
||||
int len;
|
||||
|
||||
while ((len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet)))) {
|
||||
while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
|
||||
conn->recv_nonce, packet, sizeof(packet)))) {
|
||||
if (len == -1) {
|
||||
kill_TCP_connection(conn);
|
||||
del_accepted(TCP_server, i);
|
||||
kill_accepted(TCP_server, i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (handle_TCP_packet(TCP_server, i, packet, len) == -1) {
|
||||
kill_TCP_connection(conn);
|
||||
del_accepted(TCP_server, i);
|
||||
kill_accepted(TCP_server, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
#ifndef TCP_SERVER_H
|
||||
#define TCP_SERVER_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
#include "crypto_core.h"
|
||||
#include "onion.h"
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MACH__)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
|||
#define TCP_HANDSHAKE_PLAIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES)
|
||||
#define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES)
|
||||
#define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE)
|
||||
#define TCP_MAX_OOB_DATA_LENGTH 1024
|
||||
|
||||
#define NUM_RESERVED_PORTS 16
|
||||
#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS)
|
||||
|
@ -49,16 +50,16 @@
|
|||
#define TCP_PACKET_DISCONNECT_NOTIFICATION 3
|
||||
#define TCP_PACKET_PING 4
|
||||
#define TCP_PACKET_PONG 5
|
||||
#define TCP_PACKET_OOB_SEND 6
|
||||
#define TCP_PACKET_OOB_RECV 7
|
||||
#define TCP_PACKET_ONION_REQUEST 8
|
||||
#define TCP_PACKET_ONION_RESPONSE 9
|
||||
|
||||
#define ARRAY_ENTRY_SIZE 6
|
||||
|
||||
#define TCP_ONION_FAMILY (AF_INET6 + 1)
|
||||
|
||||
/* frequency to ping connected nodes and timeout in seconds */
|
||||
#define TCP_PING_FREQUENCY 30
|
||||
#define TCP_PING_TIMEOUT 20
|
||||
#define TCP_PING_TIMEOUT 10
|
||||
|
||||
enum {
|
||||
TCP_STATUS_NO_STATUS,
|
||||
|
@ -140,4 +141,12 @@ uint16_t read_TCP_length(sock_t sock);
|
|||
*/
|
||||
int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length);
|
||||
|
||||
/* return length of received packet on success.
|
||||
* return 0 if could not read any packet.
|
||||
* return -1 on failure (connection must be killed).
|
||||
*/
|
||||
int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key,
|
||||
uint8_t *recv_nonce, uint8_t *data, uint16_t max_len);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* Candidates are kept in buckets of hash tables. The hash
|
||||
* function is calculated from the client_id. Up to
|
||||
* HASH_COLLIDE_COUNT alternative positions are tried if
|
||||
* the inital position is already used by a different entry.
|
||||
* the initial position is already used by a different entry.
|
||||
* The collision function is multiplicative, not additive.
|
||||
*
|
||||
* A new candidate can bump an existing candidate, if it is
|
||||
|
|
262
toxcore/crypto_core.c
Normal file
262
toxcore/crypto_core.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
/* net_crypto.c
|
||||
*
|
||||
* Functions for the core crypto.
|
||||
*
|
||||
* NOTE: This code has to be perfect. We don't mess around with encryption.
|
||||
*
|
||||
* Copyright (C) 2013 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "crypto_core.h"
|
||||
|
||||
|
||||
/* Use this instead of memcmp; not vulnerable to timing attacks.
|
||||
returns 0 if both mem locations of length are equal,
|
||||
return -1 if they are not. */
|
||||
int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length)
|
||||
{
|
||||
if (length == 16) {
|
||||
return crypto_verify_16(mem1, mem2);
|
||||
} else if (length == 32) {
|
||||
return crypto_verify_32(mem1, mem2);
|
||||
}
|
||||
|
||||
unsigned int i, check = 0;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
check |= mem1[i] ^ mem2[i];
|
||||
}
|
||||
|
||||
return (1 & ((check - 1) >> 8)) - 1;
|
||||
}
|
||||
|
||||
/* return a random number.
|
||||
*/
|
||||
uint32_t random_int(void)
|
||||
{
|
||||
uint32_t randnum;
|
||||
randombytes((uint8_t *)&randnum , sizeof(randnum));
|
||||
return randnum;
|
||||
}
|
||||
|
||||
uint64_t random_64b(void)
|
||||
{
|
||||
uint64_t randnum;
|
||||
randombytes((uint8_t *)&randnum, sizeof(randnum));
|
||||
return randnum;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key)
|
||||
{
|
||||
crypto_box_beforenm(enc_key, public_key, secret_key);
|
||||
}
|
||||
|
||||
int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted)
|
||||
{
|
||||
if (length == 0)
|
||||
return -1;
|
||||
|
||||
uint8_t temp_plain[length + crypto_box_ZEROBYTES];
|
||||
uint8_t temp_encrypted[length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES];
|
||||
|
||||
memset(temp_plain, 0, crypto_box_ZEROBYTES);
|
||||
memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes.
|
||||
|
||||
if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0)
|
||||
return -1;
|
||||
|
||||
/* Unpad the encrypted message. */
|
||||
memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
|
||||
return length + crypto_box_MACBYTES;
|
||||
}
|
||||
|
||||
int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain)
|
||||
{
|
||||
if (length <= crypto_box_BOXZEROBYTES)
|
||||
return -1;
|
||||
|
||||
uint8_t temp_plain[length + crypto_box_ZEROBYTES];
|
||||
uint8_t temp_encrypted[length + crypto_box_BOXZEROBYTES];
|
||||
|
||||
memset(temp_plain, 0, crypto_box_BOXZEROBYTES);
|
||||
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, secret_key) != 0)
|
||||
return -1;
|
||||
|
||||
memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
|
||||
return length - crypto_box_MACBYTES;
|
||||
}
|
||||
|
||||
int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
|
||||
uint8_t *plain, uint32_t length, uint8_t *encrypted)
|
||||
{
|
||||
uint8_t k[crypto_box_BEFORENMBYTES];
|
||||
encrypt_precompute(public_key, secret_key, k);
|
||||
return encrypt_data_symmetric(k, nonce, plain, length, encrypted);
|
||||
}
|
||||
|
||||
int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
|
||||
uint8_t *encrypted, uint32_t length, uint8_t *plain)
|
||||
{
|
||||
uint8_t k[crypto_box_BEFORENMBYTES];
|
||||
encrypt_precompute(public_key, secret_key, k);
|
||||
return decrypt_data_symmetric(k, nonce, encrypted, length, plain);
|
||||
}
|
||||
|
||||
|
||||
/* Increment the given nonce by 1. */
|
||||
void increment_nonce(uint8_t *nonce)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = crypto_box_NONCEBYTES; i != 0; --i) {
|
||||
++nonce[i - 1];
|
||||
|
||||
if (nonce[i - 1] != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* increment the given nonce by num */
|
||||
void increment_nonce_number(uint8_t *nonce, uint32_t num)
|
||||
{
|
||||
uint32_t num1, num2;
|
||||
memcpy(&num1, nonce + (crypto_box_NONCEBYTES - sizeof(num1)), sizeof(num1));
|
||||
num1 = ntohl(num1);
|
||||
num2 = num + num1;
|
||||
|
||||
if (num2 < num1) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = crypto_box_NONCEBYTES - sizeof(num1); i != 0; --i) {
|
||||
++nonce[i - 1];
|
||||
|
||||
if (nonce[i - 1] != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
num2 = htonl(num2);
|
||||
memcpy(nonce + (crypto_box_NONCEBYTES - sizeof(num2)), &num2, sizeof(num2));
|
||||
}
|
||||
|
||||
/* Fill the given nonce with random bytes. */
|
||||
void random_nonce(uint8_t *nonce)
|
||||
{
|
||||
randombytes(nonce, crypto_box_NONCEBYTES);
|
||||
}
|
||||
|
||||
/* Fill a key crypto_box_KEYBYTES big with random bytes */
|
||||
void new_symmetric_key(uint8_t *key)
|
||||
{
|
||||
randombytes(key, crypto_box_KEYBYTES);
|
||||
}
|
||||
|
||||
static uint8_t base_nonce[crypto_box_NONCEBYTES];
|
||||
static uint8_t nonce_set = 0;
|
||||
|
||||
/* Gives a nonce guaranteed to be different from previous ones.*/
|
||||
void new_nonce(uint8_t *nonce)
|
||||
{
|
||||
if (nonce_set == 0) {
|
||||
random_nonce(base_nonce);
|
||||
nonce_set = 1;
|
||||
}
|
||||
|
||||
increment_nonce(base_nonce);
|
||||
memcpy(nonce, base_nonce, crypto_box_NONCEBYTES);
|
||||
}
|
||||
|
||||
/* 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_CRYPTO_REQUEST_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).
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 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)
|
||||
{
|
||||
if (MAX_CRYPTO_REQUEST_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 +
|
||||
crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
|
||||
memcpy(temp + 1, data, length);
|
||||
temp[0] = request_id;
|
||||
new_nonce(nonce);
|
||||
int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
|
||||
1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet);
|
||||
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
packet[0] = NET_PACKET_CRYPTO;
|
||||
memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES);
|
||||
|
||||
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.
|
||||
*/
|
||||
int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
|
||||
uint8_t *request_id, uint8_t *packet, uint16_t length)
|
||||
{
|
||||
if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES &&
|
||||
length <= MAX_CRYPTO_REQUEST_SIZE) {
|
||||
if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
|
||||
memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
|
||||
int len1 = decrypt_data(public_key, self_secret_key, nonce,
|
||||
packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
|
||||
length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp);
|
||||
|
||||
if (len1 == -1 || len1 == 0)
|
||||
return -1;
|
||||
|
||||
request_id[0] = temp[0];
|
||||
--len1;
|
||||
memcpy(data, temp + 1, len1);
|
||||
return len1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
142
toxcore/crypto_core.h
Normal file
142
toxcore/crypto_core.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* crypto_core.h
|
||||
*
|
||||
* Functions for the core crypto.
|
||||
*
|
||||
* Copyright (C) 2013 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef CORE_CRYPTO_H
|
||||
#define CORE_CRYPTO_H
|
||||
|
||||
#include "network.h"
|
||||
|
||||
#ifndef VANILLA_NACL
|
||||
/* We use libsodium by default. */
|
||||
#include <sodium.h>
|
||||
#else
|
||||
#include <crypto_box.h>
|
||||
#include <randombytes.h>
|
||||
#include <crypto_hash_sha256.h>
|
||||
#include <crypto_hash_sha512.h>
|
||||
#include <crypto_verify_16.h>
|
||||
#include <crypto_verify_32.h>
|
||||
#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
|
||||
#endif
|
||||
|
||||
#define crypto_box_KEYBYTES (crypto_box_BEFORENMBYTES)
|
||||
|
||||
/* Use this instead of memcmp; not vulnerable to timing attacks.
|
||||
returns 0 if both mem locations of length are equal,
|
||||
return -1 if they are not. */
|
||||
int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length);
|
||||
|
||||
/* return a random number.
|
||||
*
|
||||
* random_int for a 32bin int.
|
||||
* random_64b for a 64bit int.
|
||||
*/
|
||||
uint32_t random_int(void);
|
||||
uint64_t random_64b(void);
|
||||
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
|
||||
uint8_t *encrypted, uint32_t length, uint8_t *plain);
|
||||
|
||||
/* Fast encrypt/decrypt operations. Use if this is not a one-time communication.
|
||||
encrypt_precompute does the shared-key generation once so it does not have
|
||||
to be preformed on every encrypt/decrypt. */
|
||||
void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key);
|
||||
|
||||
/* Encrypts plain of length length to encrypted of length + 16 using a
|
||||
* secret key crypto_box_KEYBYTES big and a 24 byte nonce.
|
||||
*
|
||||
* return -1 if there was a problem.
|
||||
* return length of encrypted data if everything was fine.
|
||||
*/
|
||||
int encrypt_data_symmetric(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 a
|
||||
* secret key crypto_box_KEYBYTES big 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_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain);
|
||||
|
||||
/* Increment the given nonce by 1. */
|
||||
void increment_nonce(uint8_t *nonce);
|
||||
|
||||
/* increment the given nonce by num */
|
||||
void increment_nonce_number(uint8_t *nonce, uint32_t num);
|
||||
|
||||
/* Fill the given nonce with random bytes. */
|
||||
void random_nonce(uint8_t *nonce);
|
||||
|
||||
/* Fill a key crypto_box_KEYBYTES big with random bytes */
|
||||
void new_symmetric_key(uint8_t *key);
|
||||
|
||||
/*Gives a nonce guaranteed to be different from previous ones.*/
|
||||
void new_nonce(uint8_t *nonce);
|
||||
|
||||
#define MAX_CRYPTO_REQUEST_SIZE 1024
|
||||
|
||||
#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
|
||||
#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
|
||||
#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */
|
||||
|
||||
/* 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_CRYPTO_REQUEST_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).
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 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);
|
||||
|
||||
/* 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. */
|
||||
int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
|
||||
uint8_t *request_id, uint8_t *packet, uint16_t length);
|
||||
|
||||
|
||||
#endif
|
|
@ -37,10 +37,10 @@
|
|||
*/
|
||||
int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length)
|
||||
{
|
||||
if (length + sizeof(nospam_num) > MAX_DATA_SIZE)
|
||||
if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0)
|
||||
return -1;
|
||||
|
||||
uint8_t temp[MAX_DATA_SIZE];
|
||||
uint8_t temp[1 + sizeof(nospam_num) + length];
|
||||
temp[0] = CRYPTO_PACKET_FRIEND_REQ;
|
||||
memcpy(temp + 1, &nospam_num, sizeof(nospam_num));
|
||||
memcpy(temp + 1 + sizeof(nospam_num), data, length);
|
||||
|
@ -50,7 +50,7 @@ int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nosp
|
|||
if (friend_num == -1)
|
||||
return -1;
|
||||
|
||||
int num = send_onion_data(onion_c, friend_num, temp, 1 + sizeof(nospam_num) + length);
|
||||
int num = send_onion_data(onion_c, friend_num, temp, sizeof(temp));
|
||||
|
||||
if (num <= 0)
|
||||
return -1;
|
||||
|
@ -135,20 +135,17 @@ int remove_request_received(Friend_Requests *fr, uint8_t *client_id)
|
|||
|
||||
static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
Friend_Requests *fr = object;
|
||||
|
||||
if (length <= 1 + sizeof(fr->nospam) || length > ONION_CLIENT_MAX_DATA_SIZE)
|
||||
return 1;
|
||||
|
||||
++packet;
|
||||
--length;
|
||||
|
||||
Friend_Requests *fr = object;
|
||||
|
||||
if (fr->handle_friendrequest_isset == 0)
|
||||
return 1;
|
||||
|
||||
if (length <= sizeof(fr->nospam))
|
||||
return 1;
|
||||
|
||||
if (request_received(fr, source_pubkey))
|
||||
return 1;
|
||||
|
||||
|
@ -161,11 +158,12 @@ static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t
|
|||
|
||||
addto_receivedlist(fr, source_pubkey);
|
||||
|
||||
uint8_t message[length - 4 + 1];
|
||||
memcpy(message, packet + 4, length - 4);
|
||||
uint32_t message_len = length - sizeof(fr->nospam);
|
||||
uint8_t message[message_len + 1];
|
||||
memcpy(message, packet + sizeof(fr->nospam), message_len);
|
||||
message[sizeof(message) - 1] = 0; /* Be sure the message is null terminated. */
|
||||
|
||||
(*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, length - 4,
|
||||
(*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, message_len,
|
||||
fr->handle_friendrequest_userdata);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#define FRIEND_REQUESTS_H
|
||||
|
||||
#include "onion_client.h"
|
||||
#include "net_crypto.h"
|
||||
|
||||
#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t)))
|
||||
|
||||
typedef struct {
|
||||
uint32_t nospam;
|
||||
|
@ -48,7 +48,8 @@ typedef struct {
|
|||
} Friend_Requests;
|
||||
|
||||
/* Try to send a friendrequest to peer with public_key.
|
||||
* data is the data in the request and length is the length.
|
||||
* data is the data in the request and length is the length.
|
||||
* Maximum length of data is MAX_FRIEND_REQUEST_DATA_SIZE.
|
||||
*/
|
||||
int send_friendrequest(Onion_Client *onion_c, 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. */
|
||||
|
|
|
@ -26,12 +26,13 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "group_chats.h"
|
||||
#include "DHT.h"
|
||||
#include "assoc.h"
|
||||
#include "group_chats.h"
|
||||
#include "LAN_discovery.h"
|
||||
#include "util.h"
|
||||
|
||||
#define GROUPCHAT_MAXDATA_LENGTH (MAX_DATA_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES))
|
||||
#define GROUPCHAT_MAXDATA_LENGTH (MAX_CRYPTO_REQUEST_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES))
|
||||
#define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES)
|
||||
|
||||
#define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2)
|
||||
|
@ -180,7 +181,7 @@ static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *publ
|
|||
if (id_equal(chat->self_public_key, public_key))
|
||||
return -1;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
|
||||
int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id);
|
||||
packet[0] = NET_PACKET_GROUP_CHATS;
|
||||
|
||||
|
@ -586,10 +587,10 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
|
|||
|
||||
static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t message_id)
|
||||
{
|
||||
if (len + GROUP_DATA_MIN_SIZE > MAX_DATA_SIZE) /*NOTE: not the real maximum len.*/
|
||||
if (len + GROUP_DATA_MIN_SIZE > MAX_CRYPTO_REQUEST_SIZE) /*NOTE: not the real maximum len.*/
|
||||
return 1;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
|
||||
++chat->message_number;
|
||||
|
||||
if (chat->message_number == 0)
|
||||
|
@ -615,11 +616,11 @@ static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t
|
|||
|
||||
int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
if (length > MAX_DATA_SIZE)
|
||||
if (length > MAX_CRYPTO_REQUEST_SIZE)
|
||||
return 1;
|
||||
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t data[MAX_DATA_SIZE];
|
||||
uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
|
||||
uint8_t number;
|
||||
int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length);
|
||||
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#ifndef GROUP_CHATS_H
|
||||
#define GROUP_CHATS_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
|
||||
#define MAX_NICK_BYTES 128
|
||||
|
||||
typedef struct {
|
||||
|
|
2831
toxcore/net_crypto.c
2831
toxcore/net_crypto.c
File diff suppressed because it is too large
Load Diff
|
@ -24,21 +24,62 @@
|
|||
#ifndef NET_CRYPTO_H
|
||||
#define NET_CRYPTO_H
|
||||
|
||||
#include "Lossless_UDP.h"
|
||||
|
||||
#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
|
||||
#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
|
||||
#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */
|
||||
#define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2)
|
||||
#include "DHT.h"
|
||||
#include "TCP_client.h"
|
||||
|
||||
#define CRYPTO_CONN_NO_CONNECTION 0
|
||||
#define CRYPTO_CONN_HANDSHAKE_SENT 1
|
||||
#define CRYPTO_CONN_NOT_CONFIRMED 2
|
||||
#define CRYPTO_CONN_ESTABLISHED 3
|
||||
#define CRYPTO_CONN_TIMED_OUT 4
|
||||
#define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets
|
||||
#define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets
|
||||
#define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets
|
||||
#define CRYPTO_CONN_ESTABLISHED 4
|
||||
#define CRYPTO_CONN_TIMED_OUT 5
|
||||
|
||||
#define CRYPTO_PACKET_BUFFER_SIZE 16384 /* Must be a power of 2 */
|
||||
|
||||
/* Minimum packet rate per second. */
|
||||
#define CRYPTO_PACKET_MIN_RATE 40.0
|
||||
|
||||
/* Minimum packet queue max length. */
|
||||
#define CRYPTO_MIN_QUEUE_LENGTH 8
|
||||
|
||||
#define MAX_CRYPTO_PACKET_SIZE 1400
|
||||
|
||||
#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + crypto_box_MACBYTES)
|
||||
|
||||
/* Max size of data in packets TODO*/
|
||||
#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
|
||||
|
||||
/* Interval in ms between sending cookie request/handshake packets. */
|
||||
#define CRYPTO_SEND_PACKET_INTERVAL 500
|
||||
/* The maximum number of times we try to send the cookie request and handshake
|
||||
before giving up. */
|
||||
#define MAX_NUM_SENDPACKET_TRIES 8
|
||||
|
||||
#define PACKET_ID_PADDING 0
|
||||
#define PACKET_ID_REQUEST 1
|
||||
#define PACKET_ID_KILL 2
|
||||
|
||||
#define CRYPTO_RESERVED_PACKETS 16
|
||||
|
||||
#define MAX_TCP_CONNECTIONS 32
|
||||
#define MAX_TCP_RELAYS_PEER 4
|
||||
|
||||
#define STATUS_TCP_NULL 0
|
||||
#define STATUS_TCP_OFFLINE 1
|
||||
#define STATUS_TCP_INVISIBLE 2 /* we know the other peer is connected to this relay but he isn't appearing online */
|
||||
#define STATUS_TCP_ONLINE 3
|
||||
|
||||
typedef struct {
|
||||
uint64_t time;
|
||||
uint16_t length;
|
||||
uint8_t data[MAX_CRYPTO_DATA_SIZE];
|
||||
} Packet_Data;
|
||||
|
||||
typedef struct {
|
||||
Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE];
|
||||
uint32_t buffer_start;
|
||||
uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */
|
||||
} Packets_Array;
|
||||
|
||||
typedef struct {
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
|
||||
|
@ -48,27 +89,73 @@ typedef struct {
|
|||
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 status; /* 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.
|
||||
uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets,
|
||||
* 2 if we are sending handshake packets
|
||||
* 3 if connection is not confirmed yet (we have received a handshake but no data packets yet),
|
||||
* 4 if the connection is established.
|
||||
* 5 if the connection is timed out.
|
||||
*/
|
||||
uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */
|
||||
uint64_t timeout;
|
||||
uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
|
||||
uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */
|
||||
uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */
|
||||
uint64_t dht_public_key_timestamp; /* Timestamp of the last time we confirmed the key was correct. */
|
||||
|
||||
uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
|
||||
uint16_t temp_packet_length;
|
||||
uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
|
||||
uint32_t temp_packet_num_sent;
|
||||
|
||||
IP_Port ip_port; /* The ip and port to contact this guy directly.*/
|
||||
uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */
|
||||
|
||||
Packets_Array send_array;
|
||||
Packets_Array recv_array;
|
||||
|
||||
int (*connection_status_callback)(void *object, int id, uint8_t status);
|
||||
void *connection_status_callback_object;
|
||||
int connection_status_callback_id;
|
||||
|
||||
int (*connection_data_callback)(void *object, int id, uint8_t *data, uint16_t length);
|
||||
void *connection_data_callback_object;
|
||||
int connection_data_callback_id;
|
||||
|
||||
uint64_t last_request_packet_sent;
|
||||
|
||||
uint32_t packet_counter;
|
||||
double packet_recv_rate;
|
||||
uint64_t packet_counter_set;
|
||||
|
||||
double packet_send_rate;
|
||||
uint32_t packets_left;
|
||||
uint64_t last_packets_left_set;
|
||||
|
||||
uint8_t sending; /* indicates if data is being sent or not. */
|
||||
|
||||
uint8_t killed; /* set to 1 to kill the connection. */
|
||||
|
||||
uint8_t status_tcp[MAX_TCP_CONNECTIONS]; /* set to one of STATUS_TCP_* */
|
||||
uint8_t con_number_tcp[MAX_TCP_CONNECTIONS];
|
||||
|
||||
Node_format tcp_relays[MAX_TCP_RELAYS_PEER];
|
||||
uint16_t num_tcp_relays;
|
||||
} Crypto_Connection;
|
||||
|
||||
typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data,
|
||||
uint32_t len);
|
||||
typedef struct {
|
||||
IP_Port source;
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
|
||||
uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer. */
|
||||
uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
|
||||
uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
|
||||
uint8_t *cookie;
|
||||
uint8_t cookie_length;
|
||||
} New_Connection;
|
||||
|
||||
typedef struct {
|
||||
cryptopacket_handler_callback function;
|
||||
void *object;
|
||||
} Cryptopacket_Handles;
|
||||
|
||||
typedef struct {
|
||||
Lossless_UDP *lossless_udp;
|
||||
DHT *dht;
|
||||
|
||||
Crypto_Connection *crypto_connections;
|
||||
TCP_Client_Connection *tcp_connections_new[MAX_TCP_CONNECTIONS];
|
||||
TCP_Client_Connection *tcp_connections[MAX_TCP_CONNECTIONS];
|
||||
|
||||
uint32_t crypto_connections_length; /* Length of connections array. */
|
||||
|
||||
|
@ -76,154 +163,131 @@ typedef struct {
|
|||
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
|
||||
Cryptopacket_Handles cryptopackethandlers[256];
|
||||
/* The secret key used for cookies */
|
||||
uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
|
||||
|
||||
int (*new_connection_callback)(void *object, New_Connection *n_c);
|
||||
void *new_connection_callback_object;
|
||||
} Net_Crypto;
|
||||
|
||||
#include "DHT.h"
|
||||
|
||||
/* 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.
|
||||
/* Set function to be called when someone requests a new connection to us.
|
||||
*
|
||||
* 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.
|
||||
* The set function should return -1 on failure and 0 on success.
|
||||
*
|
||||
* return -1 if there was a problem (decryption failed).
|
||||
* return length of plain data if everything was fine.
|
||||
* n_c is only valid for the duration of the function call.
|
||||
*/
|
||||
int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
|
||||
uint8_t *encrypted, uint32_t length, uint8_t *plain);
|
||||
void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
|
||||
void *object);
|
||||
|
||||
/* Fast encrypt/decrypt operations. Use if this is not a one-time communication.
|
||||
encrypt_precompute does the shared-key generation once so it does not have
|
||||
to be preformed on every encrypt/decrypt. */
|
||||
void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key);
|
||||
|
||||
/* Fast encrypt. Depends on enc_key from encrypt_precompute. */
|
||||
int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
|
||||
uint8_t *plain, uint32_t length, uint8_t *encrypted);
|
||||
|
||||
/* Fast decrypt. Depends on enc_ley from encrypt_precompute. */
|
||||
int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
|
||||
uint8_t *encrypted, uint32_t length, uint8_t *plain);
|
||||
|
||||
/* Encrypts plain of length length to encrypted of length + 16 using a
|
||||
* secret key crypto_secretbox_KEYBYTES big and a 24 byte nonce.
|
||||
/* Accept a crypto connection.
|
||||
*
|
||||
* return -1 if there was a problem.
|
||||
* return length of encrypted data if everything was fine.
|
||||
* return -1 on failure.
|
||||
* return connection id on success.
|
||||
*/
|
||||
int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted);
|
||||
int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
|
||||
|
||||
/* Decrypts encrypted of length length to plain of length length - 16 using a
|
||||
* secret key crypto_secretbox_KEYBYTES big and a 24 byte nonce.
|
||||
/* Create a crypto connection.
|
||||
* If one to that real public key already exists, return it.
|
||||
*
|
||||
* return -1 if there was a problem (decryption failed).
|
||||
* return length of plain data if everything was fine.
|
||||
* return -1 on failure.
|
||||
* return connection id on success.
|
||||
*/
|
||||
int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain);
|
||||
int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key);
|
||||
|
||||
/* Increment the given nonce by 1. */
|
||||
void increment_nonce(uint8_t *nonce);
|
||||
|
||||
/* Fill the given nonce with random bytes. */
|
||||
void random_nonce(uint8_t *nonce);
|
||||
|
||||
/* Fill a key crypto_secretbox_KEYBYTES big with random bytes */
|
||||
void new_symmetric_key(uint8_t *key);
|
||||
|
||||
/*Gives a nonce guaranteed to be different from previous ones.*/
|
||||
void new_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.
|
||||
/* Copy friends DHT public key into dht_key.
|
||||
*
|
||||
* return 0 on failure (no key copied).
|
||||
* return timestamp on success (key copied).
|
||||
*/
|
||||
int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data);
|
||||
uint64_t get_connection_dht_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key);
|
||||
|
||||
/* Set the DHT public key of the crypto connection.
|
||||
* timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
|
||||
* the other peer.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key, uint64_t timestamp);
|
||||
|
||||
/* Set the direct ip of the crypto connection.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port);
|
||||
|
||||
/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
|
||||
*
|
||||
* The set function should return -1 on failure and 0 on success.
|
||||
* Note that if this function is set, the connection will clear itself on disconnect.
|
||||
* Object and id will be passed to this function untouched.
|
||||
* status is 1 if the connection is going online, 0 if it is going offline.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object,
|
||||
int id, uint8_t status), void *object, int id);
|
||||
|
||||
/* Set function to be called when connection with crypt_connection_id receives a data packet of length.
|
||||
*
|
||||
* The set function should return -1 on failure and 0 on success.
|
||||
* Object and id will be passed to this function untouched.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
|
||||
int id, uint8_t *data, uint16_t length), void *object, int id);
|
||||
|
||||
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
*/
|
||||
uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id);
|
||||
|
||||
/* return 0 if data could not be put in packet queue.
|
||||
* return 1 if data was put into the queue.
|
||||
/* return -1 if data could not be put in packet queue.
|
||||
* return positive packet number if data was put into the queue.
|
||||
*/
|
||||
int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length);
|
||||
int64_t 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).
|
||||
/* Add a tcp relay, associating it to a crypt_connection_id.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return the length of the created packet on success.
|
||||
* return 0 if it was added.
|
||||
* return -1 if it wasn't.
|
||||
*/
|
||||
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);
|
||||
int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, uint8_t *public_key);
|
||||
|
||||
/* 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. */
|
||||
int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
|
||||
uint8_t *request_id, uint8_t *packet, uint16_t length);
|
||||
|
||||
/* 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.
|
||||
/* Add a tcp relay to the array.
|
||||
*
|
||||
* return -1 if failure.
|
||||
* return crypt_connection_id of the initialized connection if everything went well.
|
||||
* return 0 if it was added.
|
||||
* return -1 if it wasn't.
|
||||
*/
|
||||
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port);
|
||||
int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key);
|
||||
|
||||
/* Copy a maximum of num TCP relays we are connected to to tcp_relays.
|
||||
* NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
|
||||
*
|
||||
* return number of relays copied to tcp_relays on success.
|
||||
* return 0 on failure.
|
||||
*/
|
||||
unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
|
||||
|
||||
/* Kill a crypto connection.
|
||||
*
|
||||
* return 0 if killed successfully.
|
||||
* return 1 if there was a problem.
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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 one of CRYPTO_CONN_* values indicating the state of the connection.
|
||||
*
|
||||
* return -1 if not successful.
|
||||
* return crypt_connection_id if successful.
|
||||
* sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
|
||||
*/
|
||||
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.
|
||||
* 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);
|
||||
unsigned int crypto_connection_status(Net_Crypto *c, int crypt_connection_id, uint8_t *direct_connected);
|
||||
|
||||
|
||||
/* Generate our public and private keys.
|
||||
|
@ -244,15 +308,13 @@ 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.
|
||||
*/
|
||||
Net_Crypto *new_net_crypto(Networking_Core *net);
|
||||
Net_Crypto *new_net_crypto(DHT *dht);
|
||||
|
||||
/* Main loop. */
|
||||
void do_net_crypto(Net_Crypto *c);
|
||||
|
||||
void kill_net_crypto(Net_Crypto *c);
|
||||
|
||||
/* Initialize the cryptopacket handling. */
|
||||
void init_cryptopackets(void *dht);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,13 +29,17 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define LOGGING
|
||||
#include "logger.h"
|
||||
|
||||
#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
#include "network.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -153,6 +157,21 @@ int set_socket_nonblock(sock_t sock)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Set socket to not emit SIGPIPE
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int set_socket_nosigpipe(sock_t sock)
|
||||
{
|
||||
#if defined(__MACH__)
|
||||
int set = 1;
|
||||
return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)) == 0);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set socket to dual (IPv4 + IPv6 socket)
|
||||
*
|
||||
* return 1 on success
|
||||
|
@ -160,7 +179,7 @@ int set_socket_nonblock(sock_t sock)
|
|||
*/
|
||||
int set_socket_dualstack(sock_t sock)
|
||||
{
|
||||
char ipv6only = 0;
|
||||
int ipv6only = 0;
|
||||
socklen_t optsize = sizeof(ipv6only);
|
||||
int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize);
|
||||
|
||||
|
@ -171,8 +190,9 @@ int set_socket_dualstack(sock_t sock)
|
|||
return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0);
|
||||
}
|
||||
|
||||
|
||||
/* return current UNIX time in microseconds (us). */
|
||||
uint64_t current_time(void)
|
||||
static uint64_t current_time_actual(void)
|
||||
{
|
||||
uint64_t time;
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
|
@ -192,29 +212,52 @@ uint64_t current_time(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* return a random number.
|
||||
*/
|
||||
uint32_t random_int(void)
|
||||
{
|
||||
uint32_t randnum;
|
||||
randombytes((uint8_t *)&randnum , sizeof(randnum));
|
||||
return randnum;
|
||||
}
|
||||
|
||||
uint64_t random_64b(void)
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
static uint64_t last_monotime;
|
||||
static uint64_t add_monotime;
|
||||
#endif
|
||||
|
||||
/* return current monotonic time in milliseconds (ms). */
|
||||
uint64_t current_time_monotonic(void)
|
||||
{
|
||||
uint64_t randnum;
|
||||
randombytes((uint8_t *)&randnum, sizeof(randnum));
|
||||
return randnum;
|
||||
uint64_t time;
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
time = (uint64_t)GetTickCount() + add_monotime;
|
||||
|
||||
if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */
|
||||
uint32_t add = ~0;
|
||||
add_monotime += add;
|
||||
time += add;
|
||||
}
|
||||
|
||||
last_monotime = time;
|
||||
#else
|
||||
struct timespec monotime;
|
||||
#if defined(__linux__)
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &monotime);
|
||||
#elif defined(__APPLE__)
|
||||
clock_serv_t muhclock;
|
||||
mach_timespec_t machtime;
|
||||
|
||||
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock);
|
||||
clock_get_time(muhclock, &machtime);
|
||||
mach_port_deallocate(mach_task_self(), muhclock);
|
||||
|
||||
monotime.tv_sec = machtime.tv_sec;
|
||||
monotime.tv_nsec = machtime.tv_nsec;
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &monotime);
|
||||
#endif
|
||||
time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL);
|
||||
#endif
|
||||
return time;
|
||||
}
|
||||
|
||||
/* In case no logging */
|
||||
#ifndef LOGGING
|
||||
|
||||
#define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__)
|
||||
|
||||
#else
|
||||
|
||||
#else
|
||||
#define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0
|
||||
#define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0
|
||||
|
||||
|
@ -299,7 +342,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le
|
|||
if ((res >= 0) && ((uint32_t)res == length))
|
||||
net->send_fail_eagain = 0;
|
||||
else if ((res < 0) && (errno == EWOULDBLOCK))
|
||||
net->send_fail_eagain = current_time();
|
||||
net->send_fail_eagain = current_time_monotonic();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -308,7 +351,6 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le
|
|||
* 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(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
|
||||
{
|
||||
|
@ -322,7 +364,7 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t
|
|||
*length = 0;
|
||||
int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
|
||||
|
||||
if (fail_or_len <= 0) {
|
||||
if (fail_or_len < 0) {
|
||||
|
||||
LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK))
|
||||
LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); );
|
||||
|
@ -438,13 +480,13 @@ int networking_wait_execute(uint8_t *data, long seconds, long microseconds)
|
|||
* that code)
|
||||
*/
|
||||
if (s->send_fail_eagain != 0) {
|
||||
// current_time(): microseconds
|
||||
uint64_t now = current_time();
|
||||
// current_time(): milliseconds
|
||||
uint64_t now = current_time_monotonic();
|
||||
|
||||
/* s->sendqueue_length: might be used to guess how long we keep checking */
|
||||
/* for now, threshold is hardcoded to 250ms, too long for a really really
|
||||
* fast link, but too short for a sloooooow link... */
|
||||
if (now - s->send_fail_eagain < 250000) {
|
||||
if (now - s->send_fail_eagain < 250) {
|
||||
writefds_add = 1;
|
||||
}
|
||||
}
|
||||
|
@ -508,6 +550,11 @@ int networking_wait_cleanup(Networking_Core *net, uint8_t *data)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifndef VANILLA_NACL
|
||||
/* Used for sodium_init() */
|
||||
#include <sodium.h>
|
||||
#endif
|
||||
|
||||
uint8_t at_startup_ran = 0;
|
||||
int networking_at_startup(void)
|
||||
{
|
||||
|
@ -531,9 +578,9 @@ int networking_at_startup(void)
|
|||
return -1;
|
||||
|
||||
#else
|
||||
srandom((uint32_t)current_time());
|
||||
srandom((uint32_t)current_time_actual());
|
||||
#endif
|
||||
srand((uint32_t)current_time());
|
||||
srand((uint32_t)current_time_actual());
|
||||
at_startup_ran = 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -637,7 +684,6 @@ Networking_Core *new_networking(IP ip, uint16_t port)
|
|||
}
|
||||
|
||||
if (ip.family == AF_INET6) {
|
||||
|
||||
#ifdef LOGGING
|
||||
int is_dualstack =
|
||||
#endif /* LOGGING */
|
||||
|
@ -650,7 +696,6 @@ Networking_Core *new_networking(IP ip, uint16_t port)
|
|||
mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
|
||||
mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
|
||||
mreq.ipv6mr_interface = 0;
|
||||
|
||||
#ifdef LOGGING
|
||||
int res =
|
||||
#endif /* LOGGING */
|
||||
|
@ -829,6 +874,31 @@ void ipport_copy(IP_Port *target, IP_Port *source)
|
|||
memcpy(target, source, sizeof(IP_Port));
|
||||
};
|
||||
|
||||
/* packing and unpacking functions */
|
||||
void ip_pack(uint8_t *data, IP *source)
|
||||
{
|
||||
data[0] = source->family;
|
||||
memcpy(data + 1, &source->ip6, SIZE_IP6);
|
||||
}
|
||||
|
||||
void ip_unpack(IP *target, uint8_t *data)
|
||||
{
|
||||
target->family = data[0];
|
||||
memcpy(&target->ip6, data + 1, SIZE_IP6);
|
||||
}
|
||||
|
||||
void ipport_pack(uint8_t *data, IP_Port *source)
|
||||
{
|
||||
ip_pack(data, &source->ip);
|
||||
memcpy(data + SIZE_IP, &source->port, SIZE_PORT);
|
||||
}
|
||||
|
||||
void ipport_unpack(IP_Port *target, uint8_t *data)
|
||||
{
|
||||
ip_unpack(&target->ip, data);
|
||||
memcpy(&target->port, data + SIZE_IP, SIZE_PORT);
|
||||
}
|
||||
|
||||
/* ip_ntoa
|
||||
* converts ip into a string
|
||||
* uses a static buffer, so mustn't used multiple times in the same output
|
||||
|
|
|
@ -89,7 +89,7 @@ typedef int sock_t;
|
|||
#endif
|
||||
|
||||
#if defined(__sun__)
|
||||
#define __EXTENSIONS__ 1 // SunOS!
|
||||
#define __EXTENSIONS__ 1 // SunOS!
|
||||
#if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__) || defined(__SunOS5_9__) || defined(__SunOS5_10__)
|
||||
//Nothing needed
|
||||
#else
|
||||
|
@ -97,21 +97,6 @@ typedef int sock_t;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef VANILLA_NACL
|
||||
/* We use libsodium by default. */
|
||||
#include <sodium.h>
|
||||
#else
|
||||
#include <crypto_box.h>
|
||||
#include <crypto_secretbox.h>
|
||||
#include <randombytes.h>
|
||||
#include <crypto_hash_sha256.h>
|
||||
#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
|
||||
#endif
|
||||
|
||||
#ifndef crypto_secretbox_MACBYTES
|
||||
#define crypto_secretbox_MACBYTES (crypto_secretbox_ZEROBYTES - crypto_secretbox_BOXZEROBYTES)
|
||||
#endif
|
||||
|
||||
#ifndef IPV6_ADD_MEMBERSHIP
|
||||
#ifdef IPV6_JOIN_GROUP
|
||||
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
|
||||
|
@ -129,6 +114,10 @@ typedef int sock_t;
|
|||
#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_COOKIE_REQUEST 24 /* Cookie request packet */
|
||||
#define NET_PACKET_COOKIE_RESPONSE 25 /* Cookie response packet */
|
||||
#define NET_PACKET_CRYPTO_HS 26 /* Crypto handshake packet */
|
||||
#define NET_PACKET_CRYPTO_DATA 27 /* Crypto data packet */
|
||||
#define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */
|
||||
#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */
|
||||
#define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */
|
||||
|
@ -161,8 +150,11 @@ typedef int sock_t;
|
|||
#define TOX_PORTRANGE_TO 33545
|
||||
#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
|
||||
|
||||
|
||||
/* TODO: remove padding bytes next time we need to break compatibility with old versions of core. */
|
||||
/* TCP related */
|
||||
#define TCP_ONION_FAMILY (AF_INET6 + 1)
|
||||
#define TCP_INET (AF_INET6 + 2)
|
||||
#define TCP_INET6 (AF_INET6 + 3)
|
||||
#define TCP_FAMILY (AF_INET6 + 4)
|
||||
|
||||
typedef union __attribute__ ((__packed__))
|
||||
{
|
||||
|
@ -186,8 +178,6 @@ IP6;
|
|||
typedef struct __attribute__ ((__packed__))
|
||||
{
|
||||
uint8_t family;
|
||||
/* Not used for anything right now. */
|
||||
uint8_t padding[3];
|
||||
union {
|
||||
IP4 ip4;
|
||||
IP6 ip6;
|
||||
|
@ -195,23 +185,19 @@ typedef struct __attribute__ ((__packed__))
|
|||
}
|
||||
IP;
|
||||
|
||||
typedef union __attribute__ ((__packed__))
|
||||
typedef struct __attribute__ ((__packed__)) __attribute__((gcc_struct))
|
||||
{
|
||||
struct {
|
||||
IP4 ip;
|
||||
uint16_t port;
|
||||
/* Not used for anything right now. */
|
||||
uint16_t padding;
|
||||
};
|
||||
uint8_t uint8[8];
|
||||
}
|
||||
IP4_Port;
|
||||
|
||||
typedef struct __attribute__ ((__packed__)) IP_Port {
|
||||
IP ip;
|
||||
uint16_t port;
|
||||
uint16_t padding;
|
||||
} IP_Port;
|
||||
}
|
||||
IP_Port;
|
||||
|
||||
|
||||
#define SIZE_IP4 4
|
||||
#define SIZE_IP6 16
|
||||
#define SIZE_IP (1 + SIZE_IP6)
|
||||
#define SIZE_PORT 2
|
||||
#define SIZE_IPPORT (SIZE_IP + SIZE_PORT)
|
||||
|
||||
#define TOX_ENABLE_IPV6_DEFAULT 1
|
||||
|
||||
|
@ -250,6 +236,16 @@ void ip_copy(IP *target, IP *source);
|
|||
/* copies an ip_port structure */
|
||||
void ipport_copy(IP_Port *target, IP_Port *source);
|
||||
|
||||
|
||||
/* packs IP into data, writes SIZE_IP bytes to data */
|
||||
void ip_pack(uint8_t *data, IP *source);
|
||||
/* unpacks IP from data, reads SIZE_IP bytes from data */
|
||||
void ip_unpack(IP *target, uint8_t *data);
|
||||
/* packs IP_Port into data, writes SIZE_IPPORT bytes to data */
|
||||
void ipport_pack(uint8_t *data, IP_Port *source);
|
||||
/* unpacks IP_Port from data, reads SIZE_IPPORT bytes to data */
|
||||
void ipport_unpack(IP_Port *target, uint8_t *data);
|
||||
|
||||
/*
|
||||
* addr_resolve():
|
||||
* uses getaddrinfo to resolve an address into an IP address
|
||||
|
@ -332,6 +328,13 @@ void kill_sock(sock_t sock);
|
|||
*/
|
||||
int set_socket_nonblock(sock_t sock);
|
||||
|
||||
/* Set socket to not emit SIGPIPE
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int set_socket_nosigpipe(sock_t sock);
|
||||
|
||||
/* Set socket to dual (IPv4 + IPv6 socket)
|
||||
*
|
||||
* return 1 on success
|
||||
|
@ -339,13 +342,8 @@ int set_socket_nonblock(sock_t sock);
|
|||
*/
|
||||
int set_socket_dualstack(sock_t sock);
|
||||
|
||||
/* return current time in milleseconds since the epoch. */
|
||||
uint64_t current_time(void);
|
||||
|
||||
/* return a random number.
|
||||
*/
|
||||
uint32_t random_int(void);
|
||||
uint64_t random_64b(void);
|
||||
/* return current monotonic time in milliseconds (ms). */
|
||||
uint64_t current_time_monotonic(void);
|
||||
|
||||
/* Basic network functions: */
|
||||
|
||||
|
|
174
toxcore/onion.c
174
toxcore/onion.c
|
@ -26,8 +26,6 @@
|
|||
#include "onion.h"
|
||||
#include "util.h"
|
||||
|
||||
#define MAX_ONION_SIZE MAX_DATA_SIZE
|
||||
|
||||
#define RETURN_1 ONION_RETURN_1
|
||||
#define RETURN_2 ONION_RETURN_2
|
||||
#define RETURN_3 ONION_RETURN_3
|
||||
|
@ -89,41 +87,43 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes)
|
|||
/* Create and send a onion packet.
|
||||
*
|
||||
* Use Onion_Path path to send data of length to dest.
|
||||
* Maximum length of data is ONION_MAX_DATA_SIZE.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length)
|
||||
{
|
||||
if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0)
|
||||
if (1 + length + SEND_1 > ONION_MAX_PACKET_SIZE || length == 0)
|
||||
return -1;
|
||||
|
||||
to_net_family(&dest.ip);
|
||||
uint8_t step1[sizeof(IP_Port) + length];
|
||||
uint8_t step1[SIZE_IPPORT + length];
|
||||
|
||||
memcpy(step1, &dest, sizeof(IP_Port));
|
||||
memcpy(step1 + sizeof(IP_Port), data, length);
|
||||
|
||||
ipport_pack(step1, &dest);
|
||||
memcpy(step1 + SIZE_IPPORT, data, length);
|
||||
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
random_nonce(nonce);
|
||||
|
||||
uint8_t step2[sizeof(IP_Port) + SEND_BASE + length];
|
||||
memcpy(step2, &path->ip_port3, sizeof(IP_Port));
|
||||
memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES);
|
||||
uint8_t step2[SIZE_IPPORT + SEND_BASE + length];
|
||||
ipport_pack(step2, &path->ip_port3);
|
||||
memcpy(step2 + SIZE_IPPORT, path->public_key3, crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1),
|
||||
step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
|
||||
int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1),
|
||||
step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES)
|
||||
if ((uint32_t)len != SIZE_IPPORT + length + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length];
|
||||
memcpy(step3, &path->ip_port2, sizeof(IP_Port));
|
||||
memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES);
|
||||
len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2),
|
||||
step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
|
||||
uint8_t step3[SIZE_IPPORT + SEND_BASE * 2 + length];
|
||||
ipport_pack(step3, &path->ip_port2);
|
||||
memcpy(step3 + SIZE_IPPORT, path->public_key2, crypto_box_PUBLICKEYBYTES);
|
||||
len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2),
|
||||
step3 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES)
|
||||
if ((uint32_t)len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
uint8_t packet[1 + length + SEND_1];
|
||||
|
@ -131,10 +131,10 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint
|
|||
memcpy(packet + 1, nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3),
|
||||
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
|
||||
len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3),
|
||||
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES)
|
||||
if ((uint32_t)len != SIZE_IPPORT + SEND_BASE * 2 + length + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet))
|
||||
|
@ -142,13 +142,18 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create and send a onion response sent initially to dest with.
|
||||
* Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int send_onion_response(Networking_Core *net, IP_Port dest, uint8_t *data, uint32_t length, uint8_t *ret)
|
||||
{
|
||||
if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0)
|
||||
return -1;
|
||||
|
||||
uint8_t packet[1 + RETURN_3 + length];
|
||||
packet[0] = NET_PACKET_ONION_RECV_3;
|
||||
memcpy(packet + 1, ret, RETURN_3);
|
||||
|
@ -164,7 +169,7 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui
|
|||
{
|
||||
Onion *onion = object;
|
||||
|
||||
if (length > MAX_ONION_SIZE)
|
||||
if (length > ONION_MAX_PACKET_SIZE)
|
||||
return 1;
|
||||
|
||||
if (length <= 1 + SEND_1)
|
||||
|
@ -172,11 +177,11 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui
|
|||
|
||||
change_symmetric_key(onion);
|
||||
|
||||
uint8_t plain[MAX_ONION_SIZE];
|
||||
uint8_t plain[ONION_MAX_PACKET_SIZE];
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES);
|
||||
int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain);
|
||||
int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain);
|
||||
|
||||
if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES))
|
||||
return 1;
|
||||
|
@ -187,23 +192,26 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui
|
|||
int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uint8_t *nonce)
|
||||
{
|
||||
IP_Port send_to;
|
||||
memcpy(&send_to, plain, sizeof(IP_Port));
|
||||
ipport_unpack(&send_to, plain);
|
||||
to_host_family(&send_to.ip);
|
||||
|
||||
uint8_t data[MAX_ONION_SIZE];
|
||||
uint8_t ip_port[SIZE_IPPORT];
|
||||
ipport_pack(ip_port, &source);
|
||||
|
||||
uint8_t data[ONION_MAX_PACKET_SIZE];
|
||||
data[0] = NET_PACKET_ONION_SEND_1;
|
||||
memcpy(data + 1, nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port));
|
||||
uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - sizeof(IP_Port));
|
||||
memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT);
|
||||
uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT);
|
||||
uint8_t *ret_part = data + data_len;
|
||||
new_nonce(ret_part);
|
||||
len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, (uint8_t *)&source, sizeof(IP_Port),
|
||||
ret_part + crypto_secretbox_NONCEBYTES);
|
||||
len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
|
||||
ret_part + crypto_box_NONCEBYTES);
|
||||
|
||||
if (len != sizeof(IP_Port) + crypto_secretbox_MACBYTES)
|
||||
if (len != SIZE_IPPORT + crypto_box_MACBYTES)
|
||||
return 1;
|
||||
|
||||
data_len += crypto_secretbox_NONCEBYTES + len;
|
||||
data_len += crypto_box_NONCEBYTES + len;
|
||||
|
||||
if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len)
|
||||
return 1;
|
||||
|
@ -215,7 +223,7 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
{
|
||||
Onion *onion = object;
|
||||
|
||||
if (length > MAX_ONION_SIZE)
|
||||
if (length > ONION_MAX_PACKET_SIZE)
|
||||
return 1;
|
||||
|
||||
if (length <= 1 + SEND_2)
|
||||
|
@ -223,36 +231,36 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
|
||||
change_symmetric_key(onion);
|
||||
|
||||
uint8_t plain[MAX_ONION_SIZE];
|
||||
uint8_t plain[ONION_MAX_PACKET_SIZE];
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES);
|
||||
int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain);
|
||||
int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain);
|
||||
|
||||
if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES))
|
||||
return 1;
|
||||
|
||||
IP_Port send_to;
|
||||
memcpy(&send_to, plain, sizeof(IP_Port));
|
||||
ipport_unpack(&send_to, plain);
|
||||
to_host_family(&send_to.ip);
|
||||
|
||||
uint8_t data[MAX_ONION_SIZE];
|
||||
uint8_t data[ONION_MAX_PACKET_SIZE];
|
||||
data[0] = NET_PACKET_ONION_SEND_2;
|
||||
memcpy(data + 1, packet + 1, crypto_box_NONCEBYTES);
|
||||
memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port));
|
||||
uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - sizeof(IP_Port));
|
||||
memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT);
|
||||
uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT);
|
||||
uint8_t *ret_part = data + data_len;
|
||||
new_nonce(ret_part);
|
||||
uint8_t ret_data[RETURN_1 + sizeof(IP_Port)];
|
||||
memcpy(ret_data, &source, sizeof(IP_Port));
|
||||
memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_1), RETURN_1);
|
||||
uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
|
||||
ipport_pack(ret_data, &source);
|
||||
memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
|
||||
len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
|
||||
ret_part + crypto_secretbox_NONCEBYTES);
|
||||
ret_part + crypto_box_NONCEBYTES);
|
||||
|
||||
if (len != RETURN_2 - crypto_secretbox_NONCEBYTES)
|
||||
if (len != RETURN_2 - crypto_box_NONCEBYTES)
|
||||
return 1;
|
||||
|
||||
data_len += crypto_secretbox_NONCEBYTES + len;
|
||||
data_len += crypto_box_NONCEBYTES + len;
|
||||
|
||||
if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len)
|
||||
return 1;
|
||||
|
@ -264,7 +272,7 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
{
|
||||
Onion *onion = object;
|
||||
|
||||
if (length > MAX_ONION_SIZE)
|
||||
if (length > ONION_MAX_PACKET_SIZE)
|
||||
return 1;
|
||||
|
||||
if (length <= 1 + SEND_3)
|
||||
|
@ -272,31 +280,31 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
|
||||
change_symmetric_key(onion);
|
||||
|
||||
uint8_t plain[MAX_ONION_SIZE];
|
||||
uint8_t plain[ONION_MAX_PACKET_SIZE];
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES);
|
||||
int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain);
|
||||
int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain);
|
||||
|
||||
if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES))
|
||||
return 1;
|
||||
|
||||
IP_Port send_to;
|
||||
memcpy(&send_to, plain, sizeof(IP_Port));
|
||||
ipport_unpack(&send_to, plain);
|
||||
to_host_family(&send_to.ip);
|
||||
|
||||
uint8_t data[MAX_ONION_SIZE];
|
||||
memcpy(data, plain + sizeof(IP_Port), len - sizeof(IP_Port));
|
||||
uint32_t data_len = (len - sizeof(IP_Port));
|
||||
uint8_t *ret_part = data + (len - sizeof(IP_Port));
|
||||
uint8_t data[ONION_MAX_PACKET_SIZE];
|
||||
memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT);
|
||||
uint32_t data_len = (len - SIZE_IPPORT);
|
||||
uint8_t *ret_part = data + (len - SIZE_IPPORT);
|
||||
new_nonce(ret_part);
|
||||
uint8_t ret_data[RETURN_2 + sizeof(IP_Port)];
|
||||
memcpy(ret_data, &source, sizeof(IP_Port));
|
||||
memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_2), RETURN_2);
|
||||
uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
|
||||
ipport_pack(ret_data, &source);
|
||||
memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
|
||||
len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
|
||||
ret_part + crypto_secretbox_NONCEBYTES);
|
||||
ret_part + crypto_box_NONCEBYTES);
|
||||
|
||||
if (len != RETURN_3 - crypto_secretbox_NONCEBYTES)
|
||||
if (len != RETURN_3 - crypto_box_NONCEBYTES)
|
||||
return 1;
|
||||
|
||||
data_len += RETURN_3;
|
||||
|
@ -312,7 +320,7 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
{
|
||||
Onion *onion = object;
|
||||
|
||||
if (length > MAX_ONION_SIZE)
|
||||
if (length > ONION_MAX_PACKET_SIZE)
|
||||
return 1;
|
||||
|
||||
if (length <= 1 + RETURN_3)
|
||||
|
@ -320,19 +328,19 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
|
||||
change_symmetric_key(onion);
|
||||
|
||||
uint8_t plain[sizeof(IP_Port) + RETURN_2];
|
||||
int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES,
|
||||
sizeof(IP_Port) + RETURN_2 + crypto_secretbox_MACBYTES, plain);
|
||||
uint8_t plain[SIZE_IPPORT + RETURN_2];
|
||||
int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES,
|
||||
SIZE_IPPORT + RETURN_2 + crypto_box_MACBYTES, plain);
|
||||
|
||||
if ((uint32_t)len != sizeof(plain))
|
||||
return 1;
|
||||
|
||||
IP_Port send_to;
|
||||
memcpy(&send_to, plain, sizeof(IP_Port));
|
||||
ipport_unpack(&send_to, plain);
|
||||
|
||||
uint8_t data[MAX_ONION_SIZE];
|
||||
uint8_t data[ONION_MAX_PACKET_SIZE];
|
||||
data[0] = NET_PACKET_ONION_RECV_2;
|
||||
memcpy(data + 1, plain + sizeof(IP_Port), RETURN_2);
|
||||
memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2);
|
||||
memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3));
|
||||
uint32_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3));
|
||||
|
||||
|
@ -346,7 +354,7 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
{
|
||||
Onion *onion = object;
|
||||
|
||||
if (length > MAX_ONION_SIZE)
|
||||
if (length > ONION_MAX_PACKET_SIZE)
|
||||
return 1;
|
||||
|
||||
if (length <= 1 + RETURN_2)
|
||||
|
@ -354,19 +362,19 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
|
||||
change_symmetric_key(onion);
|
||||
|
||||
uint8_t plain[sizeof(IP_Port) + RETURN_1];
|
||||
int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES,
|
||||
sizeof(IP_Port) + RETURN_1 + crypto_secretbox_MACBYTES, plain);
|
||||
uint8_t plain[SIZE_IPPORT + RETURN_1];
|
||||
int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES,
|
||||
SIZE_IPPORT + RETURN_1 + crypto_box_MACBYTES, plain);
|
||||
|
||||
if ((uint32_t)len != sizeof(plain))
|
||||
return 1;
|
||||
|
||||
IP_Port send_to;
|
||||
memcpy(&send_to, plain, sizeof(IP_Port));
|
||||
ipport_unpack(&send_to, plain);
|
||||
|
||||
uint8_t data[MAX_ONION_SIZE];
|
||||
uint8_t data[ONION_MAX_PACKET_SIZE];
|
||||
data[0] = NET_PACKET_ONION_RECV_1;
|
||||
memcpy(data + 1, plain + sizeof(IP_Port), RETURN_1);
|
||||
memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1);
|
||||
memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2));
|
||||
uint32_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2));
|
||||
|
||||
|
@ -380,7 +388,7 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
{
|
||||
Onion *onion = object;
|
||||
|
||||
if (length > MAX_ONION_SIZE)
|
||||
if (length > ONION_MAX_PACKET_SIZE)
|
||||
return 1;
|
||||
|
||||
if (length <= 1 + RETURN_1)
|
||||
|
@ -388,14 +396,16 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
|
||||
change_symmetric_key(onion);
|
||||
|
||||
IP_Port send_to;
|
||||
uint8_t plain[SIZE_IPPORT];
|
||||
int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES,
|
||||
SIZE_IPPORT + crypto_box_MACBYTES, plain);
|
||||
|
||||
int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES,
|
||||
sizeof(IP_Port) + crypto_secretbox_MACBYTES, (uint8_t *) &send_to);
|
||||
|
||||
if ((uint32_t)len != sizeof(IP_Port))
|
||||
if ((uint32_t)len != SIZE_IPPORT)
|
||||
return 1;
|
||||
|
||||
IP_Port send_to;
|
||||
ipport_unpack(&send_to, plain);
|
||||
|
||||
uint32_t data_len = length - (1 + RETURN_1);
|
||||
|
||||
if (onion->recv_1_function && send_to.ip.family != AF_INET && send_to.ip.family != AF_INET6)
|
||||
|
@ -424,7 +434,7 @@ Onion *new_onion(DHT *dht)
|
|||
return NULL;
|
||||
|
||||
onion->dht = dht;
|
||||
onion->net = dht->c->lossless_udp->net;
|
||||
onion->net = dht->net;
|
||||
new_symmetric_key(onion->secret_symmetric_key);
|
||||
onion->timestamp = unix_time();
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
typedef struct {
|
||||
DHT *dht;
|
||||
Networking_Core *net;
|
||||
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
|
||||
uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
|
||||
uint64_t timestamp;
|
||||
|
||||
Shared_Keys shared_keys_1;
|
||||
|
@ -39,15 +39,20 @@ typedef struct {
|
|||
void *callback_object;
|
||||
} Onion;
|
||||
|
||||
#define ONION_RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES)
|
||||
#define ONION_RETURN_2 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + ONION_RETURN_1)
|
||||
#define ONION_RETURN_3 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + ONION_RETURN_2)
|
||||
#define ONION_MAX_PACKET_SIZE 1400
|
||||
|
||||
#define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_box_MACBYTES)
|
||||
#define ONION_RETURN_1 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES)
|
||||
#define ONION_RETURN_2 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_1)
|
||||
#define ONION_RETURN_3 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_2)
|
||||
|
||||
#define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + SIZE_IPPORT + crypto_box_MACBYTES)
|
||||
#define ONION_SEND_3 (crypto_box_NONCEBYTES + ONION_SEND_BASE + ONION_RETURN_2)
|
||||
#define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1)
|
||||
#define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3)
|
||||
|
||||
#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1))
|
||||
#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3))
|
||||
|
||||
typedef struct {
|
||||
uint8_t shared_key1[crypto_box_BEFORENMBYTES];
|
||||
uint8_t shared_key2[crypto_box_BEFORENMBYTES];
|
||||
|
@ -76,6 +81,7 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes);
|
|||
/* Create and send a onion packet.
|
||||
*
|
||||
* Use Onion_Path path to send data of length to dest.
|
||||
* Maximum length of data is ONION_MAX_DATA_SIZE.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
|
@ -83,6 +89,7 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes);
|
|||
int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length);
|
||||
|
||||
/* Create and send a onion response sent initially to dest with.
|
||||
* Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES)
|
||||
#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3)
|
||||
|
||||
#define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
|
||||
#define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE
|
||||
#define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3)
|
||||
|
||||
/* Create and send an onion announce request packet.
|
||||
|
@ -50,14 +50,14 @@
|
|||
* return 0 on success.
|
||||
*/
|
||||
int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
|
||||
uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
|
||||
uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint64_t sendback_data)
|
||||
{
|
||||
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
|
||||
memcpy(plain, ping_id, ONION_PING_ID_SIZE);
|
||||
memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, data_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, sendback_data,
|
||||
ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
|
||||
memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, &sendback_data,
|
||||
sizeof(sendback_data));
|
||||
uint8_t packet[ANNOUNCE_REQUEST_SIZE];
|
||||
packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
|
||||
random_nonce(packet + 1);
|
||||
|
@ -90,6 +90,9 @@ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format de
|
|||
int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
|
||||
uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if ((unsigned int)DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE)
|
||||
return -1;
|
||||
|
||||
uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
|
||||
packet[0] = NET_PACKET_ONION_DATA_REQUEST;
|
||||
memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
|
||||
|
@ -115,11 +118,11 @@ static void generate_ping_id(Onion_Announce *onion_a, uint64_t time, uint8_t *pu
|
|||
uint8_t *ping_id)
|
||||
{
|
||||
time /= PING_ID_TIMEOUT;
|
||||
uint8_t data[crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)];
|
||||
memcpy(data, onion_a->secret_bytes, crypto_secretbox_KEYBYTES);
|
||||
memcpy(data + crypto_secretbox_KEYBYTES, &time, sizeof(time));
|
||||
memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port));
|
||||
uint8_t data[crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)];
|
||||
memcpy(data, onion_a->secret_bytes, crypto_box_KEYBYTES);
|
||||
memcpy(data + crypto_box_KEYBYTES, &time, sizeof(time));
|
||||
memcpy(data + crypto_box_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(data + crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port));
|
||||
crypto_hash_sha256(ping_id, data, sizeof(data));
|
||||
}
|
||||
|
||||
|
@ -221,9 +224,9 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
|
|||
get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key);
|
||||
|
||||
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
|
||||
int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
|
||||
crypto_box_MACBYTES, plain);
|
||||
int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
|
||||
crypto_box_MACBYTES, plain);
|
||||
|
||||
if ((uint32_t)len != sizeof(plain))
|
||||
return 1;
|
||||
|
@ -247,14 +250,8 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
|
|||
|
||||
/*Respond with a announce response packet*/
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family,
|
||||
LAN_ip(source.ip) == 0, 1);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i)
|
||||
to_net_family(&nodes_list[i].ip_port.ip);
|
||||
|
||||
uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0, LAN_ip(source.ip) == 0,
|
||||
1);
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
random_nonce(nonce);
|
||||
|
||||
|
@ -274,13 +271,20 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
|
|||
}
|
||||
}
|
||||
|
||||
memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format));
|
||||
int nodes_length = 0;
|
||||
|
||||
if (num_nodes != 0) {
|
||||
nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes);
|
||||
|
||||
if (nodes_length <= 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
|
||||
len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format),
|
||||
data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES);
|
||||
len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length,
|
||||
data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES);
|
||||
|
||||
if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES)
|
||||
if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES)
|
||||
return 1;
|
||||
|
||||
data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
|
||||
|
@ -303,7 +307,7 @@ static int handle_data_request(void *object, IP_Port source, uint8_t *packet, ui
|
|||
if (length <= DATA_REQUEST_MIN_SIZE_RECV)
|
||||
return 1;
|
||||
|
||||
if (length >= MAX_DATA_SIZE)
|
||||
if (length > ONION_MAX_PACKET_SIZE)
|
||||
return 1;
|
||||
|
||||
int index = in_entries(onion_a, packet + 1);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define ONION_ANNOUNCE_TIMEOUT 300
|
||||
#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
|
||||
|
||||
#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES)
|
||||
#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t))
|
||||
|
||||
#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + 1 + ONION_PING_ID_SIZE + crypto_box_MACBYTES)
|
||||
#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
|
||||
|
@ -40,6 +40,9 @@
|
|||
#error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES
|
||||
#endif
|
||||
|
||||
#define ONION_DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
|
||||
#define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE)
|
||||
|
||||
typedef struct {
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
|
||||
IP_Port ret_ip_port;
|
||||
|
@ -52,8 +55,8 @@ typedef struct {
|
|||
DHT *dht;
|
||||
Networking_Core *net;
|
||||
Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
|
||||
/* This is crypto_secretbox_KEYBYTES long just so we can use new_symmetric_key() to fill it */
|
||||
uint8_t secret_bytes[crypto_secretbox_KEYBYTES];
|
||||
/* This is crypto_box_KEYBYTES long just so we can use new_symmetric_key() to fill it */
|
||||
uint8_t secret_bytes[crypto_box_KEYBYTES];
|
||||
|
||||
Shared_Keys shared_keys_recv;
|
||||
} Onion_Announce;
|
||||
|
@ -73,7 +76,7 @@ typedef struct {
|
|||
* return 0 on success.
|
||||
*/
|
||||
int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
|
||||
uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
|
||||
uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint64_t sendback_data);
|
||||
|
||||
/* Create and send an onion data request packet.
|
||||
*
|
||||
|
@ -86,6 +89,8 @@ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format de
|
|||
*
|
||||
* nonce is the nonce to encrypt this packet with
|
||||
*
|
||||
* The maximum length of data is MAX_DATA_REQUEST_SIZE.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
|
|
|
@ -28,8 +28,37 @@
|
|||
#include "util.h"
|
||||
#include "LAN_discovery.h"
|
||||
|
||||
/* defines for the array size and
|
||||
timeout for onion announce packets. */
|
||||
#define ANNOUNCE_ARRAY_SIZE 256
|
||||
#define ANNOUNCE_TIMEOUT 10
|
||||
|
||||
|
||||
/*
|
||||
* return -1 if nodes are suitable for creating a new path.
|
||||
* return path number of already existing similar path if one already exists.
|
||||
*/
|
||||
static int is_path_used(Onion_Client_Paths *onion_paths, Node_format *nodes)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
|
||||
if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[0].ip_port)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create a new path or use an old suitable one (if pathnum is valid)
|
||||
* or a rondom one from onion_paths.
|
||||
*
|
||||
|
@ -51,11 +80,17 @@ static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathn
|
|||
if (random_nodes_path(dht, nodes, 3) != 3)
|
||||
return -1;
|
||||
|
||||
if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1)
|
||||
return -1;
|
||||
int n = is_path_used(onion_paths, nodes);
|
||||
|
||||
onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
|
||||
onion_paths->path_creation_time[pathnum] = unix_time();
|
||||
if (n == -1) {
|
||||
if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1)
|
||||
return -1;
|
||||
|
||||
onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
|
||||
onion_paths->path_creation_time[pathnum] = unix_time();
|
||||
} else {
|
||||
pathnum = n;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
|
||||
|
@ -105,20 +140,15 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, IP_Port s
|
|||
* return 0 on success
|
||||
*
|
||||
*/
|
||||
static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint8_t *sendback)
|
||||
static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint64_t *sendback)
|
||||
{
|
||||
uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
|
||||
uint64_t time = unix_time();
|
||||
random_nonce(sendback);
|
||||
memcpy(plain, &num, sizeof(uint32_t));
|
||||
memcpy(plain + sizeof(uint32_t), &time, sizeof(uint64_t));
|
||||
memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t), public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port));
|
||||
uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
|
||||
memcpy(data, &num, sizeof(uint32_t));
|
||||
memcpy(data + sizeof(uint32_t), public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port));
|
||||
*sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data));
|
||||
|
||||
int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain),
|
||||
sendback + crypto_secretbox_NONCEBYTES);
|
||||
|
||||
if ((uint32_t)len + crypto_secretbox_NONCEBYTES != ONION_ANNOUNCE_SENDBACK_DATA_LENGTH)
|
||||
if (*sendback == 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
@ -136,24 +166,17 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key
|
|||
*/
|
||||
static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port)
|
||||
{
|
||||
uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
|
||||
int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES,
|
||||
ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain);
|
||||
uint64_t sback;
|
||||
memcpy(&sback, sendback, sizeof(uint64_t));
|
||||
uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
|
||||
|
||||
if ((uint32_t)len != sizeof(plain))
|
||||
if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data))
|
||||
return ~0;
|
||||
|
||||
uint64_t timestamp;
|
||||
memcpy(×tamp, plain + sizeof(uint32_t), sizeof(uint64_t));
|
||||
uint64_t temp_time = unix_time();
|
||||
|
||||
if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp)
|
||||
return ~0;
|
||||
|
||||
memcpy(ret_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(ret_ip_port, plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port));
|
||||
memcpy(ret_pubkey, data + sizeof(uint32_t), crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(ret_ip_port, data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port));
|
||||
uint32_t num;
|
||||
memcpy(&num, plain, sizeof(uint32_t));
|
||||
memcpy(&num, data, sizeof(uint32_t));
|
||||
return num;
|
||||
}
|
||||
|
||||
|
@ -163,9 +186,9 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
|
|||
if (num > onion_c->num_friends)
|
||||
return -1;
|
||||
|
||||
uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
|
||||
uint64_t sendback;
|
||||
|
||||
if (new_sendback(onion_c, num, dest_pubkey, dest, sendback) == -1)
|
||||
if (new_sendback(onion_c, num, dest_pubkey, dest, &sendback) == -1)
|
||||
return -1;
|
||||
|
||||
uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
|
||||
|
@ -183,9 +206,9 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
|
|||
if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1)
|
||||
return -1;
|
||||
|
||||
return send_announce_request(onion_c->net, &path, dest_node, onion_c->dht->c->self_public_key,
|
||||
onion_c->dht->c->self_secret_key, ping_id,
|
||||
onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback);
|
||||
return send_announce_request(onion_c->net, &path, dest_node, onion_c->c->self_public_key,
|
||||
onion_c->c->self_secret_key, ping_id,
|
||||
onion_c->c->self_public_key, onion_c->temp_public_key, sendback);
|
||||
} else {
|
||||
if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1)
|
||||
return -1;
|
||||
|
@ -236,7 +259,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
|
|||
|
||||
if (num == 0) {
|
||||
list_nodes = onion_c->clients_announce_list;
|
||||
reference_id = onion_c->dht->c->self_public_key;
|
||||
reference_id = onion_c->c->self_public_key;
|
||||
|
||||
if (is_stored && memcmp(pingid_or_key, onion_c->temp_public_key, crypto_box_PUBLICKEYBYTES) != 0) {
|
||||
is_stored = 0;
|
||||
|
@ -253,16 +276,9 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
|
|||
int index = -1;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
|
||||
if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT)
|
||||
|| id_closest(reference_id, list_nodes[i].client_id, public_key) == 2) {
|
||||
index = i;
|
||||
|
||||
if (i != 0)
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
|
||||
|| id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
|
||||
|
@ -286,7 +302,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
|
|||
|
||||
list_nodes[index].is_stored = is_stored;
|
||||
list_nodes[index].timestamp = unix_time();
|
||||
list_nodes[index].last_pinged = unix_time();
|
||||
list_nodes[index].last_pinged = 0;
|
||||
list_nodes[index].path_used = set_path_timeouts(onion_c, num, source);
|
||||
return 0;
|
||||
}
|
||||
|
@ -318,21 +334,18 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
|
|||
|
||||
Onion_Node *list_nodes = NULL;
|
||||
uint8_t *reference_id = NULL;
|
||||
uint32_t *ping_nodes_sent_second = NULL;
|
||||
|
||||
Last_Pinged *last_pinged = NULL;
|
||||
uint8_t *last_pinged_index = NULL;
|
||||
|
||||
if (num == 0) {
|
||||
list_nodes = onion_c->clients_announce_list;
|
||||
reference_id = onion_c->dht->c->self_public_key;
|
||||
ping_nodes_sent_second = &onion_c->ping_nodes_sent_second;
|
||||
reference_id = onion_c->c->self_public_key;
|
||||
last_pinged = onion_c->last_pinged;
|
||||
last_pinged_index = &onion_c->last_pinged_index;
|
||||
} else {
|
||||
list_nodes = onion_c->friends_list[num - 1].clients_list;
|
||||
reference_id = onion_c->friends_list[num - 1].real_client_id;
|
||||
ping_nodes_sent_second = &onion_c->friends_list[num - 1].ping_nodes_sent_second;
|
||||
last_pinged = onion_c->friends_list[num - 1].last_pinged;
|
||||
last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index;
|
||||
}
|
||||
|
@ -342,11 +355,6 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
|
|||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
|
||||
if (*ping_nodes_sent_second > MAX_PING_NODES_SECOND_PEER)
|
||||
return 0;
|
||||
|
||||
to_host_family(&nodes[i].ip_port.ip);
|
||||
|
||||
if (!lan_ips_accepted)
|
||||
if (LAN_ip(nodes[i].ip_port.ip) == 0)
|
||||
continue;
|
||||
|
@ -361,8 +369,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
|
|||
}
|
||||
|
||||
if (j == MAX_ONION_CLIENTS && good_to_ping(last_pinged, last_pinged_index, nodes[i].client_id)) {
|
||||
if (client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0) == 0)
|
||||
++*ping_nodes_sent_second;
|
||||
client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -377,10 +384,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE)
|
||||
return 1;
|
||||
|
||||
if ((length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) % sizeof(Node_format) != 0)
|
||||
return 1;
|
||||
|
||||
uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format);
|
||||
uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
|
||||
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
|
||||
IP_Port ip_port;
|
||||
|
@ -389,11 +393,11 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||
if (num > onion_c->num_friends)
|
||||
return 1;
|
||||
|
||||
uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)];
|
||||
uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes];
|
||||
int len = -1;
|
||||
|
||||
if (num == 0) {
|
||||
len = decrypt_data(public_key, onion_c->dht->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
|
||||
len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES,
|
||||
length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain);
|
||||
} else {
|
||||
|
@ -409,20 +413,24 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||
if ((uint32_t)len != sizeof(plain))
|
||||
return 1;
|
||||
|
||||
|
||||
if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1)
|
||||
return 1;
|
||||
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
memcpy(nodes, plain + 1 + ONION_PING_ID_SIZE, num_nodes * sizeof(Node_format));
|
||||
if (len_nodes != 0) {
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0);
|
||||
|
||||
if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1)
|
||||
return 1;
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
|
||||
#define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE
|
||||
|
||||
static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
|
@ -431,7 +439,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u
|
|||
if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE))
|
||||
return 1;
|
||||
|
||||
if (length > MAX_DATA_SIZE)
|
||||
if (length > MAX_DATA_REQUEST_SIZE)
|
||||
return 1;
|
||||
|
||||
uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
|
||||
|
@ -443,7 +451,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u
|
|||
return 1;
|
||||
|
||||
uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE];
|
||||
len = decrypt_data(temp_plain, onion_c->dht->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES,
|
||||
len = decrypt_data(temp_plain, onion_c->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES,
|
||||
sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain);
|
||||
|
||||
if ((uint32_t)len != sizeof(plain))
|
||||
|
@ -469,9 +477,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
|
|||
if (length > FAKEID_DATA_MAX_LENGTH)
|
||||
return 1;
|
||||
|
||||
if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0)
|
||||
return 1;
|
||||
|
||||
int friend_num = onion_friend_num(onion_c, source_pubkey);
|
||||
|
||||
if (friend_num == -1)
|
||||
|
@ -485,37 +490,42 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
|
|||
return 1;
|
||||
|
||||
onion_c->friends_list[friend_num].last_noreplay = no_replay;
|
||||
onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t), current_time_monotonic());
|
||||
onion_c->friends_list[friend_num].last_seen = unix_time();
|
||||
|
||||
if (memcmp(data + 1 + sizeof(uint64_t), onion_c->friends_list[friend_num].fake_client_id,
|
||||
crypto_box_PUBLICKEYBYTES) != 0) {
|
||||
DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
|
||||
uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH;
|
||||
|
||||
onion_c->friends_list[friend_num].last_seen = unix_time();
|
||||
if (len_nodes != 0) {
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES,
|
||||
len_nodes, 1);
|
||||
|
||||
if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) {
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
uint8_t family = nodes[i].ip_port.ip.family;
|
||||
|
||||
if (family == AF_INET || family == AF_INET6) {
|
||||
DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
|
||||
} else if (family == TCP_INET || family == TCP_INET6) {
|
||||
if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {
|
||||
void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
|
||||
uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
|
||||
onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].client_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onion_c->friends_list[friend_num].is_fake_clientid = 1;
|
||||
memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
|
||||
}
|
||||
|
||||
uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format);
|
||||
Node_format nodes[num_nodes];
|
||||
memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes));
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
to_host_family(&nodes[i].ip_port.ip);
|
||||
DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Send data of length length to friendnum.
|
||||
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
|
||||
* This data will be received by the friend using the Onion_Data_Handlers callbacks.
|
||||
*
|
||||
* Even if this function succeeds, the friend might not recieve any data.
|
||||
* Even if this function succeeds, the friend might not receive any data.
|
||||
*
|
||||
* return the number of packets sent on success
|
||||
* return -1 on failure.
|
||||
|
@ -525,7 +535,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
|
|||
if ((uint32_t)friend_num >= onion_c->num_friends)
|
||||
return -1;
|
||||
|
||||
if (length + DATA_IN_RESPONSE_MIN_SIZE + ONION_DATA_RESPONSE_MIN_SIZE + ONION_SEND_1 > MAX_DATA_SIZE)
|
||||
if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE)
|
||||
return -1;
|
||||
|
||||
if (length == 0)
|
||||
|
@ -535,8 +545,8 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
|
|||
random_nonce(nonce);
|
||||
|
||||
uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
|
||||
memcpy(packet, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data,
|
||||
memcpy(packet, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data,
|
||||
length, packet + crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
|
||||
|
@ -578,7 +588,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
|
|||
|
||||
/* Try to send the fakeid via the DHT instead of onion
|
||||
*
|
||||
* Even if this function succeeds, the friend might not recieve any data.
|
||||
* Even if this function succeeds, the friend might not receive any data.
|
||||
*
|
||||
* return the number of packets sent on success
|
||||
* return -1 on failure.
|
||||
|
@ -595,15 +605,15 @@ static int send_dht_fakeid(Onion_Client *onion_c, int friend_num, uint8_t *data,
|
|||
new_nonce(nonce);
|
||||
|
||||
uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length];
|
||||
memcpy(temp, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(temp, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
|
||||
int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data,
|
||||
int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data,
|
||||
length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
|
||||
|
||||
if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp))
|
||||
return -1;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
|
||||
len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet,
|
||||
onion_c->friends_list[friend_num].fake_client_id, temp, sizeof(temp), FAKEID_DATA_ID);
|
||||
|
||||
|
@ -624,14 +634,14 @@ static int handle_dht_fakeid(void *object, IP_Port source, uint8_t *source_pubke
|
|||
return 1;
|
||||
|
||||
uint8_t plain[FAKEID_DATA_MAX_LENGTH];
|
||||
int len = decrypt_data(packet, onion_c->dht->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES,
|
||||
int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES,
|
||||
packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
|
||||
length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain);
|
||||
|
||||
if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES))
|
||||
return 1;
|
||||
|
||||
if (memcpy(source_pubkey, packet, crypto_box_PUBLICKEYBYTES) != 0)
|
||||
if (memcmp(source_pubkey, plain + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES) != 0)
|
||||
return 1;
|
||||
|
||||
return handle_fakeid_announce(onion_c, packet, plain, len);
|
||||
|
@ -657,20 +667,26 @@ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint
|
|||
memcpy(data + 1, &no_replay, sizeof(no_replay));
|
||||
memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES);
|
||||
uint32_t i;
|
||||
uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2));
|
||||
uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays);
|
||||
num_nodes += num_relays;
|
||||
int nodes_len = 0;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i)
|
||||
to_net_family(&nodes[i].ip_port.ip);
|
||||
if (num_nodes != 0) {
|
||||
nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes,
|
||||
num_nodes);
|
||||
|
||||
if (nodes_len <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes);
|
||||
int num1 = -1, num2 = -1;
|
||||
|
||||
if (onion_dht_both != 1)
|
||||
num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes);
|
||||
num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len);
|
||||
|
||||
if (onion_dht_both != 0)
|
||||
num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes);
|
||||
num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len);
|
||||
|
||||
if (num1 == -1)
|
||||
return num2;
|
||||
|
@ -788,6 +804,84 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)
|
|||
return friend_num;
|
||||
}
|
||||
|
||||
/* Set the function for this friend that will be callbacked with object and number
|
||||
* when that friends gives us one of the TCP relays he is connected to.
|
||||
*
|
||||
* object and number will be passed as argument to this function.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object,
|
||||
uint32_t number, IP_Port ip_port, uint8_t *public_key), void *object, uint32_t number)
|
||||
{
|
||||
if ((uint32_t)friend_num >= onion_c->num_friends)
|
||||
return -1;
|
||||
|
||||
onion_c->friends_list[friend_num].tcp_relay_node_callback = tcp_relay_node_callback;
|
||||
onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object;
|
||||
onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set a friends DHT public key.
|
||||
* timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
|
||||
* the other peer.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key, uint64_t timestamp)
|
||||
{
|
||||
if ((uint32_t)friend_num >= onion_c->num_friends)
|
||||
return -1;
|
||||
|
||||
if (onion_c->friends_list[friend_num].status == 0)
|
||||
return -1;
|
||||
|
||||
if (onion_c->friends_list[friend_num].fake_client_id_timestamp >= timestamp)
|
||||
return -1;
|
||||
|
||||
if (onion_c->friends_list[friend_num].is_fake_clientid) {
|
||||
if (memcmp(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
|
||||
}
|
||||
|
||||
if (DHT_addfriend(onion_c->dht, dht_key) == 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
onion_c->friends_list[friend_num].last_seen = unix_time();
|
||||
onion_c->friends_list[friend_num].is_fake_clientid = 1;
|
||||
onion_c->friends_list[friend_num].fake_client_id_timestamp = timestamp;
|
||||
memcpy(onion_c->friends_list[friend_num].fake_client_id, dht_key, crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy friends DHT public key into dht_key.
|
||||
*
|
||||
* return 0 on failure (no key copied).
|
||||
* return timestamp on success (key copied).
|
||||
*/
|
||||
uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
|
||||
{
|
||||
if ((uint32_t)friend_num >= onion_c->num_friends)
|
||||
return 0;
|
||||
|
||||
if (onion_c->friends_list[friend_num].status == 0)
|
||||
return 0;
|
||||
|
||||
if (!onion_c->friends_list[friend_num].is_fake_clientid)
|
||||
return 0;
|
||||
|
||||
memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES);
|
||||
return onion_c->friends_list[friend_num].fake_client_id_timestamp;
|
||||
}
|
||||
|
||||
/* Get the ip of friend friendnum and put it in ip_port
|
||||
*
|
||||
* return -1, -- if client_id does NOT refer to a friend
|
||||
|
@ -797,18 +891,15 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)
|
|||
*/
|
||||
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
|
||||
{
|
||||
if ((uint32_t)friend_num >= onion_c->num_friends)
|
||||
uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0)
|
||||
return -1;
|
||||
|
||||
if (onion_c->friends_list[friend_num].status == 0)
|
||||
return -1;
|
||||
|
||||
if (!onion_c->friends_list[friend_num].is_fake_clientid)
|
||||
return -1;
|
||||
|
||||
return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port);
|
||||
return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port);
|
||||
}
|
||||
|
||||
|
||||
/* Set if friend is online or not.
|
||||
* NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
|
||||
*
|
||||
|
@ -856,6 +947,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
|
|||
|
||||
++count;
|
||||
|
||||
if (list_nodes[i].last_pinged == 0) {
|
||||
list_nodes[i].last_pinged = unix_time();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
|
||||
if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) {
|
||||
list_nodes[i].last_pinged = unix_time();
|
||||
|
@ -924,6 +1020,13 @@ static void do_announce(Onion_Client *onion_c)
|
|||
continue;
|
||||
|
||||
++count;
|
||||
|
||||
/* Don't announce ourselves the first time this is run to new peers */
|
||||
if (list_nodes[i].last_pinged == 0) {
|
||||
list_nodes[i].last_pinged = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
|
||||
|
||||
if (list_nodes[i].is_stored) {
|
||||
|
@ -941,7 +1044,7 @@ static void do_announce(Onion_Client *onion_c)
|
|||
if (count != MAX_ONION_CLIENTS) {
|
||||
if (count < (uint32_t)rand() % MAX_ONION_CLIENTS) {
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list,
|
||||
uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->c->self_public_key, nodes_list,
|
||||
rand() % 2 ? AF_INET : AF_INET6, 1, 0);
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
|
@ -963,16 +1066,14 @@ void do_onion_client(Onion_Client *onion_c)
|
|||
for (i = 0; i < onion_c->num_friends; ++i) {
|
||||
do_friend(onion_c, i);
|
||||
cleanup_friend(onion_c, i);
|
||||
onion_c->friends_list[i].ping_nodes_sent_second = 0;
|
||||
}
|
||||
|
||||
onion_c->ping_nodes_sent_second = 0;
|
||||
onion_c->last_run = unix_time();
|
||||
}
|
||||
|
||||
Onion_Client *new_onion_client(DHT *dht)
|
||||
Onion_Client *new_onion_client(Net_Crypto *c)
|
||||
{
|
||||
if (dht == NULL)
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
Onion_Client *onion_c = calloc(1, sizeof(Onion_Client));
|
||||
|
@ -980,14 +1081,20 @@ Onion_Client *new_onion_client(DHT *dht)
|
|||
if (onion_c == NULL)
|
||||
return NULL;
|
||||
|
||||
onion_c->dht = dht;
|
||||
onion_c->net = dht->c->lossless_udp->net;
|
||||
if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) {
|
||||
free(onion_c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
onion_c->dht = c->dht;
|
||||
onion_c->net = c->dht->net;
|
||||
onion_c->c = c;
|
||||
new_symmetric_key(onion_c->secret_symmetric_key);
|
||||
crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
|
||||
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
|
||||
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
|
||||
oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c);
|
||||
cryptopacket_registerhandler(onion_c->dht->c, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c);
|
||||
cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c);
|
||||
|
||||
return onion_c;
|
||||
}
|
||||
|
@ -997,11 +1104,12 @@ void kill_onion_client(Onion_Client *onion_c)
|
|||
if (onion_c == NULL)
|
||||
return;
|
||||
|
||||
ping_array_free_all(&onion_c->announce_ping_array);
|
||||
realloc_onion_friends(onion_c, 0);
|
||||
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL);
|
||||
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
|
||||
oniondata_registerhandler(onion_c, FAKEID_DATA_ID, NULL, NULL);
|
||||
cryptopacket_registerhandler(onion_c->dht->c, FAKEID_DATA_ID, NULL, NULL);
|
||||
cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, NULL, NULL);
|
||||
memset(onion_c, 0, sizeof(Onion_Client));
|
||||
free(onion_c);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#define ONION_CLIENT_H
|
||||
|
||||
#include "onion_announce.h"
|
||||
#include "net_crypto.h"
|
||||
#include "ping_array.h"
|
||||
|
||||
#define MAX_ONION_CLIENTS 8
|
||||
#define ONION_NODE_PING_INTERVAL 30
|
||||
|
@ -42,11 +44,6 @@
|
|||
#define ONION_PATH_TIMEOUT 30
|
||||
#define ONION_PATH_MAX_LIFETIME 600
|
||||
|
||||
/* A cheap way of making it take less bandwidth at startup:
|
||||
by limiting the number of ping packets we can send per
|
||||
second per peer. */
|
||||
#define MAX_PING_NODES_SECOND_PEER 5
|
||||
|
||||
#define MAX_STORED_PINGED_NODES 9
|
||||
#define MIN_NODE_PING_TIME 10
|
||||
|
||||
|
@ -80,6 +77,7 @@ typedef struct {
|
|||
uint8_t is_online; /* Set by the onion_set_friend_status function. */
|
||||
|
||||
uint8_t is_fake_clientid; /* 0 if we don't know the fake client id of the other 1 if we do. */
|
||||
uint64_t fake_client_id_timestamp;
|
||||
uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t real_client_id[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
|
@ -95,16 +93,20 @@ typedef struct {
|
|||
uint64_t last_seen;
|
||||
|
||||
Onion_Client_Paths onion_paths;
|
||||
uint32_t ping_nodes_sent_second;
|
||||
|
||||
Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
|
||||
uint8_t last_pinged_index;
|
||||
|
||||
int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, uint8_t *public_key);
|
||||
void *tcp_relay_node_callback_object;
|
||||
uint32_t tcp_relay_node_callback_number;
|
||||
} Onion_Friend;
|
||||
|
||||
typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
|
||||
|
||||
typedef struct {
|
||||
DHT *dht;
|
||||
Net_Crypto *c;
|
||||
Networking_Core *net;
|
||||
Onion_Friend *friends_list;
|
||||
uint16_t num_friends;
|
||||
|
@ -113,15 +115,15 @@ typedef struct {
|
|||
|
||||
Onion_Client_Paths onion_paths;
|
||||
|
||||
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
|
||||
uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
|
||||
uint64_t last_run;
|
||||
|
||||
uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
|
||||
uint32_t ping_nodes_sent_second;
|
||||
|
||||
Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
|
||||
|
||||
Ping_Array announce_ping_array;
|
||||
uint8_t last_pinged_index;
|
||||
struct {
|
||||
oniondata_handler_callback function;
|
||||
|
@ -170,11 +172,41 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
|
|||
*/
|
||||
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
|
||||
|
||||
/* Set the function for this friend that will be callbacked with object and number
|
||||
* when that friends gives us one of the TCP relays he is connected to.
|
||||
*
|
||||
* object and number will be passed as argument to this function.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object,
|
||||
uint32_t number, IP_Port ip_port, uint8_t *public_key), void *object, uint32_t number);
|
||||
|
||||
/* Set a friends DHT public key.
|
||||
* timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
|
||||
* the other peer.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key, uint64_t timestamp);
|
||||
|
||||
/* Copy friends DHT public key into dht_key.
|
||||
*
|
||||
* return 0 on failure (no key copied).
|
||||
* return timestamp on success (key copied).
|
||||
*/
|
||||
uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
|
||||
|
||||
#define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
|
||||
#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
|
||||
|
||||
/* Send data of length length to friendnum.
|
||||
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
|
||||
* Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE.
|
||||
* This data will be received by the friend using the Onion_Data_Handlers callbacks.
|
||||
*
|
||||
* Even if this function succeeds, the friend might not recieve any data.
|
||||
* Even if this function succeeds, the friend might not receive any data.
|
||||
*
|
||||
* return the number of packets sent on success
|
||||
* return -1 on failure.
|
||||
|
@ -186,7 +218,7 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha
|
|||
|
||||
void do_onion_client(Onion_Client *onion_c);
|
||||
|
||||
Onion_Client *new_onion_client(DHT *dht);
|
||||
Onion_Client *new_onion_client(Net_Crypto *c);
|
||||
|
||||
void kill_onion_client(Onion_Client *onion_c);
|
||||
|
||||
|
|
247
toxcore/ping.c
247
toxcore/ping.c
|
@ -34,118 +34,29 @@
|
|||
|
||||
#include "network.h"
|
||||
#include "util.h"
|
||||
#include "ping_array.h"
|
||||
|
||||
#define PING_NUM_MAX 512
|
||||
|
||||
/* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */
|
||||
#define MAX_TO_PING 16
|
||||
#define MAX_TO_PING 8
|
||||
|
||||
/* Ping newly announced nodes to ping per TIME_TO_PING seconds*/
|
||||
#define TIME_TO_PING 5
|
||||
#define TIME_TO_PING 8
|
||||
|
||||
typedef struct {
|
||||
IP_Port ip_port;
|
||||
uint64_t id;
|
||||
uint64_t timestamp;
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
} pinged_t;
|
||||
|
||||
struct PING {
|
||||
DHT *dht;
|
||||
|
||||
pinged_t pings[PING_NUM_MAX];
|
||||
size_t num_pings;
|
||||
size_t pos_pings;
|
||||
|
||||
Ping_Array ping_array;
|
||||
Node_format to_ping[MAX_TO_PING];
|
||||
uint64_t last_to_ping;
|
||||
};
|
||||
|
||||
static int is_ping_timeout(uint64_t time)
|
||||
{
|
||||
return is_timeout(time, PING_TIMEOUT);
|
||||
}
|
||||
|
||||
static void remove_timeouts(PING *ping) // O(n)
|
||||
{
|
||||
size_t i, id;
|
||||
size_t new_pos = ping->pos_pings;
|
||||
size_t new_num = ping->num_pings;
|
||||
|
||||
// Loop through buffer, oldest first.
|
||||
for (i = 0; i < ping->num_pings; i++) {
|
||||
id = (ping->pos_pings + i) % PING_NUM_MAX;
|
||||
|
||||
if (is_ping_timeout(ping->pings[id].timestamp)) {
|
||||
new_pos++;
|
||||
new_num--;
|
||||
}
|
||||
// Break here because list is sorted.
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ping->num_pings = new_num;
|
||||
ping->pos_pings = new_pos % PING_NUM_MAX;
|
||||
}
|
||||
|
||||
static uint64_t add_ping(PING *ping, IP_Port ipp, uint8_t *shared_encryption_key) // O(n)
|
||||
{
|
||||
size_t p;
|
||||
|
||||
remove_timeouts(ping);
|
||||
|
||||
/* Remove oldest ping if full buffer. */
|
||||
if (ping->num_pings == PING_NUM_MAX) {
|
||||
ping->num_pings--;
|
||||
ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX;
|
||||
}
|
||||
|
||||
/* Insert new ping at end of list. */
|
||||
p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX;
|
||||
|
||||
ping->pings[p].ip_port = ipp;
|
||||
ping->pings[p].timestamp = unix_time();
|
||||
ping->pings[p].id = random_64b();
|
||||
memcpy(ping->pings[p].shared_key, shared_encryption_key, crypto_box_BEFORENMBYTES);
|
||||
|
||||
ping->num_pings++;
|
||||
return ping->pings[p].id;
|
||||
}
|
||||
|
||||
/* checks if ip/port or ping_id are already in the list to ping
|
||||
* if both are set, both must match, otherwise the set must match
|
||||
*
|
||||
* returns 0 if neither is set or no match was found
|
||||
* returns the (index + 1) of the match if one was found
|
||||
*/
|
||||
static int is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id)
|
||||
{
|
||||
// O(n) TODO: Replace this with something else.
|
||||
|
||||
/* at least one MUST be set */
|
||||
uint8_t ip_valid = ip_isset(&ipp.ip);
|
||||
|
||||
if (!ip_valid && !ping_id)
|
||||
return 0;
|
||||
|
||||
size_t i;
|
||||
|
||||
remove_timeouts(ping);
|
||||
|
||||
for (i = 0; i < ping->num_pings; i++) {
|
||||
size_t id = (ping->pos_pings + i) % PING_NUM_MAX;
|
||||
|
||||
if (!ping_id || (ping->pings[id].id == ping_id))
|
||||
if (!ip_valid || ipport_equal(&ping->pings[id].ip_port, &ipp))
|
||||
return id + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES)
|
||||
#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
|
||||
#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + PING_PLAIN_SIZE + crypto_box_MACBYTES)
|
||||
#define PING_DATA_SIZE (CLIENT_ID_SIZE + sizeof(IP_Port))
|
||||
|
||||
int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id)
|
||||
{
|
||||
|
@ -153,7 +64,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id)
|
|||
int rc;
|
||||
uint64_t ping_id;
|
||||
|
||||
if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->dht->self_public_key))
|
||||
if (id_equal(client_id, ping->dht->self_public_key))
|
||||
return 1;
|
||||
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
|
@ -161,19 +72,29 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id)
|
|||
// generate key to encrypt ping_id with recipient privkey
|
||||
DHT_get_shared_key_sent(ping->dht, shared_key, client_id);
|
||||
// Generate random ping_id.
|
||||
ping_id = add_ping(ping, ipp, shared_key);
|
||||
uint8_t data[PING_DATA_SIZE];
|
||||
id_copy(data, client_id);
|
||||
memcpy(data + CLIENT_ID_SIZE, &ipp, sizeof(IP_Port));
|
||||
ping_id = ping_array_add(&ping->ping_array, data, sizeof(data));
|
||||
|
||||
if (ping_id == 0)
|
||||
return 1;
|
||||
|
||||
uint8_t ping_plain[PING_PLAIN_SIZE];
|
||||
ping_plain[0] = NET_PACKET_PING_REQUEST;
|
||||
memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
|
||||
|
||||
pk[0] = NET_PACKET_PING_REQUEST;
|
||||
id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey
|
||||
new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce
|
||||
|
||||
|
||||
rc = encrypt_data_fast(shared_key,
|
||||
pk + 1 + CLIENT_ID_SIZE,
|
||||
(uint8_t *) &ping_id, sizeof(ping_id),
|
||||
pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES);
|
||||
rc = encrypt_data_symmetric(shared_key,
|
||||
pk + 1 + CLIENT_ID_SIZE,
|
||||
ping_plain, sizeof(ping_plain),
|
||||
pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES);
|
||||
|
||||
if (rc != sizeof(ping_id) + crypto_box_MACBYTES)
|
||||
if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES)
|
||||
return 1;
|
||||
|
||||
return sendpacket(ping->dht->net, ipp, pk, sizeof(pk));
|
||||
|
@ -188,17 +109,21 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6
|
|||
if (id_equal(client_id, ping->dht->self_public_key))
|
||||
return 1;
|
||||
|
||||
uint8_t ping_plain[PING_PLAIN_SIZE];
|
||||
ping_plain[0] = NET_PACKET_PING_RESPONSE;
|
||||
memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
|
||||
|
||||
pk[0] = NET_PACKET_PING_RESPONSE;
|
||||
id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey
|
||||
new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce
|
||||
|
||||
// Encrypt ping_id using recipient privkey
|
||||
rc = encrypt_data_fast(shared_encryption_key,
|
||||
pk + 1 + CLIENT_ID_SIZE,
|
||||
(uint8_t *) &ping_id, sizeof(ping_id),
|
||||
pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES );
|
||||
rc = encrypt_data_symmetric(shared_encryption_key,
|
||||
pk + 1 + CLIENT_ID_SIZE,
|
||||
ping_plain, sizeof(ping_plain),
|
||||
pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES );
|
||||
|
||||
if (rc != sizeof(ping_id) + crypto_box_MACBYTES)
|
||||
if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES)
|
||||
return 1;
|
||||
|
||||
return sendpacket(ping->dht->net, ipp, pk, sizeof(pk));
|
||||
|
@ -208,7 +133,6 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint
|
|||
{
|
||||
DHT *dht = _dht;
|
||||
int rc;
|
||||
uint64_t ping_id;
|
||||
|
||||
if (length != DHT_PING_SIZE)
|
||||
return 1;
|
||||
|
@ -220,17 +144,23 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint
|
|||
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
|
||||
uint8_t ping_plain[PING_PLAIN_SIZE];
|
||||
// Decrypt ping_id
|
||||
DHT_get_shared_key_recv(dht, shared_key, packet + 1);
|
||||
rc = decrypt_data_fast(shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
sizeof(ping_id) + crypto_box_MACBYTES,
|
||||
(uint8_t *) &ping_id );
|
||||
rc = decrypt_data_symmetric(shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
PING_PLAIN_SIZE + crypto_box_MACBYTES,
|
||||
ping_plain );
|
||||
|
||||
if (rc != sizeof(ping_id))
|
||||
if (rc != sizeof(ping_plain))
|
||||
return 1;
|
||||
|
||||
if (ping_plain[0] != NET_PACKET_PING_REQUEST)
|
||||
return 1;
|
||||
|
||||
uint64_t ping_id;
|
||||
memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
|
||||
// Send response
|
||||
send_ping_response(ping, source, packet + 1, ping_id, shared_key);
|
||||
add_to_ping(ping, packet + 1, source);
|
||||
|
@ -242,7 +172,6 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin
|
|||
{
|
||||
DHT *dht = _dht;
|
||||
int rc;
|
||||
uint64_t ping_id;
|
||||
|
||||
if (length != DHT_PING_SIZE)
|
||||
return 1;
|
||||
|
@ -252,30 +181,71 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin
|
|||
if (id_equal(packet + 1, ping->dht->self_public_key))
|
||||
return 1;
|
||||
|
||||
int ping_index = is_pinging(ping, source, 0);
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
|
||||
if (!ping_index)
|
||||
return 1;
|
||||
// generate key to encrypt ping_id with recipient privkey
|
||||
DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1);
|
||||
|
||||
--ping_index;
|
||||
uint8_t ping_plain[PING_PLAIN_SIZE];
|
||||
// Decrypt ping_id
|
||||
rc = decrypt_data_fast(ping->pings[ping_index].shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
sizeof(ping_id) + crypto_box_MACBYTES,
|
||||
(uint8_t *) &ping_id);
|
||||
rc = decrypt_data_symmetric(shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
PING_PLAIN_SIZE + crypto_box_MACBYTES,
|
||||
ping_plain);
|
||||
|
||||
if (rc != sizeof(ping_id))
|
||||
if (rc != sizeof(ping_plain))
|
||||
return 1;
|
||||
|
||||
if (ping->pings[ping_index].id != ping_id)
|
||||
if (ping_plain[0] != NET_PACKET_PING_RESPONSE)
|
||||
return 1;
|
||||
|
||||
uint64_t ping_id;
|
||||
memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
|
||||
uint8_t data[PING_DATA_SIZE];
|
||||
|
||||
if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data))
|
||||
return 1;
|
||||
|
||||
if (!id_equal(packet + 1, data))
|
||||
return 1;
|
||||
|
||||
IP_Port ipp;
|
||||
memcpy(&ipp, data + CLIENT_ID_SIZE, sizeof(IP_Port));
|
||||
|
||||
if (!ipport_equal(&ipp, &source))
|
||||
return 1;
|
||||
|
||||
addto_lists(dht, source, packet + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if client_id with ip_port is in the list.
|
||||
*
|
||||
* return 1 if it is.
|
||||
* return 0 if it isn't.
|
||||
*/
|
||||
static int in_list(Client_data *list, uint32_t length, uint8_t *client_id, IP_Port ip_port)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
if (id_equal(list[i].client_id, client_id)) {
|
||||
IPPTsPng *ipptp;
|
||||
|
||||
if (ip_port.ip.family == AF_INET) {
|
||||
ipptp = &list[i].assoc4;
|
||||
} else {
|
||||
ipptp = &list[i].assoc6;
|
||||
}
|
||||
|
||||
if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add nodes to the to_ping list.
|
||||
* All nodes in this list are pinged every TIME_TO_PING seconds
|
||||
|
@ -292,6 +262,9 @@ int add_to_ping(PING *ping, uint8_t *client_id, IP_Port ip_port)
|
|||
if (!ip_isset(&ip_port.ip))
|
||||
return -1;
|
||||
|
||||
if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, client_id, ip_port))
|
||||
return -1;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_TO_PING; ++i) {
|
||||
|
@ -300,12 +273,18 @@ int add_to_ping(PING *ping, uint8_t *client_id, IP_Port ip_port)
|
|||
ipport_copy(&ping->to_ping[i].ip_port, &ip_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t r = rand();
|
||||
|
||||
for (i = 0; i < MAX_TO_PING; ++i) {
|
||||
if (id_closest(ping->dht->self_public_key, ping->to_ping[i].client_id, client_id) == 2) {
|
||||
memcpy(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE);
|
||||
ipport_copy(&ping->to_ping[i].ip_port, &ip_port);
|
||||
if (id_closest(ping->dht->self_public_key, ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id) == 2) {
|
||||
memcpy(ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id, CLIENT_ID_SIZE);
|
||||
ipport_copy(&ping->to_ping[(i + r) % MAX_TO_PING].ip_port, &ip_port);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -342,6 +321,11 @@ PING *new_ping(DHT *dht)
|
|||
if (ping == NULL)
|
||||
return NULL;
|
||||
|
||||
if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) {
|
||||
free(ping);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ping->dht = dht;
|
||||
networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
|
||||
networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
|
||||
|
@ -353,6 +337,7 @@ void kill_ping(PING *ping)
|
|||
{
|
||||
networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL);
|
||||
networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL);
|
||||
ping_array_free_all(&ping->ping_array);
|
||||
|
||||
free(ping);
|
||||
}
|
||||
|
|
162
toxcore/ping_array.c
Normal file
162
toxcore/ping_array.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/* ping_array.c
|
||||
*
|
||||
* Implementation of an efficient array to store that we pinged something.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2014 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ping_array.h"
|
||||
#include "crypto_core.h"
|
||||
#include "util.h"
|
||||
|
||||
static void clear_entry(Ping_Array *array, uint32_t index)
|
||||
{
|
||||
free(array->entries[index].data);
|
||||
array->entries[index].data = NULL;
|
||||
array->entries[index].length =
|
||||
array->entries[index].time =
|
||||
array->entries[index].ping_id = 0;
|
||||
}
|
||||
|
||||
/* Clear timed out entries.
|
||||
*/
|
||||
static void ping_array_clear_timedout(Ping_Array *array)
|
||||
{
|
||||
while (array->last_deleted != array->last_added) {
|
||||
uint32_t index = array->last_deleted % array->total_size;
|
||||
|
||||
if (!is_timeout(array->entries[index].time, array->timeout))
|
||||
break;
|
||||
|
||||
clear_entry(array, index);
|
||||
++array->last_deleted;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a data with length to the Ping_Array list and return a ping_id.
|
||||
*
|
||||
* return ping_id on success.
|
||||
* return 0 on failure.
|
||||
*/
|
||||
uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length)
|
||||
{
|
||||
ping_array_clear_timedout(array);
|
||||
uint32_t index = array->last_added % array->total_size;
|
||||
|
||||
if (array->entries[index].data != NULL) {
|
||||
array->last_deleted = array->last_added - array->total_size;
|
||||
clear_entry(array, index);
|
||||
}
|
||||
|
||||
array->entries[index].data = malloc(length);
|
||||
|
||||
if (array->entries[index].data == NULL)
|
||||
return 0;
|
||||
|
||||
memcpy(array->entries[index].data, data, length);
|
||||
array->entries[index].length = length;
|
||||
array->entries[index].time = unix_time();
|
||||
++array->last_added;
|
||||
uint64_t ping_id = random_64b();
|
||||
ping_id /= array->total_size;
|
||||
ping_id *= array->total_size;
|
||||
ping_id += index;
|
||||
|
||||
if (ping_id == 0)
|
||||
ping_id += array->total_size;
|
||||
|
||||
array->entries[index].ping_id = ping_id;
|
||||
return ping_id;
|
||||
}
|
||||
|
||||
|
||||
/* Check if ping_id is valid and not timed out.
|
||||
*
|
||||
* On success, copies the data into data of length,
|
||||
*
|
||||
* return length of data copied on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id)
|
||||
{
|
||||
if (ping_id == 0)
|
||||
return -1;
|
||||
|
||||
uint32_t index = ping_id % array->total_size;
|
||||
|
||||
if (array->entries[index].ping_id != ping_id)
|
||||
return -1;
|
||||
|
||||
if (is_timeout(array->entries[index].time, array->timeout))
|
||||
return -1;
|
||||
|
||||
if (array->entries[index].length > length)
|
||||
return -1;
|
||||
|
||||
if (array->entries[index].data == NULL)
|
||||
return -1;
|
||||
|
||||
memcpy(data, array->entries[index].data, array->entries[index].length);
|
||||
uint32_t len = array->entries[index].length;
|
||||
clear_entry(array, index);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Initialize a Ping_Array.
|
||||
* size represents the total size of the array and should be a power of 2.
|
||||
* timeout represents the maximum timeout in seconds for the entry.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout)
|
||||
{
|
||||
if (size == 0 || timeout == 0 || empty_array == NULL)
|
||||
return -1;
|
||||
|
||||
empty_array->entries = calloc(size * sizeof(Ping_Array_Entry), 1);
|
||||
|
||||
if (empty_array->entries == NULL)
|
||||
return -1;
|
||||
|
||||
empty_array->last_deleted = empty_array->last_added = 0;
|
||||
empty_array->total_size = size;
|
||||
empty_array->timeout = timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free all the allocated memory in a Ping_Array.
|
||||
*/
|
||||
void ping_array_free_all(Ping_Array *array)
|
||||
{
|
||||
while (array->last_deleted != array->last_added) {
|
||||
uint32_t index = array->last_deleted % array->total_size;
|
||||
clear_entry(array, index);
|
||||
++array->last_deleted;
|
||||
}
|
||||
|
||||
free(array->entries);
|
||||
array->entries = NULL;
|
||||
}
|
||||
|
75
toxcore/ping_array.h
Normal file
75
toxcore/ping_array.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* ping_array.h
|
||||
*
|
||||
* Implementation of an efficient array to store that we pinged something.
|
||||
*
|
||||
* Copyright (C) 2013 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef PING_ARRAY_H
|
||||
#define PING_ARRAY_H
|
||||
|
||||
#include "network.h"
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
uint32_t length;
|
||||
uint64_t time;
|
||||
uint64_t ping_id;
|
||||
} Ping_Array_Entry;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Ping_Array_Entry *entries;
|
||||
|
||||
uint32_t last_deleted; /* number representing the next entry to be deleted. */
|
||||
uint32_t last_added; /* number representing the last entry to be added. */
|
||||
uint32_t total_size; /* The length of entries */
|
||||
uint32_t timeout; /* The timeout after which entries are cleared. */
|
||||
} Ping_Array;
|
||||
|
||||
|
||||
/* Add a data with length to the Ping_Array list and return a ping_id.
|
||||
*
|
||||
* return ping_id on success.
|
||||
* return 0 on failure.
|
||||
*/
|
||||
uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length);
|
||||
|
||||
/* Check if ping_id is valid and not timed out.
|
||||
*
|
||||
* On success, copies the data into data of length,
|
||||
*
|
||||
* return length of data copied on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id);
|
||||
|
||||
/* Initialize a Ping_Array.
|
||||
* size represents the total size of the array and should be a power of 2.
|
||||
* timeout represents the maximum timeout in seconds for the entry.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout);
|
||||
|
||||
/* Free all the allocated memory in a Ping_Array.
|
||||
*/
|
||||
void ping_array_free_all(Ping_Array *array);
|
||||
|
||||
#endif
|
|
@ -187,7 +187,7 @@ int tox_set_name(Tox *tox, uint8_t *name, uint16_t length)
|
|||
}
|
||||
|
||||
/* Get your nickname.
|
||||
* m - The messanger context to use.
|
||||
* m - The messenger context to use.
|
||||
* name - Pointer to a string for the name. (must be at least MAX_NAME_LENGTH)
|
||||
*
|
||||
* return length of the name.
|
||||
|
@ -722,7 +722,7 @@ int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8
|
|||
*/
|
||||
int tox_file_data_size(Tox *tox, int32_t friendnumber)
|
||||
{
|
||||
return MAX_DATA_SIZE - crypto_box_MACBYTES - 3;
|
||||
return MAX_CRYPTO_DATA_SIZE - 2;
|
||||
}
|
||||
|
||||
/* Give the number of bytes left to be sent/received.
|
||||
|
@ -740,23 +740,38 @@ uint64_t tox_file_data_remaining(Tox *tox, int32_t friendnumber, uint8_t filenum
|
|||
|
||||
/***************END OF FILE SENDING FUNCTIONS******************/
|
||||
|
||||
/* Use these functions to bootstrap the client.
|
||||
* Sends a get nodes request to the given node with ip port and public_key.
|
||||
*/
|
||||
void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port _ip_port, uint8_t *public_key)
|
||||
/* TODO: expose this properly. */
|
||||
static int tox_add_tcp_relay(Tox *tox, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
IP_Port ip_port;
|
||||
memcpy(&ip_port, &_ip_port, sizeof(IP_Port));
|
||||
DHT_bootstrap(m->dht, ip_port, public_key);
|
||||
IP_Port ip_port_v64;
|
||||
IP *ip_extra = NULL;
|
||||
IP_Port ip_port_v4;
|
||||
ip_init(&ip_port_v64.ip, ipv6enabled);
|
||||
|
||||
if (ipv6enabled) {
|
||||
/* setup for getting BOTH: an IPv6 AND an IPv4 address */
|
||||
ip_port_v64.ip.family = AF_UNSPEC;
|
||||
ip_reset(&ip_port_v4.ip);
|
||||
ip_extra = &ip_port_v4.ip;
|
||||
}
|
||||
|
||||
if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
|
||||
ip_port_v64.port = port;
|
||||
add_tcp_relay(m->net_crypto, ip_port_v64, public_key);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int tox_bootstrap_from_address(Tox *tox, const char *address,
|
||||
uint8_t ipv6enabled, uint16_t port, uint8_t *public_key)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
tox_add_tcp_relay(tox, address, ipv6enabled, port, public_key);
|
||||
return DHT_bootstrap_from_address(m->dht, address, ipv6enabled, port, public_key);
|
||||
};
|
||||
}
|
||||
|
||||
/* return 0 if we are not connected to the DHT.
|
||||
* return 1 if we are.
|
||||
|
@ -842,33 +857,3 @@ int tox_load(Tox *tox, uint8_t *data, uint32_t length)
|
|||
Messenger *m = tox;
|
||||
return messenger_load(m, data, length);
|
||||
}
|
||||
|
||||
/* return the size of data to pass to messenger_save_encrypted(...)
|
||||
*/
|
||||
uint32_t tox_size_encrypted(Tox *tox)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return messenger_size_encrypted(m);
|
||||
}
|
||||
|
||||
/* Save the messenger, encrypting the data with key of length key_length
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return messenger_save_encrypted(m, data, key, key_length);
|
||||
}
|
||||
|
||||
/* Load the messenger from data of size length encrypted with key of key_length.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return messenger_load_encrypted(m, data, length, key, key_length);
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ int tox_set_name(Tox *tox, uint8_t *name, uint16_t length);
|
|||
|
||||
/*
|
||||
* Get your nickname.
|
||||
* m - The messanger context to use.
|
||||
* m - The messenger context to use.
|
||||
* name - needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
|
||||
*
|
||||
* return length of name.
|
||||
|
@ -515,11 +515,11 @@ uint32_t tox_get_chatlist(Tox *tox, int *out_list, uint32_t list_size);
|
|||
* tox_file_data_remaining(...) can be used to know how many bytes are left to send/receive.
|
||||
*
|
||||
* If the connection breaks during file sending (The other person goes offline without pausing the sending and then comes back)
|
||||
* the reciever must send a control packet with receive_send == 0 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being
|
||||
* a uint64_t (in host byte order) containing the number of bytes recieved.
|
||||
* the receiver must send a control packet with receive_send == 0 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being
|
||||
* a uint64_t (in host byte order) containing the number of bytes received.
|
||||
*
|
||||
* If the sender recieves this packet, he must send a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT
|
||||
* then he must start sending file data from the position (data , uint64_t in host byte order) recieved in the TOX_FILECONTROL_RESUME_BROKEN packet.
|
||||
* If the sender receives this packet, he must send a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT
|
||||
* then he must start sending file data from the position (data , uint64_t in host byte order) received in the TOX_FILECONTROL_RESUME_BROKEN packet.
|
||||
*
|
||||
* More to come...
|
||||
*/
|
||||
|
@ -601,43 +601,6 @@ uint64_t tox_file_data_remaining(Tox *tox, int32_t friendnumber, uint8_t filenum
|
|||
|
||||
/***************END OF FILE SENDING FUNCTIONS******************/
|
||||
|
||||
/* WARNING: DEPRECATED, DO NOT USE. */
|
||||
typedef union {
|
||||
uint8_t c[4];
|
||||
uint16_t s[2];
|
||||
uint32_t i;
|
||||
} tox_IP4;
|
||||
|
||||
typedef union {
|
||||
uint8_t uint8[16];
|
||||
uint16_t uint16[8];
|
||||
uint32_t uint32[4];
|
||||
struct in6_addr in6_addr;
|
||||
} tox_IP6;
|
||||
|
||||
typedef struct {
|
||||
uint8_t family;
|
||||
/* Not used for anything right now. */
|
||||
uint8_t padding[3];
|
||||
union {
|
||||
tox_IP4 ip4;
|
||||
tox_IP6 ip6;
|
||||
};
|
||||
} tox_IP;
|
||||
|
||||
/* will replace IP_Port as soon as the complete infrastructure is in place
|
||||
* removed the unused union and padding also */
|
||||
typedef struct {
|
||||
tox_IP ip;
|
||||
uint16_t port;
|
||||
} tox_IP_Port;
|
||||
/* WARNING: DEPRECATED, DO NOT USE. */
|
||||
/* Sends a "get nodes" request to the given node with ip, port and public_key
|
||||
* to setup connections
|
||||
*/
|
||||
void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
|
||||
|
||||
|
||||
/*
|
||||
* Use this function to bootstrap the client.
|
||||
*/
|
||||
|
@ -739,32 +702,6 @@ void tox_save(Tox *tox, uint8_t *data);
|
|||
*/
|
||||
int tox_load(Tox *tox, uint8_t *data, uint32_t length);
|
||||
|
||||
/**/
|
||||
|
||||
/* return the size of data to pass to messenger_save_encrypted(...)
|
||||
*/
|
||||
uint32_t tox_size_encrypted(Tox *tox);
|
||||
|
||||
/* Save the messenger, encrypting the data with key of length key_length
|
||||
*
|
||||
* This functions simply calls and then encrypt the output of tox_save(..)
|
||||
* with crypto_secretbox(...) from NaCl/libsodium with the key
|
||||
* given to crypto_secretbox(...) being the SHA256 sum of the key
|
||||
* passed to this function.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length);
|
||||
|
||||
/* Load the messenger from data of size length encrypted with key of key_length.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -36,10 +36,14 @@
|
|||
|
||||
/* don't call into system billions of times for no reason */
|
||||
static uint64_t unix_time_value;
|
||||
static uint64_t unix_base_time_value;
|
||||
|
||||
void unix_time_update()
|
||||
{
|
||||
unix_time_value = (uint64_t)time(NULL);
|
||||
if (unix_base_time_value == 0)
|
||||
unix_base_time_value = ((uint64_t)time(NULL) - (current_time_monotonic() / 1000ULL));
|
||||
|
||||
unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value;
|
||||
}
|
||||
|
||||
uint64_t unix_time()
|
||||
|
@ -49,7 +53,7 @@ uint64_t unix_time()
|
|||
|
||||
int is_timeout(uint64_t timestamp, uint64_t timeout)
|
||||
{
|
||||
return timestamp + timeout <= unix_time_value;
|
||||
return timestamp + timeout <= unix_time();
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,22 +71,17 @@ uint32_t id_copy(uint8_t *dest, uint8_t *src)
|
|||
|
||||
void host_to_net(uint8_t *num, uint16_t numbytes)
|
||||
{
|
||||
union {
|
||||
uint32_t i;
|
||||
uint8_t c[4];
|
||||
} a;
|
||||
a.i = 1;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
uint32_t i;
|
||||
uint8_t buff[numbytes];
|
||||
|
||||
if (a.c[0] == 1) {
|
||||
uint32_t i;
|
||||
uint8_t buff[numbytes];
|
||||
|
||||
for (i = 0; i < numbytes; ++i) {
|
||||
buff[i] = num[numbytes - i - 1];
|
||||
}
|
||||
|
||||
memcpy(num, buff, numbytes);
|
||||
for (i = 0; i < numbytes; ++i) {
|
||||
buff[i] = num[numbytes - i - 1];
|
||||
}
|
||||
|
||||
memcpy(num, buff, numbytes);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* state load/save */
|
||||
|
@ -99,11 +98,11 @@ int load_state(load_state_callback_func load_state_callback, void *outer,
|
|||
|
||||
uint16_t type;
|
||||
uint32_t length_sub, cookie_type;
|
||||
uint32_t size32 = sizeof(uint32_t), size_head = size32 * 2;
|
||||
uint32_t size_head = sizeof(uint32_t) * 2;
|
||||
|
||||
while (length >= size_head) {
|
||||
length_sub = *(uint32_t *)data;
|
||||
cookie_type = *(uint32_t *)(data + size32);
|
||||
memcpy(&length_sub, data, sizeof(length_sub));
|
||||
memcpy(&cookie_type, data + sizeof(length_sub), sizeof(cookie_type));
|
||||
data += size_head;
|
||||
length -= size_head;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user