aboutsummaryrefslogtreecommitdiff
path: root/broadcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'broadcast.c')
-rw-r--r--broadcast.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/broadcast.c b/broadcast.c
new file mode 100644
index 0000000..0517dc3
--- /dev/null
+++ b/broadcast.c
@@ -0,0 +1,89 @@
+#include <string.h>
+#include "broadcast.h"
+#include "db.h"
+#include "net.h"
+#include "user_data.h"
+
+
+// Returns whether value was new and therefore inserted into the list.
+// If already present, does nothing and returns false.
+// Assumes enough space for the possible new item.
+static bool sorted_insert(i64 *buf,i64 len,i64 value){
+ if(len==0){
+ buf[0]=value;
+ return true;
+ }
+ i64 L=0,H=len-1;
+ if(buf[L]==value||buf[H]==value)return false;
+ if(value<buf[L]){
+ memmove(buf+1,buf,len*sizeof(i64));
+ buf[0]=value;
+ return true;
+ }
+ if(value>buf[H]){
+ buf[len]=value;
+ return true;
+ }
+ while(L<H){
+ i64 M=L+(H-L)/2;
+ if(buf[M]==value)return false;
+ if(buf[M]<value){
+ L=M+1;
+ if(buf[L]>value)break;
+ } else if(buf[M]>value){
+ H=M-1;
+ if(buf[H]<value){
+ L=M;
+ break;
+ }
+ }
+ }
+ if(buf[L]==value)return false;
+ // We insert left of L
+ memmove(buf+L+1,buf+L,len-L);
+ buf[L]=value;
+ return true;
+}
+
+void broadcast_online_change(i64 userid){
+ i64 seencap=16,seenlen=0;
+ i64 *seen=malloc(seencap,i64);
+
+ struct db_room_list rooms=db_list_rooms(userid);
+ for(i64 i=0;i<rooms.count;i++){
+ struct db_user_list members=db_list_members(rooms.list[i].id);
+ for(i64 j=0;j<members.count;j++){
+ if(members.list[j].id==userid)continue;
+ i64 nfds;
+ (void)userdata_online(members.list[j].id,&nfds);
+ if(nfds==0)continue;
+ if(seenlen==seencap){
+ seencap*=2;
+ seen=realloc(seen,seencap,i64);
+ }
+ bool inserted=sorted_insert(seen,seenlen,members.list[j].id);
+ seenlen+=inserted;
+ }
+ db_nullify_user_list(members);
+ }
+ db_nullify_room_list(rooms);
+
+ char *name=db_get_username(userid);
+ i64 numonline;
+ (void)userdata_online(userid,&numonline);
+
+ char *buf;
+ i64 len=asprintf(&buf,"_push online %" PRIi64 " %s\n",numonline,name);
+ free(name);
+
+ for(i64 i=0;i<seenlen;i++){
+ i64 nfds;
+ const int *fds=userdata_online(seen[i],&nfds);
+ for(i64 j=0;j<nfds;j++){
+ net_send_raw_text(fds[j],buf,len);
+ }
+ }
+
+ free(buf);
+ free(seen);
+}