]> jfr.im git - solanum.git/blob - ircd/capability.c
ircd: chase capability API changes
[solanum.git] / ircd / capability.c
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"
24 #include "s_assert.h"
25
26 static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
27
28 struct CapabilityIndex {
29 char *name;
30 struct Dictionary *cap_dict;
31 unsigned int highest_bit;
32 rb_dlink_node node;
33 };
34
35 #define CAP_ORPHANED 0x1
36 #define CAP_REQUIRED 0x2
37
38 struct CapabilityEntry {
39 char *cap;
40 unsigned int value;
41 unsigned int flags;
42 void *ownerdata;
43 };
44
45 unsigned int
46 capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata)
47 {
48 struct CapabilityEntry *entry;
49
50 s_assert(idx != NULL);
51 if (cap == NULL)
52 return 0;
53
54 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
55 if (entry != NULL && !(entry->flags & CAP_ORPHANED))
56 {
57 if (ownerdata != NULL)
58 *ownerdata = entry->ownerdata;
59 return (1 << entry->value);
60 }
61
62 return 0;
63 }
64
65 unsigned int
66 capability_put(struct CapabilityIndex *idx, const char *cap, void *ownerdata)
67 {
68 struct CapabilityEntry *entry;
69
70 s_assert(idx != NULL);
71 if (!idx->highest_bit)
72 return 0xFFFFFFFF;
73
74 if ((entry = irc_dictionary_retrieve(idx->cap_dict, cap)) != NULL)
75 {
76 entry->flags &= ~CAP_ORPHANED;
77 return (1 << entry->value);
78 }
79
80 entry = rb_malloc(sizeof(struct CapabilityEntry));
81 entry->cap = rb_strdup(cap);
82 entry->flags = 0;
83 entry->value = idx->highest_bit;
84 entry->ownerdata = ownerdata;
85
86 irc_dictionary_add(idx->cap_dict, entry->cap, entry);
87
88 idx->highest_bit++;
89 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
90 idx->highest_bit = 0;
91
92 return (1 << entry->value);
93 }
94
95 unsigned int
96 capability_put_anonymous(struct CapabilityIndex *idx)
97 {
98 unsigned int value;
99
100 s_assert(idx != NULL);
101 if (!idx->highest_bit)
102 return 0xFFFFFFFF;
103 value = 1 << idx->highest_bit;
104 idx->highest_bit++;
105 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
106 idx->highest_bit = 0;
107 return value;
108 }
109
110 void
111 capability_orphan(struct CapabilityIndex *idx, const char *cap)
112 {
113 struct CapabilityEntry *entry;
114
115 s_assert(idx != NULL);
116
117 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
118 if (entry != NULL)
119 {
120 entry->flags &= ~CAP_REQUIRED;
121 entry->flags |= CAP_ORPHANED;
122 }
123 }
124
125 void
126 capability_require(struct CapabilityIndex *idx, const char *cap)
127 {
128 struct CapabilityEntry *entry;
129
130 s_assert(idx != NULL);
131
132 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
133 if (entry != NULL)
134 entry->flags |= CAP_REQUIRED;
135 }
136
137 static void
138 capability_destroy(struct DictionaryElement *delem, void *privdata)
139 {
140 s_assert(delem != NULL);
141
142 rb_free(delem->data);
143 }
144
145 struct CapabilityIndex *
146 capability_index_create(const char *name)
147 {
148 struct CapabilityIndex *idx;
149
150 idx = rb_malloc(sizeof(struct CapabilityIndex));
151 idx->name = rb_strdup(name);
152 idx->cap_dict = irc_dictionary_create(name, strcasecmp);
153 idx->highest_bit = 1;
154
155 rb_dlinkAdd(idx, &idx->node, &capability_indexes);
156
157 return idx;
158 }
159
160 void
161 capability_index_destroy(struct CapabilityIndex *idx)
162 {
163 s_assert(idx != NULL);
164
165 rb_dlinkDelete(&idx->node, &capability_indexes);
166
167 irc_dictionary_destroy(idx->cap_dict, capability_destroy, NULL);
168 rb_free(idx);
169 }
170
171 const char *
172 capability_index_list(struct CapabilityIndex *idx, unsigned int cap_mask)
173 {
174 struct DictionaryIter iter;
175 struct CapabilityEntry *entry;
176 static char buf[BUFSIZE];
177 char *t = buf;
178 int tl;
179
180 s_assert(idx != NULL);
181
182 *t = '\0';
183
184 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
185 {
186 if ((1 << entry->value) & cap_mask)
187 {
188 tl = sprintf(t, "%s ", entry->cap);
189 t += tl;
190 }
191 }
192
193 t--;
194 *t = '\0';
195
196 return buf;
197 }
198
199 unsigned int
200 capability_index_mask(struct CapabilityIndex *idx)
201 {
202 struct DictionaryIter iter;
203 struct CapabilityEntry *entry;
204 unsigned int mask = 0;
205
206 s_assert(idx != NULL);
207
208 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
209 {
210 if (!(entry->flags & CAP_ORPHANED))
211 mask |= (1 << entry->value);
212 }
213
214 return mask;
215 }
216
217 unsigned int
218 capability_index_get_required(struct CapabilityIndex *idx)
219 {
220 struct DictionaryIter iter;
221 struct CapabilityEntry *entry;
222 unsigned int mask = 0;
223
224 s_assert(idx != NULL);
225
226 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
227 {
228 if (!(entry->flags & CAP_ORPHANED) && (entry->flags & CAP_REQUIRED))
229 mask |= (1 << entry->value);
230 }
231
232 return mask;
233 }
234
235 void
236 capability_index_stats(void (*cb)(const char *line, void *privdata), void *privdata)
237 {
238 rb_dlink_node *node;
239 char buf[BUFSIZE];
240
241 RB_DLINK_FOREACH(node, capability_indexes.head)
242 {
243 struct CapabilityIndex *idx = node->data;
244 struct DictionaryIter iter;
245 struct CapabilityEntry *entry;
246
247 snprintf(buf, sizeof buf, "'%s': allocated bits - %d", idx->name, (idx->highest_bit - 1));
248 cb(buf, privdata);
249
250 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
251 {
252 snprintf(buf, sizeof buf, "bit %d: '%s'", entry->value, entry->cap);
253 cb(buf, privdata);
254 }
255
256 snprintf(buf, sizeof buf, "'%s': remaining bits - %u", idx->name,
257 (unsigned int)((sizeof(unsigned int) * 8) - (idx->highest_bit - 1)));
258 cb(buf, privdata);
259 }
260
261 snprintf(buf, sizeof buf, "%ld capability indexes", rb_dlink_list_length(&capability_indexes));
262 cb(buf, privdata);
263 }