static void cmd_title_set(Tox *m, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH]) { const char *outmsg = NULL; if (!friend_is_master(m, friendnum)) { authent_failed(m, friendnum); return; } if (argc < 2) { outmsg = "Error: Two arguments are required"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } if (argv[2][0] != '\"') { outmsg = "Error: title must be enclosed in quotes"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } int groupnum = atoi(argv[1]); if (groupnum == 0 && strcmp(argv[1], "0")) { outmsg = "Error: Invalid group number"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } /* remove opening and closing quotes */ char title[MAX_COMMAND_LENGTH]; snprintf(title, sizeof(title), "%s", &argv[2][1]); int len = strlen(title) - 1; title[len] = '\0'; char name[TOX_MAX_NAME_LENGTH]; tox_friend_get_name(m, friendnum, (uint8_t *) name, NULL); size_t nlen = tox_friend_get_name_size(m, friendnum, NULL); name[nlen] = '\0'; TOX_ERR_CONFERENCE_TITLE err; if (!tox_conference_set_title(m, groupnum, (uint8_t *) title, len, &err)) { printf("%s failed to set the title '%s' for group %d\n", name, title, groupnum); outmsg = "Failed to set title. This may be caused by an invalid group number or an empty room"; send_error(m, friendnum, outmsg, err); return; } int idx = group_index(groupnum); memcpy(Tox_Bot.g_chats[idx].title, title, len + 1); Tox_Bot.g_chats[idx].title_len = len; outmsg = "Group title set"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); printf("%s set group %d title to %s\n", name, groupnum, title); }
static void cmd_invite(Tox *m, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH]) { const char *outmsg = NULL; int groupnum = Tox_Bot.default_groupnum; if (argc >= 1) { groupnum = atoi(argv[1]); if (groupnum == 0 && strcmp(argv[1], "0")) { outmsg = "Error: Invalid group number"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } } int idx = group_index(groupnum); if (idx == -1) { outmsg = "Group doesn't exist."; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } int has_pass = Tox_Bot.g_chats[idx].has_pass; char name[TOX_MAX_NAME_LENGTH]; tox_friend_get_name(m, friendnum, (uint8_t *) name, NULL); size_t len = tox_friend_get_name_size(m, friendnum, NULL); name[len] = '\0'; const char *passwd = NULL; if (argc >= 2) { passwd = argv[2]; } if (has_pass && (!passwd || strcmp(argv[2], Tox_Bot.g_chats[idx].password) != 0)) { fprintf(stderr, "Failed to invite %s to group %d (invalid password)\n", name, groupnum); outmsg = "Invalid password."; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } TOX_ERR_CONFERENCE_INVITE err; if (!tox_conference_invite(m, friendnum, groupnum, &err)) { fprintf(stderr, "Failed to invite %s to group %d\n", name, groupnum); outmsg = "Invite failed"; send_error(m, friendnum, outmsg, err); return; } printf("Invited %s to group %d\n", name, groupnum); }
static void cb_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length, void *userdata) { char message[TOX_MAX_MESSAGE_LENGTH]; length = copy_tox_str(message, sizeof(message), (const char *) title, length); int idx = group_index(groupnumber); if (idx == -1) return; memcpy(Tox_Bot.g_chats[idx].title, message, length + 1); Tox_Bot.g_chats[idx].title_len = length; }
static void cmd_info(Tox *m, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH]) { char outmsg[MAX_COMMAND_LENGTH]; char timestr[64]; uint64_t curtime = (uint64_t) time(NULL); get_elapsed_time_str(timestr, sizeof(timestr), curtime - Tox_Bot.start_time); snprintf(outmsg, sizeof(outmsg), "Uptime: %s", timestr); tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); uint32_t numfriends = tox_self_get_friend_list_size(m); snprintf(outmsg, sizeof(outmsg), "Friends: %d (%d online)", numfriends, Tox_Bot.num_online_friends); tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); snprintf(outmsg, sizeof(outmsg), "Inactive friends are purged after %"PRIu64" days", Tox_Bot.inactive_limit / SECONDS_IN_DAY); tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); /* List active group chats and number of peers in each */ size_t num_chats = tox_conference_get_chatlist_size(m); if (num_chats == 0) { tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) "No active groupchats", strlen("No active groupchats"), NULL); return; } uint32_t groupchat_list[num_chats]; tox_conference_get_chatlist(m, groupchat_list); uint32_t i; for (i = 0; i < num_chats; ++i) { TOX_ERR_CONFERENCE_PEER_QUERY err; uint32_t groupnum = groupchat_list[i]; uint32_t num_peers = tox_conference_peer_count(m, groupnum, &err); if (err == TOX_ERR_CONFERENCE_PEER_QUERY_OK) { int idx = group_index(groupnum); const char *title = Tox_Bot.g_chats[idx].title_len ? Tox_Bot.g_chats[idx].title : "None"; const char *type = tox_conference_get_type(m, groupnum, NULL) == TOX_CONFERENCE_TYPE_AV ? "Audio" : "Text"; snprintf(outmsg, sizeof(outmsg), "Group %d | %s | peers: %d | Title: %s", groupnum, type, num_peers, title); tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); } } }
static void cmd_gmessage(Tox *m, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH]) { const char *outmsg = NULL; if (!friend_is_master(m, friendnum)) { authent_failed(m, friendnum); return; } if (argc < 1) { outmsg = "Error: Group number required"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } if (argc < 2) { outmsg = "Error: Message required"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } int groupnum = atoi(argv[1]); if (groupnum == 0 && strcmp(argv[1], "0")) { outmsg = "Error: Invalid group number"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } if (group_index(groupnum) == -1) { outmsg = "Error: Invalid group number"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } if (argv[2][0] != '\"') { outmsg = "Error: Message must be enclosed in quotes"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } /* remove opening and closing quotes */ char msg[MAX_COMMAND_LENGTH]; snprintf(msg, sizeof(msg), "%s", &argv[2][1]); int len = strlen(msg) - 1; msg[len] = '\0'; TOX_ERR_CONFERENCE_SEND_MESSAGE err; if (!tox_conference_send_message(m, groupnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) msg, strlen(msg), &err)) { outmsg = "Error: Failed to send message."; send_error(m, friendnum, outmsg, err); return; } char name[TOX_MAX_NAME_LENGTH]; tox_friend_get_name(m, friendnum, (uint8_t *) name, NULL); size_t nlen = tox_friend_get_name_size(m, friendnum, NULL); name[nlen] = '\0'; outmsg = "Message sent."; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); printf("<%s> message to group %d: %s\n", name, groupnum, msg); }
static void cmd_passwd(Tox *m, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH]) { const char *outmsg = NULL; if (!friend_is_master(m, friendnum)) { authent_failed(m, friendnum); return; } if (argc < 1) { outmsg = "Error: group number required"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } int groupnum = atoi(argv[1]); if (groupnum == 0 && strcmp(argv[1], "0")) { outmsg = "Error: Invalid group number"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } int idx = group_index(groupnum); if (idx == -1) { outmsg = "Error: Invalid group number"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } char name[TOX_MAX_NAME_LENGTH]; tox_friend_get_name(m, friendnum, (uint8_t *) name, NULL); size_t nlen = tox_friend_get_name_size(m, friendnum, NULL); name[nlen] = '\0'; /* no password */ if (argc < 2) { Tox_Bot.g_chats[idx].has_pass = false; memset(Tox_Bot.g_chats[idx].password, 0, MAX_PASSWORD_SIZE); outmsg = "No password set"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); printf("No password set for group %d by %s\n", groupnum, name); return; } if (strlen(argv[2]) >= MAX_PASSWORD_SIZE) { outmsg = "Password too long"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); return; } Tox_Bot.g_chats[idx].has_pass = true; snprintf(Tox_Bot.g_chats[idx].password, sizeof(Tox_Bot.g_chats[idx].password), "%s", argv[2]); outmsg = "Password set"; tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); printf("Password for group %d set by %s\n", groupnum, name); }
/* This function handles all initial messages from the user to the rendezvous server. It will: -List the groups currently active -Allow the user to quit -Put a user in a particular group */ void *handle_request(void *hrs){ struct handle_request_struct *args = (struct handle_request_struct *) hrs; printf("handle IP: %s\n",args->IP); int socket = args->socketfd; while(1){ printf("In handle_request while(1)\n"); //Get the size of the message from the user int recv_bytes; read_socket(socket,&recv_bytes,sizeof(int)); recv_bytes = ntohl(recv_bytes); //If it's zero, it means there's no message if(recv_bytes == 0) continue; printf("recv_bytes = %d\n",recv_bytes); char request_message[recv_bytes]; memset(request_message,0,recv_bytes); printf("Message before: %s\n",request_message); //Get the message from the user read_socket(socket,request_message,recv_bytes); printf("Message after: %s\n",request_message); //The client is requesting a list of the groups that exist if(strcmp(request_message,"L") == 0) send_list(socket); //The client is quitting the session and will disconnect. else if(strcmp(request_message,"Q") == 0){ printf("Thread exiting...\n"); pthread_exit(NULL); } // This is a join request else if(request_message[0] == 'J'){ char info[recv_bytes]; slice_string(info,request_message,1); printf("Sliced string: %s\n",info); char *gname = strtok(info,":"); char *uname = strtok(NULL,":"); /*struct user u; init_user(&u); strcpy(u.IP,args->IP); strcpy(u.username,uname);*/ // Check if group exists int index = group_index(gname); int userIndex; if(index == -1){ // Group doesn't exist, so we need to create it: userIndex = 0; index = num_groups; printf("Creating group...\n"); all_groups[index] = (struct chat_group*) malloc (sizeof(struct chat_group)); strcpy(all_groups[index]->groupname,gname); all_groups[index]->users[0] = (struct user*) malloc (sizeof(struct user)); strcpy(all_groups[index]->users[0]->IP, args->IP); printf("From handle_request: IP: %s\n",all_groups[num_groups]->users[0]->IP); strcpy(all_groups[index]->users[0]->username, uname); all_groups[index]->num_users = 1; num_groups ++; printf("Group created!\n"); } // Group exists, so just add the user to the group else { userIndex = all_groups[index]->num_users; all_groups[index]->users[all_groups[index]->num_users] = (struct user*) malloc (sizeof(struct user)); strcpy(all_groups[index]->users[all_groups[index]->num_users]->IP, args->IP); strcpy(all_groups[index]->users[all_groups[index]->num_users]->username, uname); all_groups[index]->num_users++; } all_groups[index]->users[userIndex]->socket = socket; send_group(index,args->socketfd); // Generate a thread that handles in-group requests, like leaving and member-update requests //pthread_t in_group_requests; pthread_create(&all_groups[index]->users[userIndex]->in_group_req_thread,NULL,handle_in_group_requests,(void *) args->socketfd); pthread_exit(NULL); return 0; // In case thread exit didn't work } //pthread_exit(NULL); } pthread_exit(NULL); }
/* This function removes a user from a particular group */ void remove_user_from_group_list(char *groupname, char *username){ // TODO Receive the user to be deleted from the client and update the table. Should have a dedicated // thread running this function. Another thread should also be dedicated to sending down // new possible connections for when they run out char user_IP[IP_SIZE] = {'\0'}; int user_socket; int gindex = group_index(groupname); print_group(gindex); pthread_t condemned_thread; //Iterate until you have the user you want at index i int i; for(i = 0; i < all_groups[gindex]->num_users; ++i){ if(strcmp(all_groups[gindex]->users[i]->username,username) == 0) break; } if(i >= all_groups[gindex]->num_users) return; // User not in this group else { printf("Condemned user is at index %d\n",i); //u is the user we want to remove struct user *u = all_groups[gindex]->users[i]; // These two values are for the call to handle_request strcpy(user_IP,u->IP); user_socket = u->socket; condemned_thread = u->in_group_req_thread; struct user *unext; int n; for(n = i; n < all_groups[gindex]->num_users - 1; n++){ printf("Inside remove_user's for-loop()\n"); u = all_groups[gindex]->users[n]; unext = all_groups[gindex]->users[n+1]; //Clear the user's information memset(u->username,'\0',NAME_SIZE); memset(u->IP,'\0',IP_SIZE); u->in_group_req_thread = 0; u->socket = -1; strcpy(u->username,unext->username); strcpy(u->IP,unext->IP); u->in_group_req_thread = unext->in_group_req_thread; u->socket = unext->socket; } if(all_groups[gindex]->num_users - 1 == i){ // If this condemned user is the last one in the group, only wipe it u = all_groups[gindex]->users[i]; memset(u->username,'\0',NAME_SIZE); memset(u->IP,'\0',IP_SIZE); u->in_group_req_thread = 0; u->socket = -1; } else { // Otherwise, wipe the next one too memset(unext->username,'\0',NAME_SIZE); memset(unext->IP,'\0',IP_SIZE); unext->in_group_req_thread = 0; unext->socket = -1; } all_groups[gindex]->num_users--; printf("Number of users in %s is now %d\n",groupname,all_groups[gindex]->num_users); print_group(gindex); } // Finish by creating a handle_request_struct and creating a pthread to it struct handle_request_struct *hrs = (struct handle_request_struct *) malloc (sizeof(struct handle_request_struct)); hrs->socketfd = user_socket; strcpy(hrs->IP,user_IP); pthread_t handle_request_thread; printf("Calling handle_request thread"); //pthread_create(&handle_request_thread, NULL, handle_request,(void *) hrs); pthread_cancel(condemned_thread); free(hrs); }