Refactor some code and more splitting
This commit is contained in:
parent
14664963e7
commit
b5e46c5635
|
@ -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
|
||||
)
|
||||
|
|
82
src/buffer.c
82
src/buffer.c
|
@ -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
|
||||
|
|
10
src/buffer.h
10
src/buffer.h
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
32
src/main.c
32
src/main.c
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
Reference in New Issue