new buffering strategy
This commit is contained in:
parent
43d31d6b79
commit
f06b358d0f
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
.gdb_history
|
.gdb_history
|
||||||
*.o
|
*.o
|
||||||
|
*.out
|
||||||
hibot
|
hibot
|
||||||
|
173
source/bot.h
173
source/bot.h
@ -6,7 +6,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
extern syntax_setter_t syntax_functions[];
|
extern syntax_setter_t syntax_functions[];
|
||||||
|
|
||||||
@ -31,111 +30,30 @@ char * username_root(const char * const fullname){
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
void on_request_timeout(int unused) {
|
||||||
int is_active;
|
(void)(unused);
|
||||||
char * user;
|
drop_request(request_queue[0]);
|
||||||
language_t language;
|
|
||||||
struct itimerval timer;
|
|
||||||
char * buffer[128]; // XXX: no overflow detection/avertion
|
|
||||||
unsigned int buffer_head; // is implemented on this bunch
|
|
||||||
} request_t;
|
|
||||||
|
|
||||||
void init_request(request_t * request) {
|
|
||||||
request->is_active = 0;
|
|
||||||
request->timer.it_value.tv_sec = 0;
|
|
||||||
request->timer.it_value.tv_usec = 0;
|
|
||||||
request->timer.it_interval.tv_sec = 0;
|
|
||||||
request->timer.it_interval.tv_usec = 0;
|
|
||||||
request->buffer_head = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request_t request_queue__[message_queue_size];
|
void flush_request(request_t * request) {
|
||||||
request_t * request_queue[message_queue_size];
|
// Message header
|
||||||
unsigned int request_queue_head = 0;
|
|
||||||
|
|
||||||
static inline
|
|
||||||
void touch_request_timer(request_t * request) {
|
|
||||||
request->timer.it_value.tv_sec = message_timeout;
|
|
||||||
setitimer(ITIMER_REAL, &(request->timer), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void activate_request(request_t * request) {
|
|
||||||
request->is_active = 1;
|
|
||||||
|
|
||||||
/* message header */
|
|
||||||
char * short_name = username_root(request->user);
|
char * short_name = username_root(request->user);
|
||||||
irc_message(short_name);
|
irc_message(short_name);
|
||||||
free(short_name);
|
free(short_name);
|
||||||
}
|
|
||||||
|
|
||||||
request_t * take_request(const char * const user, language_t language) {
|
// Message body
|
||||||
for (unsigned int i = 0; i < request_queue_head; i++) {
|
syntax_count = 0;
|
||||||
if(!strcmp(request_queue[i]->user, user)) {
|
syntax_functions[request->language]();
|
||||||
return request_queue[i];
|
for (unsigned i = 0; i < request->buffer_head; i++) {
|
||||||
}
|
irc_message(syntax_highlight(request->buffer[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request_queue_head == message_queue_size) {
|
// Message footer
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
request_t * request = request_queue[request_queue_head];
|
|
||||||
|
|
||||||
request->language = language;
|
|
||||||
request->user = strdup(user);
|
|
||||||
|
|
||||||
if (request_queue_head == 0) {
|
|
||||||
activate_request(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
++request_queue_head;
|
|
||||||
|
|
||||||
char * log_message;
|
|
||||||
asprintf(&log_message, "Took message: %p (%d)", (void*)request, request_queue_head);
|
|
||||||
log_notice(log_message);
|
|
||||||
free(log_message);
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drop_reqest() {
|
|
||||||
request_t * request = request_queue[0];
|
|
||||||
|
|
||||||
if (message_queue_size > 1) {
|
|
||||||
for (unsigned int i = 0; i < request_queue_head; i++) {
|
|
||||||
request_queue[i] = request_queue[i+1];
|
|
||||||
}
|
|
||||||
request_queue[request_queue_head] = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
--request_queue_head;
|
|
||||||
|
|
||||||
request->is_active = 0;
|
|
||||||
free(request->user);
|
|
||||||
|
|
||||||
if (request_queue_head) {
|
|
||||||
activate_request(request_queue[0]);
|
|
||||||
for (unsigned int i = 0; i < request_queue[0]->buffer_head; i++) {
|
|
||||||
irc_message(request_queue[0]->buffer[i]);
|
|
||||||
free(request_queue[0]->buffer[i]);
|
|
||||||
}
|
|
||||||
request_queue[0]->buffer_head = 0;
|
|
||||||
touch_request_timer(request_queue[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char * log_message;
|
|
||||||
asprintf(&log_message, "Dropped message: %p (%d)", (void*)request, request_queue_head);
|
|
||||||
log_notice(log_message);
|
|
||||||
free(log_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_message_timeout(int unused) {
|
|
||||||
(void)unused;
|
|
||||||
|
|
||||||
/* message footer */
|
|
||||||
irc_message("--");
|
irc_message("--");
|
||||||
|
|
||||||
drop_reqest(request_queue);
|
logf_notice("Flushed message: %p (%d)", (void*)request, request_queue_head);
|
||||||
|
|
||||||
|
drop_request(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -165,6 +83,7 @@ void irc_help() {
|
|||||||
irc_message(" !<language> // set language for next message");
|
irc_message(" !<language> // set language for next message");
|
||||||
irc_message(" <code> // echo this code");
|
irc_message(" <code> // echo this code");
|
||||||
irc_message(" !<language> <code> // set language and echo code");
|
irc_message(" !<language> <code> // set language and echo code");
|
||||||
|
irc_message(" !-- // flush all code");
|
||||||
irc_message("--");
|
irc_message("--");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,10 +101,7 @@ void event_connect(irc_session_t * session,
|
|||||||
|
|
||||||
log_notice("IRC connection secured.");
|
log_notice("IRC connection secured.");
|
||||||
irc_cmd_join(session, channel, 0);
|
irc_cmd_join(session, channel, 0);
|
||||||
char * buffer;
|
logf_notice("Joined destination channel: `%s`.", channel);
|
||||||
asprintf(&buffer, "Joined destination channel: `%s`.", channel);
|
|
||||||
log_notice(buffer);
|
|
||||||
free(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -194,6 +110,7 @@ void event_disconnect(irc_session_t * session,
|
|||||||
const char * origin,
|
const char * origin,
|
||||||
const char ** params,
|
const char ** params,
|
||||||
unsigned int count) {
|
unsigned int count) {
|
||||||
|
(void)session;
|
||||||
(void)event;
|
(void)event;
|
||||||
(void)origin;
|
(void)origin;
|
||||||
(void)params;
|
(void)params;
|
||||||
@ -218,6 +135,11 @@ void event_privmsg(irc_session_t * session,
|
|||||||
|
|
||||||
/* Is command */
|
/* Is command */
|
||||||
if (*message == '!') {
|
if (*message == '!') {
|
||||||
|
if (!strcmp(message, "!help")) {
|
||||||
|
irc_help();
|
||||||
|
goto END;
|
||||||
|
}
|
||||||
|
/* */
|
||||||
terminator = message;
|
terminator = message;
|
||||||
while (*terminator != ' ') {
|
while (*terminator != ' ') {
|
||||||
if (*terminator == '\0') {
|
if (*terminator == '\0') {
|
||||||
@ -227,38 +149,39 @@ void event_privmsg(irc_session_t * session,
|
|||||||
++terminator;
|
++terminator;
|
||||||
}
|
}
|
||||||
*terminator = '\0';
|
*terminator = '\0';
|
||||||
/* */
|
/* */
|
||||||
if (!strcmp(message, "!help")) {
|
{
|
||||||
irc_help();
|
request_t * request = take_request(origin);
|
||||||
goto END;
|
|
||||||
}
|
if (!strcmp(message, "!--")) {
|
||||||
/* get language */
|
if (request) {
|
||||||
for (char * s = message + 1; *s != '\0'; s++) {
|
flush_request(request);
|
||||||
*s = toupper(*s);
|
}
|
||||||
}
|
goto END;
|
||||||
int l = translate_language(message + 1);
|
}
|
||||||
message = terminator + 1;
|
|
||||||
if (l != -1) {
|
/* get language */
|
||||||
language = l;
|
for (char * s = message + 1; *s != '\0'; s++) {
|
||||||
syntax_count = 0;
|
*s = toupper(*s);
|
||||||
syntax_functions[language]();
|
}
|
||||||
}
|
int l = translate_language(message + 1);
|
||||||
|
message = terminator + 1;
|
||||||
|
if (l != -1) {
|
||||||
|
request->language = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is code */
|
/* Is code */
|
||||||
if (is_code) {
|
if (is_code) {
|
||||||
request_t * request = take_request(origin, language);
|
request_t * request = take_request(origin);
|
||||||
if (!request) {
|
if (!request) {
|
||||||
irc_private_message(origin, message_queue_full_message);
|
irc_private_message(origin, message_queue_full_message);
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->is_active) {
|
touch_request_timer(request);
|
||||||
touch_request_timer(request);
|
request->buffer[request->buffer_head++] = strdup(message);
|
||||||
irc_message(syntax_highlight(message));
|
|
||||||
} else {
|
|
||||||
request->buffer[request->buffer_head++] = strdup(syntax_highlight(message));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
END:
|
END:
|
||||||
@ -302,7 +225,7 @@ int connect_bot(const char * const server, const short port) {
|
|||||||
request_queue[i] = &request_queue__[i];
|
request_queue[i] = &request_queue__[i];
|
||||||
init_request(request_queue[i]);
|
init_request(request_queue[i]);
|
||||||
}
|
}
|
||||||
signal(SIGALRM, on_message_timeout);
|
signal(SIGALRM, on_request_timeout);
|
||||||
|
|
||||||
irc_connect(session,
|
irc_connect(session,
|
||||||
server,
|
server,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const char * const username = PROGRAM_NAME;
|
const char * const username = PROGRAM_NAME;
|
||||||
const char * const password = "";
|
const char * const password = "";
|
||||||
const int message_timeout = 3;
|
const int message_timeout = 10;
|
||||||
const char * const message_queue_full_message = "Air space too crowded in this area.";
|
const char * const message_queue_full_message = "Air space too crowded in this area.";
|
||||||
#define message_queue_size 3
|
#define message_queue_size 3
|
||||||
#define DEFAULT_LANGUAGE C
|
#define DEFAULT_LANGUAGE C
|
||||||
|
24
source/log.h
24
source/log.h
@ -1,6 +1,8 @@
|
|||||||
#ifndef LOG_H
|
#ifndef LOG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
FILE * log_file;
|
FILE * log_file;
|
||||||
|
|
||||||
@ -13,12 +15,32 @@ void log(const char * const message, const char * const color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void log_notice(const char * const message) {
|
void log_notice(const char * const message) {
|
||||||
log("", message);
|
log("", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void logf_notice(const char * const format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
char * msg;
|
||||||
|
vasprintf(&msg, format, args);
|
||||||
|
log_notice(msg);
|
||||||
|
free(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_error(const char * const message) {
|
void log_error(const char * const message) {
|
||||||
log("\033[33m", message);
|
log("\033[33m", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void logf_error(const char * const format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
char * msg;
|
||||||
|
vasprintf(&msg, format, args);
|
||||||
|
log_error(msg);
|
||||||
|
free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
#define LOG_H
|
#define LOG_H
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,12 +14,11 @@ typedef enum {
|
|||||||
ADA,
|
ADA,
|
||||||
} language_t;
|
} language_t;
|
||||||
|
|
||||||
language_t language = DEFAULT_LANGUAGE;
|
|
||||||
|
|
||||||
typedef void (*syntax_setter_t)(void);
|
typedef void (*syntax_setter_t)(void);
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "syntax.h"
|
#include "syntax.h"
|
||||||
|
#include "request.h"
|
||||||
#include "bot.h"
|
#include "bot.h"
|
||||||
|
|
||||||
syntax_setter_t syntax_functions[] = {
|
syntax_setter_t syntax_functions[] = {
|
||||||
@ -55,7 +54,7 @@ signed main(int argc, char * * argv) {
|
|||||||
|
|
||||||
log_file = LOG_FILE;
|
log_file = LOG_FILE;
|
||||||
|
|
||||||
syntax_functions[language]();
|
syntax_functions[DEFAULT_LANGUAGE]();
|
||||||
|
|
||||||
connect_bot(server, port_i);
|
connect_bot(server, port_i);
|
||||||
connection_loop();
|
connection_loop();
|
||||||
|
83
source/request.h
Normal file
83
source/request.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#ifndef REQUEST_H
|
||||||
|
#define REQUEST_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char * user;
|
||||||
|
language_t language;
|
||||||
|
struct itimerval timer;
|
||||||
|
char * buffer[128]; // XXX: no overflow detection/avertion
|
||||||
|
unsigned int buffer_head; // is implemented on this bunch
|
||||||
|
} request_t;
|
||||||
|
|
||||||
|
request_t request_queue__[message_queue_size];
|
||||||
|
request_t * request_queue[message_queue_size];
|
||||||
|
unsigned int request_queue_head = 0;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void init_request(request_t * request) {
|
||||||
|
request->timer.it_value.tv_sec = 0;
|
||||||
|
request->timer.it_value.tv_usec = 0;
|
||||||
|
request->timer.it_interval.tv_sec = 0;
|
||||||
|
request->timer.it_interval.tv_usec = 0;
|
||||||
|
request->language = DEFAULT_LANGUAGE;
|
||||||
|
request->buffer_head = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void reinit_request(request_t * request) {
|
||||||
|
free(request->user);
|
||||||
|
for (long i = 0; i < request->buffer_head; i++) {
|
||||||
|
free(request->buffer[i]);
|
||||||
|
}
|
||||||
|
init_request(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void touch_request_timer(request_t * const request) {
|
||||||
|
request->timer.it_value.tv_sec = message_timeout;
|
||||||
|
setitimer(ITIMER_REAL, &(request->timer), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
request_t * take_request(const char * const user) {
|
||||||
|
for (unsigned int i = 0; i < request_queue_head; i++) {
|
||||||
|
if(!strcmp(request_queue[i]->user, user)) {
|
||||||
|
return request_queue[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request_queue_head == message_queue_size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_t * request = request_queue[request_queue_head];
|
||||||
|
|
||||||
|
request->user = strdup(user);
|
||||||
|
|
||||||
|
++request_queue_head;
|
||||||
|
|
||||||
|
logf_notice("Took message: %p (%d)", (void*)request, request_queue_head);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drop_request(request_t * const request) {
|
||||||
|
setitimer(ITIMER_REAL, NULL, NULL);
|
||||||
|
|
||||||
|
reinit_request(request);
|
||||||
|
|
||||||
|
if (message_queue_size > 1) {
|
||||||
|
for (unsigned int i = 0; i < request_queue_head; i++) {
|
||||||
|
request_queue[i] = request_queue[i+1];
|
||||||
|
}
|
||||||
|
request_queue[request_queue_head] = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
--request_queue_head;
|
||||||
|
|
||||||
|
logf_notice("Dropped message: %p (%d)", (void*)request, request_queue_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -210,7 +210,8 @@ void syntax_cpp (void) {
|
|||||||
|
|
||||||
char * specials [] = {
|
char * specials [] = {
|
||||||
"int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t",
|
"int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t",
|
||||||
"FILE", "std", "typeof", "cout", "cin", "endl", "timespec", "tm"
|
"FILE", "std", "typeof", "cout", "cin", "endl", "timespec", "tm",
|
||||||
|
"vector", "stack", "map", "unordered_map", "queue", "deque",
|
||||||
/* TODO: I don't really care about this, but some people do, Anon please add what you find interesting in here... */
|
/* TODO: I don't really care about this, but some people do, Anon please add what you find interesting in here... */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user