diff --git a/default.config b/default.config index 10057eb..f443241 100644 --- a/default.config +++ b/default.config @@ -68,7 +68,7 @@ case "$TASK" in ;; # creates executable with debug info and no optimizations build_exec_dbg) - C_ARGS="-O0 -g3" + C_ARGS="-O0 -g3 -DDEBUG" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT= diff --git a/src/Connectors.c b/src/Connectors.c new file mode 100644 index 0000000..e949772 --- /dev/null +++ b/src/Connectors.c @@ -0,0 +1,67 @@ +#include "port-tunnel.h" + +//////////////////////////////////////// +// ConnectorUDP // +//////////////////////////////////////// + +void ConnectorUDP_construct(ConnectorUDP* ptr, knIPV4Endpoint listener_end, knIPV4Endpoint connector_end, OutputMode out_mode){ + __PipeStorage_construct(&ptr->pipes); + + if(out_mode == OutputMode_Bind){ + tryLast(knSocketUDP_open(true), m_s, ;); + ptr->main_sock = m_s.value.VoidPtr; + tryLast(knSocketUDP_bind(ptr->main_sock, connector_end), _m7u7, ;); + } + else if(out_mode == OutputMode_Send){ + tryLast(knSocketUDP_open(false), m_s, ;); + ptr->main_sock = m_s.value.VoidPtr; + } + else throw("no output mode has been selected"); + + ptr->listener_end = listener_end; + ptr->connector_end = connector_end; + ptr->out_mode = out_mode; +} + +void ConnectorUDP_destruct(ConnectorUDP* ptr){ + __PipeStorage_destruct(&ptr->pipes); + tryLast(knSocketUDP_close(ptr->main_sock), _m864, ;); +} + +void ConnectorUDP_start(ConnectorUDP* ptr){ + __PipeStorage_startGCAsync(&ptr->pipes); + +} + +//////////////////////////////////////// +// ConnectorTCP // +//////////////////////////////////////// + +void ConnectorTCP_construct(ConnectorTCP* ptr, knIPV4Endpoint listener_end, knIPV4Endpoint connector_end, OutputMode out_mode){ + __PipeStorage_construct(&ptr->pipes); + + if(out_mode == OutputMode_Bind){ + tryLast(knSocketTCP_open(true), m_s, ;); + ptr->main_sock = m_s.value.VoidPtr; + tryLast(knSocketTCP_bindAndListen(ptr->main_sock, connector_end), _m7u7, ;); + } + else if(out_mode == OutputMode_Send){ + tryLast(knSocketTCP_open(false), m_s, ;); + ptr->main_sock = m_s.value.VoidPtr; + } + else throw("no output mode has been selected"); + + ptr->listener_end = listener_end; + ptr->connector_end = connector_end; + ptr->out_mode = out_mode; +} + +void ConnectorTCP_destruct(ConnectorTCP* ptr){ + __PipeStorage_destruct(&ptr->pipes); + tryLast(knSocketTCP_close(ptr->main_sock), _m864, ;); +} + +void ConnectorTCP_start(ConnectorTCP* ptr){ + __PipeStorage_startGCAsync(&ptr->pipes); + +} diff --git a/src/Listeners.c b/src/Listeners.c new file mode 100644 index 0000000..a6dddc4 --- /dev/null +++ b/src/Listeners.c @@ -0,0 +1,43 @@ +#include "port-tunnel.h" + +//////////////////////////////////////// +// ListenerUDP // +//////////////////////////////////////// + +void ListenerUDP_construct(ListenerUDP* ptr, knIPV4Endpoint listener_end){ + __PipeStorage_construct(&ptr->pipes); + tryLast(knSocketUDP_open(true), m_s, ;); + ptr->main_sock = m_s.value.VoidPtr; + tryLast(knSocketUDP_bind(ptr->main_sock, listener_end), _m7u7, ;); + ptr->connector_end = knIPV4Endpoint_INVALID; +} + +void ListenerUDP_start(ListenerUDP* ptr){ + +} + +void ListenerUDP_destruct(ListenerUDP* ptr){ + __PipeStorage_destruct(&ptr->pipes); + tryLast(knSocketUDP_close(ptr->main_sock), _m864, ;); +} + +//////////////////////////////////////// +// ListenerTCP // +//////////////////////////////////////// + +void ListenerTCP_construct(ListenerTCP* ptr, knIPV4Endpoint listener_end){ + __PipeStorage_construct(&ptr->pipes); + tryLast(knSocketTCP_open(true), m_s, ;); + ptr->main_sock = m_s.value.VoidPtr; + tryLast(knSocketTCP_bindAndListen(ptr->main_sock, listener_end), _m7u7, ;); + ptr->connector_end = knIPV4Endpoint_INVALID; +} + +void ListenerTCP_destruct(ListenerTCP* ptr){ + __PipeStorage_destruct(&ptr->pipes); + tryLast(knSocketTCP_close(ptr->main_sock), _m864, ;); +} + +void ListenerTCP_start(ListenerTCP* ptr){ + +} diff --git a/src/PipeStorage.c b/src/PipeStorage.c new file mode 100644 index 0000000..4b979a0 --- /dev/null +++ b/src/PipeStorage.c @@ -0,0 +1,22 @@ +#include "port-tunnel.h" + + +void __PipeStorage_construct(PipeStorage* s){ + s->is_gc_stopped = true; + s->last_check_time = 0; + s->table = Hashtable_create(); +} + +void __PipeStorage_destruct(PipeStorage* s){ + __PipeStorage_stopGCAsync(s); + Hashtable_free(s->table); +} + +void __PipeStorage_startGCAsync(PipeStorage* s){ + +} + +void __PipeStorage_stopGCAsync(PipeStorage* s){ + s->is_gc_stopped = true; + s->last_check_time = 0; +} diff --git a/src/Pipes.c b/src/Pipes.c new file mode 100644 index 0000000..b331ed7 --- /dev/null +++ b/src/Pipes.c @@ -0,0 +1,65 @@ +#include "port-tunnel.h" + +//////////////////////////////////////// +// PipeBase // +//////////////////////////////////////// + +static void PipeBase_construct(PipeBase* pipe){ + pipe->is_closed = false; + pipe->is_transmitting = false; + pipe->last_transmit_time = getTimeUsec(); +} + +//////////////////////////////////////// +// PipeUDP // +//////////////////////////////////////// + +void PipeUDP_construct(PipeUDP* pipe, knSocketUDP* pipe_in_sock, knIPV4Endpoint pipe_out_end){ + PipeBase_construct(&pipe->base); + pipe->pipe_in_sock = pipe_in_sock; + pipe->pipe_out_end = pipe_out_end; +} + +void PipeUDP_destruct(PipeUDP* pipe){ + Maybe m = knSocketUDP_shutdown(pipe->pipe_in_sock, knShutdownType_Both); + if(m.errmsg) + logError("%s", m.errmsg); + m = knSocketUDP_close(pipe->pipe_in_sock); + if(m.errmsg) + logError("%s", m.errmsg); +} + +void PipeUDP_startAsync(PipeUDP* pipe){ + +} + +void PipeUDP_stop(PipeUDP* pipe){ + +} + +//////////////////////////////////////// +// PipeTCP // +//////////////////////////////////////// + +void PipeTCP_construct(PipeTCP* pipe, knSocketTCP* pipe_in_sock, knIPV4Endpoint pipe_out_end){ + PipeBase_construct(&pipe->base); + pipe->pipe_in_sock = pipe_in_sock; + pipe->pipe_out_end = pipe_out_end; +} + +void PipeTCP_destruct(PipeTCP* pipe){ + Maybe m = knSocketTCP_shutdown(pipe->pipe_in_sock, knShutdownType_Both); + if(m.errmsg) + logError("%s", m.errmsg); + m = knSocketTCP_close(pipe->pipe_in_sock); + if(m.errmsg) + logError("%s", m.errmsg); +} + +void PipeTCP_startAsync(PipeTCP* pipe){ + +} + +void PipeTCP_stop(PipeTCP* pipe){ + +} diff --git a/src/help_message.c b/src/help_message.c index a5f7316..e76d148 100644 --- a/src/help_message.c +++ b/src/help_message.c @@ -2,19 +2,25 @@ // option help definition #define HELP_OPT(ALIASES, PARAMS, DESCRIPTION...) \ - FWHI " " ALIASES " " PARAMS FGRY "\n" DESCRIPTION + FWHI" " ALIASES " " PARAMS FGRY "\n" DESCRIPTION // option parameter help definition #define HELP_PRM(PNAME) \ - FWHI "[" FCYN PNAME FWHI "]" + FWHI"[" FCYN PNAME FWHI"]" // option nullable parameter help definition #define HELP_PRMN(PNAME) \ - FWHI "[" FCYN PNAME FWHI "?]" + FWHI"[" FCYN PNAME FWHI"?]" // option parameter1/parameter2 help definition #define HELP_PRM2(PNAME1, PNAME2) \ - FWHI "[" FCYN PNAME1 FWHI "/" FCYN PNAME2 FWHI "]" + FWHI"[" FCYN PNAME1 FWHI"/" FCYN PNAME2 FWHI"]" + +#define HELP_PRM3(PNAME1, PNAME2, PNAME3) \ + FWHI"[" FCYN PNAME1 FWHI"/" FCYN PNAME2 FWHI"/" FCYN PNAME3 FWHI"]" + +#define HELP_PRM4(PNAME1, PNAME2, PNAME3, PNAME4) \ + FWHI"[" FCYN PNAME1 FWHI"/" FCYN PNAME2 FWHI"/" FCYN PNAME3 FWHI"/" FCYN PNAME4 FWHI"]" const char* help_message = ( FWHI"Usage: port-tunnel " @@ -72,4 +78,8 @@ const char* help_message = ( HELP_OPT("-e, --encrypt", HELP_PRM("key"), " Encrypt outgoing packets with a key.\n") + + HELP_OPT("-v, --verbosity, --log-level", + HELP_PRM4("debug", "info", "warning", "error"), + " Sets log verbocity level (default=info).\n") ); diff --git a/src/main.c b/src/main.c deleted file mode 100644 index fc8b350..0000000 --- a/src/main.c +++ /dev/null @@ -1,153 +0,0 @@ -#include "../kerep/src/base/base.h" -#include "../kerep/src/Network/network.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 { - TunnelProtocol_None, - TunnelProtocol_TCP, - TunnelProtocol_UDP -} TunnelProtocol; - -typedef enum { - InputMode_None, - InputMode_Listen, - InputMode_Connect -} InputMode; - -typedef enum { - OutputMode_None, - OutputMode_Bind, - OutputMode_Send -} OutputMode; - -int main(int argc, const char* const* argv){ - kt_beginInit(false); - kt_initKerepTypes(); - // kt_register(...); - kt_endInit(); - - TunnelProtocol tunnel_protocol = TunnelProtocol_None; - InputMode input_mode = InputMode_None; - OutputMode output_mode = OutputMode_None; - knIPV4Endpoint input_end = knIPV4Endpoint_INVALID; - knIPV4Endpoint output_end = knIPV4Endpoint_INVALID; - const char* encryption_key = NULL; - const char* decryption_key = NULL; - - 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("-p") || argIs("--protocol")){ - if(tunnel_protocol != TunnelProtocol_None) - throw(cptr_concat("invalid option '",arg,"': tunnel protocol has been set already")); - - const char* protocol_str = argNext(); - char* protocol_str_lower = cptr_toLower(protocol_str); - if(cptr_equals(protocol_str_lower, "tcp")) - tunnel_protocol = TunnelProtocol_TCP; - else if(cptr_equals(protocol_str_lower, "udp")) - tunnel_protocol = TunnelProtocol_UDP; - else throw(cptr_concat("invalid parameter '",protocol_str,"': unknown protocol")); - free(protocol_str_lower); - } - else if(argIs("-l") || argIs("--listen")){ - if(input_mode != InputMode_None) - throw(cptr_concat("invalid option '",arg,"': input mode has been set already")); - - input_mode = InputMode_Listen; - const char* input_end_str = argNext(); - tryLast(knIPV4Endpoint_fromStr(input_end_str, &input_end), _m8612, ;); - } - else if(argIs("-c") || argIs("--connect")){ - if(input_mode != InputMode_None) - throw(cptr_concat("invalid option '",arg,"': input mode has been set already")); - - input_mode = InputMode_Connect; - const char* input_end_str = argNext(); - tryLast(knIPV4Endpoint_fromStr(input_end_str, &input_end), _m2612, ;); - } - else if(argIs("-s") || argIs("--send-to")){ - if(output_mode != OutputMode_None) - throw(cptr_concat("invalid option '",arg,"': output mode has been set already")); - if(input_mode != InputMode_Connect) - throw(cptr_concat("invalid option '",arg,"': out endpoint setting is avaliable only in 'connect' program mode")); - - output_mode = OutputMode_Send; - const char* output_end_str = argNext(); - tryLast(knIPV4Endpoint_fromStr(output_end_str, &output_end), _m8613, ;); - } - else if(argIs("-b") || argIs("--bind-to")){ - if(output_mode != OutputMode_None) - throw(cptr_concat("invalid option '",arg,"': output mode has been set already")); - if(input_mode != InputMode_Connect) - throw(cptr_concat("invalid option '",arg,"': out endpoint setting is avaliable only in 'connect' program mode")); - - output_mode = OutputMode_Bind; - const char* output_end_str = argNext(); - tryLast(knIPV4Endpoint_fromStr(output_end_str, &output_end), _m2613, ;); - } - else if(argIs("-e") || argIs("--encrypt")){ - if(encryption_key != NULL) - throw(cptr_concat("invalid option '",arg,"': encryption key has been set already")); - - encryption_key = argNext(); - if(cptr_length(encryption_key) < 16) - throw("too short encryption key (min length 16)"); - if(cptr_length(encryption_key) > 512) - throw("too long encryption key (max length 512)"); - } - else if(argIs("-d") || argIs("--decrypt")){ - if(decryption_key != NULL) - throw(cptr_concat("invalid option '",arg,"': decryption key has been set already")); - - decryption_key = argNext(); - if(cptr_length(decryption_key) < 16) - throw("too short decryption key (min length 16)"); - if(cptr_length(decryption_key) > 512) - throw("too long decryption key (max length 512)"); - } - else { - throw(cptr_concat("invalid argument: ", arg)); - } - } - - kprintf("tunnel_protocol: %i\n", tunnel_protocol); - kprintf("input_mode: %i\n", input_mode); - kprintf("output_mode: %i\n", output_mode); - - char* temps; - if(!knIPV4Endpoint_isINVALID(input_end)){ - temps = knIPV4Endpoint_toString(&input_end); - kprintf("input_end: %s\n", temps); - free(temps); - } - else kprintf("input_end: INVALID\n"); - - if(!knIPV4Endpoint_isINVALID(output_end)){ - temps = knIPV4Endpoint_toString(&output_end); - kprintf("output_end: %s\n", temps); - free(temps); - } - else kprintf("output_end: INVALID\n"); - - kprintf("encryption_key: %s\n", encryption_key ? encryption_key : "NULL"); - kprintf("decryption_key: %s\n", decryption_key ? decryption_key : "NULL"); - - return 0; -} diff --git a/src/port-tunnel.c b/src/port-tunnel.c new file mode 100644 index 0000000..1d726ee --- /dev/null +++ b/src/port-tunnel.c @@ -0,0 +1,213 @@ +#include "port-tunnel.h" + +kt_define(PipeBase, NULL, NULL) +kt_define(PipeUDP, (freeMembers_t)PipeUDP_destruct, NULL) +kt_define(PipeTCP, (freeMembers_t)PipeTCP_destruct, NULL) +kt_define(PipeStorage, (freeMembers_t)__PipeStorage_destruct, NULL) +kt_define(ListenerUDP, (freeMembers_t)ListenerUDP_destruct, NULL) +kt_define(ListenerTCP, (freeMembers_t)ListenerTCP_destruct, NULL) +kt_define(ConnectorUDP, (freeMembers_t)ConnectorUDP_destruct, NULL) +kt_define(ConnectorTCP, (freeMembers_t)ConnectorTCP_destruct, NULL) + +LogLevel _log_level = LogLevel_Info; + +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"))] + +int main(int argc, const char* const* argv){ +#ifdef DEBUG + kt_beginInit(true); +#else + kt_beginInit(false); +#endif + kt_initKerepTypes(); + kt_register(PipeBase); + kt_register(PipeUDP); + kt_register(PipeTCP); + kt_register(PipeStorage); + kt_register(ListenerUDP); + kt_register(ListenerTCP); + kt_register(ConnectorUDP); + kt_register(ConnectorTCP); + kt_endInit(); + + tryLast(kn_tryInit(), _m11257, ;) + + TunnelProtocol tunnel_protocol = TunnelProtocol_None; + InputMode input_mode = InputMode_None; + OutputMode output_mode = OutputMode_None; + knIPV4Endpoint listener_end = knIPV4Endpoint_INVALID; + knIPV4Endpoint connector_end = knIPV4Endpoint_INVALID; + const char* encryption_key = NULL; + const char* decryption_key = NULL; + + LogLevel log_level = +#ifdef DEBUG + LogLevel_Debug; +#else + LogLevel_Info; +#endif + + // parse args + 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"", help_message); + return 0; + } + else if(argIs("-p") || argIs("--protocol")){ + if(tunnel_protocol != TunnelProtocol_None) + throw(cptr_concat("invalid option '",arg,"': tunnel protocol has been set already")); + + const char* protocol_str = argNext(); + char* protocol_str_lower = cptr_toLower(protocol_str); + if(cptr_equals(protocol_str_lower, "tcp")) + tunnel_protocol = TunnelProtocol_TCP; + else if(cptr_equals(protocol_str_lower, "udp")) + tunnel_protocol = TunnelProtocol_UDP; + else throw(cptr_concat("invalid parameter '",protocol_str,"': unknown protocol")); + free(protocol_str_lower); + } + else if(argIs("-l") || argIs("--listen")){ + if(input_mode != InputMode_None) + throw(cptr_concat("invalid option '",arg,"': input mode has been set already")); + + input_mode = InputMode_Listen; + const char* input_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(input_end_str, &listener_end), _m8612, ;); + } + else if(argIs("-c") || argIs("--connect")){ + if(input_mode != InputMode_None) + throw(cptr_concat("invalid option '",arg,"': input mode has been set already")); + + input_mode = InputMode_Connect; + const char* input_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(input_end_str, &listener_end), _m2612, ;); + } + else if(argIs("-s") || argIs("--send-to")){ + if(output_mode != OutputMode_None) + throw(cptr_concat("invalid option '",arg,"': output mode has been set already")); + if(input_mode != InputMode_Connect) + throw(cptr_concat("invalid option '",arg,"': out endpoint setting is avaliable only in 'connect' program mode")); + + output_mode = OutputMode_Send; + const char* output_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(output_end_str, &connector_end), _m8613, ;); + } + else if(argIs("-b") || argIs("--bind-to")){ + if(output_mode != OutputMode_None) + throw(cptr_concat("invalid option '",arg,"': output mode has been set already")); + if(input_mode != InputMode_Connect) + throw(cptr_concat("invalid option '",arg,"': out endpoint setting is avaliable only in 'connect' program mode")); + + output_mode = OutputMode_Bind; + const char* output_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(output_end_str, &connector_end), _m2613, ;); + } + else if(argIs("-e") || argIs("--encrypt")){ + if(encryption_key != NULL) + throw(cptr_concat("invalid option '",arg,"': encryption key has been set already")); + + encryption_key = argNext(); + if(cptr_length(encryption_key) < 16) + throw("too short encryption key (min length 16)"); + if(cptr_length(encryption_key) > 512) + throw("too long encryption key (max length 512)"); + } + else if(argIs("-d") || argIs("--decrypt")){ + if(decryption_key != NULL) + throw(cptr_concat("invalid option '",arg,"': decryption key has been set already")); + + decryption_key = argNext(); + if(cptr_length(decryption_key) < 16) + throw("too short decryption key (min length 16)"); + if(cptr_length(decryption_key) > 512) + throw("too long decryption key (max length 512)"); + } + else if(argIs("-v") || argIs("--verbosity") || argIs("--log-level")){ + char* log_level_str = argNext(); + char* opt = cptr_toLower(log_level_str); + if(cptr_equals(opt, "debug")) + log_level = LogLevel_Debug; + else if(cptr_equals(opt, "info")) + log_level = LogLevel_Info; + else if(cptr_equals(opt, "warning")) + log_level = LogLevel_Warning; + else if(cptr_equals(opt, "error")) + log_level = LogLevel_Error; + else throw(cptr_concat("invalid parameter '",log_level_str,"': unknown log_level")); + free(opt); + } + else { + throw(cptr_concat("invalid argument: ", arg)); + } + } + + setLogLevel(log_level); + + // print parsed args + logDebug("tunnel_protocol: %i", tunnel_protocol); + logDebug("input_mode: %i", input_mode); + logDebug("output_mode: %i", output_mode); + char* temps; + if(!knIPV4Endpoint_isINVALID(listener_end)){ + temps = knIPV4Endpoint_toString(&listener_end); + logDebug("listener_end: %s", temps); + free(temps); + } + else logDebug("listener_end: INVALID"); + if(!knIPV4Endpoint_isINVALID(connector_end)){ + temps = knIPV4Endpoint_toString(&connector_end); + logDebug("connector_end: %s", temps); + free(temps); + } + else logDebug("connector_end: INVALID"); + logDebug("encryption_key: %s", encryption_key ? encryption_key : "NULL"); + logDebug("decryption_key: %s", decryption_key ? decryption_key : "NULL"); + logDebug("log_level: %i", log_level); + + // create and run Listener or Connector + if(input_mode == InputMode_Connect){ + if(tunnel_protocol == TunnelProtocol_UDP){ + ConnectorUDP connector; + ConnectorUDP_construct(&connector, listener_end, connector_end, output_mode); + ConnectorUDP_start(&connector); + ConnectorUDP_destruct(&connector); + } + else if(tunnel_protocol == TunnelProtocol_TCP){ + ConnectorTCP connector; + ConnectorTCP_construct(&connector, listener_end, connector_end, output_mode); + ConnectorTCP_start(&connector); + ConnectorTCP_destruct(&connector); + } + else throw("no tunnel protocol has been selected"); + } + else if(input_mode == InputMode_Listen){ + if(tunnel_protocol == TunnelProtocol_UDP){ + ListenerUDP listener; + ListenerUDP_construct(&listener, listener_end); + ListenerUDP_start(&listener); + ListenerUDP_destruct(&listener); + } + else if(tunnel_protocol == TunnelProtocol_TCP){ + ListenerTCP listener; + ListenerTCP_construct(&listener, listener_end); + ListenerTCP_start(&listener); + ListenerTCP_destruct(&listener); + } + else throw("no tunnel protocol has been selected"); + } + else throw("no input mode has been selected"); + + tryLast(kt_tryDispose(), _m11258, ;) + return 0; +} diff --git a/src/port-tunnel.h b/src/port-tunnel.h new file mode 100644 index 0000000..cb4caa1 --- /dev/null +++ b/src/port-tunnel.h @@ -0,0 +1,189 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include +#include "../kerep/src/Network/network.h" +#include "../kerep/src/Hashtable/Hashtable.h" + +/// defined in help_message.c +extern const char* help_message; + +//////////////////////////////////////// +// Time // +//////////////////////////////////////// + +/// nanoseconds +typedef u64 nsec_t; + +/// miliseconds +typedef u64 usec_t; + +/// system time now in nanoseconds +///@return u64 will overflow in 13 years +nsec_t getTimeNsec(); + +/// system time now in microseconds +///@return u64 will overflow in 58494 years +usec_t getTimeUsec(); + +//////////////////////////////////////// +// Enums // +//////////////////////////////////////// + +typedef enum { + TunnelProtocol_None, + TunnelProtocol_TCP, + TunnelProtocol_UDP +} TunnelProtocol; + +typedef enum { + InputMode_None, + InputMode_Listen, + InputMode_Connect +} InputMode; + +typedef enum { + OutputMode_None, + OutputMode_Bind, + OutputMode_Send +} OutputMode; + +//////////////////////////////////////// +// Logging // +//////////////////////////////////////// + +typedef enum LogLevel { + LogLevel_Error = 1, + LogLevel_Warning = 2, + LogLevel_Info = 3, + LogLevel_Debug = 4 +} LogLevel; + +extern LogLevel _log_level; + +#define __logTryPrint(minimumLogLevel, format, args...)\ + if(_log_level >= minimumLogLevel) \ + kprintf(format "\n" ,##args) + +#define logDebug(format, args...) __logTryPrint(LogLevel_Debug, FGRY format ,##args) + +#define logInfo(format, args...) __logTryPrint(LogLevel_Info, FWHI format ,##args) + +#define logWarning(format, args...) __logTryPrint(LogLevel_Warning, FYEL format ,##args) + +#define logError(format, args...) __logTryPrint(LogLevel_Error, FRED format ,##args) + +#define setLogLevel(l) _log_level = l + +//////////////////////////////////////// +// Pipes // +//////////////////////////////////////// + +STRUCT(PipeBase, + usec_t last_transmit_time; + bool is_transmitting; + bool is_closed; +) + +STRUCT(PipeUDP, + PipeBase base; + knIPV4Endpoint pipe_out_end; + knSocketUDP* pipe_in_sock; +) + +void PipeUDP_construct(PipeUDP* pipe, knSocketUDP* pipe_in_sock, knIPV4Endpoint pipe_out_end); +void PipeUDP_destruct(PipeUDP* pipe); +void PipeUDP_startAsync(PipeUDP* pipe); +void PipeUDP_stopAsync(PipeUDP* pipe); + +STRUCT(PipeTCP, + PipeBase base; + knIPV4Endpoint pipe_out_end; + knSocketTCP* pipe_in_sock; +) + +void PipeTCP_construct(PipeTCP* pipe, knSocketTCP* pipe_in_sock, knIPV4Endpoint pipe_out_end); +void PipeTCP_destruct(PipeTCP* pipe); +void PipeTCP_startAsync(PipeTCP* pipe); +void PipeTCP_stopAsync(PipeTCP* pipe); + +//////////////////////////////////////// +// Pipe Storage // +//////////////////////////////////////// + +STRUCT(PipeStorage, + /* Hashtable */ + Hashtable* table; + usec_t last_check_time; + bool is_gc_stopped; +) + +void __PipeStorage_construct(PipeStorage* s); +void __PipeStorage_destruct(PipeStorage* s); +void __PipeStorage_startGCAsync(PipeStorage* s); +void __PipeStorage_stopGCAsync(PipeStorage* s); + +//////////////////////////////////////// +// Listeners // +//////////////////////////////////////// + +STRUCT(ListenerUDP, + /* Hashtable pipes.table */ + PipeStorage pipes; + knIPV4Endpoint connector_end; + knSocketUDP* main_sock; +) + +void ListenerUDP_construct(ListenerUDP* ptr, knIPV4Endpoint listener_end); +void ListenerUDP_destruct(ListenerUDP* ptr); +void ListenerUDP_start(ListenerUDP* ptr); + +STRUCT(ListenerTCP, + /* Hashtable pipes.table */ + PipeStorage pipes; + knIPV4Endpoint connector_end; + knSocketTCP* main_sock; +) + +void ListenerTCP_construct(ListenerTCP* ptr, knIPV4Endpoint listener_end); +void ListenerTCP_destruct(ListenerTCP* ptr); +void ListenerTCP_start(ListenerTCP* ptr); + +//////////////////////////////////////// +// Connectors // +//////////////////////////////////////// + +STRUCT(ConnectorUDP, + /* Hashtable */ + PipeStorage pipes; + knIPV4Endpoint listener_end; + knIPV4Endpoint connector_end; + knSocketUDP* main_sock; + OutputMode out_mode; +) + +void ConnectorUDP_construct(ConnectorUDP* ptr, knIPV4Endpoint listener_end, knIPV4Endpoint connector_end, OutputMode out_mode); +void ConnectorUDP_destruct(ConnectorUDP* ptr); +///@return doesn't return, INFINITE LOOP +void ConnectorUDP_start(ConnectorUDP* ptr); + +STRUCT(ConnectorTCP, + /* Hashtable */ + PipeStorage pipes; + knIPV4Endpoint listener_end; + knIPV4Endpoint connector_end; + knSocketTCP* main_sock; + OutputMode out_mode; +) + +void ConnectorTCP_construct(ConnectorTCP* ptr, knIPV4Endpoint listener_end, knIPV4Endpoint connector_end, OutputMode out_mode); +void ConnectorTCP_destruct(ConnectorTCP* ptr); +///@return doesn't return, INFINITE LOOP +void ConnectorTCP_start(ConnectorTCP* ptr); + +#if __cplusplus +} +#endif diff --git a/src/time.c b/src/time.c new file mode 100644 index 0000000..f8b23ee --- /dev/null +++ b/src/time.c @@ -0,0 +1,17 @@ +#include "port-tunnel.h" + +nsec_t getTimeNsec(){ + struct timespec t; + if(clock_gettime(CLOCK_REALTIME, &t) != 0) + throw(ERR_UNEXPECTEDVAL); + u64 n = t.tv_sec * 10e9 + t.tv_nsec; + return n; +} + +usec_t getTimeUsec(){ + struct timespec t; + if(clock_gettime(CLOCK_REALTIME, &t) != 0) + throw(ERR_UNEXPECTEDVAL); + u64 n = t.tv_sec * 10e6 + t.tv_nsec / 10e3; + return n; +}