aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command.c30
-rw-r--r--db.c15
-rw-r--r--db.h2
-rw-r--r--schema.sql2
-rw-r--r--user_data.c54
-rw-r--r--user_data.h8
6 files changed, 109 insertions, 2 deletions
diff --git a/command.c b/command.c
index 30d2223..3ede1cc 100644
--- a/command.c
+++ b/command.c
@@ -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]))
diff --git a/db.c b/db.c
index 068817c..fa7603c 100644
--- a/db.c
+++ b/db.c
@@ -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);
}
diff --git a/db.h b/db.h
index 9dc926c..8ca1227 100644
--- a/db.h
+++ b/db.h
@@ -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);
diff --git a/schema.sql b/schema.sql
index 321cb38..009308e 100644
--- a/schema.sql
+++ b/schema.sql
@@ -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);