]>
Commit | Line | Data |
---|---|---|
1 | /* channelindex.c */ | |
2 | ||
3 | #include "chanindex.h" | |
4 | #include "../irc/irc_config.h" | |
5 | #include "../lib/irc_string.h" | |
6 | #include "../core/error.h" | |
7 | #include "../core/nsmalloc.h" | |
8 | #include "../lib/version.h" | |
9 | ||
10 | #include <stdio.h> | |
11 | #include <string.h> | |
12 | ||
13 | MODULE_VERSION("") | |
14 | ||
15 | #define channelhash(x) (crc32i(x)%CHANNELHASHSIZE) | |
16 | ||
17 | chanindex *chantable[CHANNELHASHSIZE]; | |
18 | sstring *extnames[MAXCHANNELEXTS]; | |
19 | ||
20 | unsigned int channelmarker; | |
21 | ||
22 | void _init() { | |
23 | memset(chantable,0,sizeof(chantable)); | |
24 | memset(extnames,0,sizeof(extnames)); | |
25 | channelmarker=0; | |
26 | } | |
27 | ||
28 | void _fini() { | |
29 | nsfreeall(POOL_CHANINDEX); | |
30 | } | |
31 | ||
32 | chanindex *getchanindex() { | |
33 | return nsmalloc(POOL_CHANINDEX, sizeof(chanindex)); | |
34 | } | |
35 | ||
36 | void freechanindex(chanindex *cip) { | |
37 | nsfree(POOL_CHANINDEX, cip); | |
38 | } | |
39 | ||
40 | chanindex *findchanindex(const char *name) { | |
41 | chanindex *cip; | |
42 | int hash=channelhash(name); | |
43 | ||
44 | for (cip=chantable[hash];cip;cip=cip->next) { | |
45 | if (!ircd_strcmp(cip->name->content,name)) { | |
46 | return cip; | |
47 | } | |
48 | } | |
49 | ||
50 | return NULL; | |
51 | } | |
52 | ||
53 | chanindex *findorcreatechanindex(const char *name) { | |
54 | chanindex *cip; | |
55 | int hash=channelhash(name); | |
56 | int i; | |
57 | ||
58 | for (cip=chantable[hash];cip;cip=cip->next) { | |
59 | if (!ircd_strcmp(cip->name->content,name)) { | |
60 | return cip; | |
61 | } | |
62 | } | |
63 | ||
64 | cip=getchanindex(); | |
65 | ||
66 | cip->name=getsstring(name,CHANNELLEN); | |
67 | cip->channel=NULL; | |
68 | cip->marker=0; | |
69 | cip->next=chantable[hash]; | |
70 | chantable[hash]=cip; | |
71 | ||
72 | for(i=0;i<MAXCHANNELEXTS;i++) { | |
73 | cip->exts[i]=NULL; | |
74 | } | |
75 | ||
76 | return cip; | |
77 | } | |
78 | ||
79 | void releasechanindex(chanindex *cip) { | |
80 | int i; | |
81 | chanindex **cih; | |
82 | int hash; | |
83 | ||
84 | /* If any module is still using the channel, do nothing */ | |
85 | /* Same if the channel is still present on the network */ | |
86 | ||
87 | if (cip->channel!=NULL) { | |
88 | return; | |
89 | } | |
90 | ||
91 | for (i=0;i<MAXCHANNELEXTS;i++) { | |
92 | if (cip->exts[i]!=NULL) { | |
93 | return; | |
94 | } | |
95 | } | |
96 | ||
97 | /* Now remove the index record from the index. */ | |
98 | hash=channelhash(cip->name->content); | |
99 | ||
100 | for(cih=&(chantable[hash]);*cih;cih=&((*cih)->next)) { | |
101 | if (*cih==cip) { | |
102 | (*cih)=cip->next; | |
103 | freesstring(cip->name); | |
104 | freechanindex(cip); | |
105 | return; | |
106 | } | |
107 | } | |
108 | ||
109 | Error("channel",ERR_ERROR,"Tried to release chanindex record for %s not found in hash",cip->name->content); | |
110 | } | |
111 | ||
112 | int registerchanext(const char *name) { | |
113 | int i; | |
114 | ||
115 | if (findchanext(name)!=-1) { | |
116 | Error("channel",ERR_WARNING,"Tried to register duplicate extension %s",name); | |
117 | return -1; | |
118 | } | |
119 | ||
120 | for (i=0;i<MAXCHANNELEXTS;i++) { | |
121 | if (extnames[i]==NULL) { | |
122 | extnames[i]=getsstring(name,100); | |
123 | return i; | |
124 | } | |
125 | } | |
126 | ||
127 | Error("channel",ERR_WARNING,"Tried to register too many extensions: %s",name); | |
128 | return -1; | |
129 | } | |
130 | ||
131 | int findchanext(const char *name) { | |
132 | int i; | |
133 | ||
134 | for (i=0;i<MAXCHANNELEXTS;i++) { | |
135 | if (extnames[i]!=NULL && !ircd_strcmp(name,extnames[i]->content)) { | |
136 | return i; | |
137 | } | |
138 | } | |
139 | ||
140 | return -1; | |
141 | } | |
142 | ||
143 | void releasechanext(int index) { | |
144 | int i; | |
145 | chanindex *cip,*ncip; | |
146 | ||
147 | freesstring(extnames[index]); | |
148 | extnames[index]=NULL; | |
149 | ||
150 | for (i=0;i<CHANNELHASHSIZE;i++) { | |
151 | for (cip=chantable[i];cip;cip=ncip) { | |
152 | /* CAREFUL: deleting items from chains you're walking is bad */ | |
153 | ncip=cip->next; | |
154 | if (cip->exts[index]!=NULL) { | |
155 | cip->exts[index]=NULL; | |
156 | releasechanindex(cip); | |
157 | } | |
158 | } | |
159 | } | |
160 | } | |
161 | ||
162 | unsigned int nextchanmarker() { | |
163 | int i; | |
164 | chanindex *cip; | |
165 | ||
166 | channelmarker++; | |
167 | if (!channelmarker) { | |
168 | /* If we wrapped to zero, zap the marker on all records */ | |
169 | for (i=0;i<CHANNELHASHSIZE;i++) | |
170 | for (cip=chantable[i];cip;cip=cip->next) | |
171 | cip->marker=0; | |
172 | channelmarker++; | |
173 | } | |
174 | ||
175 | return channelmarker; | |
176 | } |