udphole

Basic UDP wormhole proxy
git clone git://git.finwo.net/app/udphole
Log | Files | Refs | README | LICENSE

commit 81d004b7644d9871420abd06cef84b8bc667e535
parent 9621d56ec9bd1dac721633dc8ee5c8151f4f39bd
Author: Robin Bron <robin.bron@yourhosting.nl>
Date:   Mon,  2 Mar 2026 15:33:56 +0100

auto-formatting

Diffstat:
A.clang-format | 334+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MMakefile | 4++++
Msrc/common/resp.c | 449++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/common/resp.h | 20++++++++++++--------
Msrc/common/scheduler.c | 30+++++++++++++++---------------
Msrc/common/scheduler.h | 10+++++-----
Msrc/common/socket_util.c | 66+++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/common/socket_util.h | 18+++++++++---------
Msrc/domain/cluster/cluster.c | 68+++++++++++++++++++++++++++++++++++---------------------------------
Msrc/domain/cluster/cluster.h | 2+-
Msrc/domain/cluster/node.c | 73+++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/domain/cluster/node.h | 14++++++++------
Msrc/domain/config.c | 6+++---
Msrc/domain/config.h | 1+
Msrc/domain/daemon/session.c | 203++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/domain/daemon/session.h | 4++--
Msrc/infrastructure/config.c | 18++++++++++--------
Msrc/infrastructure/config.h | 11+++++------
Msrc/interface/api/server.c | 179+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/interface/api/server.h | 4++--
Msrc/interface/cli/command/cluster.c | 41+++++++++++++++++++----------------------
Msrc/interface/cli/command/daemon.c | 46+++++++++++++++++++++-------------------------
Msrc/interface/cli/command/daemon.h | 3+--
Msrc/interface/cli/command/list_commands.c | 20+++++++++++---------
Msrc/interface/cli/command/list_commands.h | 3+--
Msrc/interface/cli/common.c | 46+++++++++++++++++++---------------------------
Msrc/interface/cli/common.h | 12+++++-------
Msrc/interface/cli/main.c | 104++++++++++++++++++++++++++++++++++++-------------------------------------------
28 files changed, 1114 insertions(+), 675 deletions(-)

