cb21075d |
1 | // ServerQueue.C -*- C++ -*- |
2 | // Copyright (c) 1997, 1998 Etienne BERNARD |
46af1667 |
3 | // Copyright (C) 2002,2005,2008 Clinton Ebadi |
cb21075d |
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 2 of the License, or |
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 |
c99c411a |
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 | // 02110-1301, USA. |
cb21075d |
19 | |
20 | #ifdef HAVE_CONFIG_H |
21 | #include "config.h" |
22 | #endif |
23 | |
4ce3a244 |
24 | #include <limits> |
cb21075d |
25 | #include "ServerQueue.H" |
fd7440f1 |
26 | #include "Utils.H" |
cb21075d |
27 | |
0b062618 |
28 | int ServerQueue::max_penalty = 20; |
29 | |
cb21075d |
30 | ServerQueue::ServerQueue(Socket * s, bool d) |
31 | : Queue(s,d), penalty(0) |
32 | { |
33 | #ifdef HAVE_STL_CLEAR |
34 | serverQueue.clear(); |
35 | #endif |
36 | } |
37 | |
38 | ServerQueue::~ServerQueue() |
39 | { |
4ce3a244 |
40 | penalty = std::numeric_limits<int>::min (); |
cb21075d |
41 | flush(); |
42 | } |
43 | |
44 | void |
45 | ServerQueue::addItem(ServerQueueItem *sqi) |
46 | { |
cd5342f5 |
47 | BotLock queue_lock (queue_mutex); |
cb21075d |
48 | std::list<ServerQueueItem *>::iterator it, it2; |
49 | |
c99c411a |
50 | for (it = serverQueue.begin(); it != serverQueue.end(); ++it) |
51 | { |
94a03421 |
52 | if (**it < *sqi) |
c99c411a |
53 | { |
54 | break; |
55 | } |
56 | } |
57 | |
58 | it2 = it; |
59 | --it2; |
60 | if (it2 != serverQueue.end() && *it2) |
61 | { |
62 | // All right, we try to merge this item to the previous |
63 | if ((*it2)->merge(sqi)) |
64 | { |
65 | delete sqi; |
66 | return; |
67 | } |
cb21075d |
68 | } |
c99c411a |
69 | |
cb21075d |
70 | serverQueue.insert(it, sqi); |
71 | } |
72 | |
73 | void |
74 | ServerQueue::addLine(String l, int pr, int pen, int t) |
75 | { |
76 | ServerQueueOtherItem * sqoi = |
77 | new ServerQueueOtherItem(l, pr, pen, t); |
78 | addItem(sqoi); |
79 | } |
80 | |
81 | bool |
82 | ServerQueue::flush() |
83 | { |
cd5342f5 |
84 | // Locking around the entire queue flush prevents another thread |
85 | // from spamming the queue and preventing lower priority messages |
86 | // from ever being sent |
87 | BotLock flush_lock (queue_mutex); |
88 | |
cb21075d |
89 | // Called every second, we decrement the penalty |
90 | if (penalty > 0) |
c99c411a |
91 | { |
92 | penalty--; |
93 | } |
94 | |
0b062618 |
95 | while (!serverQueue.empty() && (penalty < max_penalty)) |
c99c411a |
96 | { |
cd5342f5 |
97 | ServerQueueItem * sqi = serverQueue.front (); |
0b062618 |
98 | penalty += sqi->penalty + sqi->getLine().length()/100; |
c99c411a |
99 | |
100 | bool res = sendLine(sqi->getLine()); |
cd5342f5 |
101 | |
102 | serverQueue.pop_front (); |
c99c411a |
103 | delete sqi; |
104 | |
105 | if (!res) |
106 | { |
107 | return false; |
108 | } |
109 | } |
110 | |
cb21075d |
111 | return true; |
112 | } |
113 | |
fd7440f1 |
114 | #define MNICK (Interp::bot->nickName + "!" + Interp::bot->userHost) |
cb21075d |
115 | void |
116 | ServerQueue::sendCTCP(String to, String command, |
117 | String message) |
118 | { |
119 | sendPrivmsg(to, String("\001") + command + " " + message + "\001"); |
fd7440f1 |
120 | |
fd7440f1 |
121 | #ifdef USESCRIPTS |
122 | if (command == "ACTION") |
123 | { |
fed59248 |
124 | Interp::bot->botInterp->RunHooks (Hook::SEND_ACTION, |
125 | MNICK + " " + to + |
fd7440f1 |
126 | " " + message, |
46af1667 |
127 | scm_list_n (Utils:: |
a6339323 |
128 | str2scm (MNICK), |
fd7440f1 |
129 | Utils:: |
a6339323 |
130 | str2scm (to), |
fd7440f1 |
131 | Utils:: |
a6339323 |
132 | str2scm (message), |
fd7440f1 |
133 | SCM_UNDEFINED)); |
134 | } |
fed59248 |
135 | else |
136 | Interp::bot->botInterp->RunHooks (Hook::SEND_CTCP, |
c99c411a |
137 | MNICK + " " + to + " " + |
138 | command + " " + message, |
46af1667 |
139 | scm_list_n (Utils:: |
c99c411a |
140 | str2scm (MNICK), |
141 | Utils:: |
142 | str2scm (to), |
143 | Utils:: |
144 | str2scm |
145 | (command), |
146 | Utils:: |
147 | str2scm (message), |
148 | SCM_UNDEFINED)); |
fd7440f1 |
149 | #endif |
150 | |
cb21075d |
151 | } |
fd7440f1 |
152 | #undef MNICK |
cb21075d |
153 | |
154 | void |
155 | ServerQueue::sendCTCPReply(String to, String command, |
156 | String message) |
157 | { |
158 | sendNotice(to, String("\001") + command + " " + |
159 | message + "\001"); |
160 | } |
161 | |
162 | void |
163 | ServerQueue::sendChannelMode(String mode) |
164 | { |
165 | addLine(mode, CHANNELMODE_PRIORITY, CHANNELMODE_PENALTY, |
166 | ServerQueueItem::CHANNELMODE); |
167 | } |
168 | |
169 | void |
170 | ServerQueue::sendChannelMode(String channel, String mode, String parameters) |
171 | { |
172 | ServerQueueChannelModeItem * sqcmi = |
173 | new ServerQueueChannelModeItem(channel, mode, parameters); |
174 | addItem(sqcmi); |
175 | } |
176 | |
177 | void |
178 | ServerQueue::sendInvite(String channel, String nick) |
179 | { |
180 | addLine(String("INVITE ") + nick + " " + channel, |
181 | INVITE_PRIORITY, INVITE_PENALTY, ServerQueueItem::INVITE); |
182 | } |
183 | |
184 | void |
185 | ServerQueue::sendJoin(String channel, String key) |
186 | { |
187 | addLine(String("JOIN ") + channel + " " + key, |
188 | JOIN_PRIORITY, JOIN_PENALTY, ServerQueueItem::JOIN); |
189 | } |
190 | |
191 | void |
192 | ServerQueue::sendKick(String channel, String nick, String reason) |
193 | { |
194 | ServerQueueKickItem * sqki = |
195 | new ServerQueueKickItem(channel, nick, reason); |
196 | addItem(sqki); |
197 | } |
198 | |
199 | void |
200 | ServerQueue::sendNick(String nick) |
201 | { |
202 | addLine(String("NICK ") + nick, |
203 | NICK_PRIORITY, NICK_PENALTY, ServerQueueItem::NICK); |
204 | } |
205 | |
206 | void |
207 | ServerQueue::sendNotice(String to, String message) |
208 | { |
209 | ServerQueueNoticeItem *sqni = |
210 | new ServerQueueNoticeItem(to, message); |
211 | addItem(sqni); |
212 | } |
213 | |
214 | void |
215 | ServerQueue::sendPart(String channel) |
216 | { |
217 | addLine(String("PART ") + channel, |
218 | PART_PRIORITY, PART_PENALTY, ServerQueueItem::PART); |
219 | } |
220 | |
221 | void |
222 | ServerQueue::sendPass(String pass) |
223 | { |
224 | addLine(String("PASS ") + pass, |
225 | NICK_PRIORITY, NICK_PENALTY, ServerQueueItem::PASS); |
226 | } |
227 | |
228 | void |
229 | ServerQueue::sendPing(String server) |
230 | { |
231 | addLine(String("PING :") + server, |
232 | PING_PRIORITY, PING_PENALTY, ServerQueueItem::PING); |
233 | } |
234 | |
235 | void |
236 | ServerQueue::sendPong(String crap) |
237 | { |
238 | addLine(String("PONG ") + crap, |
239 | PONG_PRIORITY, PONG_PENALTY, ServerQueueItem::PONG); |
240 | } |
241 | |
242 | void |
243 | ServerQueue::sendPrivmsg(String dest, String message) |
244 | { |
245 | addLine(String("PRIVMSG ") + dest + " :" + message, |
246 | PRIVMSG_PRIORITY, PRIVMSG_PENALTY, ServerQueueItem::PRIVMSG); |
fd7440f1 |
247 | // hook stuff |
248 | #ifdef USESCRIPTS |
249 | if (message[0] != '\001') |
a6339323 |
250 | if (Utils::channel_p (dest)) |
fed59248 |
251 | Interp::bot->botInterp->RunHooks (Hook::SEND_PUBLIC, |
fd7440f1 |
252 | Interp::bot->nickName + " " + dest + |
253 | " " + message, |
46af1667 |
254 | scm_list_n |
c99c411a |
255 | (Utils::str2scm |
256 | (Interp::bot->nickName), |
257 | Utils::str2scm (dest), |
258 | Utils::str2scm (message), |
259 | SCM_UNDEFINED)); |
fd7440f1 |
260 | else |
ae97d6ec |
261 | Interp::bot->botInterp->RunHooks |
262 | (Hook::SEND_MESSAGE, |
263 | Interp::bot->nickName + " " + dest + |
264 | message, |
46af1667 |
265 | scm_list_n (Utils::str2scm (Interp::bot->nickName), |
ae97d6ec |
266 | Utils::str2scm (dest), |
267 | Utils::str2scm |
268 | (message), SCM_UNDEFINED)); |
fd7440f1 |
269 | #endif |
cb21075d |
270 | } |
271 | |
272 | void |
273 | ServerQueue::sendQuit(String reason) |
274 | { |
275 | addLine(String("QUIT :") + reason, |
276 | QUIT_PRIORITY, QUIT_PENALTY, ServerQueueItem::QUIT); |
277 | } |
278 | |
279 | void |
280 | ServerQueue::sendTopic(String channel, String topic) |
281 | { |
282 | addLine(String("TOPIC ") + channel + " :" + topic, |
283 | TOPIC_PRIORITY, TOPIC_PENALTY, ServerQueueItem::TOPIC); |
284 | } |
285 | |
286 | void |
287 | ServerQueue::sendUser(String username, String ircname) |
288 | { |
439869bf |
289 | addLine(String("USER ") + username + " 0 * :" + ircname, |
cb21075d |
290 | NICK_PRIORITY, NICK_PENALTY, ServerQueueItem::USER); |
291 | } |
292 | |
293 | void |
294 | ServerQueue::sendUserMode(String nick, String mode) |
295 | { |
296 | addLine(String("MODE ") + nick + " " + mode, |
297 | USERMODE_PRIORITY, USERMODE_PENALTY, |
298 | ServerQueueItem::USERMODE); |
299 | } |
300 | |
301 | void |
302 | ServerQueue::sendUserhost(String nick) |
303 | { |
304 | addLine(String("USERHOST ") + nick, |
305 | USERHOST_PRIORITY, USERHOST_PENALTY, ServerQueueItem::USERHOST); |
306 | } |
307 | |
308 | void |
309 | ServerQueue::sendWho(String who) |
310 | { |
311 | addLine(String("WHO ") + who, |
312 | WHO_PRIORITY, WHO_PENALTY, ServerQueueItem::WHO); |
528799bd |
313 | |
314 | #ifdef USESCRIPTS |
315 | Interp::bot->botInterp->RunHooks (Hook::SEND_WHO, |
316 | who, |
317 | scm_list_n (Utils:: |
318 | str2scm (who), |
319 | SCM_UNDEFINED)); |
320 | #endif |
cb21075d |
321 | } |
322 | |
323 | void |
324 | ServerQueue::sendWhois(String nick) |
325 | { |
326 | addLine(String("WHOIS ") + nick, |
327 | NICK_PRIORITY, WHOIS_PENALTY, ServerQueueItem::WHOIS); |
528799bd |
328 | |
329 | #ifdef USESCRIPTS |
330 | Interp::bot->botInterp->RunHooks (Hook::SEND_WHOIS, |
331 | nick, |
332 | scm_list_n (Utils:: |
333 | str2scm (nick), |
334 | SCM_UNDEFINED)); |
335 | #endif |
cb21075d |
336 | } |