mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Messenger now works with the new net_crypto api.
Added callbacks in net_crypto for the data packets and status changes. Added onion_getfriend_DHT_pubkey to onion_client. Net crypto isn't done yet so connections between toxes are not lossless, this means file sending is broken hence why the test fails.
This commit is contained in:
parent
8ae0a79305
commit
db78c99ff4
|
@ -1857,12 +1857,307 @@ static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t)
|
|||
}
|
||||
}
|
||||
|
||||
static int handle_status(void *object, int i, uint8_t status)
|
||||
{
|
||||
uint64_t temp_time = unix_time();
|
||||
Messenger *m = object;
|
||||
|
||||
if (status) { /* Went online. */
|
||||
set_friend_status(m, i, FRIEND_ONLINE);
|
||||
m->friendlist[i].name_sent = 0;
|
||||
m->friendlist[i].userstatus_sent = 0;
|
||||
m->friendlist[i].statusmessage_sent = 0;
|
||||
m->friendlist[i].ping_lastrecv = temp_time;
|
||||
} else { /* Went offline. */
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
|
||||
if (m->friendlist[i].status == FRIEND_ONLINE) {
|
||||
set_friend_status(m, i, FRIEND_CONFIRMED);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
Messenger *m = object;
|
||||
uint64_t temp_time = unix_time();
|
||||
uint8_t packet_id = temp[0];
|
||||
uint8_t *data = temp + 1;
|
||||
uint32_t data_length = len - 1;
|
||||
|
||||
if (m->friendlist[i].status != FRIEND_ONLINE)
|
||||
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;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t data_terminated[data_length + 1];
|
||||
memcpy(data_terminated, data, data_length);
|
||||
data_terminated[data_length] = 0;
|
||||
|
||||
/* inform of namechange before we overwrite the old name */
|
||||
if (m->friend_namechange)
|
||||
m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata);
|
||||
|
||||
memcpy(m->friendlist[i].name, data_terminated, data_length);
|
||||
m->friendlist[i].name_length = data_length;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_STATUSMESSAGE: {
|
||||
if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH)
|
||||
break;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t data_terminated[data_length + 1];
|
||||
memcpy(data_terminated, data, data_length);
|
||||
data_terminated[data_length] = 0;
|
||||
|
||||
if (m->friend_statusmessagechange)
|
||||
m->friend_statusmessagechange(m, i, data_terminated, data_length,
|
||||
m->friend_statuschange_userdata);
|
||||
|
||||
set_friend_statusmessage(m, i, data_terminated, data_length);
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_USERSTATUS: {
|
||||
if (data_length != 1)
|
||||
break;
|
||||
|
||||
USERSTATUS status = data[0];
|
||||
|
||||
if (status >= USERSTATUS_INVALID)
|
||||
break;
|
||||
|
||||
if (m->friend_userstatuschange)
|
||||
m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata);
|
||||
|
||||
set_friend_userstatus(m, i, status);
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_TYPING: {
|
||||
if (data_length != 1)
|
||||
break;
|
||||
|
||||
uint8_t typing = data[0];
|
||||
|
||||
set_friend_typing(m, i, typing);
|
||||
|
||||
if (m->friend_typingchange)
|
||||
m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_MESSAGE: {
|
||||
uint8_t *message_id = data;
|
||||
uint8_t message_id_length = 4;
|
||||
|
||||
if (data_length <= message_id_length)
|
||||
break;
|
||||
|
||||
uint8_t *message = data + message_id_length;
|
||||
uint16_t message_length = data_length - message_id_length;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t message_terminated[message_length + 1];
|
||||
memcpy(message_terminated, message, message_length);
|
||||
message_terminated[message_length] = 0;
|
||||
|
||||
if (m->friendlist[i].receives_read_receipts) {
|
||||
write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
|
||||
}
|
||||
|
||||
if (m->friend_message)
|
||||
(*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_ACTION: {
|
||||
uint8_t *message_id = data;
|
||||
uint8_t message_id_length = 4;
|
||||
|
||||
if (data_length <= message_id_length)
|
||||
break;
|
||||
|
||||
uint8_t *action = data + message_id_length;
|
||||
uint16_t action_length = data_length - message_id_length;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t action_terminated[action_length + 1];
|
||||
memcpy(action_terminated, action, action_length);
|
||||
action_terminated[action_length] = 0;
|
||||
|
||||
if (m->friendlist[i].receives_read_receipts) {
|
||||
write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
|
||||
}
|
||||
|
||||
if (m->friend_action)
|
||||
(*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_RECEIPT: {
|
||||
uint32_t msgid;
|
||||
|
||||
if (data_length < sizeof(msgid))
|
||||
break;
|
||||
|
||||
memcpy(&msgid, data, sizeof(msgid));
|
||||
msgid = ntohl(msgid);
|
||||
|
||||
if (m->read_receipt)
|
||||
(*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_INVITE_GROUPCHAT: {
|
||||
if (data_length != crypto_box_PUBLICKEYBYTES)
|
||||
break;
|
||||
|
||||
if (m->group_invite)
|
||||
(*m->group_invite)(m, i, data, m->group_invite_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_JOIN_GROUPCHAT: {
|
||||
if (data_length != crypto_box_PUBLICKEYBYTES * 2)
|
||||
break;
|
||||
|
||||
int groupnum = group_num(m, data);
|
||||
|
||||
if (groupnum == -1)
|
||||
break;
|
||||
|
||||
if (!group_invited(m, i, groupnum))
|
||||
break;
|
||||
|
||||
group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES);
|
||||
/* This is just there to speedup joining. */
|
||||
chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES);
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_SENDREQUEST: {
|
||||
if (data_length < 1 + sizeof(uint64_t) + 1)
|
||||
break;
|
||||
|
||||
uint8_t filenumber = data[0];
|
||||
uint64_t filesize;
|
||||
net_to_host(data + 1, sizeof(filesize));
|
||||
memcpy(&filesize, data + 1, sizeof(filesize));
|
||||
m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED;
|
||||
m->friendlist[i].file_receiving[filenumber].size = filesize;
|
||||
m->friendlist[i].file_receiving[filenumber].transferred = 0;
|
||||
|
||||
/* Force NULL terminate file name. */
|
||||
uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1];
|
||||
memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t));
|
||||
filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0;
|
||||
|
||||
if (m->file_sendrequest)
|
||||
(*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t),
|
||||
m->file_sendrequest_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_CONTROL: {
|
||||
if (data_length < 3)
|
||||
break;
|
||||
|
||||
uint8_t send_receive = data[0];
|
||||
uint8_t filenumber = data[1];
|
||||
uint8_t control_type = data[2];
|
||||
|
||||
if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1)
|
||||
break;
|
||||
|
||||
if (m->file_filecontrol)
|
||||
(*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3,
|
||||
m->file_filecontrol_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_DATA: {
|
||||
if (data_length < 2)
|
||||
break;
|
||||
|
||||
uint8_t filenumber = data[0];
|
||||
|
||||
if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE)
|
||||
break;
|
||||
|
||||
m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1);
|
||||
|
||||
if (m->file_filedata)
|
||||
(*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_MSI: {
|
||||
if (data_length == 0)
|
||||
break;
|
||||
|
||||
if (m->msi_packet)
|
||||
(*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata);
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int friend_new_connection(Messenger *m, int32_t friendnumber, 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);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* TODO: Make this function not suck. */
|
||||
void do_friends(Messenger *m)
|
||||
{
|
||||
uint32_t i;
|
||||
int len;
|
||||
uint8_t temp[MAX_CRYPTO_DATA_SIZE];
|
||||
uint64_t temp_time = unix_time();
|
||||
|
||||
for (i = 0; i < m->numfriends; ++i) {
|
||||
|
@ -1886,35 +2181,21 @@ void do_friends(Messenger *m)
|
|||
check_friend_request_timed_out(m, i, temp_time);
|
||||
}
|
||||
|
||||
friend_new_connection(m, i, m->friendlist[i].client_id);
|
||||
uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
if (onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key) == 0) {
|
||||
set_conection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key);
|
||||
}
|
||||
|
||||
IP_Port friendip;
|
||||
int friendok = onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip);
|
||||
|
||||
switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) {
|
||||
case CRYPTO_CONN_NO_CONNECTION:
|
||||
if (friendok == 1)
|
||||
m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip);
|
||||
|
||||
break;
|
||||
|
||||
case CRYPTO_CONN_ESTABLISHED: /* Connection is established. */
|
||||
set_friend_status(m, i, FRIEND_ONLINE);
|
||||
m->friendlist[i].name_sent = 0;
|
||||
m->friendlist[i].userstatus_sent = 0;
|
||||
m->friendlist[i].statusmessage_sent = 0;
|
||||
m->friendlist[i].ping_lastrecv = temp_time;
|
||||
break;
|
||||
|
||||
case CRYPTO_CONN_TIMED_OUT:
|
||||
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) {
|
||||
set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip);
|
||||
}
|
||||
}
|
||||
|
||||
while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
|
||||
if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
|
||||
if (m->friendlist[i].name_sent == 0) {
|
||||
if (m_sendname(m, i, m->name, m->name_length))
|
||||
m->friendlist[i].name_sent = 1;
|
||||
|
@ -1939,265 +2220,18 @@ void do_friends(Messenger *m)
|
|||
send_ping(m, i);
|
||||
}
|
||||
|
||||
len = read_cryptpacket(m->net_crypto, m->friendlist[i].crypt_connection_id, temp);
|
||||
|
||||
if (len > 0) {
|
||||
uint8_t packet_id = temp[0];
|
||||
uint8_t *data = temp + 1;
|
||||
uint32_t data_length = len - 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;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t data_terminated[data_length + 1];
|
||||
memcpy(data_terminated, data, data_length);
|
||||
data_terminated[data_length] = 0;
|
||||
|
||||
/* inform of namechange before we overwrite the old name */
|
||||
if (m->friend_namechange)
|
||||
m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata);
|
||||
|
||||
memcpy(m->friendlist[i].name, data_terminated, data_length);
|
||||
m->friendlist[i].name_length = data_length;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_STATUSMESSAGE: {
|
||||
if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH)
|
||||
break;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t data_terminated[data_length + 1];
|
||||
memcpy(data_terminated, data, data_length);
|
||||
data_terminated[data_length] = 0;
|
||||
|
||||
if (m->friend_statusmessagechange)
|
||||
m->friend_statusmessagechange(m, i, data_terminated, data_length,
|
||||
m->friend_statuschange_userdata);
|
||||
|
||||
set_friend_statusmessage(m, i, data_terminated, data_length);
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_USERSTATUS: {
|
||||
if (data_length != 1)
|
||||
break;
|
||||
|
||||
USERSTATUS status = data[0];
|
||||
|
||||
if (status >= USERSTATUS_INVALID)
|
||||
break;
|
||||
|
||||
if (m->friend_userstatuschange)
|
||||
m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata);
|
||||
|
||||
set_friend_userstatus(m, i, status);
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_TYPING: {
|
||||
if (data_length != 1)
|
||||
break;
|
||||
|
||||
uint8_t typing = data[0];
|
||||
|
||||
set_friend_typing(m, i, typing);
|
||||
|
||||
if (m->friend_typingchange)
|
||||
m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_MESSAGE: {
|
||||
uint8_t *message_id = data;
|
||||
uint8_t message_id_length = 4;
|
||||
|
||||
if (data_length <= message_id_length)
|
||||
break;
|
||||
|
||||
uint8_t *message = data + message_id_length;
|
||||
uint16_t message_length = data_length - message_id_length;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t message_terminated[message_length + 1];
|
||||
memcpy(message_terminated, message, message_length);
|
||||
message_terminated[message_length] = 0;
|
||||
|
||||
if (m->friendlist[i].receives_read_receipts) {
|
||||
write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
|
||||
}
|
||||
|
||||
if (m->friend_message)
|
||||
(*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_ACTION: {
|
||||
uint8_t *message_id = data;
|
||||
uint8_t message_id_length = 4;
|
||||
|
||||
if (data_length <= message_id_length)
|
||||
break;
|
||||
|
||||
uint8_t *action = data + message_id_length;
|
||||
uint16_t action_length = data_length - message_id_length;
|
||||
|
||||
/* Make sure the NULL terminator is present. */
|
||||
uint8_t action_terminated[action_length + 1];
|
||||
memcpy(action_terminated, action, action_length);
|
||||
action_terminated[action_length] = 0;
|
||||
|
||||
if (m->friendlist[i].receives_read_receipts) {
|
||||
write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
|
||||
}
|
||||
|
||||
if (m->friend_action)
|
||||
(*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_RECEIPT: {
|
||||
uint32_t msgid;
|
||||
|
||||
if (data_length < sizeof(msgid))
|
||||
break;
|
||||
|
||||
memcpy(&msgid, data, sizeof(msgid));
|
||||
msgid = ntohl(msgid);
|
||||
|
||||
if (m->read_receipt)
|
||||
(*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_INVITE_GROUPCHAT: {
|
||||
if (data_length != crypto_box_PUBLICKEYBYTES)
|
||||
break;
|
||||
|
||||
if (m->group_invite)
|
||||
(*m->group_invite)(m, i, data, m->group_invite_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_JOIN_GROUPCHAT: {
|
||||
if (data_length != crypto_box_PUBLICKEYBYTES * 2)
|
||||
break;
|
||||
|
||||
int groupnum = group_num(m, data);
|
||||
|
||||
if (groupnum == -1)
|
||||
break;
|
||||
|
||||
if (!group_invited(m, i, groupnum))
|
||||
break;
|
||||
|
||||
group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES);
|
||||
/* This is just there to speedup joining. */
|
||||
chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES);
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_SENDREQUEST: {
|
||||
if (data_length < 1 + sizeof(uint64_t) + 1)
|
||||
break;
|
||||
|
||||
uint8_t filenumber = data[0];
|
||||
uint64_t filesize;
|
||||
net_to_host(data + 1, sizeof(filesize));
|
||||
memcpy(&filesize, data + 1, sizeof(filesize));
|
||||
m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED;
|
||||
m->friendlist[i].file_receiving[filenumber].size = filesize;
|
||||
m->friendlist[i].file_receiving[filenumber].transferred = 0;
|
||||
|
||||
/* Force NULL terminate file name. */
|
||||
uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1];
|
||||
memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t));
|
||||
filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0;
|
||||
|
||||
if (m->file_sendrequest)
|
||||
(*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t),
|
||||
m->file_sendrequest_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_CONTROL: {
|
||||
if (data_length < 3)
|
||||
break;
|
||||
|
||||
uint8_t send_receive = data[0];
|
||||
uint8_t filenumber = data[1];
|
||||
uint8_t control_type = data[2];
|
||||
|
||||
if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1)
|
||||
break;
|
||||
|
||||
if (m->file_filecontrol)
|
||||
(*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3,
|
||||
m->file_filecontrol_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_DATA: {
|
||||
if (data_length < 2)
|
||||
break;
|
||||
|
||||
uint8_t filenumber = data[0];
|
||||
|
||||
if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE)
|
||||
break;
|
||||
|
||||
m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1);
|
||||
|
||||
if (m->file_filedata)
|
||||
(*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_MSI: {
|
||||
if (data_length == 0)
|
||||
break;
|
||||
|
||||
if (m->msi_packet)
|
||||
(*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata);
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_cryptoconnected(m->net_crypto,
|
||||
m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */
|
||||
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
set_friend_status(m, i, FRIEND_CONFIRMED);
|
||||
}
|
||||
|
||||
if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
|
||||
/* If we stopped recieving ping packets, kill it. */
|
||||
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
set_friend_status(m, i, FRIEND_CONFIRMED);
|
||||
}
|
||||
|
||||
break;
|
||||
if (is_cryptoconnected(m->net_crypto,
|
||||
m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */
|
||||
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
set_friend_status(m, i, FRIEND_CONFIRMED);
|
||||
}
|
||||
|
||||
if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
|
||||
/* If we stopped recieving ping packets, kill it. */
|
||||
crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
|
||||
m->friendlist[i].crypt_connection_id = -1;
|
||||
set_friend_status(m, i, FRIEND_CONFIRMED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -379,6 +379,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat
|
|||
return -1;
|
||||
|
||||
increment_nonce(conn->sent_nonce);
|
||||
conn->last_data_packet_sent = current_time(); //TODO remove this.
|
||||
return send_packet_to(c, crypt_connection_id, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
|
@ -459,6 +460,7 @@ static int new_temp_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *pack
|
|||
conn->temp_packet = temp_packet;
|
||||
conn->temp_packet_length = length;
|
||||
conn->temp_packet_sent_time = 0;
|
||||
conn->temp_packet_num_sent = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -480,6 +482,7 @@ static int clear_temp_packet(Net_Crypto *c, int crypt_connection_id)
|
|||
conn->temp_packet = 0;
|
||||
conn->temp_packet_length = 0;
|
||||
conn->temp_packet_sent_time = 0;
|
||||
conn->temp_packet_num_sent = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -503,6 +506,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)
|
|||
return -1;
|
||||
|
||||
conn->temp_packet_sent_time = current_time();
|
||||
++conn->temp_packet_num_sent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -594,7 +598,24 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint
|
|||
|
||||
case NET_PACKET_CRYPTO_DATA: {
|
||||
if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) {
|
||||
//TODO
|
||||
uint8_t data[MAX_DATA_DATA_PACKET_SIZE];
|
||||
int len = handle_data_packet(c, crypt_connection_id, data, packet, length);
|
||||
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
|
||||
if (conn->connection_status_callback)
|
||||
conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1);
|
||||
|
||||
clear_temp_packet(c, crypt_connection_id);
|
||||
conn->status = CRYPTO_CONN_ESTABLISHED;
|
||||
}
|
||||
|
||||
if (conn->connection_data_callback)
|
||||
conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, data, len);
|
||||
|
||||
//TODO add buffers and packet requesting.
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
@ -870,6 +891,9 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t
|
|||
if (conn == 0)
|
||||
return -1;
|
||||
|
||||
if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0)
|
||||
return -1;
|
||||
|
||||
memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
conn->dht_public_key_set = 1;
|
||||
|
||||
|
@ -908,6 +932,52 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
|
||||
*
|
||||
* The set function should return -1 on failure and 0 on success.
|
||||
* Note that if this function is set, the connection will clear itself on disconnect.
|
||||
* Object and id will be passed to this function untouched.
|
||||
* status is 1 if the connection is going online, 0 if it is going offline.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object,
|
||||
int id, uint8_t status), void *object, int id)
|
||||
{
|
||||
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
|
||||
|
||||
if (conn == 0)
|
||||
return -1;
|
||||
|
||||
conn->connection_status_callback = connection_status_callback;
|
||||
conn->connection_status_callback_object = object;
|
||||
conn->connection_status_callback_id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set function to be called when connection with crypt_connection_id receives a data packet of length.
|
||||
*
|
||||
* The set function should return -1 on failure and 0 on success.
|
||||
* Object and id will be passed to this function untouched.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
|
||||
int id, uint8_t *data, uint16_t length), void *object, int id)
|
||||
{
|
||||
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
|
||||
|
||||
if (conn == 0)
|
||||
return -1;
|
||||
|
||||
conn->connection_data_callback = connection_data_callback;
|
||||
conn->connection_data_callback_object = object;
|
||||
conn->connection_data_callback_id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the crypto connection id from the ip_port.
|
||||
*
|
||||
* return -1 on failure.
|
||||
|
@ -977,27 +1047,26 @@ static void send_crypto_packets(Net_Crypto *c)
|
|||
if (conn == 0)
|
||||
return;
|
||||
|
||||
if ((CRYPTO_SEND_PACKET_INTERVAL * 1000UL) + conn->temp_packet_sent_time < temp_time) {
|
||||
if ((CRYPTO_SEND_PACKET_INTERVAL * 1000ULL) + conn->temp_packet_sent_time < temp_time) {
|
||||
send_temp_packet(c, i);
|
||||
}
|
||||
|
||||
if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED
|
||||
&& (500ULL * 1000ULL) + conn->last_data_packet_sent < temp_time) {//TODO remove this.
|
||||
uint8_t data[4] = {};
|
||||
send_data_packet(c, i, data, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return 0 if there is no received data in the buffer.
|
||||
* return -1 if the packet was discarded.
|
||||
* return length of received data if successful.
|
||||
*/
|
||||
int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
*/
|
||||
uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id)
|
||||
{
|
||||
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return 0 if data could not be put in packet queue.
|
||||
|
@ -1005,28 +1074,22 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id)
|
|||
*/
|
||||
int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length)
|
||||
{
|
||||
//TODO
|
||||
if (send_data_packet(c, crypt_connection_id, data, length) == 0)
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Start a secure connection with other peer who has public_key and ip_port.
|
||||
*
|
||||
* return -1 if failure.
|
||||
* return crypt_connection_id of the initialized connection if everything went well.
|
||||
*/
|
||||
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Kill a crypto connection.
|
||||
*
|
||||
* return 0 if killed successfully.
|
||||
* return 1 if there was a problem.
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int crypto_kill(Net_Crypto *c, int crypt_connection_id)
|
||||
{
|
||||
|
||||
//TODO
|
||||
return wipe_crypto_connection(c, crypt_connection_id);
|
||||
}
|
||||
|
||||
/* return 0 if no connection.
|
||||
|
@ -1096,9 +1159,35 @@ Net_Crypto *new_net_crypto(DHT *dht)
|
|||
static void kill_timedout(Net_Crypto *c)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t temp_time = current_time();
|
||||
|
||||
for (i = 0; i < c->crypto_connections_length; ++i) {
|
||||
//TODO
|
||||
Crypto_Connection *conn = get_crypto_connection(c, i);
|
||||
|
||||
if (conn == 0)
|
||||
return;
|
||||
|
||||
if (conn->status == CRYPTO_CONN_NO_CONNECTION || conn->status == CRYPTO_CONN_TIMED_OUT)
|
||||
continue;
|
||||
|
||||
if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT
|
||||
|| conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
|
||||
if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES)
|
||||
continue;
|
||||
|
||||
if (conn->connection_status_callback) {
|
||||
conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0);
|
||||
crypto_kill(c, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
conn->status = CRYPTO_CONN_TIMED_OUT;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (conn->status == CRYPTO_CONN_ESTABLISHED) {
|
||||
//TODO: add a timeout here?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
|
||||
/* Interval in ms between sending cookie request/handshake packets. */
|
||||
#define CRYPTO_SEND_PACKET_INTERVAL 500
|
||||
/* The maximum number of times we try to send the cookie request and handshake
|
||||
before giving up. */
|
||||
#define MAX_NUM_SENDPACKET_TRIES 10
|
||||
|
||||
typedef struct {
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
|
||||
|
@ -59,8 +62,6 @@ typedef struct {
|
|||
* 4 if the connection is established.
|
||||
* 5 if the connection is timed out.
|
||||
*/
|
||||
uint64_t timeout;
|
||||
|
||||
uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
|
||||
uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */
|
||||
uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */
|
||||
|
@ -68,9 +69,20 @@ typedef struct {
|
|||
uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
|
||||
uint16_t temp_packet_length;
|
||||
uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
|
||||
uint32_t temp_packet_num_sent;
|
||||
|
||||
IP_Port ip_port; /* The ip and port to contact this guy directly.*/
|
||||
uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */
|
||||
|
||||
int (*connection_status_callback)(void *object, int id, uint8_t status);
|
||||
void *connection_status_callback_object;
|
||||
int connection_status_callback_id;
|
||||
|
||||
int (*connection_data_callback)(void *object, int id, uint8_t *data, uint16_t length);
|
||||
void *connection_data_callback_object;
|
||||
int connection_data_callback_id;
|
||||
|
||||
uint64_t last_data_packet_sent;
|
||||
} Crypto_Connection;
|
||||
|
||||
typedef struct {
|
||||
|
@ -117,12 +129,52 @@ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *
|
|||
*/
|
||||
int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
|
||||
|
||||
|
||||
/* return 0 if there is no received data in the buffer.
|
||||
* return -1 if the packet was discarded.
|
||||
* return length of received data if successful.
|
||||
/* Create a crypto connection.
|
||||
* If one to that real public key already exists, return it.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return connection id on success.
|
||||
*/
|
||||
int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data);
|
||||
int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key);
|
||||
|
||||
/* Set the DHT public key of the crypto connection.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key);
|
||||
|
||||
/* Set the direct ip of the crypto connection.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port);
|
||||
|
||||
/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
|
||||
*
|
||||
* The set function should return -1 on failure and 0 on success.
|
||||
* Note that if this function is set, the connection will clear itself on disconnect.
|
||||
* Object and id will be passed to this function untouched.
|
||||
* status is 1 if the connection is going online, 0 if it is going offline.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object,
|
||||
int id, uint8_t status), void *object, int id);
|
||||
|
||||
/* Set function to be called when connection with crypt_connection_id receives a data packet of length.
|
||||
*
|
||||
* The set function should return -1 on failure and 0 on success.
|
||||
* Object and id will be passed to this function untouched.
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
|
||||
int id, uint8_t *data, uint16_t length), void *object, int id);
|
||||
|
||||
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
|
@ -134,17 +186,11 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id)
|
|||
*/
|
||||
int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length);
|
||||
|
||||
/* Start a secure connection with other peer who has public_key and ip_port.
|
||||
*
|
||||
* return -1 if failure.
|
||||
* return crypt_connection_id of the initialized connection if everything went well.
|
||||
*/
|
||||
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port);
|
||||
|
||||
/* Kill a crypto connection.
|
||||
*
|
||||
* return 0 if killed successfully.
|
||||
* return 1 if there was a problem.
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int crypto_kill(Net_Crypto *c, int crypt_connection_id);
|
||||
|
||||
|
|
|
@ -796,14 +796,12 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)
|
|||
return friend_num;
|
||||
}
|
||||
|
||||
/* Get the ip of friend friendnum and put it in ip_port
|
||||
*
|
||||
* return -1, -- if client_id does NOT refer to a friend
|
||||
* return 0, -- if client_id refers to a friend and we failed to find the friend (yet)
|
||||
* return 1, ip if client_id refers to a friend and we found him
|
||||
/* Copy friends DHT public key into dht_key.
|
||||
*
|
||||
* return -1 on failure (no key copied).
|
||||
* return 0 on success (key copied).
|
||||
*/
|
||||
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
|
||||
int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
|
||||
{
|
||||
if ((uint32_t)friend_num >= onion_c->num_friends)
|
||||
return -1;
|
||||
|
@ -814,9 +812,28 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
|
|||
if (!onion_c->friends_list[friend_num].is_fake_clientid)
|
||||
return -1;
|
||||
|
||||
return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port);
|
||||
memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the ip of friend friendnum and put it in ip_port
|
||||
*
|
||||
* return -1, -- if client_id does NOT refer to a friend
|
||||
* return 0, -- if client_id refers to a friend and we failed to find the friend (yet)
|
||||
* return 1, ip if client_id refers to a friend and we found him
|
||||
*
|
||||
*/
|
||||
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
|
||||
{
|
||||
uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) != 0)
|
||||
return -1;
|
||||
|
||||
return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port);
|
||||
}
|
||||
|
||||
|
||||
/* Set if friend is online or not.
|
||||
* NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
|
||||
*
|
||||
|
|
|
@ -172,6 +172,13 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
|
|||
*/
|
||||
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
|
||||
|
||||
/* Copy friends DHT public key into dht_key.
|
||||
*
|
||||
* return -1 on failure (no key copied).
|
||||
* return 0 on success (key copied).
|
||||
*/
|
||||
int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
|
||||
|
||||
#define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
|
||||
#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user