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