Merge branch 'master' into new_api

This commit is contained in:
mannol 2015-04-29 01:02:47 +02:00
commit d8c34f4ffa
25 changed files with 3549 additions and 1175 deletions

View File

@ -171,15 +171,21 @@ Different: libvpx (webm) libopus pkgconfig gettext
(the libintl, from gettext, built into OS X 10.5 is missing libintl_setlocale, but the Macports build has it)
Verify where libintl is on your system: (MacPorts puts it in /opt/local)
$ for d in /usr/local/lib /opt/local/lib /usr/lib /lib; do ls -l $d/libintl.*; done
```
for d in /usr/local/lib /opt/local/lib /usr/lib /lib; do ls -l $d/libintl.*; done
```
Check if that copy has libintl_setlocale:
```
nm /opt/local/lib/libintl.8.dylib | grep _libintl_setlocale
```
Certain other tools may not be installed, or outdated, and should also be installed from MacPorts for simplicity: git cmake
If libsodium was installed with MacPorts, you may want to symlink the copy in /opt/local/lib to /usr/local/lib. That way you don't need special configure switches for toxcore to find libsodium, and every time MacPorts updates libsodium, the new version will be linked to toxcore every time you build:
```
ln -s /opt/local/lib/libsodium.dylib /usr/local/lib/libsodium.dylib
```
Much of the build can then be done as for other platforms: git clone, and so on. Differences will be noted with (OS X 10.5 specific)
@ -217,7 +223,9 @@ There is also a shell script called "osx_build_script_toxcore.txt" which automat
If after running ./configure you get an error about core being unable to find libsodium (and you have installed it) run the following in place of ./configure;
```
./configure --with-libsodium-headers=/usr/local/include/ --with-libsodium-libs=/usr/local/lib
```
Ensure you set the locations correctly depending on where you installed libsodium on your computer.

View File

@ -29,7 +29,7 @@ We want Tox to be as simple as possible while remaining as secure as possible.
The goal of this project is to create a configuration-free P2P Skype replacement. “Configuration-free” means that the user will simply have to open the program and will be capable of adding people and communicating with them without having to set up an account. There are many so-called Skype replacements, but all of them are either hard to configure for the normal user or suffer from being way too centralized.
## TODO:
- [TODO](/docs/TODO)
- [TODO](/docs/TODO.md)
## Documentation:

11
other/apidsl/README.md Normal file
View File

@ -0,0 +1,11 @@
This folder contains the input file that can be used to generate the tox.h api
with: https://github.com/iphydf/apidsl
You can also use the following command if you can't install it:
```
cat tox.in.h | curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl > tox.h
```
Note that the output must be passed through astyle with the config in
other/astyle/astylerc to generate the exact same file.

2076
other/apidsl/tox.in.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -336,3 +336,8 @@ void LANdiscovery_init(DHT *dht)
{
networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht);
}
void LANdiscovery_kill(DHT *dht)
{
networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, NULL, NULL);
}

View File

@ -37,6 +37,9 @@ int send_LANdiscovery(uint16_t port, DHT *dht);
/* Sets up packet handlers. */
void LANdiscovery_init(DHT *dht);
/* Clear packet handlers. */
void LANdiscovery_kill(DHT *dht);
/* checks if a given IP isn't routable
*
* return 0 if ip is a LAN ip.

View File

@ -433,14 +433,19 @@ int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber)
return -1;
if (m->friendlist[friendnumber].status == FRIEND_ONLINE) {
uint8_t direct_connected = 0;
_Bool direct_connected = 0;
unsigned int num_online_relays = 0;
crypto_connection_status(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
m->friendlist[friendnumber].friendcon_id), &direct_connected);
m->friendlist[friendnumber].friendcon_id), &direct_connected, &num_online_relays);
if (direct_connected) {
return CONNECTION_UDP;
} else {
return CONNECTION_TCP;
if (num_online_relays) {
return CONNECTION_TCP;
} else {
return CONNECTION_UNKNOWN;
}
}
} else {
return CONNECTION_NONE;
@ -493,10 +498,6 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con
uint32_t msg_id = ++m->friendlist[friendnumber].message_id;
if (msg_id == 0) {
msg_id = ++m->friendlist[friendnumber].message_id; // Otherwise, false error
}
add_receipt(m, friendnumber, packet_num, msg_id);
if (message_id)
@ -753,25 +754,6 @@ static int send_user_istyping(const Messenger *m, int32_t friendnumber, uint8_t
return write_cryptpacket_id(m, friendnumber, PACKET_ID_TYPING, &typing, sizeof(typing), 0);
}
static int send_relays(const Messenger *m, int32_t friendnumber)
{
Node_format nodes[MAX_SHARED_RELAYS];
uint8_t data[1024];
int n, length;
n = copy_connected_tcp_relays(m->net_crypto, nodes, MAX_SHARED_RELAYS);
length = pack_nodes(data, sizeof(data), nodes, n);
int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_SHARE_RELAYS, data, length, 0);
if (ret == 1)
m->friendlist[friendnumber].share_relays_lastsent = unix_time();
return ret;
}
static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length)
{
if (friend_not_valid(m, friendnumber))
@ -874,6 +856,14 @@ static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber)
if (ret == -1)
return;
if (ret == CONNECTION_UNKNOWN) {
if (last_connection_udp_tcp == CONNECTION_UDP) {
return;
} else {
ret = CONNECTION_TCP;
}
}
if (last_connection_udp_tcp != ret) {
if (m->friend_connectionstatuschange)
m->friend_connectionstatuschange(m, friendnumber, ret, m->friend_connectionstatuschange_userdata);
@ -1350,7 +1340,7 @@ int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin
if (m->friendlist[friendnumber].status != FRIEND_ONLINE)
return -2;
if (filenumber > MAX_CONCURRENT_FILE_PIPES)
if (filenumber >= MAX_CONCURRENT_FILE_PIPES)
return -3;
struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[filenumber];
@ -1775,15 +1765,6 @@ static int friend_already_added(const uint8_t *real_pk, void *data)
return -1;
}
/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
static void LANdiscovery(Messenger *m)
{
if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
send_LANdiscovery(htons(TOX_PORT_DEFAULT), m->dht);
m->last_LANdiscovery = unix_time();
}
}
/* Run this at startup. */
Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
{
@ -1852,7 +1833,6 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
m->options = *options;
friendreq_init(&(m->fr), m->fr_c);
LANdiscovery_init(m->dht);
set_nospam(&(m->fr), random_int());
set_filter_function(&(m->fr), &friend_already_added, m);
@ -2178,22 +2158,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
break;
}
case PACKET_ID_SHARE_RELAYS: {
Node_format nodes[MAX_SHARED_RELAYS];
int n;
if ((n = unpack_nodes(nodes, MAX_SHARED_RELAYS, NULL, data, data_length, 1)) == -1)
break;
int i;
for (i = 0; i < n; i++) {
add_tcp_relay(m->net_crypto, nodes[i].ip_port, nodes[i].public_key);
}
break;
}
default: {
handle_custom_lossless_packet(object, i, temp, len);
break;
@ -2251,10 +2215,6 @@ void do_friends(Messenger *m)
m->friendlist[i].user_istyping_sent = 1;
}
if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) {
send_relays(m, i);
}
check_friend_tcp_udp(m, i);
do_receipts(m, i);
do_reqchunk_filecb(m, i);
@ -2338,7 +2298,6 @@ void do_messenger(Messenger *m)
do_onion_client(m->onion_c);
do_friend_connections(m->fr_c);
do_friends(m);
LANdiscovery(m);
connection_status_cb(m);
#ifdef LOGGING

