commit 6501c349eaedaca15a9c038d4a14bc9e88e9a51d Author: Timerix22 Date: Wed Jan 3 17:03:17 2024 +0600 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4be6400 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# build results +bin/ +obj/ +*.log +*.tmp + +# IDE files +.vs/ +.vshistory/ +.editorconfig +*.user +*.vcxproj.filters + +# other files +.old*/ +current.config diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..20d3017 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "kerep"] + path = kerep + url = https://github.com/Timerix22/kerep.git +[submodule "cbuild"] + path = cbuild + url = https://github.com/Timerix22/cbuild.git diff --git a/.vscode/.gitignore b/.vscode/.gitignore new file mode 100644 index 0000000..c3d3a20 --- /dev/null +++ b/.vscode/.gitignore @@ -0,0 +1 @@ +settings.json \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1a0ad8c --- /dev/null +++ b/Makefile @@ -0,0 +1,75 @@ +###################################### +###### Build tasks ####### +###################################### + +all: build_exec_dbg + +# creates executable using profiling info generated by profile +build_exec: profile + @cbuild/call_task.sh build_exec 2>&1 | tee -a make_raw.log + +# creates executable with debug info and no optimizations +build_exec_dbg: + @cbuild/call_task.sh build_exec_dbg 2>&1 | tee make_raw.log + +# recompile libsome_dep.a in the next build task +#rebuild_some_dep: +# @cbuild/rebuild_dep.sh libsome_dep.a 2>&1 | tee make_raw.log + +#rebuild_all: rebuild_some_dep + +###################################### +###### Launch tasks ####### +###################################### + +# executes $EXEC_FILE +exec: build_exec + @cbuild/call_task.sh exec 2>&1 | tee -a make_raw.log + +# executes $EXEC_FILE +exec_dbg: build_exec_dbg + @cbuild/call_task.sh exec 2>&1 | tee -a make_raw.log + +# executes $EXEC_FILE with valgrind memory checker +valgrind: build_exec_dbg + @cbuild/call_task.sh valgrind 2>&1 | tee -a make_raw.log + +# generates profiling info +profile: + @cbuild/call_task.sh profile 2>&1 | tee make_raw.log + +# compiles program with -pg and runs it with gprof +# uses gprof2dot python script to generate function call tree (pip install gprof2dot) +# requires graphviz (https://www.graphviz.org/download/source/) +gprof: + @cbuild/call_task.sh gprof 2>&1 | tee make_raw.log + +# compiles program and runs it with callgrind (part of valgrind) +# uses gprof2dot python script to generate function call tree (pip install gprof2dot) +# requires graphviz (https://www.graphviz.org/download/source/) +# P.S. detailed results can be viewed in KCacheGrind +callgrind: + @cbuild/call_task.sh callgrind 2>&1 | tee make_raw.log + +# compiles executable with sanitizers and executes it to find errors and warnings +sanitize: + @cbuild/call_task.sh sanitize 2>&1 | tee make_raw.log + +###################################### +###### Other tasks ####### +###################################### + +# deletes generated files +clean: + @cbuild/call_task.sh clean 2>&1 | tee make_raw.log + +# removes all unreadable characters copied from stdio +fix_log: + sed 's/[^[:blank:][:print:]]//g' make_raw.log \ + | sed 's/\[0;[0-9][0-9]m//g' \ + | sed 's/\[0;[0-9]m//g' \ + | sed 's/\[[0-9][0-9]m//g' \ + | sed 's/\[[0-9]m//g' \ + | sed 's/ H //g' \ + | sed 's/\[3gH //g' \ + > make_fixed.log diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..049c6f9 --- /dev/null +++ b/TODO.md @@ -0,0 +1,5 @@ +# TODO: +- listen to tcp/udp://:port +- connect to tcp/udp://ip:port +- generate temp password from key every 10 minutes: rng(seed: time()/(10\*60\*CLOCKS_PER_SECOND), salt: hash(key)) +- encrypt/decrypt diff --git a/cbuild b/cbuild new file mode 160000 index 0000000..c20e1e8 --- /dev/null +++ b/cbuild @@ -0,0 +1 @@ +Subproject commit c20e1e8f1c3e92e7f980a74942352b0a3744edcd diff --git a/default.config b/default.config new file mode 100644 index 0000000..10057eb --- /dev/null +++ b/default.config @@ -0,0 +1,153 @@ +#!/bin/bash +CBUILD_VERSION=7 +CONFIG_VERSION=1 + +PROJECT="port-tunnel" +CMP_C="gcc" +CMP_CPP="gcc" +STD_C="c11" +STD_CPP="c++11" +WARN_C="-Wall -Wno-discarded-qualifiers -Wextra -Wno-unused-parameter" +WARN_CPP="-Wall -Wextra -Wno-unused-parameter" +SRC_C="$( find src -name '*.c')" +SRC_CPP="$( find src -name '*.cpp')" +#TESTS_C="$( find tests -name '*.c')" +#TESTS_CPP="$(find tests -name '*.cpp')" + +# dir with dependeicy dirs +DEPS_BASEDIR="." +# EXAMPLE: "dependency_dir='build_task out_dir lib_file' +# other_depndency_dir=..." +# Dependencies must be declared on separate lines +# Values can be override by resetting one of dependencies: +# DEPS="$DEPS +# dependency_dir='...'" +DEPS="kerep='build_static_lib bin libkerep.a'" + +# OBJDIR structure: +# ├── objects/ - dir where compiled *.o files are stored. cleans every call of build task +# ├── profile/ - dir where gcc *.gcda profiling info files stored +# └── libs/ - there you can put static libs and linker will find them +OBJDIR="obj" +OUTDIR="bin" +STATIC_LIB_FILE="lib$PROJECT.a" + +# OS-specific options +case "$OS" in + WINDOWS) + EXEC_FILE="$PROJECT.exe" + SHARED_LIB_FILE="$PROJECT.dll" + LINKER_LIBS="-lpthread -lws2_32" + ;; + LINUX) + EXEC_FILE="$PROJECT" + SHARED_LIB_FILE="$PROJECT.so" + LINKER_LIBS="" + ;; + *) + error "operating system $OS has no configuration variants" + ;; +esac + +# TASKS +case "$TASK" in + # creates executable using profiling info if it exists + build_exec) + # -flto applies more optimizations across object files + # -flto=auto is needed to multithreaded copilation + # -fuse-linker-plugin is required to use static libs with lto + # -fprofile-use enables compiler to use profiling info files to optimize executable + # -fprofile-prefix-path sets path where profiling info about objects are be saved + # -fdata-sections -ffunction-sections -Wl,--gc-sections removes unused code + C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" + PRE_TASK_SCRIPT= + TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + POST_TASK_SCRIPT= + ;; + # creates executable with debug info and no optimizations + build_exec_dbg) + C_ARGS="-O0 -g3" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" + PRE_TASK_SCRIPT= + TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + POST_TASK_SCRIPT= + DEPS="$DEPS + kerep='build_static_lib_dbg bin libkerep.a'" + ;; + # executes $EXEC_FILE + exec) + TASK_SCRIPT=cbuild/default_tasks/exec.sh + ;; + # executes $EXEC_FILE with valgrind memory checker + valgrind) + VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all" + TASK_SCRIPT=cbuild/default_tasks/valgrind.sh + ;; + # generates profiling info + profile) + OUTDIR="$OUTDIR/profile" + # -flto applies more optimizations across object files + # -flto=auto is needed to multithreaded copilation + # -fuse-linker-plugin is required to use static libs with lto + # -pg adds code to executable, that generates file containing function call info (gmon.out) + # -fprofile-generate generates executable with profiling code + # -fprofile-prefix-path sets path where profiling info about objects will be saved + C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" + PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + TASK_SCRIPT=cbuild/default_tasks/profile.sh + POST_TASK_SCRIPT= + ;; + # compiles program with -pg and runs it with gprof + # uses gprof2dot python script to generate function call tree (pip install gprof2dot) + # requires graphviz (https://www.graphviz.org/download/source/) + gprof) + OUTDIR="$OUTDIR/gprof" + # -pg adds code to executable, that generates file containing function call info (gmon.out) + C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" + PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + TASK_SCRIPT=cbuild/default_tasks/gprof.sh + POST_TASK_SCRIPT= + ;; + # compiles program and runs it with callgrind (part of valgrind) + # uses gprof2dot python script to generate function call tree (pip install gprof2dot) + # requires graphviz (https://www.graphviz.org/download/source/) + # P.S. detailed results can be viewed in KCacheGrind + callgrind) + OUTDIR="$OUTDIR/callgrind" + # -pg adds code to executable, that generates file containing function call info (gmon.out) + C_ARGS="-O2 -flto=auto -fuse-linker-plugin" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" + PRE_TASK_SCRIPT=tasks/pre_build.sh + TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + POST_TASK_SCRIPT=cbuild/default_tasks/callgrind.sh + ;; + # compiles executable with sanitizers and executes it to find errors and warnings + sanitize) + OUTDIR="$OUTDIR/sanitize" + C_ARGS="-O0 -g3 -fsanitize=undefined,address" + CPP_ARGS="$C_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" + PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh + TASK_SCRIPT=cbuild/default_tasks/exec.sh + POST_TASK_SCRIPT= + ;; + # deletes generated files + clean) + TASK_SCRIPT=cbuild/default_tasks/clean.sh + ;; + # nothing to do + no_task) + ;; + # unknown task + *) + error "task <$TASK> not found" + ;; +esac diff --git a/kerep b/kerep new file mode 160000 index 0000000..7ba15b2 --- /dev/null +++ b/kerep @@ -0,0 +1 @@ +Subproject commit 7ba15b208f105b0a6c2a9dfdb522c149e2d36620 diff --git a/src/help_message.c b/src/help_message.c new file mode 100644 index 0000000..9a21777 --- /dev/null +++ b/src/help_message.c @@ -0,0 +1,55 @@ +#include "../kerep/src/kprint/kprintf.h" + +// option help definition +#define HELP_OPT(ALIASES, PARAMS, DESCRIPTION...) \ + FWHI " " ALIASES " " PARAMS FGRY "\n" DESCRIPTION + +// option parameter help definition +#define HELP_PRM(PNAME) \ + FWHI "[" FCYN PNAME FWHI "]" + +// option nullable parameter help definition +#define HELP_PRMN(PNAME) \ + FWHI "[" FCYN PNAME FWHI "?]" + +// option parameter1/parameter2 help definition +#define HELP_PRM2(PNAME1, PNAME2) \ + FWHI "[" FCYN PNAME1 FWHI "/" FCYN PNAME2 FWHI "]" + +const char* help_message = ( + FWHI"Usage: port-tunnel " + HELP_PRM("program_mode") + " " HELP_PRM("other_options...") "\n" + + FWHI" Options syntax: --"FCYN" " HELP_PRM("options") "\n" + " " HELP_PRM("val") FGRY" - some value\n" + " " HELP_PRMN("val") FGRY" - value or nothing\n" + " " HELP_PRM2("variant1", "variant2") FGRY" - variant1 or variant2\n" + + FWHI" Program mode options:\n" + + HELP_OPT("-c, --connect", + HELP_PRM2("tcp","udp") "://" HELP_PRMN("ip") ":" HELP_PRM("port"), + " Connect to a listening instance of port-tunnel.\n") + + HELP_OPT("-l, --listen", + HELP_PRM2("tcp","udp") "://" HELP_PRMN("ip") ":" HELP_PRM("port"), + " Listen for incomming packets at the address (if provided) and the port\n") + + FWHI" Other options:\n" + + HELP_OPT("-h, --help, /?", "", + " Show this message.\n") + + HELP_OPT("-p, --out-port", + HELP_PRM("port"), + " Port incoming packets will be sent to.\n") + + HELP_OPT("-d, --decrypt", + HELP_PRM("key"), + " Decrypt incoming packets with a key.\n") + + HELP_OPT("-e, --encrypt", + HELP_PRM("key"), + " Encrypt outgoing packets with a key.\n") +); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..ed83609 --- /dev/null +++ b/src/main.c @@ -0,0 +1,70 @@ +#include "../kerep/src/base/base.h" + +extern const char* help_message; + +int errs(char* err_msg){ + throw(err_msg); + return -1; +} + +#define argIs(STR) cptr_equals(arg, STR) + +#define argNext() argv[++argi < argc ? argi : errs(cptr_concat("option '",arg,"' must have a parameter"))] + +typedef enum { + ProgramMode_None, + ProgramMode_Listen, + ProgramMode_Connect +} ProgramMode; + +int main(int argc, const char* const* argv){ + kt_beginInit(false); + kt_initKerepTypes(); + // kt_register(...); + kt_endInit(); + + ProgramMode mode = ProgramMode_None; + const char* endpoint_str = ""; + const char* out_port_str = ""; + + if(argc < 2) + throw("No arguments provided. Run the program with argument -h to see help message"); + + for(int argi = 1; argi < argc; argi++){ + const char* arg = argv[argi]; + if(argIs("-h") || argIs("--help") || argIs("/?")){ + kprintf("%s"FGRY"\n", help_message); + return 0; + } + else if(argIs("-c") || argIs("--connect")){ + if(mode != ProgramMode_None) + throw(cptr_concat("invalid option '",arg,"': program mode has been selected already")); + + mode = ProgramMode_Connect; + endpoint_str = argNext(); + } + else if(argIs("-l") || argIs("--listen")){ + if(mode != ProgramMode_None) + throw(cptr_concat("invalid option '",arg,"': program mode has been selected already")); + + mode = ProgramMode_Listen; + endpoint_str = argNext(); + } + else if(argIs("-p") || argIs("--out-port")){ + if(out_port_str[0] != 0) + throw(cptr_concat("invalid option '",arg,"': out port has been selected already")); + if(mode != ProgramMode_Connect) + throw(cptr_concat("invalid option '",arg,"': out port setting is avaliable only for 'connect' program mode")); + + out_port_str = argNext(); + } + else { + throw(cptr_concat("invalid argument: ", arg)); + } + } + + kprintf("endpoint_str: %s\n", endpoint_str); + kprintf("out_port_str: %s\n", out_port_str); + + return 0; +}