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:
irungentoo 2014-05-02 21:25:23 -04:00
parent 8ae0a79305
commit db78c99ff4
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
5 changed files with 526 additions and 333 deletions

View File

@ -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);
}
}
}

View File

@ -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?
}
}
}

View File

@ -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);

View File

@ -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.
*

View File

@ -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)