Skip to main content

An implementation of the Application Layer Network (ALN).

Project description

Application Layer Network - Python 3

alnmeshpy is a Python implementation of Application Layer Network (ALN), an amature mesh networking protocol for home lab networking designed for hacking prototype projects that benefit from the simplicity gained from completely ignoring security as a concern. Don't use this for production.

Install with --no-deps unless you need Bluetooth support (very experimental) which use bleak and aiofiles.

pip install --no-deps alnmeshpy

The example app demonstrates a 3-node topology

  • Node 1 hosts TCP connections and demonstrates mesh networking
  • Node 2 connects to Node 1 and provides a 'ping' service
  • Node 3 connects to Node 1 and sends packets to 'ping' service

Running example

Node 1

import selectors, signal
from alnmeshpy import TcpHost, Router

def main():
    sel = selectors.DefaultSelector() # app event loop
    router = Router(sel, "python-host-1") # must be unique
    router.start() # Router is a Thread object

    def on_connect(tcpChannel, addr): # define TCP host listener 
        router.add_channel(tcpChannel) # give all new channels to our single router
    TcpHost().listen(sel, 'localhost', 8081, on_connect)
    
    def signal_handler(signal, frame): # listen for ^C
        router.close()
        sel.close()
    signal.signal(signal.SIGINT, signal_handler)
    signal.pause()

if __name__ == "__main__":
    main()

Node 2

import selectors, signal, socket
from alnmeshpy import TcpChannel, Router,Packet

def main():
    sel = selectors.DefaultSelector()
    router = Router(sel, "python-ping-service-1")
    router.start() # router s a Thread object so it must be started

    def ping_handler(packet):
        print("ping from [{0}]".format(packet.srcAddr))
        router.send(Packet(
            destAddr=packet.srcAddr, # return to sender
            contextID=packet.contextID, # required
            data="pong"
        ))
    router.register_service("ping", ping_handler)

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('localhost', 8081)) # hard-coded address for demonstration
    router.add_channel(TcpChannel(sock)) # let the router operate on this channel

    def signal_handler(signal, frame):
        router.close()
        sel.close()
    signal.signal(signal.SIGINT, signal_handler)
    signal.pause()

if __name__ == "__main__":
    main()

Node 3

import selectors, signal, socket, time
from alnmeshpy import TcpChannel, Router,Packet

def main():
    sel = selectors.DefaultSelector()
    router = Router(sel, "python-browser-client-1")
    router.start()

    def on_pong(packet): # define the ping response handler
        print('received:', str(packet.data), 'from:', packet.srcAddr)
        time.sleep(1) # wait a second then ping again
        router.send(Packet(service="ping", contextID=packet.contextID))
    ctxID = router.register_context_handler(on_pong) # set response handler

    # send a packet when a 'ping' service is discovered
    def on_service_discovery(service, capacity, address):
        print("on_service_discovery: {0}:{1}:{2}".format(service, capacity, address))
        if service == "ping":
            print("sending ping with ctxID {0}".format(ctxID))
            router.send(Packet(destAddr=address, service="ping", contextID=ctxID))      
    router.set_on_service_capacity_changed_handler(on_service_discovery)

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('localhost', 8081)) # hard-coded address for demonstration

    router.add_channel(TcpChannel(sock)) # let the router operate on this channel

    def signal_handler(signal, frame):
        router.close()
        sel.close()
    signal.signal(signal.SIGINT, signal_handler)   
    signal.pause()

if __name__ == "__main__":
    main()

Integration test

This test is functionally equivalent but uses pipes to connect all 3 routers within a single process. This script serves as a useful integration test when hacking on the protocol.

import os, selectors, signal
from threading import Lock
from alnmeshpy import LocalChannel, Router,Packet

# this is an integration test that configures 3 nodes
# node 1 advertises a ping service that responds with a 'pong'
# node 2 is an intermediate node that demonstrates multi-hop routing
# node 3 listens for the ping service advertisment and sends a pack to it
# finally node 3 prints the content of the ping packet

def main():
    
    r1a, w1a = os.pipe()
    r2a, w2a = os.pipe()
    ch1a = LocalChannel(r1a, w2a)
    ch2a = LocalChannel(r2a, w1a)

    sel = selectors.DefaultSelector()

    # configure the ping handler on node 1
    def ping_handler(packet):
        print("ping from [{0}]".format(packet.srcAddr))
        router1.send(Packet(
            destAddr=packet.srcAddr,
            contextID=packet.contextID,
            data="pong"
        ))

    router1 = Router(sel, "aln-node-1")
    router1.start()
    router1.register_service("ping", ping_handler)
    
    # node 2 exists to test mesh networking
    router2 = Router(sel, "aln-node-2")
    router2.start()
    
    router1.add_channel(ch1a)
    router2.add_channel(ch2a)
    
    r1b, w1b = os.pipe()
    r2b, w2b = os.pipe()
    ch1b = LocalChannel(r1b, w2b)
    ch2b = LocalChannel(r2b, w1b)

    # node 3 will:
    #  listen for the ping service advertisment advertisement
    #  send a 'ping' packet to the advertising node
    #  print the response to the console
    router3 = Router(sel, "aln-node-3")
    router3.start()

    # set up listener for ping response
    def on_packet(packet):
        print(packet.toJsonString())
        print('unpacked response data:', packet.data)
        print('ctrl-C to quit')
    ctxID = router3.register_context_handler(on_packet)

    # set up a service discovery handler for the "ping" service
    def on_service_discovery(service, capacity, address):
        print("on_service_discovery at aln-node-3: {0}:{1}:{2}".format(service, capacity, address))
        if service == "ping":
            print("sending ping with ctxID {0}".format(ctxID))
            text = "hello world".encode(encoding="utf-8")
            router3.send(Packet(destAddr=address, service="ping", contextID=ctxID, data=text))
            
    router3.set_on_service_capacity_changed_handler(on_service_discovery)
    router3.add_channel(ch2b)
    router2.add_channel(ch1b)

    def signal_handler(signal, frame):
        sel.close()
    signal.signal(signal.SIGINT, signal_handler)
    signal.pause()

if __name__ == "__main__":
    main()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

alnmeshpy-0.1.0.tar.gz (28.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

alnmeshpy-0.1.0-py3-none-any.whl (17.2 kB view details)

Uploaded Python 3

File details

Details for the file alnmeshpy-0.1.0.tar.gz.

File metadata

  • Download URL: alnmeshpy-0.1.0.tar.gz
  • Upload date:
  • Size: 28.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for alnmeshpy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ec9ce1a39c522d6063a1a985c37821aedf54e8a9d6541ba79e1bdd25e64d0774
MD5 354a949d35bc22bd97ff2dbc04a3c8aa
BLAKE2b-256 3099e3d3b1846daff70edafb0f4b725679e9f51d030947a32670f98e0d17dfbd

See more details on using hashes here.

File details

Details for the file alnmeshpy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: alnmeshpy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 17.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for alnmeshpy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2beb50ce32c6811b8fa2adaa6160e83e1c5588d12da5b41e2dd12134dcc89732
MD5 e901b9865320eeaad712b87939cd2697
BLAKE2b-256 3bd184f06d2c8ec5aff4dbb0fcdbf17a85dc8f5a671727e699733f15c60a9a7e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page