Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 16 additions & 20 deletions meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)

Expand Down
17 changes: 1 addition & 16 deletions meshtastic/tests/test_tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,12 @@

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)


@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):
Expand Down
8 changes: 3 additions & 5 deletions meshtastic/tunnel.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -109,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(
Expand Down
70 changes: 35 additions & 35 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading