diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-03-16 21:06:11 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-03-16 21:06:57 +0100 |
commit | 047e1828901b5b08cd538a7b11c0de2149606797 (patch) | |
tree | 9249612fe9bb88bf3063733744a6c02c391e5739 | |
parent | a441b302c2c11c291df60fe642ec0d51646218dd (diff) |
Basic message sending
TODO: broadcast to all online fd's of a user?
TODO: close users that aren't reachable in a broadcast?
-rw-r--r-- | command.c | 26 | ||||
-rw-r--r-- | db.c | 31 | ||||
-rw-r--r-- | db.h | 6 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | user_data.c | 26 | ||||
-rw-r--r-- | user_data.h | 2 |
6 files changed, 88 insertions, 6 deletions
@@ -7,6 +7,7 @@ #include <sys/socket.h> #include "command.h" #include "db.h" +#include "user_data.h" static i64 make_timestamp(void){ @@ -89,6 +90,15 @@ static bool send_list(int fd,const char *tag,i64 count,const char **list){ return send_raw_text(fd,"\n",1); } +static bool send_push(int fd,const char *head,const char *arg){ + char *buf=NULL; + i64 len=asprintf(&buf,"_push %s %s\n",head,arg); + assert(buf); + bool closed=send_raw_text(fd,buf,len); + free(buf); + return closed; +} + static bool cmd_register(struct conn_data *data,const char *tag,const char **args){ i64 userid=db_find_user(args[0]); @@ -109,8 +119,12 @@ static bool cmd_login(struct conn_data *data,const char *tag,const char **args){ char *pass=db_get_pass(userid); bool success=strcmp(args[1],pass)==0; free(pass); + if(data->userid!=-1){ + userdata_unregister(data->userid,data->fd); + } if(success){ data->userid=userid; + userdata_register(userid,data->fd); send_ok(data->fd,tag); } else { data->userid=-1; @@ -196,7 +210,16 @@ static bool cmd_send(struct conn_data *data,const char *tag,const char **args){ db_create_message(roomid,data->userid,make_timestamp(),args[1]); bool closed=send_ok(data->fd,tag); -#warning TODO: broadcast + struct db_user_list members=db_get_members(roomid); + for(i64 i=0;i<members.count;i++){ + int fd=userdata_online(members.list[i].id); + if(fd!=-1&&fd!=data->fd){ + send_push(fd,"message",args[1]); + // TODO: unregister and close users that aren't reachable anymore; maybe ping instead? + } + } + + return closed; } @@ -219,6 +242,7 @@ static const struct cmd_info commands[]={ bool handle_input_line(struct conn_data *data,char *line,size_t linelen){ + line[linelen]='\0'; char *sepp=memchr(line,' ',linelen); if(sepp==NULL){ debug("No space in input line from connection %d",data->fd); @@ -85,6 +85,37 @@ bool db_is_member(i64 roomid,i64 userid){ return success; } +struct db_user_list db_get_members(i64 roomid){ + sqlite3_stmt *stmt; + SQLITE(prepare_v2,database, + "select U.id, U.name " + "from Users as U, Members as M " + "where M.room = ? and M.user = U.id" + ,-1,&stmt,NULL); + SQLITE(bind_int64,stmt,1,roomid); + + struct db_user_list ul; + i64 cap=4; + ul.count=0; + ul.list=malloc(cap,struct db_name_id); + + int ret; + while((ret=sqlite3_step(stmt))==SQLITE_ROW){ + if(ul.count==cap){ + cap*=2; + ul.list=realloc(ul.list,cap,struct db_name_id); + } + ul.list[ul.count].id=sqlite3_column_int64(stmt,0); + ul.list[ul.count].name=strdup((const char*)sqlite3_column_text(stmt,1)); + ul.count++; + } + + if(ret!=SQLITE_DONE)die_sqlite("sqlite3_step"); + SQLITE(finalize,stmt); + + return ul; +} + i64 db_find_room(const char *name){ sqlite3_stmt *stmt; SQLITE(prepare_v2,database,"select id from Rooms where name = ?",-1,&stmt,NULL); @@ -23,6 +23,11 @@ struct db_message_list{ struct db_message *list; }; +struct db_user_list{ + i64 count; + struct db_name_id *list; +}; + void db_init(void); void db_close(void); @@ -31,6 +36,7 @@ bool db_delete_room(i64 roomid); bool db_add_member(i64 roomid,i64 userid); bool db_remove_member(i64 roomid,i64 userid); bool db_is_member(i64 roomid,i64 userid); +struct db_user_list db_get_members(i64 roomid); i64 db_find_room(const char *name); // -1 if not found struct db_room_list db_list_rooms(i64 userid); @@ -10,6 +10,7 @@ #include "conn_data.h" #include "db.h" #include "runloop.h" +#include "user_data.h" #define PORT (29536) // python: int("msg",36) @@ -50,6 +51,7 @@ static void delete_conn_data(int fd){ struct hash_item *item=conn_hash[fd%CONN_HASH_SIZE]; assert(item); if(item->cd.fd==fd){ + if(item->cd.userid!=-1)userdata_unregister(item->cd.userid,fd); conn_hash[fd%CONN_HASH_SIZE]=item->next; conn_data_nullify(&item->cd); free(item); @@ -62,6 +64,7 @@ static void delete_conn_data(int fd){ } assert(parent); assert(item); + if(item->cd.userid!=-1)userdata_unregister(item->cd.userid,fd); conn_data_nullify(&item->cd); parent->next=item->next; free(item); diff --git a/user_data.c b/user_data.c index 5bd4a6d..77e09cc 100644 --- a/user_data.c +++ b/user_data.c @@ -1,3 +1,5 @@ +#include <string.h> +#include <assert.h> #include "user_data.h" @@ -28,8 +30,7 @@ void userdata_register(i64 userid,int fd){ 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; + die("userdata_register(%lld, %d) while pair already existed",userid,fd); } } if(item->data.fds_len==item->data.fds_cap){ @@ -49,6 +50,23 @@ void userdata_register(i64 userid,int fd){ } } -void userdata_unregister(i64 userid,int fd); +void userdata_unregister(i64 userid,int fd){ + struct hash_item *item=find_userdata(userid); + assert(item); + i64 i; + for(i=0;i<item->data.fds_len;i++){ + if(item->data.fds[i]==fd)break; + } + if(i==item->data.fds_len){ + die("userdata_unregister(%lld, %d) while nonexistent",userid,fd); + } + memmove(item->data.fds+i,item->data.fds+i+1,item->data.fds_len-i-1); + item->data.fds_len--; +} -bool userdata_online(i64 userid); +int userdata_online(i64 userid){ + struct hash_item *item=find_userdata(userid); + if(!item)return false; + assert(item->data.fds_len!=0); + return item->data.fds[0]; // TODO: return all fds in some way? +} diff --git a/user_data.h b/user_data.h index 572c97a..4b4fc10 100644 --- a/user_data.h +++ b/user_data.h @@ -5,4 +5,4 @@ void userdata_register(i64 userid,int fd); void userdata_unregister(i64 userid,int fd); -bool userdata_online(i64 userid); +int userdata_online(i64 userid); // Returns fd |