diff options
Diffstat (limited to 'command.c')
-rw-r--r-- | command.c | 101 |
1 files changed, 77 insertions, 24 deletions
@@ -193,6 +193,57 @@ static struct cmd_retval cmd_create_room(struct conn_data *data,const char *tag, return RET_CLOSE(closed); } +static struct cmd_retval cmd_leave_room(struct conn_data *data,const char *tag,const char **args){ + (void)args; + if (data->userid == -1) { + net_send_error(data->fd, tag, "Not logged in"); + return RET_OK; + } + userdata_mark_active(data->userid, data->fd, true); + + const char *roomname = args[0]; + + i64 roomid = db_find_room(roomname); + if (roomid == -1) { + net_send_error(data->fd, tag, "Room not found"); + return RET_OK; + } + + if (!db_remove_member(roomid, data->userid)) { + net_send_error(data->fd, tag, "Not in that room"); + return RET_OK; + } + + char *username = db_get_username(data->userid); + char *msgbuf = NULL; + i64 msgbuflen = asprintf(&msgbuf, "_push leave %s %s\n", roomname, username); + free(username); + + // First send the leave push message to all remaining room members + struct db_user_list members = db_list_members(roomid); + for (i64 i = 0; i < members.count; i++) { + i64 nfds; + const int *fds = userdata_online(members.list[i].id, &nfds); + for (i64 j = 0; j < nfds; j++) { + net_send_raw_text(fds[j], msgbuf, msgbuflen); + } + } + db_nullify_user_list(members); + + // Then send the leave push message to the other sessions of the current user + i64 nfds; + const int *fds = userdata_online(data->userid, &nfds); + for (i64 j = 0; j < nfds; j++) { + if (fds[j] != data->fd) { + net_send_raw_text(fds[j], msgbuf, msgbuflen); + } + } + + free(msgbuf); + + return RET_CLOSE(net_send_ok(data->fd,tag)); +} + static struct cmd_retval cmd_invite(struct conn_data *data,const char *tag,const char **args){ if(data->userid==-1){ net_send_error(data->fd,tag,"Not logged in"); @@ -497,33 +548,34 @@ struct cmd_info{ // Use CommandHash.hs to re-generate this perfect hash function for a different // list of commands. -#define COMMAND_HASH_MODULUS 35 -#define COMMAND_HASH(cmd0, len) ((1 * cmd0 + 6 * len) % COMMAND_HASH_MODULUS) +#define COMMAND_HASH_MODULUS 31 +#define COMMAND_HASH(cmd0, cmd1, len) ((9 * cmd0 + 1 * cmd1 + 3 * len) % COMMAND_HASH_MODULUS) -#define COMMAND_ENTRY(cmd0, cmd, nargs, longlast, handler) \ - [COMMAND_HASH(cmd0, strlen(cmd))] = {cmd, nargs, longlast, handler} +#define COMMAND_ENTRY(cmd0, cmd1, cmd, nargs, longlast, handler) \ + [COMMAND_HASH(cmd0, cmd1, strlen(cmd))] = {cmd, nargs, longlast, handler} -// First argument to COMMAND_ENTRY must be command[0]. This is because +// First two arguments to COMMAND_ENTRY must be command[0] and [1]. This is because // apparently, "abc"[0] is not a constant expression, while strlen("abc") is. static const struct cmd_info commands[COMMAND_HASH_MODULUS] = { - COMMAND_ENTRY('v', "version", 1, false, cmd_version), - COMMAND_ENTRY('r', "register", 2, true, cmd_register), - COMMAND_ENTRY('l', "login", 2, true, cmd_login), - COMMAND_ENTRY('l', "logout", 0, false, cmd_logout), - COMMAND_ENTRY('c', "change_password", 1, true, cmd_change_password), - COMMAND_ENTRY('l', "list_rooms", 0, false, cmd_list_rooms), - COMMAND_ENTRY('l', "list_members", 1, false, cmd_list_members), - COMMAND_ENTRY('c', "create_room", 0, false, cmd_create_room), - COMMAND_ENTRY('i', "invite", 2, false, cmd_invite), - COMMAND_ENTRY('s', "send", 3, true, cmd_send), - COMMAND_ENTRY('h', "history", 2, false, cmd_history), - COMMAND_ENTRY('h', "history_before", 3, false, cmd_history_before), - COMMAND_ENTRY('g', "get_message", 1, false, cmd_get_message), - COMMAND_ENTRY('p', "ping", 0, false, cmd_ping), - COMMAND_ENTRY('i', "is_online", 1, false, cmd_is_online), - COMMAND_ENTRY('f', "firebase_token", 1, false, cmd_firebase_token), - COMMAND_ENTRY('d', "delete_firebase_token", 1, false, cmd_delete_firebase_token), - COMMAND_ENTRY('u', "user_active", 1, false, cmd_user_active), + COMMAND_ENTRY('v','e', "version", 1, false, cmd_version), + COMMAND_ENTRY('r','e', "register", 2, true, cmd_register), + COMMAND_ENTRY('l','o', "login", 2, true, cmd_login), + COMMAND_ENTRY('l','o', "logout", 0, false, cmd_logout), + COMMAND_ENTRY('c','h', "change_password", 1, true, cmd_change_password), + COMMAND_ENTRY('l','i', "list_rooms", 0, false, cmd_list_rooms), + COMMAND_ENTRY('l','i', "list_members", 1, false, cmd_list_members), + COMMAND_ENTRY('c','r', "create_room", 0, false, cmd_create_room), + COMMAND_ENTRY('l','e', "leave_room", 1, false, cmd_leave_room), + COMMAND_ENTRY('i','n', "invite", 2, false, cmd_invite), + COMMAND_ENTRY('s','e', "send", 3, true, cmd_send), + COMMAND_ENTRY('h','i', "history", 2, false, cmd_history), + COMMAND_ENTRY('h','i', "history_before", 3, false, cmd_history_before), + COMMAND_ENTRY('g','e', "get_message", 1, false, cmd_get_message), + COMMAND_ENTRY('p','i', "ping", 0, false, cmd_ping), + COMMAND_ENTRY('i','s', "is_online", 1, false, cmd_is_online), + COMMAND_ENTRY('f','i', "firebase_token", 1, false, cmd_firebase_token), + COMMAND_ENTRY('d','e', "delete_firebase_token", 1, false, cmd_delete_firebase_token), + COMMAND_ENTRY('u','s', "user_active", 1, false, cmd_user_active), }; @@ -543,7 +595,8 @@ bool handle_input_line(struct conn_data *data,char *line,size_t linelen){ sepp=memchr(line,' ',linelen); if(sepp==NULL)sepp=line+linelen; const size_t cmdlen=sepp-line; - const struct cmd_info *command=&commands[COMMAND_HASH(line[0],cmdlen)]; + const struct cmd_info *command=NULL; + if(cmdlen>=2)command=&commands[COMMAND_HASH(line[0],line[1],cmdlen)]; if(!command->cmdname ||cmdlen!=strlen(command->cmdname) ||memcmp(line,command->cmdname,cmdlen)!=0){ |