diff options
| -rw-r--r-- | broadcast.c | 4 | ||||
| -rw-r--r-- | command.c | 5 | ||||
| -rw-r--r-- | event.c | 99 | ||||
| -rw-r--r-- | event.h | 31 | ||||
| -rw-r--r-- | main.c | 20 | 
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); @@ -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); @@ -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); +} @@ -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); @@ -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();  } | 
