Refactor some code and more splitting

This commit is contained in:
Alex D. 2021-01-19 20:35:23 +00:00
parent 14664963e7
commit b5e46c5635
Signed by: caskd
GPG Key ID: F92BA85F61F4C173
7 changed files with 147 additions and 76 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
project(
uIRCd
VERSION 2021.01.12
VERSION 2021.01.19
DESCRIPTION "High performance IRC daemon based on uIRC"
LANGUAGES C
)
@ -22,6 +22,7 @@ add_executable(uircd
src/logging.c
src/main.c
src/memory.c
src/misc.c
src/signal.c
src/channels.c
)

View File

@ -20,6 +20,7 @@
#include "logging.h"
#include <assert.h> // assert()
#include <errno.h> // errno
#include <stdio.h> // fprintf()
#include <string.h> // strerror()
@ -28,67 +29,78 @@
#include <unistd.h> // write()
ssize_t
get_buffer_line(char* buf)
read_buffer(Buffer_Info* binfo)
{
if (buf == NULL) return -1;
char* ppoi;
if ((ppoi = strchr(buf, '\n')) != NULL) {
*ppoi = '\0';
if (ppoi > buf && *(ppoi - 1) == '\r') *(ppoi - 1) = '\0';
return ++ppoi - buf;
assert(binfo != NULL);
ssize_t brd;
if ((brd = read(binfo->fd, binfo->buffer + binfo->data_size, binfo->buf_size - binfo->data_size - 1)) > 0) {
*(binfo->buffer + (binfo->data_size += (size_t) brd)) = '\0';
LOG(LOG_DEBUG, "Read %li bytes from socket buffer and currently at position %li", brd, binfo->data_size);
} else if (brd == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) return 0;
LOG(LOG_WARNING, "Failed to read inbound traffic on fd %i: " ERRNOFMT, binfo->fd, strerror(errno), errno);
}
return 0;
return brd;
}
ssize_t
flush_buffer(char* buf, size_t buflen, int fd)
write_buffer(Buffer_Info* binfo)
{
assert(binfo != NULL);
ssize_t res;
char* pos = buf;
size_t pos = 0;
for (;;) {
if ((size_t)(res = write(fd, pos, buflen - (size_t)(pos - buf))) != buflen - (size_t)(pos - buf)) {
size_t left = binfo->data_size - pos;
if ((size_t)(res = write(binfo->fd, binfo->buffer + pos, left)) != left) {
if (res == -1 && errno != EINTR) {
LOG(LOG_WARNING, "Couldn't flush buffer to fd %i: " ERRNOFMT, fd, strerror(errno), errno);
LOG(LOG_WARNING, "Couldn't flush buffer to fd %i: " ERRNOFMT, binfo->fd, strerror(errno), errno);
return -1;
}
pos += res;
LOG(LOG_DEBUG, "Wrote %lu bytes to fd %i", res, fd);
LOG(LOG_DEBUG, "Wrote %lu bytes to fd %i", res, binfo->fd);
} else
return res;
}
}
ssize_t
read_buffer(Buffer_Info* buf)
/*!
* Move a string to the begging of a buffer from offset
*
* This function moves string in a buffer to the begging in chunks.
* Chunks are either offset sized or b_left sized depending if the offset is bigger than how much is left.
* This is done because strcpy may be optimized and copy order is not defined, so destination might overwrite source on a rtl copy
*/
size_t
buffer_offset_move(Buffer_Info* binfo, size_t offset)
{
ssize_t brd;
if ((brd = read(buf->fd, buf->buffer + buf->append_pos, buf->csize - buf->append_pos - 1)) > 0) {
*(buf->buffer + (buf->append_pos += (size_t) brd)) = '\0';
LOG(LOG_DEBUG, "Read %li bytes from socket buffer and currently at position %li", brd, buf->append_pos, buf->buffer);
} else if (brd == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) return 0;
LOG(LOG_WARNING, "Failed to read inbound traffic on fd %i: " ERRNOFMT, buf->fd, strerror(errno), errno);
}
return brd;
assert(binfo != NULL);
size_t pos = 0;
do {
char* dest = binfo->buffer + pos;
size_t b_left = binfo->data_size - pos - offset;
strncpy(dest, dest + offset, (b_left < offset) ? b_left : offset);
LOG(LOG_DEBUG, "Moved %lu bytes from %lu to %lu", (b_left < offset) ? b_left : offset, offset + pos, pos);
pos += offset;
} while (offset + pos < binfo->data_size);
binfo->data_size -= offset;
return binfo->data_size;
}
int
reset_buffer(Buffer_Info* buf, short clr_fd)
reset_buffer(Buffer_Info* binfo, short clr_fd)
{
if (clr_fd) {
if (clr_fd == 2) close(buf->fd);
buf->fd = -1;
if (clr_fd == 2) close(binfo->fd);
binfo->fd = -1;
}
#ifdef UIRCD_RELAXED_RFC
free(buf->buffer);
buf->buffer = NULL;
buf->csize = 0;
if (binfo->buffer != NULL) free(binfo->buffer);
binfo->buffer = NULL;
binfo->buf_size = 0;
#else /* UIRCD_RELAXED_RFC */
*buf->buffer = '\0';
buf->csize = UIRCD_LIMITS_LINE + 1;
*binfo->buffer = '\0';
binfo->buf_size = UIRCD_LIMITS_LINE + 1;
#endif /* UIRCD_RELAXED_RFC */
buf->append_pos = 0;
binfo->data_size = 0;
return 1;
}
// TODO: Buffer allocators and resizers

