int m_addfriend_norequest(uint8_t * client_id) { if (getfriend_id(client_id) != -1) return -1; /* resize the friend list if necessary */ realloc_friendlist(numfriends + 1); uint32_t i; for (i = 0; i <= numfriends; ++i) { if(friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); friendlist[i].status = FRIEND_REQUESTED; friendlist[i].crypt_connection_id = -1; friendlist[i].friend_request_id = -1; memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].statusmessage = calloc(1, 1); friendlist[i].statusmessage_length = 1; friendlist[i].userstatus = USERSTATUS_NONE; friendlist[i].message_id = 0; friendlist[i].receives_read_receipts = 1; /* default: YES */ ++numfriends; return i; } } return -1; }
/* Set a friends DHT public key. * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to * the other peer. * * return -1 on failure. * return 0 on success. */ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key, uint64_t timestamp) { 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].fake_client_id_timestamp >= timestamp) return -1; if (onion_c->friends_list[friend_num].is_fake_clientid) { if (memcmp(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) == 0) { return -1; } DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); } if (DHT_addfriend(onion_c->dht, dht_key) == 1) { return -1; } onion_c->friends_list[friend_num].last_seen = unix_time(); onion_c->friends_list[friend_num].is_fake_clientid = 1; onion_c->friends_list[friend_num].fake_client_id_timestamp = timestamp; memcpy(onion_c->friends_list[friend_num].fake_client_id, dht_key, crypto_box_PUBLICKEYBYTES); return 0; }
int m_addfriend_norequest(Messenger *m, uint8_t *client_id) { if (getfriend_id(m, client_id) != -1) return -1; /* resize the friend list if necessary */ if (realloc_friendlist(m, m->numfriends + 1) != 0) return FAERR_NOMEM; memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); m->friendlist[i].status = FRIEND_CONFIRMED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE); m->friendlist[i].statusmessage = calloc(1, 1); m->friendlist[i].statusmessage_length = 1; m->friendlist[i].userstatus = USERSTATUS_NONE; m->friendlist[i].message_id = 0; m->friendlist[i].receives_read_receipts = 1; /* default: YES */ if (m->numfriends == i) ++ m->numfriends; return i; } } return -1; }
/* add a friend set the data that will be sent along with friend request client_id is the client id of the friend data is the data and length is the length returns the friend number if success return -1 if failure. */ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) { if (length == 0 || length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) return -1; if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) return -1; if (getfriend_id(client_id) != -1) return -1; uint32_t i; for (i = 0; i <= numfriends; ++i) { if(friendlist[i].status == 0) { DHT_addfriend(client_id); friendlist[i].status = 1; friendlist[i].crypt_connection_id = -1; friendlist[i].friend_request_id = -1; memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].userstatus = calloc(1, 1); friendlist[i].userstatus_length = 1; memcpy(friendlist[i].info, data, length); friendlist[i].info_size = length; ++numfriends; return i; } } return -1; }
static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata) { if ((NUM_FIRST == number && !first) || (NUM_LAST == number && !last)) { Onions *on = (Onions *)object; uint16_t count = 0; int ret = DHT_addfriend(on->onion->dht, dht_public_key, &dht_ip_callback, object, number, &count); ck_assert_msg(ret == 0, "DHT_addfriend() did not return 0"); ck_assert_msg(count == 1, "Count not 1, count is %u", count); if (NUM_FIRST == number && !first) { first = 1; if (memcmp(dht_public_key, last_dht_pk, crypto_box_PUBLICKEYBYTES) != 0) { ck_abort_msg("Error wrong dht key."); } return; } if (NUM_LAST == number && !last) { last = 1; if (memcmp(dht_public_key, first_dht_pk, crypto_box_PUBLICKEYBYTES) != 0) { ck_abort_msg("Error wrong dht key."); } return; } ck_abort_msg("Error."); } }
/* Callback for dht public key changes. */ static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key) { Friend_Connections *fr_c = object; Friend_Conn *friend_con = get_conn(fr_c, number); if (!friend_con) return; friend_con->dht_ping_lastrecv = unix_time(); if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) return; if (friend_con->dht_lock) { if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) { printf("a. Could not delete dht peer. Please report this.\n"); return; } friend_con->dht_lock = 0; } DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, object, number, &friend_con->dht_lock); if (friend_con->crypt_connection_id == -1) { friend_new_connection(fr_c, number); } set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, dht_public_key); onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key); memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); }
/* * add a friend * set the data that will be sent along with friend request * client_id is the client id of the friend * data is the data and length is the length * returns the friend number if success * return FA_TOOLONG if message length is too long * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte) * return FAERR_OWNKEY if user's own key * return FAERR_ALREADYSENT if friend request already sent or already a friend * return FAERR_UNKNOWN for unknown error */ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) { if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) return FAERR_TOOLONG; if (length < 1) return FAERR_NOMESSAGE; if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) return FAERR_OWNKEY; if (getfriend_id(client_id) != -1) return FAERR_ALREADYSENT; uint32_t i; for (i = 0; i <= numfriends && i <= MAX_NUM_FRIENDS; ++i) { /*TODO: dynamic memory allocation to allow for more than MAX_NUM_FRIENDS friends */ if(friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); friendlist[i].status = FRIEND_ADDED; friendlist[i].crypt_connection_id = -1; friendlist[i].friend_request_id = -1; memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].userstatus = calloc(1, 1); friendlist[i].userstatus_length = 1; friendlist[i].userstatus_kind = USERSTATUS_KIND_OFFLINE; memcpy(friendlist[i].info, data, length); friendlist[i].info_size = length; ++numfriends; return i; } } return FAERR_UNKNOWN; }
int main(int argc, char *argv[]) { //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); if (argc < 4) { printf("usage %s ip port client_id(of friend to find ip_port of)\n", argv[0]); exit(0); } DHT_addfriend((uint8_t *)argv[3]); //initialize networking //bind to ip 0.0.0.0:PORT IP ip; ip.i = 0; init_networking(ip, PORT); int randdomnum = random_int(); memcpy(self_client_id, &randdomnum, 4); perror("Initialization"); IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); //bootstrap_ip_port.ip.c[0] = 127; //bootstrap_ip_port.ip.c[1] = 0; //bootstrap_ip_port.ip.c[2] = 0; //bootstrap_ip_port.ip.c[3] = 1; 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; while(1) { doDHT(); while(receivepacket(&ip_port, data, &length) != -1) { if(DHT_handlepacket(data, length, ip_port)) { //unhandled packet printpacket(data, length, ip_port); } else { printf("Received handled packet with length: %u\n", length); } } print_clientlist(); print_friendlist(); c_sleep(300); } shutdown_networking(); return 0; }
static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t length) { Onion_Client *onion_c = object; if (length < FAKEID_DATA_MIN_LENGTH) return 1; if (length > FAKEID_DATA_MAX_LENGTH) return 1; if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0) return 1; int friend_num = onion_friend_num(onion_c, source_pubkey); if (friend_num == -1) return 1; uint64_t no_replay; net_to_host(data + 1, sizeof(no_replay)); memcpy(&no_replay, data + 1, sizeof(uint64_t)); if (no_replay <= onion_c->friends_list[friend_num].last_noreplay) return 1; onion_c->friends_list[friend_num].last_noreplay = no_replay; if (memcmp(data + 1 + sizeof(uint64_t), onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) != 0) { DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); onion_c->friends_list[friend_num].last_seen = unix_time(); if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) { return 1; } onion_c->friends_list[friend_num].is_fake_clientid = 1; memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); } uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format); Node_format nodes[num_nodes]; memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes)); uint32_t i; for (i = 0; i < num_nodes; ++i) { to_host_family(&nodes[i].ip_port.ip); DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); } return 0; }
int m_addfriend_norequest(uint8_t * client_id) { if (getfriend_id(client_id) != -1) return -1; uint32_t i; for (i = 0; i <= numfriends; ++i) { if(friendlist[i].status == 0) { DHT_addfriend(client_id); friendlist[i].status = 2; friendlist[i].crypt_connection_id = -1; friendlist[i].friend_request_id = -1; memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].userstatus = calloc(1, 1); friendlist[i].userstatus_length = 1; numfriends++; return i; } } return -1; }
int m_addfriend_norequest(uint8_t * client_id) { if (getfriend_id(client_id) != -1) return -1; uint32_t i; for (i = 0; i <= numfriends && i <= MAX_NUM_FRIENDS; ++i) { /*TODO: dynamic memory allocation to allow for more than MAX_NUM_FRIENDS friends */ if(friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); friendlist[i].status = FRIEND_REQUESTED; friendlist[i].crypt_connection_id = -1; friendlist[i].friend_request_id = -1; memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].userstatus = calloc(1, 1); friendlist[i].userstatus_length = 1; numfriends++; return i; } } return -1; }
static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key) { Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); if (!friend_con) return; friend_con->dht_pk_lastrecv = unix_time(); if (friend_con->dht_lock) { if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) { printf("a. Could not delete dht peer. Please report this.\n"); return; } friend_con->dht_lock = 0; } DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock); memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); }
/* * add a friend * set the data that will be sent along with friend request * client_id is the client id of the friend * data is the data and length is the length * returns the friend number if success * return FA_TOOLONG if message length is too long * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte) * return FAERR_OWNKEY if user's own key * return FAERR_ALREADYSENT if friend request already sent or already a friend * return FAERR_UNKNOWN for unknown error */ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) { if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) return FAERR_TOOLONG; if (length < 1) return FAERR_NOMESSAGE; if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) return FAERR_OWNKEY; if (getfriend_id(client_id) != -1) return FAERR_ALREADYSENT; /* resize the friend list if necessary */ realloc_friendlist(numfriends + 1); uint32_t i; for (i = 0; i <= numfriends; ++i) { if (friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); friendlist[i].status = FRIEND_ADDED; friendlist[i].crypt_connection_id = -1; friendlist[i].friend_request_id = -1; memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].statusmessage = calloc(1, 1); friendlist[i].statusmessage_length = 1; friendlist[i].userstatus = USERSTATUS_NONE; memcpy(friendlist[i].info, data, length); friendlist[i].info_size = length; friendlist[i].message_id = 0; friendlist[i].receives_read_receipts = 1; /* default: YES */ ++numfriends; return i; } } return FAERR_UNKNOWN; }
int main(int argc, char *argv[]) { //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); if (argc < 4) { printf("usage %s ip port public_key\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]); } char temp_id[128]; printf("\nEnter the client_id of the friend you wish to add (32 bytes HEX format):\n"); if(scanf("%s", temp_id) != 1) exit(0); DHT_addfriend(hex_string_to_bin(temp_id)); /* initialize networking */ /* bind to ip 0.0.0.0:PORT */ IP ip; ip.i = 0; init_networking(ip, PORT); perror("Initialization"); IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); /* bootstrap_ip_port.ip.c[0] = 127; * bootstrap_ip_port.ip.c[1] = 0; * bootstrap_ip_port.ip.c[2] = 0; * bootstrap_ip_port.ip.c[3] = 1; */ bootstrap_ip_port.ip.i = inet_addr(argv[1]); DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; while(1) { doDHT(); while(receivepacket(&ip_port, data, &length) != -1) { if(DHT_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) { //unhandled packet printpacket(data, length, ip_port); } else { printf("Received handled packet with length: %u\n", length); } } print_clientlist(); print_friendlist(); c_sleep(300); } shutdown_networking(); return 0; }
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; }
/* * add a friend * set the data that will be sent along with friend request * address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes. TODO: add checksum. * data is the data and length is the length * returns the friend number if success * return FA_TOOLONG if message length is too long * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte) * return FAERR_OWNKEY if user's own key * return FAERR_ALREADYSENT if friend request already sent or already a friend * return FAERR_UNKNOWN for unknown error * return FAERR_BADCHECKSUM if bad checksum in address * return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different * (the nospam for that friend was set to the new one) * return FAERR_NOMEM if increasing the friend list size fails */ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) { if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) return FAERR_TOOLONG; uint8_t client_id[crypto_box_PUBLICKEYBYTES]; memcpy(client_id, address, crypto_box_PUBLICKEYBYTES); uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); memcpy(&check, address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), sizeof(check)); if (check != checksum) return FAERR_BADCHECKSUM; if (length < 1) return FAERR_NOMESSAGE; if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) return FAERR_OWNKEY; int friend_id = getfriend_id(m, client_id); if (friend_id != -1) { uint32_t nospam; memcpy(&nospam, address + crypto_box_PUBLICKEYBYTES, sizeof(nospam)); if (m->friendlist[friend_id].friendrequest_nospam == nospam) return FAERR_ALREADYSENT; m->friendlist[friend_id].friendrequest_nospam = nospam; return FAERR_SETNEWNOSPAM; } /* resize the friend list if necessary */ if (realloc_friendlist(m, m->numfriends + 1) != 0) return FAERR_NOMEM; memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); m->friendlist[i].status = FRIEND_ADDED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; m->friendlist[i].friendrequest_timeout = FRIENDREQUEST_TIMEOUT; memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE); m->friendlist[i].statusmessage = calloc(1, 1); m->friendlist[i].statusmessage_length = 1; m->friendlist[i].userstatus = USERSTATUS_NONE; memcpy(m->friendlist[i].info, data, length); m->friendlist[i].info_size = length; m->friendlist[i].message_id = 0; m->friendlist[i].receives_read_receipts = 1; /* default: YES */ memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); if (m->numfriends == i) ++ m->numfriends; return i; } } return FAERR_UNKNOWN; }