aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-03-16 21:06:11 +0100
committertomsmeding <tom.smeding@gmail.com>2017-03-16 21:06:57 +0100
commit047e1828901b5b08cd538a7b11c0de2149606797 (patch)
tree9249612fe9bb88bf3063733744a6c02c391e5739
parenta441b302c2c11c291df60fe642ec0d51646218dd (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.c26
-rw-r--r--db.c31
-rw-r--r--db.h6
-rw-r--r--main.c3
-rw-r--r--user_data.c26
-rw-r--r--user_data.h2
6 files changed, 88 insertions, 6 deletions
diff --git a/command.c b/command.c
index 3ede1cc..0f2cd06 100644
--- a/command.c
+++ b/command.c
@@ -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);
diff --git a/db.c b/db.c
index fa7603c..828c081 100644
--- a/db.c
+++ b/db.c
@@ -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);
diff --git a/db.h b/db.h
index 8ca1227..9eb9a1f 100644
--- a/db.h
+++ b/db.h
@@ -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);
diff --git a/main.c b/main.c
index cfedf93..557dc77 100644
--- a/main.c
+++ b/main.c
@@ -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