mirror of
https://github.com/JoelBender/bacpypes
synced 2025-09-28 22:15:23 +08:00
751 lines
28 KiB
Python
Executable File
751 lines
28 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
"""
|
|
Network Service
|
|
"""
|
|
|
|
from copy import copy as _copy
|
|
|
|
from .debugging import ModuleLogger, DebugContents, bacpypes_debugging
|
|
from .errors import ConfigurationError
|
|
|
|
from .comm import Client, Server, bind, \
|
|
ServiceAccessPoint, ApplicationServiceElement
|
|
|
|
from .pdu import Address, LocalBroadcast, LocalStation, PDU, RemoteStation
|
|
from .npdu import IAmRouterToNetwork, NPDU, WhoIsRouterToNetwork, npdu_types
|
|
from .apdu import APDU as _APDU
|
|
|
|
# some debugging
|
|
_debug = 0
|
|
_log = ModuleLogger(globals())
|
|
|
|
# router status values
|
|
ROUTER_AVAILABLE = 0 # normal
|
|
ROUTER_BUSY = 1 # router is busy
|
|
ROUTER_DISCONNECTED = 2 # could make a connection, but hasn't
|
|
ROUTER_UNREACHABLE = 3 # cannot route
|
|
|
|
#
|
|
# NetworkReference
|
|
#
|
|
|
|
class NetworkReference:
|
|
"""These objects map a network to a router."""
|
|
|
|
def __init__(self, net, router, status):
|
|
self.network = net
|
|
self.router = router
|
|
self.status = status
|
|
|
|
#
|
|
# RouterReference
|
|
#
|
|
|
|
class RouterReference(DebugContents):
|
|
"""These objects map a router; the adapter to talk to it,
|
|
its address, and a list of networks that it routes to."""
|
|
|
|
_debug_contents = ('adapter-', 'address', 'networks', 'status')
|
|
|
|
def __init__(self, adapter, addr, nets, status):
|
|
self.adapter = adapter
|
|
self.address = addr # local station relative to the adapter
|
|
self.networks = nets # list of remote networks
|
|
self.status = status # status as presented by the router
|
|
|
|
#
|
|
# NetworkAdapter
|
|
#
|
|
|
|
@bacpypes_debugging
|
|
class NetworkAdapter(Client, DebugContents):
|
|
|
|
_debug_contents = ('adapterSAP-', 'adapterNet')
|
|
|
|
def __init__(self, sap, net, cid=None):
|
|
if _debug: NetworkAdapter._debug("__init__ %r (net=%r) cid=%r", sap, net, cid)
|
|
Client.__init__(self, cid)
|
|
self.adapterSAP = sap
|
|
self.adapterNet = net
|
|
|
|
# add this to the list of adapters for the network
|
|
sap.adapters.append(self)
|
|
|
|
def confirmation(self, pdu):
|
|
"""Decode upstream PDUs and pass them up to the service access point."""
|
|
if _debug: NetworkAdapter._debug("confirmation %r (net=%r)", pdu, self.adapterNet)
|
|
|
|
npdu = NPDU(user_data=pdu.pduUserData)
|
|
npdu.decode(pdu)
|
|
self.adapterSAP.process_npdu(self, npdu)
|
|
|
|
def process_npdu(self, npdu):
|
|
"""Encode NPDUs from the service access point and send them downstream."""
|
|
if _debug: NetworkAdapter._debug("process_npdu %r (net=%r)", npdu, self.adapterNet)
|
|
|
|
pdu = PDU(user_data=npdu.pduUserData)
|
|
npdu.encode(pdu)
|
|
self.request(pdu)
|
|
|
|
def EstablishConnectionToNetwork(self, net):
|
|
pass
|
|
|
|
def DisconnectConnectionToNetwork(self, net):
|
|
pass
|
|
|
|
#
|
|
# NetworkServiceAccessPoint
|
|
#
|
|
|
|
@bacpypes_debugging
|
|
class NetworkServiceAccessPoint(ServiceAccessPoint, Server, DebugContents):
|
|
|
|
_debug_contents = ('adapters++', 'routers++', 'networks+'
|
|
, 'localAdapter-', 'localAddress'
|
|
)
|
|
|
|
def __init__(self, sap=None, sid=None):
|
|
if _debug: NetworkServiceAccessPoint._debug("__init__ sap=%r sid=%r", sap, sid)
|
|
ServiceAccessPoint.__init__(self, sap)
|
|
Server.__init__(self, sid)
|
|
|
|
self.adapters = [] # list of adapters
|
|
self.routers = {} # (adapter, address) -> RouterReference
|
|
self.networks = {} # network -> RouterReference
|
|
|
|
self.localAdapter = None # which one is local
|
|
self.localAddress = None # what is the local address
|
|
|
|
def bind(self, server, net=None, address=None):
|
|
"""Create a network adapter object and bind."""
|
|
if _debug: NetworkServiceAccessPoint._debug("bind %r net=%r address=%r", server, net, address)
|
|
|
|
if (net is None) and self.adapters:
|
|
raise RuntimeError("already bound")
|
|
|
|
# create an adapter object
|
|
adapter = NetworkAdapter(self, net)
|
|
|
|
# if the address was given, make it the "local" one
|
|
if address:
|
|
self.localAdapter = adapter
|
|
self.localAddress = address
|
|
|
|
# bind to the server
|
|
bind(adapter, server)
|
|
|
|
#-----
|
|
|
|
def add_router_references(self, adapter, address, netlist):
|
|
"""Add/update references to routers."""
|
|
if _debug: NetworkServiceAccessPoint._debug("add_router_references %r %r %r", adapter, address, netlist)
|
|
|
|
# make a key for the router reference
|
|
rkey = (adapter, address)
|
|
|
|
for snet in netlist:
|
|
# see if this is spoofing an existing routing table entry
|
|
if snet in self.networks:
|
|
rref = self.networks[snet]
|
|
|
|
if rref.adapter == adapter and rref.address == address:
|
|
pass # matches current entry
|
|
else:
|
|
### check to see if this source could be a router to the new network
|
|
|
|
# remove the network from the rref
|
|
i = rref.networks.index(snet)
|
|
del rref.networks[i]
|
|
|
|
# remove the network
|
|
del self.networks[snet]
|
|
|
|
### check to see if it is OK to add the new entry
|
|
|
|
# get the router reference for this router
|
|
rref = self.routers.get(rkey, None)
|
|
if rref:
|
|
if snet not in rref.networks:
|
|
# add the network
|
|
rref.networks.append(snet)
|
|
|
|
# reference the snet
|
|
self.networks[snet] = rref
|
|
else:
|
|
# new reference
|
|
rref = RouterReference( adapter, address, [snet], 0)
|
|
self.routers[rkey] = rref
|
|
|
|
# reference the snet
|
|
self.networks[snet] = rref
|
|
|
|
def remove_router_references(self, adapter, address=None):
|
|
"""Add/update references to routers."""
|
|
if _debug: NetworkServiceAccessPoint._debug("remove_router_references %r %r", adapter, address)
|
|
|
|
delrlist = []
|
|
delnlist = []
|
|
# scan through the dictionary of router references
|
|
for rkey in self.routers.keys():
|
|
# rip apart the key
|
|
radapter, raddress = rkey
|
|
|
|
# pick all references on the adapter, optionally limited to a specific address
|
|
match = radapter is adapter
|
|
if match and address is not None:
|
|
match = (raddress == address)
|
|
if not match:
|
|
continue
|
|
|
|
# save it for deletion
|
|
delrlist.append(rkey)
|
|
delnlist.extend(self.routers[rkey].networks)
|
|
if _debug:
|
|
NetworkServiceAccessPoint._debug(" - delrlist: %r", delrlist)
|
|
NetworkServiceAccessPoint._debug(" - delnlist: %r", delnlist)
|
|
|
|
# delete the entries
|
|
for rkey in delrlist:
|
|
try:
|
|
del self.routers[rkey]
|
|
except KeyError:
|
|
if _debug: NetworkServiceAccessPoint._debug(" - rkey not in self.routers: %r", rkey)
|
|
for nkey in delnlist:
|
|
try:
|
|
del self.networks[nkey]
|
|
except KeyError:
|
|
if _debug: NetworkServiceAccessPoint._debug(" - nkey not in self.networks: %r", rkey)
|
|
|
|
#-----
|
|
|
|
def indication(self, pdu):
|
|
if _debug: NetworkServiceAccessPoint._debug("indication %r", pdu)
|
|
|
|
# make sure our configuration is OK
|
|
if (not self.adapters):
|
|
raise ConfigurationError("no adapters")
|
|
|
|
# might be able to relax this restriction
|
|
if (len(self.adapters) > 1) and (not self.localAdapter):
|
|
raise ConfigurationError("local adapter must be set")
|
|
|
|
# get the local adapter
|
|
adapter = self.localAdapter or self.adapters[0]
|
|
|
|
# build a generic APDU
|
|
apdu = _APDU(user_data=pdu.pduUserData)
|
|
pdu.encode(apdu)
|
|
if _debug: NetworkServiceAccessPoint._debug(" - apdu: %r", apdu)
|
|
|
|
# build an NPDU specific to where it is going
|
|
npdu = NPDU(user_data=pdu.pduUserData)
|
|
apdu.encode(npdu)
|
|
if _debug: NetworkServiceAccessPoint._debug(" - npdu: %r", npdu)
|
|
|
|
# the hop count always starts out big
|
|
npdu.npduHopCount = 255
|
|
|
|
# local stations given to local adapter
|
|
if (npdu.pduDestination.addrType == Address.localStationAddr):
|
|
adapter.process_npdu(npdu)
|
|
return
|
|
|
|
# local broadcast given to local adapter
|
|
if (npdu.pduDestination.addrType == Address.localBroadcastAddr):
|
|
adapter.process_npdu(npdu)
|
|
return
|
|
|
|
# global broadcast
|
|
if (npdu.pduDestination.addrType == Address.globalBroadcastAddr):
|
|
# set the destination
|
|
npdu.pduDestination = LocalBroadcast()
|
|
npdu.npduDADR = apdu.pduDestination
|
|
|
|
# send it to all of connected adapters
|
|
for xadapter in self.adapters:
|
|
xadapter.process_npdu(npdu)
|
|
return
|
|
|
|
# remote broadcast
|
|
if (npdu.pduDestination.addrType != Address.remoteBroadcastAddr) and (npdu.pduDestination.addrType != Address.remoteStationAddr):
|
|
raise RuntimeError("invalid destination address type: %s" % (npdu.pduDestination.addrType,))
|
|
|
|
dnet = npdu.pduDestination.addrNet
|
|
|
|
# if the network matches the local adapter it's local
|
|
if (dnet == adapter.adapterNet):
|
|
### log this, the application shouldn't be sending to a remote station address
|
|
### when it's a directly connected network
|
|
raise RuntimeError("addressing problem")
|
|
|
|
# check for an available path
|
|
if dnet in self.networks:
|
|
rref = self.networks[dnet]
|
|
adapter = rref.adapter
|
|
|
|
### make sure the direct connect is OK, may need to connect
|
|
|
|
### make sure the peer router is OK, may need to connect
|
|
|
|
# fix the destination
|
|
npdu.pduDestination = rref.address
|
|
npdu.npduDADR = apdu.pduDestination
|
|
|
|
# send it along
|
|
adapter.process_npdu(npdu)
|
|
return
|
|
|
|
if _debug: NetworkServiceAccessPoint._debug(" - no known path to network, broadcast to discover it")
|
|
|
|
# set the destination
|
|
npdu.pduDestination = LocalBroadcast()
|
|
npdu.npduDADR = apdu.pduDestination
|
|
|
|
# send it to all of the connected adapters
|
|
for xadapter in self.adapters:
|
|
xadapter.process_npdu(npdu)
|
|
|
|
def process_npdu(self, adapter, npdu):
|
|
if _debug: NetworkServiceAccessPoint._debug("process_npdu %r %r", adapter, npdu)
|
|
|
|
# make sure our configuration is OK
|
|
if (not self.adapters):
|
|
raise ConfigurationError("no adapters")
|
|
if (len(self.adapters) > 1) and (not self.localAdapter):
|
|
raise ConfigurationError("local adapter must be set")
|
|
|
|
# check for source routing
|
|
if npdu.npduSADR and (npdu.npduSADR.addrType != Address.nullAddr):
|
|
# see if this is attempting to spoof a directly connected network
|
|
snet = npdu.npduSADR.addrNet
|
|
for xadapter in self.adapters:
|
|
if (xadapter is not adapter) and (snet == xadapter.adapterNet):
|
|
NetworkServiceAccessPoint._warning("spoof?")
|
|
### log this
|
|
return
|
|
|
|
# make a key for the router reference
|
|
rkey = (adapter, npdu.pduSource)
|
|
|
|
# see if this is spoofing an existing routing table entry
|
|
if snet in self.networks:
|
|
rref = self.networks[snet]
|
|
if rref.adapter == adapter and rref.address == npdu.pduSource:
|
|
pass # matches current entry
|
|
else:
|
|
if _debug: NetworkServiceAccessPoint._debug(" - replaces entry")
|
|
|
|
### check to see if this source could be a router to the new network
|
|
|
|
# remove the network from the rref
|
|
i = rref.networks.index(snet)
|
|
del rref.networks[i]
|
|
|
|
# remove the network
|
|
del self.networks[snet]
|
|
|
|
# get the router reference for this router
|
|
rref = self.routers.get(rkey)
|
|
if rref:
|
|
if snet not in rref.networks:
|
|
# add the network
|
|
rref.networks.append(snet)
|
|
|
|
# reference the snet
|
|
self.networks[snet] = rref
|
|
else:
|
|
# new reference
|
|
rref = RouterReference( adapter, npdu.pduSource, [snet], 0)
|
|
self.routers[rkey] = rref
|
|
|
|
# reference the snet
|
|
self.networks[snet] = rref
|
|
|
|
# check for destination routing
|
|
if (not npdu.npduDADR) or (npdu.npduDADR.addrType == Address.nullAddr):
|
|
processLocally = (not self.localAdapter) or (adapter is self.localAdapter) or (npdu.npduNetMessage is not None)
|
|
forwardMessage = False
|
|
|
|
elif npdu.npduDADR.addrType == Address.remoteBroadcastAddr:
|
|
if not self.localAdapter:
|
|
return
|
|
if (npdu.npduDADR.addrNet == adapter.adapterNet):
|
|
### log this, attempt to route to a network the device is already on
|
|
return
|
|
|
|
processLocally = (npdu.npduDADR.addrNet == self.localAdapter.adapterNet)
|
|
forwardMessage = True
|
|
|
|
elif npdu.npduDADR.addrType == Address.remoteStationAddr:
|
|
if not self.localAdapter:
|
|
return
|
|
if (npdu.npduDADR.addrNet == adapter.adapterNet):
|
|
### log this, attempt to route to a network the device is already on
|
|
return
|
|
|
|
processLocally = (npdu.npduDADR.addrNet == self.localAdapter.adapterNet) \
|
|
and (npdu.npduDADR.addrAddr == self.localAddress.addrAddr)
|
|
forwardMessage = not processLocally
|
|
|
|
elif npdu.npduDADR.addrType == Address.globalBroadcastAddr:
|
|
processLocally = True
|
|
forwardMessage = True
|
|
|
|
else:
|
|
NetworkServiceAccessPoint._warning("invalid destination address type: %s", npdu.npduDADR.addrType)
|
|
return
|
|
|
|
if _debug:
|
|
NetworkServiceAccessPoint._debug(" - processLocally: %r", processLocally)
|
|
NetworkServiceAccessPoint._debug(" - forwardMessage: %r", forwardMessage)
|
|
|
|
# application or network layer message
|
|
if npdu.npduNetMessage is None:
|
|
if processLocally and self.serverPeer:
|
|
# decode as a generic APDU
|
|
apdu = _APDU(user_data=npdu.pduUserData)
|
|
apdu.decode(_copy(npdu))
|
|
if _debug: NetworkServiceAccessPoint._debug(" - apdu: %r", apdu)
|
|
|
|
# see if it needs to look routed
|
|
if (len(self.adapters) > 1) and (adapter != self.localAdapter):
|
|
# combine the source address
|
|
if not npdu.npduSADR:
|
|
apdu.pduSource = RemoteStation( adapter.adapterNet, npdu.pduSource.addrAddr )
|
|
else:
|
|
apdu.pduSource = npdu.npduSADR
|
|
|
|
# map the destination
|
|
if not npdu.npduDADR:
|
|
apdu.pduDestination = self.localAddress
|
|
elif npdu.npduDADR.addrType == Address.globalBroadcastAddr:
|
|
apdu.pduDestination = npdu.npduDADR
|
|
elif npdu.npduDADR.addrType == Address.remoteBroadcastAddr:
|
|
apdu.pduDestination = LocalBroadcast()
|
|
else:
|
|
apdu.pduDestination = self.localAddress
|
|
else:
|
|
# combine the source address
|
|
if npdu.npduSADR:
|
|
apdu.pduSource = npdu.npduSADR
|
|
else:
|
|
apdu.pduSource = npdu.pduSource
|
|
|
|
# pass along global broadcast
|
|
if npdu.npduDADR and npdu.npduDADR.addrType == Address.globalBroadcastAddr:
|
|
apdu.pduDestination = npdu.npduDADR
|
|
else:
|
|
apdu.pduDestination = npdu.pduDestination
|
|
if _debug:
|
|
NetworkServiceAccessPoint._debug(" - apdu.pduSource: %r", apdu.pduSource)
|
|
NetworkServiceAccessPoint._debug(" - apdu.pduDestination: %r", apdu.pduDestination)
|
|
|
|
# pass upstream to the application layer
|
|
self.response(apdu)
|
|
|
|
if not forwardMessage:
|
|
return
|
|
else:
|
|
if processLocally:
|
|
if npdu.npduNetMessage not in npdu_types:
|
|
if _debug: NetworkServiceAccessPoint._debug(" - unknown npdu type: %r", npdu.npduNetMessage)
|
|
return
|
|
|
|
# do a deeper decode of the NPDU
|
|
xpdu = npdu_types[npdu.npduNetMessage](user_data=npdu.pduUserData)
|
|
xpdu.decode(_copy(npdu))
|
|
|
|
# pass to the service element
|
|
self.sap_request(adapter, xpdu)
|
|
|
|
if not forwardMessage:
|
|
return
|
|
|
|
# make sure we're really a router
|
|
if (len(self.adapters) == 1):
|
|
return
|
|
|
|
# make sure it hasn't looped
|
|
if (npdu.npduHopCount == 0):
|
|
return
|
|
|
|
# build a new NPDU to send to other adapters
|
|
newpdu = _copy(npdu)
|
|
|
|
# clear out the source and destination
|
|
newpdu.pduSource = None
|
|
newpdu.pduDestination = None
|
|
|
|
# decrease the hop count
|
|
newpdu.npduHopCount -= 1
|
|
|
|
# set the source address
|
|
if not npdu.npduSADR:
|
|
newpdu.npduSADR = RemoteStation( adapter.adapterNet, npdu.pduSource.addrAddr )
|
|
else:
|
|
newpdu.npduSADR = npdu.npduSADR
|
|
|
|
# if this is a broadcast it goes everywhere
|
|
if npdu.npduDADR.addrType == Address.globalBroadcastAddr:
|
|
newpdu.pduDestination = LocalBroadcast()
|
|
|
|
for xadapter in self.adapters:
|
|
if (xadapter is not adapter):
|
|
xadapter.process_npdu(newpdu)
|
|
return
|
|
|
|
if (npdu.npduDADR.addrType == Address.remoteBroadcastAddr) \
|
|
or (npdu.npduDADR.addrType == Address.remoteStationAddr):
|
|
dnet = npdu.npduDADR.addrNet
|
|
|
|
# see if this should go to one of our directly connected adapters
|
|
for xadapter in self.adapters:
|
|
if dnet == xadapter.adapterNet:
|
|
if _debug: NetworkServiceAccessPoint._debug(" - found direct connect via %r", xadapter)
|
|
if (npdu.npduDADR.addrType == Address.remoteBroadcastAddr):
|
|
newpdu.pduDestination = LocalBroadcast()
|
|
else:
|
|
newpdu.pduDestination = LocalStation(npdu.npduDADR.addrAddr)
|
|
|
|
# last leg in routing
|
|
newpdu.npduDADR = None
|
|
|
|
# send the packet downstream
|
|
xadapter.process_npdu(newpdu)
|
|
return
|
|
|
|
# see if we know how to get there
|
|
if dnet in self.networks:
|
|
rref = self.networks[dnet]
|
|
newpdu.pduDestination = rref.address
|
|
|
|
### check to make sure the router is OK
|
|
|
|
### check to make sure the network is OK, may need to connect
|
|
|
|
if _debug: NetworkServiceAccessPoint._debug(" - newpdu: %r", newpdu)
|
|
|
|
# send the packet downstream
|
|
rref.adapter.process_npdu(newpdu)
|
|
return
|
|
|
|
### queue this message for reprocessing when the response comes back
|
|
|
|
# try to find a path to the network
|
|
xnpdu = WhoIsRouterToNetwork(dnet)
|
|
xnpdu.pduDestination = LocalBroadcast()
|
|
|
|
# send it to all of the connected adapters
|
|
for xadapter in self.adapters:
|
|
# skip the horse it rode in on
|
|
if (xadapter is adapter):
|
|
continue
|
|
|
|
### make sure the adapter is OK
|
|
self.sap_indication(xadapter, xnpdu)
|
|
|
|
### log this, what to do?
|
|
return
|
|
|
|
def sap_indication(self, adapter, npdu):
|
|
if _debug: NetworkServiceAccessPoint._debug("sap_indication %r %r", adapter, npdu)
|
|
|
|
# encode it as a generic NPDU
|
|
xpdu = NPDU(user_data=npdu.pduUserData)
|
|
npdu.encode(xpdu)
|
|
npdu._xpdu = xpdu
|
|
|
|
# tell the adapter to process the NPDU
|
|
adapter.process_npdu(xpdu)
|
|
|
|
def sap_confirmation(self, adapter, npdu):
|
|
if _debug: NetworkServiceAccessPoint._debug("sap_confirmation %r %r", adapter, npdu)
|
|
|
|
# encode it as a generic NPDU
|
|
xpdu = NPDU(user_data=npdu.pduUserData)
|
|
npdu.encode(xpdu)
|
|
npdu._xpdu = xpdu
|
|
|
|
# tell the adapter to process the NPDU
|
|
adapter.process_npdu(xpdu)
|
|
|
|
#
|
|
# NetworkServiceElement
|
|
#
|
|
|
|
@bacpypes_debugging
|
|
class NetworkServiceElement(ApplicationServiceElement):
|
|
|
|
def __init__(self, eid=None):
|
|
if _debug: NetworkServiceElement._debug("__init__ eid=%r", eid)
|
|
ApplicationServiceElement.__init__(self, eid)
|
|
|
|
def indication(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("indication %r %r", adapter, npdu)
|
|
|
|
# redirect
|
|
fn = npdu.__class__.__name__
|
|
if hasattr(self, fn):
|
|
getattr(self, fn)(adapter, npdu)
|
|
|
|
def confirmation(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("confirmation %r %r", adapter, npdu)
|
|
|
|
# redirect
|
|
fn = npdu.__class__.__name__
|
|
if hasattr(self, fn):
|
|
getattr(self, fn)(adapter, npdu)
|
|
|
|
#-----
|
|
|
|
def WhoIsRouterToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("WhoIsRouterToNetwork %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
sap = self.elementService
|
|
if _debug: NetworkServiceElement._debug(" - sap: %r", sap)
|
|
|
|
# if we're not a router, skip it
|
|
if len(sap.adapters) == 1:
|
|
if _debug: NetworkServiceElement._debug(" - not a router")
|
|
return
|
|
|
|
if npdu.wirtnNetwork is None:
|
|
# requesting all networks
|
|
if _debug: NetworkServiceElement._debug(" - requesting all networks")
|
|
|
|
# build a list of reachable networks
|
|
netlist = []
|
|
|
|
# start with directly connected networks
|
|
for xadapter in sap.adapters:
|
|
if (xadapter is not adapter):
|
|
netlist.append(xadapter.adapterNet)
|
|
|
|
# build a list of other available networks
|
|
for net, rref in sap.networks.items():
|
|
if rref.adapter is not adapter:
|
|
### skip those marked unreachable
|
|
### skip those that are not available
|
|
netlist.append(net)
|
|
|
|
if netlist:
|
|
if _debug: NetworkServiceElement._debug(" - found these: %r", netlist)
|
|
|
|
# build a response
|
|
iamrtn = IAmRouterToNetwork(netlist, user_data=npdu.pduUserData)
|
|
iamrtn.pduDestination = npdu.pduSource
|
|
|
|
# send it back
|
|
self.response(adapter, iamrtn)
|
|
|
|
else:
|
|
# requesting a specific network
|
|
if _debug: NetworkServiceElement._debug(" - requesting specific network: %r", npdu.wirtnNetwork)
|
|
|
|
# start with directly connected networks
|
|
for xadapter in sap.adapters:
|
|
if (xadapter is not adapter) and (npdu.wirtnNetwork == xadapter.adapterNet):
|
|
if _debug: NetworkServiceElement._debug(" - found it directly connected")
|
|
|
|
# build a response
|
|
iamrtn = IAmRouterToNetwork([npdu.wirtnNetwork], user_data=npdu.pduUserData)
|
|
iamrtn.pduDestination = npdu.pduSource
|
|
|
|
# send it back
|
|
self.response(adapter, iamrtn)
|
|
|
|
break
|
|
else:
|
|
# check for networks I know about
|
|
if npdu.wirtnNetwork in sap.networks:
|
|
rref = sap.networks[npdu.wirtnNetwork]
|
|
if rref.adapter is adapter:
|
|
if _debug: NetworkServiceElement._debug(" - same net as request")
|
|
|
|
else:
|
|
if _debug: NetworkServiceElement._debug(" - found on adapter: %r", rref.adapter)
|
|
|
|
# build a response
|
|
iamrtn = IAmRouterToNetwork([npdu.wirtnNetwork], user_data=npdu.pduUserData)
|
|
iamrtn.pduDestination = npdu.pduSource
|
|
|
|
# send it back
|
|
self.response(adapter, iamrtn)
|
|
|
|
else:
|
|
if _debug: NetworkServiceElement._debug(" - forwarding request to other adapters")
|
|
|
|
# build a request
|
|
whoisrtn = WhoIsRouterToNetwork(npdu.wirtnNetwork, user_data=npdu.pduUserData)
|
|
whoisrtn.pduDestination = LocalBroadcast()
|
|
|
|
# if the request had a source, forward it along
|
|
if npdu.npduSADR:
|
|
whoisrtn.npduSADR = npdu.npduSADR
|
|
else:
|
|
whoisrtn.npduSADR = RemoteStation(adapter.adapterNet, npdu.pduSource.addrAddr)
|
|
if _debug: NetworkServiceElement._debug(" - whoisrtn: %r", whoisrtn)
|
|
|
|
# send it to all of the (other) adapters
|
|
for xadapter in sap.adapters:
|
|
if xadapter is not adapter:
|
|
if _debug: NetworkServiceElement._debug(" - sending on adapter: %r", xadapter)
|
|
self.request(xadapter, whoisrtn)
|
|
|
|
def IAmRouterToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("IAmRouterToNetwork %r %r", adapter, npdu)
|
|
|
|
# pass along to the service access point
|
|
self.elementService.add_router_references(adapter, npdu.pduSource, npdu.iartnNetworkList)
|
|
|
|
def ICouldBeRouterToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("ICouldBeRouterToNetwork %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|
|
def RejectMessageToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("RejectMessageToNetwork %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|
|
def RouterBusyToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("RouterBusyToNetwork %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|
|
def RouterAvailableToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("RouterAvailableToNetwork %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|
|
def InitializeRoutingTable(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("InitializeRoutingTable %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|
|
def InitializeRoutingTableAck(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("InitializeRoutingTableAck %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|
|
def EstablishConnectionToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("EstablishConnectionToNetwork %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|
|
def DisconnectConnectionToNetwork(self, adapter, npdu):
|
|
if _debug: NetworkServiceElement._debug("DisconnectConnectionToNetwork %r %r", adapter, npdu)
|
|
|
|
# reference the service access point
|
|
# sap = self.elementService
|
|
|