aboutsummaryrefslogtreecommitdiff
path: root/command.c
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-09-29 22:18:33 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-09-29 22:25:23 +0200
commita8a0603375fa4c5c1e61bd8a0dc0ed7f3f77854e (patch)
treec1749d16c7fe8fad8b0d04cc80092cd22c180a9d /command.c
parent1ecfdb8eef2e1cf5c9f017708b6313ea5d4093d7 (diff)
server: Implement room_leave
Diffstat (limited to 'command.c')
-rw-r--r--command.c101
1 files changed, 77 insertions, 24 deletions
diff --git a/command.c b/command.c
index 69f40b2..f69593c 100644
--- a/command.c
+++ b/command.c
@@ -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){