mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Moved all the connection stuff from messenger to friend_connection.
Messenger was doing way do many things. friend_connection takes care of finding and establishing a connection to friends.
This commit is contained in:
parent
834ffee47d
commit
6c71bb7e64
|
@ -122,7 +122,7 @@ typedef struct {
|
|||
uint64_t NATping_timestamp;
|
||||
} NAT;
|
||||
|
||||
#define DHT_FRIEND_MAX_LOCKS 2
|
||||
#define DHT_FRIEND_MAX_LOCKS 32
|
||||
|
||||
typedef struct {
|
||||
uint8_t client_id[CLIENT_ID_SIZE];
|
||||
|
|
|
@ -19,6 +19,8 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \
|
|||
../toxcore/friend_requests.c \
|
||||
../toxcore/LAN_discovery.h \
|
||||
../toxcore/LAN_discovery.c \
|
||||
../toxcore/friend_connection.h \
|
||||
../toxcore/friend_connection.c \
|
||||
../toxcore/Messenger.h \
|
||||
../toxcore/Messenger.c \
|
||||
../toxcore/ping.h \
|
||||
|
|
|
@ -153,73 +153,9 @@ void getaddress(const Messenger *m, uint8_t *address)
|
|||
memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum));
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
Messenger *m = object;
|
||||
|
||||
if (friend_not_valid(m, number))
|
||||
return -1;
|
||||
|
||||
if (m->friendlist[number].crypt_connection_id != -1) {
|
||||
return add_tcp_relay_peer(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port, public_key);
|
||||
} else {
|
||||
return add_tcp_relay(m->net_crypto, ip_port, public_key);
|
||||
}
|
||||
}
|
||||
|
||||
static int friend_new_connection(Messenger *m, int32_t friendnumber, const uint8_t *real_public_key);
|
||||
/* Callback for DHT ip_port changes. */
|
||||
static void dht_ip_callback(void *data, int32_t number, IP_Port ip_port)
|
||||
{
|
||||
Messenger *m = data;
|
||||
|
||||
if (friend_not_valid(m, number))
|
||||
return;
|
||||
|
||||
if (m->friendlist[number].crypt_connection_id == -1) {
|
||||
friend_new_connection(m, number, m->friendlist[number].client_id);
|
||||
}
|
||||
|
||||
set_direct_ip_port(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port);
|
||||
m->friendlist[number].dht_ip_port = ip_port;
|
||||
m->friendlist[number].dht_ip_port_lastrecv = unix_time();
|
||||
}
|
||||
|
||||
/* Callback for dht public key changes. */
|
||||
static void dht_pk_callback(void *data, int32_t number, const uint8_t *dht_public_key)
|
||||
{
|
||||
Messenger *m = data;
|
||||
|
||||
if (friend_not_valid(m, number))
|
||||
return;
|
||||
|
||||
m->friendlist[number].dht_ping_lastrecv = unix_time();
|
||||
|
||||
if (memcmp(m->friendlist[number].dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0)
|
||||
return;
|
||||
|
||||
if (m->friendlist[number].dht_lock) {
|
||||
if (DHT_delfriend(m->dht, m->friendlist[number].dht_temp_pk, m->friendlist[number].dht_lock) != 0) {
|
||||
printf("a. Could not delete dht peer. Please report this.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
m->friendlist[number].dht_lock = 0;
|
||||
}
|
||||
|
||||
DHT_addfriend(m->dht, dht_public_key, dht_ip_callback, data, number, &m->friendlist[number].dht_lock);
|
||||
|
||||
if (m->friendlist[number].crypt_connection_id == -1) {
|
||||
friend_new_connection(m, number, m->friendlist[number].client_id);
|
||||
}
|
||||
|
||||
set_connection_dht_public_key(m->net_crypto, m->friendlist[number].crypt_connection_id, dht_public_key);
|
||||
onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[number].onion_friendnum, dht_public_key);
|
||||
|
||||
memcpy(m->friendlist[number].dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
}
|
||||
|
||||
static int handle_status(void *object, int i, uint8_t status);
|
||||
static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len);
|
||||
static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length);
|
||||
|
||||
/*
|
||||
* Add a friend.
|
||||
|
@ -283,18 +219,17 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
|
|||
|
||||
memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
|
||||
|
||||
int32_t onion_friendnum = onion_addfriend(m->onion_c, client_id);
|
||||
int friendcon_id = new_friend_connection(m->fr_c, client_id);
|
||||
|
||||
if (onion_friendnum == -1)
|
||||
return FAERR_UNKNOWN;
|
||||
if (friendcon_id == -1)
|
||||
return -1;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i <= m->numfriends; ++i) {
|
||||
if (m->friendlist[i].status == NOFRIEND) {
|
||||
m->friendlist[i].onion_friendnum = onion_friendnum;
|
||||
m->friendlist[i].status = FRIEND_ADDED;
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
m->friendlist[i].friendcon_id = friendcon_id;
|
||||
m->friendlist[i].friendrequest_lastsent = 0;
|
||||
m->friendlist[i].friendrequest_timeout = FRIENDREQUEST_TIMEOUT;
|
||||
id_copy(m->friendlist[i].client_id, client_id);
|
||||
|
@ -311,8 +246,9 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
|
|||
m->friendlist[i].message_id = 0;
|
||||
m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
|
||||
memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
|
||||
recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i);
|
||||
onion_dht_pk_callback(m->onion_c, onion_friendnum, &dht_pk_callback, m, i);
|
||||
friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
|
||||
&handle_custom_lossy_packet, m, i);
|
||||
|
||||
|
||||
if (m->numfriends == i)
|
||||
++m->numfriends;
|
||||
|
@ -341,18 +277,17 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id)
|
|||
|
||||
memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
|
||||
|
||||
int32_t onion_friendnum = onion_addfriend(m->onion_c, client_id);
|
||||
int friendcon_id = new_friend_connection(m->fr_c, client_id);
|
||||
|
||||
if (onion_friendnum == -1)
|
||||
if (friendcon_id == -1)
|
||||
return -1;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i <= m->numfriends; ++i) {
|
||||
if (m->friendlist[i].status == NOFRIEND) {
|
||||
m->friendlist[i].onion_friendnum = onion_friendnum;
|
||||
m->friendlist[i].status = FRIEND_CONFIRMED;
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
m->friendlist[i].friendcon_id = friendcon_id;
|
||||
m->friendlist[i].friendrequest_lastsent = 0;
|
||||
id_copy(m->friendlist[i].client_id, client_id);
|
||||
m->friendlist[i].statusmessage = calloc(1, 1);
|
||||
|
@ -365,8 +300,8 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id)
|
|||
m->friendlist[i].is_typing = 0;
|
||||
m->friendlist[i].message_id = 0;
|
||||
m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
|
||||
recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i);
|
||||
onion_dht_pk_callback(m->onion_c, onion_friendnum, &dht_pk_callback, m, i);
|
||||
friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
|
||||
&handle_custom_lossy_packet, m, i);
|
||||
|
||||
if (m->numfriends == i)
|
||||
++m->numfriends;
|
||||
|
@ -391,16 +326,11 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
|
|||
if (m->friendlist[friendnumber].status == FRIEND_ONLINE)
|
||||
remove_online_friend(m, friendnumber);
|
||||
|
||||
onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum);
|
||||
|
||||
if (m->friendlist[friendnumber].dht_lock) {
|
||||
DHT_delfriend(m->dht, m->friendlist[friendnumber].dht_temp_pk, m->friendlist[friendnumber].dht_lock);
|
||||
}
|
||||
|
||||
crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id);
|
||||
free(m->friendlist[friendnumber].statusmessage);
|
||||
free(m->friendlist[friendnumber].avatar_recv_data);
|
||||
remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id);
|
||||
friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
|
||||
kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
|
||||
memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
|
||||
uint32_t i;
|
||||
|
||||
|
@ -867,16 +797,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_ping(const Messenger *m, int32_t friendnumber)
|
||||
{
|
||||
int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_ALIVE, 0, 0, 0);
|
||||
|
||||
if (ret == 1)
|
||||
m->friendlist[friendnumber].ping_lastsent = unix_time();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int send_relays(const Messenger *m, int32_t friendnumber)
|
||||
{
|
||||
Node_format nodes[MAX_SHARED_RELAYS];
|
||||
|
@ -1023,8 +943,6 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
|
|||
const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
|
||||
const uint8_t is_online = status == FRIEND_ONLINE;
|
||||
|
||||
onion_set_friend_online(m->onion_c, m->friendlist[friendnumber].onion_friendnum, is_online);
|
||||
|
||||
if (is_online != was_online) {
|
||||
if (was_online) {
|
||||
break_files(m, friendnumber);
|
||||
|
@ -1065,8 +983,8 @@ static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_
|
|||
if (length != 0)
|
||||
memcpy(packet + 1, data, length);
|
||||
|
||||
return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1,
|
||||
congestion_control) != -1;
|
||||
return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
|
||||
m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1;
|
||||
}
|
||||
|
||||
/**********GROUP CHATS************/
|
||||
|
@ -1311,8 +1229,8 @@ int file_data(const Messenger *m, int32_t friendnumber, uint8_t filenumber, cons
|
|||
if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING)
|
||||
return -1;
|
||||
|
||||
/* Prevent file sending from filling up the entire buffer preventing messages from being sent. */
|
||||
if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE)
|
||||
/* Prevent file sending from filling up the entire buffer preventing messages from being sent. TODO: remove */
|
||||
if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE)
|
||||
return -1;
|
||||
|
||||
uint8_t packet[MAX_CRYPTO_DATA_SIZE];
|
||||
|
@ -1518,10 +1436,8 @@ int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uin
|
|||
if (m->friendlist[friendnumber].status != FRIEND_ONLINE)
|
||||
return -1;
|
||||
|
||||
if (m->friendlist[friendnumber].crypt_connection_id == -1)
|
||||
return -1;
|
||||
|
||||
return send_lossy_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length);
|
||||
return send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
|
||||
m->friendlist[friendnumber].friendcon_id), data, length);
|
||||
}
|
||||
|
||||
static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length)
|
||||
|
@ -1579,10 +1495,8 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const
|
|||
if (m->friendlist[friendnumber].status != FRIEND_ONLINE)
|
||||
return -1;
|
||||
|
||||
if (m->friendlist[friendnumber].crypt_connection_id == -1)
|
||||
return -1;
|
||||
|
||||
if (write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length, 1) == -1) {
|
||||
if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
|
||||
m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -1609,42 +1523,6 @@ static void LANdiscovery(Messenger *m)
|
|||
}
|
||||
}
|
||||
|
||||
static int handle_status(void *object, int i, uint8_t status);
|
||||
static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len);
|
||||
|
||||
static int handle_new_connections(void *object, New_Connection *n_c)
|
||||
{
|
||||
Messenger *m = object;
|
||||
int friend_id = getfriend_id(m, n_c->public_key);
|
||||
|
||||
if (friend_id != -1) {
|
||||
if (m->friendlist[friend_id].crypt_connection_id != -1)
|
||||
return -1;
|
||||
|
||||
int id = accept_crypto_connection(m->net_crypto, n_c);
|
||||
connection_status_handler(m->net_crypto, id, &handle_status, m, friend_id);
|
||||
connection_data_handler(m->net_crypto, id, &handle_packet, m, friend_id);
|
||||
connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friend_id);
|
||||
m->friendlist[friend_id].crypt_connection_id = id;
|
||||
set_friend_status(m, friend_id, FRIEND_CONFIRMED);
|
||||
|
||||
if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) {
|
||||
set_direct_ip_port(m->net_crypto, m->friendlist[friend_id].crypt_connection_id, m->friendlist[friend_id].dht_ip_port);
|
||||
} else {
|
||||
m->friendlist[friend_id].dht_ip_port = n_c->source;
|
||||
m->friendlist[friend_id].dht_ip_port_lastrecv = unix_time();
|
||||
}
|
||||
|
||||
dht_pk_callback(m, friend_id, n_c->dht_public_key);
|
||||
|
||||
nc_dht_pk_callback(m->net_crypto, id, &dht_pk_callback, m, friend_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Run this at startup. */
|
||||
Messenger *new_messenger(Messenger_Options *options)
|
||||
{
|
||||
|
@ -1691,13 +1569,13 @@ Messenger *new_messenger(Messenger_Options *options)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
new_connection_handler(m->net_crypto, &handle_new_connections, m);
|
||||
|
||||
m->onion = new_onion(m->dht);
|
||||
m->onion_a = new_onion_announce(m->dht);
|
||||
m->onion_c = new_onion_client(m->net_crypto);
|
||||
m->fr_c = new_friend_connections(m->onion_c);
|
||||
|
||||
if (!(m->onion && m->onion_a && m->onion_c)) {
|
||||
kill_friend_connections(m->fr_c);
|
||||
kill_onion(m->onion);
|
||||
kill_onion_announce(m->onion_a);
|
||||
kill_onion_client(m->onion_c);
|
||||
|
@ -1722,6 +1600,7 @@ void kill_messenger(Messenger *m)
|
|||
{
|
||||
uint32_t i;
|
||||
|
||||
kill_friend_connections(m->fr_c);
|
||||
kill_onion(m->onion);
|
||||
kill_onion_announce(m->onion_a);
|
||||
kill_onion_client(m->onion_c);
|
||||
|
@ -1769,10 +1648,6 @@ static int handle_status(void *object, int i, uint8_t status)
|
|||
m->friendlist[i].statusmessage_sent = 0;
|
||||
m->friendlist[i].ping_lastrecv = temp_time;
|
||||
} else { /* Went offline. */
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
|
||||
m->friendlist[i].dht_ping_lastrecv = temp_time;
|
||||
|
||||
if (m->friendlist[i].status == FRIEND_ONLINE) {
|
||||
set_friend_status(m, i, FRIEND_CONFIRMED);
|
||||
}
|
||||
|
@ -2072,11 +1947,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
|
|||
return -1;
|
||||
|
||||
switch (packet_id) {
|
||||
case PACKET_ID_ALIVE: {
|
||||
m->friendlist[i].ping_lastrecv = temp_time;
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_NICKNAME: {
|
||||
if (data_length > MAX_NAME_LENGTH || data_length == 0)
|
||||
break;
|
||||
|
@ -2359,29 +2229,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int friend_new_connection(Messenger *m, int32_t friendnumber, const uint8_t *real_public_key)
|
||||
{
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return -1;
|
||||
|
||||
if (m->friendlist[friendnumber].crypt_connection_id != -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int id = new_crypto_connection(m->net_crypto, real_public_key);
|
||||
|
||||
if (id == -1)
|
||||
return -1;
|
||||
|
||||
m->friendlist[friendnumber].crypt_connection_id = id;
|
||||
connection_status_handler(m->net_crypto, id, &handle_status, m, friendnumber);
|
||||
connection_data_handler(m->net_crypto, id, &handle_packet, m, friendnumber);
|
||||
connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friendnumber);
|
||||
nc_dht_pk_callback(m->net_crypto, id, &dht_pk_callback, m, friendnumber);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Make this function not suck. */
|
||||
void do_friends(Messenger *m)
|
||||
{
|
||||
|
@ -2407,27 +2254,7 @@ void do_friends(Messenger *m)
|
|||
* unsuccessful so we set the status back to FRIEND_ADDED and try again.
|
||||
*/
|
||||
check_friend_request_timed_out(m, i, temp_time);
|
||||
|
||||
} else {
|
||||
if (m->friendlist[i].dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
|
||||
if (m->friendlist[i].dht_lock) {
|
||||
DHT_delfriend(m->dht, m->friendlist[i].dht_temp_pk, m->friendlist[i].dht_lock);
|
||||
m->friendlist[i].dht_lock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (m->friendlist[i].dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
|
||||
m->friendlist[i].dht_ip_port.ip.family = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (friend_new_connection(m, i, m->friendlist[i].client_id) == 0) {
|
||||
if (m->friendlist[i].dht_lock)
|
||||
set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_temp_pk);
|
||||
|
||||
set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, m->friendlist[i].dht_ip_port);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
|
||||
|
@ -2456,17 +2283,6 @@ void do_friends(Messenger *m)
|
|||
m->friendlist[i].user_istyping_sent = 1;
|
||||
}
|
||||
|
||||
if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
|
||||
send_ping(m, i);
|
||||
}
|
||||
|
||||
if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
|
||||
/* If we stopped receiving ping packets, kill it. */
|
||||
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
set_friend_status(m, i, FRIEND_CONFIRMED);
|
||||
}
|
||||
|
||||
if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) {
|
||||
send_relays(m, i);
|
||||
}
|
||||
|
@ -2536,6 +2352,7 @@ void do_messenger(Messenger *m)
|
|||
|
||||
do_net_crypto(m->net_crypto);
|
||||
do_onion_client(m->onion_c);
|
||||
do_friend_connections(m->fr_c);
|
||||
do_friends(m);
|
||||
LANdiscovery(m);
|
||||
|
||||
|
@ -2616,8 +2433,8 @@ void do_messenger(Messenger *m)
|
|||
if (ping_lastrecv > 999)
|
||||
ping_lastrecv = 999;
|
||||
|
||||
LOGGER_INFO("F[%2u:%2u] <%s> %02i [%03u] %s",
|
||||
dht2m[friend], friend, msgfptr->name, msgfptr->crypt_connection_id,
|
||||
LOGGER_INFO("F[%2u:%2u] <%s> [%03u] %s",
|
||||
dht2m[friend], friend, msgfptr->name,
|
||||
ping_lastrecv, ID2String(msgfptr->client_id));
|
||||
} else {
|
||||
LOGGER_INFO("F[--:%2u] %s", friend, ID2String(dhtfptr->client_id));
|
||||
|
|
|
@ -26,11 +26,9 @@
|
|||
#ifndef MESSENGER_H
|
||||
#define MESSENGER_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
#include "DHT.h"
|
||||
#include "friend_requests.h"
|
||||
#include "LAN_discovery.h"
|
||||
#include "onion_client.h"
|
||||
#include "friend_connection.h"
|
||||
|
||||
#define MAX_NAME_LENGTH 128
|
||||
/* TODO: this must depend on other variable. */
|
||||
|
@ -41,8 +39,7 @@
|
|||
|
||||
#define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t))
|
||||
|
||||
/* NOTE: Packet ids below 16 must never be used. */
|
||||
#define PACKET_ID_ALIVE 16
|
||||
/* NOTE: Packet ids below 17 must never be used. */
|
||||
#define PACKET_ID_SHARE_RELAYS 17
|
||||
#define PACKET_ID_NICKNAME 48
|
||||
#define PACKET_ID_STATUSMESSAGE 49
|
||||
|
@ -104,15 +101,9 @@ enum {
|
|||
/* Default start timeout in seconds between friend requests. */
|
||||
#define FRIENDREQUEST_TIMEOUT 5;
|
||||
|
||||
/* Interval between the sending of ping packets. */
|
||||
#define FRIEND_PING_INTERVAL 6
|
||||
|
||||
/* Interval between the sending of tcp relay information */
|
||||
#define FRIEND_SHARE_RELAYS_INTERVAL (5 * 60)
|
||||
|
||||
/* If no packets are received from friend in this time interval, kill the connection. */
|
||||
#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 3)
|
||||
|
||||
/* Must be < MAX_CRYPTO_DATA_SIZE */
|
||||
#define AVATAR_DATA_MAX_CHUNK_SIZE (MAX_CRYPTO_DATA_SIZE-1)
|
||||
|
||||
|
@ -120,7 +111,6 @@ enum {
|
|||
#define AVATAR_DATA_TRANSFER_LIMIT (10*AVATAR_MAX_DATA_LENGTH)
|
||||
#define AVATAR_DATA_TRANSFER_TIMEOUT (60) /* 164kB every 60 seconds is not a lot */
|
||||
|
||||
#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT /* Time before friend is removed from the DHT after last hearing about him. */
|
||||
|
||||
/* USERSTATUS -
|
||||
* Represents userstatuses someone can have.
|
||||
|
@ -197,14 +187,8 @@ enum {
|
|||
|
||||
typedef struct {
|
||||
uint8_t client_id[crypto_box_PUBLICKEYBYTES];
|
||||
int friendcon_id;
|
||||
|
||||
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;
|
||||
|
||||
uint32_t onion_friendnum;
|
||||
int crypt_connection_id;
|
||||
uint64_t friendrequest_lastsent; // Time at which the last friend request was sent.
|
||||
uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts.
|
||||
uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online.
|
||||
|
@ -225,8 +209,7 @@ typedef struct {
|
|||
uint32_t message_id; // a semi-unique id used in read receipts.
|
||||
uint8_t receives_read_receipts; // shall we send read receipts to this person?
|
||||
uint32_t friendrequest_nospam; // The nospam number used in the friend request.
|
||||
uint64_t ping_lastrecv;
|
||||
uint64_t ping_lastsent;
|
||||
uint64_t ping_lastrecv;//TODO remove
|
||||
uint64_t share_relays_lastsent;
|
||||
struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
|
||||
struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
|
||||
|
@ -256,6 +239,8 @@ typedef struct Messenger {
|
|||
Onion_Announce *onion_a;
|
||||
Onion_Client *onion_c;
|
||||
|
||||
Friend_Connections *fr_c;
|
||||
|
||||
Friend_Requests fr;
|
||||
uint8_t name[MAX_NAME_LENGTH];
|
||||
uint16_t name_length;
|
||||
|
|
565
toxcore/friend_connection.c
Normal file
565
toxcore/friend_connection.c
Normal file
|
@ -0,0 +1,565 @@
|
|||
/* friend_connection.c
|
||||
*
|
||||
* Connection to friends.
|
||||
*
|
||||
* 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 "friend_connection.h"
|
||||
#include "util.h"
|
||||
|
||||
/* return 1 if the friendcon_id is not valid.
|
||||
* return 0 if the friendcon_id is valid.
|
||||
*/
|
||||
static uint8_t friendconn_id_not_valid(const Friend_Connections *fr_c, int friendcon_id)
|
||||
{
|
||||
if ((unsigned int)friendcon_id >= fr_c->num_cons)
|
||||
return 1;
|
||||
|
||||
if (fr_c->conns == NULL)
|
||||
return 1;
|
||||
|
||||
if (fr_c->conns[friendcon_id].status == FRIENDCONN_STATUS_NONE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Set the size of the friend connections list to num.
|
||||
*
|
||||
* return -1 if realloc fails.
|
||||
* return 0 if it succeeds.
|
||||
*/
|
||||
static int realloc_friendconns(Friend_Connections *fr_c, uint32_t num)
|
||||
{
|
||||
if (num == 0) {
|
||||
free(fr_c->conns);
|
||||
fr_c->conns = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Friend_Conn *newgroup_cons = realloc(fr_c->conns, num * sizeof(Friend_Conn));
|
||||
|
||||
if (newgroup_cons == NULL)
|
||||
return -1;
|
||||
|
||||
fr_c->conns = newgroup_cons;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a new empty friend connection.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return friendcon_id on success.
|
||||
*/
|
||||
static int create_friend_conn(Friend_Connections *fr_c)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < fr_c->num_cons; ++i) {
|
||||
if (fr_c->conns[i].status == FRIENDCONN_STATUS_NONE)
|
||||
return i;
|
||||
}
|
||||
|
||||
int id = -1;
|
||||
|
||||
if (realloc_friendconns(fr_c, fr_c->num_cons + 1) == 0) {
|
||||
id = fr_c->num_cons;
|
||||
++fr_c->num_cons;
|
||||
memset(&(fr_c->conns[id]), 0, sizeof(Friend_Conn));
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Wipe a friend connection.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id)
|
||||
{
|
||||
if (friendconn_id_not_valid(fr_c, friendcon_id))
|
||||
return -1;
|
||||
|
||||
uint32_t i;
|
||||
memset(&(fr_c->conns[friendcon_id]), 0 , sizeof(Friend_Conn));
|
||||
|
||||
for (i = fr_c->num_cons; i != 0; --i) {
|
||||
if (fr_c->conns[i - 1].status != FRIENDCONN_STATUS_NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_c->num_cons != i) {
|
||||
fr_c->num_cons = i;
|
||||
realloc_friendconns(fr_c, fr_c->num_cons);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id)
|
||||
{
|
||||
if (friendconn_id_not_valid(fr_c, friendcon_id))
|
||||
return 0;
|
||||
|
||||
return &fr_c->conns[friendcon_id];
|
||||
}
|
||||
|
||||
/* return friendcon_id corresponding to the real public key on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < fr_c->num_cons; ++i) {
|
||||
Friend_Conn *friend_con = get_conn(fr_c, i);
|
||||
|
||||
if (friend_con) {
|
||||
if (memcmp(friend_con->real_public_key, real_pk, crypto_box_PUBLICKEYBYTES) == 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
Friend_Connections *fr_c = object;
|
||||
Friend_Conn *friend_con = get_conn(fr_c, number);
|
||||
|
||||
if (!friend_con)
|
||||
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);
|
||||
} else {
|
||||
return add_tcp_relay(fr_c->net_crypto, ip_port, public_key);
|
||||
}
|
||||
}
|
||||
|
||||
static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id);
|
||||
/* Callback for DHT ip_port changes. */
|
||||
static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
|
||||
{
|
||||
Friend_Connections *fr_c = object;
|
||||
Friend_Conn *friend_con = get_conn(fr_c, number);
|
||||
|
||||
if (!friend_con)
|
||||
return;
|
||||
|
||||
if (friend_con->crypt_connection_id == -1) {
|
||||
friend_new_connection(fr_c, number);
|
||||
}
|
||||
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port);
|
||||
friend_con->dht_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)
|
||||
{
|
||||
Friend_Connections *fr_c = object;
|
||||
Friend_Conn *friend_con = get_conn(fr_c, number);
|
||||
|
||||
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;
|
||||
|
||||
if (friend_con->dht_lock) {
|
||||
if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) {
|
||||
printf("a. Could not delete dht peer. Please report this.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
}
|
||||
|
||||
static int handle_status(void *object, int number, uint8_t status)
|
||||
{
|
||||
Friend_Connections *fr_c = object;
|
||||
Friend_Conn *friend_con = get_conn(fr_c, number);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
if (status) { /* Went online. */
|
||||
friend_con->status = FRIENDCONN_STATUS_CONNECTED;
|
||||
friend_con->ping_lastrecv = unix_time();
|
||||
onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
|
||||
} else { /* Went offline. */
|
||||
friend_con->status = FRIENDCONN_STATUS_CONNECTING;
|
||||
friend_con->crypt_connection_id = -1;
|
||||
friend_con->dht_ping_lastrecv = unix_time();
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
|
||||
if (friend_con->callbacks[i].status_callback)
|
||||
friend_con->callbacks[i].status_callback(friend_con->callbacks[i].status_callback_object,
|
||||
friend_con->callbacks[i].status_callback_id, status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_packet(void *object, int number, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return -1;
|
||||
|
||||
Friend_Connections *fr_c = object;
|
||||
Friend_Conn *friend_con = get_conn(fr_c, number);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
if (data[0] == PACKET_ID_ALIVE) {
|
||||
friend_con->ping_lastrecv = unix_time();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
|
||||
if (friend_con->callbacks[i].data_callback)
|
||||
friend_con->callbacks[i].data_callback(friend_con->callbacks[i].data_callback_object,
|
||||
friend_con->callbacks[i].data_callback_id, data, length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return -1;
|
||||
|
||||
Friend_Connections *fr_c = object;
|
||||
Friend_Conn *friend_con = get_conn(fr_c, number);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
|
||||
if (friend_con->callbacks[i].lossy_data_callback)
|
||||
friend_con->callbacks[i].lossy_data_callback(friend_con->callbacks[i].lossy_data_callback_object,
|
||||
friend_con->callbacks[i].lossy_data_callback_id, data, length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_new_connections(void *object, New_Connection *n_c)
|
||||
{
|
||||
Friend_Connections *fr_c = object;
|
||||
int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key);
|
||||
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
|
||||
|
||||
if (friend_con) {
|
||||
|
||||
if (friend_con->crypt_connection_id != -1)
|
||||
return -1;
|
||||
|
||||
int id = accept_crypto_connection(fr_c->net_crypto, n_c);
|
||||
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);
|
||||
friend_con->crypt_connection_id = id;
|
||||
|
||||
if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) {
|
||||
set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port);
|
||||
} else {
|
||||
friend_con->dht_ip_port = n_c->source;
|
||||
friend_con->dht_ip_port_lastrecv = unix_time();
|
||||
}
|
||||
|
||||
dht_pk_callback(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;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id)
|
||||
{
|
||||
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
if (friend_con->crypt_connection_id != -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key);
|
||||
|
||||
if (id == -1)
|
||||
return -1;
|
||||
|
||||
friend_con->crypt_connection_id = id;
|
||||
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);
|
||||
nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_ping(const Friend_Connections *fr_c, int friendcon_id)
|
||||
{
|
||||
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
uint8_t ping = PACKET_ID_ALIVE;
|
||||
int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0);
|
||||
|
||||
if (ret != -1) {
|
||||
friend_con->ping_lastsent = unix_time();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure
|
||||
*/
|
||||
int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
|
||||
int (*status_callback)(void *object, int id, uint8_t status), int (*data_callback)(void *object, int id, uint8_t *data,
|
||||
uint16_t length), int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object,
|
||||
int number)
|
||||
{
|
||||
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
if (index >= MAX_FRIEND_CONNECTION_CALLBACKS)
|
||||
return -1;
|
||||
|
||||
friend_con->callbacks[index].status_callback = status_callback;
|
||||
friend_con->callbacks[index].data_callback = data_callback;
|
||||
friend_con->callbacks[index].lossy_data_callback = lossy_data_callback;
|
||||
|
||||
friend_con->callbacks[index].status_callback_object =
|
||||
friend_con->callbacks[index].data_callback_object =
|
||||
friend_con->callbacks[index].lossy_data_callback_object = object;
|
||||
|
||||
friend_con->callbacks[index].status_callback_id =
|
||||
friend_con->callbacks[index].data_callback_id =
|
||||
friend_con->callbacks[index].lossy_data_callback_id = number;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return the crypt_connection_id for the connection.
|
||||
*
|
||||
* return crypt_connection_id on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id)
|
||||
{
|
||||
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
return friend_con->crypt_connection_id;
|
||||
}
|
||||
|
||||
/* Create a new friend connection.
|
||||
* If one to that real public key already exists, increase lock count and return it.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return connection id on success.
|
||||
*/
|
||||
int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key)
|
||||
{
|
||||
int friendcon_id = getfriend_conn_id_pk(fr_c, real_public_key);
|
||||
|
||||
if (friendcon_id != -1) {
|
||||
++fr_c->conns[friendcon_id].lock_count;
|
||||
return friendcon_id;
|
||||
}
|
||||
|
||||
friendcon_id = create_friend_conn(fr_c);
|
||||
|
||||
if (friendcon_id == -1)
|
||||
return -1;
|
||||
|
||||
int32_t onion_friendnum = onion_addfriend(fr_c->onion_c, real_public_key);
|
||||
|
||||
if (onion_friendnum == -1)
|
||||
return -1;
|
||||
|
||||
Friend_Conn *friend_con = &fr_c->conns[friendcon_id];
|
||||
|
||||
friend_con->crypt_connection_id = -1;
|
||||
friend_con->status = FRIENDCONN_STATUS_CONNECTING;
|
||||
memcpy(friend_con->real_public_key, real_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
friend_con->onion_friendnum = onion_friendnum;
|
||||
|
||||
recv_tcp_relay_handler(fr_c->onion_c, onion_friendnum, &tcp_relay_node_callback, fr_c, friendcon_id);
|
||||
onion_dht_pk_callback(fr_c->onion_c, onion_friendnum, &dht_pk_callback, fr_c, friendcon_id);
|
||||
|
||||
return friendcon_id;
|
||||
}
|
||||
|
||||
/* Kill a friend connection.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
|
||||
{
|
||||
Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
|
||||
|
||||
if (!friend_con)
|
||||
return -1;
|
||||
|
||||
if (friend_con->lock_count) {
|
||||
--friend_con->lock_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
onion_delfriend(fr_c->onion_c, friend_con->onion_friendnum);
|
||||
crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
|
||||
|
||||
if (friend_con->dht_lock) {
|
||||
DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
|
||||
}
|
||||
|
||||
return wipe_friend_conn(fr_c, friendcon_id);
|
||||
}
|
||||
|
||||
|
||||
/* Create new friend_connections instance. */
|
||||
Friend_Connections *new_friend_connections(Onion_Client *onion_c)
|
||||
{
|
||||
if (!onion_c)
|
||||
return NULL;
|
||||
|
||||
Friend_Connections *temp = calloc(1, sizeof(Friend_Connections));
|
||||
|
||||
if (temp == NULL)
|
||||
return NULL;
|
||||
|
||||
temp->dht = onion_c->dht;
|
||||
temp->net_crypto = onion_c->c;
|
||||
temp->onion_c = onion_c;
|
||||
|
||||
new_connection_handler(temp->net_crypto, &handle_new_connections, temp);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* main friend_connections loop. */
|
||||
void do_friend_connections(Friend_Connections *fr_c)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t temp_time = unix_time();
|
||||
|
||||
for (i = 0; i < fr_c->num_cons; ++i) {
|
||||
Friend_Conn *friend_con = get_conn(fr_c, i);
|
||||
|
||||
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_lock) {
|
||||
DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
|
||||
friend_con->dht_lock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
|
||||
friend_con->dht_ip_port.ip.family = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
|
||||
if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
|
||||
send_ping(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);
|
||||
friend_con->crypt_connection_id = -1;
|
||||
handle_status(fr_c, i, 0); /* Going offline. */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free everything related with friend_connections. */
|
||||
void kill_friend_connections(Friend_Connections *fr_c)
|
||||
{
|
||||
if (!fr_c)
|
||||
return;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < fr_c->num_cons; ++i) {
|
||||
kill_friend_connection(fr_c, i);
|
||||
}
|
||||
|
||||
free(fr_c);
|
||||
}
|
140
toxcore/friend_connection.h
Normal file
140
toxcore/friend_connection.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* friend_connection.h
|
||||
*
|
||||
* Connection to friends.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FRIEND_CONNECTION_H
|
||||
#define FRIEND_CONNECTION_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
#include "DHT.h"
|
||||
#include "LAN_discovery.h"
|
||||
#include "onion_client.h"
|
||||
|
||||
|
||||
#define MAX_FRIEND_CONNECTION_CALLBACKS 2
|
||||
#define MESSENGER_CALLBACK_INDEX 0
|
||||
#define GROUPCHAT_CALLBACK_INDEX 1
|
||||
|
||||
#define PACKET_ID_ALIVE 16
|
||||
|
||||
/* Interval between the sending of ping packets. */
|
||||
#define FRIEND_PING_INTERVAL 6
|
||||
|
||||
/* If no packets are received from friend in this time interval, kill the connection. */
|
||||
#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 3)
|
||||
|
||||
/* Time before friend is removed from the DHT after last hearing about him. */
|
||||
#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT
|
||||
|
||||
|
||||
enum {
|
||||
FRIENDCONN_STATUS_NONE,
|
||||
FRIENDCONN_STATUS_CONNECTING,
|
||||
FRIENDCONN_STATUS_CONNECTED
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t status;
|
||||
|
||||
uint8_t real_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
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;
|
||||
|
||||
int onion_friendnum;
|
||||
int crypt_connection_id;
|
||||
|
||||
uint64_t ping_lastrecv, ping_lastsent;
|
||||
|
||||
struct {
|
||||
int (*status_callback)(void *object, int id, uint8_t status);
|
||||
void *status_callback_object;
|
||||
int status_callback_id;
|
||||
|
||||
int (*data_callback)(void *object, int id, uint8_t *data, uint16_t length);
|
||||
void *data_callback_object;
|
||||
int data_callback_id;
|
||||
|
||||
int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length);
|
||||
void *lossy_data_callback_object;
|
||||
int lossy_data_callback_id;
|
||||
} callbacks[MAX_FRIEND_CONNECTION_CALLBACKS];
|
||||
|
||||
uint16_t lock_count;
|
||||
} Friend_Conn;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Net_Crypto *net_crypto;
|
||||
DHT *dht;
|
||||
Onion_Client *onion_c;
|
||||
|
||||
Friend_Conn *conns;
|
||||
uint32_t num_cons;
|
||||
|
||||
} Friend_Connections;
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure
|
||||
*/
|
||||
int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
|
||||
int (*status_callback)(void *object, int id, uint8_t status), int (*data_callback)(void *object, int id, uint8_t *data,
|
||||
uint16_t length), int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object,
|
||||
int number);
|
||||
|
||||
/* return the crypt_connection_id for the connection.
|
||||
*
|
||||
* return crypt_connection_id on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id);
|
||||
|
||||
/* Create a new friend connection.
|
||||
* If one to that real public key already exists, increase lock count and return it.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return connection id on success.
|
||||
*/
|
||||
int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key);
|
||||
|
||||
/* Kill a friend connection.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id);
|
||||
|
||||
/* Create new friend_connections instance. */
|
||||
Friend_Connections *new_friend_connections(Onion_Client *onion_c);
|
||||
|
||||
/* main friend_connections loop. */
|
||||
void do_friend_connections(Friend_Connections *fr_c);
|
||||
|
||||
/* Free everything related with friend_connections. */
|
||||
void kill_friend_connections(Friend_Connections *fr_c);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user