View File

@ -42,8 +42,7 @@ enum {
MESSAGE_ACTION
};
/* NOTE: Packet ids below 20 must never be used. */
#define PACKET_ID_SHARE_RELAYS 23
/* NOTE: Packet ids below 24 must never be used. */
#define PACKET_ID_ONLINE 24
#define PACKET_ID_OFFLINE 25
#define PACKET_ID_NICKNAME 48
@ -62,9 +61,6 @@ enum {
#define PACKET_ID_MESSAGE_GROUPCHAT 99
#define PACKET_ID_LOSSY_GROUPCHAT 199
/* Max number of tcp relays sent to friends */
#define MAX_SHARED_RELAYS 16
/* All packets starting with a byte in this range can be used for anything. */
#define PACKET_ID_LOSSLESS_RANGE_START 160
#define PACKET_ID_LOSSLESS_RANGE_SIZE 32
@ -110,13 +106,11 @@ enum {
/* Default start timeout in seconds between friend requests. */
#define FRIENDREQUEST_TIMEOUT 5;
/* Interval between the sending of tcp relay information */
#define FRIEND_SHARE_RELAYS_INTERVAL (5 * 60)
enum {
CONNECTION_NONE,
CONNECTION_TCP,
CONNECTION_UDP
CONNECTION_UDP,
CONNECTION_UNKNOWN
};
/* USERSTATUS -
@ -199,7 +193,6 @@ typedef struct {
uint32_t message_id; // a semi-unique id used in read receipts.
uint32_t friendrequest_nospam; // The nospam number used in the friend request.
uint64_t last_seen_time;
uint64_t share_relays_lastsent;
uint8_t last_connection_udp_tcp;
struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
unsigned int num_sending_files;
@ -241,8 +234,6 @@ struct Messenger {
uint32_t numonline_friends;
uint64_t last_LANdiscovery;
#define NUM_SAVED_TCP_RELAYS 8
uint8_t has_added_relays; // If the first connection has occurred in do_messenger
Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config

View File

@ -87,7 +87,7 @@ static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_con
const int written = snprintf((char *)TCP_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two,
ip, port, three);
if (written < 0) {
if (written < 0 || MAX_PACKET_SIZE < written) {
return 0;
}

View File

@ -78,10 +78,6 @@ typedef struct {
uint64_t ping_response_id;
uint64_t ping_request_id;
//TODO: remove
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];

View File

@ -26,6 +26,7 @@
#endif
#include "TCP_connection.h"
#include "util.h"
/* Set the size of the array to num.
*
@ -212,6 +213,8 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
unsigned int i;
int ret = -1;
_Bool limit_reached = 0;
for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
uint8_t status = con_to->connections[i].status;
@ -227,6 +230,10 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
ret = send_data(tcp_con->connection, connection_id, packet, length);
if (ret == 0) {
limit_reached = 1;
}
if (ret == 1) {
break;
}
@ -235,7 +242,10 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
if (ret == 1) {
return 0;
} else {
} else if (!limit_reached) {
ret = 0;
/* Send oob packets to all relays tied to the connection. */
for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
uint8_t status = con_to->connections[i].status;
@ -249,19 +259,19 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
continue;
}
ret = send_oob_packet(tcp_con->connection, con_to->public_key, packet, length);
if (ret == 1) {
break;
if (send_oob_packet(tcp_con->connection, con_to->public_key, packet, length) == 1) {
ret += 1;
}
}
}
if (ret == 1) {
if (ret >= 1) {
return 0;
} else {
return -1;
}
} else {
return -1;
}
}
@ -273,13 +283,15 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
* return TCP connection number on success.
* return -1 on failure.
*/
int get_random_tcp_conn_number(TCP_Connections *tcp_c)
int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c)
{
unsigned int i, r = rand();
for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
if (tcp_c->tcp_connections[(i + r) % tcp_c->tcp_connections_length].status == TCP_CONN_CONNECTED) {
return ((i + r) % tcp_c->tcp_connections_length);
unsigned int index = ((i + r) % tcp_c->tcp_connections_length);
if (tcp_c->tcp_connections[index].onion && tcp_c->tcp_connections[index].status == TCP_CONN_CONNECTED) {
return index;
}
}
@ -321,6 +333,9 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num
if (!tcp_con)
return -1;
if (tcp_con->status != TCP_CONN_CONNECTED)
return -1;
int ret = send_oob_packet(tcp_con->connection, public_key, packet, length);
if (ret == 1)
@ -392,8 +407,14 @@ static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *rela
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con) {
if (memcmp(tcp_con->connection->public_key, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) {
return i;
if (tcp_con->status == TCP_CONN_SLEEPING) {
if (memcmp(tcp_con->relay_pk, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) {
return i;
}
} else {
if (memcmp(tcp_con->connection->public_key, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) {
return i;
}
}
}
}
@ -451,14 +472,86 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id);
}
--tcp_con->lock_count;
if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
--tcp_con->lock_count;
if (con_to->status == TCP_CONN_SLEEPING) {
--tcp_con->sleep_count;
}
}
}
}
return wipe_connection(tcp_c, connections_number);
}
static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, int tcp_connections_number)
/* Set connection status.
*
* status of 1 means we are using the connection.
* status of 0 means we are not using it.
*
* Unused tcp connections will be disconnected from but kept in case they are needed.
*
* return 0 on success.
* return -1 on failure.
*/
int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, _Bool status)
{
TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
if (!con_to)
return -1;
if (status) {
/* Conection is unsleeping. */
if (con_to->status != TCP_CONN_SLEEPING)
return -1;
unsigned int i;
for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
if (con_to->connections[i].tcp_connection) {
unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
if (!tcp_con)
continue;
if (tcp_con->status == TCP_CONN_SLEEPING) {
tcp_con->unsleep = 1;
}
}
}
con_to->status = TCP_CONN_VALID;
return 0;
} else {
/* Conection is going to sleep. */
if (con_to->status != TCP_CONN_VALID)
return -1;
unsigned int i;
for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
if (con_to->connections[i].tcp_connection) {
unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
if (!tcp_con)
continue;
if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
++tcp_con->sleep_count;
}
}
}
con_to->status = TCP_CONN_SLEEPING;
return 0;
}
}
static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
{
unsigned int i;
@ -474,7 +567,7 @@ static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, int tcp_connectio
/* return index on success.
* return -1 on failure.
*/
static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, int tcp_connections_number)
static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
{
unsigned int i;
@ -496,7 +589,7 @@ static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, int tcp_connect
/* return index on success.
* return -1 on failure.
*/
static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, int tcp_connections_number)
static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
{
unsigned int i;
@ -512,16 +605,39 @@ static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, int tcp_connec
return -1;
}
/* return number of online connections on success.
* return -1 on failure.
*/
static unsigned int online_tcp_connection_from_conn(TCP_Connection_to *con_to)
{
unsigned int i, count = 0;
for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
if (con_to->connections[i].tcp_connection) {
if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
++count;
}
}
}
return count;
}
/* return index on success.
* return -1 on failure.
*/
static int set_tcp_connection_status(TCP_Connection_to *con_to, int tcp_connections_number, unsigned int status,
uint8_t connection_id)
static int set_tcp_connection_status(TCP_Connection_to *con_to, unsigned int tcp_connections_number,
unsigned int status, uint8_t connection_id)
{
unsigned int i;
for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
if (con_to->connections[i].status == status) {
return -1;
}
con_to->connections[i].status = status;
con_to->connections[i].connection_id = connection_id;
return i;
@ -553,11 +669,130 @@ static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections
}
}
if (tcp_con->onion) {
--tcp_c->onion_num_conns;
}
kill_TCP_connection(tcp_con->connection);
return wipe_tcp_connection(tcp_c, tcp_connections_number);
}
static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
{
TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
if (!tcp_con)
return -1;
if (tcp_con->status == TCP_CONN_SLEEPING)
return -1;
IP_Port ip_port = tcp_con->connection->ip_port;
uint8_t relay_pk[crypto_box_PUBLICKEYBYTES];
memcpy(relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES);
kill_TCP_connection(tcp_con->connection);
tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->dht->self_public_key, tcp_c->dht->self_secret_key,
&tcp_c->proxy_info);
if (!tcp_con->connection) {
kill_tcp_relay_connection(tcp_c, tcp_connections_number);
return -1;
}
unsigned int i;
for (i = 0; i < tcp_c->connections_length; ++i) {
TCP_Connection_to *con_to = get_connection(tcp_c, i);
if (con_to) {
set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
}
}
if (tcp_con->onion) {
--tcp_c->onion_num_conns;
tcp_con->onion = 0;
}
tcp_con->lock_count = 0;
tcp_con->sleep_count = 0;
tcp_con->connected_time = 0;
tcp_con->status = TCP_CONN_VALID;
tcp_con->unsleep = 0;
return 0;
}
static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
{
TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
if (!tcp_con)
return -1;
if (tcp_con->status != TCP_CONN_CONNECTED)
return -1;
if (tcp_con->lock_count != tcp_con->sleep_count)
return -1;
tcp_con->ip_port = tcp_con->connection->ip_port;
memcpy(tcp_con->relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES);
kill_TCP_connection(tcp_con->connection);
tcp_con->connection = NULL;
unsigned int i;
for (i = 0; i < tcp_c->connections_length; ++i) {
TCP_Connection_to *con_to = get_connection(tcp_c, i);
if (con_to) {
set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
}
}
if (tcp_con->onion) {
--tcp_c->onion_num_conns;
tcp_con->onion = 0;
}
tcp_con->lock_count = 0;
tcp_con->sleep_count = 0;
tcp_con->connected_time = 0;
tcp_con->status = TCP_CONN_SLEEPING;
tcp_con->unsleep = 0;
return 0;
}
static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
{
TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
if (!tcp_con)
return -1;
if (tcp_con->status != TCP_CONN_SLEEPING)
return -1;
tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->dht->self_public_key,
tcp_c->dht->self_secret_key, &tcp_c->proxy_info);
if (!tcp_con->connection) {
kill_tcp_relay_connection(tcp_c, tcp_connections_number);
return -1;
}
tcp_con->lock_count = 0;
tcp_con->sleep_count = 0;
tcp_con->connected_time = 0;
tcp_con->status = TCP_CONN_VALID;
tcp_con->unsleep = 0;
return 0;
}
/* Send a TCP routing request.
*
* return 0 on success.
@ -570,6 +805,9 @@ static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connec
if (!tcp_con)
return -1;
if (tcp_con->status == TCP_CONN_SLEEPING)
return -1;
if (send_routing_request(tcp_con->connection, public_key) != 1)
return -1;
@ -592,8 +830,6 @@ static int tcp_response_callback(void *object, uint8_t connection_id, const uint
if (connections_number == -1)
return -1;
set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
if (con_to == NULL)
@ -602,6 +838,8 @@ static int tcp_response_callback(void *object, uint8_t connection_id, const uint
if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1)
return -1;
set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
return 0;
}
@ -621,10 +859,20 @@ static int tcp_status_callback(void *object, uint32_t number, uint8_t connection
if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1)
return -1;
--tcp_con->lock_count;
if (con_to->status == TCP_CONN_SLEEPING) {
--tcp_con->sleep_count;
}
} else if (status == 2) {
if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1)
return -1;
++tcp_con->lock_count;
if (con_to->status == TCP_CONN_SLEEPING) {
++tcp_con->sleep_count;
}
}
return 0;
@ -673,11 +921,13 @@ static int tcp_oob_callback(void *object, const uint8_t *public_key, const uint8
/* TODO: optimize */
int connections_number = find_tcp_connection_to(tcp_c, public_key);
if (connections_number == -1) {
TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
if (con_to && tcp_connection_in_conn(con_to, tcp_connections_number)) {
return tcp_data_callback(object, connections_number, 0, data, length);
} else {
if (tcp_c->tcp_oob_callback)
tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length);
} else {
return tcp_data_callback(object, connections_number, 0, data, length);
}
return 0;
@ -725,20 +975,35 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe
if (!tcp_con)
return -1;
unsigned int i;
unsigned int i, sent = 0;
for (i = 0; i < tcp_c->connections_length; ++i) {
TCP_Connection_to *con_to = get_connection(tcp_c, i);
if (con_to) {
if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key);
if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
++sent;
}
}
}
}
tcp_relay_set_callbacks(tcp_c, tcp_connections_number);
tcp_con->status = TCP_CONN_CONNECTED;
/* If this connection isn't used by any connection, we don't need to wait for them to come online. */
if (sent) {
tcp_con->connected_time = unix_time();
} else {
tcp_con->connected_time = 0;
}
if (tcp_c->onion_status && tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
tcp_con->onion = 1;
++tcp_c->onion_num_conns;
}
return 0;
}
@ -807,13 +1072,17 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb
if (!tcp_con)
return -1;
if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) {
tcp_con->unsleep = 1;
}
if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1)
return -1;
++tcp_con->lock_count;
if (tcp_con->status == TCP_CONN_CONNECTED) {
send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key);
if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
tcp_con->connected_time = unix_time();
}
}
return 0;
@ -836,22 +1105,38 @@ int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_
if (tcp_connections_number != -1) {
return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number);
} else {
int tcp_connections_number = add_tcp_relay(tcp_c, ip_port, relay_pk);
if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
if (online_tcp_connection_from_conn(con_to) >= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
return -1;
}
int tcp_connections_number = add_tcp_relay(tcp_c, ip_port, relay_pk);
TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
if (!tcp_con)
return -1;
++tcp_con->lock_count;
if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
return -1;
}
return 0;
}
}
/* return number of online tcp relays tied to the connection on success.
* return 0 on failure.
*/
unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number)
{
TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
if (!con_to)
return 0;
return online_tcp_connection_from_conn(con_to);
}
/* Copy a maximum of max_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.
*
@ -860,10 +1145,10 @@ int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_
*/
unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num)
{
unsigned int i, copied = 0;
unsigned int i, copied = 0, r = rand();
for (i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) {
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length);
if (!tcp_con) {
continue;
@ -886,7 +1171,74 @@ unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_
return copied;
}
TCP_Connections *new_tcp_connections(DHT *dht)
/* Set if we want TCP_connection to allocate some connection for onion use.
*
* If status is 1, allocate some connections. if status is 0, don't.
*
* return 0 on success.
* return -1 on failure.
*/
int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status)
{
if (tcp_c->onion_status == status)
return -1;
if (status) {
unsigned int i;
for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con) {
if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion) {
++tcp_c->onion_num_conns;
tcp_con->onion = 1;
}
}
if (tcp_c->onion_num_conns >= NUM_ONION_TCP_CONNECTIONS)
break;
}
if (tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
unsigned int wakeup = NUM_ONION_TCP_CONNECTIONS - tcp_c->onion_num_conns;
for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con) {
if (tcp_con->status == TCP_CONN_SLEEPING) {
tcp_con->unsleep = 1;
}
}
if (!wakeup)
break;
}
}
tcp_c->onion_status = 1;
} else {
unsigned int i;
for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con) {
if (tcp_con->onion) {
--tcp_c->onion_num_conns;
tcp_con->onion = 0;
}
}
}
tcp_c->onion_status = 0;
}
return 0;
}
TCP_Connections *new_tcp_connections(DHT *dht, TCP_Proxy_Info *proxy_info)
{
if (dht == NULL)
return NULL;
@ -897,6 +1249,8 @@ TCP_Connections *new_tcp_connections(DHT *dht)
return NULL;
temp->dht = dht;
temp->proxy_info = *proxy_info;
return temp;
}
@ -908,18 +1262,35 @@ static void do_tcp_conns(TCP_Connections *tcp_c)
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con) {
do_TCP_connection(tcp_con->connection);
if (tcp_con->status != TCP_CONN_SLEEPING) {
do_TCP_connection(tcp_con->connection);
/* callbacks can change TCP connection address. */
tcp_con = get_tcp_connection(tcp_c, i);
/* callbacks can change TCP connection address. */
tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) {
kill_tcp_relay_connection(tcp_c, i);
continue;
if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) {
if (tcp_con->status == TCP_CONN_CONNECTED) {
reconnect_tcp_relay_connection(tcp_c, i);
} else {
kill_tcp_relay_connection(tcp_c, i);
}
continue;
}
if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) {
tcp_relay_on_online(tcp_c, i);
}
if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count
&& tcp_con->lock_count == tcp_con->sleep_count
&& is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
sleep_tcp_relay_connection(tcp_c, i);
}
}
if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) {
tcp_relay_on_online(tcp_c, i);
if (tcp_con->status == TCP_CONN_SLEEPING && tcp_con->unsleep) {
unsleep_tcp_relay_connection(tcp_c, i);
}
}
}
@ -927,27 +1298,42 @@ static void do_tcp_conns(TCP_Connections *tcp_c)
static void kill_nonused_tcp(TCP_Connections *tcp_c)
{
unsigned int i, num_online = 0;
if (tcp_c->tcp_connections_length == 0)
return;
unsigned int i, num_online = 0, num_kill = 0, to_kill[tcp_c->tcp_connections_length];
for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con) {
if (tcp_con->status == TCP_CONN_CONNECTED) {
if (!tcp_con->lock_count && num_online >= MAX_FRIEND_TCP_CONNECTIONS) {
kill_tcp_relay_connection(tcp_c, i);
continue;
if (!tcp_con->onion && !tcp_con->lock_count && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
to_kill[num_kill] = i;
++num_kill;
}
++num_online;
}
}
}
if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
return;
} else {
unsigned int n = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS;
if (n < num_kill)
num_kill = n;
}
for (i = 0; i < num_kill; ++i) {
kill_tcp_relay_connection(tcp_c, to_kill[i]);
}
}
void do_tcp_connections(TCP_Connections *tcp_c)
{
//TODO reconnect to TCP relays if disconnects happen.
do_tcp_conns(tcp_c);
kill_nonused_tcp(tcp_c);
}

