From 358083effcd245cebfb5d73880449b670692e5ed Mon Sep 17 00:00:00 2001 From: Federico Santandrea Date: Mon, 26 Oct 2026 15:17:52 +0100 Subject: [PATCH 1/5] Use pytap3 to provide IP tunnelling cross-platform --- .github/copilot-instructions.md | 2 +- meshtastic/__main__.py | 36 ++++++++--------- meshtastic/tests/test_tunnel.py | 2 +- meshtastic/tunnel.py | 7 +--- poetry.lock | 70 ++++++++++++++++----------------- pyproject.toml | 4 +- tests/tuntest.py | 4 +- 7 files changed, 59 insertions(+), 66 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index aa0afdcf5..96b4b13c9 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -194,7 +194,7 @@ The CLI is in `meshtastic/__main__.py`. When adding new CLI commands: ### Optional (extras) - `cli` extra: `pyqrcode`, `print-color`, `dotmap`, `argcomplete` -- `tunnel` extra: `pytap2` +- `tunnel` extra: `pytap3` - `analysis` extra: `dash`, `pandas` ## Important Notes diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index ca1680a58..288d48cde 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -1165,8 +1165,7 @@ def setSimpleConfig(modem_preset): if args.listen: closeNow = False - have_tunnel = platform.system() == "Linux" - if have_tunnel and args.tunnel: + if args.tunnel: if args.dest != BROADCAST_ADDR: print("A tunnel can only be created using the local node.") return @@ -1790,11 +1789,10 @@ def common(): # We assume client is fully connected now onConnected(client) - have_tunnel = platform.system() == "Linux" if ( args.noproto or args.reply - or (have_tunnel and args.tunnel) + or args.tunnel or args.listen ): # loop until someone presses ctrlc try: @@ -2581,22 +2579,20 @@ def initParser(): "--gpio-watch", help="Start watching a GPIO mask for changes (ex: '0x10')" ) - have_tunnel = platform.system() == "Linux" - if have_tunnel: - tunnelArgs = parser.add_argument_group( - "Tunnel", "Arguments related to establishing a tunnel device over the mesh." - ) - tunnelArgs.add_argument( - "--tunnel", - action="store_true", - help="Create a TUN tunnel device for forwarding IP packets over the mesh", - ) - tunnelArgs.add_argument( - "--subnet", - dest="tunnel_net", - help="Sets the local-end subnet address for the TUN IP bridge. (ex: 10.115' which is the default)", - default=None, - ) + tunnelArgs = parser.add_argument_group( + "Tunnel", "Arguments related to establishing a tunnel device over the mesh." + ) + tunnelArgs.add_argument( + "--tunnel", + action="store_true", + help="Create a TUN tunnel device for forwarding IP packets over the mesh", + ) + tunnelArgs.add_argument( + "--subnet", + dest="tunnel_net", + help="Sets the local-end subnet address for the TUN IP bridge. (ex: 10.115' which is the default)", + default=None, + ) parser.set_defaults(deprecated=None) diff --git a/meshtastic/tests/test_tunnel.py b/meshtastic/tests/test_tunnel.py index e2e917e5b..ac8f5706a 100644 --- a/meshtastic/tests/test_tunnel.py +++ b/meshtastic/tests/test_tunnel.py @@ -10,7 +10,7 @@ from ..tcp_interface import TCPInterface try: - # Depends upon pytap2, not installed by default + # Depends upon pytap3, not installed by default from ..tunnel import Tunnel, onTunnelReceive except ImportError: pytest.skip("Can't import Tunnel or onTunnelReceive", allow_module_level=True) diff --git a/meshtastic/tunnel.py b/meshtastic/tunnel.py index 46e3a2e0d..3f0e8b09b 100644 --- a/meshtastic/tunnel.py +++ b/meshtastic/tunnel.py @@ -1,7 +1,7 @@ """Code for IP tunnel over a mesh # Note python-pytuntap was too buggy -# using pip3 install pytap2 +# using pip3 install pytap3 # make sure to "sudo setcap cap_net_admin+eip /usr/bin/python3.8" so python can access tun device without being root # sudo ip tuntap del mode tun tun0 # sudo bin/run.sh --port /dev/ttyUSB0 --setch-shortfast @@ -20,7 +20,7 @@ import threading from pubsub import pub # type: ignore[import-untyped] -from pytap2 import TapDevice +from pytap3 import TapDevice from meshtastic.protobuf import portnums_pb2 from meshtastic import mt_config @@ -64,9 +64,6 @@ def __init__(self, iface, subnet: str="10.115", netmask: str="255.255.0.0") -> N self.iface = iface self.subnetPrefix = subnet - if platform.system() != "Linux": - raise Tunnel.TunnelError("Tunnel() can only be run instantiated on a Linux system") - mt_config.tunnelInstance = self """A list of chatty UDP services we should never accidentally diff --git a/poetry.lock b/poetry.lock index d82445c45..5a6466781 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.5.1 and should not be changed by hand. [[package]] name = "altgraph" @@ -1777,7 +1777,7 @@ comm = ">=0.1.1" debugpy = ">=1.6.5" ipython = ">=7.23.1" jupyter-client = ">=8.0.0" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0 || >=5.1.dev0" matplotlib-inline = ">=0.1" nest-asyncio = ">=1.4" packaging = ">=22" @@ -1812,7 +1812,7 @@ comm = ">=0.1.1" debugpy = ">=1.6.5" ipython = ">=7.23.1" jupyter-client = ">=8.0.0" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0 || >=5.1.dev0" matplotlib-inline = ">=0.1" nest-asyncio = ">=1.4" packaging = ">=22" @@ -2093,7 +2093,7 @@ fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} -jsonschema-specifications = ">=2023.03.6" +jsonschema-specifications = ">=2023.3.6" referencing = ">=0.28.4" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} @@ -2135,7 +2135,7 @@ files = [ [package.dependencies] importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0 || >=5.1.dev0" python-dateutil = ">=2.8.2" pyzmq = ">=23.0" tornado = ">=6.2" @@ -2249,7 +2249,7 @@ anyio = ">=3.1.0" argon2-cffi = ">=21.1" jinja2 = ">=3.0.3" jupyter-client = ">=7.4.4" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0 || >=5.1.dev0" jupyter-events = ">=0.11.0" jupyter-server-terminals = ">=0.4.4" nbconvert = ">=6.4.4" @@ -2287,7 +2287,7 @@ anyio = ">=3.1.0" argon2-cffi = ">=21.1" jinja2 = ">=3.0.3" jupyter-client = ">=7.4.4" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0 || >=5.1.dev0" jupyter-events = ">=0.11.0" jupyter-server-terminals = ">=0.4.4" nbconvert = ">=6.4.4" @@ -2343,7 +2343,7 @@ files = [ async-lru = ">=1.0.0" httpx = ">=0.25.0,<1" importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -ipykernel = ">=6.5.0,<6.30.0 || >6.30.0" +ipykernel = ">=6.5.0,!=6.30.0" jinja2 = ">=3.0.3" jupyter-core = "*" jupyter-lsp = ">=2.0.0" @@ -3178,7 +3178,7 @@ files = [ [package.dependencies] jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0 || >=5.1.dev0" nbformat = ">=5.1" traitlets = ">=5.4" @@ -3240,7 +3240,7 @@ files = [ [package.dependencies] fastjsonschema = ">=2.15" jsonschema = ">=2.6" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0 || >=5.1.dev0" traitlets = ">=5.1" [package.extras] @@ -3513,8 +3513,8 @@ files = [ [package.dependencies] numpy = [ {version = ">=1.22.4", markers = "python_version < \"3.11\""}, - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -4343,7 +4343,7 @@ altgraph = "*" importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} packaging = ">=22.0" -pefile = {version = ">=2022.5.30,<2024.8.26 || >2024.8.26", markers = "sys_platform == \"win32\""} +pefile = {version = ">=2022.5.30,!=2024.8.26", markers = "sys_platform == \"win32\""} pyinstaller-hooks-contrib = ">=2025.8" pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} setuptools = ">=42.0.0" @@ -4386,10 +4386,10 @@ astroid = ">=3.3.8,<=3.4.0.dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, - {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, {version = ">=0.3.6", markers = "python_version == \"3.11\""}, + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, ] -isort = ">=4.2.5,<5.13 || >5.13,<7" +isort = ">=4.2.5,!=5.13,<7" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2" tomli = {version = ">=1.1", markers = "python_version < \"3.11\""} @@ -4511,6 +4511,7 @@ python-versions = ">=3.3, <4" groups = ["main"] files = [ {file = "Pypubsub-4.0.3-py3-none-any.whl", hash = "sha256:7f716bae9388afe01ff82b264ba8a96a8ae78b42bb1f114f2716ca8f9e404e2a"}, + {file = "pypubsub-4.0.3.tar.gz", hash = "sha256:32d662de3ade0fb0880da92df209c62a4803684de5ccb8d19421c92747a258c7"}, ] [[package]] @@ -4545,16 +4546,15 @@ files = [ cp2110 = ["hidapi"] [[package]] -name = "pytap2" -version = "2.3.0" -description = "Object-oriented wrapper around the Linux Tun/Tap device" +name = "pytap3" +version = "3.0.0" +description = "Cross-platform tunnel interface for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"tunnel\"" files = [ - {file = "pytap2-2.3.0-py3-none-any.whl", hash = "sha256:a1edc287cf25c61f8fa8415fb6b61e50ac119ef5cd758ce15f2105d2c69f24ef"}, - {file = "pytap2-2.3.0.tar.gz", hash = "sha256:5a90d7b7c7107a438e53c7b27c1baadffe72889ada6024c02d19801fece2c383"}, + {file = "pytap3-3.0.0.tar.gz", hash = "sha256:ae86bf160affe7391611b8d73203d24fdf1f1e2884e8ef473c3f7e23f5ce5ba6"}, ] [[package]] @@ -5935,10 +5935,10 @@ files = [ ] [package.dependencies] -winrt-runtime = ">=3.2.1.0,<3.3.0.0" +winrt-runtime = ">=3.2.1.0,<3.2.2.0" [package.extras] -all = ["winrt-Windows.Devices.Bluetooth.GenericAttributeProfile[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Devices.Bluetooth.Rfcomm[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Devices.Enumeration[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Devices.Radios[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Networking[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.3.0.0)"] +all = ["winrt-Windows.Devices.Bluetooth.GenericAttributeProfile[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Devices.Bluetooth.Rfcomm[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Devices.Enumeration[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Devices.Radios[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Networking[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.2.2.0)"] [[package]] name = "winrt-windows-devices-bluetooth-advertisement" @@ -5971,10 +5971,10 @@ files = [ ] [package.dependencies] -winrt-runtime = ">=3.2.1.0,<3.3.0.0" +winrt-runtime = ">=3.2.1.0,<3.2.2.0" [package.extras] -all = ["winrt-Windows.Devices.Bluetooth[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.3.0.0)"] +all = ["winrt-Windows.Devices.Bluetooth[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.2.2.0)"] [[package]] name = "winrt-windows-devices-bluetooth-genericattributeprofile" @@ -6007,10 +6007,10 @@ files = [ ] [package.dependencies] -winrt-runtime = ">=3.2.1.0,<3.3.0.0" +winrt-runtime = ">=3.2.1.0,<3.2.2.0" [package.extras] -all = ["winrt-Windows.Devices.Bluetooth[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Devices.Enumeration[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.3.0.0)"] +all = ["winrt-Windows.Devices.Bluetooth[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Devices.Enumeration[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.2.2.0)"] [[package]] name = "winrt-windows-devices-enumeration" @@ -6043,10 +6043,10 @@ files = [ ] [package.dependencies] -winrt-runtime = ">=3.2.1.0,<3.3.0.0" +winrt-runtime = ">=3.2.1.0,<3.2.2.0" [package.extras] -all = ["winrt-Windows.ApplicationModel.Background[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Security.Credentials[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.UI.Popups[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.UI[all] (>=3.2.1.0,<3.3.0.0)"] +all = ["winrt-Windows.ApplicationModel.Background[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Security.Credentials[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Storage.Streams[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.UI.Popups[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.UI[all] (>=3.2.1.0,<3.2.2.0)"] [[package]] name = "winrt-windows-foundation" @@ -6079,10 +6079,10 @@ files = [ ] [package.dependencies] -winrt-runtime = ">=3.2.1.0,<3.3.0.0" +winrt-runtime = ">=3.2.1.0,<3.2.2.0" [package.extras] -all = ["winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)"] +all = ["winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.2.2.0)"] [[package]] name = "winrt-windows-foundation-collections" @@ -6115,10 +6115,10 @@ files = [ ] [package.dependencies] -winrt-runtime = ">=3.2.1.0,<3.3.0.0" +winrt-runtime = ">=3.2.1.0,<3.2.2.0" [package.extras] -all = ["winrt-Windows.Foundation[all] (>=3.2.1.0,<3.3.0.0)"] +all = ["winrt-Windows.Foundation[all] (>=3.2.1.0,<3.2.2.0)"] [[package]] name = "winrt-windows-storage-streams" @@ -6151,10 +6151,10 @@ files = [ ] [package.dependencies] -winrt-runtime = ">=3.2.1.0,<3.3.0.0" +winrt-runtime = ">=3.2.1.0,<3.2.2.0" [package.extras] -all = ["winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Storage[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.System[all] (>=3.2.1.0,<3.3.0.0)"] +all = ["winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.Storage[all] (>=3.2.1.0,<3.2.2.0)", "winrt-Windows.System[all] (>=3.2.1.0,<3.2.2.0)"] [[package]] name = "zipp" @@ -6180,9 +6180,9 @@ type = ["pytest-mypy"] [extras] analysis = ["dash", "dash-bootstrap-components", "pandas", "pandas-stubs"] cli = ["argcomplete", "dotmap", "print-color", "pyqrcode", "wcwidth"] -tunnel = ["pytap2"] +tunnel = ["pytap3"] [metadata] lock-version = "2.1" python-versions = "^3.9,<3.15" -content-hash = "7dd0dc28e13f7569f1a8cc28453d5983a6f742790d9328bafe86d1a2914d88ad" +content-hash = "83406ca243dbd819df86686734f37ac5d9ea27914ccda7f384c1d0aea467414d" diff --git a/pyproject.toml b/pyproject.toml index 6d2b28b2a..114ea9e96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ pyqrcode = { version = "^1.2.1", optional = true } dotmap = { version = "^1.3.30", optional = true } print-color = { version = "^0.4.6", optional = true } dash = { version = "^2.17.1", optional = true } -pytap2 = { version = "^2.3.0", optional = true } +pytap3 = { version = "^3.0.0", optional = true } dash-bootstrap-components = { version = "^1.6.0", optional = true } pandas = { version = "^2.2.2", optional = true } pandas-stubs = { version = "^2.2.2.240603", optional = true } @@ -70,7 +70,7 @@ jupyterlab-widgets = "^3.0.11" [tool.poetry.extras] cli = ["pyqrcode", "print-color", "dotmap", "argcomplete", "wcwidth"] -tunnel = ["pytap2"] +tunnel = ["pytap3"] analysis = ["dash", "dash-bootstrap-components", "pandas", "pandas-stubs"] [tool.poetry.scripts] diff --git a/tests/tuntest.py b/tests/tuntest.py index 38f623124..3e0d3a35f 100644 --- a/tests/tuntest.py +++ b/tests/tuntest.py @@ -1,6 +1,6 @@ # delete me eventually # Note python-pytuntap was too buggy -# using pip3 install pytap2 +# using pip3 install pytap3 # make sure to "sudo setcap cap_net_admin+eip /usr/bin/python3.8" so python can access tun device without being root # sudo ip tuntap del mode tun tun0 @@ -11,7 +11,7 @@ import logging from _thread import start_new_thread -from pytap2 import TapDevice +from pytap3 import TapDevice """A list of chatty UDP services we should never accidentally forward to our slow network""" From a81ded80078eefaa971c0a53ecf0c5fab386a865 Mon Sep 17 00:00:00 2001 From: Federico Santandrea Date: Mon, 26 Oct 2026 15:35:12 +0100 Subject: [PATCH 2/5] Fixed CodeRabbit comments --- meshtastic/tests/test_tunnel.py | 15 --------------- meshtastic/tunnel.py | 1 + 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/meshtastic/tests/test_tunnel.py b/meshtastic/tests/test_tunnel.py index ac8f5706a..0199c8f51 100644 --- a/meshtastic/tests/test_tunnel.py +++ b/meshtastic/tests/test_tunnel.py @@ -16,21 +16,6 @@ pytest.skip("Can't import Tunnel or onTunnelReceive", allow_module_level=True) -@pytest.mark.unit -@patch("platform.system") -def test_Tunnel_on_non_linux_system(mock_platform_system): - """Test that we cannot instantiate a Tunnel on a non Linux system""" - a_mock = MagicMock() - a_mock.return_value = "notLinux" - mock_platform_system.side_effect = a_mock - with patch("socket.socket") as mock_socket: - with pytest.raises(Tunnel.TunnelError) as pytest_wrapped_e: - iface = TCPInterface(hostname="localhost", noProto=True) - Tunnel(iface) - assert pytest_wrapped_e.type == Tunnel.TunnelError - assert mock_socket.called - - @pytest.mark.unit @patch("platform.system") def test_Tunnel_without_interface(mock_platform_system): diff --git a/meshtastic/tunnel.py b/meshtastic/tunnel.py index 3f0e8b09b..7013f13b4 100644 --- a/meshtastic/tunnel.py +++ b/meshtastic/tunnel.py @@ -106,6 +106,7 @@ def __init__(self, iface, subnet: str="10.115", netmask: str="255.255.0.0") -> N logger.debug("creating TUN device with MTU=200") # FIXME - figure out real max MTU, it should be 240 - the overhead bytes for SubPacket and Data + # Windows would like an MTU >= 576 bytes, but in practice the tunnel works without issues. self.tun = None if self.iface.noProto: logger.warning( From 9b341790c7d75ddb6a740fb3afe2807117902f99 Mon Sep 17 00:00:00 2001 From: Federico Santandrea Date: Mon, 26 Oct 2026 16:03:05 +0100 Subject: [PATCH 3/5] Fixed CodeRabbit comment --- poetry.lock | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5a6466781..bcdea3f29 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4547,14 +4547,14 @@ cp2110 = ["hidapi"] [[package]] name = "pytap3" -version = "3.0.0" +version = "3.0.1" description = "Cross-platform tunnel interface for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"tunnel\"" files = [ - {file = "pytap3-3.0.0.tar.gz", hash = "sha256:ae86bf160affe7391611b8d73203d24fdf1f1e2884e8ef473c3f7e23f5ce5ba6"}, + {file = "pytap3-3.0.1.tar.gz", hash = "sha256:a5151bcea8fd8ece1000d4be7346246a2395dddaf681896b0e4004a31d440197"}, ] [[package]] @@ -6185,4 +6185,4 @@ tunnel = ["pytap3"] [metadata] lock-version = "2.1" python-versions = "^3.9,<3.15" -content-hash = "83406ca243dbd819df86686734f37ac5d9ea27914ccda7f384c1d0aea467414d" +content-hash = "b16d2d3764dd59e45de792165a2d2ed9bb6cc487c878e60eb2047e2a5e3bae83" diff --git a/pyproject.toml b/pyproject.toml index 114ea9e96..23076799f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ pyqrcode = { version = "^1.2.1", optional = true } dotmap = { version = "^1.3.30", optional = true } print-color = { version = "^0.4.6", optional = true } dash = { version = "^2.17.1", optional = true } -pytap3 = { version = "^3.0.0", optional = true } +pytap3 = { version = ">=3.0.1", optional = true } dash-bootstrap-components = { version = "^1.6.0", optional = true } pandas = { version = "^2.2.2", optional = true } pandas-stubs = { version = "^2.2.2.240603", optional = true } From 0996a886aefbdab771fc435802955558af7ec09a Mon Sep 17 00:00:00 2001 From: Federico Santandrea Date: Mon, 26 Oct 2026 16:27:18 +0100 Subject: [PATCH 4/5] Using pytap3 version 3.0.2 --- poetry.lock | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index bcdea3f29..6bfc1690b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4547,14 +4547,14 @@ cp2110 = ["hidapi"] [[package]] name = "pytap3" -version = "3.0.1" +version = "3.0.2" description = "Cross-platform tunnel interface for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"tunnel\"" files = [ - {file = "pytap3-3.0.1.tar.gz", hash = "sha256:a5151bcea8fd8ece1000d4be7346246a2395dddaf681896b0e4004a31d440197"}, + {file = "pytap3-3.0.2.tar.gz", hash = "sha256:0ae36d8badc39bd2263e20ffcb02c32a641f85cf87431234b51b9c3cedc40063"}, ] [[package]] @@ -6185,4 +6185,4 @@ tunnel = ["pytap3"] [metadata] lock-version = "2.1" python-versions = "^3.9,<3.15" -content-hash = "b16d2d3764dd59e45de792165a2d2ed9bb6cc487c878e60eb2047e2a5e3bae83" +content-hash = "fc0d78fb1bbfe78504676fbe1fd1eb02a815a1cad26e7ed0b828c20bc1fd402c" diff --git a/pyproject.toml b/pyproject.toml index 23076799f..6854e1693 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ pyqrcode = { version = "^1.2.1", optional = true } dotmap = { version = "^1.3.30", optional = true } print-color = { version = "^0.4.6", optional = true } dash = { version = "^2.17.1", optional = true } -pytap3 = { version = ">=3.0.1", optional = true } +pytap3 = { version = ">=3.0.2", optional = true } dash-bootstrap-components = { version = "^1.6.0", optional = true } pandas = { version = "^2.2.2", optional = true } pandas-stubs = { version = "^2.2.2.240603", optional = true } From 3d8abf8cac6bad0f300ab98a227a9382244537f7 Mon Sep 17 00:00:00 2001 From: Federico Santandrea Date: Tue, 27 Oct 2026 20:14:10 +0100 Subject: [PATCH 5/5] Using newer pytap3 version --- poetry.lock | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6bfc1690b..d47970391 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4547,14 +4547,14 @@ cp2110 = ["hidapi"] [[package]] name = "pytap3" -version = "3.0.2" +version = "3.1.2" description = "Cross-platform tunnel interface for Python" optional = true python-versions = ">=3.8" groups = ["main"] markers = "extra == \"tunnel\"" files = [ - {file = "pytap3-3.0.2.tar.gz", hash = "sha256:0ae36d8badc39bd2263e20ffcb02c32a641f85cf87431234b51b9c3cedc40063"}, + {file = "pytap3-3.1.2.tar.gz", hash = "sha256:c260e3d00e6af57b1486e01ec45e5bb26299a827c8803a92b1acc4ef2201efe4"}, ] [[package]] @@ -6185,4 +6185,4 @@ tunnel = ["pytap3"] [metadata] lock-version = "2.1" python-versions = "^3.9,<3.15" -content-hash = "fc0d78fb1bbfe78504676fbe1fd1eb02a815a1cad26e7ed0b828c20bc1fd402c" +content-hash = "f0cb25533d38970846250f178ec62089abf9c0dd0da40bf893a46bc62b69d4ea" diff --git a/pyproject.toml b/pyproject.toml index 6854e1693..142886c4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ pyqrcode = { version = "^1.2.1", optional = true } dotmap = { version = "^1.3.30", optional = true } print-color = { version = "^0.4.6", optional = true } dash = { version = "^2.17.1", optional = true } -pytap3 = { version = ">=3.0.2", optional = true } +pytap3 = { version = ">=3.1.2", optional = true } dash-bootstrap-components = { version = "^1.6.0", optional = true } pandas = { version = "^2.2.2", optional = true } pandas-stubs = { version = "^2.2.2.240603", optional = true }