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