Rewrite a big chunk of the code, split the code into functions and clean it up, fix undefined behaviours and more
This commit is contained in:
parent
f0bfff775d
commit
a4d1e501eb
@ -7,7 +7,7 @@ IndentWidth: 8
|
|||||||
UseTab: ForIndentation
|
UseTab: ForIndentation
|
||||||
AllowShortBlocksOnASingleLine: true
|
AllowShortBlocksOnASingleLine: true
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
AllowShortFunctionsOnASingleLine: All
|
AllowShortFunctionsOnASingleLine: true
|
||||||
AllowShortIfStatementsOnASingleLine: true
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
AllowShortLoopsOnASingleLine: true
|
AllowShortLoopsOnASingleLine: true
|
||||||
BreakBeforeBinaryOperators: NonAssignment
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
180
.clang-tidy
Normal file
180
.clang-tidy
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
---
|
||||||
|
Checks: 'clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,-*,clang-analyzer-core.*,clang-analyzer-optin.performance.*,clang-analyzer-optin.portability.*,clang-analyzer-nullability.*,clang-analyzer-security.*,clang-analyzer-unix.*,bugprone-*,misc-*,performance-*,readability-*,-*,clang-analyzer-core.*,clang-analyzer-optin.performance.*,clang-analyzer-optin.portability.*,clang-analyzer-nullability.*,clang-analyzer-security.*,clang-analyzer-unix.*,bugprone-*,misc-*,performance-*,readability-*,-readability-isolate-declaration,-readability-else-after-return,-readability-braces-around-statements,-*,clang-analyzer-core.*,clang-analyzer-optin.performance.*,clang-analyzer-optin.portability.*,clang-analyzer-nullability.*,clang-analyzer-security.*,clang-analyzer-unix.*,bugprone-*,misc-*,performance-*,readability-*,-readability-isolate-declaration,-readability-else-after-return,-readability-braces-around-statements,-readability-magic-numbers'
|
||||||
|
WarningsAsErrors: ''
|
||||||
|
HeaderFilterRegex: ''
|
||||||
|
AnalyzeTemporaryDtors: false
|
||||||
|
FormatStyle: none
|
||||||
|
User: caskd
|
||||||
|
CheckOptions:
|
||||||
|
- key: bugprone-argument-comment.CommentBoolLiterals
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.CommentCharacterLiterals
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.CommentFloatLiterals
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.CommentIntegerLiterals
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.CommentNullPtrs
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.CommentStringLiterals
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.CommentUserDefinedLiterals
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.IgnoreSingleArgument
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-argument-comment.StrictMode
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-assert-side-effect.AssertMacros
|
||||||
|
value: assert
|
||||||
|
- key: bugprone-assert-side-effect.CheckFunctionCalls
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-dangling-handle.HandleClasses
|
||||||
|
value: 'std::basic_string_view;std::experimental::basic_string_view'
|
||||||
|
- key: bugprone-dynamic-static-initializers.HeaderFileExtensions
|
||||||
|
value: ',h,hh,hpp,hxx'
|
||||||
|
- key: bugprone-exception-escape.FunctionsThatShouldNotThrow
|
||||||
|
value: ''
|
||||||
|
- key: bugprone-exception-escape.IgnoredExceptions
|
||||||
|
value: ''
|
||||||
|
- key: bugprone-misplaced-widening-cast.CheckImplicitCasts
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-not-null-terminated-result.WantToUseSafeFunctions
|
||||||
|
value: '1'
|
||||||
|
- key: bugprone-signed-char-misuse.CharTypdefsToIgnore
|
||||||
|
value: ''
|
||||||
|
- key: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant
|
||||||
|
value: '1'
|
||||||
|
- key: bugprone-sizeof-expression.WarnOnSizeOfConstant
|
||||||
|
value: '1'
|
||||||
|
- key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-sizeof-expression.WarnOnSizeOfThis
|
||||||
|
value: '1'
|
||||||
|
- key: bugprone-string-constructor.LargeLengthThreshold
|
||||||
|
value: '8388608'
|
||||||
|
- key: bugprone-string-constructor.WarnOnLargeLength
|
||||||
|
value: '1'
|
||||||
|
- key: bugprone-suspicious-enum-usage.StrictMode
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-suspicious-missing-comma.MaxConcatenatedTokens
|
||||||
|
value: '5'
|
||||||
|
- key: bugprone-suspicious-missing-comma.RatioThreshold
|
||||||
|
value: '0.200000'
|
||||||
|
- key: bugprone-suspicious-missing-comma.SizeThreshold
|
||||||
|
value: '5'
|
||||||
|
- key: bugprone-suspicious-string-compare.StringCompareLikeFunctions
|
||||||
|
value: ''
|
||||||
|
- key: bugprone-suspicious-string-compare.WarnOnImplicitComparison
|
||||||
|
value: '1'
|
||||||
|
- key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison
|
||||||
|
value: '0'
|
||||||
|
- key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit
|
||||||
|
value: '16'
|
||||||
|
- key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField
|
||||||
|
value: '1'
|
||||||
|
- key: bugprone-unused-return-value.CheckedFunctions
|
||||||
|
value: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty'
|
||||||
|
- key: cert-dcl16-c.NewSuffixes
|
||||||
|
value: 'L;LL;LU;LLU'
|
||||||
|
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
|
||||||
|
value: '0'
|
||||||
|
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
|
||||||
|
value: '1'
|
||||||
|
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
|
||||||
|
value: '1'
|
||||||
|
- key: google-readability-braces-around-statements.ShortStatementLines
|
||||||
|
value: '1'
|
||||||
|
- key: google-readability-function-size.StatementThreshold
|
||||||
|
value: '800'
|
||||||
|
- key: google-readability-namespace-comments.ShortNamespaceLines
|
||||||
|
value: '10'
|
||||||
|
- key: google-readability-namespace-comments.SpacesBeforeComments
|
||||||
|
value: '2'
|
||||||
|
- key: misc-definitions-in-headers.HeaderFileExtensions
|
||||||
|
value: ',h,hh,hpp,hxx'
|
||||||
|
- key: misc-definitions-in-headers.UseHeaderFileExtension
|
||||||
|
value: '1'
|
||||||
|
- key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries
|
||||||
|
value: '1'
|
||||||
|
- key: misc-unused-parameters.StrictMode
|
||||||
|
value: '0'
|
||||||
|
- key: modernize-loop-convert.MaxCopySize
|
||||||
|
value: '16'
|
||||||
|
- key: modernize-loop-convert.MinConfidence
|
||||||
|
value: reasonable
|
||||||
|
- key: modernize-loop-convert.NamingStyle
|
||||||
|
value: CamelCase
|
||||||
|
- key: modernize-pass-by-value.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: modernize-use-nullptr.NullMacros
|
||||||
|
value: 'NULL'
|
||||||
|
- key: performance-faster-string-find.StringLikeClasses
|
||||||
|
value: 'std::basic_string'
|
||||||
|
- key: performance-for-range-copy.AllowedTypes
|
||||||
|
value: ''
|
||||||
|
- key: performance-for-range-copy.WarnOnAllAutoCopies
|
||||||
|
value: '0'
|
||||||
|
- key: performance-inefficient-string-concatenation.StrictMode
|
||||||
|
value: '0'
|
||||||
|
- key: performance-inefficient-vector-operation.EnableProto
|
||||||
|
value: '0'
|
||||||
|
- key: performance-inefficient-vector-operation.VectorLikeClasses
|
||||||
|
value: '::std::vector'
|
||||||
|
- key: performance-move-const-arg.CheckTriviallyCopyableMove
|
||||||
|
value: '1'
|
||||||
|
- key: performance-move-constructor-init.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: performance-no-automatic-move.AllowedTypes
|
||||||
|
value: ''
|
||||||
|
- key: performance-type-promotion-in-math-fn.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: performance-unnecessary-copy-initialization.AllowedTypes
|
||||||
|
value: ''
|
||||||
|
- key: performance-unnecessary-value-param.AllowedTypes
|
||||||
|
value: ''
|
||||||
|
- key: performance-unnecessary-value-param.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: readability-function-size.BranchThreshold
|
||||||
|
value: '4294967295'
|
||||||
|
- key: readability-function-size.LineThreshold
|
||||||
|
value: '4294967295'
|
||||||
|
- key: readability-function-size.NestingThreshold
|
||||||
|
value: '4294967295'
|
||||||
|
- key: readability-function-size.ParameterThreshold
|
||||||
|
value: '4294967295'
|
||||||
|
- key: readability-function-size.StatementThreshold
|
||||||
|
value: '800'
|
||||||
|
- key: readability-function-size.VariableThreshold
|
||||||
|
value: '4294967295'
|
||||||
|
- key: readability-identifier-naming.IgnoreFailedSplit
|
||||||
|
value: '0'
|
||||||
|
- key: readability-implicit-bool-conversion.AllowIntegerConditions
|
||||||
|
value: '0'
|
||||||
|
- key: readability-implicit-bool-conversion.AllowPointerConditions
|
||||||
|
value: '0'
|
||||||
|
- key: readability-inconsistent-declaration-parameter-name.IgnoreMacros
|
||||||
|
value: '1'
|
||||||
|
- key: readability-inconsistent-declaration-parameter-name.Strict
|
||||||
|
value: '0'
|
||||||
|
- key: readability-redundant-member-init.IgnoreBaseInCopyConstructors
|
||||||
|
value: '0'
|
||||||
|
- key: readability-redundant-smartptr-get.IgnoreMacros
|
||||||
|
value: '1'
|
||||||
|
- key: readability-redundant-string-init.StringNames
|
||||||
|
value: '::std::basic_string'
|
||||||
|
- key: readability-simplify-boolean-expr.ChainedConditionalAssignment
|
||||||
|
value: '0'
|
||||||
|
- key: readability-simplify-boolean-expr.ChainedConditionalReturn
|
||||||
|
value: '0'
|
||||||
|
- key: readability-simplify-subscript-expr.Types
|
||||||
|
value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array'
|
||||||
|
- key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold
|
||||||
|
value: '3'
|
||||||
|
- key: readability-uppercase-literal-suffix.IgnoreMacros
|
||||||
|
value: '1'
|
||||||
|
- key: readability-uppercase-literal-suffix.NewSuffixes
|
||||||
|
value: ''
|
||||||
|
...
|
||||||
|
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,6 +1,3 @@
|
|||||||
build/
|
build/
|
||||||
CMakeFiles/
|
.clangd/
|
||||||
CMakeCache.txt
|
compile_commands.json
|
||||||
cmake_install.cmake
|
|
||||||
Makefile
|
|
||||||
.swp
|
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(microircd LANGUAGES C)
|
project(microircd LANGUAGES C)
|
||||||
|
|
||||||
set(COMPILE_OPTIONS "-Wall -Wextra -pedantic -Wformat-overflow=2 -Wformat-security -Winit-self -Wstrict-overflow=2 -Wstringop-overflow=2 -Walloc-zero -Wduplicated-branches -Wduplicated-cond -Wtrampolines -Wfloat-equal -Wshadow -Wunsafe-loop-optimizations -Wparentheses -fanalyzer -fstack-protector")
|
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||||
|
add_compile_options(-Wall -Wextra -Wformat-overflow=2 -Wformat-security -Winit-self -Wstrict-overflow=2 -Wstringop-overflow=2 -Walloc-zero -Wduplicated-branches -Wduplicated-cond -Wtrampolines -Wfloat-equal -Wshadow -Wunsafe-loop-optimizations -Wparentheses -pedantic -fanalyzer -fstack-check)
|
||||||
|
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
|
add_compile_options(-Weverything -pedantic -Wno-padded -Wno-disabled-macro-expansion)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE Debug)
|
set(CMAKE_BUILD_TYPE Debug)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE EQUAL "Debug")
|
if (CMAKE_BUILD_TYPE EQUAL "Debug")
|
||||||
set(COMPILE_OPTIONS "${COMPILE_OPTIONS} -Og")
|
set(COMPILE_OPTIONS "${COMPILE_OPTIONS} -Og")
|
||||||
elseif (CMAKE_BUILD_TYPE EQUAL "Release")
|
elseif (CMAKE_BUILD_TYPE EQUAL "Release")
|
||||||
|
19
src/.clang-format
Normal file
19
src/.clang-format
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
Standard: Cpp11
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
TabWidth: 8
|
||||||
|
IndentWidth: 8
|
||||||
|
UseTab: ForIndentation
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
BreakBeforeBraces: Linux
|
||||||
|
IndentCaseLabels: true
|
||||||
|
PointerAlignment: Left
|
||||||
|
ColumnLimit: 0
|
||||||
|
...
|
||||||
|
|
175
src/filesystem.c
175
src/filesystem.c
@ -14,49 +14,64 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
|
|
||||||
int assemble_path(char** path, char* out, int len)
|
int mkdir_bottomup(char* path)
|
||||||
{
|
{
|
||||||
if (path == NULL || *path == NULL || len <= 0)
|
if (path == NULL || *path == '\0')
|
||||||
return 0;
|
return 0;
|
||||||
char* orig = out;
|
for (char* x = path; x != NULL && *x;) {
|
||||||
int cprint;
|
if ((x = strchr(x, '/')) != NULL) {
|
||||||
for (char** i = path; i != NULL && *i != NULL && out - orig < len; i++) {
|
char save = *(x + 1);
|
||||||
if (i != path && len - (out - orig) > 0)
|
*(x + 1) = '\0';
|
||||||
*(out++) = '/';
|
if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0 && errno != EEXIST) {
|
||||||
if ((cprint = snprintf(out, len - (out - orig), "%s", *i)) > 0)
|
*(x + 1) = save;
|
||||||
out += cprint;
|
LOG(LOG_ERROR, "Could not create directory \"%s\".", path);
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int mkdir_bottomup(char** dir)
|
|
||||||
{
|
|
||||||
if (dir == NULL || *dir == NULL)
|
|
||||||
return -1;
|
|
||||||
int cprint;
|
|
||||||
char buf[PATH_MAX], *bufp = buf;
|
|
||||||
for (char** i = dir; i != NULL && *i != NULL && bufp - buf < sizeof(buf); i++) {
|
|
||||||
if (i != dir && sizeof(buf) - (bufp - buf) > 0)
|
|
||||||
*(bufp++) = '/';
|
|
||||||
if ((cprint = snprintf(bufp, sizeof(buf) - (bufp - buf), "%s", *i)) > 0) {
|
|
||||||
if (mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0 && errno != EEXIST) {
|
|
||||||
LOG(LOG_ERROR, "Could not create directory \"%s\".", buf);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bufp += cprint;
|
*(x + 1) = save;
|
||||||
} else {
|
x++;
|
||||||
LOG(LOG_ERROR, "Path limit reached!");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOG(LOG_DEBUG, "Created directory at: %s", path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int cleanup_path_names(char* name)
|
|
||||||
|
int makeinput(char* path)
|
||||||
|
{
|
||||||
|
if (path == NULL)
|
||||||
|
return -1;
|
||||||
|
int tmp;
|
||||||
|
if ((tmp = mkfifo(path, S_IRUSR | S_IWUSR | S_IWGRP)) == 0) {
|
||||||
|
LOG(LOG_VERBOSE, "Created a FIFO pipe for input at %s.", path);
|
||||||
|
} else if (errno != EEXIST) {
|
||||||
|
LOG(LOG_WARN, "Couldn't create FIFO at \"%s\" for input. " ERRNOFMT, path, strerror(errno), errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int fd;
|
||||||
|
if ((fd = open(path, O_RDONLY | O_NONBLOCK)) != -1) {
|
||||||
|
LOG(LOG_DEBUG, "Opened \"%s\" for reading.", path);
|
||||||
|
return fd;
|
||||||
|
} else
|
||||||
|
LOG(LOG_WARN, "Couldn't open FIFO pipe \"%s\" for reading. " ERRNOFMT, path, strerror(errno), errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool write_log(char* path, char* message)
|
||||||
|
{
|
||||||
|
FILE* logfile;
|
||||||
|
if ((logfile = fopen(path, "a")) != NULL) {
|
||||||
|
fprintf(logfile, "%s", message);
|
||||||
|
fclose(logfile);
|
||||||
|
return 1;
|
||||||
|
} else
|
||||||
|
LOG(LOG_WARN, "Couldn't open file \"%s\" for appending.", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cleanup_path_names(char* name)
|
||||||
{
|
{
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@ -64,9 +79,103 @@ int cleanup_path_names(char* name)
|
|||||||
*name = '_';
|
*name = '_';
|
||||||
for (; *name; name++) {
|
for (; *name; name++) {
|
||||||
if (isalpha(*name))
|
if (isalpha(*name))
|
||||||
*name = tolower(*name);
|
*name = (char)tolower(*name);
|
||||||
else if (strchr(".+-_#&", *name) == NULL && !isdigit(*name))
|
else if (strchr(".+-_#&", *name) == NULL && !isdigit(*name))
|
||||||
*name = '_';
|
*name = '_';
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool add_socket_flags(int fd, int flags)
|
||||||
|
{
|
||||||
|
int cflgs;
|
||||||
|
if ((cflgs = fcntl(fd, F_GETFL)) != -1) {
|
||||||
|
if (fcntl(fd, F_SETFL, cflgs | flags) == -1) {
|
||||||
|
LOG(LOG_WARN, "Couldn't add socket flags. " ERRNOFMT, strerror(errno), errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG(LOG_WARN, "Failed to get socket flags. " ERRNOFMT, strerror(errno), errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t set_path_elem(char* content, unsigned int nth_elem, bool isdir, PathBuf* buf)
|
||||||
|
{
|
||||||
|
if (buf == NULL || buf->elements[nth_elem].bufpos == NULL)
|
||||||
|
return -1;
|
||||||
|
size_t totallen = 0;
|
||||||
|
for (unsigned long i = 0; i < sizeof(buf->elements) / sizeof(PathBufElem) && buf->elements[i].len > 0; i++)
|
||||||
|
totallen += buf->elements[i].len;
|
||||||
|
ssize_t temp;
|
||||||
|
if ((temp = snprintf(buf->elements[nth_elem].bufpos, sizeof(buf->buf) - totallen, (isdir) ? "%s/" : "%s", content)) == -1)
|
||||||
|
return -2;
|
||||||
|
buf->elements[nth_elem].len = (size_t)temp;
|
||||||
|
if (nth_elem < sizeof(buf->elements) / sizeof(PathBufElem)) {
|
||||||
|
buf->elements[nth_elem + 1].bufpos = buf->elements[nth_elem].bufpos + temp;
|
||||||
|
buf->elements[nth_elem + 1].len = 0;
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
signed int prepare_log_path(IRC_Message* message, PathBuf* pathbuffer)
|
||||||
|
{
|
||||||
|
char temp[MAXLINE];
|
||||||
|
char *type, *bufname;
|
||||||
|
char* types[] = {"channel", "user"};
|
||||||
|
switch (message->cmd) {
|
||||||
|
case JOIN:
|
||||||
|
case PART:
|
||||||
|
case MODE:
|
||||||
|
case TOPIC:
|
||||||
|
case KICK:
|
||||||
|
case NAMES:
|
||||||
|
case RPL_INVITING:
|
||||||
|
case RPL_BANLIST:
|
||||||
|
case RPL_ENDOFBANLIST: {
|
||||||
|
type = types[0];
|
||||||
|
bufname = message->args[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RPL_NOTOPIC:
|
||||||
|
case RPL_TOPIC: {
|
||||||
|
bufname = message->args[0];
|
||||||
|
// NOTE: Some weird servers don't follow the RFC and use args[0] as target nick
|
||||||
|
if (message->args[2] != NULL)
|
||||||
|
bufname = message->args[1];
|
||||||
|
type = types[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KILL: {
|
||||||
|
type = types[1];
|
||||||
|
bufname = message->args[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PRIVMSG:
|
||||||
|
case NOTICE: {
|
||||||
|
bufname = message->args[0];
|
||||||
|
type = types[1];
|
||||||
|
if (*bufname == '#' || *bufname == '&' || *bufname == '!' || *bufname == '+')
|
||||||
|
type = types[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
if (set_path_elem(type, 1, true, pathbuffer) <= 0)
|
||||||
|
return -1;
|
||||||
|
if (!mkdir_bottomup(pathbuffer->buf))
|
||||||
|
return -1;
|
||||||
|
strncpy(temp, bufname, sizeof(temp));
|
||||||
|
cleanup_path_names(temp);
|
||||||
|
if (set_path_elem(temp, 2, true, pathbuffer) <= 0)
|
||||||
|
return -1;
|
||||||
|
if (!mkdir_bottomup(pathbuffer->buf))
|
||||||
|
return -1;
|
||||||
|
if (set_path_elem("out", 3, false, pathbuffer) <= 0)
|
||||||
|
return -1;
|
||||||
|
if (!mkdir_bottomup(pathbuffer->buf))
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -16,23 +16,29 @@
|
|||||||
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uirc/functions.h"
|
|
||||||
#include "uirc/mappings.h"
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
|
#define UIRC_IRCV3
|
||||||
|
#include "uirc/functions.h"
|
||||||
|
#include "uirc/mappings.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <linux/limits.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifndef _UIRCD_INCLUDED_FS
|
#ifndef UIRCD_INCLUDED_FS
|
||||||
#define _UIRCD_INCLUDED_FS
|
#define UIRCD_INCLUDED_FS
|
||||||
|
|
||||||
int cleanup_path_names(char* name);
|
int mkdir_bottomup(char* path);
|
||||||
int assemble_path(char** path, char* out, int len);
|
int makeinput(char* path);
|
||||||
int mkdir_bottomup(char** dir);
|
bool cleanup_path_names(char* name);
|
||||||
|
bool write_log(char* path, char* message);
|
||||||
|
bool add_socket_flags(int fd, int flags);
|
||||||
|
ssize_t set_path_elem(char* content, unsigned int nth_elem, bool isdir, PathBuf* buf);
|
||||||
|
int prepare_log_path(IRC_Message* message, PathBuf* pathbuffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -16,18 +16,19 @@
|
|||||||
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "structs.h"
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#ifndef _UIRCD_INCLUDED_GLOBAL
|
#ifndef UIRCD_INCLUDED_GLOBAL
|
||||||
#define _UIRCD_INCLUDED_GLOBAL
|
#define UIRCD_INCLUDED_GLOBAL
|
||||||
|
|
||||||
#define MAXLINE 512
|
#define MAXLINE 512
|
||||||
#define MAXPATH 1024
|
#define MAXPATH 1024
|
||||||
#define MAXCONN 64
|
#define MAXCONN 64
|
||||||
|
#define MAXNICK 32
|
||||||
#define ERRNOFMT "%s (%i)"
|
#define ERRNOFMT "%s (%i)"
|
||||||
#define ADDRFMT "%s:%s"
|
#define ADDRFMT "%s:%s"
|
||||||
|
|
||||||
extern sig_atomic_t volatile run;
|
extern sig_atomic_t volatile run;
|
||||||
extern int loglevel;
|
extern int loglevel;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
40
src/log.h
40
src/log.h
@ -18,8 +18,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _UIRCD_INCLUDED_LOG
|
#ifndef UIRCD_INCLUDED_LOG
|
||||||
#define _UIRCD_INCLUDED_LOG
|
#define UIRCD_INCLUDED_LOG
|
||||||
|
|
||||||
#define LOG_FATAL 0
|
#define LOG_FATAL 0
|
||||||
#define LOG_ERROR 1
|
#define LOG_ERROR 1
|
||||||
@ -28,23 +28,23 @@
|
|||||||
#define LOG_VERBOSE 4
|
#define LOG_VERBOSE 4
|
||||||
#define LOG_DEBUG 5
|
#define LOG_DEBUG 5
|
||||||
|
|
||||||
#define LOG(LEVEL, ...) \
|
#define LOG(LEVEL, ...) \
|
||||||
{ \
|
if (LEVEL <= loglevel) { \
|
||||||
if (LEVEL <= loglevel) { \
|
char* logchar = "?"; \
|
||||||
char* logchar = "?"; \
|
switch (LEVEL) { \
|
||||||
switch (LEVEL) { \
|
case (LOG_DEBUG): logchar = "D"; break; \
|
||||||
case (LOG_DEBUG): logchar = "D"; break; \
|
case (LOG_VERBOSE): logchar = "V"; break; \
|
||||||
case (LOG_VERBOSE): logchar = "V"; break; \
|
case (LOG_INFO): logchar = "I"; break; \
|
||||||
case (LOG_INFO): logchar = "I"; break; \
|
case (LOG_WARN): logchar = "W"; break; \
|
||||||
case (LOG_WARN): logchar = "W"; break; \
|
case (LOG_ERROR): logchar = "E"; break; \
|
||||||
case (LOG_ERROR): logchar = "E"; break; \
|
case (LOG_FATAL): logchar = "F"; break; \
|
||||||
case (LOG_FATAL): logchar = "F"; break; \
|
} \
|
||||||
} \
|
fprintf(stderr, "[%s] ", logchar); \
|
||||||
fprintf(stderr, "[%s] ", logchar); \
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
fprintf(stderr, __VA_ARGS__); \
|
if (loglevel == LOG_DEBUG) \
|
||||||
if (loglevel == LOG_DEBUG) \
|
fprintf(stderr, " --> LINE: %i -- FILE: %s", __LINE__, __FILE__); \
|
||||||
fprintf(stderr, " --> LINE: %i -- FILE: %s", __LINE__, __FILE__); \
|
putc('\n', stderr); \
|
||||||
putc('\n', stderr); \
|
|
||||||
} \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
383
src/main.c
383
src/main.c
@ -22,8 +22,9 @@ sig_atomic_t volatile run = true;
|
|||||||
int loglevel = LOG_FATAL;
|
int loglevel = LOG_FATAL;
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
char *quitmsg = "uIRC indev beta", c, *pos = NULL;
|
int c;
|
||||||
unsigned int totcon = 0, actcon = 0, delay = 10, timeout = 30;
|
char *quitmsg = "uIRC indev beta", *pos = NULL;
|
||||||
|
unsigned int totcon = 0, actcon = 0, timeout = 30;
|
||||||
Connection cons[MAXCONN] = {0};
|
Connection cons[MAXCONN] = {0};
|
||||||
setvbuf(stderr, NULL, _IOLBF, 0); /* Threads may want to print incomplete messages to the log at the same that, avoid that. */
|
setvbuf(stderr, NULL, _IOLBF, 0); /* Threads may want to print incomplete messages to the log at the same that, avoid that. */
|
||||||
|
|
||||||
@ -31,7 +32,6 @@ int main(int argc, char* argv[])
|
|||||||
* -c Connection in format: nick [ '!' user ] [ '@' host ] [ '/' [ '+' ] port ] [ ',' channel [ ',' channel ... ] ]
|
* -c Connection in format: nick [ '!' user ] [ '@' host ] [ '/' [ '+' ] port ] [ ',' channel [ ',' channel ... ] ]
|
||||||
* -l Starting directory for message tree
|
* -l Starting directory for message tree
|
||||||
* -m Message sent on closing the bouncer gracefully
|
* -m Message sent on closing the bouncer gracefully
|
||||||
* -d Reconnection delay (seconds)
|
|
||||||
* -t Timeout duration (seconds)
|
* -t Timeout duration (seconds)
|
||||||
* -V Log level: 0 being FATAL and 5 being DEBUG
|
* -V Log level: 0 being FATAL and 5 being DEBUG
|
||||||
* -C Configuration file path
|
* -C Configuration file path
|
||||||
@ -64,8 +64,7 @@ int main(int argc, char* argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'm': quitmsg = optarg; break;
|
case 'm': quitmsg = optarg; break;
|
||||||
case 'd': delay = atoi(optarg); break;
|
case 't': timeout = (unsigned int)atoi(optarg); break;
|
||||||
case 't': timeout = atoi(optarg); break;
|
|
||||||
case 'C': break; // TODO: Reserved for config file path
|
case 'C': break; // TODO: Reserved for config file path
|
||||||
case 'V': loglevel = atoi(optarg); break;
|
case 'V': loglevel = atoi(optarg); break;
|
||||||
case 'v': {
|
case 'v': {
|
||||||
@ -92,7 +91,7 @@ int main(int argc, char* argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (cpid == 0) {
|
} else if (cpid == 0) {
|
||||||
return run_main(&cons[actcon], delay, quitmsg, timeout);
|
return run_main(&cons[actcon], quitmsg, timeout);
|
||||||
} else {
|
} else {
|
||||||
LOG(LOG_VERBOSE, "Successfully forked for connection " ADDRFMT ".", cons[actcon].data.addr, cons[actcon].data.port);
|
LOG(LOG_VERBOSE, "Successfully forked for connection " ADDRFMT ".", cons[actcon].data.addr, cons[actcon].data.port);
|
||||||
actcon++;
|
actcon++;
|
||||||
@ -106,283 +105,195 @@ int main(int argc, char* argv[])
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_main(Connection* conn, unsigned int recon_inter, char* quitmsg, int timeout)
|
int run_main(Connection* conn, char* quitmsg, unsigned int timeout)
|
||||||
{
|
{
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
IRC_Message buffer;
|
IRC_Message buffer;
|
||||||
char sendbuf[MAXLINE + 1], recvbuf[MAXLINE + 1], fifobuf[MAXLINE + 1], /* Buffers */
|
Buffer_Info buffers[3]; /* Buffers */
|
||||||
connstr[100], *path[4] = {connstr, NULL, 0}; /* Path buffers */
|
#define recvbuf buffers[0]
|
||||||
size_t sendbufpos = 0, recvbufpos = 0, fifobufpos = 0; /* Positions */
|
#define sendbuf buffers[1]
|
||||||
signed int connstate = CONN_PENDING, fds[2] = {-1, -1}; /* Connection state and file descriptors */
|
#define fifobuf buffers[2]
|
||||||
unsigned int lastping = 0, lastconnect = 0, ctime = 0, lastpong = 0, lastmesg = 0, /* Timestamps */
|
PathBuf filebuf;
|
||||||
reconinter = (recon_inter) ? recon_inter : 10; /* Intervals */
|
signed int reconinter = 0;
|
||||||
|
time_t ctime;
|
||||||
get_connstr(connstr, sizeof(connstr), conn);
|
bool active = true;
|
||||||
srand(time(NULL));
|
struct timespec sleep = {0, 50000000L};
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct timespec sleep = {0, 10000000L};
|
|
||||||
nanosleep(&sleep, NULL);
|
|
||||||
|
|
||||||
/* Connection manager */
|
|
||||||
ctime = time(NULL);
|
ctime = time(NULL);
|
||||||
if (!run || connstate == CONN_CLOSING) {
|
if (!active)
|
||||||
if (fds[0] != -1) {
|
nanosleep(&sleep, NULL);
|
||||||
if ((sendbufpos = Assm_mesg(sendbuf, Assm_cmd_QUIT(quitmsg), sizeof(sendbuf))) > 0) {
|
active = false;
|
||||||
LOG(LOG_VERBOSE, "Sending a QUIT message to " ADDRFMT " containing \"%s\".", conn->data.addr, conn->data.port, quitmsg);
|
if (!run || conn->state == CONN_CLOSING) {
|
||||||
if (flush_buffer(sendbuf, sendbufpos, fds[0]) == -1)
|
signed long temp;
|
||||||
LOG(LOG_WARN, "Couldn't flush send buffer to " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
if ((temp = Assm_mesg(sendbuf.buffer, Assm_cmd_QUIT(quitmsg), sizeof(sendbuf.buffer))) > 0) {
|
||||||
}
|
sendbuf.append_pos = (unsigned long)temp;
|
||||||
close(fds[0]);
|
LOG(LOG_VERBOSE, "Sending a QUIT message to " ADDRFMT " containing \"%s\".", conn->data.addr, conn->data.port, quitmsg);
|
||||||
|
if (flush_buffer(sendbuf.buffer, sendbuf.append_pos, sendbuf.fd) == -1)
|
||||||
|
LOG(LOG_WARN, "Couldn't flush send buffer to " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
||||||
}
|
}
|
||||||
if (fds[1] == -1)
|
close(sendbuf.fd);
|
||||||
close(fds[1]);
|
close(fifobuf.fd);
|
||||||
connstate = CONN_CLOSED;
|
conn->state = CONN_CLOSED;
|
||||||
LOG(LOG_VERBOSE, "Connection to " ADDRFMT " was closed.", conn->data.addr, conn->data.port);
|
LOG(LOG_VERBOSE, "Connection to " ADDRFMT " was closed.", conn->data.addr, conn->data.port);
|
||||||
break;
|
break;
|
||||||
} else if (connstate == CONN_CLOSED)
|
} else if (conn->state == CONN_CLOSED)
|
||||||
break;
|
break;
|
||||||
else if (connstate == CONN_PENDING) {
|
else if (conn->state == CONN_RECONNECTING) {
|
||||||
if (ctime - lastconnect < recon_inter)
|
close(sendbuf.fd);
|
||||||
|
close(fifobuf.fd);
|
||||||
|
conn->state = CONN_PENDING;
|
||||||
|
continue;
|
||||||
|
} else if (conn->state == CONN_PENDING) {
|
||||||
|
if (ctime - conn->lastconnect < reconinter)
|
||||||
continue;
|
continue;
|
||||||
if (fds[0] != -1)
|
conn->lastconnect = ctime;
|
||||||
close(fds[0]);
|
filebuf.elements[0].bufpos = filebuf.buf;
|
||||||
lastconnect = ctime;
|
|
||||||
int tmp;
|
|
||||||
if ((tmp = init_conn(conn)) > 0) {
|
|
||||||
fds[0] = tmp;
|
|
||||||
memset(recvbuf, '\0', sizeof(recvbuf));
|
|
||||||
memset(sendbuf, '\0', sizeof(sendbuf));
|
|
||||||
memset(fifobuf, '\0', sizeof(fifobuf));
|
|
||||||
lastpong = ctime;
|
|
||||||
lastping = ctime;
|
|
||||||
|
|
||||||
int flags;
|
/* Reset all state-dependent values to empty */
|
||||||
if ((flags = fcntl(fds[0], F_GETFL)) != -1) {
|
memset(&recvbuf, '\0', sizeof(recvbuf));
|
||||||
if (fcntl(fds[0], F_SETFL, flags | O_NONBLOCK) == -1)
|
memset(&sendbuf, '\0', sizeof(sendbuf));
|
||||||
LOG(LOG_WARN, "Couldn't set socket to be non-blocking. Messages may be delayed as a result. " ERRNOFMT, strerror(errno), errno);
|
memset(&fifobuf, '\0', sizeof(fifobuf));
|
||||||
} else
|
conn->lastping = 0;
|
||||||
LOG(LOG_WARN, "Failed to get socket flags. Messages may be delayed as sockets will block. " ERRNOFMT, strerror(errno), errno);
|
conn->lastpong = 0;
|
||||||
|
conn->lastmessage = 0;
|
||||||
|
|
||||||
/* Create server.port/global for FIFO and open it */
|
/* Prepare first part of path */
|
||||||
path[1] = category[CAT_GLOB];
|
char tempath[MAXPATH];
|
||||||
path[2] = NULL;
|
if ((get_connstr(tempath, sizeof(tempath), conn)) >= 0) {
|
||||||
if (mkdir_bottomup(path)) {
|
cleanup_path_names(tempath);
|
||||||
path[2] = "in";
|
if (set_path_elem(tempath, 0, true, &filebuf) > 0 && set_path_elem("global", 1, true, &filebuf) > 0) {
|
||||||
path[3] = NULL;
|
if (!mkdir_bottomup(filebuf.buf))
|
||||||
char pbuf[PATH_MAX];
|
break;
|
||||||
int tmp;
|
if (set_path_elem("in", 2, false, &filebuf)) {
|
||||||
if (assemble_path(path, pbuf, sizeof(pbuf))) {
|
if ((fifobuf.fd = makeinput(filebuf.buf)) == -1)
|
||||||
if ((mkfifo(pbuf, S_IRUSR | S_IWUSR | S_IWGRP)) != 0 && errno != EEXIST) {
|
break;
|
||||||
LOG(LOG_WARN, "Couldn't create FIFO at \"%s\" for input. " ERRNOFMT, pbuf, strerror(errno), errno);
|
}
|
||||||
} else {
|
|
||||||
LOG(LOG_VERBOSE, "Created a FIFO pipe for input at %s.", pbuf);
|
|
||||||
ssize_t fd;
|
|
||||||
if ((fd = open(pbuf, O_RDONLY | O_NONBLOCK)) != -1)
|
|
||||||
fds[1] = fd;
|
|
||||||
else
|
|
||||||
LOG(LOG_WARN, "Couldn't open FIFO pipe \"%s\" for reading. " ERRNOFMT, pbuf, strerror(errno), errno);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
LOG(LOG_WARN, "Couldn't assemble path for FIFO.");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((sendbufpos = Assm_mesg(sendbuf, Assm_cmd_NICK(conn->names.nick), sizeof(sendbuf))) > 0) {
|
if ((sendbuf.fd = init_conn(conn)) > 0) {
|
||||||
|
recvbuf.fd = sendbuf.fd;
|
||||||
|
add_socket_flags(sendbuf.fd, O_NONBLOCK);
|
||||||
|
/* Send NICK and USER registration */
|
||||||
|
// TODO: PASS
|
||||||
|
signed long temp;
|
||||||
|
if ((temp = Assm_mesg(sendbuf.buffer, Assm_cmd_NICK(conn->names.nick), sizeof(sendbuf.buffer))) > 0) {
|
||||||
|
sendbuf.append_pos = (size_t)temp;
|
||||||
LOG(LOG_VERBOSE, "Sending a NICK registration to " ADDRFMT " containing \"%s\".", conn->data.addr, conn->data.port, conn->names.nick);
|
LOG(LOG_VERBOSE, "Sending a NICK registration to " ADDRFMT " containing \"%s\".", conn->data.addr, conn->data.port, conn->names.nick);
|
||||||
if (flush_buffer(sendbuf, sendbufpos, fds[0]) == -1) {
|
if (flush_buffer(sendbuf.buffer, sendbuf.append_pos, sendbuf.fd) == -1) {
|
||||||
LOG(LOG_WARN, "Couldn't register nickname on " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
LOG(LOG_WARN, "Couldn't register nickname on " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
||||||
connstate = CONN_PENDING;
|
conn->state = CONN_RECONNECTING;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((sendbufpos = Assm_mesg(sendbuf, Assm_cmd_USER(conn->names.user, conn->names.real, 0), sizeof(sendbuf))) > 0) {
|
if ((temp = Assm_mesg(sendbuf.buffer, Assm_cmd_USER(conn->names.user, conn->names.real, 0), sizeof(sendbuf.buffer))) > 0) {
|
||||||
|
sendbuf.append_pos = (size_t)temp;
|
||||||
LOG(LOG_VERBOSE, "Sending a USER registration to " ADDRFMT " containing \"%s\".", conn->data.addr, conn->data.port, conn->names.real);
|
LOG(LOG_VERBOSE, "Sending a USER registration to " ADDRFMT " containing \"%s\".", conn->data.addr, conn->data.port, conn->names.real);
|
||||||
if (flush_buffer(sendbuf, sendbufpos, fds[0]) == -1) {
|
if (flush_buffer(sendbuf.buffer, sendbuf.append_pos, sendbuf.fd) == -1) {
|
||||||
LOG(LOG_WARN, "Couldn't register user and real name on " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
LOG(LOG_WARN, "Couldn't register user and real name on " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
||||||
connstate = CONN_PENDING;
|
conn->state = CONN_RECONNECTING;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connstate = CONN_REGISTERED;
|
conn->state = CONN_REGISTERED;
|
||||||
} else if (tmp == INIT_SOFTFAIL) {
|
} else if (sendbuf.fd == INIT_SOFTFAIL) {
|
||||||
connstate = CONN_PENDING;
|
conn->state = CONN_RECONNECTING;
|
||||||
continue;
|
continue;
|
||||||
} else if (tmp == INIT_HARDFAIL) {
|
} else if (sendbuf.fd == INIT_HARDFAIL) {
|
||||||
connstate = CONN_CLOSED;
|
conn->state = CONN_CLOSED;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (connstate == CONN_ACTIVE) {
|
} else if (conn->state == CONN_ACTIVE) {
|
||||||
if (lastmesg < ctime - timeout && lastpong < lastping - timeout) {
|
if (conn->lastmessage < ctime - timeout && conn->lastpong < conn->lastping - timeout) {
|
||||||
LOG(LOG_WARN, "Server " ADDRFMT " didn't respond to a PING in time.", conn->data.addr, conn->data.port);
|
LOG(LOG_WARN, "Server " ADDRFMT " didn't respond to a PING in time.", conn->data.addr, conn->data.port);
|
||||||
connstate = CONN_PENDING;
|
conn->state = CONN_RECONNECTING;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ctime - lastmesg >= timeout / 4 && ctime - lastping >= timeout / 4) {
|
if (ctime - conn->lastmessage >= timeout / 4 && ctime - conn->lastping >= timeout / 4) {
|
||||||
char mesg[] = "uIRC PING -- XXXXXX";
|
char mesg[] = "uIRC PING -- XXXXXX";
|
||||||
snprintf(mesg + sizeof(mesg) - 7, 7, "%.6i", rand());
|
snprintf(mesg + sizeof(mesg) - 7, 7, "%.6i", rand());
|
||||||
if ((sendbufpos = Assm_mesg(sendbuf, Assm_cmd_PING(mesg, NULL), sizeof(sendbuf))) > 0) {
|
signed long temp;
|
||||||
|
if ((temp = Assm_mesg(sendbuf.buffer, Assm_cmd_PING(mesg, NULL), sizeof(sendbuf.buffer))) > 0) {
|
||||||
|
sendbuf.append_pos = (size_t)temp;
|
||||||
LOG(LOG_DEBUG, "Sending ping to " ADDRFMT " with message \"%s\"", conn->data.addr, conn->data.port, mesg);
|
LOG(LOG_DEBUG, "Sending ping to " ADDRFMT " with message \"%s\"", conn->data.addr, conn->data.port, mesg);
|
||||||
if (flush_buffer(sendbuf, sendbufpos, fds[0]) == -1) {
|
if (flush_buffer(sendbuf.buffer, sendbuf.append_pos, sendbuf.fd) == -1) {
|
||||||
LOG(LOG_WARN, "Couldn't ping " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
LOG(LOG_WARN, "Couldn't ping " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
||||||
connstate = CONN_PENDING;
|
conn->state = CONN_RECONNECTING;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
lastping = ctime;
|
conn->lastping = ctime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Buffer reader */
|
|
||||||
ssize_t brd;
|
ssize_t brd;
|
||||||
if ((brd = read(fds[0], recvbuf + recvbufpos, sizeof(recvbuf) - recvbufpos - 1)) > 0) {
|
|
||||||
LOG(LOG_DEBUG, "Read %li bytes.", brd);
|
/* Buffer reader */
|
||||||
*(recvbuf + (recvbufpos += brd)) = '\0';
|
if ((brd = read(recvbuf.fd, recvbuf.buffer + recvbuf.append_pos, sizeof(recvbuf.buffer) - recvbuf.append_pos - 1)) > 0) {
|
||||||
} else if (brd == 0) {
|
*(recvbuf.buffer + (recvbuf.append_pos += (size_t)brd)) = '\0';
|
||||||
connstate = CONN_PENDING;
|
LOG(LOG_DEBUG, "Read %li bytes from socket buffer. Now appending at %li", brd, recvbuf.append_pos);
|
||||||
|
active = true;
|
||||||
} else if (brd == -1 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
} else if (brd == -1 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
||||||
LOG(LOG_ERROR, "Failed to read inbound traffic. " ERRNOFMT, strerror(errno), errno);
|
LOG(LOG_ERROR, "Failed to read inbound traffic. " ERRNOFMT, strerror(errno), errno);
|
||||||
connstate = CONN_PENDING;
|
conn->state = CONN_RECONNECTING;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ppoi;
|
ssize_t len;
|
||||||
if ((ppoi = strchr(recvbuf, '\n')) != NULL) {
|
memset((void*)&buffer, '\0', sizeof(IRC_Message));
|
||||||
*ppoi = '\0';
|
if ((len = get_buffer_line(recvbuf.buffer, &buffer)) > 0) {
|
||||||
if (ppoi > recvbuf && *(ppoi - 1) == '\r')
|
conn->lastmessage = ctime;
|
||||||
*(ppoi - 1) = '\0';
|
if (set_path_elem("global", 1, true, &filebuf) > 0 && set_path_elem("out", 2, false, &filebuf) > 0) {
|
||||||
LOG(LOG_DEBUG, "Recieved line: %s", recvbuf);
|
LOG(LOG_DEBUG, "Writing message to global path %s.", filebuf.buf);
|
||||||
lastmesg = ctime;
|
signed long temp;
|
||||||
memset((void*)&buffer, '\0', sizeof(IRC_Message));
|
if ((temp = Assm_mesg(sendbuf.buffer, &buffer, sizeof(sendbuf.buffer))) > 0)
|
||||||
if (Tok_mesg(recvbuf, &buffer) == 1) {
|
write_log(filebuf.buf, sendbuf.buffer);
|
||||||
char bufname[MAXPATH + 1], logpath[PATH_MAX], *bprint = "out";
|
}
|
||||||
FILE* logfile;
|
if (prepare_log_path(&buffer, &filebuf) == 1) {
|
||||||
LOG(LOG_DEBUG, "Tokenized message successfully.");
|
LOG(LOG_DEBUG, "Writing message to path %s.", filebuf.buf);
|
||||||
|
signed long temp;
|
||||||
/* Path Assembly and Filtering */
|
if ((temp = Assm_mesg(sendbuf.buffer, &buffer, sizeof(sendbuf.buffer))) > 0)
|
||||||
if (buffer.cmd == PRIVMSG || buffer.cmd == NOTICE) {
|
write_log(filebuf.buf, sendbuf.buffer);
|
||||||
if (strchr("&!#+", *buffer.args[0])) {
|
}
|
||||||
path[1] = category[CAT_CHAN];
|
if (!auto_msg_actions(&buffer, conn, &sendbuf))
|
||||||
bprint = buffer.args[0];
|
continue;
|
||||||
} else if (buffer.name.nick != NULL) {
|
for (long unsigned int x = 0; x < sizeof(recvbuf.buffer) && *(recvbuf.buffer + len + x); x++)
|
||||||
path[1] = category[CAT_USER];
|
*(recvbuf.buffer + x) = *(recvbuf.buffer + x + len);
|
||||||
bprint = buffer.name.nick;
|
recvbuf.append_pos -= (unsigned long)len;
|
||||||
}
|
*(recvbuf.buffer + recvbuf.append_pos) = '\0';
|
||||||
} else if (buffer.cmd == RPL_BANLIST || buffer.cmd == RPL_ENDOFBANLIST) {
|
active = true;
|
||||||
path[1] = category[CAT_CHAN];
|
} else if (len == -1)
|
||||||
bprint = buffer.args[0];
|
conn->state = CONN_RECONNECTING;
|
||||||
} else if (buffer.cmd == KILL || buffer.cmd == RPL_AWAY) {
|
|
||||||
path[1] = category[CAT_USER];
|
|
||||||
bprint = buffer.name.nick;
|
|
||||||
} else if (buffer.cmd == JOIN || buffer.cmd == PART) {
|
|
||||||
path[1] = category[CAT_CHAN];
|
|
||||||
bprint = buffer.args[0];
|
|
||||||
} else {
|
|
||||||
path[1] = category[CAT_GLOB];
|
|
||||||
}
|
|
||||||
path[2] = NULL;
|
|
||||||
|
|
||||||
if (mkdir_bottomup(path)) {
|
|
||||||
snprintf(bufname, sizeof(bufname), "%s", bprint);
|
|
||||||
cleanup_path_names(bufname);
|
|
||||||
path[2] = bufname;
|
|
||||||
path[3] = NULL;
|
|
||||||
if (assemble_path(path, logpath, sizeof(logpath))) {
|
|
||||||
char linebuf[513];
|
|
||||||
if (Assm_mesg(sendbuf, &buffer, sizeof(sendbuf)) > 0) {
|
|
||||||
LOG(LOG_DEBUG, "Assembled line: \"%s\" to write to %s.", sendbuf, bufname);
|
|
||||||
if ((logfile = fopen(logpath, "a")) != NULL) {
|
|
||||||
fprintf(logfile, "%s", sendbuf);
|
|
||||||
fclose(logfile);
|
|
||||||
} else
|
|
||||||
LOG(LOG_WARN, "Couldn't open file \"%s\" for appending.", logpath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
LOG(LOG_WARN, "Log directory couldn't be created. " ERRNOFMT, strerror(errno), errno);
|
|
||||||
|
|
||||||
/* Automatic message handling */
|
|
||||||
switch (buffer.cmd) {
|
|
||||||
case (PING): {
|
|
||||||
LOG(LOG_DEBUG, "Auto-replying to ping \"%s\".", buffer.args[0]);
|
|
||||||
if ((sendbufpos = Assm_mesg(sendbuf, Assm_cmd_PONG(buffer.args[0], NULL), sizeof(sendbuf))) > 0)
|
|
||||||
if (flush_buffer(sendbuf, sendbufpos, fds[0]) == -1) {
|
|
||||||
LOG(LOG_WARN, "Couldn't pong " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
|
||||||
connstate = CONN_PENDING;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (PONG): {
|
|
||||||
if (buffer.trailing && buffer.args[1] != NULL) {
|
|
||||||
LOG(LOG_DEBUG, "Got PONG back with message \"%s\".", buffer.args[1]);
|
|
||||||
lastpong = ctime;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Autojoin channels from current connection on first response from the server
|
|
||||||
* TODO? Split channels and join X channels each
|
|
||||||
* This most likely is not required unless the user has loooots of channels.
|
|
||||||
* If you are that type of user, you are free to add that.
|
|
||||||
*/
|
|
||||||
case (RPL_WELCOME): {
|
|
||||||
LOG(LOG_INFO, "Connection established to " ADDRFMT ".", conn->data.addr, conn->data.port);
|
|
||||||
connstate = CONN_ACTIVE;
|
|
||||||
if (conn->data.chans != NULL) {
|
|
||||||
LOG(LOG_VERBOSE, "Auto-joining channels \"%s\" on " ADDRFMT ".", conn->data.chans, conn->data.addr, conn->data.port);
|
|
||||||
if ((sendbufpos = Assm_mesg(sendbuf, Assm_cmd_JOIN(conn->data.chans, NULL), sizeof(sendbuf))) > 0) {
|
|
||||||
if (flush_buffer(sendbuf, sendbufpos, fds[0]) == -1) {
|
|
||||||
LOG(LOG_WARN, "Couldn't auto-join channels \"%s\" " ADDRFMT ". " ERRNOFMT, conn->data.chans, conn->data.addr, conn->data.port, strerror(errno), errno);
|
|
||||||
connstate = CONN_PENDING;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (ERROR): {
|
|
||||||
LOG(LOG_ERROR, "Received error on connection " ADDRFMT " with the message \"%s\".", conn->data.addr, conn->data.port, buffer.args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
LOG(LOG_WARN, "Received invalid IRC message (see RFC2812).");
|
|
||||||
for (char* x = (ppoi + 1); *x; x++)
|
|
||||||
*(recvbuf + (x - (ppoi + 1))) = *x;
|
|
||||||
recvbufpos -= (ppoi + 1) - recvbuf;
|
|
||||||
*(recvbuf + recvbufpos) = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Buffer writer */
|
/* Buffer writer */
|
||||||
if ((brd = read(fds[1], fifobuf + fifobufpos, sizeof(fifobuf) - fifobufpos - 1)) > 0) {
|
if ((brd = read(fifobuf.fd, fifobuf.buffer + fifobuf.append_pos, sizeof(fifobuf.buffer) - fifobuf.append_pos - 1)) > 0) {
|
||||||
LOG(LOG_DEBUG, "Read %li bytes from FIFO.", brd);
|
*(fifobuf.buffer + (fifobuf.append_pos += (size_t)brd)) = '\0';
|
||||||
*(fifobuf + (fifobufpos += brd)) = '\0';
|
LOG(LOG_DEBUG, "Read %li bytes from FIFO. Now appending at %li", brd, fifobuf.append_pos);
|
||||||
} else if (brd == -1 && errno != EAGAIN && errno != EINTR) {
|
active = true;
|
||||||
LOG(LOG_ERROR, "Failed to read FIFO input for connection " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
} else if (brd == -1 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
||||||
connstate = CONN_PENDING;
|
LOG(LOG_ERROR, "Failed to read FIFO input. " ERRNOFMT, strerror(errno), errno);
|
||||||
|
conn->state = CONN_RECONNECTING;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ppoi = strchr(fifobuf, '\n')) != NULL) {
|
memset((void*)&buffer, '\0', sizeof(IRC_Message));
|
||||||
*ppoi = '\0';
|
if ((len = get_buffer_line(fifobuf.buffer, &buffer)) > 0) {
|
||||||
if (ppoi > fifobuf && *(ppoi - 1) == '\r')
|
LOG(LOG_DEBUG, "Tokenized FIFO message successfully.");
|
||||||
*(ppoi - 1) = '\0';
|
signed long temp;
|
||||||
LOG(LOG_DEBUG, "Recieved FIFO line: %s", fifobuf);
|
if ((temp = Assm_mesg(fifobuf.buffer, &buffer, sizeof(fifobuf.buffer))) > 0) {
|
||||||
memset((void*)&buffer, '\0', sizeof(IRC_Message));
|
if (flush_buffer(fifobuf.buffer, (size_t)temp, sendbuf.fd) == -1) {
|
||||||
if (Tok_mesg(fifobuf, &buffer) == 1) {
|
LOG(LOG_WARN, "Couldn't send FIFO input to " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
||||||
LOG(LOG_DEBUG, "Tokenized FIFO message successfully.");
|
conn->state = CONN_RECONNECTING;
|
||||||
if ((sendbufpos = Assm_mesg(sendbuf, &buffer, sizeof(sendbuf))) > 0) {
|
continue;
|
||||||
if (flush_buffer(sendbuf, sendbufpos, fds[0]) == -1) {
|
|
||||||
LOG(LOG_WARN, "Couldn't send FIFO input to " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
|
||||||
connstate = CONN_PENDING;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
LOG(LOG_WARN, "Received invalid IRC message on FIFO (see RFC2812).");
|
for (long unsigned int x = 0; x < sizeof(fifobuf.buffer) && *(fifobuf.buffer + len + x); x++)
|
||||||
for (char* x = (ppoi + 1); *x; x++)
|
*(fifobuf.buffer + x) = *(fifobuf.buffer + x + len);
|
||||||
*(fifobuf + (x - (ppoi + 1))) = *x;
|
fifobuf.append_pos -= (unsigned long)len;
|
||||||
fifobufpos -= ppoi + 1 - fifobuf;
|
*(fifobuf.buffer + fifobuf.append_pos) = '\0';
|
||||||
*(fifobuf + fifobufpos) = '\0';
|
active = true;
|
||||||
}
|
} else if (len == -1)
|
||||||
|
conn->state = CONN_RECONNECTING;
|
||||||
}
|
}
|
||||||
LOG(LOG_VERBOSE, "Exiting thread with connection " ADDRFMT " gracefully.", conn->data.addr, conn->data.port);
|
LOG(LOG_VERBOSE, "Exiting thread with connection " ADDRFMT " gracefully.", conn->data.addr, conn->data.port);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
@ -394,20 +305,22 @@ void print_help(void)
|
|||||||
char arg;
|
char arg;
|
||||||
char* desc;
|
char* desc;
|
||||||
char* def;
|
char* def;
|
||||||
} arg_list[] = {{'c', "Define connection in format \"nick!user:real name@host/+port,#channel1,#channel2\""},
|
} arg_list[] = {{'c', "Define connection in format \"nick!user:real name@host/+port,#channel1,#channel2\"", NULL},
|
||||||
{'l', "Directory for logs", "current dir"},
|
{'l', "Directory for logs", "current dir"},
|
||||||
{'m', "Quit message", "uIRC indev beta"},
|
{'m', "Quit message", "uIRC indev beta"},
|
||||||
{'d', "Reconnection delay", "10 seconds"},
|
|
||||||
{'t', "Timeout duration", "30 seconds"},
|
{'t', "Timeout duration", "30 seconds"},
|
||||||
{'V', "Log level (0-5)", "0 [LOG_FATAL]"},
|
{'V', "Log level (0-5)", "0 [LOG_FATAL]"},
|
||||||
/* {'C', "Configuration path", "~/.config/uircd/main.conf"}, */
|
/* {'C', "Configuration path", "~/.config/uircd/main.conf"}, */
|
||||||
{'v', "Print version information", NULL},
|
{'v', "Print version information", NULL},
|
||||||
{'h', "Print this help message", NULL}};
|
{'h', "Print this help message", NULL}};
|
||||||
printf("usage: uirc -c [connection] [options...]\n");
|
printf("usage: uirc -c [connection] [options...]\n");
|
||||||
for (int i = 0; i < sizeof(arg_list) / sizeof(*arg_list); i++) {
|
for (size_t i = 0; i < sizeof(arg_list) / sizeof(*arg_list); i++) {
|
||||||
printf("\t-%c\t%s", arg_list[i].arg, arg_list[i].desc);
|
printf("\t-%c\t%s", arg_list[i].arg, arg_list[i].desc);
|
||||||
if (arg_list[i].def != NULL)
|
if (arg_list[i].def != NULL)
|
||||||
printf(" (default: %s)", arg_list[i].def);
|
printf(" (default: %s)", arg_list[i].def);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stop_loop() { run = 0; }
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifndef UIRCD_INCLUDED_MAIN
|
||||||
|
#define UIRCD_INCLUDED_MAIN
|
||||||
#define VERSION "indev - testing"
|
#define VERSION "indev - testing"
|
||||||
int run_main(Connection* conn, unsigned int recon_inter, char* quitmsg, int timeout);
|
|
||||||
|
void stop_loop(void);
|
||||||
|
int run_main(Connection* conn, char* quitmsg, unsigned int timeout);
|
||||||
void print_help(void);
|
void print_help(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
82
src/misc.c
82
src/misc.c
@ -18,15 +18,6 @@
|
|||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
char* category[] = {
|
|
||||||
[CAT_CHAN] = "channel",
|
|
||||||
[CAT_USER] = "user",
|
|
||||||
[CAT_GLOB] = "global"};
|
|
||||||
|
|
||||||
void stop_loop()
|
|
||||||
{
|
|
||||||
run = 0;
|
|
||||||
}
|
|
||||||
char* point_after(char* string, char point)
|
char* point_after(char* string, char point)
|
||||||
/*
|
/*
|
||||||
* Used to tokenize right to left based on characters
|
* Used to tokenize right to left based on characters
|
||||||
@ -39,10 +30,79 @@ char* point_after(char* string, char point)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_connstr(char* buf, size_t maxlen, Connection* conn)
|
ssize_t get_connstr(char* buf, size_t maxlen, Connection* conn)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
if ((len = snprintf(buf, maxlen, "%s.%s", conn->data.addr, conn->data.port)) <= 0)
|
if ((len = snprintf(buf, maxlen, "%s.%s", conn->data.addr, conn->data.port)) <= 0)
|
||||||
return 0;
|
return -1;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t get_buffer_line(char* buf, IRC_Message* parsed)
|
||||||
|
{
|
||||||
|
if (buf == NULL || parsed == NULL)
|
||||||
|
return -1;
|
||||||
|
char* ppoi;
|
||||||
|
if ((ppoi = strchr(buf, '\n')) != NULL) {
|
||||||
|
*ppoi = '\0';
|
||||||
|
if (ppoi > buf && *(ppoi - 1) == '\r')
|
||||||
|
*(ppoi - 1) = '\0';
|
||||||
|
LOG(LOG_DEBUG, "Got message %s", buf);
|
||||||
|
if (Tok_mesg(buf, parsed) == 1)
|
||||||
|
return ++ppoi - buf;
|
||||||
|
LOG(LOG_WARN, "Received invalid IRC message (see RFC2812).");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int auto_msg_actions(IRC_Message* message, Connection* conn, Buffer_Info* buf)
|
||||||
|
{
|
||||||
|
signed long len;
|
||||||
|
time_t ctime = time(NULL);
|
||||||
|
switch (message->cmd) {
|
||||||
|
case (PING): {
|
||||||
|
LOG(LOG_DEBUG, "Auto-replying to ping \"%s\".", message->args[0]);
|
||||||
|
if ((len = Assm_mesg(buf->buffer, Assm_cmd_PONG(message->args[0], NULL), sizeof(buf->buffer))) > 0)
|
||||||
|
if (flush_buffer(buf->buffer, (size_t)len, buf->fd) == -1) {
|
||||||
|
LOG(LOG_WARN, "Couldn't pong " ADDRFMT ". " ERRNOFMT, conn->data.addr, conn->data.port, strerror(errno), errno);
|
||||||
|
conn->state = CONN_RECONNECTING;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (PONG): {
|
||||||
|
if (message->trailing && message->args[1] != NULL) {
|
||||||
|
LOG(LOG_DEBUG, "Got PONG back with message \"%s\".", message->args[1]);
|
||||||
|
conn->lastpong = ctime;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Autojoin channels from current connection on first response from the server
|
||||||
|
* TODO: Split channels and join X channels each
|
||||||
|
* This most likely is not required unless the user has loooots of channels.
|
||||||
|
* If you are that type of user, you are free to add that case
|
||||||
|
*/
|
||||||
|
case (RPL_WELCOME): {
|
||||||
|
LOG(LOG_INFO, "Connection established to " ADDRFMT ".", conn->data.addr, conn->data.port);
|
||||||
|
conn->state = CONN_ACTIVE;
|
||||||
|
if (conn->data.chans != NULL) {
|
||||||
|
LOG(LOG_VERBOSE, "Auto-joining channels \"%s\" on " ADDRFMT ".", conn->data.chans, conn->data.addr, conn->data.port);
|
||||||
|
if ((len = Assm_mesg(buf->buffer, Assm_cmd_JOIN(conn->data.chans, NULL), sizeof(buf->buffer))) > 0) {
|
||||||
|
if (flush_buffer(buf->buffer, (size_t)len, buf->fd) == -1) {
|
||||||
|
LOG(LOG_WARN, "Couldn't auto-join channels \"%s\" " ADDRFMT ". " ERRNOFMT, conn->data.chans, conn->data.addr, conn->data.port, strerror(errno), errno);
|
||||||
|
conn->state = CONN_RECONNECTING;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ERROR): {
|
||||||
|
LOG(LOG_ERROR, "Received error on connection " ADDRFMT " with the message \"%s\".", conn->data.addr, conn->data.port, message->args[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
46
src/misc.h
46
src/misc.h
@ -1,44 +1,22 @@
|
|||||||
/*
|
|
||||||
* 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 "uirc/functions.h"
|
|
||||||
#include "uirc/mappings.h"
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "net.h"
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
|
#define UIRC_IRCV3
|
||||||
|
#include "uirc/functions.h"
|
||||||
|
#include "uirc/helpers.h"
|
||||||
|
#include "uirc/mappings.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#define UIRC_HELPERS
|
|
||||||
#include "uirc/helpers.h"
|
|
||||||
|
|
||||||
#ifndef _UIRCD_INCLUDED_MISC
|
#ifndef UIRCD_INCLUDED_MISC
|
||||||
#define _UIRCD_INCLUDED_MISC
|
#define UIRCD_INCLUDED_MISC
|
||||||
|
|
||||||
extern char* category[];
|
|
||||||
enum categories {
|
|
||||||
CAT_CHAN = 1,
|
|
||||||
CAT_USER,
|
|
||||||
CAT_GLOB
|
|
||||||
};
|
|
||||||
|
|
||||||
char* point_after(char* string, char point);
|
char* point_after(char* string, char point);
|
||||||
void stop_loop();
|
ssize_t get_connstr(char* buf, size_t maxlen, Connection* conn);
|
||||||
int get_connstr(char* buf, size_t maxlen, Connection* conn);
|
ssize_t get_buffer_line(char* buf, IRC_Message* parsed);
|
||||||
int get_category(IRC_Message* mesg);
|
int auto_msg_actions(IRC_Message* message, Connection* conn, Buffer_Info* buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
18
src/net.c
18
src/net.c
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
signed int init_conn(Connection* info)
|
signed int init_conn(Connection* info)
|
||||||
{
|
{
|
||||||
const struct timespec retry_timeout = {3, 0.0L};
|
|
||||||
int sockfd, getaddrres, connectres;
|
int sockfd, getaddrres, connectres;
|
||||||
if (info->data.addr == NULL) return INIT_HARDFAIL;
|
if (info->data.addr == NULL) return INIT_HARDFAIL;
|
||||||
struct addrinfo* conn;
|
struct addrinfo* conn;
|
||||||
@ -28,7 +27,7 @@ signed int init_conn(Connection* info)
|
|||||||
freeaddrinfo(conn);
|
freeaddrinfo(conn);
|
||||||
if (getaddrres != EAI_AGAIN && getaddrres != EAI_NONAME) {
|
if (getaddrres != EAI_AGAIN && getaddrres != EAI_NONAME) {
|
||||||
return INIT_HARDFAIL;
|
return INIT_HARDFAIL;
|
||||||
} else
|
} else
|
||||||
return INIT_SOFTFAIL;
|
return INIT_SOFTFAIL;
|
||||||
}
|
}
|
||||||
if ((sockfd = socket(conn->ai_family, conn->ai_socktype, conn->ai_protocol)) < 0) {
|
if ((sockfd = socket(conn->ai_family, conn->ai_socktype, conn->ai_protocol)) < 0) {
|
||||||
@ -42,26 +41,25 @@ signed int init_conn(Connection* info)
|
|||||||
freeaddrinfo(conn);
|
freeaddrinfo(conn);
|
||||||
if (errno != EADDRNOTAVAIL && errno != ETIMEDOUT && errno != ECONNRESET && errno != ECONNREFUSED) {
|
if (errno != EADDRNOTAVAIL && errno != ETIMEDOUT && errno != ECONNRESET && errno != ECONNREFUSED) {
|
||||||
return INIT_HARDFAIL;
|
return INIT_HARDFAIL;
|
||||||
} else
|
} else
|
||||||
return INIT_SOFTFAIL;
|
return INIT_SOFTFAIL;
|
||||||
}
|
}
|
||||||
freeaddrinfo(conn);
|
freeaddrinfo(conn);
|
||||||
return sockfd;
|
return sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flush_buffer(char* buf, int buflen, int fd)
|
ssize_t flush_buffer(char* buf, size_t buflen, int fd)
|
||||||
{
|
{
|
||||||
int res;
|
ssize_t res;
|
||||||
char* pos = buf;
|
char* pos = buf;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((res = write(fd, pos, buflen - (pos - buf))) != buflen - (pos - buf)) {
|
if ((size_t)(res = write(fd, pos, buflen - (size_t)(pos - buf))) != buflen - (size_t)(pos - buf)) {
|
||||||
if (res == -1) {
|
if (res == -1)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
else
|
||||||
pos += res;
|
pos += res;
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
return pos - buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
src/net.h
13
src/net.h
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define UIRC_HELPERS
|
#define UIRC_HELPERS
|
||||||
|
#define UIRC_IRCV3
|
||||||
#include "uirc/functions.h"
|
#include "uirc/functions.h"
|
||||||
#include "uirc/helpers.h"
|
#include "uirc/helpers.h"
|
||||||
#include "uirc/mappings.h"
|
#include "uirc/mappings.h"
|
||||||
@ -36,18 +37,20 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifndef _UIRCD_INCLUDED_NETWORK
|
#ifndef UIRCD_INCLUDED_NETWORK
|
||||||
#define _UIRCD_INCLUDED_NETWORK
|
#define UIRCD_INCLUDED_NETWORK
|
||||||
|
|
||||||
#define CONN_ACTIVE 2
|
#define CONN_ACTIVE 2
|
||||||
#define CONN_REGISTERED 1
|
#define CONN_REGISTERED 1
|
||||||
#define CONN_PENDING 0
|
#define CONN_PENDING 0
|
||||||
#define CONN_CLOSING -1
|
#define CONN_RECONNECTING -1
|
||||||
#define CONN_CLOSED -2
|
#define CONN_CLOSING -2
|
||||||
|
#define CONN_CLOSED -3
|
||||||
|
|
||||||
#define INIT_HARDFAIL -1
|
#define INIT_HARDFAIL -1
|
||||||
#define INIT_SOFTFAIL -2
|
#define INIT_SOFTFAIL -2
|
||||||
|
|
||||||
signed int init_conn(Connection* info);
|
signed int init_conn(Connection* info);
|
||||||
int flush_buffer(char* buf, int buflen, int fd);
|
ssize_t flush_buffer(char* buf, size_t buflen, int fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -16,26 +16,41 @@
|
|||||||
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#define UIRC_IRCV3
|
||||||
#include "uirc/types.h"
|
#include "uirc/types.h"
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifndef _UIRCD_INCLUDED_STRUCTS
|
#ifndef UIRCD_INCLUDED_STRUCTS
|
||||||
#define _UIRCD_INCLUDED_STRUCTS
|
#define UIRCD_INCLUDED_STRUCTS
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* addr;
|
char *addr, *port, *chans;
|
||||||
char* port;
|
|
||||||
char* chans;
|
|
||||||
bool ssl;
|
bool ssl;
|
||||||
} Connection_Data;
|
} Connection_Data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char buffer[513];
|
char buffer[513];
|
||||||
char* append_pos;
|
size_t append_pos;
|
||||||
char* nex_line;
|
int fd;
|
||||||
int* fd;
|
|
||||||
} Buffer_Info;
|
} Buffer_Info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IRC_User names;
|
IRC_User names;
|
||||||
Connection_Data data;
|
Connection_Data data;
|
||||||
|
time_t lastping, lastpong, lastconnect, lastmessage;
|
||||||
|
signed short state;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
} Connection;
|
} Connection;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* bufpos;
|
||||||
|
size_t len;
|
||||||
|
} PathBufElem;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char buf[MAXPATH];
|
||||||
|
PathBufElem elements[5];
|
||||||
|
} PathBuf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user