/* Try to send a friendrequest to peer with public_key data is the data in the request and length is the length. return -1 if failure. return 0 if it sent the friend request directly to the friend. return the number of peers it was routed through if it did not send it directly.*/ int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length) { uint8_t packet[MAX_DATA_SIZE]; int len = create_request(packet, public_key, data, length, 32); /* 32 is friend request packet id */ if (len == -1) return -1; IP_Port ip_port = DHT_getfriendip(public_key); if (ip_port.ip.i == 1) return -1; if (ip_port.ip.i != 0) { if (sendpacket(ip_port, packet, len) != -1) return 0; return -1; } int num = route_tofriend(public_key, packet, len); if (num == 0) return -1; return num; }
void print_friendlist() { uint32_t i, j, k; IP_Port p_ip; printf("_________________FRIENDS__________________________________\n"); for(k = 0; k < num_friends; k++) { printf("FRIEND %u\n", k); printf("ID: "); for(j = 0; j < 32; j++) { printf("%c", friends_list[k].client_id[j]); } p_ip = DHT_getfriendip(friends_list[k].client_id); printf("\nIP: %u.%u.%u.%u:%u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); printf("\nCLIENTS IN LIST:\n\n"); for(i = 0; i < 4; i++) { printf("ClientID: "); for(j = 0; j < 32; j++) { if(friends_list[k].client_list[i].client_id[j] < 16) printf("0"); printf("%hhX", friends_list[k].client_list[i].client_id[j]); } p_ip = friends_list[k].client_list[i].ip_port; printf("\nIP: %u.%u.%u.%u:%u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); printf("\nTimestamp: %llu",(long long unsigned int) friends_list[k].client_list[i].timestamp); printf("\nLast pinged: %llu\n",(long long unsigned int) friends_list[k].client_list[i].last_pinged); p_ip = friends_list[k].client_list[i].ret_ip_port; printf("ret IP: %u.%u.%u.%u:%u\n",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); printf("Timestamp: %llu\n", (long long unsigned int)friends_list[k].client_list[i].ret_timestamp); } } }
/* Try to send a friend request to peer with public_key. * data is the data in the request and length is the length. * return -1 if failure. * return 0 if it sent the friend request directly to the friend. * return the number of peers it was routed through if it did not send it directly. */ int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) { if (length + sizeof(nospam_num) > MAX_DATA_SIZE) return -1; uint8_t temp[MAX_DATA_SIZE]; memcpy(temp, &nospam_num, sizeof(nospam_num)); memcpy(temp + sizeof(nospam_num), data, length); uint8_t packet[MAX_DATA_SIZE]; int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, temp, length + sizeof(nospam_num), CRYPTO_PACKET_FRIEND_REQ); if (len == -1) return -1; IP_Port ip_port = DHT_getfriendip(dht, public_key); if (ip_port.ip.uint32 == 1) return -1; if (ip_port.ip.uint32 != 0) { if (sendpacket(dht->c->lossless_udp->net->sock, ip_port, packet, len) != -1) return 0; return -1; } int num = route_tofriend(dht, public_key, packet, len); if (num == 0) return -1; return 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 * */ int onion_getfriendip(const 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); }
/* 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) { if ((uint32_t)friend_num >= onion_c->num_friends) return -1; if (onion_c->friends_list[friend_num].status == 0) return -1; 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); }
/* Add nodes to the to_ping list. * All nodes in this list are pinged every TIME_TO_PING seconds * and are then removed from the list. * If the list is full the nodes farthest from our public_key are replaced. * The purpose of this list is to enable quick integration of new nodes into the * network while preventing amplification attacks. * * return 0 if node was added. * return -1 if node was not added. */ int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port) { if (!ip_isset(&ip_port.ip)) { return -1; } if (!node_addable_to_close_list(ping->dht, public_key, ip_port)) { return -1; } if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) { return -1; } IP_Port temp; if (DHT_getfriendip(ping->dht, public_key, &temp) == 0) { send_ping_request(ping, ip_port, public_key); return -1; } unsigned int i; for (i = 0; i < MAX_TO_PING; ++i) { if (!ip_isset(&ping->to_ping[i].ip_port.ip)) { memcpy(ping->to_ping[i].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); ipport_copy(&ping->to_ping[i].ip_port, &ip_port); return 0; } if (public_key_cmp(ping->to_ping[i].public_key, public_key) == 0) { return -1; } } if (add_to_list(ping->to_ping, MAX_TO_PING, public_key, ip_port, ping->dht->self_public_key)) { return 0; } return -1; }
int main(int argc, char *argv[]) { if (argc < 4) { printf("usage %s ip port filename(of file to send)\n", argv[0]); exit(0); } new_keys(); printf("OUR ID: "); uint32_t i; for(i = 0; i < 32; i++) { if(self_public_key[i] < 16) printf("0"); printf("%hhX",self_public_key[i]); } printf("\n"); memcpy(self_client_id, self_public_key, 32); char temp_id[128]; printf("Enter the client_id of the friend to connect to (32 bytes HEX format):\n"); scanf("%s", temp_id); uint8_t friend_id[32]; memcpy(friend_id, hex_string_to_bin(temp_id), 32); /* memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); */ DHT_addfriend(friend_id); IP_Port friend_ip; int connection = -1; int inconnection = -1; uint8_t acceptedfriend_public_key[crypto_box_PUBLICKEYBYTES]; int friendrequest = -1; uint8_t request_data[512]; /* initialize networking * bind to ip 0.0.0.0:PORT */ IP ip; ip.i = 0; init_networking(ip, PORT); initNetCrypto(); perror("Initialization"); IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); bootstrap_ip_port.ip.i = inet_addr(argv[1]); DHT_bootstrap(bootstrap_ip_port); IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; uint8_t buffer1[128]; int read1 = 0; uint8_t buffer2[128]; int read2 = 0; FILE *file1 = fopen(argv[3], "rb"); if ( file1==NULL ){printf("Error opening file.\n");return 1;} FILE *file2 = fopen("received.txt", "wb"); if ( file2==NULL ){return 1;} read1 = fread(buffer1, 1, 128, file1); while(1) { while(receivepacket(&ip_port, data, &length) != -1) { if(rand() % 3 != 1) { /* simulate packet loss */ if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) { /* if packet is not recognized */ printf("Received unhandled packet with length: %u\n", length); } else { printf("Received handled packet with length: %u\n", length); } } } friend_ip = DHT_getfriendip(friend_id); if(friend_ip.ip.i != 0) { if(connection == -1 && friendrequest == -1) { printf("Sending friend request to peer:"); printip(friend_ip); friendrequest = send_friendrequest(friend_id, friend_ip,(uint8_t *) "Hello World", 12); /* connection = crypto_connect((uint8_t *)friend_id, friend_ip); */ /* connection = new_connection(friend_ip); */ } if(check_friendrequest(friendrequest) == 1) { printf("Started connecting to friend:"); connection = crypto_connect(friend_id, friend_ip); } } if(inconnection == -1) { uint8_t secret_nonce[crypto_box_NONCEBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES]; inconnection = crypto_inbound(public_key, secret_nonce, session_key); inconnection = accept_crypto_inbound(inconnection, acceptedfriend_public_key, secret_nonce, session_key); /* inconnection = incoming_connection(); */ if(inconnection != -1) { printf("Someone connected to us:\n"); /* printip(connection_ip(inconnection)); */ } } if(handle_friendrequest(acceptedfriend_public_key, request_data) > 1) { printf("RECIEVED FRIEND REQUEST: %s\n", request_data); } /* if someone connected to us write what he sends to a file * also send him our file. */ if(inconnection != -1) { if(write_cryptpacket(inconnection, buffer1, read1)) { printf("Wrote data1.\n"); read1 = fread(buffer1, 1, 128, file1); } read2 = read_cryptpacket(inconnection, buffer2); if(read2 != 0) { printf("Received data1.\n"); if(!fwrite(buffer2, read2, 1, file2)) { printf("file write error1\n"); } if(read2 < 128) { printf("Closed file1 %u\n", read2); fclose(file2); } } /* if buffer is empty and the connection timed out. */ else if(is_cryptoconnected(inconnection) == 4) { crypto_kill(inconnection); } } /* if we are connected to a friend send him data from the file. * also put what he sends us in a file. */ if(is_cryptoconnected(connection) >= 3) { if(write_cryptpacket(0, buffer1, read1)) { printf("Wrote data2.\n"); read1 = fread(buffer1, 1, 128, file1); } read2 = read_cryptpacket(0, buffer2); if(read2 != 0) { printf("Received data2.\n"); if(!fwrite(buffer2, read2, 1, file2)) { printf("file write error2\n"); } if(read2 < 128) { printf("Closed file2 %u\n", read2); fclose(file2); } } /* if buffer is empty and the connection timed out. */ else if(is_cryptoconnected(connection) == 4) { crypto_kill(connection); } } doDHT(); doLossless_UDP(); doNetCrypto(); /*print_clientlist(); *print_friendlist(); *c_sleep(300); */ c_sleep(1); } shutdown_networking(); return 0; }
//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. static void doFriends() { /* 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 == 1) { 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 */ friendlist[i].status = 2; else if (fr > 0) friendlist[i].status = 2; } if (friendlist[i].status == 2 || friendlist[i].status == 3) { /* friend is not online */ if (friendlist[i].status == 2) { 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 */ friendlist[i].status = 4; break; case 4: crypto_kill(friendlist[i].crypt_connection_id); friendlist[i].crypt_connection_id = -1; break; default: break; } } while (friendlist[i].status == 4) { /* 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].userstatus_sent == 0) { if (send_userstatus(i, self_userstatus, self_userstatus_len)) friendlist[i].userstatus_sent = 1; } len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); if (len > 0) { switch (temp[0]) { case PACKET_ID_NICKNAME: { if (len >= MAX_NAME_LENGTH + 1 || len == 1) break; if(friend_namechange_isset) friend_namechange(i, temp + 1, len - 1); memcpy(friendlist[i].name, temp + 1, len - 1); friendlist[i].name[len - 2] = 0; /* make sure the NULL terminator is present. */ break; } case PACKET_ID_USERSTATUS: { uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1); memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH)); if (friend_statuschange_isset) friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); free(status); break; } case PACKET_ID_MESSAGE: { if (friend_message_isset) (*friend_message)(i, temp + 1, len - 1); 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; friendlist[i].status = 3; } 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); } } } }