//TODO: make this function not suck. static void doFriends(void) { /* TODO: add incoming connections and some other stuff. */ uint32_t i; int len; uint8_t temp[MAX_DATA_SIZE]; for (i = 0; i < numfriends; ++i) { if (friendlist[i].status == FRIEND_ADDED) { int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */ set_friend_status(i, FRIEND_REQUESTED); else if (fr > 0) set_friend_status(i, FRIEND_REQUESTED); } if (friendlist[i].status == FRIEND_REQUESTED || friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */ if (friendlist[i].status == FRIEND_REQUESTED) { if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/ send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); friendlist[i].friend_request_id = unix_time(); } } IP_Port friendip = DHT_getfriendip(friendlist[i].client_id); switch (is_cryptoconnected(friendlist[i].crypt_connection_id)) { case 0: if (friendip.ip.i > 1) friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip); break; case 3: /* Connection is established */ set_friend_status(i, FRIEND_ONLINE); friendlist[i].name_sent = 0; friendlist[i].userstatus_sent = 0; friendlist[i].statusmessage_sent = 0; break; case 4: crypto_kill(friendlist[i].crypt_connection_id); friendlist[i].crypt_connection_id = -1; break; default: break; } } while (friendlist[i].status == FRIEND_ONLINE) { /* friend is online */ if (friendlist[i].name_sent == 0) { if (m_sendname(i, self_name, self_name_length)) friendlist[i].name_sent = 1; } if (friendlist[i].statusmessage_sent == 0) { if (send_statusmessage(i, self_statusmessage, self_statusmessage_length)) friendlist[i].statusmessage_sent = 1; } if (friendlist[i].userstatus_sent == 0) { if (send_userstatus(i, self_userstatus)) friendlist[i].userstatus_sent = 1; } len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); uint8_t packet_id = temp[0]; uint8_t* data = temp + 1; int data_length = len - 1; if (len > 0) { switch (packet_id) { case PACKET_ID_NICKNAME: { if (data_length >= MAX_NAME_LENGTH || data_length == 0) break; if(friend_namechange_isset) friend_namechange(i, data, data_length); memcpy(friendlist[i].name, data, data_length); friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */ break; } case PACKET_ID_STATUSMESSAGE: { if (data_length == 0) break; uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1); memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); if (friend_statusmessagechange_isset) friend_statusmessagechange(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); set_friend_statusmessage(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); free(status); break; } case PACKET_ID_USERSTATUS: { if (data_length != 1) break; USERSTATUS status = data[0]; if (friend_userstatuschange_isset) friend_userstatuschange(i, status); set_friend_userstatus(i, status); break; } case PACKET_ID_MESSAGE: { uint8_t *message_id = data; uint8_t message_id_length = 4; uint8_t *message = data + message_id_length; uint16_t message_length = data_length - message_id_length; if (friendlist[i].receives_read_receipts) { write_cryptpacket_id(i, PACKET_ID_RECEIPT, message_id, message_id_length); } if (friend_message_isset) (*friend_message)(i, message, message_length); break; } case PACKET_ID_ACTION: { if (friend_action_isset) (*friend_action)(i, data, data_length); break; } case PACKET_ID_RECEIPT: { uint32_t msgid; if (data_length < sizeof(msgid)) break; memcpy(&msgid, data, sizeof(msgid)); msgid = ntohl(msgid); if (read_receipt_isset) (*read_receipt)(i, msgid); break; } } } else { if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ crypto_kill(friendlist[i].crypt_connection_id); friendlist[i].crypt_connection_id = -1; set_friend_status(i, FRIEND_CONFIRMED); } break; } } } }
//TODO: make this function not suck. void doFriends(Messenger *m) { /* TODO: add incoming connections and some other stuff. */ uint32_t i; int len; uint8_t temp[MAX_DATA_SIZE]; uint64_t temp_time = unix_time(); for (i = 0; i < m->numfriends; ++i) { if (m->friendlist[i].status == FRIEND_ADDED) { int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, m->friendlist[i].info_size); if (fr >= 0) { set_friend_status(m, i, FRIEND_REQUESTED); m->friendlist[i].friendrequest_lastsent = temp_time; } } if (m->friendlist[i].status == FRIEND_REQUESTED || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */ if (m->friendlist[i].status == FRIEND_REQUESTED) { /* If we didn't connect to friend after successfully sending him a friend request the request is deemed unsuccessful so we set the status back to FRIEND_ADDED and try again.*/ if (m->friendlist[i].friendrequest_lastsent + m->friendlist[i].friendrequest_timeout < temp_time) { set_friend_status(m, i, FRIEND_ADDED); /* Double the default timeout everytime if friendrequest is assumed to have been sent unsuccessfully. */ m->friendlist[i].friendrequest_timeout *= 2; } } IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id); switch (is_cryptoconnected(m->friendlist[i].crypt_connection_id)) { case 0: if (friendip.ip.i > 1) m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip); break; case 3: /* 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 4: crypto_kill(m->friendlist[i].crypt_connection_id); m->friendlist[i].crypt_connection_id = -1; break; default: break; } } while (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; } if (m->friendlist[i].statusmessage_sent == 0) { if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) m->friendlist[i].statusmessage_sent = 1; } if (m->friendlist[i].userstatus_sent == 0) { if (send_userstatus(m, i, m->userstatus)) m->friendlist[i].userstatus_sent = 1; } if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { send_ping(m, i); } len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp); uint8_t packet_id = temp[0]; uint8_t *data = temp + 1; int data_length = len - 1; if (len > 0) { switch (packet_id) { case PACKET_ID_PING: { m->friendlist[i].ping_lastrecv = temp_time; break; } case PACKET_ID_NICKNAME: { if (data_length >= MAX_NAME_LENGTH || data_length == 0) break; if (m->friend_namechange) m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata); memcpy(m->friendlist[i].name, data, data_length); m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */ break; } case PACKET_ID_STATUSMESSAGE: { if (data_length == 0) break; uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1); memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); if (m->friend_statusmessagechange) m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH), m->friend_statuschange_userdata); set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); free(status); break; } case PACKET_ID_USERSTATUS: { if (data_length != 1) break; USERSTATUS status = data[0]; if (m->friend_userstatuschange) m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); set_friend_userstatus(m, i, status); break; } case PACKET_ID_MESSAGE: { uint8_t *message_id = data; uint8_t message_id_length = 4; uint8_t *message = data + message_id_length; uint16_t message_length = data_length - message_id_length; 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, message_length, m->friend_message_userdata); break; } case PACKET_ID_ACTION: { if (m->friend_action) (*m->friend_action)(m, i, data, data_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; } } } else { if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ crypto_kill(m->friendlist[i].crypt_connection_id); m->friendlist[i].crypt_connection_id = -1; set_friend_status(m, i, FRIEND_CONFIRMED); } break; } if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { /* if we stopped recieving ping packets kill it */ crypto_kill(m->friendlist[i].crypt_connection_id); m->friendlist[i].crypt_connection_id = -1; set_friend_status(m, i, FRIEND_CONFIRMED); } } } }