new buffering strategy

This commit is contained in:
anon 2024-06-28 21:56:53 +02:00
parent 43d31d6b79
commit f06b358d0f
7 changed files with 160 additions and 131 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.gdb_history
*.o
*.out
hibot

View File

@ -6,7 +6,6 @@
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/time.h>
extern syntax_setter_t syntax_functions[];
@ -31,111 +30,30 @@ char * username_root(const char * const fullname){
return r;
}
typedef struct {
int is_active;
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;
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;
void on_request_timeout(int unused) {
(void)(unused);
drop_request(request_queue[0]);
}
request_t request_queue__[message_queue_size];
request_t * request_queue[message_queue_size];
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 */
void flush_request(request_t * request) {
// Message header
char * short_name = username_root(request->user);
irc_message(short_name);
free(short_name);
}
request_t * take_request(const char * const user, language_t language) {
for (unsigned int i = 0; i < request_queue_head; i++) {
if(!strcmp(request_queue[i]->user, user)) {
return request_queue[i];
}
}
// Message body
syntax_count = 0;
syntax_functions[request->language]();
for (unsigned i = 0; i < request->buffer_head; i++) {
irc_message(syntax_highlight(request->buffer[i]));
}
if (request_queue_head == message_queue_size) {
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 */
// Message footer
irc_message("--");
drop_reqest(request_queue);
logf_notice("Flushed message: %p (%d)", (void*)request, request_queue_head);
drop_request(request);
}
static
@ -165,6 +83,7 @@ void irc_help() {
irc_message(" !<language> // set language for next message");
irc_message(" <code> // echo this code");
irc_message(" !<language> <code> // set language and echo code");
irc_message(" !-- // flush all code");
irc_message("--");
}
@ -182,10 +101,7 @@ void event_connect(irc_session_t * session,
log_notice("IRC connection secured.");
irc_cmd_join(session, channel, 0);
char * buffer;
asprintf(&buffer, "Joined destination channel: `%s`.", channel);
log_notice(buffer);
free(buffer);
logf_notice("Joined destination channel: `%s`.", channel);
}
static
@ -194,6 +110,7 @@ void event_disconnect(irc_session_t * session,
const char * origin,
const char ** params,
unsigned int count) {
(void)session;
(void)event;
(void)origin;
(void)params;
@ -218,6 +135,11 @@ void event_privmsg(irc_session_t * session,
/* Is command */
if (*message == '!') {
if (!strcmp(message, "!help")) {
irc_help();
goto END;
}
/* */
terminator = message;
while (*terminator != ' ') {
if (*terminator == '\0') {
@ -227,38 +149,39 @@ void event_privmsg(irc_session_t * session,
++terminator;
}
*terminator = '\0';
/* */
if (!strcmp(message, "!help")) {
irc_help();
goto END;
}
/* get language */
for (char * s = message + 1; *s != '\0'; s++) {
*s = toupper(*s);
}
int l = translate_language(message + 1);
message = terminator + 1;
if (l != -1) {
language = l;
syntax_count = 0;
syntax_functions[language]();
}
/* */
{
request_t * request = take_request(origin);
if (!strcmp(message, "!--")) {
if (request) {
flush_request(request);
}
goto END;
}
/* get language */
for (char * s = message + 1; *s != '\0'; s++) {
*s = toupper(*s);
}
int l = translate_language(message + 1);
message = terminator + 1;
if (l != -1) {
request->language = l;
}
}
}
/* Is code */
if (is_code) {
request_t * request = take_request(origin, language);
request_t * request = take_request(origin);
if (!request) {
irc_private_message(origin, message_queue_full_message);
goto END;
}
if (request->is_active) {
touch_request_timer(request);
irc_message(syntax_highlight(message));
} else {
request->buffer[request->buffer_head++] = strdup(syntax_highlight(message));
}
touch_request_timer(request);
request->buffer[request->buffer_head++] = strdup(message);
}
END:
@ -302,7 +225,7 @@ int connect_bot(const char * const server, const short port) {
request_queue[i] = &request_queue__[i];
init_request(request_queue[i]);
}
signal(SIGALRM, on_message_timeout);
signal(SIGALRM, on_request_timeout);
irc_connect(session,
server,

View File

@ -2,7 +2,7 @@
const char * const username = PROGRAM_NAME;
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.";
#define message_queue_size 3
#define DEFAULT_LANGUAGE C

View File

@ -1,6 +1,8 @@
#ifndef LOG_H
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
FILE * log_file;
@ -13,12 +15,32 @@ void log(const char * const message, const char * const color) {
}
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) {
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
#endif

View File

@ -14,12 +14,11 @@ typedef enum {
ADA,
} language_t;
language_t language = DEFAULT_LANGUAGE;
typedef void (*syntax_setter_t)(void);
#include "log.h"
#include "syntax.h"
#include "request.h"
#include "bot.h"
syntax_setter_t syntax_functions[] = {
@ -55,7 +54,7 @@ signed main(int argc, char * * argv) {
log_file = LOG_FILE;
syntax_functions[language]();
syntax_functions[DEFAULT_LANGUAGE]();
connect_bot(server, port_i);
connection_loop();

83
source/request.h Normal file
View 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

View File

@ -210,7 +210,8 @@ void syntax_cpp (void) {
char * specials [] = {
"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... */
};