-/* IRCQueue.c - NeonServ v5.4
+/* IRCQueue.c - NeonServ v5.5
* Copyright (C) 2011-2012 Philipp Kreil (pk910)
*
* This program is free software: you can redistribute it and/or modify
*/
#include "IRCQueue.h"
#include "ClientSocket.h"
+#include "IOHandler.h"
#define MAXPENALTY 8 /* 4 messages */
struct BotQueue {
struct ClientSocket *client;
- int penalty;
+ struct IODescriptor *iofd;
+ int penalty : 8;
+ int rem_penalty : 8;
struct QueueEntry *fastqueue_first, *fastqueue_last;
struct QueueEntry *normalqueue_first, *normalqueue_last;
struct QueueEntry *textqueue_first, *textqueue_last;
};
+static IOHANDLER_CALLBACK(queue_callback);
+
static struct BotQueue *initialize_queue(struct ClientSocket *client) {
struct BotQueue *queue = malloc(sizeof(*queue));
if (!queue) {
struct BotQueue *queue = client->queue;
char *args = strstr(msg, " ");
int type;
+ int add_queue = 0;
if(args) {
*args = '\0';
if(!stricmp(msg, "MODE"))
*args = ' ';
} else
type = 2;
- struct QueueEntry *entry = malloc(sizeof(*entry));
- if (!entry) {
- perror("malloc() failed");
- return 0;
+
+ //check if we need to queue
+ switch(type) {
+ case 1:
+ if(queue->textqueue_first) {
+ add_queue = 1;
+ break;
+ }
+ case 2:
+ if(queue->normalqueue_first) {
+ add_queue = 1;
+ break;
+ }
+ case 3:
+ if(queue->fastqueue_first) {
+ add_queue = 1;
+ break;
+ }
+ default:
+ if(queue->penalty >= MAXPENALTY)
+ add_queue = 1;
+ break;
}
- entry->msg = strdup(msg);
- entry->next = NULL;
- if(type == 1) { //low priority
- if(queue->textqueue_last) {
- queue->textqueue_last->next = entry;
- queue->textqueue_last = entry;
- } else {
- queue->textqueue_last = entry;
- queue->textqueue_first = entry;
+
+ if(!add_queue) {
+ int penalty = calculate_penalty(msg);
+ write_socket_force(client, msg, len);
+ queue->penalty += penalty;
+ if(!queue->iofd) {
+ struct timeval timeout;
+ gettimeofday(&timeout, NULL);
+ queue->rem_penalty = (MAXPENALTY - queue->penalty) + 1;
+ timeout.tv_sec += queue->rem_penalty;
+ queue->iofd = iohandler_timer(timeout, queue_callback);
}
- } else if(type == 2) { //normal priority
- if(queue->normalqueue_last) {
- queue->normalqueue_last->next = entry;
- queue->normalqueue_last = entry;
- } else {
- queue->normalqueue_last = entry;
- queue->normalqueue_first = entry;
+ } else {
+ struct QueueEntry *entry = malloc(sizeof(*entry));
+ if (!entry) {
+ perror("malloc() failed");
+ return 0;
}
- } else if(type == 3) { //high priority
- if(queue->fastqueue_last) {
- queue->fastqueue_last->next = entry;
- queue->fastqueue_last = entry;
- } else {
- queue->fastqueue_last = entry;
- queue->fastqueue_first = entry;
+ entry->msg = strdup(msg);
+ entry->next = NULL;
+ if(type == 1) { //low priority
+ if(queue->textqueue_last) {
+ queue->textqueue_last->next = entry;
+ queue->textqueue_last = entry;
+ } else {
+ queue->textqueue_last = entry;
+ queue->textqueue_first = entry;
+ }
+ } else if(type == 2) { //normal priority
+ if(queue->normalqueue_last) {
+ queue->normalqueue_last->next = entry;
+ queue->normalqueue_last = entry;
+ } else {
+ queue->normalqueue_last = entry;
+ queue->normalqueue_first = entry;
+ }
+ } else if(type == 3) { //high priority
+ if(queue->fastqueue_last) {
+ queue->fastqueue_last->next = entry;
+ queue->fastqueue_last = entry;
+ } else {
+ queue->fastqueue_last = entry;
+ queue->fastqueue_first = entry;
+ }
}
}
return 1;
free(entry->msg);
free(entry);
}
+ if(client->queue->iofd)
+ iohandler_close(client->queue->iofd);
free(client->queue);
client->queue = NULL;
}
-static struct timeval lastloop;
-void queue_init() {
- gettimeofday(&lastloop, NULL);
-}
-
-
-void queue_loop() {
- struct ClientSocket *bot;
- struct timeval now;
- gettimeofday(&now, NULL);
- long mtime, seconds, useconds;
- seconds = now.tv_sec - lastloop.tv_sec;
- useconds = now.tv_usec - lastloop.tv_usec;
- mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
- int fullseconds = mtime/1000;
- if(fullseconds) {
- lastloop.tv_sec += fullseconds;
- for(bot = getBots(0, NULL); bot; bot = getBots(0, bot)) {
- if(bot->queue && bot->queue->penalty) {
- bot->queue->penalty -= fullseconds;
- if(bot->queue->penalty < 0)
- bot->queue->penalty = 0;
- }
+static IOHANDLER_CALLBACK(queue_callback) {
+ struct BotQueue *queue = event->iofd->data;
+ switch(event->type) {
+ case IOEVENT_TIMEOUT:
+ queue->penalty -= queue->rem_penalty;
+ dequeue_bot(queue->client);
+ if(queue->penalty > 0) {
+ struct timeval timeout;
+ gettimeofday(&timeout, NULL);
+ queue->rem_penalty = (MAXPENALTY - queue->penalty) + 1;
+ timeout.tv_sec += queue->rem_penalty;
+ queue->iofd = iohandler_timer(timeout, queue_callback);
+ } else {
+ queue->iofd = NULL;
+ queue->penalty = 0;
}
- }
- for(bot = getBots(0, NULL); bot; bot = getBots(0, bot)) {
- if(bot->queue)
- dequeue_bot(bot);
+ break;
+ default:
+ break;
}
}