diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-03-15 10:20:55 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-03-15 10:20:55 +0100 |
commit | a441b302c2c11c291df60fe642ec0d51646218dd (patch) | |
tree | 22200cb885c3b7e38871f3827490700606c025c2 | |
parent | f1634688d62f2a6115739b65a311ab2b1cf79764 (diff) |
Start with implementing online status etc for broadcasting
-rw-r--r-- | command.c | 30 | ||||
-rw-r--r-- | db.c | 15 | ||||
-rw-r--r-- | db.h | 2 | ||||
-rw-r--r-- | schema.sql | 2 | ||||
-rw-r--r-- | user_data.c | 54 | ||||
-rw-r--r-- | user_data.h | 8 |
6 files changed, 109 insertions, 2 deletions
@@ -3,11 +3,19 @@ #include <string.h> #include <errno.h> #include <assert.h> +#include <sys/time.h> #include <sys/socket.h> #include "command.h" #include "db.h" +static i64 make_timestamp(void){ + struct timeval tv; + gettimeofday(&tv,NULL); + return (i64)tv.tv_sec+tv.tv_usec; +} + + static bool send_raw_text(int fd,const char *text,i64 len){ i64 cursor=0; while(cursor<len){ @@ -170,6 +178,27 @@ static bool cmd_invite(struct conn_data *data,const char *tag,const char **args) return send_ok(data->fd,tag); } +static bool cmd_send(struct conn_data *data,const char *tag,const char **args){ + if(data->userid==-1){ + send_error(data->fd,tag,"Not logged in"); + return false; + } + i64 roomid=db_find_room(args[0]); + if(roomid==-1){ + send_error(data->fd,tag,"Room not found"); + return false; + } + if(!db_is_member(roomid,data->userid)){ + send_error(data->fd,tag,"Not in that room"); + return false; + } + + db_create_message(roomid,data->userid,make_timestamp(),args[1]); + bool closed=send_ok(data->fd,tag); + +#warning TODO: broadcast +} + struct cmd_info{ const char *cmdname; @@ -184,6 +213,7 @@ static const struct cmd_info commands[]={ {"list_rooms",0,false,cmd_list_rooms}, {"create_room",0,false,cmd_create_room}, {"invite",2,false,cmd_invite}, + {"send",2,true,cmd_send}, }; #define NCOMMANDS (sizeof(commands)/sizeof(commands[0])) @@ -170,6 +170,21 @@ i64 db_find_user(const char *name){ } +void db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message){ + sqlite3_stmt *stmt; + SQLITE(prepare_v2,database, + "insert into Messages (room, user, time, message) " + "values (?, ?, ?, ?)" + ,-1,&stmt,NULL); + SQLITE(bind_int64,stmt,1,roomid); + SQLITE(bind_int64,stmt,2,userid); + SQLITE(bind_int64,stmt,3,timestamp); + SQLITE(bind_blob,stmt,4,message,strlen(message),SQLITE_STATIC); + if(sqlite3_step(stmt)!=SQLITE_DONE)die_sqlite("sqlite3_step"); + SQLITE(finalize,stmt); +} + + void db_nullify_name_id(struct db_name_id ni){ if(ni.name)free(ni.name); } @@ -42,7 +42,7 @@ char* db_get_pass(i64 userid); bool db_delete_user(i64 userid); i64 db_find_user(const char *name); // -1 if not found -bool db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message); +void db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message); struct db_message_list db_get_messages(i64 roomid,i64 timestamp,i64 count); // pass timestamp==-1 for last messages void db_nullify_name_id(struct db_name_id ni); @@ -26,7 +26,7 @@ create table Messages ( room integer not null, user integer null, time integer not null, - message text, + message blob, foreign key(room) references Rooms(id) on delete cascade, foreign key(user) references Users(id) on delete set null ); diff --git a/user_data.c b/user_data.c new file mode 100644 index 0000000..5bd4a6d --- /dev/null +++ b/user_data.c @@ -0,0 +1,54 @@ +#include "user_data.h" + + +struct user_data{ + i64 userid; + + int *fds; + i64 fds_cap,fds_len; +}; + +struct hash_item{ + struct user_data data; + struct hash_item *next; +}; + +#define USER_HASH_SIZE (16) +static struct hash_item *user_hash[USER_HASH_SIZE]; + + +static struct hash_item* find_userdata(i64 userid){ + struct hash_item *item=user_hash[userid%USER_HASH_SIZE]; + while(item&&item->data.userid!=userid)item=item->next; + return item; +} + +void userdata_register(i64 userid,int fd){ + struct hash_item *item=find_userdata(userid); + if(item){ + for(i64 i=0;i<item->data.fds_len;i++){ + if(item->data.fds[i]==fd){ + debug("userdata_register(%lld, %d) while pair already existed",userid,fd); + return; + } + } + if(item->data.fds_len==item->data.fds_cap){ + item->data.fds_cap*=2; + item->data.fds=realloc(item->data.fds,item->data.fds_cap,int); + } + item->data.fds[item->data.fds_len++]=fd; + } else { + item=malloc(1,struct hash_item); + item->data.userid=userid; + item->data.fds_cap=2; + item->data.fds_len=1; + item->data.fds=malloc(item->data.fds_cap,int); + item->data.fds[0]=fd; + item->next=user_hash[userid%USER_HASH_SIZE]; + user_hash[userid%USER_HASH_SIZE]=item; + } +} + +void userdata_unregister(i64 userid,int fd); + +bool userdata_online(i64 userid); diff --git a/user_data.h b/user_data.h new file mode 100644 index 0000000..572c97a --- /dev/null +++ b/user_data.h @@ -0,0 +1,8 @@ +#pragma once + +#include "global.h" + + +void userdata_register(i64 userid,int fd); +void userdata_unregister(i64 userid,int fd); +bool userdata_online(i64 userid); |