View File

@ -28,14 +28,28 @@
#define TCP_CONN_NONE 0
#define TCP_CONN_VALID 1
/* NOTE: only used by TCP_con */
#define TCP_CONN_CONNECTED 2
/* Connection is not connected but can be quickly reconnected in case it is needed. */
#define TCP_CONN_SLEEPING 3
#define TCP_CONNECTIONS_STATUS_NONE 0
#define TCP_CONNECTIONS_STATUS_REGISTERED 1
#define TCP_CONNECTIONS_STATUS_ONLINE 2
#define MAX_FRIEND_TCP_CONNECTIONS 4
#define MAX_FRIEND_TCP_CONNECTIONS 6
/* Time until connection to friend gets killed (if it doesn't get locked withing that time) */
#define TCP_CONNECTION_ANNOUNCE_TIMEOUT (TCP_CONNECTION_TIMEOUT)
/* The amount of recommended connections for each friend
NOTE: Must be at most (MAX_FRIEND_TCP_CONNECTIONS / 2) */
#define RECOMMENDED_FRIEND_TCP_CONNECTIONS (MAX_FRIEND_TCP_CONNECTIONS / 2)
/* Number of TCP connections used for onion purposes. */
#define NUM_ONION_TCP_CONNECTIONS RECOMMENDED_FRIEND_TCP_CONNECTIONS
typedef struct {
uint8_t status;
@ -53,7 +67,15 @@ typedef struct {
typedef struct {
uint8_t status;
TCP_Client_Connection *connection;
uint64_t connected_time;
uint32_t lock_count;
uint32_t sleep_count;
_Bool onion;
/* Only used when connection is sleeping. */
IP_Port ip_port;
uint8_t relay_pk[crypto_box_PUBLICKEYBYTES];
_Bool unsleep; /* set to 1 to unsleep connection. */
} TCP_con;
typedef struct {
@ -76,6 +98,9 @@ typedef struct {
void *tcp_onion_callback_object;
TCP_Proxy_Info proxy_info;
_Bool onion_status;
uint16_t onion_num_conns;
} TCP_Connections;
/* Send a packet to the TCP connection.
@ -93,7 +118,7 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
* return TCP connection number on success.
* return -1 on failure.
*/
int get_random_tcp_conn_number(TCP_Connections *tcp_c);
int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c);
/* Send an onion packet via the TCP relay corresponding to tcp_connections_number.
*
@ -103,6 +128,15 @@ int get_random_tcp_conn_number(TCP_Connections *tcp_c);
int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *data,
uint16_t length);
/* Set if we want TCP_connection to allocate some connection for onion use.
*
* If status is 1, allocate some connections. if status is 0, don't.
*
* return 0 on success.
* return -1 on failure.
*/
int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status);
/* Send an oob packet via the TCP relay corresponding to tcp_connections_number.
*
* return 0 on success.
@ -140,6 +174,23 @@ int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int
*/
int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number);
/* Set connection status.
*
* status of 1 means we are using the connection.
* status of 0 means we are not using it.
*
* Unused tcp connections will be disconnected from but kept in case they are needed.
*
* return 0 on success.
* return -1 on failure.
*/
int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, _Bool status);
/* return number of online tcp relays tied to the connection on success.
* return 0 on failure.
*/
unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number);
/* Add a TCP relay tied to a connection.
*
* NOTE: This can only be used during the tcp_oob_callback.
@ -172,7 +223,7 @@ int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t
*/
unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num);
TCP_Connections *new_tcp_connections(DHT *dht);
TCP_Connections *new_tcp_connections(DHT *dht, TCP_Proxy_Info *proxy_info);
void do_tcp_connections(TCP_Connections *tcp_c);
void kill_tcp_connections(TCP_Connections *tcp_c);

