257f359e006a32e480314f9f227675596cb9d022
[ircu2.10.12-pk.git] / ircd / class.c
1 /*
2  * IRC - Internet Relay Chat, ircd/class.c
3  * Copyright (C) 1990 Darren Reed
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 1, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include "sys.h"
21 #include "h.h"
22 #include "struct.h"
23 #include "class.h"
24 #include "s_conf.h"
25 #include "s_serv.h"
26 #include "send.h"
27 #include "s_err.h"
28 #include "numeric.h"
29 #include "ircd.h"
30
31 RCSTAG_CC("$Id$");
32
33 #define BAD_CONF_CLASS          ((unsigned int)-1)
34 #define BAD_PING                ((unsigned int)-2)
35 #define BAD_CLIENT_CLASS        ((unsigned int)-3)
36
37 aConfClass *classes;
38
39 unsigned int get_conf_class(aConfItem *aconf)
40 {
41   if ((aconf) && (aconf->confClass))
42     return (ConfClass(aconf));
43
44   Debug((DEBUG_DEBUG, "No Class For %s", (aconf) ? aconf->name : "*No Conf*"));
45
46   return (BAD_CONF_CLASS);
47
48 }
49
50 static unsigned int get_conf_ping(aConfItem *aconf)
51 {
52   if ((aconf) && (aconf->confClass))
53     return (ConfPingFreq(aconf));
54
55   Debug((DEBUG_DEBUG, "No Ping For %s", (aconf) ? aconf->name : "*No Conf*"));
56
57   return (BAD_PING);
58 }
59
60 unsigned int get_client_class(aClient *acptr)
61 {
62   Reg1 Link *tmp;
63   Reg2 aConfClass *cl;
64   unsigned int retc = BAD_CLIENT_CLASS;
65
66   if (acptr && !IsMe(acptr) && !IsPing(acptr) && (acptr->confs))
67     for (tmp = acptr->confs; tmp; tmp = tmp->next)
68     {
69       if (!tmp->value.aconf || !(cl = tmp->value.aconf->confClass))
70         continue;
71       if (ConClass(cl) > retc || retc == BAD_CLIENT_CLASS)
72         retc = ConClass(cl);
73     }
74
75   Debug((DEBUG_DEBUG, "Returning Class %d For %s", retc, acptr->name));
76
77   return (retc);
78 }
79
80 int unsigned get_client_ping(aClient *acptr)
81 {
82   unsigned int ping = 0, ping2;
83   aConfItem *aconf;
84   Link *link;
85
86   link = acptr->confs;
87
88   if (link)
89     while (link)
90     {
91       aconf = link->value.aconf;
92       if (aconf->status &
93           (CONF_CLIENT | CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER))
94       {
95         ping2 = get_conf_ping(aconf);
96         if ((ping2 != BAD_PING) && ((ping > ping2) || !ping))
97           ping = ping2;
98       }
99       link = link->next;
100     }
101   else
102   {
103     ping = PINGFREQUENCY;
104     Debug((DEBUG_DEBUG, "No Attached Confs"));
105   }
106   if (ping <= 0)
107     ping = PINGFREQUENCY;
108   Debug((DEBUG_DEBUG, "Client %s Ping %d", acptr->name, ping));
109   return (ping);
110 }
111
112 unsigned int get_con_freq(aConfClass * clptr)
113 {
114   if (clptr)
115     return (ConFreq(clptr));
116   else
117     return (CONNECTFREQUENCY);
118 }
119
120 /*
121  * When adding a class, check to see if it is already present first.
122  * if so, then update the information for that class, rather than create
123  * a new entry for it and later delete the old entry.
124  * if no present entry is found, then create a new one and add it in
125  * immeadiately after the first one (class 0).
126  */
127 void add_class(unsigned int conClass, unsigned int ping, unsigned int confreq,
128     unsigned int maxli, size_t sendq)
129 {
130   aConfClass *t, *p;
131
132   t = find_class(conClass);
133   if ((t == classes) && (conClass != 0))
134   {
135     p = (aConfClass *) make_class();
136     NextClass(p) = NextClass(t);
137     NextClass(t) = p;
138   }
139   else
140     p = t;
141   Debug((DEBUG_DEBUG, "Add Class %u: p %p t %p - cf: %u pf: %u ml: %u sq: %d",
142       conClass, p, t, confreq, ping, maxli, sendq));
143   ConClass(p) = conClass;
144   ConFreq(p) = confreq;
145   PingFreq(p) = ping;
146   MaxLinks(p) = maxli;
147   MaxSendq(p) = (sendq > 0) ? sendq : DEFAULTMAXSENDQLENGTH;
148   if (p != t)
149     Links(p) = 0;
150 }
151
152 aConfClass *find_class(unsigned int cclass)
153 {
154   aConfClass *cltmp;
155
156   for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
157     if (ConClass(cltmp) == cclass)
158       return cltmp;
159   return classes;
160 }
161
162 void check_class(void)
163 {
164   aConfClass *cltmp, *cltmp2;
165
166   Debug((DEBUG_DEBUG, "Class check:"));
167
168   for (cltmp2 = cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp2))
169   {
170     Debug((DEBUG_DEBUG,
171         "Class %d : CF: %d PF: %d ML: %d LI: %d SQ: %d",
172         ConClass(cltmp), ConFreq(cltmp), PingFreq(cltmp),
173         MaxLinks(cltmp), Links(cltmp), MaxSendq(cltmp)));
174     if (IsMarkedDelete(cltmp))
175     {
176       NextClass(cltmp2) = NextClass(cltmp);
177       if (Links(cltmp) == 0)
178         free_class(cltmp);
179     }
180     else
181       cltmp2 = cltmp;
182   }
183 }
184
185 void initclass(void)
186 {
187   classes = (aConfClass *) make_class();
188
189   ConClass(FirstClass()) = 0;
190   ConFreq(FirstClass()) = CONNECTFREQUENCY;
191   PingFreq(FirstClass()) = PINGFREQUENCY;
192   MaxLinks(FirstClass()) = MAXIMUM_LINKS;
193   MaxSendq(FirstClass()) = DEFAULTMAXSENDQLENGTH;
194   Links(FirstClass()) = 0;
195   NextClass(FirstClass()) = NULL;
196 }
197
198 void report_classes(aClient *sptr)
199 {
200   aConfClass *cltmp;
201
202   for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
203     sendto_one(sptr, rpl_str(RPL_STATSYLINE), me.name, sptr->name,
204         'Y', ConClass(cltmp), PingFreq(cltmp), ConFreq(cltmp),
205         MaxLinks(cltmp), MaxSendq(cltmp));
206 }
207
208 size_t get_sendq(aClient *cptr)
209 {
210   size_t sendq = DEFAULTMAXSENDQLENGTH;
211   Link *tmp;
212   aConfClass *cl;
213
214   if (cptr && !IsMe(cptr) && (cptr->confs))
215     for (tmp = cptr->confs; tmp; tmp = tmp->next)
216     {
217       if (!tmp->value.aconf || !(cl = tmp->value.aconf->confClass))
218         continue;
219       if (ConClass(cl) != BAD_CLIENT_CLASS)
220         sendq = MaxSendq(cl);
221     }
222   return sendq;
223 }