1 /* IRCQueue.c - NeonServ v5.2
2 * Copyright (C) 2011 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "ClientSocket.h"
20 #define MAXPENALTY 8 /* 4 messages */
24 struct QueueEntry *next;
28 struct ClientSocket *client;
30 struct QueueEntry *fastqueue_first, *fastqueue_last;
31 struct QueueEntry *normalqueue_first, *normalqueue_last;
32 struct QueueEntry *textqueue_first, *textqueue_last;
35 static struct BotQueue *initialize_queue(struct ClientSocket *client) {
36 struct BotQueue *queue = malloc(sizeof(*queue));
38 perror("malloc() failed");
41 queue->client = client;
42 client->queue = queue;
44 queue->fastqueue_first = NULL;
45 queue->fastqueue_last = NULL;
46 queue->normalqueue_first = NULL;
47 queue->normalqueue_last = NULL;
48 queue->textqueue_first = NULL;
49 queue->textqueue_last = NULL;
53 int queue_add(struct ClientSocket *client, char* msg, int len) {
55 client->queue = initialize_queue(client);
56 struct BotQueue *queue = client->queue;
57 char *args = strstr(msg, " ");
61 if(!stricmp(msg, "MODE"))
63 else if(!stricmp(msg, "KICK"))
65 else if(!stricmp(msg, "PONG"))
67 else if(!stricmp(msg, "PRIVMSG"))
69 else if(!stricmp(msg, "NOTICE"))
71 else if(!stricmp(msg, "WHO"))
78 struct QueueEntry *entry = malloc(sizeof(*entry));
80 perror("malloc() failed");
83 entry->msg = strdup(msg);
85 if(type == 1) { //low priority
86 if(queue->textqueue_last) {
87 queue->textqueue_last->next = entry;
88 queue->textqueue_last = entry;
90 queue->textqueue_last = entry;
91 queue->textqueue_first = entry;
93 } else if(type == 2) { //normal priority
94 if(queue->normalqueue_last) {
95 queue->normalqueue_last->next = entry;
96 queue->normalqueue_last = entry;
98 queue->normalqueue_last = entry;
99 queue->normalqueue_first = entry;
101 } else if(type == 3) { //high priority
102 if(queue->fastqueue_last) {
103 queue->fastqueue_last->next = entry;
104 queue->fastqueue_last = entry;
106 queue->fastqueue_last = entry;
107 queue->fastqueue_first = entry;
113 static int calculate_penalty(char *message) {
114 int msglen = strlen(message);
115 int penalty = (2 + msglen / 100);
119 static void dequeue_bot(struct ClientSocket *client) {
120 if(client->queue->penalty >= MAXPENALTY) return;
122 //try to send high priority messages
123 if(client->queue->fastqueue_first) {
125 struct QueueEntry *entry = client->queue->fastqueue_first;
127 client->queue->fastqueue_last = NULL;
128 client->queue->fastqueue_first = client->queue->fastqueue_first->next;
129 penalty = calculate_penalty(entry->msg);
130 write_socket_force(client, entry->msg, strlen(entry->msg));
131 client->queue->penalty += penalty;
134 } while(client->queue->penalty < MAXPENALTY && client->queue->fastqueue_first);
136 if(client->queue->penalty >= MAXPENALTY) return;
137 //try to send normal priority messages
138 if(client->queue->normalqueue_first) {
140 struct QueueEntry *entry = client->queue->normalqueue_first;
142 client->queue->normalqueue_last = NULL;
143 client->queue->normalqueue_first = client->queue->normalqueue_first->next;
144 penalty = calculate_penalty(entry->msg);
145 write_socket_force(client, entry->msg, strlen(entry->msg));
146 client->queue->penalty += penalty;
149 } while(client->queue->penalty < MAXPENALTY && client->queue->normalqueue_first);
151 if(client->queue->penalty >= MAXPENALTY) return;
152 //try to send low priority messages
153 if(client->queue->textqueue_first) {
155 struct QueueEntry *entry = client->queue->textqueue_first;
157 client->queue->textqueue_last = NULL;
158 client->queue->textqueue_first = client->queue->textqueue_first->next;
159 penalty = calculate_penalty(entry->msg);
160 write_socket_force(client, entry->msg, strlen(entry->msg));
161 client->queue->penalty += penalty;
164 } while(client->queue->penalty < MAXPENALTY && client->queue->textqueue_first);
168 void queue_destroy(struct ClientSocket *client) {
169 if(!client->queue) return;
170 struct QueueEntry *entry, *next;
171 for(entry = client->queue->fastqueue_first; entry; entry = next) {
176 for(entry = client->queue->normalqueue_first; entry; entry = next) {
181 for(entry = client->queue->textqueue_first; entry; entry = next) {
187 client->queue = NULL;
190 static struct timeval lastloop;
192 gettimeofday(&lastloop, NULL);
197 struct ClientSocket *bot;
199 gettimeofday(&now, NULL);
200 long mtime, seconds, useconds;
201 seconds = now.tv_sec - lastloop.tv_sec;
202 useconds = now.tv_usec - lastloop.tv_usec;
203 mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
204 int fullseconds = mtime/1000;
206 lastloop.tv_sec += fullseconds;
207 for(bot = getBots(0, NULL); bot; bot = getBots(0, bot)) {
208 if(bot->queue && bot->queue->penalty) {
209 bot->queue->penalty -= fullseconds;
210 if(bot->queue->penalty < 0)
211 bot->queue->penalty = 0;
215 for(bot = getBots(0, NULL); bot; bot = getBots(0, bot)) {