{"id":46184792,"url":"https://github.com/neilstephens/miniplex","last_synced_at":"2026-05-04T10:04:04.113Z","repository":{"id":151807917,"uuid":"618701239","full_name":"neilstephens/MiniPlex","owner":"neilstephens","description":"A minimal UDP/TCP/Serial multiplexer/hub/broker. A simple way to bolt-on rudimentary multi-cast/multi-path or combine connections.","archived":false,"fork":false,"pushed_at":"2026-05-04T06:21:13.000Z","size":245,"stargazers_count":1,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-04T08:23:51.734Z","etag":null,"topics":["broker","dnp3","framing","hub","multi-path","multiplexer","serial","tcp","udp"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neilstephens.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-25T05:00:38.000Z","updated_at":"2026-05-04T06:21:17.000Z","dependencies_parsed_at":"2024-02-16T11:32:29.997Z","dependency_job_id":"01898bbb-1000-4a13-9f9e-e110a8bc5d39","html_url":"https://github.com/neilstephens/MiniPlex","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/neilstephens/MiniPlex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neilstephens%2FMiniPlex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neilstephens%2FMiniPlex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neilstephens%2FMiniPlex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neilstephens%2FMiniPlex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neilstephens","download_url":"https://codeload.github.com/neilstephens/MiniPlex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neilstephens%2FMiniPlex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32602730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["broker","dnp3","framing","hub","multi-path","multiplexer","serial","tcp","udp"],"created_at":"2026-03-02T22:21:51.186Z","updated_at":"2026-05-04T10:04:04.100Z","avatar_url":"https://github.com/neilstephens.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MiniPlex\n[![MiniPlex Workflow](https://github.com/neilstephens/MiniPlex/actions/workflows/MiniPlex.yml/badge.svg)](https://github.com/neilstephens/MiniPlex/actions/workflows/MiniPlex.yml)\n\n## Synopsis\n```\n\nMiniPlex: A minimal UDP multiplexer/hub/broker.\nProtoConv: Protocol adapter to convert between a stream and datagrams.\n\n\t\tIn combination, a simple way to bolt-on rudimentary multi-cast/multi-path or combine connections for existing applications\n\nUSAGE: \n\n   ./MiniPlex  {-H|-T|-P|-X} -p \u003cport\u003e [-l \u003clocaladdr\u003e] [-Z \u003crcv buf size\u003e]\n               [-Y \u003cqueue size\u003e] [-o \u003ctimeout\u003e] [-O \u003cbranch cache max\u003e] [-n\n               \u003cswitch cache max\u003e] [-r \u003ctrunk host\u003e] [-t \u003ctrunk port\u003e] [-B\n               \u003cbranch host\u003e] ... [-b \u003cbranch port\u003e] ... [-C \u003cswitchmode\n               bytecode file\u003e] [-c \u003cconsole log level\u003e] [-f \u003cfile log\n               level\u003e] [-F \u003clog filename\u003e] [-S \u003csize in kB\u003e] [-N \u003cnumber of\n               files\u003e] [-x \u003cnum threads\u003e] [-M] [-m \u003cmilliseconds\u003e] [--]\n               [--version] [-h]\n\n\nWhere: \n\n   -H,  --hub\n     (OR required)  Hub mode: Forward datagrams from/to all endpoints.\n         -- OR --\n   -T,  --trunk\n     (OR required)  Trunk mode: Forward frames from a 'trunk' to other\n     endpoints. Forward datagrams from other endpoints to the trunk.\n         -- OR --\n   -P,  --prune\n     (OR required)  Like Trunk mode, but limits flow to one (first in best\n     dressed) branch\n         -- OR --\n   -X,  --switch\n     (OR required)  Switch mode: forward datagrams based on application\n     addresses.\n\n\n   -p \u003cport\u003e,  --port \u003cport\u003e\n     (required)  Local port to listen/receive on.\n\n   -l \u003clocaladdr\u003e,  --local \u003clocaladdr\u003e\n     Local ip address. Defaults to 0.0.0.0 for all ipv4 interfaces.\n\n   -Z \u003crcv buf size\u003e,  --so_rcvbuf \u003crcv buf size\u003e\n     Datagram socket receive buffer size.\n\n   -Y \u003cqueue size\u003e,  --max_process_q \u003cqueue size\u003e\n     Maximun number of datagram buffers to allocate. If this limit is\n     reached, reading the socket is delayed until processing catches up\n\n   -o \u003ctimeout\u003e,  --timeout \u003ctimeout\u003e\n     Milliseconds to keep an idle endpoint cached\n\n   -O \u003cbranch cache max\u003e,  --branch_cache_max \u003cbranch cache max\u003e\n     Max number of entries in the active branch cache\n\n   -n \u003cswitch cache max\u003e,  --switch_cache_max \u003cswitch cache max\u003e\n     Max number of branches to cache for each switch mode address\n\n   -r \u003ctrunk host\u003e,  --trunk_ip \u003ctrunk host\u003e\n     Remote trunk ip address.\n\n   -t \u003ctrunk port\u003e,  --trunk_port \u003ctrunk port\u003e\n     Remote trunk port.\n\n   -B \u003cbranch host\u003e,  --branch_ip \u003cbranch host\u003e  (accepted multiple times)\n     Remote endpoint addresses to permanently cache. Use -b to provide\n     respective ports in the same order.\n\n   -b \u003cbranch port\u003e,  --branch_port \u003cbranch port\u003e  (accepted multiple\n      times)\n     Remote endpoint port to permanently cache. Use -B to provide\n     respective addresses in the same order.\n\n   -C \u003cswitchmode bytecode file\u003e,  --byte_code \u003cswitchmode bytecode file\u003e\n     RV64IM RISC-V byte code file. Switch mode code for extracting src and\n     dst addrs from packet data.\n\n     Pre-conditions: a0=\u0026buf, a1=buf_size, a2=\u0026src, a3=\u0026dst.\n     Post-execution: result = a0 (success result==0, src/dst have been\n     written).\n\n   -c \u003cconsole log level\u003e,  --console_logging \u003cconsole log level\u003e\n     Console log level: off, critical, error, warn, info, debug, or trace.\n     Default critical.\n\n   -f \u003cfile log level\u003e,  --file_logging \u003cfile log level\u003e\n     File log level: off, critical, error, warn, info, debug, or trace.\n     Default error.\n\n   -F \u003clog filename\u003e,  --log_file \u003clog filename\u003e\n     Log filename. Defaults to ./MiniPlex.log\n\n   -S \u003csize in kB\u003e,  --log_size \u003csize in kB\u003e\n     Roll the log file at this many kB. Defaults to 5000\n\n   -N \u003cnumber of files\u003e,  --log_num \u003cnumber of files\u003e\n     Keep this many log files when rolling the log. Defaults to 3\n\n   -x \u003cnum threads\u003e,  --concurrency \u003cnum threads\u003e\n     A hint for the number of threads in thread pool. Defaults to detected\n     hardware concurrency.\n\n   -M,  --benchmark\n     Run a loopback test for fixed duration (see -m) and exit.\n\n   -m \u003cmilliseconds\u003e,  --benchmark_duration \u003cmilliseconds\u003e\n     Number of milliseconds to run the loopback benchmark test. Defaults to\n     10000.\n\n   --,  --ignore_rest\n     Ignores the rest of the labeled arguments following this flag.\n\n   --version\n     Displays version information and exits.\n\n   -h,  --help\n     Displays usage information and exits.\n\n\n=================================================================================\n\n\n   ./ProtoConv  -l \u003clocal port\u003e [-a \u003clocal addr\u003e] -A \u003cremote addr\u003e -r\n                \u003cremote port\u003e [-B \u003crcv buf size\u003e] [-Q \u003cmax write queue\n                size\u003e] [-D \u003cpacket delimiter\u003e] [-q \u003cmax out-of-order\n                frames\u003e] [-m \u003cmax out-of-order frame wait ms\u003e] [-T \u003cremote\n                tcp host\u003e] [-C \u003ctcp is client\u003e] [-k \u003ctcp connection retry\n                times\u003e] [-t \u003cremote tcp port\u003e] [-s \u003cserial devices\u003e] ...\n                [-b \u003cserial bauds rates\u003e] ... [-L \u003cserial flow ctl\n                settings\u003e] ... [-Z \u003cserial char sizes\u003e] ... [-i \u003cserial\n                stop bits\u003e] ... [-p \u003cframe protocol\u003e] [-c \u003cconsole log\n                level\u003e] [-f \u003cfile log level\u003e] [-F \u003clog filename\u003e] [-S \u003clog\n                file size in kB\u003e] [-N \u003cnumber of log files\u003e] [-x\n                \u003cnumthreads\u003e] [--] [--version] [-h]\n\n\nWhere: \n\n   -l \u003clocal port\u003e,  --localport \u003clocal port\u003e\n     (required)  Local port to listen/receive datagrams on.\n\n   -a \u003clocal addr\u003e,  --localaddr \u003clocal addr\u003e\n     Local ip address for datagrams. Defaults to 0.0.0.0 for all ipv4\n     interfaces.\n\n   -A \u003cremote addr\u003e,  --remoteaddr \u003cremote addr\u003e\n     (required)  Remote ip address for datagrams.\n\n   -r \u003cremote port\u003e,  --remoteport \u003cremote port\u003e\n     (required)  Remote port for datagrams.\n\n   -B \u003crcv buf size\u003e,  --so_rcvbuf \u003crcv buf size\u003e\n     Datagram socket receive buffer size.\n\n   -Q \u003cmax write queue size\u003e,  --write_queue_size \u003cmax write queue size\u003e\n     Max number of messages to buffer in the stream writer queue before\n     dropping (older) data.\n\n   -D \u003cpacket delimiter\u003e,  --packet_delimiter \u003cpacket delimiter\u003e\n     Use a packet delimiter (inserted in the stream with sequence and CRC)\n     instead of protocol framing.\n\n   -q \u003cmax out-of-order frames\u003e,  --max_sequence_reorder \u003cmax out-of-order\n      frames\u003e\n     Tolerance for frame re-ordering: max frames to buffer waiting for the\n     next sequence number.\n\n   -m \u003cmax out-of-order frame wait ms\u003e,  --max_sequence_age_ms \u003cmax\n      out-of-order frame wait ms\u003e\n     Tolerance for frame re-ordering: max time (ms) to wait for the next\n     sequence number.\n\n   -T \u003cremote tcp host\u003e,  --tcphost \u003cremote tcp host\u003e\n     If converting TCP, this is the remote IP address for the connection.\n\n   -C \u003ctcp is client\u003e,  --tcpisclient \u003ctcp is client\u003e\n     If converting TCP, this is defines if it's a client or server\n     connection.\n\n   -k \u003ctcp connection retry times\u003e,  --tcpretrytimes \u003ctcp connection retry\n      times\u003e\n     Timing parameters for the tcp connection retry exponential backoff:\n     '\u003cMinRetryTime\u003e \u003cMaxRetryTime\u003e \u003cEstablishedResetTime\u003e' in\n     milliseconds\n\n   -t \u003cremote tcp port\u003e,  --tcpport \u003cremote tcp port\u003e\n     TCP port if converting TCP.\n\n   -s \u003cserial devices\u003e,  --serialdevices \u003cserial devices\u003e  (accepted\n      multiple times)\n     List of serial devices, if converting serial\n\n   -b \u003cserial bauds rates\u003e,  --serialbauds \u003cserial bauds rates\u003e  (accepted\n      multiple times)\n     List of serial board rates, if converting serial\n\n   -L \u003cserial flow ctl settings\u003e,  --serialflowctl \u003cserial flow ctl\n      settings\u003e  (accepted multiple times)\n     List of serial flow control settings, if converting serial\n\n   -Z \u003cserial char sizes\u003e,  --serialcharsize \u003cserial char sizes\u003e  (accepted\n      multiple times)\n     List of serial char sizes, if converting serial\n\n   -i \u003cserial stop bits\u003e,  --serialstopbits \u003cserial stop bits\u003e  (accepted\n      multiple times)\n     List of serial stop bits settings, if converting serial\n\n   -p \u003cframe protocol\u003e,  --frameprotocol \u003cframe protocol\u003e\n     Parse stream frames based on this protocol\n\n   -c \u003cconsole log level\u003e,  --console_logging \u003cconsole log level\u003e\n     Console log level: off, critical, error, warn, info, debug, or trace.\n     Default critical.\n\n   -f \u003cfile log level\u003e,  --file_logging \u003cfile log level\u003e\n     File log level: off, critical, error, warn, info, debug, or trace.\n     Default error.\n\n   -F \u003clog filename\u003e,  --log_file \u003clog filename\u003e\n     Log filename. Defaults to ./ProtoConv.log\n\n   -S \u003clog file size in kB\u003e,  --log_size \u003clog file size in kB\u003e\n     Roll the log file at this many kB. Defaults to 5000\n\n   -N \u003cnumber of log files\u003e,  --log_num \u003cnumber of log files\u003e\n     Keep this many log files when rolling the log. Defaults to 3\n\n   -x \u003cnumthreads\u003e,  --concurrency \u003cnumthreads\u003e\n     A hint for the number of threads in thread pool. Defaults to detected\n     hardware concurrency.\n\n   --,  --ignore_rest\n     Ignores the rest of the labeled arguments following this flag.\n\n   --version\n     Displays version information and exits.\n\n   -h,  --help\n     Displays usage information and exits.\n   \n```\n\n## Get MiniPlex\n\nYou can download a pre-built binaries for various platforms from the github [Releases](https://github.com/neilstephens/MiniPlex/releases) section. Alternatively, simply build your own copy from source using the instructions below.\n\n## Example Use Case\n\nSuppose you have a network that doesn't support UDP multicast. Maybe it's disabled for security or performance, or maybe you like firewall policies to have strict point-to-point rules.\nBut you would still like to stream UDP packets to multiple endpoints. This is where MiniPlex can help. MiniPlex can convert a single unicast stream into multiple streams, or route packets in any number of ways. For example:\n\n### Stream some audio to multiple endpoints:\n\nRun MiniPlex to listen on port 1234 in hub mode any incoming datagrams will be forwarded to all branches.\nWe specify two fixed branches on the command line, because they will just passively recieve data:\n\n```\n./MiniPlex -H -p 1234 -B 192.168.1.5 -b 1234 -B 192.168.1.6 -b 1234\n```\n\nUse vlc to stream out some unicast UDP audio:\n\n```\nvlc sftp://192.168.1.2/Music/ --sout=\"#std{access=udp, mux=ts, dst=127.0.0.1:1234}\"\n```\n\nOn the branch hosts (192.168.1.5 and 192.168.1.6 in this example) run vlc to recieve the the audio that is being forwarded by MiniPlex:\n\n```\nvlc udp://@:1234\n```\n\n### UDP Switch\n\nSee [these examples](Examples/SwitchBytecode/README.md) for how to use MiniPlex as a layer 4 UDP switch! The examples include VXLAN, WireGuard and DNP3, but any address based protocol is possible.\n\n## Build\n\nAssuming\n  * You've git cloned this repo into a directory called 'MiniPlex' (source directory),\n  * Created an adjacent build directory called MiniPlex-bin,\n  * Have the appropriate c++20 toolchain installed (earlier version might work, but aren't tested):\n    * g++ \u003e= 9.4.0, or\n    * clang \u003e= 10.0.0, or\n    * MSVC \u003e= VS 2019 v16.11\n\n### Configure the build\n\n```\ncmake -S MiniPlex -B MiniPlex-bin\n```\nThis will automatically clone and init the submodules repo dependencies for spdlog, tclap and asio and configure the default build system.\n\n### Run the build\n```\ncmake --build MiniPlex-bin\n```\nYou should have a MiniPlex executable in MiniPlex-bin. See the synopsis above for how to use it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneilstephens%2Fminiplex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneilstephens%2Fminiplex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneilstephens%2Fminiplex/lists"}