]> jfr.im git - irc/quakenet/newserv.git/blob - whowas/whowas_channels.c
BUILD: specify all dependencies and upgrade to bionic
[irc/quakenet/newserv.git] / whowas / whowas_channels.c
1 #include <string.h>
2 #include <assert.h>
3 #include <stdint.h>
4 #include "../lib/version.h"
5 #include "../nick/nick.h"
6 #include "../chanindex/chanindex.h"
7 #include "../channel/channel.h"
8 #include "../core/hooks.h"
9 #include "whowas.h"
10
11 MODULE_VERSION("");
12
13 static int wwcnext, wwccext;
14
15 static void wwc_refchannel(chanindex *cip) {
16 uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext];
17 (*refcount)++;
18 }
19
20 static void wwc_derefchannel(chanindex *cip) {
21 uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext];
22 (*refcount)--;
23
24 if (*refcount == 0)
25 releasechanindex(cip);
26 }
27
28 static void wwc_hook_joincreate(int hooknum, void *arg) {
29 void **args = arg;
30 channel *cp = args[0];
31 nick *np = args[1];
32 chanindex **wchans = np->exts[wwcnext];
33
34 if (!wchans) {
35 wchans = calloc(sizeof(chanindex *), WW_MAXCHANNELS);
36 np->exts[wwcnext] = wchans;
37 }
38
39 wwc_refchannel(cp->index);
40
41 memmove(&wchans[1], &wchans[0], sizeof(chanindex *) * (WW_MAXCHANNELS - 1));
42 wchans[0] = cp->index;
43 }
44
45 static void wwc_hook_lostnick(int hooknum, void *arg) {
46 nick *np = arg;
47 chanindex **wchans = np->exts[wwcnext];
48 int i;
49
50 if (!wchans)
51 return;
52
53 for (i = 0; i < WW_MAXCHANNELS; i++) {
54 if (!wchans[i])
55 break;
56
57 wwc_derefchannel(wchans[i]);
58 }
59
60 free(wchans);
61 np->exts[wwcnext] = NULL;
62 }
63
64 static void wwc_hook_newrecord(int hooknum, void *arg) {
65 void **args = arg;
66 whowas *ww = args[0];
67 nick *np = args[1];
68 chanindex **wchans = np->exts[wwcnext];
69 int i;
70
71 memset(ww->channels, 0, sizeof(ww->channels));
72
73 if (!wchans)
74 return;
75
76 for (i = 0; i < WW_MAXCHANNELS; i++) {
77 if (!wchans[i])
78 break;
79
80 wwc_refchannel(wchans[i]);
81 ww->channels[i] = wchans[i];
82 }
83 }
84
85 static void wwc_hook_lostrecord(int hooknum, void *arg) {
86 whowas *ww = arg;
87 int i;
88
89 for (i = 0; i < WW_MAXCHANNELS; i++) {
90 if (!ww->channels[i])
91 break;
92
93 wwc_derefchannel(ww->channels[i]);
94 }
95 }
96
97 void _init(void) {
98 wwcnext = registernickext("whowas_channels");
99 wwccext = registerchanext("whowas_channels");
100
101 registerhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate);
102 registerhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate);
103 registerhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick);
104 registerhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord);
105 registerhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord);
106 }
107
108 void _fini(void) {
109 releasenickext(wwcnext);
110 releasechanext(wwccext);
111
112 deregisterhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate);
113 deregisterhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate);
114 deregisterhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick);
115 deregisterhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord);
116 deregisterhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord);
117 }