aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-05-08 22:06:47 +0200
committertomsmeding <tom.smeding@gmail.com>2017-05-08 22:08:56 +0200
commita7a0ce278e661bf5d3f2b47556d8c30469d2bd6c (patch)
treedef6c7b56df0b21351c4f1b0766163426ee47649
parent886fc77026a2a805e5d166b2f87bd24720ad9ea4 (diff)
server: Add event system
-rw-r--r--broadcast.c4
-rw-r--r--command.c5
-rw-r--r--event.c99
-rw-r--r--event.h31
-rw-r--r--main.c20
5 files changed, 159 insertions, 0 deletions
diff --git a/broadcast.c b/broadcast.c
index 0517dc3..2970b54 100644
--- a/broadcast.c
+++ b/broadcast.c
@@ -1,8 +1,10 @@
#include <string.h>
#include "broadcast.h"
#include "db.h"
+#include "event.h"
#include "net.h"
#include "user_data.h"
+#include "util.h"
// Returns whether value was new and therefore inserted into the list.
@@ -72,6 +74,8 @@ void broadcast_online_change(i64 userid){
i64 numonline;
(void)userdata_online(userid,&numonline);
+ event_emit_online(make_timestamp(),name,numonline);
+
char *buf;
i64 len=asprintf(&buf,"_push online %" PRIi64 " %s\n",numonline,name);
free(name);
diff --git a/command.c b/command.c
index b0b9a26..0ae7fa3 100644
--- a/command.c
+++ b/command.c
@@ -7,6 +7,7 @@
#include "broadcast.h"
#include "command.h"
#include "db.h"
+#include "event.h"
#include "net.h"
#include "user_data.h"
#include "util.h"
@@ -160,6 +161,8 @@ static bool cmd_invite(struct conn_data *data,const char *tag,const char **args)
char *invitebuf=NULL;
i64 invitebuflen=asprintf(&invitebuf,"_push invite %s\n",roomname);
+ event_emit_join(make_timestamp(),username,roomname);
+
struct db_user_list members=db_list_members(roomid);
for(i64 i=0;i<members.count;i++){
i64 nfds;
@@ -208,6 +211,8 @@ static bool cmd_send(struct conn_data *data,const char *tag,const char **args){
char *username=db_get_username(data->userid);
i64 pushbuflen=asprintf(&pushbuf,"_push message %s %s %" PRIi64 " %s\n",
roomname,username,timestamp,message);
+
+ event_emit_message(timestamp,message,username,roomname);
free(username);
struct db_user_list members=db_list_members(roomid);
diff --git a/event.c b/event.c
new file mode 100644
index 0000000..40eaff8
--- /dev/null
+++ b/event.c
@@ -0,0 +1,99 @@
+#include <string.h>
+#include "event.h"
+
+
+struct cbs_chain{
+ event_callback_t *cb;
+ struct cbs_chain *prev,*next;
+};
+
+struct cbs_chain *callbacks=NULL,*callbacks_last=NULL;
+
+
+static struct cbs_chain* find_chain_item(event_callback_t *cb){
+ struct cbs_chain *item=callbacks;
+ while(item&&item->cb!=cb)item=item->next;
+ return item;
+}
+
+
+void event_register(event_callback_t *cb){
+ struct cbs_chain *item=find_chain_item(cb);
+ if(item!=NULL){
+ debug("event_register: callback %p already registered!",cb);
+ return;
+ }
+ item=malloc(1,struct cbs_chain);
+ item->cb=cb;
+ item->prev=item->next=NULL;
+ if(callbacks){
+ item->prev=callbacks_last;
+ callbacks_last->next=item;
+ callbacks_last=item;
+ } else {
+ callbacks=callbacks_last=item;
+ }
+}
+
+void event_unregister(event_callback_t *cb){
+ struct cbs_chain *item=find_chain_item(cb);
+ if(item==NULL){
+ debug("event_unregister: callback %p was not registered!",cb);
+ return;
+ }
+ if(item->prev)item->prev->next=item->next;
+ if(item->next)item->next->prev=item->prev;
+ if(callbacks==item)callbacks=item->next;
+ if(callbacks_last==item)callbacks_last=item->prev;
+ free(item);
+}
+
+struct event_item* event_item_alloc(void){
+ struct event_item *event=malloc(1,struct event_item);
+ memset(event,0,sizeof(struct event_item));
+ return event;
+}
+
+void event_item_free(struct event_item *event){
+ if(event->message)free(event->message);
+ if(event->user)free(event->user);
+ if(event->room)free(event->room);
+ free(event);
+}
+
+void event_emit(const struct event_item *event){
+ for(struct cbs_chain *item=callbacks;item!=NULL;item=item->next){
+ item->cb(event);
+ }
+}
+
+void event_emit_message(i64 timestamp,const char *message,const char *user,const char *room){
+ struct event_item *event=event_item_alloc();
+ event->type=EVENT_MESSAGE;
+ event->timestamp=timestamp;
+ event->message=strdup(message);
+ event->user=strdup(user);
+ event->room=strdup(room);
+ event_emit(event);
+ event_item_free(event);
+}
+
+void event_emit_online(i64 timestamp,const char *user,i64 numonline){
+ struct event_item *event=event_item_alloc();
+ event->type=EVENT_ONLINE;
+ event->timestamp=timestamp;
+ event->user=strdup(user);
+ event->num=numonline;
+ event_emit(event);
+ event_item_free(event);
+}
+
+void event_emit_join(i64 timestamp,const char *user,const char *room){
+ struct event_item *event=event_item_alloc();
+ event->type=EVENT_JOIN;
+ event->timestamp=timestamp;
+ event->user=strdup(user);
+ event->room=strdup(room);
+ event_emit(event);
+ event_item_free(event);
+}
diff --git a/event.h b/event.h
new file mode 100644
index 0000000..638cd20
--- /dev/null
+++ b/event.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "global.h"
+
+
+enum event_type{
+ EVENT_MESSAGE, // message, user, room
+ EVENT_ONLINE, // user, num
+ EVENT_JOIN, // user, room
+};
+
+struct event_item{
+ enum event_type type;
+ i64 timestamp; // always set
+ char *message,*user,*room;
+ i64 num;
+};
+
+typedef void event_callback_t(const struct event_item *event);
+
+
+void event_register(event_callback_t *cb);
+void event_unregister(event_callback_t *cb);
+
+struct event_item* event_item_alloc(void);
+void event_item_free(struct event_item *event);
+
+void event_emit(const struct event_item *event);
+void event_emit_message(i64 timestamp,const char *message,const char *user,const char *room);
+void event_emit_online(i64 timestamp,const char *user,i64 numonline);
+void event_emit_join(i64 timestamp,const char *user,const char *room);
diff --git a/main.c b/main.c
index 5afece8..a754f02 100644
--- a/main.c
+++ b/main.c
@@ -11,6 +11,7 @@
#include "command.h"
#include "conn_data.h"
#include "db.h"
+#include "event.h"
#include "net.h"
#include "runloop.h"
#include "user_data.h"
@@ -145,15 +146,34 @@ void srandomdev(void){
}
#endif
+__attribute__((unused))
+static void dummy_event_handler(const struct event_item *event){
+ switch(event->type){
+ case EVENT_MESSAGE:
+ debug("event: <%s>@%s: %s",event->user,event->room,event->message);
+ break;
+
+ case EVENT_ONLINE:
+ debug("event: <%s> online=%" PRIi64,event->user,event->num);
+ break;
+
+ case EVENT_JOIN:
+ debug("event: <%s> joins %s",event->user,event->room);
+ break;
+ }
+}
+
int main(void){
srandomdev();
db_init();
int sock=create_server_socket();
printf("Listening on port %d\n",PORT);
+ // event_register(dummy_event_handler);
runloop_set_timeout(60*1000000,timeout_callback);
runloop_add_fd(sock,server_socket_callback,false);
runloop_run();
printf("Runloop empty, shutting down\n");
+ // event_unregister(dummy_event_handler);
db_close();
}