diff --git a/.clang-format b/.clang-format @@ -0,0 +1,334 @@ +--- +Language: Cpp +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: true + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCaseArrows: false + AlignCaseColons: false +AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenCondOperatorColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenDefinitionColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AllowShortNamespacesOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AttributeMacros: + - __capability + - absl_nonnull + - absl_nullable + - absl_nullability_unknown +BinPackArguments: true +BinPackLongBracedList: true +BinPackParameters: BinPack +BitFieldColonSpacing: Both +BracedInitializerIndentWidth: -1 +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakAfterReturnType: None +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTemplateCloser: false +BreakBeforeTernaryOperators: true +BreakBinaryOperations: Never +BreakConstructorInitializers: BeforeColon +BreakFunctionDefinitionParameters: false +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +BreakTemplateDeclarations: Yes +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +EnumTrailingComma: Leave +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^<ext/.*\.h>' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: true +IndentCaseLabels: true +IndentExportBlock: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: true +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: false + AtStartOfFile: false +KeepFormFeed: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MainIncludeChar: Quote +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +OneLineFormatOffRegex: '' +PackConstructorInitializers: NextLine +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakBeforeMemberAccess: 150 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: pb + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: Always +RemoveBracesLLVM: false +RemoveEmptyLinesInUnwrappedLines: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: + Enabled: true + IgnoreCase: false +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterOperatorKeyword: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterNot: false + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TableGenBreakInsideDAGArg: DontBreak +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +WrapNamespaceBodyWithEmptyLines: Leave +... + diff --git a/Makefile b/Makefile @@ -131,3 +131,7 @@ clean: rm -rf $(BIN) $(BIN).1 rm -rf $(OBJ) rm -rf doc/cli_doc.md doc/cli_doc.man doc/license.man + +.PHONY: format +format: + $(FIND) src/ -type f \( -name '*.c' -o -name '*.h' \) -exec clang-format -i {} + diff --git a/src/common/resp.c b/src/common/resp.c @@ -1,14 +1,15 @@ +#include "common/resp.h" + +#include <errno.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdio.h> #include <unistd.h> -#include <errno.h> #include "rxi/log.h" -#include "common/resp.h" -#define MAX_BULK_LEN (256 * 1024) -#define LINE_BUF 4096 +#define MAX_BULK_LEN (256 * 1024) +#define LINE_BUF 4096 static void resp_free_internal(resp_object *o); @@ -21,8 +22,8 @@ static int resp_read_byte_from_buf(const char **buf, size_t *len) { } static int resp_read_line_from_buf(const char **buf, size_t *len, char *out, size_t out_size) { - size_t i = 0; - int prev = -1; + size_t i = 0; + int prev = -1; while (i + 1 < out_size) { if (*len < 1) return -1; int b = (int)(unsigned char)(*buf)[0]; @@ -32,15 +33,15 @@ static int resp_read_line_from_buf(const char **buf, size_t *len, char *out, siz out[i - 1] = '\0'; return 0; } - prev = b; + prev = b; out[i++] = (char)b; } return -1; } resp_object *resp_read_buf(const char *buf, size_t len) { - const char *p = buf; - size_t remaining = len; + const char *p = buf; + size_t remaining = len; int type_c = resp_read_byte_from_buf(&p, &remaining); if (type_c < 0) return NULL; @@ -51,66 +52,111 @@ resp_object *resp_read_buf(const char *buf, size_t len) { switch ((char)type_c) { case '+': o->type = RESPT_SIMPLE; - if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { free(o); return NULL; } + if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { + free(o); + return NULL; + } o->u.s = strdup(line); break; case '-': o->type = RESPT_ERROR; - if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { free(o); return NULL; } + if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { + free(o); + return NULL; + } o->u.s = strdup(line); break; - case ':': { - if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { free(o); return NULL; } - o->type = RESPT_INT; - o->u.i = (long long)strtoll(line, NULL, 10); - break; - } - case '$': { - if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { free(o); return NULL; } - long blen = strtol(line, NULL, 10); - if (blen < 0 || blen > (long)MAX_BULK_LEN) { free(o); return NULL; } - o->type = RESPT_BULK; - if (blen == 0) { - o->u.s = strdup(""); - if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { free(o->u.s); free(o); return NULL; } - } else { - if ((size_t)blen > remaining) { free(o); return NULL; } - o->u.s = malloc((size_t)blen + 1); - if (!o->u.s) { free(o); return NULL; } - memcpy(o->u.s, p, (size_t)blen); - p += blen; - remaining -= (size_t)blen; - o->u.s[blen] = '\0'; - if (remaining < 2) { free(o->u.s); free(o); return NULL; } - if (p[0] != '\r' || p[1] != '\n') { free(o->u.s); free(o); return NULL; } - p += 2; - remaining -= 2; + case ':': + { + if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { + free(o); + return NULL; + } + o->type = RESPT_INT; + o->u.i = (long long)strtoll(line, NULL, 10); + break; } - break; - } - case '*': { - if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { free(o); return NULL; } - long n = strtol(line, NULL, 10); - if (n < 0 || n > 65536) { free(o); return NULL; } - o->type = RESPT_ARRAY; - o->u.arr.n = (size_t)n; - o->u.arr.elem = n ? calloc((size_t)n, sizeof(resp_object)) : NULL; - if (n && !o->u.arr.elem) { free(o); return NULL; } - for (size_t i = 0; i < (size_t)n; i++) { - resp_object *sub = resp_read_buf(p, remaining); - if (!sub) { - for (size_t j = 0; j < i; j++) resp_free_internal(&o->u.arr.elem[j]); - free(o->u.arr.elem); + case '$': + { + if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { + free(o); + return NULL; + } + long blen = strtol(line, NULL, 10); + if (blen < 0 || blen > (long)MAX_BULK_LEN) { free(o); return NULL; } - p += remaining - (sub ? remaining : 0); - remaining = 0; - o->u.arr.elem[i] = *sub; - free(sub); + o->type = RESPT_BULK; + if (blen == 0) { + o->u.s = strdup(""); + if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { + free(o->u.s); + free(o); + return NULL; + } + } else { + if ((size_t)blen > remaining) { + free(o); + return NULL; + } + o->u.s = malloc((size_t)blen + 1); + if (!o->u.s) { + free(o); + return NULL; + } + memcpy(o->u.s, p, (size_t)blen); + p += blen; + remaining -= (size_t)blen; + o->u.s[blen] = '\0'; + if (remaining < 2) { + free(o->u.s); + free(o); + return NULL; + } + if (p[0] != '\r' || p[1] != '\n') { + free(o->u.s); + free(o); + return NULL; + } + p += 2; + remaining -= 2; + } + break; + } + case '*': + { + if (resp_read_line_from_buf(&p, &remaining, line, sizeof(line)) != 0) { + free(o); + return NULL; + } + long n = strtol(line, NULL, 10); + if (n < 0 || n > 65536) { + free(o); + return NULL; + } + o->type = RESPT_ARRAY; + o->u.arr.n = (size_t)n; + o->u.arr.elem = n ? calloc((size_t)n, sizeof(resp_object)) : NULL; + if (n && !o->u.arr.elem) { + free(o); + return NULL; + } + for (size_t i = 0; i < (size_t)n; i++) { + resp_object *sub = resp_read_buf(p, remaining); + if (!sub) { + for (size_t j = 0; j < i; j++) resp_free_internal(&o->u.arr.elem[j]); + free(o->u.arr.elem); + free(o); + return NULL; + } + p += remaining - (sub ? remaining : 0); + remaining = 0; + o->u.arr.elem[i] = *sub; + free(sub); + } + break; } - break; - } default: free(o); return NULL; @@ -120,18 +166,17 @@ resp_object *resp_read_buf(const char *buf, size_t len) { static int resp_read_byte(int fd) { unsigned char c; - ssize_t n = read(fd, &c, 1); + ssize_t n = read(fd, &c, 1); if (n != 1) { - if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) - return -2; + if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) return -2; return -1; } return (int)c; } static int resp_read_line(int fd, char *buf, size_t buf_size) { - size_t i = 0; - int prev = -1; + size_t i = 0; + int prev = -1; while (i + 1 < buf_size) { int b = resp_read_byte(fd); if (b < 0) return -1; @@ -139,7 +184,7 @@ static int resp_read_line(int fd, char *buf, size_t buf_size) { buf[i - 1] = '\0'; return 0; } - prev = b; + prev = b; buf[i++] = (char)b; } return -1; @@ -155,58 +200,100 @@ resp_object *resp_read(int fd) { switch ((char)type_c) { case '+': o->type = RESPT_SIMPLE; - if (resp_read_line(fd, line, sizeof(line)) != 0) { free(o); return NULL; } + if (resp_read_line(fd, line, sizeof(line)) != 0) { + free(o); + return NULL; + } o->u.s = strdup(line); break; case '-': o->type = RESPT_ERROR; - if (resp_read_line(fd, line, sizeof(line)) != 0) { free(o); return NULL; } + if (resp_read_line(fd, line, sizeof(line)) != 0) { + free(o); + return NULL; + } o->u.s = strdup(line); break; - case ':': { - if (resp_read_line(fd, line, sizeof(line)) != 0) { free(o); return NULL; } - o->type = RESPT_INT; - o->u.i = (long long)strtoll(line, NULL, 10); - break; - } - case '$': { - if (resp_read_line(fd, line, sizeof(line)) != 0) { free(o); return NULL; } - long len = strtol(line, NULL, 10); - if (len < 0 || len > (long)MAX_BULK_LEN) { free(o); return NULL; } - o->type = RESPT_BULK; - if (len == 0) { - o->u.s = strdup(""); - if (resp_read_line(fd, line, sizeof(line)) != 0) { free(o->u.s); free(o); return NULL; } - } else { - o->u.s = malloc((size_t)len + 1); - if (!o->u.s) { free(o); return NULL; } - if (read(fd, o->u.s, (size_t)len) != (ssize_t)len) { free(o->u.s); free(o); return NULL; } - o->u.s[len] = '\0'; - if (resp_read_byte(fd) != '\r' || resp_read_byte(fd) != '\n') { free(o->u.s); free(o); return NULL; } + case ':': + { + if (resp_read_line(fd, line, sizeof(line)) != 0) { + free(o); + return NULL; + } + o->type = RESPT_INT; + o->u.i = (long long)strtoll(line, NULL, 10); + break; } - break; - } - case '*': { - if (resp_read_line(fd, line, sizeof(line)) != 0) { free(o); return NULL; } - long n = strtol(line, NULL, 10); - if (n < 0 || n > 65536) { free(o); return NULL; } - o->type = RESPT_ARRAY; - o->u.arr.n = (size_t)n; - o->u.arr.elem = n ? calloc((size_t)n, sizeof(resp_object)) : NULL; - if (n && !o->u.arr.elem) { free(o); return NULL; } - for (size_t i = 0; i < (size_t)n; i++) { - resp_object *sub = resp_read(fd); - if (!sub) { - for (size_t j = 0; j < i; j++) resp_free_internal(&o->u.arr.elem[j]); - free(o->u.arr.elem); + case '$': + { + if (resp_read_line(fd, line, sizeof(line)) != 0) { + free(o); + return NULL; + } + long len = strtol(line, NULL, 10); + if (len < 0 || len > (long)MAX_BULK_LEN) { free(o); return NULL; } - o->u.arr.elem[i] = *sub; - free(sub); + o->type = RESPT_BULK; + if (len == 0) { + o->u.s = strdup(""); + if (resp_read_line(fd, line, sizeof(line)) != 0) { + free(o->u.s); + free(o); + return NULL; + } + } else { + o->u.s = malloc((size_t)len + 1); + if (!o->u.s) { + free(o); + return NULL; + } + if (read(fd, o->u.s, (size_t)len) != (ssize_t)len) { + free(o->u.s); + free(o); + return NULL; + } + o->u.s[len] = '\0'; + if (resp_read_byte(fd) != '\r' || resp_read_byte(fd) != '\n') { + free(o->u.s); + free(o); + return NULL; + } + } + break; + } + case '*': + { + if (resp_read_line(fd, line, sizeof(line)) != 0) { + free(o); + return NULL; + } + long n = strtol(line, NULL, 10); + if (n < 0 || n > 65536) { + free(o); + return NULL; + } + o->type = RESPT_ARRAY; + o->u.arr.n = (size_t)n; + o->u.arr.elem = n ? calloc((size_t)n, sizeof(resp_object)) : NULL; + if (n && !o->u.arr.elem) { + free(o); + return NULL; + } + for (size_t i = 0; i < (size_t)n; i++) { + resp_object *sub = resp_read(fd); + if (!sub) { + for (size_t j = 0; j < i; j++) resp_free_internal(&o->u.arr.elem[j]); + free(o->u.arr.elem); + free(o); + return NULL; + } + o->u.arr.elem[i] = *sub; + free(sub); + } + break; } - break; - } default: free(o); return NULL; @@ -219,8 +306,7 @@ static void resp_free_internal(resp_object *o) { if (o->type == RESPT_SIMPLE || o->type == RESPT_ERROR || o->type == RESPT_BULK) { free(o->u.s); } else if (o->type == RESPT_ARRAY) { - for (size_t i = 0; i < o->u.arr.n; i++) - resp_free_internal(&o->u.arr.elem[i]); + for (size_t i = 0; i < o->u.arr.n; i++) resp_free_internal(&o->u.arr.elem[i]); free(o->u.arr.elem); } } @@ -237,7 +323,10 @@ resp_object *resp_deep_copy(const resp_object *o) { c->type = o->type; if (o->type == RESPT_SIMPLE || o->type == RESPT_ERROR || o->type == RESPT_BULK) { c->u.s = o->u.s ? strdup(o->u.s) : NULL; - if (o->u.s && !c->u.s) { free(c); return NULL; } + if (o->u.s && !c->u.s) { + free(c); + return NULL; + } return c; } if (o->type == RESPT_INT) { @@ -245,9 +334,12 @@ resp_object *resp_deep_copy(const resp_object *o) { return c; } if (o->type == RESPT_ARRAY) { - c->u.arr.n = o->u.arr.n; + c->u.arr.n = o->u.arr.n; c->u.arr.elem = o->u.arr.n ? (resp_object *)calloc(o->u.arr.n, sizeof(resp_object)) : NULL; - if (o->u.arr.n && !c->u.arr.elem) { free(c); return NULL; } + if (o->u.arr.n && !c->u.arr.elem) { + free(c); + return NULL; + } for (size_t i = 0; i < o->u.arr.n; i++) { resp_object *sub = resp_deep_copy(&o->u.arr.elem[i]); if (!sub) { @@ -271,9 +363,8 @@ resp_object *resp_map_get(const resp_object *o, const char *key) { if (n & 1) return NULL; for (size_t i = 0; i < n; i += 2) { const resp_object *k = &o->u.arr.elem[i]; - const char *s = (k->type == RESPT_BULK || k->type == RESPT_SIMPLE) ? k->u.s : NULL; - if (s && strcmp(s, key) == 0 && i + 1 < n) - return (resp_object *)&o->u.arr.elem[i + 1]; + const char *s = (k->type == RESPT_BULK || k->type == RESPT_SIMPLE) ? k->u.s : NULL; + if (s && strcmp(s, key) == 0 && i + 1 < n) return (resp_object *)&o->u.arr.elem[i + 1]; } return NULL; } @@ -281,8 +372,7 @@ resp_object *resp_map_get(const resp_object *o, const char *key) { const char *resp_map_get_string(const resp_object *o, const char *key) { resp_object *val = resp_map_get(o, key); if (!val) return NULL; - if (val->type == RESPT_BULK || val->type == RESPT_SIMPLE) - return val->u.s; + if (val->type == RESPT_BULK || val->type == RESPT_SIMPLE) return val->u.s; return NULL; } @@ -290,7 +380,7 @@ void resp_map_set(resp_object *o, const char *key, resp_object *value) { if (!o || !key || o->type != RESPT_ARRAY) return; for (size_t i = 0; i + 1 < o->u.arr.n; i += 2) { const resp_object *k = &o->u.arr.elem[i]; - const char *s = (k->type == RESPT_BULK || k->type == RESPT_SIMPLE) ? k->u.s : NULL; + const char *s = (k->type == RESPT_BULK || k->type == RESPT_SIMPLE) ? k->u.s : NULL; if (s && strcmp(s, key) == 0 && i + 1 < o->u.arr.n) { resp_free(&o->u.arr.elem[i + 1]); o->u.arr.elem[i + 1] = *value; @@ -307,48 +397,50 @@ static int resp_append_object(char **buf, size_t *cap, size_t *len, const resp_o size_t need = *len + 256; if (o->type == RESPT_BULK || o->type == RESPT_SIMPLE || o->type == RESPT_ERROR) { size_t slen = o->u.s ? strlen(o->u.s) : 0; - need = *len + 32 + slen + 2; + need = *len + 32 + slen + 2; } else if (o->type == RESPT_ARRAY) { need = *len + 32; - for (size_t i = 0; i < o->u.arr.n; i++) - need += 64; + for (size_t i = 0; i < o->u.arr.n; i++) need += 64; } if (need > *cap) { size_t newcap = need + 4096; - char *n = realloc(*buf, newcap); + char *n = realloc(*buf, newcap); if (!n) return -1; *buf = n; *cap = newcap; } switch (o->type) { - case RESPT_SIMPLE: { - const char *s = o->u.s ? o->u.s : ""; - *len += (size_t)snprintf(*buf + *len, *cap - *len, "+%s\r\n", s); - break; - } - case RESPT_ERROR: { - const char *s = o->u.s ? o->u.s : ""; - *len += (size_t)snprintf(*buf + *len, *cap - *len, "-%s\r\n", s); - break; - } + case RESPT_SIMPLE: + { + const char *s = o->u.s ? o->u.s : ""; + *len += (size_t)snprintf(*buf + *len, *cap - *len, "+%s\r\n", s); + break; + } + case RESPT_ERROR: + { + const char *s = o->u.s ? o->u.s : ""; + *len += (size_t)snprintf(*buf + *len, *cap - *len, "-%s\r\n", s); + break; + } case RESPT_INT: *len += (size_t)snprintf(*buf + *len, *cap - *len, ":%lld\r\n", (long long)o->u.i); break; - case RESPT_BULK: { - const char *s = o->u.s ? o->u.s : ""; - size_t slen = strlen(s); - *len += (size_t)snprintf(*buf + *len, *cap - *len, "$%zu\r\n%s\r\n", slen, s); - break; - } - case RESPT_ARRAY: { - size_t n = o->u.arr.n; - *len += (size_t)snprintf(*buf + *len, *cap - *len, "*%zu\r\n", n); - for (size_t i = 0; i < n; i++) { - if (resp_append_object(buf, cap, len, &o->u.arr.elem[i]) != 0) - return -1; + case RESPT_BULK: + { + const char *s = o->u.s ? o->u.s : ""; + size_t slen = strlen(s); + *len += (size_t)snprintf(*buf + *len, *cap - *len, "$%zu\r\n%s\r\n", slen, s); + break; + } + case RESPT_ARRAY: + { + size_t n = o->u.arr.n; + *len += (size_t)snprintf(*buf + *len, *cap - *len, "*%zu\r\n", n); + for (size_t i = 0; i < n; i++) { + if (resp_append_object(buf, cap, len, &o->u.arr.elem[i]) != 0) return -1; + } + break; } - break; - } default: return -1; } @@ -358,10 +450,13 @@ static int resp_append_object(char **buf, size_t *cap, size_t *len, const resp_o int resp_encode_array(int argc, const resp_object *const *argv, char **out_buf, size_t *out_len) { size_t cap = 64; size_t len = 0; - char *buf = malloc(cap); + char *buf = malloc(cap); if (!buf) return -1; len += (size_t)snprintf(buf + len, cap - len, "*%d\r\n", argc); - if (len >= cap) { free(buf); return -1; } + if (len >= cap) { + free(buf); + return -1; + } for (int i = 0; i < argc; i++) { if (resp_append_object(&buf, &cap, &len, argv[i]) != 0) { free(buf); @@ -376,7 +471,7 @@ int resp_encode_array(int argc, const resp_object *const *argv, char **out_buf, int resp_serialize(const resp_object *o, char **out_buf, size_t *out_len) { size_t cap = 64; size_t len = 0; - char *buf = malloc(cap); + char *buf = malloc(cap); if (!buf) return -1; if (resp_append_object(&buf, &cap, &len, o) != 0) { free(buf); @@ -390,8 +485,8 @@ int resp_serialize(const resp_object *o, char **out_buf, size_t *out_len) { resp_object *resp_array_init(void) { resp_object *o = calloc(1, sizeof(resp_object)); if (!o) return NULL; - o->type = RESPT_ARRAY; - o->u.arr.n = 0; + o->type = RESPT_ARRAY; + o->u.arr.n = 0; o->u.arr.elem = NULL; return o; } @@ -400,16 +495,16 @@ resp_object *resp_simple_init(const char *value) { resp_object *o = calloc(1, sizeof(resp_object)); if (!o) return NULL; o->type = RESPT_SIMPLE; - o->u.s = value ? strdup(value) : NULL; + o->u.s = value ? strdup(value) : NULL; return o; } int resp_array_append_obj(resp_object *destination, resp_object *value) { if (!destination || destination->type != RESPT_ARRAY || !value) return -1; - size_t n = destination->u.arr.n; + size_t n = destination->u.arr.n; resp_object *new_elem = realloc(destination->u.arr.elem, (n + 1) * sizeof(resp_object)); if (!new_elem) return -1; - destination->u.arr.elem = new_elem; + destination->u.arr.elem = new_elem; destination->u.arr.elem[n] = *value; destination->u.arr.n++; free(value); @@ -420,8 +515,11 @@ resp_object *resp_error_init(const char *value) { resp_object *o = calloc(1, sizeof(resp_object)); if (!o) return NULL; o->type = RESPT_ERROR; - o->u.s = strdup(value ? value : ""); - if (!o->u.s) { free(o); return NULL; } + o->u.s = strdup(value ? value : ""); + if (!o->u.s) { + free(o); + return NULL; + } return o; } @@ -429,9 +527,16 @@ int resp_array_append_simple(resp_object *destination, const char *str) { resp_object *o = calloc(1, sizeof(resp_object)); if (!o) return -1; o->type = RESPT_SIMPLE; - o->u.s = strdup(str ? str : ""); - if (!o->u.s) { free(o); return -1; } - if (resp_array_append_obj(destination, o) != 0) { free(o->u.s); free(o); return -1; } + o->u.s = strdup(str ? str : ""); + if (!o->u.s) { + free(o); + return -1; + } + if (resp_array_append_obj(destination, o) != 0) { + free(o->u.s); + free(o); + return -1; + } return 0; } @@ -439,9 +544,16 @@ int resp_array_append_error(resp_object *destination, const char *str) { resp_object *o = calloc(1, sizeof(resp_object)); if (!o) return -1; o->type = RESPT_ERROR; - o->u.s = strdup(str ? str : ""); - if (!o->u.s) { free(o); return -1; } - if (resp_array_append_obj(destination, o) != 0) { free(o->u.s); free(o); return -1; } + o->u.s = strdup(str ? str : ""); + if (!o->u.s) { + free(o); + return -1; + } + if (resp_array_append_obj(destination, o) != 0) { + free(o->u.s); + free(o); + return -1; + } return 0; } @@ -449,9 +561,16 @@ int resp_array_append_bulk(resp_object *destination, const char *str) { resp_object *o = calloc(1, sizeof(resp_object)); if (!o) return -1; o->type = RESPT_BULK; - o->u.s = strdup(str ? str : ""); - if (!o->u.s) { free(o); return -1; } - if (resp_array_append_obj(destination, o) != 0) { free(o->u.s); free(o); return -1; } + o->u.s = strdup(str ? str : ""); + if (!o->u.s) { + free(o); + return -1; + } + if (resp_array_append_obj(destination, o) != 0) { + free(o->u.s); + free(o); + return -1; + } return 0; } @@ -459,6 +578,6 @@ int resp_array_append_int(resp_object *destination, long long i) { resp_object *o = malloc(sizeof(resp_object)); if (!o) return -1; o->type = RESPT_INT; - o->u.i = i; + o->u.i = i; return resp_array_append_obj(destination, o); } diff --git a/src/common/resp.h b/src/common/resp.h @@ -3,19 +3,22 @@ #include <stddef.h> -#define RESPT_SIMPLE 0 -#define RESPT_ERROR 1 -#define RESPT_BULK 2 -#define RESPT_INT 3 -#define RESPT_ARRAY 4 +#define RESPT_SIMPLE 0 +#define RESPT_ERROR 1 +#define RESPT_BULK 2 +#define RESPT_INT 3 +#define RESPT_ARRAY 4 typedef struct resp_object resp_object; struct resp_object { int type; union { - char *s; + char *s; long long i; - struct { resp_object *elem; size_t n; } arr; + struct { + resp_object *elem; + size_t n; + } arr; } u; }; @@ -50,7 +53,8 @@ resp_object *resp_array_init(void); /* Returns new array object: caller owns the result, must call resp_free() */ resp_object *resp_simple_init(const char *value); -/* Returns new simple string object: caller owns the result, must call resp_free() */ +/* Returns new simple string object: caller owns the result, must call + * resp_free() */ resp_object *resp_error_init(const char *value); /* Returns new error object: caller owns the result, must call resp_free() */ diff --git a/src/common/scheduler.c b/src/common/scheduler.c @@ -1,27 +1,27 @@ +#include "common/scheduler.h" + #include <stdlib.h> #include <sys/select.h> #include <sys/time.h> -#include "common/scheduler.h" - #ifndef NULL -#define NULL ((void*)0) +#define NULL ((void *)0) #endif -pt_task_t *pt_first = NULL; -fd_set g_select_result; +pt_task_t *pt_first = NULL; +fd_set g_select_result; static fd_set g_want_fds; int sched_create(pt_task_fn fn, void *udata) { if (!fn) return 1; pt_task_t *node = calloc(1, sizeof(pt_task_t)); - node->next = pt_first; - node->func = fn; - node->udata = udata; - node->is_active = 1; - pt_first = node; - + node->next = pt_first; + node->func = fn; + node->udata = udata; + node->is_active = 1; + pt_first = node; + return 0; } @@ -73,9 +73,9 @@ int sched_main(void) { if (!pt_first) return 0; struct timeval tv; - int maxfd; + int maxfd; - for(;;) { + for (;;) { maxfd = -1; for (int fd = 0; fd < FD_SETSIZE; fd++) { if (FD_ISSET(fd, &g_want_fds)) { @@ -84,11 +84,11 @@ int sched_main(void) { } if (maxfd < 0) { - tv.tv_sec = 0; + tv.tv_sec = 0; tv.tv_usec = 100000; select(0, NULL, NULL, NULL, &tv); } else { - tv.tv_sec = 0; + tv.tv_sec = 0; tv.tv_usec = 100000; select(maxfd + 1, &g_want_fds, NULL, NULL, &tv); g_select_result = g_want_fds; diff --git a/src/common/scheduler.h b/src/common/scheduler.h @@ -14,10 +14,10 @@ typedef int (*pt_task_fn)(int64_t timestamp, struct pt_task *task); typedef struct pt_task { struct pt_task *next; - pt_task_fn func; - void *udata; - char is_active; - int maxfd; + pt_task_fn func; + void *udata; + char is_active; + int maxfd; } pt_task_t; int sched_create(pt_task_fn fn, void *udata); @@ -26,4 +26,4 @@ int sched_main(void); int sched_has_data(int *in_fds); -#endif // UDPHOLE_SCHEDULER_H +#endif // UDPHOLE_SCHEDULER_H diff --git a/src/common/socket_util.c b/src/common/socket_util.c @@ -1,19 +1,21 @@ #include "common/socket_util.h" -#include "rxi/log.h" + +#include <arpa/inet.h> +#include <errno.h> #include <fcntl.h> -#include <unistd.h> -#include <string.h> +#include <grp.h> +#include <netdb.h> +#include <netinet/in.h> +#include <pwd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <errno.h> -#include <sys/un.h> #include <sys/stat.h> -#include <pwd.h> -#include <grp.h> +#include <sys/un.h> +#include <unistd.h> + +#include "rxi/log.h" int set_socket_nonblocking(int fd, int nonblock) { int flags = fcntl(fd, F_GETFL, 0); @@ -27,7 +29,7 @@ int set_socket_nonblocking(int fd, int nonblock) { int *tcp_listen(const char *addr, const char *default_host, const char *default_port) { char host[256] = ""; - char port[32] = ""; + char port[32] = ""; if (default_host && default_host[0]) { snprintf(host, sizeof(host), "%s", default_host); @@ -61,11 +63,14 @@ int *tcp_listen(const char *addr, const char *default_host, const char *default_ return NULL; } } else { - int leading_colon = (addr[0] == ':'); - const char *p = leading_colon ? addr + 1 : addr; - int is_port_only = 1; + int leading_colon = (addr[0] == ':'); + const char *p = leading_colon ? addr + 1 : addr; + int is_port_only = 1; for (const char *q = p; *q; q++) { - if (*q < '0' || *q > '9') { is_port_only = 0; break; } + if (*q < '0' || *q > '9') { + is_port_only = 0; + break; + } } const char *colon = strrchr(addr, ':'); @@ -96,9 +101,9 @@ int *tcp_listen(const char *addr, const char *default_host, const char *default_ struct addrinfo hints, *res = NULL; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; if (getaddrinfo(host[0] ? host : NULL, port, &hints, &res) != 0 || !res) { log_error("tcp_listen: getaddrinfo failed for %s:%s", host, port); return NULL; @@ -111,7 +116,7 @@ int *tcp_listen(const char *addr, const char *default_host, const char *default_ } fds[0] = 0; - int listen_all = (host[0] == '\0'); + int listen_all = (host[0] == '\0'); struct addrinfo *p; for (p = res; p; p = p->ai_next) { @@ -154,7 +159,7 @@ int *tcp_listen(const char *addr, const char *default_host, const char *default_ int *udp_recv(const char *addr, const char *default_host, const char *default_port) { char host[256] = ""; - char port[32] = ""; + char port[32] = ""; if (default_host && default_host[0]) { snprintf(host, sizeof(host), "%s", default_host); @@ -188,11 +193,14 @@ int *udp_recv(const char *addr, const char *default_host, const char *default_po return NULL; } } else { - int leading_colon = (addr[0] == ':'); - const char *p = leading_colon ? addr + 1 : addr; - int is_port_only = 1; + int leading_colon = (addr[0] == ':'); + const char *p = leading_colon ? addr + 1 : addr; + int is_port_only = 1; for (const char *q = p; *q; q++) { - if (*q < '0' || *q > '9') { is_port_only = 0; break; } + if (*q < '0' || *q > '9') { + is_port_only = 0; + break; + } } const char *colon = strrchr(addr, ':'); @@ -223,9 +231,9 @@ int *udp_recv(const char *addr, const char *default_host, const char *default_po struct addrinfo hints, *res = NULL; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; if (getaddrinfo(host[0] ? host : NULL, port, &hints, &res) != 0 || !res) { log_error("udp_recv: getaddrinfo failed for %s:%s", host, port); return NULL; @@ -238,7 +246,7 @@ int *udp_recv(const char *addr, const char *default_host, const char *default_po } fds[0] = 0; - int listen_all = (host[0] == '\0'); + int listen_all = (host[0] == '\0'); struct addrinfo *p; for (p = res; p; p = p->ai_next) { @@ -339,8 +347,8 @@ int *unix_listen(const char *path, int sock_type, const char *owner) { } if (owner && owner[0]) { - uid_t uid = -1; - gid_t gid = -1; + uid_t uid = -1; + gid_t gid = -1; char *owner_copy = strdup(owner); if (owner_copy) { char *colon = strchr(owner_copy, ':'); @@ -350,7 +358,7 @@ int *unix_listen(const char *path, int sock_type, const char *owner) { if (colon[0]) { struct passwd *pw = getpwnam(owner_copy); if (pw) { - uid = pw->pw_uid; + uid = pw->pw_uid; struct group *gr = getgrnam(colon); if (gr) { gid = gr->gr_gid; diff --git a/src/common/socket_util.h b/src/common/socket_util.h @@ -1,23 +1,23 @@ #ifndef UDPHOLE_SOCKET_UTIL_H #define UDPHOLE_SOCKET_UTIL_H -/* Set socket blocking (0) or non-blocking (1). Returns 0 on success, -1 on error. */ +/* Set socket blocking (0) or non-blocking (1). Returns 0 on success, -1 on + * error. */ int set_socket_nonblocking(int fd, int nonblock); /* Create listening sockets. Supports dual-stack when host is empty. - * addr can be "port", "host:port", or "[ipv6]:port". Missing host uses default_host, - * missing port uses default_port. - * Returns int array: index 0 = count, index 1+ = socket fds. Caller must free. - * On error returns NULL. */ + * addr can be "port", "host:port", or "[ipv6]:port". Missing host uses + * default_host, missing port uses default_port. Returns int array: index 0 = + * count, index 1+ = socket fds. Caller must free. On error returns NULL. */ int *tcp_listen(const char *addr, const char *default_host, const char *default_port); /* Create UDP receiving sockets. Same semantics as tcp_listen(). */ int *udp_recv(const char *addr, const char *default_host, const char *default_port); -/* Create Unix domain socket. path is the socket path, sock_type is SOCK_DGRAM or SOCK_STREAM. - * owner is optional and can be "user" or "user:group" to set socket ownership. - * Returns int array: index 0 = count, index 1 = socket fd. Caller must free. - * On error returns NULL. */ +/* Create Unix domain socket. path is the socket path, sock_type is SOCK_DGRAM + * or SOCK_STREAM. owner is optional and can be "user" or "user:group" to set + * socket ownership. Returns int array: index 0 = count, index 1 = socket fd. + * Caller must free. On error returns NULL. */ int *unix_listen(const char *path, int sock_type, const char *owner); #endif diff --git a/src/domain/cluster/cluster.c b/src/domain/cluster/cluster.c @@ -1,13 +1,14 @@ +#include "cluster.h" + +#include <math.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdio.h> -#include <math.h> -#include "rxi/log.h" #include "common/resp.h" #include "common/scheduler.h" #include "domain/config.h" -#include "cluster.h" +#include "rxi/log.h" cluster_state_t *cluster_state = NULL; @@ -21,12 +22,12 @@ static int is_session_not_found(resp_object *resp) { } static resp_object *cluster_forward_to_nodes(const char *cmd_str) { - size_t available_count = 0; - cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); + size_t available_count = 0; + cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); if (!available || available_count == 0) { free(available); - return resp_error_init("ERR no available nodes"); + return resp_error_init("ERR no available nodes"); } for (size_t i = 0; i < available_count; i++) { @@ -64,7 +65,7 @@ void cluster_init(void) { cluster_shutdown(); } - cluster_state = calloc(1, sizeof(cluster_state_t)); + cluster_state = calloc(1, sizeof(cluster_state_t)); cluster_state->nodes = cluster_nodes_create(); if (!domain_cfg) return; @@ -79,22 +80,22 @@ void cluster_init(void) { for (size_t i = 0; i < cluster_nodes->u.arr.n; i++) { resp_object *elem = &cluster_nodes->u.arr.elem[i]; if (elem->type != RESPT_BULK || !elem->u.s) continue; - + const char *node_name = elem->u.s; - + char node_section[256]; snprintf(node_section, sizeof(node_section), "cluster:%s", node_name); resp_object *node_sec = resp_map_get(domain_cfg, node_section); - - const char *address = node_sec ? resp_map_get_string(node_sec, "address") : NULL; + + const char *address = node_sec ? resp_map_get_string(node_sec, "address") : NULL; const char *username = node_sec ? resp_map_get_string(node_sec, "username") : NULL; const char *password = node_sec ? resp_map_get_string(node_sec, "password") : NULL; - + if (!address) { log_error("cluster: node '%s' has no address configured", node_name); continue; } - + cluster_node_t *node = calloc(1, sizeof(cluster_node_t)); if (cluster_node_init(node, node_name, address, username, password) == 0) { cluster_nodes_add(cluster_state->nodes, node); @@ -124,7 +125,7 @@ void cluster_shutdown(void) { } static char *serialize_args(resp_object *args) { - char *cmd_str = NULL; + char *cmd_str = NULL; size_t cmd_len = 0; resp_serialize(args, &cmd_str, &cmd_len); return cmd_str; @@ -141,20 +142,20 @@ resp_object *cluster_session_create(const char *cmd, resp_object *args) { return resp_error_init("ERR failed to serialize command"); } - cluster_node_t *selected_node = NULL; - double selected_ratio = -1.0; - resp_object *resp = NULL; + cluster_node_t *selected_node = NULL; + double selected_ratio = -1.0; + resp_object *resp = NULL; for (int attempt = 0; attempt < 10; attempt++) { - size_t available_count = 0; - cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); + size_t available_count = 0; + cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); if (!available || available_count == 0) { free(available); break; } - selected_node = NULL; + selected_node = NULL; selected_ratio = -1.0; for (size_t i = 0; i < available_count; i++) { @@ -168,7 +169,8 @@ resp_object *cluster_session_create(const char *cmd, resp_object *args) { size_t node_session_count = 0; if (count_str) { resp_object *count_resp = NULL; - if (cluster_node_send_command(node, count_str, &count_resp) == 0 && count_resp && count_resp->type == RESPT_INT) { + if (cluster_node_send_command(node, count_str, &count_resp) == 0 && count_resp && + count_resp->type == RESPT_INT) { node_session_count = (size_t)count_resp->u.i; } if (count_resp) resp_free(count_resp); @@ -177,7 +179,7 @@ resp_object *cluster_session_create(const char *cmd, resp_object *args) { double ratio = (double)node_session_count / (double)node->weight; if (selected_node == NULL || ratio < selected_ratio) { - selected_node = node; + selected_node = node; selected_ratio = ratio; } } @@ -213,8 +215,8 @@ resp_object *cluster_session_list(const char *cmd, resp_object *args) { return resp_error_init("ERR cluster not initialized"); } - size_t available_count = 0; - cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); + size_t available_count = 0; + cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); if (!available || available_count == 0) { free(available); @@ -256,12 +258,12 @@ resp_object *cluster_session_info(const char *cmd, resp_object *args) { return resp_error_init("ERR cluster not initialized"); } - size_t available_count = 0; - cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); + size_t available_count = 0; + cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); if (!available || available_count == 0) { free(available); - return resp_error_init("ERR no available nodes"); + return resp_error_init("ERR no available nodes"); } resp_object *cmd_args = resp_array_init(); @@ -447,15 +449,15 @@ resp_object *cluster_session_count(const char *cmd, resp_object *args) { return resp_error_init("ERR cluster not initialized"); } - size_t available_count = 0; - cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); + size_t available_count = 0; + cluster_node_t **available = cluster_nodes_get_available(cluster_state->nodes, &available_count); if (!available || available_count == 0) { free(available); resp_object *res = malloc(sizeof(resp_object)); if (!res) return NULL; res->type = RESPT_INT; - res->u.i = 0; + res->u.i = 0; return res; } @@ -484,7 +486,7 @@ resp_object *cluster_session_count(const char *cmd, resp_object *args) { resp_object *res = malloc(sizeof(resp_object)); if (!res) return NULL; res->type = RESPT_INT; - res->u.i = (long long)total_count; + res->u.i = (long long)total_count; return res; } @@ -498,7 +500,7 @@ resp_object *cluster_system_load(const char *cmd, resp_object *args) { } resp_object *res = resp_array_init(); - char buf[64]; + char buf[64]; resp_array_append_bulk(res, "1min"); snprintf(buf, sizeof(buf), "%.2f", loadavg[0]); diff --git a/src/domain/cluster/cluster.h b/src/domain/cluster/cluster.h @@ -6,7 +6,7 @@ typedef struct { cluster_nodes_t *nodes; - int initialized; + int initialized; } cluster_state_t; extern cluster_state_t *cluster_state; diff --git a/src/domain/cluster/node.c b/src/domain/cluster/node.c @@ -1,29 +1,30 @@ -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> +#include "node.h" + +#include <arpa/inet.h> #include <errno.h> #include <fcntl.h> -#include <sys/socket.h> -#include <sys/un.h> +#include <netdb.h> #include <netinet/in.h> #include <netinet/tcp.h> -#include <arpa/inet.h> -#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> -#include "rxi/log.h" #include "common/resp.h" #include "common/socket_util.h" -#include "node.h" +#include "rxi/log.h" -#define QUERY_TIMEOUT_MS 500 +#define QUERY_TIMEOUT_MS 500 #define HEALTHCHECK_INTERVAL_MS 5000 static int parse_address(const char *address, char **host, int *port, char **unix_path) { if (!address) return -1; if (strncmp(address, "tcp://", 6) == 0) { - const char *hp = address + 6; + const char *hp = address + 6; const char *colon = strchr(hp, ':'); if (!colon) { log_error("cluster: invalid tcp address '%s' (missing port)", address); @@ -31,7 +32,7 @@ static int parse_address(const char *address, char **host, int *port, char **uni } size_t host_len = colon - hp; - *host = malloc(host_len + 1); + *host = malloc(host_len + 1); if (!*host) return -1; memcpy(*host, hp, host_len); (*host)[host_len] = '\0'; @@ -48,8 +49,8 @@ static int parse_address(const char *address, char **host, int *port, char **uni } else if (strncmp(address, "unix://", 7) == 0) { *unix_path = strdup(address + 7); - *host = NULL; - *port = 0; + *host = NULL; + *port = 0; return 0; } @@ -57,11 +58,12 @@ static int parse_address(const char *address, char **host, int *port, char **uni return -1; } -int cluster_node_init(cluster_node_t *node, const char *name, const char *address, const char *username, const char *password) { +int cluster_node_init(cluster_node_t *node, const char *name, const char *address, const char *username, + const char *password) { memset(node, 0, sizeof(*node)); - node->name = strdup(name); - node->address = address ? strdup(address) : NULL; + node->name = strdup(name); + node->address = address ? strdup(address) : NULL; node->username = username ? strdup(username) : NULL; node->password = password ? strdup(password) : NULL; @@ -74,11 +76,11 @@ int cluster_node_init(cluster_node_t *node, const char *name, const char *addres return -1; } - node->fd = -1; - node->available = 0; - node->last_ping = 0; + node->fd = -1; + node->available = 0; + node->last_ping = 0; node->last_check = 0; - node->weight = 1; + node->weight = 1; return 0; } @@ -96,10 +98,10 @@ void cluster_node_free(cluster_node_t *node) { static int connect_tcp(const char *host, int port) { struct addrinfo hints, *res, *res0; - int sockfd, error; + int sockfd, error; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; @@ -135,7 +137,7 @@ static int connect_tcp(const char *host, int port) { static int connect_unix(const char *path) { struct sockaddr_un addr; - int sockfd; + int sockfd; if (strlen(path) >= sizeof(addr.sun_path)) { log_error("cluster: unix socket path too long: %s", path); @@ -178,9 +180,9 @@ int cluster_node_connect(cluster_node_t *node) { log_info("cluster: connected to node '%s' at %s", node->name, node->address); if (node->username && node->password) { - char *cmd_str = NULL; - size_t cmd_len = 0; - resp_object *cmd = resp_array_init(); + char *cmd_str = NULL; + size_t cmd_len = 0; + resp_object *cmd = resp_array_init(); resp_array_append_bulk(cmd, "auth"); resp_array_append_bulk(cmd, node->username); resp_array_append_bulk(cmd, node->password); @@ -215,8 +217,8 @@ void cluster_node_disconnect(cluster_node_t *node) { } static int send_resp_command(int fd, const char *cmd) { - size_t cmd_len = strlen(cmd); - ssize_t n = send(fd, cmd, cmd_len, 0); + size_t cmd_len = strlen(cmd); + ssize_t n = send(fd, cmd, cmd_len, 0); return (n == (ssize_t)cmd_len) ? 0 : -1; } @@ -263,9 +265,9 @@ int cluster_node_healthcheck_pt(int64_t timestamp, struct pt_task *task) { } } - char *cmd_str = NULL; - size_t cmd_len = 0; - resp_object *cmd = resp_array_init(); + char *cmd_str = NULL; + size_t cmd_len = 0; + resp_object *cmd = resp_array_init(); resp_array_append_bulk(cmd, "ping"); resp_serialize(cmd, &cmd_str, &cmd_len); resp_free(cmd); @@ -319,10 +321,9 @@ void cluster_nodes_free(cluster_nodes_t *cnodes) { } int cluster_nodes_add(cluster_nodes_t *cnodes, cluster_node_t *node) { - cluster_node_t **new_nodes = realloc(cnodes->nodes, - sizeof(cluster_node_t *) * (cnodes->nodes_count + 1)); + cluster_node_t **new_nodes = realloc(cnodes->nodes, sizeof(cluster_node_t *) * (cnodes->nodes_count + 1)); if (!new_nodes) return -1; - cnodes->nodes = new_nodes; + cnodes->nodes = new_nodes; cnodes->nodes[cnodes->nodes_count++] = node; return 0; } diff --git a/src/domain/cluster/node.h b/src/domain/cluster/node.h @@ -2,6 +2,7 @@ #define UDPHOLE_CLUSTER_NODE_H #include <stdint.h> + #include "common/resp.h" #include "common/scheduler.h" @@ -9,24 +10,25 @@ typedef struct cluster_node { char *name; char *address; char *host; - int port; + int port; char *unix_path; char *username; char *password; - int weight; + int weight; - int fd; - int available; + int fd; + int available; int64_t last_ping; int64_t last_check; } cluster_node_t; typedef struct { cluster_node_t **nodes; - size_t nodes_count; + size_t nodes_count; } cluster_nodes_t; -int cluster_node_init(cluster_node_t *node, const char *name, const char *address, const char *username, const char *password); +int cluster_node_init(cluster_node_t *node, const char *name, const char *address, const char *username, + const char *password); void cluster_node_free(cluster_node_t *node); diff --git a/src/domain/config.c b/src/domain/config.c @@ -1,8 +1,8 @@ +#include "domain/config.h" + +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdio.h> - -#include "domain/config.h" resp_object *domain_cfg = NULL; diff --git a/src/domain/config.h b/src/domain/config.h @@ -2,6 +2,7 @@ #define UDPHOLE_DOMAIN_CONFIG_H #include <stdint.h> + #include "common/resp.h" extern resp_object *domain_cfg; diff --git a/src/domain/daemon/session.c b/src/domain/daemon/session.c @@ -1,43 +1,44 @@ -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> +#include "session.h" + +#include <arpa/inet.h> #include <errno.h> #include <fcntl.h> -#include <time.h> +#include <netinet/in.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <sys/socket.h> -#include <sys/un.h> #include <sys/stat.h> -#include <netinet/in.h> -#include <arpa/inet.h> +#include <sys/un.h> +#include <time.h> +#include <unistd.h> -#include "rxi/log.h" +#include "common/resp.h" #include "common/scheduler.h" -#include "domain/config.h" #include "common/socket_util.h" -#include "common/resp.h" +#include "domain/config.h" +#include "rxi/log.h" #include "tidwall/hashmap.h" -#include "session.h" static resp_object *get_udphole_cfg(void) { return domain_cfg ? resp_map_get(domain_cfg, "udphole") : NULL; } -#define SESSION_HASH_SIZE 256 -#define BUFFER_SIZE 4096 +#define SESSION_HASH_SIZE 256 +#define BUFFER_SIZE 4096 #define DEFAULT_IDLE_EXPIRY 60 typedef struct socket { - char *socket_id; - int *fds; - int local_port; - int mode; + char *socket_id; + int *fds; + int local_port; + int mode; struct sockaddr_storage remote_addr; - socklen_t remote_addrlen; - int learned_valid; + socklen_t remote_addrlen; + int learned_valid; struct sockaddr_storage learned_addr; - socklen_t learned_addrlen; + socklen_t learned_addrlen; } socket_t; typedef struct forward { @@ -46,22 +47,22 @@ typedef struct forward { } forward_t; typedef struct session { - char *session_id; - time_t idle_expiry; - time_t created; - time_t last_activity; - socket_t **sockets; - size_t sockets_count; - forward_t *forwards; - size_t forwards_count; - int marked_for_deletion; - int *ready_fds; - int *all_fds; + char *session_id; + time_t idle_expiry; + time_t created; + time_t last_activity; + socket_t **sockets; + size_t sockets_count; + forward_t *forwards; + size_t forwards_count; + int marked_for_deletion; + int *ready_fds; + int *all_fds; struct pt_task *task; } session_t; -static session_t **sessions = NULL; -static size_t sessions_count = 0; +static session_t **sessions = NULL; +static size_t sessions_count = 0; static session_t *find_session(const char *session_id) { for (size_t i = 0; i < sessions_count; i++) { @@ -86,11 +87,11 @@ static int alloc_port(void) { resp_object *udphole = get_udphole_cfg(); if (!udphole) return 0; const char *ports_str = resp_map_get_string(udphole, "ports"); - int port_low = 7000, port_high = 7999, port_cur = 7000; + int port_low = 7000, port_high = 7999, port_cur = 7000; if (ports_str) sscanf(ports_str, "%d-%d", &port_low, &port_high); const char *port_cur_str = resp_map_get_string(udphole, "_port_cur"); if (port_cur_str) port_cur = atoi(port_cur_str); - + for (int i = 0; i < port_high - port_low; i++) { int port = port_cur + i; if (port > port_high) port = port_low; @@ -99,9 +100,9 @@ static int alloc_port(void) { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; + addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); + addr.sin_port = htons(port); int udp_fd = socket(AF_INET, SOCK_DGRAM, 0); if (udp_fd < 0) continue; @@ -120,16 +121,16 @@ static int parse_ip_addr(const char *ip_str, int port, struct sockaddr_storage * struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; if (inet_pton(AF_INET, ip_str, &addr4->sin_addr) == 1) { addr4->sin_family = AF_INET; - addr4->sin_port = htons(port); - *addrlen = sizeof(*addr4); + addr4->sin_port = htons(port); + *addrlen = sizeof(*addr4); return 0; } struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; if (inet_pton(AF_INET6, ip_str, &addr6->sin6_addr) == 1) { addr6->sin6_family = AF_INET6; - addr6->sin6_port = htons(port); - *addrlen = sizeof(*addr6); + addr6->sin6_port = htons(port); + *addrlen = sizeof(*addr6); return 0; } @@ -192,12 +193,12 @@ static session_t *create_session(const char *session_id, int idle_expiry) { session_t *s = calloc(1, sizeof(*s)); if (!s) return NULL; - s->session_id = strdup(session_id); - s->created = time(NULL); + s->session_id = strdup(session_id); + s->created = time(NULL); s->last_activity = s->created; - s->idle_expiry = idle_expiry > 0 ? idle_expiry : DEFAULT_IDLE_EXPIRY; + s->idle_expiry = idle_expiry > 0 ? idle_expiry : DEFAULT_IDLE_EXPIRY; - sessions = realloc(sessions, sizeof(session_t *) * (sessions_count + 1)); + sessions = realloc(sessions, sizeof(session_t *) * (sessions_count + 1)); sessions[sessions_count++] = s; return s; @@ -211,8 +212,8 @@ static void cleanup_expired_sessions(void) { session_t *s = sessions[i]; if (!s) continue; if (now - s->last_activity > s->idle_expiry) { - log_debug("udphole: session %s expired (idle %ld > expiry %ld)", - s->session_id, (long)(now - s->last_activity), (long)s->idle_expiry); + log_debug("udphole: session %s expired (idle %ld > expiry %ld)", s->session_id, (long)(now - s->last_activity), + (long)s->idle_expiry); destroy_session(s); } } @@ -220,8 +221,7 @@ static void cleanup_expired_sessions(void) { static int add_forward(session_t *s, const char *src_id, const char *dst_id) { for (size_t i = 0; i < s->forwards_count; i++) { - if (strcmp(s->forwards[i].src_socket_id, src_id) == 0 && - strcmp(s->forwards[i].dst_socket_id, dst_id) == 0) { + if (strcmp(s->forwards[i].src_socket_id, src_id) == 0 && strcmp(s->forwards[i].dst_socket_id, dst_id) == 0) { return 0; } } @@ -239,8 +239,7 @@ static int add_forward(session_t *s, const char *src_id, const char *dst_id) { static int remove_forward(session_t *s, const char *src_id, const char *dst_id) { for (size_t i = 0; i < s->forwards_count; i++) { - if (strcmp(s->forwards[i].src_socket_id, src_id) == 0 && - strcmp(s->forwards[i].dst_socket_id, dst_id) == 0) { + if (strcmp(s->forwards[i].src_socket_id, src_id) == 0 && strcmp(s->forwards[i].dst_socket_id, dst_id) == 0) { free(s->forwards[i].src_socket_id); free(s->forwards[i].dst_socket_id); for (size_t j = i; j < s->forwards_count - 1; j++) { @@ -278,22 +277,20 @@ static socket_t *create_listen_socket(session_t *sess, const char *socket_id) { return NULL; } - sock->socket_id = strdup(socket_id); - sock->fds = fds; - sock->local_port = port; - sock->mode = 0; + sock->socket_id = strdup(socket_id); + sock->fds = fds; + sock->local_port = port; + sock->mode = 0; sock->learned_valid = 0; - sess->sockets = realloc(sess->sockets, sizeof(socket_t *) * (sess->sockets_count + 1)); + sess->sockets = realloc(sess->sockets, sizeof(socket_t *) * (sess->sockets_count + 1)); sess->sockets[sess->sockets_count++] = sock; - log_debug("udphole: created listen socket %s in session %s on port %d", - socket_id, sess->session_id, port); + log_debug("udphole: created listen socket %s in session %s on port %d", socket_id, sess->session_id, port); return sock; } -static socket_t *create_connect_socket(session_t *sess, const char *socket_id, - const char *ip, int port) { +static socket_t *create_connect_socket(session_t *sess, const char *socket_id, const char *ip, int port) { socket_t *existing = find_socket(sess, socket_id); if (existing) return existing; @@ -313,7 +310,7 @@ static socket_t *create_connect_socket(session_t *sess, const char *socket_id, } struct sockaddr_storage remote_addr; - socklen_t remote_addrlen; + socklen_t remote_addrlen; if (parse_ip_addr(ip, port, &remote_addr, &remote_addrlen) != 0) { log_error("udphole: invalid remote address %s:%d", ip, port); free(fds); @@ -326,19 +323,19 @@ static socket_t *create_connect_socket(session_t *sess, const char *socket_id, return NULL; } - sock->socket_id = strdup(socket_id); - sock->fds = fds; - sock->local_port = local_port; - sock->mode = 1; - sock->remote_addr = remote_addr; + sock->socket_id = strdup(socket_id); + sock->fds = fds; + sock->local_port = local_port; + sock->mode = 1; + sock->remote_addr = remote_addr; sock->remote_addrlen = remote_addrlen; - sock->learned_valid = 0; + sock->learned_valid = 0; - sess->sockets = realloc(sess->sockets, sizeof(socket_t *) * (sess->sockets_count + 1)); + sess->sockets = realloc(sess->sockets, sizeof(socket_t *) * (sess->sockets_count + 1)); sess->sockets[sess->sockets_count++] = sock; - log_debug("udphole: created connect socket %s in session %s on port %d -> %s:%d", - socket_id, sess->session_id, local_port, ip, port); + log_debug("udphole: created connect socket %s in session %s on port %d -> %s:%d", socket_id, sess->session_id, + local_port, ip, port); return sock; } @@ -354,7 +351,7 @@ static int destroy_socket(session_t *sess, const char *socket_id) { } free_socket(sock); - for (size_t i = 0; i < sess->forwards_count; ) { + for (size_t i = 0; i < sess->forwards_count;) { if (strcmp(sess->forwards[i].src_socket_id, socket_id) == 0 || strcmp(sess->forwards[i].dst_socket_id, socket_id) == 0) { free(sess->forwards[i].src_socket_id); @@ -420,21 +417,19 @@ int session_pt(int64_t timestamp, struct pt_task *task) { return SCHED_RUNNING; } - char buffer[BUFFER_SIZE]; + char buffer[BUFFER_SIZE]; socket_t *src_sock = find_socket_by_fd(s, ready_fd); if (!src_sock) { return SCHED_RUNNING; } struct sockaddr_storage from_addr; - socklen_t from_len = sizeof(from_addr); - ssize_t n = recvfrom(ready_fd, buffer, sizeof(buffer) - 1, 0, - (struct sockaddr *)&from_addr, &from_len); + socklen_t from_len = sizeof(from_addr); + ssize_t n = recvfrom(ready_fd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&from_addr, &from_len); if (n <= 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { - log_warn("udphole: recvfrom error on socket %s: %s", - src_sock->socket_id, strerror(errno)); + log_warn("udphole: recvfrom error on socket %s: %s", src_sock->socket_id, strerror(errno)); } return SCHED_RUNNING; } @@ -442,9 +437,9 @@ int session_pt(int64_t timestamp, struct pt_task *task) { s->last_activity = time(NULL); if (src_sock->mode == 0 && !src_sock->learned_valid) { - src_sock->learned_addr = from_addr; + src_sock->learned_addr = from_addr; src_sock->learned_addrlen = from_len; - src_sock->learned_valid = 1; + src_sock->learned_valid = 1; log_debug("udphole: socket %s learned remote address", src_sock->socket_id); } @@ -456,23 +451,22 @@ int session_pt(int64_t timestamp, struct pt_task *task) { socket_t *dst_sock = find_socket(s, s->forwards[i].dst_socket_id); if (!dst_sock || !dst_sock->fds || dst_sock->fds[0] == 0) continue; - struct sockaddr *dest_addr = NULL; - socklen_t dest_addrlen = 0; + struct sockaddr *dest_addr = NULL; + socklen_t dest_addrlen = 0; if (dst_sock->mode == 1) { - dest_addr = (struct sockaddr *)&dst_sock->remote_addr; + dest_addr = (struct sockaddr *)&dst_sock->remote_addr; dest_addrlen = dst_sock->remote_addrlen; } else if (dst_sock->learned_valid) { - dest_addr = (struct sockaddr *)&dst_sock->learned_addr; + dest_addr = (struct sockaddr *)&dst_sock->learned_addr; dest_addrlen = dst_sock->learned_addrlen; } if (dest_addr && dest_addrlen > 0) { - int dst_fd = dst_sock->fds[1]; - ssize_t sent = sendto(dst_fd, buffer, n, 0, dest_addr, dest_addrlen); + int dst_fd = dst_sock->fds[1]; + ssize_t sent = sendto(dst_fd, buffer, n, 0, dest_addr, dest_addrlen); if (sent < 0) { - log_warn("udphole: forward failed %s -> %s: %s", - src_sock->socket_id, dst_sock->socket_id, strerror(errno)); + log_warn("udphole: forward failed %s -> %s: %s", src_sock->socket_id, dst_sock->socket_id, strerror(errno)); } } } @@ -654,7 +648,7 @@ resp_object *domain_socket_create_listen(const char *cmd, resp_object *args) { } const char *session_id = NULL; - const char *socket_id = NULL; + const char *socket_id = NULL; if (args->u.arr.elem[1].type == RESPT_BULK) { session_id = args->u.arr.elem[1].u.s; @@ -684,8 +678,8 @@ resp_object *domain_socket_create_listen(const char *cmd, resp_object *args) { resp_object *res = resp_array_init(); resp_array_append_int(res, sock->local_port); - resp_object *udphole = get_udphole_cfg(); - const char *advertise = udphole ? resp_map_get_string(udphole, "advertise") : NULL; + resp_object *udphole = get_udphole_cfg(); + const char *advertise = udphole ? resp_map_get_string(udphole, "advertise") : NULL; resp_array_append_bulk(res, advertise ? advertise : ""); return res; } @@ -699,9 +693,9 @@ resp_object *domain_socket_create_connect(const char *cmd, resp_object *args) { } const char *session_id = NULL; - const char *socket_id = NULL; - const char *ip = NULL; - const char *port_str = NULL; + const char *socket_id = NULL; + const char *ip = NULL; + const char *port_str = NULL; if (args->u.arr.elem[1].type == RESPT_BULK) { session_id = args->u.arr.elem[1].u.s; @@ -739,8 +733,8 @@ resp_object *domain_socket_create_connect(const char *cmd, resp_object *args) { resp_object *res = resp_array_init(); resp_array_append_int(res, sock->local_port); - resp_object *udphole = get_udphole_cfg(); - const char *advertise = udphole ? resp_map_get_string(udphole, "advertise") : NULL; + resp_object *udphole = get_udphole_cfg(); + const char *advertise = udphole ? resp_map_get_string(udphole, "advertise") : NULL; resp_array_append_bulk(res, advertise ? advertise : ""); return res; } @@ -754,7 +748,7 @@ resp_object *domain_socket_destroy(const char *cmd, resp_object *args) { } const char *session_id = NULL; - const char *socket_id = NULL; + const char *socket_id = NULL; if (args->u.arr.elem[1].type == RESPT_BULK) { session_id = args->u.arr.elem[1].u.s; @@ -826,7 +820,7 @@ resp_object *domain_forward_create(const char *cmd, resp_object *args) { return err; } - const char *session_id = NULL; + const char *session_id = NULL; const char *src_socket_id = NULL; const char *dst_socket_id = NULL; @@ -886,7 +880,7 @@ resp_object *domain_forward_destroy(const char *cmd, resp_object *args) { return err; } - const char *session_id = NULL; + const char *session_id = NULL; const char *src_socket_id = NULL; const char *dst_socket_id = NULL; @@ -934,7 +928,7 @@ resp_object *domain_system_load(const char *cmd, resp_object *args) { } resp_object *res = resp_array_init(); - char buf[64]; + char buf[64]; resp_array_append_bulk(res, "1min"); snprintf(buf, sizeof(buf), "%.2f", loadavg[0]); @@ -965,7 +959,7 @@ resp_object *domain_session_count(const char *cmd, resp_object *args) { resp_object *res = malloc(sizeof(resp_object)); if (!res) return NULL; res->type = RESPT_INT; - res->u.i = (long long)count; + res->u.i = (long long)count; return res; } @@ -979,7 +973,7 @@ int session_manager_pt(int64_t timestamp, struct pt_task *task) { if (!udata->initialized) { const char *ports_str = resp_map_get_string(udphole, "ports"); - int port_low = 7000, port_high = 7999; + int port_low = 7000, port_high = 7999; if (ports_str) sscanf(ports_str, "%d-%d", &port_low, &port_high); log_info("udphole: manager started with port range %d-%d", port_low, port_high); udata->initialized = 1; @@ -991,4 +985,4 @@ int session_manager_pt(int64_t timestamp, struct pt_task *task) { } return SCHED_RUNNING; -} -\ No newline at end of file +} diff --git a/src/domain/daemon/session.h b/src/domain/daemon/session.h @@ -3,12 +3,12 @@ #include <stdint.h> -#include "common/scheduler.h" #include "common/resp.h" +#include "common/scheduler.h" typedef struct { int64_t last_cleanup; - int initialized; + int initialized; } session_manager_udata_t; int session_manager_pt(int64_t timestamp, struct pt_task *task); diff --git a/src/infrastructure/config.c b/src/infrastructure/config.c @@ -1,10 +1,12 @@ +#include "infrastructure/config.h" + #include <stdlib.h> #include <string.h> + #include "benhoyt/inih.h" -#include "rxi/log.h" -#include "infrastructure/config.h" #include "common/resp.h" #include "domain/config.h" +#include "rxi/log.h" resp_object *pending_cfg = NULL; @@ -19,7 +21,7 @@ static int config_handler(void *user, const char *section, const char *name, con resp_map_set(cfg, section, sec); sec = resp_map_get(cfg, section); } - + if (strcmp(name, "cluster") == 0) { resp_object *arr = resp_map_get(sec, "cluster"); if (!arr) { @@ -44,8 +46,8 @@ void config_init(void) { pending_cfg = resp_array_init(); config_load(NULL, config_get_path()); resp_object *old = domain_cfg; - domain_cfg = pending_cfg; - pending_cfg = NULL; + domain_cfg = pending_cfg; + pending_cfg = NULL; if (old) resp_free(old); } @@ -67,14 +69,14 @@ int config_reload(void) { int r = config_load(NULL, config_get_path()); if (r < 0) return -1; resp_object *old = domain_cfg; - domain_cfg = pending_cfg; - pending_cfg = NULL; + domain_cfg = pending_cfg; + pending_cfg = NULL; if (old) resp_free(old); return 0; } void config_set_path(const char *path) { - if (stored_config_path) free((void*)stored_config_path); + if (stored_config_path) free((void *)stored_config_path); stored_config_path = path ? strdup(path) : NULL; } diff --git a/src/infrastructure/config.h b/src/infrastructure/config.h @@ -5,10 +5,10 @@ extern resp_object *pending_cfg; -void config_init(void); -int config_load(resp_object *cfg, const char *path); -int config_reload(void); -void config_set_path(const char *path); +void config_init(void); +int config_load(resp_object *cfg, const char *path); +int config_reload(void); +void config_set_path(const char *path); const char *config_get_path(void); -#endif -\ No newline at end of file +#endif diff --git a/src/interface/api/server.c b/src/interface/api/server.c @@ -6,67 +6,68 @@ * Runs as a protothread in the main select() loop. */ -#include <stdlib.h> -#include <string.h> -#include <stdio.h> +#include "interface/api/server.h" + +#include <arpa/inet.h> #include <ctype.h> -#include <unistd.h> #include <errno.h> #include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <sys/socket.h> #include <sys/types.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> +#include <unistd.h> -#include "rxi/log.h" -#include "tidwall/hashmap.h" +#include "common/resp.h" #include "common/scheduler.h" #include "common/socket_util.h" -#include "infrastructure/config.h" #include "domain/config.h" -#include "interface/api/server.h" -#include "common/resp.h" +#include "infrastructure/config.h" +#include "rxi/log.h" +#include "tidwall/hashmap.h" int api_client_pt(int64_t timestamp, struct pt_task *task); -#define API_MAX_CLIENTS 8 -#define READ_BUF_SIZE 4096 -#define WRITE_BUF_INIT 4096 -#define MAX_ARGS 32 +#define API_MAX_CLIENTS 8 +#define READ_BUF_SIZE 4096 +#define WRITE_BUF_INIT 4096 +#define MAX_ARGS 32 struct api_client_state { - int fd; - int *fds; - int *ready_fds; - int ready_fd; - char *username; - char rbuf[READ_BUF_SIZE]; - size_t rlen; - char *wbuf; - size_t wlen; - size_t wcap; + int fd; + int *fds; + int *ready_fds; + int ready_fd; + char *username; + char rbuf[READ_BUF_SIZE]; + size_t rlen; + char *wbuf; + size_t wlen; + size_t wcap; }; typedef struct api_client_state api_client_t; typedef struct { - const char *name; - char (*func)(api_client_t *c, char **args, int nargs); + const char *name; + char (*func)(api_client_t *c, char **args, int nargs); } api_cmd_entry; typedef struct { - const char *name; + const char *name; domain_cmd_fn func; } domain_cmd_entry; -static char *current_listen = NULL; -static struct hashmap *cmd_map = NULL; -static struct hashmap *domain_cmd_map = NULL; +static char *current_listen = NULL; +static struct hashmap *cmd_map = NULL; +static struct hashmap *domain_cmd_map = NULL; typedef struct { - int *server_fds; - int *ready_fds; + int *server_fds; + int *ready_fds; } api_server_udata_t; bool api_write_raw(api_client_t *c, const void *data, size_t len) { @@ -118,7 +119,7 @@ bool api_write_array(api_client_t *c, size_t nitems) { bool api_write_bulk_cstr(api_client_t *c, const char *s) { if (!s) return api_write_nil(c); size_t len = strlen(s); - char prefix[32]; + char prefix[32]; snprintf(prefix, sizeof(prefix), "$%zu\r\n", len); if (!api_write_cstr(c, prefix)) return false; if (!api_write_raw(c, s, len)) return false; @@ -139,7 +140,7 @@ static void client_close(api_client_t *c) { free(c->wbuf); c->wbuf = NULL; c->wlen = c->wcap = 0; - c->rlen = 0; + c->rlen = 0; free(c->username); c->username = NULL; } @@ -148,8 +149,7 @@ static void client_flush(api_client_t *c) { if (c->fd < 0 || c->wlen == 0) return; ssize_t n = send(c->fd, c->wbuf, c->wlen, 0); if (n > 0) { - if ((size_t)n < c->wlen) - memmove(c->wbuf, c->wbuf + n, c->wlen - (size_t)n); + if ((size_t)n < c->wlen) memmove(c->wbuf, c->wbuf + n, c->wlen - (size_t)n); c->wlen -= (size_t)n; } else if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { client_close(c); @@ -158,8 +158,7 @@ static void client_flush(api_client_t *c) { static bool permit_matches(const char *pattern, const char *cmd) { size_t plen = strlen(pattern); - if (plen == 1 && pattern[0] == '*') - return true; + if (plen == 1 && pattern[0] == '*') return true; if (plen >= 2 && pattern[plen - 1] == '*') { return strncasecmp(pattern, cmd, plen - 1) == 0; } @@ -167,7 +166,7 @@ static bool permit_matches(const char *pattern, const char *cmd) { } static bool user_has_permit(api_client_t *c, const char *cmd) { - char section[128]; + char section[128]; const char *uname = (c->username && c->username[0]) ? c->username : "*"; snprintf(section, sizeof(section), "user:%s", uname); resp_object *sec = resp_map_get(domain_cfg, section); @@ -180,8 +179,7 @@ static bool user_has_permit(api_client_t *c, const char *cmd) { if (val->type == RESPT_ARRAY) { for (size_t j = 0; j < val->u.arr.n; j++) { resp_object *p = &val->u.arr.elem[j]; - if (p->type == RESPT_BULK && p->u.s && permit_matches(p->u.s, cmd)) - return true; + if (p->type == RESPT_BULK && p->u.s && permit_matches(p->u.s, cmd)) return true; } } else if (val->type == RESPT_BULK && val->u.s && permit_matches(val->u.s, cmd)) { return true; @@ -201,8 +199,7 @@ static bool user_has_permit(api_client_t *c, const char *cmd) { if (val->type == RESPT_ARRAY) { for (size_t j = 0; j < val->u.arr.n; j++) { resp_object *p = &val->u.arr.elem[j]; - if (p->type == RESPT_BULK && p->u.s && permit_matches(p->u.s, cmd)) - return true; + if (p->type == RESPT_BULK && p->u.s && permit_matches(p->u.s, cmd)) return true; } } else if (val->type == RESPT_BULK && val->u.s && permit_matches(val->u.s, cmd)) { return true; @@ -228,9 +225,8 @@ static int cmd_compare(const void *a, const void *b, void *udata) { } void api_register_cmd(const char *name, char (*func)(api_client_t *, char **, int)) { - if (!cmd_map) - cmd_map = hashmap_new(sizeof(api_cmd_entry), 0, 0, 0, cmd_hash, cmd_compare, NULL, NULL); - hashmap_set(cmd_map, &(api_cmd_entry){ .name = name, .func = func }); + if (!cmd_map) cmd_map = hashmap_new(sizeof(api_cmd_entry), 0, 0, 0, cmd_hash, cmd_compare, NULL, NULL); + hashmap_set(cmd_map, &(api_cmd_entry){.name = name, .func = func}); log_trace("api: registered command '%s'", name); } @@ -249,21 +245,23 @@ static int domain_cmd_compare(const void *a, const void *b, void *udata) { void api_register_domain_cmd(const char *name, domain_cmd_fn func) { if (!domain_cmd_map) domain_cmd_map = hashmap_new(sizeof(domain_cmd_entry), 0, 0, 0, domain_cmd_hash, domain_cmd_compare, NULL, NULL); - hashmap_set(domain_cmd_map, &(domain_cmd_entry){ .name = name, .func = func }); + hashmap_set(domain_cmd_map, &(domain_cmd_entry){.name = name, .func = func}); log_trace("api: registered domain command '%s'", name); } static char cmdAUTH(api_client_t *c, char **args, int nargs) { if (nargs != 3) { - api_write_err(c, "wrong number of arguments for 'auth' command (AUTH username password)"); + api_write_err(c, + "wrong number of arguments for 'auth' command (AUTH " + "username password)"); return 1; } const char *uname = args[1]; const char *pass = args[2]; - char section[128]; + char section[128]; snprintf(section, sizeof(section), "user:%s", uname); - resp_object *sec = resp_map_get(domain_cfg, section); - const char *secret = sec ? resp_map_get_string(sec, "secret") : NULL; + resp_object *sec = resp_map_get(domain_cfg, section); + const char *secret = sec ? resp_map_get_string(sec, "secret") : NULL; if (secret && pass && strcmp(secret, pass) == 0) { free(c->username); c->username = strdup(uname); @@ -277,15 +275,14 @@ static char cmdAUTH(api_client_t *c, char **args, int nargs) { static char cmdPING(api_client_t *c, char **args, int nargs) { (void)args; - if (nargs == 1) - return api_write_cstr(c, "+PONG\r\n") ? 1 : 0; - if (nargs == 2) - return api_write_bulk_cstr(c, args[1]) ? 1 : 0; + if (nargs == 1) return api_write_cstr(c, "+PONG\r\n") ? 1 : 0; + if (nargs == 2) return api_write_bulk_cstr(c, args[1]) ? 1 : 0; return api_write_err(c, "wrong number of arguments for 'ping' command") ? 1 : 0; } static char cmdQUIT(api_client_t *c, char **args, int nargs) { - (void)args; (void)nargs; + (void)args; + (void)nargs; api_write_ok(c); return 0; } @@ -294,23 +291,24 @@ static bool is_builtin(const char *name); static char cmdCOMMAND(api_client_t *c, char **args, int nargs) { (void)args; - if (!cmd_map && !domain_cmd_map) - return api_write_array(c, 0) ? 1 : 0; + if (!cmd_map && !domain_cmd_map) return api_write_array(c, 0) ? 1 : 0; resp_object *result = resp_array_init(); if (!result) return 0; if (domain_cmd_map) { size_t iter = 0; - void *item; + void *item; while (hashmap_iter(domain_cmd_map, &iter, &item)) { const domain_cmd_entry *e = item; - if (!user_has_permit(c, e->name)) - continue; + if (!user_has_permit(c, e->name)) continue; resp_array_append_bulk(result, e->name); resp_object *meta = resp_array_init(); - if (!meta) { resp_free(result); return 0; } + if (!meta) { + resp_free(result); + return 0; + } resp_array_append_bulk(meta, "summary"); resp_array_append_bulk(meta, "UDP hole proxy command"); resp_array_append_obj(result, meta); @@ -319,22 +317,24 @@ static char cmdCOMMAND(api_client_t *c, char **args, int nargs) { if (cmd_map) { size_t iter = 0; - void *item; + void *item; while (hashmap_iter(cmd_map, &iter, &item)) { const api_cmd_entry *e = item; - if (!is_builtin(e->name) && !user_has_permit(c, e->name)) - continue; + if (!is_builtin(e->name) && !user_has_permit(c, e->name)) continue; resp_array_append_bulk(result, e->name); resp_object *meta = resp_array_init(); - if (!meta) { resp_free(result); return 0; } + if (!meta) { + resp_free(result); + return 0; + } resp_array_append_bulk(meta, "summary"); resp_array_append_bulk(meta, "UDP hole proxy command"); resp_array_append_obj(result, meta); } } - char *out_buf = NULL; + char *out_buf = NULL; size_t out_len = 0; if (resp_serialize(result, &out_buf, &out_len) != 0 || !out_buf) { resp_free(result); @@ -348,16 +348,14 @@ static char cmdCOMMAND(api_client_t *c, char **args, int nargs) { } static void init_builtins(void) { - api_register_cmd("auth", cmdAUTH); - api_register_cmd("ping", cmdPING); - api_register_cmd("quit", cmdQUIT); + api_register_cmd("auth", cmdAUTH); + api_register_cmd("ping", cmdPING); + api_register_cmd("quit", cmdQUIT); api_register_cmd("command", cmdCOMMAND); } static bool is_builtin(const char *name) { - return (strcasecmp(name, "auth") == 0 || - strcasecmp(name, "ping") == 0 || - strcasecmp(name, "quit") == 0 || + return (strcasecmp(name, "auth") == 0 || strcasecmp(name, "ping") == 0 || strcasecmp(name, "quit") == 0 || strcasecmp(name, "command") == 0); } @@ -366,7 +364,7 @@ static void dispatch_command(api_client_t *c, char **args, int nargs) { for (char *p = args[0]; *p; p++) *p = (char)tolower((unsigned char)*p); - const domain_cmd_entry *dcmd = hashmap_get(domain_cmd_map, &(domain_cmd_entry){ .name = args[0] }); + const domain_cmd_entry *dcmd = hashmap_get(domain_cmd_map, &(domain_cmd_entry){.name = args[0]}); if (dcmd) { if (!is_builtin(args[0])) { if (!user_has_permit(c, args[0])) { @@ -390,7 +388,7 @@ static void dispatch_command(api_client_t *c, char **args, int nargs) { return; } - char *out_buf = NULL; + char *out_buf = NULL; size_t out_len = 0; if (resp_serialize(result, &out_buf, &out_len) != 0 || !out_buf) { resp_free(result); @@ -404,7 +402,7 @@ static void dispatch_command(api_client_t *c, char **args, int nargs) { return; } - const api_cmd_entry *cmd = hashmap_get(cmd_map, &(api_cmd_entry){ .name = args[0] }); + const api_cmd_entry *cmd = hashmap_get(cmd_map, &(api_cmd_entry){.name = args[0]}); if (!cmd) { api_write_err(c, "unknown command"); return; @@ -425,17 +423,17 @@ static void dispatch_command(api_client_t *c, char **args, int nargs) { } static int *create_listen_socket(const char *listen_addr) { - const char *default_port = "6379"; - resp_object *api_sec = resp_map_get(domain_cfg, "udphole"); + const char *default_port = "6379"; + resp_object *api_sec = resp_map_get(domain_cfg, "udphole"); if (api_sec) { const char *cfg_port = resp_map_get_string(api_sec, "port"); if (cfg_port && cfg_port[0]) default_port = cfg_port; } if (listen_addr && strncmp(listen_addr, "unix://", 7) == 0) { - const char *socket_path = listen_addr + 7; + const char *socket_path = listen_addr + 7; const char *socket_owner = api_sec ? resp_map_get_string(api_sec, "socket_owner") : NULL; - int *fds = unix_listen(socket_path, SOCK_STREAM, socket_owner); + int *fds = unix_listen(socket_path, SOCK_STREAM, socket_owner); if (!fds) { return NULL; } @@ -453,8 +451,8 @@ static int *create_listen_socket(const char *listen_addr) { static void handle_accept(int ready_fd) { struct sockaddr_storage addr; - socklen_t addrlen = sizeof(addr); - int fd = accept(ready_fd, (struct sockaddr *)&addr, &addrlen); + socklen_t addrlen = sizeof(addr); + int fd = accept(ready_fd, (struct sockaddr *)&addr, &addrlen); if (fd < 0) return; set_socket_nonblocking(fd, 1); @@ -484,8 +482,8 @@ int api_server_pt(int64_t timestamp, struct pt_task *task) { } if (udata->server_fds == NULL) { - resp_object *api_sec = resp_map_get(domain_cfg, "udphole"); - const char *listen_str = api_sec ? resp_map_get_string(api_sec, "listen") : NULL; + resp_object *api_sec = resp_map_get(domain_cfg, "udphole"); + const char *listen_str = api_sec ? resp_map_get_string(api_sec, "listen") : NULL; if (!listen_str || !listen_str[0]) { return SCHED_RUNNING; @@ -538,7 +536,7 @@ int api_client_pt(int64_t timestamp, struct pt_task *task) { return SCHED_RUNNING; } - char buf[1]; + char buf[1]; ssize_t n = recv(state->fd, buf, 1, MSG_PEEK); if (n <= 0) { goto cleanup; @@ -560,12 +558,12 @@ int api_client_pt(int64_t timestamp, struct pt_task *task) { } char *args[MAX_ARGS]; - int nargs = 0; + int nargs = 0; for (size_t i = 0; i < cmd->u.arr.n && nargs < MAX_ARGS; i++) { resp_object *elem = &cmd->u.arr.elem[i]; if (elem->type == RESPT_BULK && elem->u.s) { args[nargs++] = elem->u.s; - elem->u.s = NULL; + elem->u.s = NULL; } else if (elem->type == RESPT_SIMPLE) { args[nargs++] = elem->u.s ? elem->u.s : ""; } @@ -597,4 +595,4 @@ cleanup: free(state->username); free(state); return SCHED_DONE; -} -\ No newline at end of file +} diff --git a/src/interface/api/server.h b/src/interface/api/server.h @@ -1,11 +1,11 @@ #ifndef UDPHOLE_API_SERVER_H #define UDPHOLE_API_SERVER_H -#include <stdint.h> #include <stdbool.h> +#include <stdint.h> -#include "common/scheduler.h" #include "common/resp.h" +#include "common/scheduler.h" struct api_client_state; typedef struct api_client_state api_client_t; diff --git a/src/interface/cli/command/cluster.c b/src/interface/cli/command/cluster.c @@ -1,20 +1,20 @@ +#include "domain/cluster/cluster.h" + +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> -#include <fcntl.h> #include <sys/stat.h> +#include <unistd.h> +#include "../common.h" #include "cofyc/argparse.h" -#include "rxi/log.h" - -#include "infrastructure/config.h" #include "common/resp.h" -#include "../common.h" #include "common/scheduler.h" #include "domain/config.h" -#include "domain/cluster/cluster.h" +#include "infrastructure/config.h" #include "interface/api/server.h" +#include "rxi/log.h" static void register_cluster_commands(void) { api_register_domain_cmd("session.create", cluster_session_create); @@ -38,8 +38,7 @@ static int do_daemonize(void) { log_fatal("fork: %m"); return -1; } - if (pid > 0) - _exit(0); + if (pid > 0) _exit(0); if (setsid() < 0) { log_fatal("setsid: %m"); _exit(1); @@ -49,33 +48,31 @@ static int do_daemonize(void) { log_fatal("fork: %m"); _exit(1); } - if (pid > 0) - _exit(0); - if (chdir("/") != 0) {} + if (pid > 0) _exit(0); + if (chdir("/") != 0) { + } int fd; - for (fd = 0; fd < 3; fd++) - (void)close(fd); + for (fd = 0; fd < 3; fd++) (void)close(fd); fd = open("/dev/null", O_RDWR); if (fd >= 0) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); - if (fd > 2) - close(fd); + if (fd > 2) close(fd); } return 0; } int cli_cmd_cluster(int argc, const char **argv) { - int daemonize_flag = 0; + int daemonize_flag = 0; int no_daemonize_flag = 0; - struct argparse argparse; + struct argparse argparse; struct argparse_option options[] = { - OPT_HELP(), - OPT_BOOLEAN('d', "daemonize", &daemonize_flag, "run in background", NULL, 0, 0), - OPT_BOOLEAN('D', "no-daemonize", &no_daemonize_flag, "force foreground", NULL, 0, 0), - OPT_END(), + OPT_HELP(), + OPT_BOOLEAN('d', "daemonize", &daemonize_flag, "run in background", NULL, 0, 0), + OPT_BOOLEAN('D', "no-daemonize", &no_daemonize_flag, "force foreground", NULL, 0, 0), + OPT_END(), }; argparse_init(&argparse, options, (const char *const[]){"udphole cluster", NULL}, ARGPARSE_STOP_AT_NON_OPTION); argparse_parse(&argparse, argc, argv); diff --git a/src/interface/cli/command/daemon.c b/src/interface/cli/command/daemon.c @@ -1,21 +1,21 @@ +#include "daemon.h" + +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> -#include <fcntl.h> #include <sys/stat.h> +#include <unistd.h> +#include "../common.h" #include "cofyc/argparse.h" -#include "rxi/log.h" - -#include "infrastructure/config.h" #include "common/resp.h" -#include "../common.h" #include "common/scheduler.h" #include "domain/config.h" -#include "daemon.h" -#include "interface/api/server.h" #include "domain/daemon/session.h" +#include "infrastructure/config.h" +#include "interface/api/server.h" +#include "rxi/log.h" static void register_domain_commands(void) { api_register_domain_cmd("session.create", domain_session_create); @@ -39,8 +39,7 @@ static int do_daemonize(void) { log_fatal("fork: %m"); return -1; } - if (pid > 0) - _exit(0); + if (pid > 0) _exit(0); if (setsid() < 0) { log_fatal("setsid: %m"); _exit(1); @@ -50,33 +49,31 @@ static int do_daemonize(void) { log_fatal("fork: %m"); _exit(1); } - if (pid > 0) - _exit(0); - if (chdir("/") != 0) {} + if (pid > 0) _exit(0); + if (chdir("/") != 0) { + } int fd; - for (fd = 0; fd < 3; fd++) - (void)close(fd); + for (fd = 0; fd < 3; fd++) (void)close(fd); fd = open("/dev/null", O_RDWR); if (fd >= 0) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); - if (fd > 2) - close(fd); + if (fd > 2) close(fd); } return 0; } int cli_cmd_daemon(int argc, const char **argv) { - int daemonize_flag = 0; + int daemonize_flag = 0; int no_daemonize_flag = 0; - struct argparse argparse; + struct argparse argparse; struct argparse_option options[] = { - OPT_HELP(), - OPT_BOOLEAN('d', "daemonize", &daemonize_flag, "run in background", NULL, 0, 0), - OPT_BOOLEAN('D', "no-daemonize", &no_daemonize_flag, "force foreground", NULL, 0, 0), - OPT_END(), + OPT_HELP(), + OPT_BOOLEAN('d', "daemonize", &daemonize_flag, "run in background", NULL, 0, 0), + OPT_BOOLEAN('D', "no-daemonize", &no_daemonize_flag, "force foreground", NULL, 0, 0), + OPT_END(), }; argparse_init(&argparse, options, (const char *const[]){"udphole daemon", NULL}, ARGPARSE_STOP_AT_NON_OPTION); argparse_parse(&argparse, argc, argv); @@ -99,4 +96,4 @@ int cli_cmd_daemon(int argc, const char **argv) { log_info("udphole: daemon started"); return sched_main(); -} -\ No newline at end of file +} diff --git a/src/interface/cli/command/daemon.h b/src/interface/cli/command/daemon.h @@ -3,4 +3,4 @@ int cli_cmd_daemon(int argc, const char **argv); -#endif // UDPHOLE_CLI_DAEMON_H -\ No newline at end of file +#endif // UDPHOLE_CLI_DAEMON_H diff --git a/src/interface/cli/command/list_commands.c b/src/interface/cli/command/list_commands.c @@ -1,22 +1,25 @@ +#include "list_commands.h" + #include <stdio.h> #include <string.h> #include "../common.h" -#include "list_commands.h" int cli_cmd_list_commands(int argc, const char **argv) { (void)argc; (void)argv; - int len; - int name_longest = 0; - struct cli_command *cmd = cli_commands; - while(cmd) { + int len; + int name_longest = 0; + struct cli_command *cmd = cli_commands; + while (cmd) { len = (int)strlen(cmd->cmd); - if (len > name_longest) { name_longest = len; } + if (len > name_longest) { + name_longest = len; + } cmd = cmd->next; } - int width = cli_get_output_width(80); + int width = cli_get_output_width(80); int left_col = name_longest + 3; printf("\n"); @@ -30,4 +33,4 @@ int cli_cmd_list_commands(int argc, const char **argv) { printf("\n\n"); return 0; -} -\ No newline at end of file +} diff --git a/src/interface/cli/command/list_commands.h b/src/interface/cli/command/list_commands.h @@ -3,4 +3,4 @@ int cli_cmd_list_commands(int argc, const char **argv); -#endif // UDPHOLE_CLI_LIST_COMMANDS_H -\ No newline at end of file +#endif // UDPHOLE_CLI_LIST_COMMANDS_H diff --git a/src/interface/cli/common.c b/src/interface/cli/common.c @@ -1,26 +1,24 @@ +#include "common.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <sys/ioctl.h> - -#include "common.h" +#include <unistd.h> #ifndef NULL -#define NULL (void*)0 +#define NULL (void *)0 #endif struct cli_command *cli_commands = NULL; const char *cli_find_arg(int argc, const char **argv, const char *name) { for (int i = 0; i < argc - 1; i++) - if (strcmp(argv[i], name) == 0) - return argv[i + 1]; + if (strcmp(argv[i], name) == 0) return argv[i + 1]; return NULL; } -size_t cli_collect_positional(int argc, const char **argv, int start, - const char **out, size_t max_out) { +size_t cli_collect_positional(int argc, const char **argv, int start, const char **out, size_t max_out) { size_t n = 0; for (int i = start; i < argc && n < max_out; i++) { if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] != '\0') { @@ -47,21 +45,17 @@ const char *cli_resolve_default_config(void) { } int cli_get_output_width(int default_width) { - if (!isatty(STDOUT_FILENO)) - return default_width; + if (!isatty(STDOUT_FILENO)) return default_width; struct winsize w; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0 || w.ws_col <= 0) - return default_width; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0 || w.ws_col <= 0) return default_width; return (int)w.ws_col; } void cli_print_wrapped(FILE *out, const char *text, int width, int left_col_width) { - if (!text || width <= left_col_width) - return; + if (!text || width <= left_col_width) return; char *copy = strdup(text); - if (!copy) - return; - int len = left_col_width; + if (!copy) return; + int len = left_col_width; char *tok = strtok(copy, " "); while (tok) { int toklen = (int)strlen(tok); @@ -69,8 +63,7 @@ void cli_print_wrapped(FILE *out, const char *text, int width, int left_col_widt fprintf(out, "\n%*s", left_col_width, ""); len = left_col_width; } - if (len > left_col_width) - fputc(' ', out); + if (len > left_col_width) fputc(' ', out); fputs(tok, out); len += (len > left_col_width ? 1 : 0) + toklen; tok = strtok(NULL, " "); @@ -80,21 +73,21 @@ void cli_print_wrapped(FILE *out, const char *text, int width, int left_col_widt void cli_register_command(const char *name, const char *description, int (*fn)(int, const char **)) { struct cli_command *cmd = malloc(sizeof(*cmd)); - cmd->cmd = name; - cmd->desc = description; - cmd->fn = fn; - cmd->next = cli_commands; - cli_commands = cmd; + cmd->cmd = name; + cmd->desc = description; + cmd->fn = fn; + cmd->next = cli_commands; + cli_commands = cmd; } int cli_execute_command(int argc, const char **argv) { struct cli_command *cmd = cli_commands; - while(cmd) { + while (cmd) { if (!strcmp(cmd->cmd, argv[0])) return cmd->fn(argc, argv); cmd = cmd->next; } fprintf(stderr, "Unknown command: %s\n", argv[0]); return 1; -} -\ No newline at end of file +} diff --git a/src/interface/cli/common.h b/src/interface/cli/common.h @@ -5,7 +5,7 @@ #include <stdio.h> struct cli_command { - void *next; + void *next; const char *cmd; const char *desc; int (*fn)(int, const char **); @@ -15,10 +15,9 @@ extern struct cli_command *cli_commands; const char *cli_find_arg(int argc, const char **argv, const char *name); -size_t cli_collect_positional(int argc, const char **argv, int start, - const char **out, size_t max_out); +size_t cli_collect_positional(int argc, const char **argv, int start, const char **out, size_t max_out); -void cli_set_config_path(const char *path); +void cli_set_config_path(const char *path); const char *cli_config_path(void); const char *cli_resolve_default_config(void); @@ -28,6 +27,6 @@ int cli_get_output_width(int default_width); void cli_print_wrapped(FILE *out, const char *text, int width, int left_col_width); void cli_register_command(const char *name, const char *description, int (*fn)(int, const char **)); -int cli_execute_command(int argc, const char **argv); +int cli_execute_command(int argc, const char **argv); -#endif // UDPHOLE_CLI_COMMON_H -\ No newline at end of file +#endif // UDPHOLE_CLI_COMMON_H diff --git a/src/interface/cli/main.c b/src/interface/cli/main.c @@ -2,21 +2,20 @@ extern "C" { #endif +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> -#include <signal.h> #include "cofyc/argparse.h" -#include "rxi/log.h" - -#include "interface/cli/common.h" -#include "interface/cli/command/list_commands.h" -#include "interface/cli/command/daemon.h" -#include "interface/cli/command/cluster.h" -#include "infrastructure/config.h" #include "domain/cluster/cluster.h" +#include "infrastructure/config.h" +#include "interface/cli/command/cluster.h" +#include "interface/cli/command/daemon.h" +#include "interface/cli/command/list_commands.h" +#include "interface/cli/common.h" +#include "rxi/log.h" #ifdef __cplusplus } @@ -27,14 +26,14 @@ extern "C" { INCTXT(License, "LICENSE.md"); static const char *const usages[] = { - "udphole [global] command [local]", - "udphole list-commands", - "udphole --license", - NULL, + "udphole [global] command [local]", + "udphole list-commands", + "udphole --license", + NULL, }; -static FILE *log_file; -static char *log_path; +static FILE *log_file; +static char *log_path; static volatile sig_atomic_t sighup_received; static void logfile_callback(log_Event *ev) { @@ -62,7 +61,7 @@ static void sighup_handler(int sig) { sighup_received = 1; } -#define MARKER_PARAGRAPH "<!-- paragraph -->" +#define MARKER_PARAGRAPH "<!-- paragraph -->" #define MARKER_LIST_START "<!-- list:start -->" #define MARKER_LIST_END "<!-- list:end -->" @@ -76,7 +75,7 @@ static void print_license_paragraph(const char *start, const char *end, int widt while (end > start && (end[-1] == ' ' || end[-1] == '\n' || end[-1] == '\r')) end--; if (start >= end) return; static char buf[4096]; - size_t n = (size_t)(end - start); + size_t n = (size_t)(end - start); if (n >= sizeof(buf)) n = sizeof(buf) - 1; memcpy(buf, start, n); buf[n] = '\0'; @@ -88,24 +87,30 @@ static void print_license_paragraph(const char *start, const char *end, int widt } static void print_license_list(const char *start, const char *end, int width) { - const int left_col = 5; - const char *p = start; + const int left_col = 5; + const char *p = start; while (p < end) { skip_whitespace(&p); if (p >= end) break; - if (*p < '0' || *p > '9') { p++; continue; } + if (*p < '0' || *p > '9') { + p++; + continue; + } const char *num_start = p; while (p < end && *p >= '0' && *p <= '9') p++; if (p >= end || *p != '.') continue; p++; skip_whitespace(&p); const char *text_start = p; - const char *item_end = p; + const char *item_end = p; while (item_end < end) { const char *next = item_end; while (next < end && *next != '\n') next++; if (next < end) next++; - if (next >= end) { item_end = end; break; } + if (next >= end) { + item_end = end; + break; + } skip_whitespace(&next); if (next < end && *next >= '0' && *next <= '9') { const char *q = next; @@ -118,7 +123,7 @@ static void print_license_list(const char *start, const char *end, int width) { int num = atoi(num_start); fprintf(stdout, " %2d. ", num); static char buf[1024]; - size_t n = (size_t)(item_end - text_start); + size_t n = (size_t)(item_end - text_start); if (n >= sizeof(buf)) n = sizeof(buf) - 1; memcpy(buf, text_start, n); buf[n] = '\0'; @@ -140,8 +145,7 @@ static void cli_print_license(FILE *out, const char *text, int width) { print_license_paragraph(p, p + strlen(p), width); break; } - if (q > p) - print_license_paragraph(p, q, width); + if (q > p) print_license_paragraph(p, q, width); q += 5; if (strncmp(q, "paragraph -->", 13) == 0) { q += 13; @@ -156,8 +160,7 @@ static void cli_print_license(FILE *out, const char *text, int width) { q += 14; skip_whitespace(&q); const char *r = strstr(q, "<!-- list:end -->"); - if (r) - print_license_list(q, r, width); + if (r) print_license_list(q, r, width); p = r ? r + 17 : q + strlen(q); continue; } @@ -166,37 +169,26 @@ static void cli_print_license(FILE *out, const char *text, int width) { } int main(int argc, const char **argv) { - const char *loglevel = "info"; + const char *loglevel = "info"; const char *logfile_path = NULL; - const char *config_path = NULL; - static int license_flag = 0; + const char *config_path = NULL; + static int license_flag = 0; - cli_register_command( - "list-commands", - "Displays known commands and their descriptions", - cli_cmd_list_commands - ); + cli_register_command("list-commands", "Displays known commands and their descriptions", cli_cmd_list_commands); - cli_register_command( - "daemon", - "Run the udphole daemon", - cli_cmd_daemon - ); + cli_register_command("daemon", "Run the udphole daemon", cli_cmd_daemon); - cli_register_command( - "cluster", - "Run the udphole cluster", - cli_cmd_cluster - ); + cli_register_command("cluster", "Run the udphole cluster", cli_cmd_cluster); - struct argparse argparse; + struct argparse argparse; struct argparse_option options[] = { - OPT_HELP(), - OPT_STRING('f', "config", &config_path, "config file path (default: auto-detect)", NULL, 0, 0), - OPT_STRING('v', "verbosity", &loglevel, "log verbosity: fatal,error,warn,info,debug,trace (default: info)", NULL, 0, 0), - OPT_STRING(0, "log", &logfile_path, "also write log to file (SIGHUP reopens for logrotate)", NULL, 0, 0), - OPT_BOOLEAN(0, "license", &license_flag, "print license and exit", NULL, 0, 0), - OPT_END(), + OPT_HELP(), + OPT_STRING('f', "config", &config_path, "config file path (default: auto-detect)", NULL, 0, 0), + OPT_STRING('v', "verbosity", &loglevel, "log verbosity: fatal,error,warn,info,debug,trace (default: info)", NULL, + 0, 0), + OPT_STRING(0, "log", &logfile_path, "also write log to file (SIGHUP reopens for logrotate)", NULL, 0, 0), + OPT_BOOLEAN(0, "license", &license_flag, "print license and exit", NULL, 0, 0), + OPT_END(), }; argparse_init(&argparse, options, usages, ARGPARSE_STOP_AT_NON_OPTION); argc = argparse_parse(&argparse, argc, argv); @@ -211,8 +203,7 @@ int main(int argc, const char **argv) { return 1; } - if (!config_path || !config_path[0]) - config_path = cli_resolve_default_config(); + if (!config_path || !config_path[0]) config_path = cli_resolve_default_config(); config_set_path(config_path); config_init(); @@ -238,8 +229,8 @@ int main(int argc, const char **argv) { log_set_level(level); setvbuf(stderr, NULL, _IOLBF, 0); - log_file = NULL; - log_path = NULL; + log_file = NULL; + log_path = NULL; sighup_received = 0; if (logfile_path && logfile_path[0]) { @@ -256,4 +247,4 @@ int main(int argc, const char **argv) { } return cli_execute_command(argc, argv); -} -\ No newline at end of file +}