]> jfr.im git - solanum.git/blame - ircd/capability.c
ircd: ensure irc_dictionary users have names, for stats tracking.
[solanum.git] / ircd / capability.c
CommitLineData
64b56afd
AC
1/*
2 * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21#include "stdinc.h"
22#include "capability.h"
23#include "irc_dictionary.h"
77d3d2db 24#include "s_assert.h"
64b56afd 25
885cd603
AC
26static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
27
64b56afd 28struct CapabilityIndex {
885cd603 29 char *name;
64b56afd
AC
30 struct Dictionary *cap_dict;
31 unsigned int highest_bit;
885cd603 32 rb_dlink_node node;
64b56afd
AC
33};
34
5058c8eb 35#define CAP_ORPHANED 0x1
f01f67f0 36#define CAP_REQUIRED 0x2
5058c8eb 37
64b56afd 38struct CapabilityEntry {
e679e389 39 char *cap;
64b56afd 40 unsigned int value;
5058c8eb 41 unsigned int flags;
64b56afd
AC
42};
43
44unsigned int
bde42c60 45capability_get(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
46{
47 struct CapabilityEntry *entry;
48
bde42c60 49 s_assert(idx != NULL);
d7e4ed77
AC
50 if (cap == NULL)
51 return 0;
64b56afd 52
bde42c60 53 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
5058c8eb 54 if (entry != NULL && !(entry->flags & CAP_ORPHANED))
8bedf01d 55 return (1 << entry->value);
64b56afd 56
8d20b088 57 return 0;
64b56afd
AC
58}
59
60unsigned int
bde42c60 61capability_put(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
62{
63 struct CapabilityEntry *entry;
64
bde42c60
JT
65 s_assert(idx != NULL);
66 if (!idx->highest_bit)
8bedf01d 67 return 0xFFFFFFFF;
64b56afd 68
bde42c60 69 if ((entry = irc_dictionary_retrieve(idx->cap_dict, cap)) != NULL)
64b56afd 70 {
5058c8eb 71 entry->flags &= ~CAP_ORPHANED;
8bedf01d 72 return (1 << entry->value);
64b56afd
AC
73 }
74
75 entry = rb_malloc(sizeof(struct CapabilityEntry));
e679e389 76 entry->cap = rb_strdup(cap);
5058c8eb 77 entry->flags = 0;
bde42c60 78 entry->value = idx->highest_bit;
64b56afd 79
bde42c60 80 irc_dictionary_add(idx->cap_dict, entry->cap, entry);
64b56afd 81
bde42c60
JT
82 idx->highest_bit++;
83 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
84 idx->highest_bit = 0;
64b56afd 85
8bedf01d 86 return (1 << entry->value);
64b56afd
AC
87}
88
22cae20f
JT
89unsigned int
90capability_put_anonymous(struct CapabilityIndex *idx)
91{
92 unsigned int value;
93
94 s_assert(idx != NULL);
95 if (!idx->highest_bit)
96 return 0xFFFFFFFF;
97 value = 1 << idx->highest_bit;
98 idx->highest_bit++;
99 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
100 idx->highest_bit = 0;
101 return value;
102}
103
64b56afd 104void
bde42c60 105capability_orphan(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
106{
107 struct CapabilityEntry *entry;
108
bde42c60 109 s_assert(idx != NULL);
64b56afd 110
bde42c60 111 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
64b56afd 112 if (entry != NULL)
f01f67f0
AC
113 {
114 entry->flags &= ~CAP_REQUIRED;
5058c8eb 115 entry->flags |= CAP_ORPHANED;
f01f67f0
AC
116 }
117}
118
119void
bde42c60 120capability_require(struct CapabilityIndex *idx, const char *cap)
f01f67f0
AC
121{
122 struct CapabilityEntry *entry;
123
bde42c60 124 s_assert(idx != NULL);
f01f67f0 125
bde42c60 126 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
f01f67f0
AC
127 if (entry != NULL)
128 entry->flags |= CAP_REQUIRED;
64b56afd
AC
129}
130
131static void
132capability_destroy(struct DictionaryElement *delem, void *privdata)
133{
134 s_assert(delem != NULL);
135
136 rb_free(delem->data);
137}
138
139struct CapabilityIndex *
885cd603 140capability_index_create(const char *name)
64b56afd 141{
bde42c60 142 struct CapabilityIndex *idx;
64b56afd 143
bde42c60 144 idx = rb_malloc(sizeof(struct CapabilityIndex));
885cd603 145 idx->name = rb_strdup(name);
99b461bb 146 idx->cap_dict = irc_dictionary_create(name, strcasecmp);
bde42c60 147 idx->highest_bit = 1;
64b56afd 148
885cd603
AC
149 rb_dlinkAdd(idx, &idx->node, &capability_indexes);
150
bde42c60 151 return idx;
64b56afd
AC
152}
153
154void
bde42c60 155capability_index_destroy(struct CapabilityIndex *idx)
64b56afd 156{
bde42c60 157 s_assert(idx != NULL);
64b56afd 158
885cd603
AC
159 rb_dlinkDelete(&idx->node, &capability_indexes);
160
bde42c60
JT
161 irc_dictionary_destroy(idx->cap_dict, capability_destroy, NULL);
162 rb_free(idx);
64b56afd 163}
5e773521
AC
164
165const char *
bde42c60 166capability_index_list(struct CapabilityIndex *idx, unsigned int cap_mask)
5e773521
AC
167{
168 struct DictionaryIter iter;
169 struct CapabilityEntry *entry;
170 static char buf[BUFSIZE];
171 char *t = buf;
172 int tl;
173
bde42c60 174 s_assert(idx != NULL);
5e773521
AC
175
176 *t = '\0';
177
bde42c60 178 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
5e773521 179 {
33b214fa 180 if ((1 << entry->value) & cap_mask)
5e773521 181 {
e915e51f 182 tl = rb_sprintf(t, "%s ", entry->cap);
5e773521
AC
183 t += tl;
184 }
185 }
186
187 t--;
188 *t = '\0';
189
190 return buf;
191}
ec3a9055
AC
192
193unsigned int
bde42c60 194capability_index_mask(struct CapabilityIndex *idx)
ec3a9055
AC
195{
196 struct DictionaryIter iter;
197 struct CapabilityEntry *entry;
198 unsigned int mask = 0;
199
bde42c60 200 s_assert(idx != NULL);
ec3a9055 201
bde42c60 202 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
ec3a9055 203 {
0582290f 204 if (!(entry->flags & CAP_ORPHANED))
8bedf01d 205 mask |= (1 << entry->value);
ec3a9055
AC
206 }
207
208 return mask;
209}
f01f67f0
AC
210
211unsigned int
bde42c60 212capability_index_get_required(struct CapabilityIndex *idx)
f01f67f0
AC
213{
214 struct DictionaryIter iter;
215 struct CapabilityEntry *entry;
216 unsigned int mask = 0;
217
bde42c60 218 s_assert(idx != NULL);
f01f67f0 219
bde42c60 220 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
f01f67f0
AC
221 {
222 if (!(entry->flags & CAP_ORPHANED) && (entry->flags & CAP_REQUIRED))
8bedf01d 223 mask |= (1 << entry->value);
f01f67f0
AC
224 }
225
226 return mask;
227}
a16910aa
AC
228
229void
230capability_index_stats(void (*cb)(const char *line, void *privdata), void *privdata)
231{
232 rb_dlink_node *node;
233 char buf[BUFSIZE];
234
235 RB_DLINK_FOREACH(node, capability_indexes.head)
236 {
237 struct CapabilityIndex *idx = node->data;
238 struct DictionaryIter iter;
239 struct CapabilityEntry *entry;
240
241 rb_snprintf(buf, sizeof buf, "'%s': allocated bits - %d", idx->name, (idx->highest_bit - 1));
242 cb(buf, privdata);
243
244 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
245 {
246 rb_snprintf(buf, sizeof buf, "bit %d: '%s'", entry->value, entry->cap);
247 cb(buf, privdata);
248 }
249
0c5e50f4
JT
250 rb_snprintf(buf, sizeof buf, "'%s': remaining bits - %u", idx->name,
251 (unsigned int)((sizeof(unsigned int) * 8) - (idx->highest_bit - 1)));
a16910aa
AC
252 cb(buf, privdata);
253 }
254
255 rb_snprintf(buf, sizeof buf, "%ld capability indexes", rb_dlink_list_length(&capability_indexes));
256 cb(buf, privdata);
257}