diff options
| -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); | 
