/** * Add a friend message to the message queue and tries to send it if the * friend is online. Handles splitting of messages. (TODO: actually split messages) */ void twc_message_queue_add_friend_message(struct t_twc_profile *profile, int32_t friend_number, const char *message, enum TWC_MESSAGE_TYPE message_type) { struct t_twc_queued_message *queued_message = malloc(sizeof(struct t_twc_queued_message)); time_t rawtime = time(NULL); queued_message->time = malloc(sizeof(struct tm)); memcpy(queued_message->time, gmtime(&rawtime), sizeof(struct tm)); queued_message->message = strdup(message); queued_message->message_type = message_type; // create a queue if needed and add message struct t_twc_list *message_queue = twc_message_queue_get_or_create(profile, friend_number); twc_list_item_new_data_add(message_queue, queued_message); // flush if friend is online if (profile->tox && tox_get_friend_connection_status(profile->tox, friend_number) == 1) twc_message_queue_flush_friend(profile, friend_number); }
static void chat_onInit(ToxWindow *self, Tox *m) { int x2, y2; getmaxyx(self->window, y2, x2); self->x = x2; /* Init statusbar info */ StatusBar *statusbar = self->stb; statusbar->status = tox_get_user_status(m, self->num); statusbar->is_online = tox_get_friend_connection_status(m, self->num) == 1; uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; tox_get_status_message(m, self->num, statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); statusbar->statusmsg_len = tox_get_status_message_size(m, self->num); /* Init subwindows */ ChatContext *ctx = self->chatwin; statusbar->topline = subwin(self->window, 2, x2, 0, 0); ctx->history = subwin(self->window, y2-CHATBOX_HEIGHT+1, x2, 0, 0); scrollok(ctx->history, 1); ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2-CHATBOX_HEIGHT, 0); wprintw(ctx->history, "\n\n"); execute(ctx->history, self, m, "/help", CHAT_COMMAND_MODE); wmove(self->window, y2 - CURS_Y_OFFSET, 0); }
/** * read message from remote message queue, and send to remote * this will only send one message in the message queue * and write_data_remote will be block at the same time */ void send_data_remote(){ MSGTask *mTask = front(msg_task_queue); // 开始处理 int friend_num = tox_get_friend_number(my_tox,mTask->target_addr_bin); int res = -1; int retry_count = 0; //debug_msg_bin(mTask->msg); while(res <=0 && retry_count <5){ res = tox_send_message(my_tox,friend_num,mTask->msg,MY_MESSAGE_LENGTH); retry_count += 1; } if(retry_count < 5){ Dequeue(msg_task_queue); pthread_cond_broadcast(&msg_task_cond); }else{ // check target online status if(tox_get_friend_connection_status(my_tox,friend_num) != 1){ // target offline Dequeue(msg_task_queue); pthread_cond_broadcast(&msg_task_cond); // unpack msg to get uuid uint8_t *uuid = (uint8_t *)malloc(sizeof(uint8_t)*UUID_LENGTH+1); memset(uuid,'\0',UUID_LENGTH+1); uint8_t *cmd = (uint8_t *)malloc(sizeof(uint8_t)*CMD_STR_LENGTH); uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t)*MY_MESSAGE_LENGTH); uint32_t *length = (uint32_t *)malloc(sizeof(uint32_t)); unpack_msg_bin(mTask->msg, uuid, cmd, data, length); // get socket fd by uuid int32_t sockfd = get_local_socks(msocks_list,uuid); // close socket close_local_socks(msocks_list,sockfd); free(uuid); free(cmd); free(data); free(length); printf("target is offline. ******************************************************\n"); printf("status %d\n", tox_get_friend_connection_status(my_tox,friend_num)); printf("friend num %d\n", friend_num); //exit(1); } } }
static void chat_onInit(ToxWindow *self, Tox *m) { curs_set(1); int x2, y2; getmaxyx(self->window, y2, x2); self->x = x2; /* Init statusbar info */ StatusBar *statusbar = self->stb; statusbar->status = tox_get_user_status(m, self->num); statusbar->is_online = tox_get_friend_connection_status(m, self->num) == 1; char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; uint16_t s_len = tox_get_status_message(m, self->num, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); statusmsg[s_len] = '\0'; snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); statusbar->statusmsg_len = s_len; char nick[TOX_MAX_NAME_LENGTH]; int n_len = get_nick_truncate(m, nick, self->num); snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick); statusbar->nick_len = n_len; /* Init subwindows */ ChatContext *ctx = self->chatwin; statusbar->topline = subwin(self->window, 2, x2, 0, 0); ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0); ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0); ctx->hst = calloc(1, sizeof(struct history)); ctx->log = calloc(1, sizeof(struct chatlog)); if (ctx->log == NULL || ctx->hst == NULL) exit_toxic_err("failed in chat_onInit", FATALERR_MEMORY); line_info_init(ctx->hst); if (friends[self->num].logging_on) log_enable(nick, friends[self->num].pub_key, ctx->log); execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE); scrollok(ctx->history, 0); wmove(self->window, y2 - CURS_Y_OFFSET, 0); }
END_TEST #define NUM_TOXES 66 #define NUM_FRIENDS 20 START_TEST(test_many_clients) { long long unsigned int cur_time = time(NULL); Tox *toxes[NUM_TOXES]; uint32_t i, j; uint32_t to_comp = 974536; for (i = 0; i < NUM_TOXES; ++i) { toxes[i] = tox_new(0); ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i); tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp); } struct { uint16_t tox1; uint16_t tox2; } pairs[NUM_FRIENDS]; uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; for (i = 0; i < NUM_FRIENDS; ++i) { loop_top: pairs[i].tox1 = rand() % NUM_TOXES; pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES; for (j = 0; j < i; ++j) { if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) goto loop_top; } tox_get_address(toxes[pairs[i].tox1], address); int test = tox_add_friend(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7); if (test == TOX_FAERR_ALREADYSENT) { goto loop_top; } ck_assert_msg(test >= 0, "Failed to add friend error code: %i", test); } while (1) { uint16_t counter = 0; for (i = 0; i < NUM_TOXES; ++i) { for (j = 0; j < tox_count_friendlist(toxes[i]); ++j) if (tox_get_friend_connection_status(toxes[i], j) == 1) ++counter; } if (counter == NUM_FRIENDS * 2) { break; } for (i = 0; i < NUM_TOXES; ++i) { tox_do(toxes[i]); } c_sleep(50); } printf("test_many_clients succeeded, took %llu seconds\n", time(NULL) - cur_time); for (i = 0; i < NUM_TOXES; ++i) { tox_kill(toxes[i]); } }
int main(int argc, char *argv[]) { uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); if (argvoffset < 0) exit(1); /* with optional --ipvx, now it can be 1-4 arguments... */ if ((argc != argvoffset + 3) && (argc != argvoffset + 5)) { printf("Usage: %s [--ipv4|--ipv6] ip port public_key (of the DHT bootstrap node) folder (to sync)\n", argv[0]); exit(0); } Tox *tox = tox_new(ipv6enabled); tox_callback_file_data(tox, write_file, NULL); tox_callback_file_control(tox, file_print_control, NULL); tox_callback_file_send_request(tox, file_request_accept, NULL); tox_callback_connection_status(tox, print_online, NULL); uint16_t port = htons(atoi(argv[argvoffset + 2])); unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]); int res = tox_bootstrap_from_address(tox, argv[argvoffset + 1], ipv6enabled, port, binary_string); free(binary_string); if (!res) { printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); exit(1); } uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; tox_get_address(tox, address); uint32_t i; for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { printf("%02X", address[i]); } char temp_id[128]; printf("\nEnter the address of the other id you want to sync with (38 bytes HEX format):\n"); if (scanf("%s", temp_id) != 1) { return 1; } uint8_t *bin_id = hex_string_to_bin(temp_id); int num = tox_add_friend(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); free(bin_id); if (num < 0) { printf("\nSomething went wrong when adding friend.\n"); return 1; } memcpy(path, argv[argvoffset + 4], strlen(argv[argvoffset + 4])); DIR *d; struct dirent *dir; uint8_t notconnected = 1; while (1) { if (tox_isconnected(tox) && notconnected) { printf("\nDHT connected.\n"); notconnected = 0; } if (not_sending() && tox_get_friend_connection_status(tox, num)) { d = opendir(path); if (d) { while ((dir = readdir(d)) != NULL) { if (dir->d_type == DT_REG) { char fullpath[1024]; if (path[strlen(path) - 1] == '/') sprintf(fullpath, "%s%s", path, dir->d_name); else sprintf(fullpath, "%s/%s", path, dir->d_name); add_filesender(tox, num, fullpath); } } closedir(d); } else { printf("\nFailed to open directory.\n"); return 1; } } send_filesenders(tox); tox_do(tox); c_sleep(1); } return 0; }