/** * Return the null-terminated status message of a Tox friend. Must be freed. */ char * twc_get_status_message_nt(Tox *tox, int32_t friend_number) { TOX_ERR_FRIEND_QUERY err; size_t length = tox_friend_get_status_message_size(tox, friend_number, &err); if ((err != TOX_ERR_FRIEND_QUERY_OK) || (length == SIZE_MAX)) { char *msg = malloc(1); *msg = 0; return msg; } uint8_t message[length]; tox_friend_get_status_message(tox, friend_number, message, &err); return twc_null_terminate(message, length); }
void Core::loadFriends() { const uint32_t friendCount = tox_self_get_friend_list_size(tox); if (friendCount > 0) { // assuming there are not that many friends to fill up the whole stack uint32_t *ids = new uint32_t[friendCount]; tox_self_get_friend_list(tox, ids); uint8_t clientId[TOX_PUBLIC_KEY_SIZE]; for (int32_t i = 0; i < static_cast<int32_t>(friendCount); ++i) { if (tox_friend_get_public_key(tox, ids[i], clientId, nullptr)) { emit friendAdded(ids[i], CUserId::toString(clientId)); const size_t nameSize = tox_friend_get_name_size(tox, ids[i], nullptr); if (nameSize && nameSize != SIZE_MAX) { uint8_t *name = new uint8_t[nameSize]; if (tox_friend_get_name(tox, ids[i], name, nullptr)) emit friendUsernameChanged(ids[i], CString::toString(name, nameSize)); delete[] name; } const size_t statusMessageSize = tox_friend_get_status_message_size(tox, ids[i], nullptr); if (statusMessageSize != SIZE_MAX) { uint8_t *statusMessage = new uint8_t[statusMessageSize]; if (tox_friend_get_status_message(tox, ids[i], statusMessage, nullptr)) { emit friendStatusMessageChanged(ids[i], CString::toString(statusMessage, statusMessageSize)); } delete[] statusMessage; } checkLastOnline(ids[i]); } } delete[] ids; } }
void utox_friend_init(Tox *tox, uint32_t friend_number){ int size; // get friend pointer FRIEND *f = &friend[friend_number]; uint8_t name[TOX_MAX_NAME_LENGTH]; // Set scroll position to bottom of window. f->msg.scroll = 1.0; // Get and set the public key for this friend number and set it. tox_friend_get_public_key(tox, friend_number, f->cid, 0); // Set the friend number we got from toxcore f->number = friend_number; // Get and set friend name and length size = tox_friend_get_name_size(tox, friend_number, 0); tox_friend_get_name(tox, friend_number, name, 0); // Set the name for utox as well friend_setname(f, name, size); // Get and set the status message size = tox_friend_get_status_message_size(tox, friend_number, 0); f->status_message = malloc(size); tox_friend_get_status_message(tox, friend_number, f->status_message, 0); f->status_length = size; // Get the hex version of this friends ID char_t cid[TOX_PUBLIC_KEY_SIZE * 2]; cid_to_string(cid, f->cid); init_avatar(&f->avatar, cid, NULL, NULL); // Get the chat backlog log_read(tox, friend_number); // Load the meta data, if it exists. friend_meta_data_read(tox, friend_number); }
static void friendlist_onDraw(ToxWindow *self, Tox *m) { curs_set(0); werase(self->window); int x2, y2; getmaxyx(self->window, y2, x2); bool fix_statuses = x2 != self->x; /* true if window max x value has changed */ wattron(self->window, COLOR_PAIR(CYAN)); wprintw(self->window, " Press the"); wattron(self->window, A_BOLD); wprintw(self->window, " h "); wattroff(self->window, A_BOLD); wprintw(self->window, "key for help\n\n"); wattroff(self->window, COLOR_PAIR(CYAN)); if (blocklist_view == 1) { blocklist_onDraw(self, m, y2, x2); return; } uint64_t cur_time = time(NULL); struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); wattron(self->window, A_BOLD); wprintw(self->window, " Online: "); wattroff(self->window, A_BOLD); wprintw(self->window, "%d/%d \n\n", Friends.num_online, Friends.num_friends); if ((y2 - FLIST_OFST) <= 0) return; uint32_t selected_num = 0; /* Determine which portion of friendlist to draw based on current position */ pthread_mutex_lock(&Winthread.lock); int page = Friends.num_selected / (y2 - FLIST_OFST); pthread_mutex_unlock(&Winthread.lock); int start = (y2 - FLIST_OFST) * page; int end = y2 - FLIST_OFST + start; pthread_mutex_lock(&Winthread.lock); size_t num_friends = Friends.num_friends; pthread_mutex_unlock(&Winthread.lock); int i; for (i = start; i < num_friends && i < end; ++i) { pthread_mutex_lock(&Winthread.lock); uint32_t f = Friends.index[i]; bool is_active = Friends.list[f].active; int num_selected = Friends.num_selected; pthread_mutex_unlock(&Winthread.lock); bool f_selected = false; if (is_active) { if (i == num_selected) { wattron(self->window, A_BOLD); wprintw(self->window, " > "); wattroff(self->window, A_BOLD); selected_num = f; f_selected = true; } else { wprintw(self->window, " "); } pthread_mutex_lock(&Winthread.lock); TOX_CONNECTION connection_status = Friends.list[f].connection_status; TOX_USER_STATUS status = Friends.list[f].status; pthread_mutex_unlock(&Winthread.lock); if (connection_status != TOX_CONNECTION_NONE) { int colour = MAGENTA; switch (status) { case TOX_USER_STATUS_NONE: colour = GREEN; break; case TOX_USER_STATUS_AWAY: colour = YELLOW; break; case TOX_USER_STATUS_BUSY: colour = RED; break; } wattron(self->window, COLOR_PAIR(colour) | A_BOLD); wprintw(self->window, "%s ", ONLINE_CHAR); wattroff(self->window, COLOR_PAIR(colour) | A_BOLD); if (f_selected) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); pthread_mutex_lock(&Winthread.lock); wprintw(self->window, "%s", Friends.list[f].name); pthread_mutex_unlock(&Winthread.lock); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); /* Reset Friends.list[f].statusmsg on window resize */ if (fix_statuses) { char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH]; pthread_mutex_lock(&Winthread.lock); tox_friend_get_status_message(m, Friends.list[f].num, (uint8_t *) statusmsg, NULL); size_t s_len = tox_friend_get_status_message_size(m, Friends.list[f].num, NULL); pthread_mutex_unlock(&Winthread.lock); statusmsg[s_len] = '\0'; filter_str(statusmsg, s_len); pthread_mutex_lock(&Winthread.lock); snprintf(Friends.list[f].statusmsg, sizeof(Friends.list[f].statusmsg), "%s", statusmsg); Friends.list[f].statusmsg_len = strlen(Friends.list[f].statusmsg); pthread_mutex_unlock(&Winthread.lock); } /* Truncate note if it doesn't fit on one line */ size_t maxlen = x2 - getcurx(self->window) - 2; pthread_mutex_lock(&Winthread.lock); if (Friends.list[f].statusmsg_len > maxlen) { Friends.list[f].statusmsg[maxlen - 3] = '\0'; strcat(Friends.list[f].statusmsg, "..."); Friends.list[f].statusmsg[maxlen] = '\0'; Friends.list[f].statusmsg_len = maxlen; } if (Friends.list[f].statusmsg_len > 0) wprintw(self->window, " %s", Friends.list[f].statusmsg); pthread_mutex_unlock(&Winthread.lock); wprintw(self->window, "\n"); } else { wprintw(self->window, "%s ", OFFLINE_CHAR); if (f_selected) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); pthread_mutex_lock(&Winthread.lock); wprintw(self->window, "%s", Friends.list[f].name); pthread_mutex_unlock(&Winthread.lock); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); pthread_mutex_lock(&Winthread.lock); uint64_t last_seen = Friends.list[f].last_online.last_on; pthread_mutex_unlock(&Winthread.lock); if (last_seen != 0) { pthread_mutex_lock(&Winthread.lock); int day_dist = ( cur_loc_tm.tm_yday - Friends.list[f].last_online.tm.tm_yday + ((cur_loc_tm.tm_year - Friends.list[f].last_online.tm.tm_year) * 365) ); const char *hourmin = Friends.list[f].last_online.hour_min_str; pthread_mutex_unlock(&Winthread.lock); switch (day_dist) { case 0: wprintw(self->window, " Last seen: Today %s\n", hourmin); break; case 1: wprintw(self->window, " Last seen: Yesterday %s\n", hourmin); break; default: wprintw(self->window, " Last seen: %d days ago\n", day_dist); break; } } else { wprintw(self->window, " Last seen: Never\n"); } } } } self->x = x2; if (num_friends) { wmove(self->window, y2 - 1, 1); wattron(self->window, A_BOLD); wprintw(self->window, "Key: "); wattroff(self->window, A_BOLD); int i; for (i = 0; i < TOX_PUBLIC_KEY_SIZE; ++i) wprintw(self->window, "%02X", Friends.list[selected_num].pub_key[i] & 0xff); } wrefresh(self->window); draw_del_popup(); if (self->help->active) help_onDraw(self); }
static void test_set_status_message(void) { printf("initialising 2 toxes\n"); uint32_t index[] = { 1, 2 }; const time_t cur_time = time(nullptr); Tox *const tox1 = tox_new_log(nullptr, nullptr, &index[0]); Tox *const tox2 = tox_new_log(nullptr, nullptr, &index[1]); ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances"); printf("tox1 adds tox2 as friend, tox2 adds tox1\n"); uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_public_key(tox2, public_key); tox_friend_add_norequest(tox1, public_key, nullptr); tox_self_get_public_key(tox1, public_key); tox_friend_add_norequest(tox2, public_key, nullptr); printf("bootstrapping tox2 off tox1\n"); uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_dht_id(tox1, dht_key); const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr); tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr); while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE || tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE) { tox_iterate(tox1, nullptr); tox_iterate(tox2, nullptr); c_sleep(ITERATION_INTERVAL); } printf("toxes are online, took %ld seconds\n", time(nullptr) - cur_time); const time_t con_time = time(nullptr); while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP || tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP) { tox_iterate(tox1, nullptr); tox_iterate(tox2, nullptr); c_sleep(ITERATION_INTERVAL); } printf("tox clients connected took %ld seconds\n", time(nullptr) - con_time); TOX_ERR_SET_INFO err_n; tox_callback_friend_status_message(tox2, status_callback); bool ret = tox_self_set_status_message(tox1, (const uint8_t *)STATUS_MESSAGE, sizeof(STATUS_MESSAGE), &err_n); ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %u\n", err_n); bool status_updated = false; while (!status_updated) { tox_iterate(tox1, nullptr); tox_iterate(tox2, &status_updated); c_sleep(ITERATION_INTERVAL); } ck_assert_msg(tox_friend_get_status_message_size(tox2, 0, nullptr) == sizeof(STATUS_MESSAGE), "status message length not correct"); uint8_t cmp_status[sizeof(STATUS_MESSAGE)]; tox_friend_get_status_message(tox2, 0, cmp_status, nullptr); ck_assert_msg(memcmp(cmp_status, STATUS_MESSAGE, sizeof(STATUS_MESSAGE)) == 0, "status message not correct"); printf("test_set_status_message succeeded, took %ld seconds\n", time(nullptr) - cur_time); tox_kill(tox1); tox_kill(tox2); }
int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); Tox *const tox1 = tox_new_log(nullptr, nullptr, nullptr); Tox *const tox2 = tox_new_log(nullptr, nullptr, nullptr); printf("bootstrapping tox2 off tox1\n"); uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_dht_id(tox1, dht_key); const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr); tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr); struct test_data to_compare = {{0}}; uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_public_key(tox1, public_key); tox_friend_add_norequest(tox2, public_key, nullptr); tox_self_get_public_key(tox2, public_key); tox_friend_add_norequest(tox1, public_key, nullptr); uint8_t reference_name[TOX_MAX_NAME_LENGTH] = { 0 }; uint8_t reference_status[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 }; set_random(tox1, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox2, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox1, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); set_random(tox2, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); tox_self_get_name(tox2, reference_name); tox_self_get_status_message(tox2, reference_status); tox_callback_friend_name(tox1, namechange_callback); tox_callback_friend_status_message(tox1, statuschange_callback); while (true) { if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2) && tox_friend_get_connection_status(tox1, 0, nullptr) == TOX_CONNECTION_UDP) { printf("Connected.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, nullptr); c_sleep(tox_iteration_interval(tox1)); } while (true) { if (to_compare.received_name && to_compare.received_status_message) { printf("Exchanged names and status messages.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, nullptr); c_sleep(tox_iteration_interval(tox1)); } size_t save_size = tox_get_savedata_size(tox1); VLA(uint8_t, savedata, save_size); tox_get_savedata(tox1, savedata); struct Tox_Options *const options = tox_options_new(nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_data(options, savedata, save_size); Tox *const tox_to_compare = tox_new_log(options, nullptr, nullptr); tox_friend_get_name(tox_to_compare, 0, to_compare.name, nullptr); tox_friend_get_status_message(tox_to_compare, 0, to_compare.status_message, nullptr); ck_assert_msg(memcmp(reference_name, to_compare.name, TOX_MAX_NAME_LENGTH) == 0, "incorrect name: should be all zeroes"); ck_assert_msg(memcmp(reference_status, to_compare.status_message, TOX_MAX_STATUS_MESSAGE_LENGTH) == 0, "incorrect status message: should be all zeroes"); tox_options_free(options); tox_kill(tox1); tox_kill(tox2); tox_kill(tox_to_compare); return 0; }
int main(int argc, char *argv[]) { Tox *tox1 = tox_new_log(0, 0, 0); Tox *tox2 = tox_new_log(0, 0, 0); struct test_data to_compare = { { 0 } }; uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_public_key(tox1, public_key); tox_friend_add_norequest(tox2, public_key, NULL); tox_self_get_public_key(tox2, public_key); tox_friend_add_norequest(tox1, public_key, NULL); uint8_t reference_name[TOX_MAX_NAME_LENGTH] = { 0 }; uint8_t reference_status[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 }; set_random(tox1, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox2, tox_self_set_name, TOX_MAX_NAME_LENGTH); set_random(tox1, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); set_random(tox2, tox_self_set_status_message, TOX_MAX_STATUS_MESSAGE_LENGTH); tox_self_get_name(tox2, reference_name); tox_self_get_status_message(tox2, reference_status); tox_callback_friend_name(tox1, namechange_callback); tox_callback_friend_status_message(tox1, statuschange_callback); while (true) { if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2) && tox_friend_get_connection_status(tox1, 0, 0) == TOX_CONNECTION_UDP) { printf("Connected.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, NULL); c_sleep(tox_iteration_interval(tox1)); } while (true) { if (to_compare.received_name && to_compare.received_status_message) { printf("Exchanged names and status messages.\n"); break; } tox_iterate(tox1, &to_compare); tox_iterate(tox2, NULL); c_sleep(tox_iteration_interval(tox1)); } size_t save_size = tox_get_savedata_size(tox1); VLA(uint8_t, savedata, save_size); tox_get_savedata(tox1, savedata); struct Tox_Options *options = tox_options_new(NULL); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_data(options, savedata, save_size); Tox *tox_to_compare = tox_new(options, 0); tox_friend_get_name(tox_to_compare, 0, to_compare.name, 0); tox_friend_get_status_message(tox_to_compare, 0, to_compare.status_message, 0); assert(memcmp(reference_name, to_compare.name, TOX_MAX_NAME_LENGTH) == 0); assert(memcmp(reference_status, to_compare.status_message, TOX_MAX_STATUS_MESSAGE_LENGTH) == 0); tox_options_free(options); tox_kill(tox1); tox_kill(tox2); tox_kill(tox_to_compare); return 0; }