View File

@ -29,26 +29,16 @@
#include "crypto_core.h"
#if crypto_box_PUBLICKEYBYTES != 32
#error crypto_box_PUBLICKEYBYTES is required to be 32 bytes for public_key_cmp to work,
#endif
/* Use this instead of memcmp; not vulnerable to timing attacks.
/* compare 2 public keys of length crypto_box_PUBLICKEYBYTES, not vulnerable to timing attacks.
returns 0 if both mem locations of length are equal,
return -1 if they are not. */
int crypto_cmp(const uint8_t *mem1, const uint8_t *mem2, size_t length)
int public_key_cmp(const uint8_t *pk1, const uint8_t *pk2)
{
if (length == 16) {
return crypto_verify_16(mem1, mem2);
} else if (length == 32) {
return crypto_verify_32(mem1, mem2);
}
unsigned int check = 0;
size_t i;
for (i = 0; i < length; ++i) {
check |= mem1[i] ^ mem2[i];
}
return (1 & ((check - 1) >> 8)) - 1;
return crypto_verify_32(pk1, pk2);
}
/* return a random number.

View File

@ -40,10 +40,10 @@
#define crypto_box_KEYBYTES (crypto_box_BEFORENMBYTES)
/* Use this instead of memcmp; not vulnerable to timing attacks.
/* compare 2 public keys of length crypto_box_PUBLICKEYBYTES, not vulnerable to timing attacks.
returns 0 if both mem locations of length are equal,
return -1 if they are not. */
int crypto_cmp(const uint8_t *mem1, const uint8_t *mem2, size_t length);
int public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);
/* return a random number.
*

View File

@ -146,6 +146,95 @@ int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk)
return -1;
}
/* Add a TCP relay associated to the friend.
*
* return -1 on failure.
* return 0 on success.
*/
int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key)
{
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
if (!friend_con)
return -1;
unsigned int i;
uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS;
for (i = 0; i < FRIEND_MAX_STORED_TCP_RELAYS; ++i) {
if (friend_con->tcp_relays[i].ip_port.ip.family != 0
&& memcmp(friend_con->tcp_relays[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
memset(&friend_con->tcp_relays[i], 0, sizeof(Node_format));
}
}
friend_con->tcp_relays[index].ip_port = ip_port;
memcpy(friend_con->tcp_relays[index].public_key, public_key, crypto_box_PUBLICKEYBYTES);
++friend_con->tcp_relay_counter;
return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key);
}
/* Connect to number saved relays for friend. */
static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number)
{
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
if (!friend_con)
return;
unsigned int i;
for (i = 0; (i < FRIEND_MAX_STORED_TCP_RELAYS) && (number != 0); ++i) {
uint16_t index = (friend_con->tcp_relay_counter - (i + 1)) % FRIEND_MAX_STORED_TCP_RELAYS;
if (friend_con->tcp_relays[index].ip_port.ip.family) {
if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->tcp_relays[index].ip_port,
friend_con->tcp_relays[index].public_key) == 0) {
--number;
}
}
}
}
static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)
{
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
if (!friend_con)
return 0;
Node_format nodes[MAX_SHARED_RELAYS];
uint8_t data[1024];
int n, length;
n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS);
unsigned int i;
for (i = 0; i < n; ++i) {
/* Associated the relays being sent with this connection.
On receiving the peer will do the same which will establish the connection. */
friend_add_tcp_relay(fr_c, friendcon_id, nodes[i].ip_port, nodes[i].public_key);
}
length = pack_nodes(data + 1, sizeof(data) - 1, nodes, n);
if (length <= 0)
return 0;
data[0] = PACKET_ID_SHARE_RELAYS;
++length;
if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) {
friend_con->share_relays_lastsent = unix_time();
return 1;
}
return 0;
}
/* callback for recv TCP relay nodes. */
static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key)
{
@ -156,7 +245,7 @@ static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_por
return -1;
if (friend_con->crypt_connection_id != -1) {
return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key);
return friend_add_tcp_relay(fr_c, number, ip_port, public_key);
} else {
return add_tcp_relay(fr_c->net_crypto, ip_port, public_key);
}
@ -181,19 +270,14 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
friend_con->dht_ip_port_lastrecv = unix_time();
}
/* Callback for dht public key changes. */
static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key)
static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
{
Friend_Connections *fr_c = object;
Friend_Conn *friend_con = get_conn(fr_c, number);
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
if (!friend_con)
return;
friend_con->dht_ping_lastrecv = unix_time();
if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0)
return;
friend_con->dht_pk_lastrecv = unix_time();
if (friend_con->dht_lock) {
if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) {
@ -204,15 +288,7 @@ static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_pub
friend_con->dht_lock = 0;
}
DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, object, number, &friend_con->dht_lock);
if (friend_con->crypt_connection_id == -1) {
friend_new_connection(fr_c, number);
}
set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, dht_public_key);
onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock);
memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES);
}
@ -230,11 +306,12 @@ static int handle_status(void *object, int number, uint8_t status)
call_cb = 1;
friend_con->status = FRIENDCONN_STATUS_CONNECTED;
friend_con->ping_lastrecv = unix_time();
friend_con->share_relays_lastsent = 0;
onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
} else { /* Went offline. */
if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) {
call_cb = 1;
friend_con->dht_ping_lastrecv = unix_time();
friend_con->dht_pk_lastrecv = unix_time();
onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
}
@ -255,6 +332,31 @@ static int handle_status(void *object, int number, uint8_t status)
return 0;
}
/* Callback for dht public key changes. */
static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key)
{
Friend_Connections *fr_c = object;
Friend_Conn *friend_con = get_conn(fr_c, number);
if (!friend_con)
return;
if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0)
return;
change_dht_pk(fr_c, number, dht_public_key);
/* if pk changed, create a new connection.*/
if (friend_con->crypt_connection_id != -1) {
crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
friend_con->crypt_connection_id = -1;
handle_status(object, number, 0); /* Going offline. */
}
friend_new_connection(fr_c, number);
onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
}
static int handle_packet(void *object, int number, uint8_t *data, uint16_t length)
{
if (length == 0)
@ -263,18 +365,30 @@ static int handle_packet(void *object, int number, uint8_t *data, uint16_t lengt
Friend_Connections *fr_c = object;
Friend_Conn *friend_con = get_conn(fr_c, number);
if (!friend_con)
return -1;
if (data[0] == PACKET_ID_FRIEND_REQUESTS) {
if (fr_c->fr_request_callback)
fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length);
return 0;
}
if (!friend_con)
return -1;
if (data[0] == PACKET_ID_ALIVE) {
} else if (data[0] == PACKET_ID_ALIVE) {
friend_con->ping_lastrecv = unix_time();
return 0;
} else if (data[0] == PACKET_ID_SHARE_RELAYS) {
Node_format nodes[MAX_SHARED_RELAYS];
int n;
if ((n = unpack_nodes(nodes, MAX_SHARED_RELAYS, NULL, data + 1, length - 1, 1)) == -1)
return -1;
int j;
for (j = 0; j < n; j++) {
friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key);
}
return 0;
}
@ -333,6 +447,11 @@ static int handle_new_connections(void *object, New_Connection *n_c)
return -1;
int id = accept_crypto_connection(fr_c->net_crypto, n_c);
if (id == -1) {
return -1;
}
connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id);
connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id);
connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id);
@ -345,7 +464,9 @@ static int handle_new_connections(void *object, New_Connection *n_c)
friend_con->dht_ip_port_lastrecv = unix_time();
}
dht_pk_callback(fr_c, friendcon_id, n_c->dht_public_key);
if (memcmp(friend_con->dht_temp_pk, n_c->dht_public_key, crypto_box_PUBLICKEYBYTES) != 0) {
change_dht_pk(fr_c, friendcon_id, n_c->dht_public_key);
}
nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id);
return 0;
@ -365,7 +486,12 @@ static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id)
return -1;
}
int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key);
/* If dht_temp_pk does not contains a pk. */
if (!friend_con->dht_lock) {
return -1;
}
int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key, friend_con->dht_temp_pk);
if (id == -1)
return -1;
@ -632,10 +758,20 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c)
temp->onion_c = onion_c;
new_connection_handler(temp->net_crypto, &handle_new_connections, temp);
LANdiscovery_init(temp->dht);
return temp;
}
/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
static void LANdiscovery(Friend_Connections *fr_c)
{
if (fr_c->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
send_LANdiscovery(htons(TOX_PORT_DEFAULT), fr_c->dht);
fr_c->last_LANdiscovery = unix_time();
}
}
/* main friend_connections loop. */
void do_friend_connections(Friend_Connections *fr_c)
{
@ -647,7 +783,7 @@ void do_friend_connections(Friend_Connections *fr_c)
if (friend_con) {
if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
if (friend_con->dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
if (friend_con->dht_lock) {
DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
friend_con->dht_lock = 0;
@ -660,8 +796,8 @@ void do_friend_connections(Friend_Connections *fr_c)
if (friend_con->dht_lock) {
if (friend_new_connection(fr_c, i) == 0) {
set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_temp_pk);
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port);
connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
}
}
@ -670,6 +806,10 @@ void do_friend_connections(Friend_Connections *fr_c)
send_ping(fr_c, i);
}
if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) {
send_relays(fr_c, i);
}
if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
/* If we stopped receiving ping packets, kill it. */
crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
@ -679,6 +819,8 @@ void do_friend_connections(Friend_Connections *fr_c)
}
}
}
LANdiscovery(fr_c);
}
/* Free everything related with friend_connections. */
@ -693,5 +835,6 @@ void kill_friend_connections(Friend_Connections *fr_c)
kill_friend_connection(fr_c, i);
}
LANdiscovery_kill(fr_c->dht);
free(fr_c);
}