View File

@ -32,13 +32,13 @@ typedef struct {
buffer[UIRCD_LIMITS_LINE + 1]
#endif /* UIRCD_RELAXED_RFC */
;
size_t append_pos, csize;
size_t data_size, buf_size;
int fd;
} Buffer_Info;
ssize_t get_buffer_line(char* buf);
ssize_t flush_buffer(char* buf, size_t buflen, int fd);
ssize_t read_buffer(Buffer_Info* buf);
int reset_buffer(Buffer_Info* buf, short clr_fd);
ssize_t read_buffer(Buffer_Info* binfo);
ssize_t write_buffer(Buffer_Info* binfo);
size_t buffer_offset_move(Buffer_Info* binfo, size_t offset);
int reset_buffer(Buffer_Info* binfo, short clr_fd);
#endif /* UIRCD_GUARD_BUFFER */

View File

@ -138,8 +138,8 @@ auto_msg_actions(IRC_Message* mesg, Connection* conn, Buffer_Info* buf)
switch (mesg->cmd) {
case (PING): {
LOG(LOG_DEBUG, "Auto-replying to ping \"%s\"", mesg->args[0]);
if ((len = Assm_mesg(buf->buffer, Assm_cmd_PONG(mesg->args[0], NULL), buf->csize)) > 0)
if (flush_buffer(buf->buffer, (size_t) len, buf->fd) == -1) {
if ((buf->data_size = Assm_mesg(buf->buffer, Assm_cmd_PONG(mesg->args[0], NULL), buf->buf_size)) > 0)
if (write_buffer(buf) == -1) {
LOG(LOG_WARNING, "Couldn't pong " ADDRFMT ". " ERRNOFMT, conn->data.address, conn->data.service, strerror(errno), errno);
conn->info.state = CONN_RECONNECTING;
return 0;
@ -225,8 +225,8 @@ commit_channelist(Buffer_Info* buf, Connection* conn)
signed long len;
for (unsigned int i = 0; conn->info.channels != NULL && conn->info.channels[i].name != NULL; i++) {
IRC_Message msg = { .args = { conn->info.channels[i].name, conn->info.channels[i].key, NULL }, .trailing = true, .cmd = (conn->info.channels[i].joined) ? JOIN : PART };
if ((len = Assm_mesg(buf->buffer, &msg, buf->csize)) > 0) {
if (flush_buffer(buf->buffer, (size_t) len, buf->fd) == -1) {
if ((buf->data_size = Assm_mesg(buf->buffer, &msg, buf->buf_size)) > 0) {
if (write_buffer(buf) == -1) {
LOG(LOG_WARNING,
"Couldn't auto-join channels \"%s\" " ADDRFMT ". " ERRNOFMT,
conn->info.channels[i].name,
@ -245,12 +245,11 @@ commit_channelist(Buffer_Info* buf, Connection* conn)
int
register_user(Connection* conn, Buffer_Info* buf)
{
signed long temp;
/* Registration process and CAP negotiation (TODO)
if ((temp = Assm_mesg(buf.send[0].buffer, Assm_cmd_CAP_LS("302"), sizeof(buf.send[0].buffer))) > 0) {
buf.send[0].append_pos = (size_t) temp;
buf.send[0].data_size = (size_t) temp;
LOG(LOG_INFO, "Sending a CAP LS to " ADDRFMT ".", connection.data.address, connection.data.service);
if (flush_buffer(buf.send[0].buffer, buf.send[0].append_pos, buf.send[0].fd) == -1) {
if (flush_buffer(buf.send[0].buffer, buf.send[0].data_size, buf.send[0].fd) == -1) {
LOG(LOG_WARNING,
"Couldn't send CAP LS to " ADDRFMT ". " ERRNOFMT,
connection.data.address,
@ -262,27 +261,24 @@ register_user(Connection* conn, Buffer_Info* buf)
}
}
*/
if (conn->user.password != NULL && (temp = Assm_mesg(buf->buffer, Assm_cmd_PASS(conn->user.password), buf->csize)) > 0) {
buf->append_pos = (size_t) temp;
if (flush_buffer(buf->buffer, buf->append_pos, buf->fd) != -1) {
if (conn->user.password != NULL && (buf->data_size = Assm_mesg(buf->buffer, Assm_cmd_PASS(conn->user.password), buf->buf_size)) > 0) {
if (write_buffer(buf) != -1) {
LOG(LOG_INFO, "Sent PASS authentication to " ADDRFMT, conn->data.address, conn->data.service);
} else {
conn->info.state = CONN_RECONNECTING;
return 0;
}
}
if ((temp = Assm_mesg(buf->buffer, Assm_cmd_NICK(conn->user.nickname), buf->csize)) > 0) {
buf->append_pos = (size_t) temp;
if (flush_buffer(buf->buffer, buf->append_pos, buf->fd) != -1) {
if ((buf->data_size = Assm_mesg(buf->buffer, Assm_cmd_NICK(conn->user.nickname), buf->buf_size)) > 0) {
if (write_buffer(buf) != -1) {
LOG(LOG_INFO, "Sent NICK registration to " ADDRFMT " with nickname \"%s\".", conn->data.address, conn->data.service, conn->user.nickname);
} else {
conn->info.state = CONN_RECONNECTING;
return 0;
}
}
if ((temp = Assm_mesg(buf->buffer, Assm_cmd_USER(conn->user.username, conn->user.realname, 0), buf->csize)) > 0) {
buf->append_pos = (size_t) temp;
if (flush_buffer(buf->buffer, buf->append_pos, buf->fd) != -1) {
if ((buf->data_size = Assm_mesg(buf->buffer, Assm_cmd_USER(conn->user.username, conn->user.realname, 0), buf->buf_size)) > 0) {
if (write_buffer(buf) != -1) {
LOG(LOG_INFO,
"Sent USER registration to " ADDRFMT " with username \"%s\" and realname \"%s\".",
conn->data.address,

View File

@ -24,6 +24,7 @@
#include "filesystem.h"
#include "logging.h"
#include "memory.h"
#include "misc.h"
#include "signal.h"
#include <errno.h> // errno
@ -179,10 +180,8 @@ main(int argc, char* argv[])
LOG(LOG_INFO, "Exiting gracefully");
return EXIT_SUCCESS;
} else if (!run || connection.info.state == CONN_CLOSING) {
signed long temp;
if ((temp = Assm_mesg(buf.send[0].buffer, Assm_cmd_QUIT(connection.data.quitmsg), buf.send[0].csize)) > 0) {
buf.send[0].append_pos = (unsigned long) temp;
if (flush_buffer(buf.send[0].buffer, buf.send[0].append_pos, buf.send[0].fd) != -1)
if ((buf.send[0].data_size = Assm_mesg(buf.send[0].buffer, Assm_cmd_QUIT(connection.data.quitmsg), buf.send[0].buf_size)) > 0) {
if (write_buffer(&buf.send[0]) != -1)
LOG(LOG_INFO, "Sent a QUIT message to " ADDRFMT " containing \"%s\"", connection.data.address, connection.data.service, connection.data.quitmsg);
}
reset_buffer(&buf.recv[0], 2); // net rw/FIFO read fd
@ -240,12 +239,11 @@ main(int argc, char* argv[])
}
memset((void*) &buffer, '\0', sizeof(IRC_Message));
if ((len = get_buffer_line(buf.recv[1].buffer)) > 0) {
if ((len = tok_irc_line(buf.recv[1].buffer)) > 0) {
LOG(LOG_DEBUG, "Got IRC message: %s", buf.recv[1].buffer);
if (Tok_mesg(buf.recv[1].buffer, &buffer) == 1) {
signed long temp;
if ((temp = Assm_mesg(buf.send[1].buffer, &buffer, buf.send[1].csize)) > 0) {
if (flush_buffer(buf.send[1].buffer, (size_t) temp, buf.send[1].fd) == -1) {
if ((buf.send[1].data_size = Assm_mesg(buf.send[1].buffer, &buffer, buf.send[1].buf_size)) > 0) {
if (write_buffer(&buf.send[1]) == -1) {
connection.info.state = CONN_RECONNECTING;
continue;
}
@ -253,10 +251,8 @@ main(int argc, char* argv[])
} else
LOG(LOG_WARNING, "Received invalid IRC message on FIFO (see RFC2812)");
for (long unsigned int x = 0; x < buf.recv[1].csize && *(buf.recv[1].buffer + len + x); x++) *(buf.recv[1].buffer + x) = *(buf.recv[1].buffer + x + len);
buf.recv[1].append_pos -= (unsigned long) len;
*(buf.recv[1].buffer + buf.recv[1].append_pos) = '\0';
} else if (buf.recv[1].append_pos == buf.recv[1].csize - 1) {
buffer_offset_move(&buf.recv[1], len);
} else if (buf.recv[1].data_size == buf.recv[1].buf_size - 1) {
#ifdef UIRCD_RELAXED_RFC
// TODO: Add resize here
#else /* UIRCD_RELAXED_RFC */
@ -281,7 +277,7 @@ main(int argc, char* argv[])
}
memset((void*) &buffer, '\0', sizeof(IRC_Message));
if ((len = get_buffer_line(buf.recv[0].buffer)) > 0) {
if ((len = tok_irc_line(buf.recv[0].buffer)) > 0) {
LOG(LOG_DEBUG, "Got IRC message on recvbuffer: %s", buf.recv[0].buffer);
if (Tok_mesg(buf.recv[0].buffer, &buffer) == 1) {
connection.info.l_message = ctime;
@ -293,7 +289,7 @@ main(int argc, char* argv[])
}
char logpath[UIRCD_LIMITS_PATH];
if (Assm_mesg(buf.log.buffer, &buffer, buf.log.csize) > 0) {
if ((buf.log.data_size = Assm_mesg(buf.log.buffer, &buffer, buf.log.buf_size)) > 0) {
printf("%s", buf.log.buffer);
bool match[][3] = { { false, false, false }, { true, false, false }, { true, false, true } };
for (unsigned long i = 0; i < sizeof(match) / sizeof(*match); i++) {
@ -305,15 +301,13 @@ main(int argc, char* argv[])
if (!auto_msg_actions(&buffer, &connection, &buf.send[0])) continue;
for (long unsigned int x = 0; x < buf.recv[0].csize && *(buf.recv[0].buffer + len + x); x++) *(buf.recv[0].buffer + x) = *(buf.recv[0].buffer + x + len);
buf.recv[0].append_pos -= (unsigned long) len;
*(buf.recv[0].buffer + buf.recv[0].append_pos) = '\0';
connection.info.state = CONN_ACTIVE;
buffer_offset_move(&buf.recv[0], len);
connection.info.state = CONN_ACTIVE;
} else
LOG(LOG_WARNING, "Received invalid IRC message (see RFC2812).");
} else if (len == -1) {
connection.info.state = CONN_RECONNECTING;
} else if (buf.recv[0].append_pos == buf.recv[0].csize - 1) {
} else if (buf.recv[0].data_size == buf.recv[0].buf_size - 1) {
#ifdef UIRCD_RELAXED_RFC
// TODO: Add resize here
#else /* UIRCD_RELAXED_RFC */

42
src/misc.c Normal file
View File

@ -0,0 +1,42 @@
/*
* This file is part of uIRCd. (https://git.redxen.eu/caskd/uIRCd)
* Copyright (c) 2019, 2020 Alex-David Denes
*
* uIRCd is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* uIRCd is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
*/
#include "misc.h"
#include "buffer.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#define UIRC_IRCV3
#define UIRC_HELPERS
#include <uirc/uirc.h>
ssize_t
tok_irc_line(char* buf)
{
assert(buf != NULL);
char* ppoi;
if ((ppoi = strchr(buf, '\n')) != NULL) {
*ppoi = '\0';
if (ppoi > buf && *(ppoi - 1) == '\r') *(ppoi - 1) = '\0';
return ++ppoi - buf;
}
return 0;
}

26
src/misc.h Normal file
View File

@ -0,0 +1,26 @@
/*
* This file is part of uIRCd. (https://git.redxen.eu/caskd/uIRCd)
* Copyright (c) 2019, 2020 Alex-David Denes
*
* uIRCd is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* uIRCd is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sys/types.h> // ssize_t
#ifndef UIRCD_GUARD_MISC
#define UIRCD_GUARD_MISC
ssize_t tok_irc_line(char* buf);
#endif /* UIRCD_GUARD_MISC */