1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
#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.
// 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);
event_emit_online(make_timestamp(),name,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);
}
|