View File

@ -36,6 +36,7 @@
#define GROUPCHAT_CALLBACK_INDEX 1
#define PACKET_ID_ALIVE 16
#define PACKET_ID_SHARE_RELAYS 17
#define PACKET_ID_FRIEND_REQUESTS 18
/* Interval between the sending of ping packets. */
@ -47,6 +48,14 @@
/* Time before friend is removed from the DHT after last hearing about him. */
#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT
#define FRIEND_MAX_STORED_TCP_RELAYS (MAX_FRIEND_TCP_CONNECTIONS * 4)
/* Max number of tcp relays sent to friends */
#define MAX_SHARED_RELAYS (RECOMMENDED_FRIEND_TCP_CONNECTIONS)
/* Interval between the sending of tcp relay information */
#define SHARE_RELAYS_INTERVAL (5 * 60)
enum {
FRIENDCONN_STATUS_NONE,
@ -61,12 +70,13 @@ typedef struct {
uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES];
uint16_t dht_lock;
IP_Port dht_ip_port;
uint64_t dht_ping_lastrecv, dht_ip_port_lastrecv;
uint64_t dht_pk_lastrecv, dht_ip_port_lastrecv;
int onion_friendnum;
int crypt_connection_id;
uint64_t ping_lastrecv, ping_lastsent;
uint64_t share_relays_lastsent;
struct {
int (*status_callback)(void *object, int id, uint8_t status);
@ -83,6 +93,9 @@ typedef struct {
} callbacks[MAX_FRIEND_CONNECTION_CALLBACKS];
uint16_t lock_count;
Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
uint16_t tcp_relay_counter;
} Friend_Conn;
@ -96,6 +109,8 @@ typedef struct {
int (*fr_request_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t len);
void *fr_request_object;
uint64_t last_LANdiscovery;
} Friend_Connections;
/* return friendcon_id corresponding to the real public key on success.
@ -127,6 +142,13 @@ int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Con
*/
void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk);
/* Add a TCP relay associated to the friend.
*
* return -1 on failure.
* return 0 on success.
*/
int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key);
/* Set the callbacks for the friend connection.
* index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array.
*

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
#include "DHT.h"
#include "LAN_discovery.h"
#include "TCP_client.h"
#include "TCP_connection.h"
#include <pthread.h>
#define CRYPTO_CONN_NO_CONNECTION 0
@ -34,7 +34,6 @@
#define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets
#define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets, we have received one from the other
#define CRYPTO_CONN_ESTABLISHED 4
#define CRYPTO_CONN_TIMED_OUT 5
/* Maximum size of receiving and sending packet buffers. */
#define CRYPTO_PACKET_BUFFER_SIZE 16384 /* Must be a power of 2 */
@ -61,7 +60,7 @@
#define MAX_NUM_SENDPACKET_TRIES 8
/* The timeout of no received UDP packets before the direct UDP connection is considered dead. */
#define UDP_DIRECT_TIMEOUT ((MAX_NUM_SENDPACKET_TRIES * CRYPTO_SEND_PACKET_INTERVAL) / 2)
#define UDP_DIRECT_TIMEOUT ((MAX_NUM_SENDPACKET_TRIES * CRYPTO_SEND_PACKET_INTERVAL) / 1000)
#define PACKET_ID_PADDING 0 /* Denotes padding */
#define PACKET_ID_REQUEST 1 /* Used to request unreceived packets */
@ -73,11 +72,6 @@
#define MAX_TCP_CONNECTIONS 64
#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
/* All packets starting with a byte in this range are considered lossy packets. */
#define PACKET_ID_LOSSY_RANGE_START 192
#define PACKET_ID_LOSSY_RANGE_SIZE 63
@ -112,11 +106,9 @@ typedef struct {
* 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.
*/
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. */
uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
uint16_t temp_packet_length;
@ -155,15 +147,8 @@ typedef struct {
long signed int last_num_packets_sent[CONGESTION_QUEUE_ARRAY_SIZE];
uint32_t packets_sent;
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];
unsigned int last_relay_sentto;
unsigned int num_tcp_online;
Node_format tcp_relays[MAX_TCP_RELAYS_PEER];
uint16_t num_tcp_relays;
/* TCP_connection connection_number */
unsigned int connection_number_tcp;
uint8_t maximum_speed_reached;
@ -186,10 +171,9 @@ typedef struct {
typedef struct {
DHT *dht;
TCP_Connections *tcp_c;
Crypto_Connection *crypto_connections;
TCP_Client_Connection *tcp_connections_new[MAX_TCP_CONNECTIONS];
TCP_Client_Connection *tcp_connections[MAX_TCP_CONNECTIONS];
pthread_mutex_t tcp_mutex;
pthread_mutex_t connections_mutex;
@ -211,11 +195,6 @@ typedef struct {
uint32_t current_sleep_time;
BS_LIST ip_port_list;
int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length);
void *tcp_onion_callback_object;
TCP_Proxy_Info proxy_info;
} Net_Crypto;
@ -241,21 +220,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
* return -1 on failure.
* return connection id on success.
*/
int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key);
/* Copy friends DHT public key into dht_key.
*
* return 0 on failure (no key copied).
* return 1 on success (key copied).
*/
unsigned int get_connection_dht_key(const Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key);
/* Set the DHT public key of the crypto connection.
*
* return -1 on failure.
* return 0 on success.
*/
int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, const uint8_t *dht_public_key);
int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const uint8_t *dht_public_key);
/* Set the direct ip of the crypto connection.
*
@ -301,8 +266,10 @@ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object,
int id);
/* Set the function for this friend that will be callbacked with object and number
* when that friend gives us his DHT temporary public key.
/* Set the function for this friend that will be callbacked with object and number if
* the friend sends us a different dht public key than we have associated to him.
*
* If this function is called, the connection should be recreated with the new public key.
*
* object and number will be passed as argument to this function.
*
@ -364,11 +331,6 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,
*/
int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key);
/* Set the function to be called when an onion response packet is received by one of the TCP connections.
*/
void tcp_onion_response_handler(Net_Crypto *c, int (*tcp_onion_callback)(void *object, const uint8_t *data,
uint16_t length), void *object);
/* Return a random TCP connection number for use in send_tcp_onion_request.
*
* return TCP connection number on success.
@ -389,7 +351,7 @@ int send_tcp_onion_request(Net_Crypto *c, unsigned int TCP_conn_number, const ui
* return number of relays copied to tcp_relays on success.
* return 0 on failure.
*/
unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
/* Kill a crypto connection.
*
@ -398,13 +360,13 @@ unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_rel
*/
int crypto_kill(Net_Crypto *c, int crypt_connection_id);
/* return one of CRYPTO_CONN_* values indicating the state of the connection.
*
* sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
* sets online_tcp_relays to the number of connected tcp relays this connection has.
*/
unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, uint8_t *direct_connected);
unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, _Bool *direct_connected,
unsigned int *online_tcp_relays);
/* Generate our public and private keys.
* Only call this function the first time the program starts.

View File

@ -35,8 +35,8 @@
#define SEND_2 ONION_SEND_2
#define SEND_1 ONION_SEND_1
/* Change symmetric keys every hour to make paths expire eventually. */
#define KEY_REFRESH_INTERVAL (60 * 60)
/* Change symmetric keys every 2 hours to make paths expire eventually. */
#define KEY_REFRESH_INTERVAL (2 * 60 * 60)
static void change_symmetric_key(Onion *onion)
{
if (is_timeout(onion->timestamp, KEY_REFRESH_INTERVAL)) {

View File

@ -1425,7 +1425,6 @@ void do_onion_client(Onion_Client *onion_c)
++onion_c->onion_connected;
}
onion_c->UDP_connected = DHT_non_lan_connected(onion_c->dht);
} else {
populate_path_nodes_tcp(onion_c);
@ -1434,12 +1433,22 @@ void do_onion_client(Onion_Client *onion_c)
}
}
onion_c->UDP_connected = DHT_non_lan_connected(onion_c->dht);
if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) {
set_tcp_onion_status(onion_c->c->tcp_c, !onion_c->UDP_connected);
}
if (onion_connection_status(onion_c)) {
for (i = 0; i < onion_c->num_friends; ++i) {
do_friend(onion_c, i);
}
}
if (onion_c->last_run == 0) {
onion_c->first_run = unix_time();
}
onion_c->last_run = unix_time();
}
@ -1467,7 +1476,7 @@ Onion_Client *new_onion_client(Net_Crypto *c)
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, &handle_dht_dhtpk, onion_c);
tcp_onion_response_handler(onion_c->c, &handle_tcp_onion, onion_c);
set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, &handle_tcp_onion, onion_c);
return onion_c;
}
@ -1483,7 +1492,7 @@ void kill_onion_client(Onion_Client *onion_c)
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, NULL, NULL);
cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, NULL, NULL);
tcp_onion_response_handler(onion_c->c, NULL, NULL);
set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, NULL, NULL);
memset(onion_c, 0, sizeof(Onion_Client));
free(onion_c);
}

View File

@ -136,7 +136,7 @@ typedef struct {
Onion_Client_Paths onion_paths_friends;
uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
uint64_t last_run;
uint64_t last_run, first_run;
uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];

File diff suppressed because it is too large Load Diff