mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-22 13:40:19 +00:00
Compare commits
5 Commits
29693c6fe2
...
da7a4433c0
Author | SHA1 | Date | |
---|---|---|---|
|
da7a4433c0 | ||
|
5e5d89cc92 | ||
|
a3bee4baa9 | ||
|
fab83ec399 | ||
|
b740e36985 |
@ -190,7 +190,6 @@ these dependencies, and when the `rns` package is installed with `pip`, they
|
|||||||
will be downloaded and installed as well.
|
will be downloaded and installed as well.
|
||||||
|
|
||||||
- [PyCA/cryptography](https://github.com/pyca/cryptography)
|
- [PyCA/cryptography](https://github.com/pyca/cryptography)
|
||||||
- [netifaces](https://github.com/al45tair/netifaces)
|
|
||||||
- [pyserial](https://github.com/pyserial/pyserial)
|
- [pyserial](https://github.com/pyserial/pyserial)
|
||||||
|
|
||||||
On more unusual systems, and in some rare cases, it might not be possible to
|
On more unusual systems, and in some rare cases, it might not be possible to
|
||||||
@ -341,8 +340,8 @@ projects:
|
|||||||
- [Curve25519.py](https://gist.github.com/nickovs/cc3c22d15f239a2640c185035c06f8a3#file-curve25519-py) by [Nicko van Someren](https://gist.github.com/nickovs), *Public Domain*
|
- [Curve25519.py](https://gist.github.com/nickovs/cc3c22d15f239a2640c185035c06f8a3#file-curve25519-py) by [Nicko van Someren](https://gist.github.com/nickovs), *Public Domain*
|
||||||
- [I2Plib](https://github.com/l-n-s/i2plib) by [Viktor Villainov](https://github.com/l-n-s)
|
- [I2Plib](https://github.com/l-n-s/i2plib) by [Viktor Villainov](https://github.com/l-n-s)
|
||||||
- [PySerial](https://github.com/pyserial/pyserial) by Chris Liechti, *BSD License*
|
- [PySerial](https://github.com/pyserial/pyserial) by Chris Liechti, *BSD License*
|
||||||
- [Netifaces](https://github.com/al45tair/netifaces) by [Alastair Houghton](https://github.com/al45tair), *MIT License*
|
|
||||||
- [Configobj](https://github.com/DiffSK/configobj) by Michael Foord, Nicola Larosa, Rob Dennis & Eli Courtwright, *BSD License*
|
- [Configobj](https://github.com/DiffSK/configobj) by Michael Foord, Nicola Larosa, Rob Dennis & Eli Courtwright, *BSD License*
|
||||||
- [Six](https://github.com/benjaminp/six) by [Benjamin Peterson](https://github.com/benjaminp), *MIT License*
|
- [Six](https://github.com/benjaminp/six) by [Benjamin Peterson](https://github.com/benjaminp), *MIT License*
|
||||||
- [Umsgpack.py](https://github.com/vsergeev/u-msgpack-python) by [Ivan A. Sergeev](https://github.com/vsergeev)
|
- [Umsgpack.py](https://github.com/vsergeev/u-msgpack-python) by [Ivan A. Sergeev](https://github.com/vsergeev)
|
||||||
|
- [ifaddr](https://github.com/pydron/ifaddr) by [Pydron](https://github.com/pydron), *MIT License*
|
||||||
- [Python](https://www.python.org)
|
- [Python](https://www.python.org)
|
||||||
|
@ -62,16 +62,18 @@ class AutoInterface(Interface):
|
|||||||
link_local_addr = re.sub(r"fe80:[0-9a-f]*::","fe80::", link_local_addr)
|
link_local_addr = re.sub(r"fe80:[0-9a-f]*::","fe80::", link_local_addr)
|
||||||
return link_local_addr
|
return link_local_addr
|
||||||
|
|
||||||
def __init__(self, owner, name, group_id=None, discovery_scope=None, discovery_port=None, data_port=None, allowed_interfaces=None, ignored_interfaces=None, configured_bitrate=None):
|
def list_interfaces(self):
|
||||||
import importlib
|
ifs = self.netinfo.interfaces()
|
||||||
if importlib.util.find_spec('netifaces') != None:
|
return ifs
|
||||||
import netifaces
|
|
||||||
else:
|
def list_addresses(self, ifname):
|
||||||
RNS.log("Using AutoInterface requires the netifaces module.", RNS.LOG_CRITICAL)
|
ifas = self.netinfo.ifaddresses(ifname)
|
||||||
RNS.log("You can install it with the command: python3 -m pip install netifaces", RNS.LOG_CRITICAL)
|
return ifas
|
||||||
RNS.panic()
|
|
||||||
|
def __init__(self, owner, name, group_id=None, discovery_scope=None, discovery_port=None, data_port=None, allowed_interfaces=None, ignored_interfaces=None, configured_bitrate=None):
|
||||||
|
from RNS.vendor.ifaddr import niwrapper
|
||||||
|
self.netinfo = niwrapper
|
||||||
|
|
||||||
self.netifaces = netifaces
|
|
||||||
self.rxb = 0
|
self.rxb = 0
|
||||||
self.txb = 0
|
self.txb = 0
|
||||||
|
|
||||||
@ -148,7 +150,7 @@ class AutoInterface(Interface):
|
|||||||
self.mcast_discovery_address = "ff1"+self.discovery_scope+":"+gt
|
self.mcast_discovery_address = "ff1"+self.discovery_scope+":"+gt
|
||||||
|
|
||||||
suitable_interfaces = 0
|
suitable_interfaces = 0
|
||||||
for ifname in self.netifaces.interfaces():
|
for ifname in self.list_interfaces():
|
||||||
if RNS.vendor.platformutils.is_darwin() and ifname in AutoInterface.DARWIN_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
if RNS.vendor.platformutils.is_darwin() and ifname in AutoInterface.DARWIN_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
||||||
RNS.log(str(self)+" skipping Darwin AWDL or tethering interface "+str(ifname), RNS.LOG_EXTREME)
|
RNS.log(str(self)+" skipping Darwin AWDL or tethering interface "+str(ifname), RNS.LOG_EXTREME)
|
||||||
elif RNS.vendor.platformutils.is_darwin() and ifname == "lo0":
|
elif RNS.vendor.platformutils.is_darwin() and ifname == "lo0":
|
||||||
@ -163,10 +165,10 @@ class AutoInterface(Interface):
|
|||||||
if len(self.allowed_interfaces) > 0 and not ifname in self.allowed_interfaces:
|
if len(self.allowed_interfaces) > 0 and not ifname in self.allowed_interfaces:
|
||||||
RNS.log(str(self)+" ignoring interface "+str(ifname)+" since it was not allowed", RNS.LOG_EXTREME)
|
RNS.log(str(self)+" ignoring interface "+str(ifname)+" since it was not allowed", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
addresses = self.netifaces.ifaddresses(ifname)
|
addresses = self.list_addresses(ifname)
|
||||||
if self.netifaces.AF_INET6 in addresses:
|
if self.netinfo.AF_INET6 in addresses:
|
||||||
link_local_addr = None
|
link_local_addr = None
|
||||||
for address in addresses[self.netifaces.AF_INET6]:
|
for address in addresses[self.netinfo.AF_INET6]:
|
||||||
if "addr" in address:
|
if "addr" in address:
|
||||||
if address["addr"].startswith("fe80:"):
|
if address["addr"].startswith("fe80:"):
|
||||||
link_local_addr = self.descope_linklocal(address["addr"])
|
link_local_addr = self.descope_linklocal(address["addr"])
|
||||||
@ -287,10 +289,10 @@ class AutoInterface(Interface):
|
|||||||
for ifname in self.adopted_interfaces:
|
for ifname in self.adopted_interfaces:
|
||||||
# Check that the link-local address has not changed
|
# Check that the link-local address has not changed
|
||||||
try:
|
try:
|
||||||
addresses = self.netifaces.ifaddresses(ifname)
|
addresses = self.list_addresses(ifname)
|
||||||
if self.netifaces.AF_INET6 in addresses:
|
if self.netinfo.AF_INET6 in addresses:
|
||||||
link_local_addr = None
|
link_local_addr = None
|
||||||
for address in addresses[self.netifaces.AF_INET6]:
|
for address in addresses[self.netinfo.AF_INET6]:
|
||||||
if "addr" in address:
|
if "addr" in address:
|
||||||
if address["addr"].startswith("fe80:"):
|
if address["addr"].startswith("fe80:"):
|
||||||
link_local_addr = self.descope_linklocal(address["addr"])
|
link_local_addr = self.descope_linklocal(address["addr"])
|
||||||
|
@ -408,25 +408,15 @@ class TCPServerInterface(Interface):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_address_for_if(name):
|
def get_address_for_if(name):
|
||||||
import importlib
|
import RNS.vendor.ifaddr.niwrapper as netinfo
|
||||||
if importlib.util.find_spec('netifaces') != None:
|
ifaddr = netinfo.ifaddresses(name)
|
||||||
import netifaces
|
return ifaddr[netinfo.AF_INET][0]["addr"]
|
||||||
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['addr']
|
|
||||||
else:
|
|
||||||
RNS.log("Getting interface addresses from device names requires the netifaces module.", RNS.LOG_CRITICAL)
|
|
||||||
RNS.log("You can install it with the command: python3 -m pip install netifaces", RNS.LOG_CRITICAL)
|
|
||||||
RNS.panic()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_broadcast_for_if(name):
|
def get_broadcast_for_if(name):
|
||||||
import importlib
|
import RNS.vendor.ifaddr.niwrapper as netinfo
|
||||||
if importlib.util.find_spec('netifaces') != None:
|
ifaddr = netinfo.ifaddresses(name)
|
||||||
import netifaces
|
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
||||||
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['broadcast']
|
|
||||||
else:
|
|
||||||
RNS.log("Getting interface addresses from device names requires the netifaces module.", RNS.LOG_CRITICAL)
|
|
||||||
RNS.log("You can install it with the command: python3 -m pip install netifaces", RNS.LOG_CRITICAL)
|
|
||||||
RNS.panic()
|
|
||||||
|
|
||||||
def __init__(self, owner, name, device=None, bindip=None, bindport=None, i2p_tunneled=False):
|
def __init__(self, owner, name, device=None, bindip=None, bindport=None, i2p_tunneled=False):
|
||||||
self.rxb = 0
|
self.rxb = 0
|
||||||
|
@ -34,25 +34,15 @@ class UDPInterface(Interface):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_address_for_if(name):
|
def get_address_for_if(name):
|
||||||
import importlib
|
import RNS.vendor.ifaddr.niwrapper as netinfo
|
||||||
if importlib.util.find_spec('netifaces') != None:
|
ifaddr = netinfo.ifaddresses(name)
|
||||||
import netifaces
|
return ifaddr[netinfo.AF_INET][0]["addr"]
|
||||||
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['addr']
|
|
||||||
else:
|
|
||||||
RNS.log("Getting interface addresses from device names requires the netifaces module.", RNS.LOG_CRITICAL)
|
|
||||||
RNS.log("You can install it with the command: python3 -m pip install netifaces", RNS.LOG_CRITICAL)
|
|
||||||
RNS.panic()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_broadcast_for_if(name):
|
def get_broadcast_for_if(name):
|
||||||
import importlib
|
import RNS.vendor.ifaddr.niwrapper as netinfo
|
||||||
if importlib.util.find_spec('netifaces') != None:
|
ifaddr = netinfo.ifaddresses(name)
|
||||||
import netifaces
|
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
||||||
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['broadcast']
|
|
||||||
else:
|
|
||||||
RNS.log("Getting interface addresses from device names requires the netifaces module.", RNS.LOG_CRITICAL)
|
|
||||||
RNS.log("You can install it with the command: python3 -m pip install netifaces", RNS.LOG_CRITICAL)
|
|
||||||
RNS.panic()
|
|
||||||
|
|
||||||
def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None):
|
def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None):
|
||||||
self.rxb = 0
|
self.rxb = 0
|
||||||
|
33
RNS/vendor/ifaddr/__init__.py
vendored
Normal file
33
RNS/vendor/ifaddr/__init__.py
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Copyright (c) 2014 Stefan C. Mueller
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from ifaddr._shared import Adapter, IP
|
||||||
|
|
||||||
|
if os.name == "nt":
|
||||||
|
from ifaddr._win32 import get_adapters
|
||||||
|
elif os.name == "posix":
|
||||||
|
from ifaddr._posix import get_adapters
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unsupported Operating System: %s" % os.name)
|
||||||
|
|
||||||
|
__all__ = ['Adapter', 'IP', 'get_adapters']
|
96
RNS/vendor/ifaddr/_posix.py
vendored
Normal file
96
RNS/vendor/ifaddr/_posix.py
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# Copyright (c) 2014 Stefan C. Mueller
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import ctypes.util
|
||||||
|
import ipaddress
|
||||||
|
import collections
|
||||||
|
import socket
|
||||||
|
|
||||||
|
from typing import Iterable, Optional
|
||||||
|
|
||||||
|
import ifaddr._shared as shared
|
||||||
|
|
||||||
|
# from ifaddr._shared import sockaddr, Interface, sockaddr_to_ip, ipv6_prefixlength
|
||||||
|
|
||||||
|
|
||||||
|
class ifaddrs(ctypes.Structure):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
ifaddrs._fields_ = [
|
||||||
|
('ifa_next', ctypes.POINTER(ifaddrs)),
|
||||||
|
('ifa_name', ctypes.c_char_p),
|
||||||
|
('ifa_flags', ctypes.c_uint),
|
||||||
|
('ifa_addr', ctypes.POINTER(shared.sockaddr)),
|
||||||
|
('ifa_netmask', ctypes.POINTER(shared.sockaddr)),
|
||||||
|
]
|
||||||
|
|
||||||
|
libc = ctypes.CDLL(ctypes.util.find_library("socket" if os.uname()[0] == "SunOS" else "c"), use_errno=True) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def get_adapters(include_unconfigured: bool = False) -> Iterable[shared.Adapter]:
|
||||||
|
|
||||||
|
addr0 = addr = ctypes.POINTER(ifaddrs)()
|
||||||
|
retval = libc.getifaddrs(ctypes.byref(addr))
|
||||||
|
if retval != 0:
|
||||||
|
eno = ctypes.get_errno()
|
||||||
|
raise OSError(eno, os.strerror(eno))
|
||||||
|
|
||||||
|
ips = collections.OrderedDict()
|
||||||
|
|
||||||
|
def add_ip(adapter_name: str, ip: Optional[shared.IP]) -> None:
|
||||||
|
if adapter_name not in ips:
|
||||||
|
index = None # type: Optional[int]
|
||||||
|
try:
|
||||||
|
# Mypy errors on this when the Windows CI runs:
|
||||||
|
# error: Module has no attribute "if_nametoindex"
|
||||||
|
index = socket.if_nametoindex(adapter_name) # type: ignore
|
||||||
|
except (OSError, AttributeError):
|
||||||
|
pass
|
||||||
|
ips[adapter_name] = shared.Adapter(adapter_name, adapter_name, [], index=index)
|
||||||
|
if ip is not None:
|
||||||
|
ips[adapter_name].ips.append(ip)
|
||||||
|
|
||||||
|
while addr:
|
||||||
|
name = addr[0].ifa_name.decode(encoding='UTF-8')
|
||||||
|
ip_addr = shared.sockaddr_to_ip(addr[0].ifa_addr)
|
||||||
|
if ip_addr:
|
||||||
|
if addr[0].ifa_netmask and not addr[0].ifa_netmask[0].sa_familiy:
|
||||||
|
addr[0].ifa_netmask[0].sa_familiy = addr[0].ifa_addr[0].sa_familiy
|
||||||
|
netmask = shared.sockaddr_to_ip(addr[0].ifa_netmask)
|
||||||
|
if isinstance(netmask, tuple):
|
||||||
|
netmaskStr = str(netmask[0])
|
||||||
|
prefixlen = shared.ipv6_prefixlength(ipaddress.IPv6Address(netmaskStr))
|
||||||
|
else:
|
||||||
|
assert netmask is not None, f'sockaddr_to_ip({addr[0].ifa_netmask}) returned None'
|
||||||
|
netmaskStr = str('0.0.0.0/' + netmask)
|
||||||
|
prefixlen = ipaddress.IPv4Network(netmaskStr).prefixlen
|
||||||
|
ip = shared.IP(ip_addr, prefixlen, name)
|
||||||
|
add_ip(name, ip)
|
||||||
|
else:
|
||||||
|
if include_unconfigured:
|
||||||
|
add_ip(name, None)
|
||||||
|
addr = addr[0].ifa_next
|
||||||
|
|
||||||
|
libc.freeifaddrs(addr0)
|
||||||
|
|
||||||
|
return ips.values()
|
199
RNS/vendor/ifaddr/_shared.py
vendored
Normal file
199
RNS/vendor/ifaddr/_shared.py
vendored
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
# Copyright (c) 2014 Stefan C. Mueller
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import socket
|
||||||
|
import ipaddress
|
||||||
|
import platform
|
||||||
|
|
||||||
|
from typing import List, Optional, Tuple, Union
|
||||||
|
|
||||||
|
|
||||||
|
class Adapter(object):
|
||||||
|
"""
|
||||||
|
Represents a network interface device controller (NIC), such as a
|
||||||
|
network card. An adapter can have multiple IPs.
|
||||||
|
|
||||||
|
On Linux aliasing (multiple IPs per physical NIC) is implemented
|
||||||
|
by creating 'virtual' adapters, each represented by an instance
|
||||||
|
of this class. Each of those 'virtual' adapters can have both
|
||||||
|
a IPv4 and an IPv6 IP address.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name: str, nice_name: str, ips: List['IP'], index: Optional[int] = None) -> None:
|
||||||
|
|
||||||
|
#: Unique name that identifies the adapter in the system.
|
||||||
|
#: On Linux this is of the form of `eth0` or `eth0:1`, on
|
||||||
|
#: Windows it is a UUID in string representation, such as
|
||||||
|
#: `{846EE342-7039-11DE-9D20-806E6F6E6963}`.
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
#: Human readable name of the adpater. On Linux this
|
||||||
|
#: is currently the same as :attr:`name`. On Windows
|
||||||
|
#: this is the name of the device.
|
||||||
|
self.nice_name = nice_name
|
||||||
|
|
||||||
|
#: List of :class:`ifaddr.IP` instances in the order they were
|
||||||
|
#: reported by the system.
|
||||||
|
self.ips = ips
|
||||||
|
|
||||||
|
#: Adapter index as used by some API (e.g. IPv6 multicast group join).
|
||||||
|
self.index = index
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return "Adapter(name={name}, nice_name={nice_name}, ips={ips}, index={index})".format(
|
||||||
|
name=repr(self.name), nice_name=repr(self.nice_name), ips=repr(self.ips), index=repr(self.index)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Type of an IPv4 address (a string in "xxx.xxx.xxx.xxx" format)
|
||||||
|
_IPv4Address = str
|
||||||
|
|
||||||
|
# Type of an IPv6 address (a three-tuple `(ip, flowinfo, scope_id)`)
|
||||||
|
_IPv6Address = Tuple[str, int, int]
|
||||||
|
|
||||||
|
|
||||||
|
class IP(object):
|
||||||
|
"""
|
||||||
|
Represents an IP address of an adapter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, ip: Union[_IPv4Address, _IPv6Address], network_prefix: int, nice_name: str) -> None:
|
||||||
|
|
||||||
|
#: IP address. For IPv4 addresses this is a string in
|
||||||
|
#: "xxx.xxx.xxx.xxx" format. For IPv6 addresses this
|
||||||
|
#: is a three-tuple `(ip, flowinfo, scope_id)`, where
|
||||||
|
#: `ip` is a string in the usual collon separated
|
||||||
|
#: hex format.
|
||||||
|
self.ip = ip
|
||||||
|
|
||||||
|
#: Number of bits of the IP that represent the
|
||||||
|
#: network. For a `255.255.255.0` netmask, this
|
||||||
|
#: number would be `24`.
|
||||||
|
self.network_prefix = network_prefix
|
||||||
|
|
||||||
|
#: Human readable name for this IP.
|
||||||
|
#: On Linux is this currently the same as the adapter name.
|
||||||
|
#: On Windows this is the name of the network connection
|
||||||
|
#: as configured in the system control panel.
|
||||||
|
self.nice_name = nice_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_IPv4(self) -> bool:
|
||||||
|
"""
|
||||||
|
Returns `True` if this IP is an IPv4 address and `False`
|
||||||
|
if it is an IPv6 address.
|
||||||
|
"""
|
||||||
|
return not isinstance(self.ip, tuple)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_IPv6(self) -> bool:
|
||||||
|
"""
|
||||||
|
Returns `True` if this IP is an IPv6 address and `False`
|
||||||
|
if it is an IPv4 address.
|
||||||
|
"""
|
||||||
|
return isinstance(self.ip, tuple)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return "IP(ip={ip}, network_prefix={network_prefix}, nice_name={nice_name})".format(
|
||||||
|
ip=repr(self.ip), network_prefix=repr(self.network_prefix), nice_name=repr(self.nice_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if platform.system() == "Darwin" or "BSD" in platform.system():
|
||||||
|
|
||||||
|
# BSD derived systems use marginally different structures
|
||||||
|
# than either Linux or Windows.
|
||||||
|
# I still keep it in `shared` since we can use
|
||||||
|
# both structures equally.
|
||||||
|
|
||||||
|
class sockaddr(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('sa_len', ctypes.c_uint8),
|
||||||
|
('sa_familiy', ctypes.c_uint8),
|
||||||
|
('sa_data', ctypes.c_uint8 * 14),
|
||||||
|
]
|
||||||
|
|
||||||
|
class sockaddr_in(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('sa_len', ctypes.c_uint8),
|
||||||
|
('sa_familiy', ctypes.c_uint8),
|
||||||
|
('sin_port', ctypes.c_uint16),
|
||||||
|
('sin_addr', ctypes.c_uint8 * 4),
|
||||||
|
('sin_zero', ctypes.c_uint8 * 8),
|
||||||
|
]
|
||||||
|
|
||||||
|
class sockaddr_in6(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('sa_len', ctypes.c_uint8),
|
||||||
|
('sa_familiy', ctypes.c_uint8),
|
||||||
|
('sin6_port', ctypes.c_uint16),
|
||||||
|
('sin6_flowinfo', ctypes.c_uint32),
|
||||||
|
('sin6_addr', ctypes.c_uint8 * 16),
|
||||||
|
('sin6_scope_id', ctypes.c_uint32),
|
||||||
|
]
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
class sockaddr(ctypes.Structure): # type: ignore
|
||||||
|
_fields_ = [('sa_familiy', ctypes.c_uint16), ('sa_data', ctypes.c_uint8 * 14)]
|
||||||
|
|
||||||
|
class sockaddr_in(ctypes.Structure): # type: ignore
|
||||||
|
_fields_ = [
|
||||||
|
('sin_familiy', ctypes.c_uint16),
|
||||||
|
('sin_port', ctypes.c_uint16),
|
||||||
|
('sin_addr', ctypes.c_uint8 * 4),
|
||||||
|
('sin_zero', ctypes.c_uint8 * 8),
|
||||||
|
]
|
||||||
|
|
||||||
|
class sockaddr_in6(ctypes.Structure): # type: ignore
|
||||||
|
_fields_ = [
|
||||||
|
('sin6_familiy', ctypes.c_uint16),
|
||||||
|
('sin6_port', ctypes.c_uint16),
|
||||||
|
('sin6_flowinfo', ctypes.c_uint32),
|
||||||
|
('sin6_addr', ctypes.c_uint8 * 16),
|
||||||
|
('sin6_scope_id', ctypes.c_uint32),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def sockaddr_to_ip(sockaddr_ptr: 'ctypes.pointer[sockaddr]') -> Optional[Union[_IPv4Address, _IPv6Address]]:
|
||||||
|
if sockaddr_ptr:
|
||||||
|
if sockaddr_ptr[0].sa_familiy == socket.AF_INET:
|
||||||
|
ipv4 = ctypes.cast(sockaddr_ptr, ctypes.POINTER(sockaddr_in))
|
||||||
|
ippacked = bytes(bytearray(ipv4[0].sin_addr))
|
||||||
|
ip = str(ipaddress.ip_address(ippacked))
|
||||||
|
return ip
|
||||||
|
elif sockaddr_ptr[0].sa_familiy == socket.AF_INET6:
|
||||||
|
ipv6 = ctypes.cast(sockaddr_ptr, ctypes.POINTER(sockaddr_in6))
|
||||||
|
flowinfo = ipv6[0].sin6_flowinfo
|
||||||
|
ippacked = bytes(bytearray(ipv6[0].sin6_addr))
|
||||||
|
ip = str(ipaddress.ip_address(ippacked))
|
||||||
|
scope_id = ipv6[0].sin6_scope_id
|
||||||
|
return (ip, flowinfo, scope_id)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def ipv6_prefixlength(address: ipaddress.IPv6Address) -> int:
|
||||||
|
prefix_length = 0
|
||||||
|
for i in range(address.max_prefixlen):
|
||||||
|
if int(address) >> i & 1:
|
||||||
|
prefix_length = prefix_length + 1
|
||||||
|
return prefix_length
|
145
RNS/vendor/ifaddr/_win32.py
vendored
Normal file
145
RNS/vendor/ifaddr/_win32.py
vendored
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# Copyright (c) 2014 Stefan C. Mueller
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
from ctypes import wintypes
|
||||||
|
from typing import Iterable, List
|
||||||
|
|
||||||
|
import ifaddr._shared as shared
|
||||||
|
|
||||||
|
NO_ERROR = 0
|
||||||
|
ERROR_BUFFER_OVERFLOW = 111
|
||||||
|
MAX_ADAPTER_NAME_LENGTH = 256
|
||||||
|
MAX_ADAPTER_DESCRIPTION_LENGTH = 128
|
||||||
|
MAX_ADAPTER_ADDRESS_LENGTH = 8
|
||||||
|
AF_UNSPEC = 0
|
||||||
|
|
||||||
|
|
||||||
|
class SOCKET_ADDRESS(ctypes.Structure):
|
||||||
|
_fields_ = [('lpSockaddr', ctypes.POINTER(shared.sockaddr)), ('iSockaddrLength', wintypes.INT)]
|
||||||
|
|
||||||
|
|
||||||
|
class IP_ADAPTER_UNICAST_ADDRESS(ctypes.Structure):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
IP_ADAPTER_UNICAST_ADDRESS._fields_ = [
|
||||||
|
('Length', wintypes.ULONG),
|
||||||
|
('Flags', wintypes.DWORD),
|
||||||
|
('Next', ctypes.POINTER(IP_ADAPTER_UNICAST_ADDRESS)),
|
||||||
|
('Address', SOCKET_ADDRESS),
|
||||||
|
('PrefixOrigin', ctypes.c_uint),
|
||||||
|
('SuffixOrigin', ctypes.c_uint),
|
||||||
|
('DadState', ctypes.c_uint),
|
||||||
|
('ValidLifetime', wintypes.ULONG),
|
||||||
|
('PreferredLifetime', wintypes.ULONG),
|
||||||
|
('LeaseLifetime', wintypes.ULONG),
|
||||||
|
('OnLinkPrefixLength', ctypes.c_uint8),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class IP_ADAPTER_ADDRESSES(ctypes.Structure):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
IP_ADAPTER_ADDRESSES._fields_ = [
|
||||||
|
('Length', wintypes.ULONG),
|
||||||
|
('IfIndex', wintypes.DWORD),
|
||||||
|
('Next', ctypes.POINTER(IP_ADAPTER_ADDRESSES)),
|
||||||
|
('AdapterName', ctypes.c_char_p),
|
||||||
|
('FirstUnicastAddress', ctypes.POINTER(IP_ADAPTER_UNICAST_ADDRESS)),
|
||||||
|
('FirstAnycastAddress', ctypes.c_void_p),
|
||||||
|
('FirstMulticastAddress', ctypes.c_void_p),
|
||||||
|
('FirstDnsServerAddress', ctypes.c_void_p),
|
||||||
|
('DnsSuffix', ctypes.c_wchar_p),
|
||||||
|
('Description', ctypes.c_wchar_p),
|
||||||
|
('FriendlyName', ctypes.c_wchar_p),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
iphlpapi = ctypes.windll.LoadLibrary("Iphlpapi") # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def enumerate_interfaces_of_adapter(
|
||||||
|
nice_name: str, address: IP_ADAPTER_UNICAST_ADDRESS
|
||||||
|
) -> Iterable[shared.IP]:
|
||||||
|
|
||||||
|
# Iterate through linked list and fill list
|
||||||
|
addresses = [] # type: List[IP_ADAPTER_UNICAST_ADDRESS]
|
||||||
|
while True:
|
||||||
|
addresses.append(address)
|
||||||
|
if not address.Next:
|
||||||
|
break
|
||||||
|
address = address.Next[0]
|
||||||
|
|
||||||
|
for address in addresses:
|
||||||
|
ip = shared.sockaddr_to_ip(address.Address.lpSockaddr)
|
||||||
|
assert ip is not None, f'sockaddr_to_ip({address.Address.lpSockaddr}) returned None'
|
||||||
|
network_prefix = address.OnLinkPrefixLength
|
||||||
|
yield shared.IP(ip, network_prefix, nice_name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_adapters(include_unconfigured: bool = False) -> Iterable[shared.Adapter]:
|
||||||
|
|
||||||
|
# Call GetAdaptersAddresses() with error and buffer size handling
|
||||||
|
|
||||||
|
addressbuffersize = wintypes.ULONG(15 * 1024)
|
||||||
|
retval = ERROR_BUFFER_OVERFLOW
|
||||||
|
while retval == ERROR_BUFFER_OVERFLOW:
|
||||||
|
addressbuffer = ctypes.create_string_buffer(addressbuffersize.value)
|
||||||
|
retval = iphlpapi.GetAdaptersAddresses(
|
||||||
|
wintypes.ULONG(AF_UNSPEC),
|
||||||
|
wintypes.ULONG(0),
|
||||||
|
None,
|
||||||
|
ctypes.byref(addressbuffer),
|
||||||
|
ctypes.byref(addressbuffersize),
|
||||||
|
)
|
||||||
|
if retval != NO_ERROR:
|
||||||
|
raise ctypes.WinError() # type: ignore
|
||||||
|
|
||||||
|
# Iterate through adapters fill array
|
||||||
|
address_infos = [] # type: List[IP_ADAPTER_ADDRESSES]
|
||||||
|
address_info = IP_ADAPTER_ADDRESSES.from_buffer(addressbuffer)
|
||||||
|
while True:
|
||||||
|
address_infos.append(address_info)
|
||||||
|
if not address_info.Next:
|
||||||
|
break
|
||||||
|
address_info = address_info.Next[0]
|
||||||
|
|
||||||
|
# Iterate through unicast addresses
|
||||||
|
result = [] # type: List[shared.Adapter]
|
||||||
|
for adapter_info in address_infos:
|
||||||
|
|
||||||
|
# We don't expect non-ascii characters here, so encoding shouldn't matter
|
||||||
|
name = adapter_info.AdapterName.decode()
|
||||||
|
nice_name = adapter_info.Description
|
||||||
|
index = adapter_info.IfIndex
|
||||||
|
|
||||||
|
if adapter_info.FirstUnicastAddress:
|
||||||
|
ips = enumerate_interfaces_of_adapter(
|
||||||
|
adapter_info.FriendlyName, adapter_info.FirstUnicastAddress[0]
|
||||||
|
)
|
||||||
|
ips = list(ips)
|
||||||
|
result.append(shared.Adapter(name, nice_name, ips, index=index))
|
||||||
|
elif include_unconfigured:
|
||||||
|
result.append(shared.Adapter(name, nice_name, [], index=index))
|
||||||
|
|
||||||
|
return result
|
38
RNS/vendor/ifaddr/niwrapper.py
vendored
Normal file
38
RNS/vendor/ifaddr/niwrapper.py
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import ipaddress
|
||||||
|
import ifaddr
|
||||||
|
import socket
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
AF_INET6 = socket.AF_INET6.value
|
||||||
|
AF_INET = socket.AF_INET.value
|
||||||
|
|
||||||
|
def interfaces() -> List[str]:
|
||||||
|
adapters = ifaddr.get_adapters(include_unconfigured=True)
|
||||||
|
return [a.name for a in adapters]
|
||||||
|
|
||||||
|
def ifaddresses(ifname) -> dict:
|
||||||
|
adapters = ifaddr.get_adapters(include_unconfigured=True)
|
||||||
|
ifa = {}
|
||||||
|
for a in adapters:
|
||||||
|
if a.name == ifname:
|
||||||
|
ipv4s = []
|
||||||
|
ipv6s = []
|
||||||
|
for ip in a.ips:
|
||||||
|
t = {}
|
||||||
|
if ip.is_IPv4:
|
||||||
|
net = ipaddress.ip_network(str(ip.ip)+"/"+str(ip.network_prefix), strict=False)
|
||||||
|
t["addr"] = ip.ip
|
||||||
|
t["prefix"] = ip.network_prefix
|
||||||
|
t["broadcast"] = str(net.broadcast_address)
|
||||||
|
ipv4s.append(t)
|
||||||
|
if ip.is_IPv6:
|
||||||
|
t["addr"] = ip.ip[0]
|
||||||
|
ipv6s.append(t)
|
||||||
|
|
||||||
|
if len(ipv4s) > 0:
|
||||||
|
ifa[AF_INET] = ipv4s
|
||||||
|
if len(ipv6s) > 0:
|
||||||
|
ifa[AF_INET6] = ipv6s
|
||||||
|
|
||||||
|
return ifa
|
0
RNS/vendor/ifaddr/py.typed
vendored
Normal file
0
RNS/vendor/ifaddr/py.typed
vendored
Normal file
@ -38,7 +38,6 @@ These efforts are aimed at improving the ease of which Reticulum is understood,
|
|||||||
- Update NomadNet screenshots
|
- Update NomadNet screenshots
|
||||||
- Update Sideband screenshots
|
- Update Sideband screenshots
|
||||||
- Installation
|
- Installation
|
||||||
- Install docs for fedora, needs `python3-netifaces`
|
|
||||||
- Add a *Reticulum On Raspberry Pi* section
|
- Add a *Reticulum On Raspberry Pi* section
|
||||||
- Update *Reticulum On Android* section if necessary
|
- Update *Reticulum On Android* section if necessary
|
||||||
- Update Android install documentation.
|
- Update Android install documentation.
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -25,30 +25,13 @@ and install them offline using ``pip``:
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pip install ./rns-0.4.6-py3-none-any.whl
|
pip install ./rns-0.5.1-py3-none-any.whl
|
||||||
|
|
||||||
|
|
||||||
Resolving Dependency & Installation Issues
|
Resolving Dependency & Installation Issues
|
||||||
=============================================
|
=============================================
|
||||||
On some platforms, there may not be binary packages available for all dependencies, and
|
On some platforms, there may not be binary packages available for all dependencies, and
|
||||||
``pip`` installation may fail with an error message. Most often, this is simply due to
|
``pip`` installation may fail with an error message. In these cases, the issue can usually
|
||||||
the ``netifaces`` package not having a pre-compiled package available via ``pip``.
|
|
||||||
|
|
||||||
Usually, this can be resolved by simply installing ``netifaces`` via the system package
|
|
||||||
manager:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
# Debian / Ubuntu / Derivatives
|
|
||||||
sudo apt install python3-netifaces
|
|
||||||
|
|
||||||
# Arch / Manjaro / Derivatives
|
|
||||||
sudo pamac install python3-netifaces
|
|
||||||
|
|
||||||
# Fedora
|
|
||||||
sudo dnf install python3-netifaces
|
|
||||||
|
|
||||||
More rarely, other dependencies cannot be resolved. In these cases, the issue can usually
|
|
||||||
be resolved by installing the development essentials packages for your platform:
|
be resolved by installing the development essentials packages for your platform:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
@ -308,7 +291,7 @@ For extended functionality, you can install optional dependencies:
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pip3 install pyserial netifaces
|
pip3 install pyserial
|
||||||
|
|
||||||
|
|
||||||
Further information can be found in the :ref:`API Reference<api-main>`.
|
Further information can be found in the :ref:`API Reference<api-main>`.
|
||||||
@ -323,7 +306,7 @@ don't use pip, but try this recipe:
|
|||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
pip3 install cryptography pyserial netifaces
|
pip3 install cryptography pyserial
|
||||||
|
|
||||||
# Clone repository
|
# Clone repository
|
||||||
git clone https://github.com/markqvist/Reticulum.git
|
git clone https://github.com/markqvist/Reticulum.git
|
||||||
@ -461,24 +444,6 @@ it will require manually configuring and installing some packages, and is not
|
|||||||
detailed in this manual.
|
detailed in this manual.
|
||||||
|
|
||||||
|
|
||||||
Fedora
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
On Fedora, ``pip`` installation may fail with an error message, since the ``netifaces``
|
|
||||||
package cannot be installed natively via ``pip``. This can be resolved by installing
|
|
||||||
the ``python3-netifaces`` package via ``dnf`` first:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
sudo dnf install python3-netifaces
|
|
||||||
|
|
||||||
Alternatively, you can install basic development packages, which will allow
|
|
||||||
``pip`` to install any required packages from source:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
sudo dnf groupinstall "Development Tools" "Development Libraries"
|
|
||||||
|
|
||||||
|
|
||||||
Debian Bookworm
|
Debian Bookworm
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
On versions of Debian released after April 2023, it is no longer possible
|
On versions of Debian released after April 2023, it is no longer possible
|
||||||
|
@ -238,28 +238,14 @@ of your system with a command like <code class="docutils literal notranslate"><s
|
|||||||
<code class="docutils literal notranslate"><span class="pre">sudo</span> <span class="pre">pamac</span> <span class="pre">install</span> <span class="pre">python-pip</span></code> or similar.</p>
|
<code class="docutils literal notranslate"><span class="pre">sudo</span> <span class="pre">pamac</span> <span class="pre">install</span> <span class="pre">python-pip</span></code> or similar.</p>
|
||||||
<p>You can also dowload the Reticulum release wheels from GitHub, or other release channels,
|
<p>You can also dowload the Reticulum release wheels from GitHub, or other release channels,
|
||||||
and install them offline using <code class="docutils literal notranslate"><span class="pre">pip</span></code>:</p>
|
and install them offline using <code class="docutils literal notranslate"><span class="pre">pip</span></code>:</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="o">./</span><span class="n">rns</span><span class="o">-</span><span class="mf">0.4.6</span><span class="o">-</span><span class="n">py3</span><span class="o">-</span><span class="n">none</span><span class="o">-</span><span class="nb">any</span><span class="o">.</span><span class="n">whl</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="o">./</span><span class="n">rns</span><span class="o">-</span><span class="mf">0.5.1</span><span class="o">-</span><span class="n">py3</span><span class="o">-</span><span class="n">none</span><span class="o">-</span><span class="nb">any</span><span class="o">.</span><span class="n">whl</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="resolving-dependency-installation-issues">
|
<section id="resolving-dependency-installation-issues">
|
||||||
<h2>Resolving Dependency & Installation Issues<a class="headerlink" href="#resolving-dependency-installation-issues" title="Permalink to this heading">#</a></h2>
|
<h2>Resolving Dependency & Installation Issues<a class="headerlink" href="#resolving-dependency-installation-issues" title="Permalink to this heading">#</a></h2>
|
||||||
<p>On some platforms, there may not be binary packages available for all dependencies, and
|
<p>On some platforms, there may not be binary packages available for all dependencies, and
|
||||||
<code class="docutils literal notranslate"><span class="pre">pip</span></code> installation may fail with an error message. Most often, this is simply due to
|
<code class="docutils literal notranslate"><span class="pre">pip</span></code> installation may fail with an error message. In these cases, the issue can usually
|
||||||
the <code class="docutils literal notranslate"><span class="pre">netifaces</span></code> package not having a pre-compiled package available via <code class="docutils literal notranslate"><span class="pre">pip</span></code>.</p>
|
|
||||||
<p>Usually, this can be resolved by simply installing <code class="docutils literal notranslate"><span class="pre">netifaces</span></code> via the system package
|
|
||||||
manager:</p>
|
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Debian / Ubuntu / Derivatives</span>
|
|
||||||
<span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">python3</span><span class="o">-</span><span class="n">netifaces</span>
|
|
||||||
|
|
||||||
<span class="c1"># Arch / Manjaro / Derivatives</span>
|
|
||||||
<span class="n">sudo</span> <span class="n">pamac</span> <span class="n">install</span> <span class="n">python3</span><span class="o">-</span><span class="n">netifaces</span>
|
|
||||||
|
|
||||||
<span class="c1"># Fedora</span>
|
|
||||||
<span class="n">sudo</span> <span class="n">dnf</span> <span class="n">install</span> <span class="n">python3</span><span class="o">-</span><span class="n">netifaces</span>
|
|
||||||
</pre></div>
|
|
||||||
</div>
|
|
||||||
<p>More rarely, other dependencies cannot be resolved. In these cases, the issue can usually
|
|
||||||
be resolved by installing the development essentials packages for your platform:</p>
|
be resolved by installing the development essentials packages for your platform:</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Debian / Ubuntu / Derivatives</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Debian / Ubuntu / Derivatives</span>
|
||||||
<span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span>
|
<span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span>
|
||||||
@ -464,7 +450,7 @@ started is to install the latest release of Reticulum via pip:</p>
|
|||||||
ready to import and use RNS in your own programs. The next step will most
|
ready to import and use RNS in your own programs. The next step will most
|
||||||
likely be to look at some <a class="reference internal" href="examples.html#examples-main"><span class="std std-ref">Example Programs</span></a>.</p>
|
likely be to look at some <a class="reference internal" href="examples.html#examples-main"><span class="std std-ref">Example Programs</span></a>.</p>
|
||||||
<p>For extended functionality, you can install optional dependencies:</p>
|
<p>For extended functionality, you can install optional dependencies:</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip3</span> <span class="n">install</span> <span class="n">pyserial</span> <span class="n">netifaces</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip3</span> <span class="n">install</span> <span class="n">pyserial</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>Further information can be found in the <a class="reference internal" href="reference.html#api-main"><span class="std std-ref">API Reference</span></a>.</p>
|
<p>Further information can be found in the <a class="reference internal" href="reference.html#api-main"><span class="std std-ref">API Reference</span></a>.</p>
|
||||||
@ -475,7 +461,7 @@ likely be to look at some <a class="reference internal" href="examples.html#exam
|
|||||||
utilities, you’ll want to get the latest source from GitHub. In that case,
|
utilities, you’ll want to get the latest source from GitHub. In that case,
|
||||||
don’t use pip, but try this recipe:</p>
|
don’t use pip, but try this recipe:</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Install dependencies</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Install dependencies</span>
|
||||||
<span class="n">pip3</span> <span class="n">install</span> <span class="n">cryptography</span> <span class="n">pyserial</span> <span class="n">netifaces</span>
|
<span class="n">pip3</span> <span class="n">install</span> <span class="n">cryptography</span> <span class="n">pyserial</span>
|
||||||
|
|
||||||
<span class="c1"># Clone repository</span>
|
<span class="c1"># Clone repository</span>
|
||||||
<span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">markqvist</span><span class="o">/</span><span class="n">Reticulum</span><span class="o">.</span><span class="n">git</span>
|
<span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">markqvist</span><span class="o">/</span><span class="n">Reticulum</span><span class="o">.</span><span class="n">git</span>
|
||||||
@ -598,20 +584,6 @@ don’t always have packages available for some dependencies.</p>
|
|||||||
it will require manually configuring and installing some packages, and is not
|
it will require manually configuring and installing some packages, and is not
|
||||||
detailed in this manual.</p>
|
detailed in this manual.</p>
|
||||||
</section>
|
</section>
|
||||||
<section id="fedora">
|
|
||||||
<h3>Fedora<a class="headerlink" href="#fedora" title="Permalink to this heading">#</a></h3>
|
|
||||||
<p>On Fedora, <code class="docutils literal notranslate"><span class="pre">pip</span></code> installation may fail with an error message, since the <code class="docutils literal notranslate"><span class="pre">netifaces</span></code>
|
|
||||||
package cannot be installed natively via <code class="docutils literal notranslate"><span class="pre">pip</span></code>. This can be resolved by installing
|
|
||||||
the <code class="docutils literal notranslate"><span class="pre">python3-netifaces</span></code> package via <code class="docutils literal notranslate"><span class="pre">dnf</span></code> first:</p>
|
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sudo</span> <span class="n">dnf</span> <span class="n">install</span> <span class="n">python3</span><span class="o">-</span><span class="n">netifaces</span>
|
|
||||||
</pre></div>
|
|
||||||
</div>
|
|
||||||
<p>Alternatively, you can install basic development packages, which will allow
|
|
||||||
<code class="docutils literal notranslate"><span class="pre">pip</span></code> to install any required packages from source:</p>
|
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sudo</span> <span class="n">dnf</span> <span class="n">groupinstall</span> <span class="s2">"Development Tools"</span> <span class="s2">"Development Libraries"</span>
|
|
||||||
</pre></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section id="debian-bookworm">
|
<section id="debian-bookworm">
|
||||||
<h3>Debian Bookworm<a class="headerlink" href="#debian-bookworm" title="Permalink to this heading">#</a></h3>
|
<h3>Debian Bookworm<a class="headerlink" href="#debian-bookworm" title="Permalink to this heading">#</a></h3>
|
||||||
<p>On versions of Debian released after April 2023, it is no longer possible
|
<p>On versions of Debian released after April 2023, it is no longer possible
|
||||||
@ -749,7 +721,6 @@ section of this manual.</p>
|
|||||||
<li><a class="reference internal" href="#android">Android</a></li>
|
<li><a class="reference internal" href="#android">Android</a></li>
|
||||||
<li><a class="reference internal" href="#arm64">ARM64</a></li>
|
<li><a class="reference internal" href="#arm64">ARM64</a></li>
|
||||||
<li><a class="reference internal" href="#raspberry-pi">Raspberry Pi</a></li>
|
<li><a class="reference internal" href="#raspberry-pi">Raspberry Pi</a></li>
|
||||||
<li><a class="reference internal" href="#fedora">Fedora</a></li>
|
|
||||||
<li><a class="reference internal" href="#debian-bookworm">Debian Bookworm</a></li>
|
<li><a class="reference internal" href="#debian-bookworm">Debian Bookworm</a></li>
|
||||||
<li><a class="reference internal" href="#ubuntu-lunar">Ubuntu Lunar</a></li>
|
<li><a class="reference internal" href="#ubuntu-lunar">Ubuntu Lunar</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -260,7 +260,6 @@ to participate in the development of Reticulum itself.</p>
|
|||||||
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#android">Android</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#android">Android</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#arm64">ARM64</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#arm64">ARM64</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#raspberry-pi">Raspberry Pi</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#raspberry-pi">Raspberry Pi</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#fedora">Fedora</a></li>
|
|
||||||
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#debian-bookworm">Debian Bookworm</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#debian-bookworm">Debian Bookworm</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#ubuntu-lunar">Ubuntu Lunar</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="gettingstartedfast.html#ubuntu-lunar">Ubuntu Lunar</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -25,30 +25,13 @@ and install them offline using ``pip``:
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pip install ./rns-0.4.6-py3-none-any.whl
|
pip install ./rns-0.5.1-py3-none-any.whl
|
||||||
|
|
||||||
|
|
||||||
Resolving Dependency & Installation Issues
|
Resolving Dependency & Installation Issues
|
||||||
=============================================
|
=============================================
|
||||||
On some platforms, there may not be binary packages available for all dependencies, and
|
On some platforms, there may not be binary packages available for all dependencies, and
|
||||||
``pip`` installation may fail with an error message. Most often, this is simply due to
|
``pip`` installation may fail with an error message. In these cases, the issue can usually
|
||||||
the ``netifaces`` package not having a pre-compiled package available via ``pip``.
|
|
||||||
|
|
||||||
Usually, this can be resolved by simply installing ``netifaces`` via the system package
|
|
||||||
manager:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
# Debian / Ubuntu / Derivatives
|
|
||||||
sudo apt install python3-netifaces
|
|
||||||
|
|
||||||
# Arch / Manjaro / Derivatives
|
|
||||||
sudo pamac install python3-netifaces
|
|
||||||
|
|
||||||
# Fedora
|
|
||||||
sudo dnf install python3-netifaces
|
|
||||||
|
|
||||||
More rarely, other dependencies cannot be resolved. In these cases, the issue can usually
|
|
||||||
be resolved by installing the development essentials packages for your platform:
|
be resolved by installing the development essentials packages for your platform:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
@ -308,7 +291,7 @@ For extended functionality, you can install optional dependencies:
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pip3 install pyserial netifaces
|
pip3 install pyserial
|
||||||
|
|
||||||
|
|
||||||
Further information can be found in the :ref:`API Reference<api-main>`.
|
Further information can be found in the :ref:`API Reference<api-main>`.
|
||||||
@ -323,7 +306,7 @@ don't use pip, but try this recipe:
|
|||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
pip3 install cryptography pyserial netifaces
|
pip3 install cryptography pyserial
|
||||||
|
|
||||||
# Clone repository
|
# Clone repository
|
||||||
git clone https://github.com/markqvist/Reticulum.git
|
git clone https://github.com/markqvist/Reticulum.git
|
||||||
@ -461,24 +444,6 @@ it will require manually configuring and installing some packages, and is not
|
|||||||
detailed in this manual.
|
detailed in this manual.
|
||||||
|
|
||||||
|
|
||||||
Fedora
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
On Fedora, ``pip`` installation may fail with an error message, since the ``netifaces``
|
|
||||||
package cannot be installed natively via ``pip``. This can be resolved by installing
|
|
||||||
the ``python3-netifaces`` package via ``dnf`` first:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
sudo dnf install python3-netifaces
|
|
||||||
|
|
||||||
Alternatively, you can install basic development packages, which will allow
|
|
||||||
``pip`` to install any required packages from source:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
sudo dnf groupinstall "Development Tools" "Development Libraries"
|
|
||||||
|
|
||||||
|
|
||||||
Debian Bookworm
|
Debian Bookworm
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
On versions of Debian released after April 2023, it is no longer possible
|
On versions of Debian released after April 2023, it is no longer possible
|
||||||
|
2
setup.py
2
setup.py
@ -20,7 +20,7 @@ if pure_python:
|
|||||||
long_description = long_description.replace("</p>", "</p>"+pure_notice)
|
long_description = long_description.replace("</p>", "</p>"+pure_notice)
|
||||||
else:
|
else:
|
||||||
pkg_name = "rns"
|
pkg_name = "rns"
|
||||||
requirements = ['cryptography>=3.4.7', 'pyserial>=3.5', 'netifaces']
|
requirements = ['cryptography>=3.4.7', 'pyserial>=3.5']
|
||||||
|
|
||||||
excluded_modules = exclude=["tests.*", "tests"]
|
excluded_modules = exclude=["tests.*", "tests"]
|
||||||
packages = setuptools.find_packages(exclude=excluded_modules)
|
packages = setuptools.find_packages(exclude=excluded_modules)
|
||||||
|
Loading…
Reference in New Issue
Block a user