diff options
| -rw-r--r-- | command.c | 28 | ||||
| -rw-r--r-- | db.c | 35 | ||||
| -rw-r--r-- | db.h | 2 | 
3 files changed, 53 insertions, 12 deletions
| @@ -1,6 +1,7 @@  #define _GNU_SOURCE  #include <stdio.h>  #include <string.h> +#include <limits.h>  #include <errno.h>  #include <sys/time.h>  #include <sys/socket.h> @@ -238,11 +239,14 @@ static bool cmd_send(struct conn_data *data,const char *tag,const char **args){  	return closed;  } -static bool cmd_history(struct conn_data *data,const char *tag,const char **args){ +static bool history_cmd_helper( +		struct conn_data *data,const char *tag,const char **args, +		const char *cmdname,i64 beforeid){  	char *endp;  	i64 nrequested=strtoll(args[1],&endp,10);  	if(args[1][0]=='\0'||*endp!='\0'||nrequested<0){ -		debug("Connection fd=%d sent an invalid number for 'history': '%s'",data->fd,args[1]); +		debug("Connection fd=%d sent an invalid number for '%s': '%s'", +				data->fd,cmdname,args[1]);  		return true;  	} @@ -261,7 +265,7 @@ static bool cmd_history(struct conn_data *data,const char *tag,const char **args  		return false;  	} -	struct db_message_list ml=db_get_messages(roomid,nrequested); +	struct db_message_list ml=db_get_messages_before(roomid,nrequested,beforeid);  	char *buf=NULL;  	i64 len=asprintf(&buf,"%s history %" PRIi64 "\n",tag,ml.count);  	bool closed=net_send_raw_text(data->fd,buf,len); @@ -286,6 +290,23 @@ static bool cmd_history(struct conn_data *data,const char *tag,const char **args  	return closed;  } +static bool cmd_history(struct conn_data *data,const char *tag,const char **args){ +	return history_cmd_helper(data,tag,args,"history",-1); +} + +static bool cmd_history_before(struct conn_data *data,const char *tag,const char **args){ +	char *endp; +	i64 beforeid=strtoll(args[2],&endp,10); +	if(args[2][0]=='\0'||*endp!='\0'){ +		debug("Connection fd=%d sent an invalid id for 'history_before': '%s'", +				data->fd,args[2]); +		return true; +	} +	if(beforeid<0)beforeid=INT64_MAX; + +	return history_cmd_helper(data,tag,args,"history_before",beforeid); +} +  static bool cmd_ping(struct conn_data *data,const char *tag,const char **args){  	(void)args;  	return net_send_pong(data->fd,tag); @@ -353,6 +374,7 @@ static const struct cmd_info commands[]={  	{"invite",2,false,cmd_invite},  	{"send",2,true,cmd_send},  	{"history",2,false,cmd_history}, +	{"history_before",3,false,cmd_history_before},  	{"ping",0,false,cmd_ping},  	{"is_online",1,false,cmd_is_online},  	{"firebase_token",1,false,cmd_firebase_token}, @@ -304,18 +304,35 @@ void db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message){  }  struct db_message_list db_get_messages(i64 roomid,i64 count){ +	return db_get_messages_before(roomid,count,-1); +} + +struct db_message_list db_get_messages_before(i64 roomid,i64 count,i64 beforeid){  	assert(count>=0);  	sqlite3_stmt *stmt; -	SQLITE(prepare_v2,database, -			"select id, user, time, message " -			"from Messages " -			"where room = ? " -			"order by time desc " -			"limit ?" -		,-1,&stmt,NULL); -	SQLITE(bind_int64,stmt,1,roomid); -	SQLITE(bind_int64,stmt,2,count); +	if(beforeid<0){ +		SQLITE(prepare_v2,database, +				"select id, user, time, message " +				"from Messages " +				"where room = ? " +				"order by time desc " +				"limit ?" +			,-1,&stmt,NULL); +		SQLITE(bind_int64,stmt,1,roomid); +		SQLITE(bind_int64,stmt,2,count); +	} else { +		SQLITE(prepare_v2,database, +				"select id, user, time, message " +				"from Messages " +				"where room = ? and time < (select time from Messages where id = ?) " +				"order by time desc " +				"limit ?" +			,-1,&stmt,NULL); +		SQLITE(bind_int64,stmt,1,roomid); +		SQLITE(bind_int64,stmt,2,beforeid); +		SQLITE(bind_int64,stmt,3,count); +	}  	struct db_message_list ml;  	i64 cap=count; @@ -60,6 +60,8 @@ bool db_delete_token(i64 userid,const char *token);  void db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message);  struct db_message_list db_get_messages(i64 roomid,i64 count);  // gets latest `count` messages +// if beforeid<0, same as db_get_messages +struct db_message_list db_get_messages_before(i64 roomid,i64 count,i64 beforeid);  void db_nullify_name_id(struct db_name_id ni);  void db_nullify_room_list(struct db_room_list rl); | 
