1
0
mirror of https://github.com/JoelBender/bacpypes synced 2025-09-28 22:15:23 +08:00

merge #181 with additional tests

This commit is contained in:
Joel Bender 2018-05-03 22:26:50 -04:00
parent 68bcfc869d
commit 3ee0cbd0dd
16 changed files with 1094 additions and 332 deletions

View File

@ -546,19 +546,31 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents):
return
elif isinstance(pdu, OriginalUnicastNPDU):
# check the BBMD registration status, we may not be registered
if self.registrationStatus != 0:
if _debug: BIPForeign._debug(" - packet dropped, unregistered")
return
if isinstance(pdu, OriginalUnicastNPDU):
# build a vanilla PDU
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
# check the BBMD registration status, we may not be registered
if self.registrationStatus != 0:
if _debug: BIPForeign._debug(" - packet dropped, unregistered")
return
elif isinstance(pdu, ForwardedNPDU):
# make sure the forwarded PDU from the bbmd
if pdu.pduSource != self.bbmdAddress:
if _debug: BIPForeign._debug(" - packet dropped, not from the BBMD")
return
if isinstance(pdu, ReadBroadcastDistributionTableAck):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
elif isinstance(pdu, ReadBroadcastDistributionTableAck):
# send this to the service access point
self.sap_response(pdu)
@ -566,13 +578,6 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents):
# send this to the service access point
self.sap_response(pdu)
elif isinstance(pdu, ForwardedNPDU):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
elif isinstance(pdu, WriteBroadcastDistributionTable):
# build a response
xpdu = Result(code=0x0010, user_data=pdu.pduUserData)
@ -696,7 +701,7 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
# make an original unicast PDU
xpdu = OriginalUnicastNPDU(pdu, user_data=pdu.pduUserData)
xpdu.pduDestination = pdu.pduDestination
if _debug: BIPBBMD._debug(" - xpdu: %r", xpdu)
if _debug: BIPBBMD._debug(" - original unicast xpdu: %r", xpdu)
# send it downstream
self.request(xpdu)
@ -719,13 +724,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte != self.bbmdAddress:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
else:
@ -741,8 +746,9 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
elif isinstance(pdu, WriteBroadcastDistributionTable):
# build a response
xpdu = Result(code=99, user_data=pdu.pduUserData)
xpdu = Result(code=0x0010, user_data=pdu.pduUserData)
xpdu.pduDestination = pdu.pduSource
if _debug: BIPBBMD._debug(" - xpdu: %r", xpdu)
# send it downstream
self.request(xpdu)
@ -761,27 +767,38 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
self.sap_response(pdu)
elif isinstance(pdu, ForwardedNPDU):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# build a forwarded NPDU to send out
xpdu = ForwardedNPDU(pdu.bvlciAddress, pdu, destination=None, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - forwarded xpdu: %r", xpdu)
# look for self as first entry in the BDT
if self.bbmdBDT and (self.bbmdBDT[0] == self.bbmdAddress):
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
# if this was unicast to us, do next hop
if pdu.pduDestination.addrType == Address.localStationAddr:
if _debug: BIPBBMD._debug(" - unicast message")
# if this BBMD is listed in its BDT, send a local broadcast
if self.bbmdAddress in self.bbmdBDT:
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
elif pdu.pduDestination.addrType == Address.localBroadcastAddr:
if _debug: BIPBBMD._debug(" - directed broadcast message")
else:
BIPBBMD._warning("invalid destination address: %r", pdu.pduDestination)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
elif isinstance(pdu, RegisterForeignDevice):
@ -820,12 +837,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
self.request(xpdu)
elif isinstance(pdu, DistributeBroadcastToNetwork):
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# build a forwarded NPDU to send out
xpdu = ForwardedNPDU(pdu.pduSource, pdu, user_data=pdu.pduUserData)
@ -835,35 +853,37 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte == self.bbmdAddress:
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
else:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the other registered foreign devices
for fdte in self.bbmdFDT:
if fdte.fdAddress != pdu.pduSource:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
elif isinstance(pdu, OriginalUnicastNPDU):
# build a vanilla PDU
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
elif isinstance(pdu, OriginalBroadcastNPDU):
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# make a forwarded PDU
xpdu = ForwardedNPDU(pdu.pduSource, pdu, user_data=pdu.pduUserData)
@ -873,13 +893,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte != self.bbmdAddress:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
else:
@ -929,7 +949,7 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
del self.bbmdFDT[i]
break
else:
stat = 99 ### entry not found
stat = 0x0050 ### entry not found
# return status
return stat
@ -956,10 +976,6 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
else:
raise TypeError("addr must be a string or an Address")
# if it's this BBMD, make it the first one
if self.bbmdBDT and (addr == self.bbmdAddress):
raise RuntimeError("add self to BDT as first address")
# see if it's already there
for bdte in self.bbmdBDT:
if addr == bdte:

View File

@ -161,9 +161,9 @@ class IPNetwork(Network):
('1.2.3.255', 5) and the other nodes must have the same tuple.
"""
def __init__(self):
def __init__(self, name=''):
if _debug: IPNetwork._debug("__init__")
Network.__init__(self)
Network.__init__(self, name=name)
def add_node(self, node):
if _debug: IPNetwork._debug("add_node %r", node)
@ -213,7 +213,7 @@ bacpypes_debugging(IPNode)
class IPRouterNode(Client):
def __init__(self, router, addr, lan=None):
def __init__(self, router, addr, lan):
if _debug: IPRouterNode._debug("__init__ %r %r lan=%r", router, addr, lan)
# save the reference to the router
@ -238,6 +238,9 @@ class IPRouterNode(Client):
# pass it downstream
self.request(pdu)
def __repr__(self):
return "<%s for %s>" % (self.__class__.__name__, self.lan.name)
bacpypes_debugging(IPRouterNode)
#

View File

@ -542,20 +542,31 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents):
return
elif isinstance(pdu, OriginalUnicastNPDU):
# build a vanilla PDU
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
return
# check the BBMD registration status, we may not be registered
if self.registrationStatus != 0:
if _debug: BIPForeign._debug(" - packet dropped, unregistered")
return
if isinstance(pdu, ReadBroadcastDistributionTableAck):
if isinstance(pdu, OriginalUnicastNPDU):
# build a vanilla PDU
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
elif isinstance(pdu, ForwardedNPDU):
# make sure the forwarded PDU from the bbmd
if pdu.pduSource != self.bbmdAddress:
if _debug: BIPForeign._debug(" - packet dropped, not from the BBMD")
return
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
elif isinstance(pdu, ReadBroadcastDistributionTableAck):
# send this to the service access point
self.sap_response(pdu)
@ -563,13 +574,6 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents):
# send this to the service access point
self.sap_response(pdu)
elif isinstance(pdu, ForwardedNPDU):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
elif isinstance(pdu, WriteBroadcastDistributionTable):
# build a response
xpdu = Result(code=0x0010, user_data=pdu.pduUserData)
@ -692,7 +696,7 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
# make an original unicast PDU
xpdu = OriginalUnicastNPDU(pdu, user_data=pdu.pduUserData)
xpdu.pduDestination = pdu.pduDestination
if _debug: BIPBBMD._debug(" - xpdu: %r", xpdu)
if _debug: BIPBBMD._debug(" - original unicast xpdu: %r", xpdu)
# send it downstream
self.request(xpdu)
@ -715,13 +719,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte != self.bbmdAddress:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
else:
@ -737,8 +741,9 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
elif isinstance(pdu, WriteBroadcastDistributionTable):
# build a response
xpdu = Result(code=99, user_data=pdu.pduUserData)
xpdu = Result(code=0x0010, user_data=pdu.pduUserData)
xpdu.pduDestination = pdu.pduSource
if _debug: BIPBBMD._debug(" - xpdu: %r", xpdu)
# send it downstream
self.request(xpdu)
@ -757,27 +762,38 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
self.sap_response(pdu)
elif isinstance(pdu, ForwardedNPDU):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# build a forwarded NPDU to send out
xpdu = ForwardedNPDU(pdu.bvlciAddress, pdu, destination=None, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - forwarded xpdu: %r", xpdu)
# look for self as first entry in the BDT
if self.bbmdBDT and (self.bbmdBDT[0] == self.bbmdAddress):
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
# if this was unicast to us, do next hop
if pdu.pduDestination.addrType == Address.localStationAddr:
if _debug: BIPBBMD._debug(" - unicast message")
# if this BBMD is listed in its BDT, send a local broadcast
if self.bbmdAddress in self.bbmdBDT:
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
elif pdu.pduDestination.addrType == Address.localBroadcastAddr:
if _debug: BIPBBMD._debug(" - directed broadcast message")
else:
BIPBBMD._warning("invalid destination address: %r", pdu.pduDestination)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
elif isinstance(pdu, RegisterForeignDevice):
@ -816,12 +832,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
self.request(xpdu)
elif isinstance(pdu, DistributeBroadcastToNetwork):
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# build a forwarded NPDU to send out
xpdu = ForwardedNPDU(pdu.pduSource, pdu, user_data=pdu.pduUserData)
@ -831,35 +848,37 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte == self.bbmdAddress:
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
else:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the other registered foreign devices
for fdte in self.bbmdFDT:
if fdte.fdAddress != pdu.pduSource:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
elif isinstance(pdu, OriginalUnicastNPDU):
# build a vanilla PDU
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
elif isinstance(pdu, OriginalBroadcastNPDU):
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# make a forwarded PDU
xpdu = ForwardedNPDU(pdu.pduSource, pdu, user_data=pdu.pduUserData)
@ -869,13 +888,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte != self.bbmdAddress:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
else:
@ -925,7 +944,7 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
del self.bbmdFDT[i]
break
else:
stat = 99 ### entry not found
stat = 0x0050 ### entry not found
# return status
return stat
@ -952,10 +971,6 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
else:
raise TypeError("addr must be a string or an Address")
# if it's this BBMD, make it the first one
if self.bbmdBDT and (addr == self.bbmdAddress):
raise RuntimeError("add self to BDT as first address")
# see if it's already there
for bdte in self.bbmdBDT:
if addr == bdte:

View File

@ -161,9 +161,9 @@ class IPNetwork(Network):
('1.2.3.255', 5) and the other nodes must have the same tuple.
"""
def __init__(self):
def __init__(self, name=''):
if _debug: IPNetwork._debug("__init__")
Network.__init__(self)
Network.__init__(self, name=name)
def add_node(self, node):
if _debug: IPNetwork._debug("add_node %r", node)
@ -213,7 +213,7 @@ class IPNode(Node):
@bacpypes_debugging
class IPRouterNode(Client):
def __init__(self, router, addr, lan=None):
def __init__(self, router, addr, lan):
if _debug: IPRouterNode._debug("__init__ %r %r lan=%r", router, addr, lan)
# save the reference to the router
@ -238,6 +238,9 @@ class IPRouterNode(Client):
# pass it downstream
self.request(pdu)
def __repr__(self):
return "<%s for %s>" % (self.__class__.__name__, self.lan.name)
#
# IPRouter
#

View File

@ -541,19 +541,31 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents):
return
elif isinstance(pdu, OriginalUnicastNPDU):
# check the BBMD registration status, we may not be registered
if self.registrationStatus != 0:
if _debug: BIPForeign._debug(" - packet dropped, unregistered")
return
if isinstance(pdu, OriginalUnicastNPDU):
# build a vanilla PDU
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
# check the BBMD registration status, we may not be registered
if self.registrationStatus != 0:
if _debug: BIPForeign._debug(" - packet dropped, unregistered")
return
elif isinstance(pdu, ForwardedNPDU):
# make sure the forwarded PDU from the bbmd
if pdu.pduSource != self.bbmdAddress:
if _debug: BIPForeign._debug(" - packet dropped, not from the BBMD")
return
if isinstance(pdu, ReadBroadcastDistributionTableAck):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
elif isinstance(pdu, ReadBroadcastDistributionTableAck):
# send this to the service access point
self.sap_response(pdu)
@ -561,13 +573,6 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents):
# send this to the service access point
self.sap_response(pdu)
elif isinstance(pdu, ForwardedNPDU):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
# send it upstream
self.response(xpdu)
elif isinstance(pdu, WriteBroadcastDistributionTable):
# build a response
xpdu = Result(code=0x0010, user_data=pdu.pduUserData)
@ -690,7 +695,7 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
# make an original unicast PDU
xpdu = OriginalUnicastNPDU(pdu, user_data=pdu.pduUserData)
xpdu.pduDestination = pdu.pduDestination
if _debug: BIPBBMD._debug(" - xpdu: %r", xpdu)
if _debug: BIPBBMD._debug(" - original unicast xpdu: %r", xpdu)
# send it downstream
self.request(xpdu)
@ -713,13 +718,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte != self.bbmdAddress:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
else:
@ -735,8 +740,9 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
elif isinstance(pdu, WriteBroadcastDistributionTable):
# build a response
xpdu = Result(code=99, user_data=pdu.pduUserData)
xpdu = Result(code=0x0010, user_data=pdu.pduUserData)
xpdu.pduDestination = pdu.pduSource
if _debug: BIPBBMD._debug(" - xpdu: %r", xpdu)
# send it downstream
self.request(xpdu)
@ -755,27 +761,38 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
self.sap_response(pdu)
elif isinstance(pdu, ForwardedNPDU):
# build a PDU with the source from the real source
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.bvlciAddress, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# build a forwarded NPDU to send out
xpdu = ForwardedNPDU(pdu.bvlciAddress, pdu, destination=None, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - forwarded xpdu: %r", xpdu)
# look for self as first entry in the BDT
if self.bbmdBDT and (self.bbmdBDT[0] == self.bbmdAddress):
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
# if this was unicast to us, do next hop
if pdu.pduDestination.addrType == Address.localStationAddr:
if _debug: BIPBBMD._debug(" - unicast message")
# if this BBMD is listed in its BDT, send a local broadcast
if self.bbmdAddress in self.bbmdBDT:
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
elif pdu.pduDestination.addrType == Address.localBroadcastAddr:
if _debug: BIPBBMD._debug(" - directed broadcast message")
else:
BIPBBMD._warning("invalid destination address: %r", pdu.pduDestination)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
elif isinstance(pdu, RegisterForeignDevice):
@ -814,12 +831,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
self.request(xpdu)
elif isinstance(pdu, DistributeBroadcastToNetwork):
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# build a forwarded NPDU to send out
xpdu = ForwardedNPDU(pdu.pduSource, pdu, user_data=pdu.pduUserData)
@ -829,35 +847,37 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte == self.bbmdAddress:
xpdu.pduDestination = LocalBroadcast()
if _debug: BIPBBMD._debug(" - local broadcast")
if _debug: BIPBBMD._debug(" - local broadcast")
self.request(xpdu)
else:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the other registered foreign devices
for fdte in self.bbmdFDT:
if fdte.fdAddress != pdu.pduSource:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
elif isinstance(pdu, OriginalUnicastNPDU):
# build a vanilla PDU
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=pdu.pduDestination, user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
elif isinstance(pdu, OriginalBroadcastNPDU):
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream if there is a network layer
if self.serverPeer:
# build a PDU with a local broadcast address
xpdu = PDU(pdu.pduData, source=pdu.pduSource, destination=LocalBroadcast(), user_data=pdu.pduUserData)
if _debug: BIPBBMD._debug(" - upstream xpdu: %r", xpdu)
# send it upstream
self.response(xpdu)
self.response(xpdu)
# make a forwarded PDU
xpdu = ForwardedNPDU(pdu.pduSource, pdu, user_data=pdu.pduUserData)
@ -867,13 +887,13 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
for bdte in self.bbmdBDT:
if bdte != self.bbmdAddress:
xpdu.pduDestination = Address( ((bdte.addrIP|~bdte.addrMask), bdte.addrPort) )
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to peer: %r", xpdu.pduDestination)
self.request(xpdu)
# send it to the registered foreign devices
for fdte in self.bbmdFDT:
xpdu.pduDestination = fdte.fdAddress
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
if _debug: BIPBBMD._debug(" - sending to foreign device: %r", xpdu.pduDestination)
self.request(xpdu)
else:
@ -923,7 +943,7 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
del self.bbmdFDT[i]
break
else:
stat = 99 ### entry not found
stat = 0x0050 ### entry not found
# return status
return stat
@ -950,10 +970,6 @@ class BIPBBMD(BIPSAP, Client, Server, RecurringTask, DebugContents):
else:
raise TypeError("addr must be a string or an Address")
# if it's this BBMD, make it the first one
if self.bbmdBDT and (addr == self.bbmdAddress):
raise RuntimeError("add self to BDT as first address")
# see if it's already there
for bdte in self.bbmdBDT:
if addr == bdte:

View File

@ -161,9 +161,9 @@ class IPNetwork(Network):
('1.2.3.255', 5) and the other nodes must have the same tuple.
"""
def __init__(self):
def __init__(self, name=''):
if _debug: IPNetwork._debug("__init__")
Network.__init__(self)
Network.__init__(self, name=name)
def add_node(self, node):
if _debug: IPNetwork._debug("add_node %r", node)
@ -213,7 +213,7 @@ class IPNode(Node):
@bacpypes_debugging
class IPRouterNode(Client):
def __init__(self, router, addr, lan=None):
def __init__(self, router, addr, lan):
if _debug: IPRouterNode._debug("__init__ %r %r lan=%r", router, addr, lan)
# save the reference to the router
@ -238,6 +238,9 @@ class IPRouterNode(Client):
# pass it downstream
self.request(pdu)
def __repr__(self):
return "<%s for %s>" % (self.__class__.__name__, self.lan.name)
#
# IPRouter
#

139
samples/NATRouter.py Normal file
View File

@ -0,0 +1,139 @@
#!/usr/bin/env python
"""
This sample application presents itself as a router between an "inside" network
that sits behind a NAT and a "global" network of other NAT router peers.
$ python NATRouter.py addr1 port1 net1 addr2 port2 net2
addr1 - local address like 192.168.1.10/24
port1 - local port
net1 - local network number
addr2 - global address like 201.1.1.1:47809
port2 - local mapped port
net2 - global network number
The sample addresses are like running BR1 from Figure J-8, Clause J.7.5.
"""
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.consolelogging import ArgumentParser
from bacpypes.core import run
from bacpypes.comm import bind
from bacpypes.pdu import Address
from bacpypes.netservice import NetworkServiceAccessPoint, NetworkServiceElement
from bacpypes.bvllservice import BIPBBMD, BIPNAT, AnnexJCodec, UDPMultiplexer
# some debugging
_debug = 0
_log = ModuleLogger(globals())
#
# NATRouter
#
@bacpypes_debugging
class NATRouter:
def __init__(self, addr1, port1, net1, addr2, port2, net2):
if _debug: NATRouter._debug("__init__ %r %r %r %r %r %r", addr1, port1, net1, addr2, port2, net2)
# a network service access point will be needed
self.nsap = NetworkServiceAccessPoint()
# give the NSAP a generic network layer service element
self.nse = NetworkServiceElement()
bind(self.nse, self.nsap)
#== First stack
# local address
local_addr = Address("{}:{}".format(addr1, port1))
# create a BBMD stack
self.s1_bip = BIPBBMD(local_addr)
self.s1_annexj = AnnexJCodec()
self.s1_mux = UDPMultiplexer(local_addr)
# bind the bottom layers
bind(self.s1_bip, self.s1_annexj, self.s1_mux.annexJ)
# bind the BIP stack to the local network
self.nsap.bind(self.s1_bip, net1, addr1)
#== Second stack
# global address
global_addr = Address(addr2)
nat_addr = Address("{}:{}".format(addr1, port2))
# create a NAT stack
self.s2_bip = BIPNAT(global_addr)
self.s2_annexj = AnnexJCodec()
self.s2_mux = UDPMultiplexer(nat_addr)
# bind the bottom layers
bind(self.s2_bip, self.s2_annexj, self.s2_mux.annexJ)
# bind the BIP stack to the global network
self.nsap.bind(self.s2_bip, net2)
#
# __main__
#
def main():
# parse the command line arguments
parser = ArgumentParser(description=__doc__)
# add an argument for local address
parser.add_argument('addr1', type=str,
help='address of first network',
)
# add an argument for local port
parser.add_argument('port1', type=int,
help='port number of local network',
)
# add an argument for interval
parser.add_argument('net1', type=int,
help='network number of local network',
)
# add an argument for interval
parser.add_argument('addr2', type=str,
help='address of global network (outside NAT)',
)
# add an argument for local port
parser.add_argument('port2', type=int,
help='port number of global forwarded port',
)
# add an argument for interval
parser.add_argument('net2', type=int,
help='network number of global network',
)
# now parse the arguments
args = parser.parse_args()
if _debug: _log.debug("initialization")
if _debug: _log.debug(" - args: %r", args)
# create the router
router = NATRouter(args.addr1, args.port1, args.net1, args.addr2, args.port2, args.net2)
if _debug: _log.debug(" - router: %r", router)
_log.debug("running")
run()
_log.debug("fini")
if __name__ == "__main__":
main()

View File

@ -6,10 +6,19 @@ B/IP VLAN Helper Classes
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.comm import Client, Server, bind
from bacpypes.comm import Client, Server, ApplicationServiceElement, bind
from bacpypes.pdu import Address, LocalBroadcast, PDU, unpack_ip_addr
from bacpypes.vlan import IPNode
from bacpypes.app import DeviceInfoCache, Application
from bacpypes.appservice import StateMachineAccessPoint, ApplicationServiceAccessPoint
from bacpypes.netservice import NetworkServiceAccessPoint, NetworkServiceElement
from bacpypes.object import register_object_type
from bacpypes.local.device import LocalDeviceObject
from bacpypes.service.device import WhoIsIAmServices
from bacpypes.service.object import ReadWritePropertyServices
from ..state_machine import ClientStateMachine
from bacpypes.bvllservice import BIPSimple, BIPForeign, BIPBBMD, AnnexJCodec
@ -26,6 +35,12 @@ _log = ModuleLogger(globals())
@bacpypes_debugging
class FauxMultiplexer(Client, Server):
"""This class is a placeholder for UDPMultiplexer without the code that
determines if the upstream packets are Annex-H or Annex-J packets, it
assumes they are all Annex-J. It creates and binds itself to an IPNode
which is added to an IPNetwork.
"""
def __init__(self, addr, network=None, cid=None, sid=None):
if _debug: FauxMultiplexer._debug("__init__")
@ -81,37 +96,54 @@ class FauxMultiplexer(Client, Server):
self.response(PDU(pdu, source=src, destination=dest))
#
# SnifferNode
# SnifferStateMachine
#
@bacpypes_debugging
class SnifferNode(ClientStateMachine):
class SnifferStateMachine(ClientStateMachine):
"""This class acts as a sniffer for BVLL messages. The client state
machine sits above an Annex-J codec so the send and receive PDUs are
BVLL PDUs.
"""
def __init__(self, address, vlan):
if _debug: SnifferNode._debug("__init__ %r %r", address, vlan)
if _debug: SnifferStateMachine._debug("__init__ %r %r", address, vlan)
ClientStateMachine.__init__(self)
# save the name and address
self.name = address
self.address = Address(address)
# create a promiscuous node, added to the network
self.node = IPNode(self.address, vlan, promiscuous=True)
if _debug: SnifferNode._debug(" - node: %r", self.node)
# BACnet/IP interpreter
self.annexj = AnnexJCodec()
# bind this to the node
bind(self, self.node)
# fake multiplexer has a VLAN node in it
self.mux = FauxMultiplexer(self.address, vlan)
# might receive all packets and allow spoofing
self.mux.node.promiscuous = True
self.mux.node.spoofing = True
# bind the stack together
bind(self, self.annexj, self.mux)
#
# CodecNode
# BIPStateMachine
#
@bacpypes_debugging
class CodecNode(ClientStateMachine):
class BIPStateMachine(ClientStateMachine):
"""This class is an application layer for BVLL messages that has no BVLL
processing like the 'simple', 'foreign', or 'bbmd' versions. The client
state machine sits above and Annex-J codec so the send and receive PDUs are
BVLL PDUs.
"""
def __init__(self, address, vlan):
if _debug: CodecNode._debug("__init__ %r %r", address, vlan)
if _debug: BIPStateMachine._debug("__init__ %r %r", address, vlan)
ClientStateMachine.__init__(self)
# save the name and address
@ -129,14 +161,18 @@ class CodecNode(ClientStateMachine):
#
# SimpleNode
# BIPSimpleStateMachine
#
@bacpypes_debugging
class SimpleNode(ClientStateMachine):
class BIPSimpleStateMachine(ClientStateMachine):
"""This class sits on a BIPSimple instance, the send() and receive()
parameters are NPDUs.
"""
def __init__(self, address, vlan):
if _debug: SimpleNode._debug("__init__ %r %r", address, vlan)
if _debug: BIPSimpleStateMachine._debug("__init__ %r %r", address, vlan)
ClientStateMachine.__init__(self)
# save the name and address
@ -155,14 +191,18 @@ class SimpleNode(ClientStateMachine):
#
# ForeignNode
# BIPForeignStateMachine
#
@bacpypes_debugging
class ForeignNode(ClientStateMachine):
class BIPForeignStateMachine(ClientStateMachine):
"""This class sits on a BIPForeign instance, the send() and receive()
parameters are NPDUs.
"""
def __init__(self, address, vlan):
if _debug: ForeignNode._debug("__init__ %r %r", address, vlan)
if _debug: BIPForeignStateMachine._debug("__init__ %r %r", address, vlan)
ClientStateMachine.__init__(self)
# save the name and address
@ -180,14 +220,18 @@ class ForeignNode(ClientStateMachine):
bind(self, self.bip, self.annexj, self.mux)
#
# BBMDNode
# BIPBBMDStateMachine
#
@bacpypes_debugging
class BBMDNode(ClientStateMachine):
class BIPBBMDStateMachine(ClientStateMachine):
"""This class sits on a BIPBBMD instance, the send() and receive()
parameters are NPDUs.
"""
def __init__(self, address, vlan):
if _debug: BBMDNode._debug("__init__ %r %r", address, vlan)
if _debug: BIPBBMDStateMachine._debug("__init__ %r %r", address, vlan)
ClientStateMachine.__init__(self)
# save the name and address
@ -200,7 +244,7 @@ class BBMDNode(ClientStateMachine):
# build an address, full mask
bdt_address = "%s/32:%d" % self.address.addrTuple
if _debug: BBMDNode._debug(" - bdt_address: %r", bdt_address)
if _debug: BIPBBMDStateMachine._debug(" - bdt_address: %r", bdt_address)
# add itself as the first entry in the BDT
self.bip.add_peer(Address(bdt_address))
@ -211,3 +255,209 @@ class BBMDNode(ClientStateMachine):
# bind the stack together
bind(self, self.bip, self.annexj, self.mux)
#
# BIPSimpleNode
#
@bacpypes_debugging
class BIPSimpleNode:
"""This class is a BIPSimple instance that is not bound to a state machine."""
def __init__(self, address, vlan):
if _debug: BIPSimpleNode._debug("__init__ %r %r", address, vlan)
# save the name and address
self.name = address
self.address = Address(address)
# BACnet/IP interpreter
self.bip = BIPSimple()
self.annexj = AnnexJCodec()
# fake multiplexer has a VLAN node in it
self.mux = FauxMultiplexer(self.address, vlan)
# bind the stack together
bind(self.bip, self.annexj, self.mux)
#
# BIPBBMDNode
#
@bacpypes_debugging
class BIPBBMDNode:
"""This class is a BIPBBMD instance that is not bound to a state machine."""
def __init__(self, address, vlan):
if _debug: BIPBBMDNode._debug("__init__ %r %r", address, vlan)
# save the name and address
self.name = address
self.address = Address(address)
if _debug: BIPBBMDNode._debug(" - address: %r", self.address)
# BACnet/IP interpreter
self.bip = BIPBBMD(self.address)
self.annexj = AnnexJCodec()
# build an address, full mask
bdt_address = "%s/32:%d" % self.address.addrTuple
if _debug: BIPBBMDNode._debug(" - bdt_address: %r", bdt_address)
# add itself as the first entry in the BDT
self.bip.add_peer(Address(bdt_address))
# fake multiplexer has a VLAN node in it
self.mux = FauxMultiplexer(self.address, vlan)
# bind the stack together
bind(self.bip, self.annexj, self.mux)
#
# TestDeviceObject
#
@register_object_type(vendor_id=999)
class TestDeviceObject(LocalDeviceObject):
pass
#
# BIPSimpleApplicationLayerStateMachine
#
@bacpypes_debugging
class BIPSimpleApplicationLayerStateMachine(ApplicationServiceElement, ClientStateMachine):
def __init__(self, address, vlan):
if _debug: BIPSimpleApplicationLayerStateMachine._debug("__init__ %r %r", address, vlan)
# build a name, save the address
self.name = "app @ %s" % (address,)
self.address = Address(address)
# build a local device object
local_device = TestDeviceObject(
objectName=self.name,
objectIdentifier=('device', 998),
vendorIdentifier=999,
)
# build an address and save it
self.address = Address(address)
if _debug: BIPSimpleApplicationLayerStateMachine._debug(" - address: %r", self.address)
# continue with initialization
ApplicationServiceElement.__init__(self)
ClientStateMachine.__init__(self, name=local_device.objectName)
# include a application decoder
self.asap = ApplicationServiceAccessPoint()
# pass the device object to the state machine access point so it
# can know if it should support segmentation
self.smap = StateMachineAccessPoint(local_device)
# the segmentation state machines need access to some device
# information cache, usually shared with the application
self.smap.deviceInfoCache = DeviceInfoCache()
# a network service access point will be needed
self.nsap = NetworkServiceAccessPoint()
# give the NSAP a generic network layer service element
self.nse = NetworkServiceElement()
bind(self.nse, self.nsap)
# bind the top layers
bind(self, self.asap, self.smap, self.nsap)
# BACnet/IP interpreter
self.bip = BIPSimple()
self.annexj = AnnexJCodec()
# fake multiplexer has a VLAN node in it
self.mux = FauxMultiplexer(self.address, vlan)
# bind the stack together
bind(self.bip, self.annexj, self.mux)
# bind the stack to the local network
self.nsap.bind(self.bip)
def indication(self, apdu):
if _debug: BIPSimpleApplicationLayerStateMachine._debug("indication %r", apdu)
self.receive(apdu)
def confirmation(self, apdu):
if _debug: BIPSimpleApplicationLayerStateMachine._debug("confirmation %r %r", apdu)
self.receive(apdu)
#
# BIPBBMDApplication
#
class BIPBBMDApplication(Application, WhoIsIAmServices, ReadWritePropertyServices):
def __init__(self, address, vlan):
if _debug: BIPBBMDApplication._debug("__init__ %r %r", address, vlan)
# build a name, save the address
self.name = "app @ %s" % (address,)
self.address = Address(address)
if _debug: BIPBBMDApplication._debug(" - address: %r", self.address)
# build a local device object
local_device = TestDeviceObject(
objectName=self.name,
objectIdentifier=('device', 999),
vendorIdentifier=999,
)
# continue with initialization
Application.__init__(self, local_device, self.address)
# include a application decoder
self.asap = ApplicationServiceAccessPoint()
# pass the device object to the state machine access point so it
# can know if it should support segmentation
self.smap = StateMachineAccessPoint(local_device)
# the segmentation state machines need access to the same device
# information cache as the application
self.smap.deviceInfoCache = self.deviceInfoCache
# a network service access point will be needed
self.nsap = NetworkServiceAccessPoint()
# give the NSAP a generic network layer service element
self.nse = NetworkServiceElement()
bind(self.nse, self.nsap)
# bind the top layers
bind(self, self.asap, self.smap, self.nsap)
# BACnet/IP interpreter
self.bip = BIPBBMD(self.address)
self.annexj = AnnexJCodec()
# build an address, full mask
bdt_address = "%s/32:%d" % self.address.addrTuple
if _debug: BIPBBMDNode._debug(" - bdt_address: %r", bdt_address)
# add itself as the first entry in the BDT
self.bip.add_peer(Address(bdt_address))
# fake multiplexer has a VLAN node in it
self.mux = FauxMultiplexer(self.address, vlan)
# bind the stack together
bind(self.bip, self.annexj, self.mux)
# bind the stack to the local network
self.nsap.bind(self.bip)

View File

@ -1 +1,302 @@
# placeholder
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test BBMD
---------
"""
import unittest
from bacpypes.debugging import bacpypes_debugging, ModuleLogger, xtob
from bacpypes.pdu import Address, PDU, LocalBroadcast
from bacpypes.vlan import IPNetwork, IPRouter
from bacpypes.bvll import (
Result,
WriteBroadcastDistributionTable,
ReadBroadcastDistributionTable, ReadBroadcastDistributionTableAck,
ForwardedNPDU,
RegisterForeignDevice,
ReadForeignDeviceTable, ReadForeignDeviceTableAck,
DeleteForeignDeviceTableEntry,
DistributeBroadcastToNetwork,
OriginalUnicastNPDU,
OriginalBroadcastNPDU,
)
from bacpypes.apdu import (
WhoIsRequest, IAmRequest,
ReadPropertyRequest, ReadPropertyACK,
AbortPDU,
)
from ..state_machine import StateMachineGroup, TrafficLog
from ..time_machine import reset_time_machine, run_time_machine
from .helpers import (
SnifferStateMachine, BIPStateMachine, BIPSimpleStateMachine,
BIPForeignStateMachine, BIPBBMDStateMachine,
BIPSimpleNode, BIPBBMDNode,
BIPSimpleApplicationLayerStateMachine,
BIPBBMDApplication,
)
# some debugging
_debug = 0
_log = ModuleLogger(globals())
#
# TNetwork
#
@bacpypes_debugging
class TNetwork(StateMachineGroup):
def __init__(self, count):
if _debug: TNetwork._debug("__init__ %r", count)
StateMachineGroup.__init__(self)
# reset the time machine
reset_time_machine()
if _debug: TNetwork._debug(" - time machine reset")
# create a traffic log
self.traffic_log = TrafficLog()
# make a router
self.router = IPRouter()
# make the networks
self.vlan = []
for net in range(1, count + 1):
# make a network and set the traffic log
ip_network = IPNetwork("192.168.{}.0/24".format(net))
ip_network.traffic_log = self.traffic_log
# make a router
router_address = Address("192.168.{}.1/24".format(net))
self.router.add_network(router_address, ip_network)
self.vlan.append(ip_network)
def run(self, time_limit=60.0):
if _debug: TNetwork._debug("run %r", time_limit)
# run the group
super(TNetwork, self).run()
# run it for some time
run_time_machine(time_limit)
if _debug: TNetwork._debug(" - time machine finished")
# check for success
all_success, some_failed = super(TNetwork, self).check_for_success()
if _debug:
TNetwork._debug(" - all_success, some_failed: %r, %r", all_success, some_failed)
for state_machine in self.state_machines:
if state_machine.running:
TNetwork._debug(" %r (running)", state_machine)
elif not state_machine.current_state:
TNetwork._debug(" %r (not started)", state_machine)
else:
TNetwork._debug(" %r", state_machine)
for direction, pdu in state_machine.transaction_log:
TNetwork._debug(" %s %r", direction, pdu)
# traffic log has what was processed on each vlan
self.traffic_log.dump(TNetwork._debug)
assert all_success
@bacpypes_debugging
class TestNonBBMD(unittest.TestCase):
def setup_method(self, method):
"""This function is called before each test method is called and is
given a reference to the test method."""
if _debug: TestNonBBMD._debug("setup_method %r", method)
# create a network
self.tnet = TNetwork(1)
# test device
self.td = BIPStateMachine("192.168.1.2/24", self.tnet.vlan[0])
self.tnet.append(self.td)
# implementation under test
self.iut = BIPSimpleNode("192.168.1.3/24", self.tnet.vlan[0])
def test_write_bdt_fail(self):
"""Test writing a BDT."""
if _debug: TestNonBBMD._debug("test_write_bdt_fail")
# read the broadcast distribution table, get a nack
self.td.start_state.doc("1-1-0") \
.send(WriteBroadcastDistributionTable(destination=self.iut.address)).doc("1-1-1") \
.receive(Result, bvlciResultCode=0x0010).doc("1-1-2") \
.success()
# run the group
self.tnet.run()
def test_read_bdt_fail(self):
"""Test reading a BDT."""
if _debug: TestNonBBMD._debug("test_read_bdt_fail")
# read the broadcast distribution table, get a nack
self.td.start_state.doc("1-2-0") \
.send(ReadBroadcastDistributionTable(destination=self.iut.address)).doc("1-2-1") \
.receive(Result, bvlciResultCode=0x0020).doc("1-2-2") \
.success()
# run the group
self.tnet.run()
def test_register_fail(self):
"""Test registering as a foreign device to a non-BBMD."""
if _debug: TestNonBBMD._debug("test_read_fdt_success")
# read the broadcast distribution table, get a nack
self.td.start_state.doc("1-3-0") \
.send(RegisterForeignDevice(10, destination=self.iut.address)).doc("1-3-1") \
.receive(Result, bvlciResultCode=0x0030).doc("1-3-2") \
.success()
# run the group
self.tnet.run()
def test_read_fdt_fail(self):
"""Test reading an FDT from a non-BBMD."""
if _debug: TestNonBBMD._debug("test_read_fdt_success")
# read the broadcast distribution table, get a nack
self.td.start_state.doc("1-4-0") \
.send(ReadForeignDeviceTable(destination=self.iut.address)).doc("1-4-1") \
.receive(Result, bvlciResultCode=0x0040).doc("1-4-2") \
.success()
# run the group
self.tnet.run()
def test_delete_fail(self):
"""Test deleting an FDT entry from a non-BBMD."""
if _debug: TestNonBBMD._debug("test_delete_fail")
# read the broadcast distribution table, get a nack
self.td.start_state.doc("1-5-0") \
.send(DeleteForeignDeviceTableEntry(Address("1.2.3.4"), destination=self.iut.address)).doc("1-5-1") \
.receive(Result, bvlciResultCode=0x0050).doc("1-5-2") \
.success()
# run the group
self.tnet.run()
def test_distribute_fail(self):
"""Test asking a non-BBMD to distribute a broadcast."""
if _debug: TestNonBBMD._debug("test_delete_fail")
# read the broadcast distribution table, get a nack
self.td.start_state.doc("1-6-0") \
.send(DistributeBroadcastToNetwork(xtob('deadbeef'), destination=self.iut.address)).doc("1-6-1") \
.receive(Result, bvlciResultCode=0x0060).doc("1-6-2") \
.success()
# run the group
self.tnet.run()
@bacpypes_debugging
class TestBBMD(unittest.TestCase):
def test_14_2_1_1(self):
"""14.2.1.1 Execute Forwarded-NPDU (One-hop Distribution)."""
if _debug: TestBBMD._debug("test_14_2_1_1")
# create a network
tnet = TNetwork(2)
# implementation under test
iut = BIPBBMDApplication("192.168.1.2/24", tnet.vlan[0])
if _debug: TestBBMD._debug(" - iut.bip: %r", iut.bip)
# BBMD on net 2
bbmd1 = BIPBBMDNode("192.168.2.2/24", tnet.vlan[1])
# add the IUT as a one-hop peer
bbmd1.bip.add_peer(Address("192.168.1.2/24"))
if _debug: TestBBMD._debug(" - bbmd1.bip: %r", bbmd1.bip)
# test device
td = BIPSimpleApplicationLayerStateMachine("192.168.2.3/24", tnet.vlan[1])
tnet.append(td)
# listener looks for extra traffic
listener = BIPStateMachine("192.168.1.3/24", tnet.vlan[0])
listener.mux.node.promiscuous = True
tnet.append(listener)
# broadcast a forwarded NPDU
td.start_state.doc("2-1-0") \
.send(WhoIsRequest(destination=LocalBroadcast())).doc("2-1-1") \
.receive(IAmRequest).doc("2-1-2") \
.success()
# listen for the directed broadcast, then the original unicast,
# then fail if there's anything else
listener.start_state.doc("2-2-0") \
.receive(ForwardedNPDU).doc("2-2-1") \
.receive(OriginalUnicastNPDU).doc("2-2-2") \
.timeout(3).doc("2-2-3") \
.success()
# run the group
tnet.run()
def test_14_2_1_2(self):
"""14.2.1.1 Execute Forwarded-NPDU (Two-hop Distribution)."""
if _debug: TestBBMD._debug("test_14_2_1_2")
# create a network
tnet = TNetwork(2)
# implementation under test
iut = BIPBBMDApplication("192.168.1.2/24", tnet.vlan[0])
if _debug: TestBBMD._debug(" - iut.bip: %r", iut.bip)
# BBMD on net 2
bbmd1 = BIPBBMDNode("192.168.2.2/24", tnet.vlan[1])
# add the IUT as a two-hop peer
bbmd1.bip.add_peer(Address("192.168.1.2/32"))
if _debug: TestBBMD._debug(" - bbmd1.bip: %r", bbmd1.bip)
# test device
td = BIPSimpleApplicationLayerStateMachine("192.168.2.3/24", tnet.vlan[1])
tnet.append(td)
# listener looks for extra traffic
listener = BIPStateMachine("192.168.1.3/24", tnet.vlan[0])
listener.mux.node.promiscuous = True
tnet.append(listener)
# broadcast a forwarded NPDU
td.start_state.doc("2-3-0") \
.send(WhoIsRequest(destination=LocalBroadcast())).doc("2-3-1") \
.receive(IAmRequest).doc("2-3-2") \
.success()
# listen for the forwarded NPDU, then the re-braodcast on the local LAN
# then the original unicast going back, then fail if there's anything else
listener.start_state.doc("2-4-0") \
.receive(ForwardedNPDU).doc("2-4-1") \
.receive(ForwardedNPDU).doc("2-4-2") \
.receive(OriginalUnicastNPDU).doc("2-4-3") \
.timeout(3).doc("2-4-4") \
.success()
# run the group
tnet.run()

View File

@ -12,12 +12,20 @@ from bacpypes.debugging import bacpypes_debugging, ModuleLogger, xtob
from bacpypes.pdu import Address, PDU, LocalBroadcast
from bacpypes.vlan import IPNetwork, IPRouter
from bacpypes.bvll import ReadForeignDeviceTable, ReadForeignDeviceTableAck
from bacpypes.bvll import (
Result, RegisterForeignDevice,
ReadForeignDeviceTable, ReadForeignDeviceTableAck,
DistributeBroadcastToNetwork, ForwardedNPDU,
OriginalUnicastNPDU, OriginalBroadcastNPDU,
)
from ..state_machine import StateMachineGroup
from ..state_machine import StateMachineGroup, TrafficLog
from ..time_machine import reset_time_machine, run_time_machine
from .helpers import SnifferNode, CodecNode, SimpleNode, ForeignNode, BBMDNode
from .helpers import (
SnifferStateMachine, BIPStateMachine,
BIPSimpleStateMachine, BIPForeignStateMachine, BIPBBMDStateMachine,
)
# some debugging
_debug = 0
@ -39,23 +47,28 @@ class TNetwork(StateMachineGroup):
reset_time_machine()
if _debug: TNetwork._debug(" - time machine reset")
# create a traffic log
self.traffic_log = TrafficLog()
# make a router
self.router = IPRouter()
# make a home LAN
self.home_vlan = IPNetwork()
self.router.add_network(Address("192.168.5.1/24"), self.home_vlan)
self.vlan_5 = IPNetwork("192.168.5.0/24")
self.vlan_5.traffic_log = self.traffic_log
self.router.add_network(Address("192.168.5.1/24"), self.vlan_5)
# make a remote LAN
self.remote_vlan = IPNetwork()
self.router.add_network(Address("192.168.6.1/24"), self.remote_vlan)
self.vlan_6 = IPNetwork("192.168.6.0/24")
self.vlan_6.traffic_log = self.traffic_log
self.router.add_network(Address("192.168.6.1/24"), self.vlan_6)
# the foreign device
self.fd = ForeignNode("192.168.6.2/24", self.remote_vlan)
self.fd = BIPForeignStateMachine("192.168.6.2/24", self.vlan_6)
self.append(self.fd)
# bbmd
self.bbmd = BBMDNode("192.168.5.3/24", self.home_vlan)
self.bbmd = BIPBBMDStateMachine("192.168.5.3/24", self.vlan_5)
self.append(self.bbmd)
def run(self, time_limit=60.0):
@ -70,6 +83,22 @@ class TNetwork(StateMachineGroup):
# check for success
all_success, some_failed = super(TNetwork, self).check_for_success()
if _debug:
TNetwork._debug(" - all_success, some_failed: %r, %r", all_success, some_failed)
for state_machine in self.state_machines:
if state_machine.running:
TNetwork._debug(" %r (running)", state_machine)
elif not state_machine.current_state:
TNetwork._debug(" %r (not started)", state_machine)
else:
TNetwork._debug(" %r", state_machine)
for direction, pdu in state_machine.transaction_log:
TNetwork._debug(" %s %s", direction, str(pdu))
# traffic log has what was processed on each vlan
self.traffic_log.dump(TNetwork._debug)
assert all_success
@ -97,58 +126,46 @@ class TestForeign(unittest.TestCase):
# create a network
tnet = TNetwork()
# add an addition codec node to the home vlan
cnode = CodecNode("192.168.5.2/24", tnet.home_vlan)
tnet.append(cnode)
# home sniffer node
home_sniffer = SnifferNode("192.168.5.254/24", tnet.home_vlan)
tnet.append(home_sniffer)
# remote sniffer node
remote_sniffer = SnifferNode("192.168.6.254/24", tnet.remote_vlan)
tnet.append(remote_sniffer)
# tell the B/IP layer of the foreign device to register
tnet.fd.start_state \
.call(tnet.fd.bip.register, tnet.bbmd.address, 30) \
.success()
# sniffer pieces
registration_request = xtob('81.05.0006' # bvlci
'001e' # time-to-live
)
registration_ack = xtob('81.00.0006.0000') # simple ack
# remote sniffer node
remote_sniffer = SnifferStateMachine("192.168.6.254/24", tnet.vlan_6)
tnet.append(remote_sniffer)
# remote sniffer sees registration
# sniffer traffic
remote_sniffer.start_state.doc("1-1-0") \
.receive(PDU, pduData=registration_request).doc("1-1-1") \
.receive(PDU, pduData=registration_ack).doc("1-1-2") \
.receive(RegisterForeignDevice).doc("1-1-1") \
.receive(Result).doc("1-1-2") \
.set_event('fd-registered').doc("1-1-3") \
.success()
# the bbmd is idle
tnet.bbmd.start_state.success()
# read the FDT
cnode.start_state.doc("1-2-0") \
# home snooper node
home_snooper = BIPStateMachine("192.168.5.2/24", tnet.vlan_5)
tnet.append(home_snooper)
# snooper will read the foreign device table
home_snooper.start_state.doc("1-2-0") \
.wait_event('fd-registered').doc("1-2-1") \
.send(ReadForeignDeviceTable(destination=tnet.bbmd.address)).doc("1-2-2") \
.receive(ReadForeignDeviceTableAck).doc("1-2-3") \
.success()
# the tnode reads the registration table
read_fdt_request = xtob('81.06.0004') # bvlci
read_fdt_ack = xtob('81.07.000e' # read-ack
'c0.a8.06.02.ba.c0 001e 0023' # address, ttl, remaining
)
# home sniffer node
home_sniffer = SnifferStateMachine("192.168.5.254/24", tnet.vlan_5)
tnet.append(home_sniffer)
# home sniffer sees registration
# sniffer traffic
home_sniffer.start_state.doc("1-3-0") \
.receive(PDU, pduData=registration_request).doc("1-3-1") \
.receive(PDU, pduData=registration_ack).doc("1-3-2") \
.receive(PDU, pduData=read_fdt_request).doc("1-3-3") \
.receive(PDU, pduData=read_fdt_ack).doc("1-3-4") \
.receive(RegisterForeignDevice).doc("1-3-1") \
.receive(Result).doc("1-3-2") \
.receive(ReadForeignDeviceTable).doc("1-3-3") \
.receive(ReadForeignDeviceTableAck).doc("1-3-4") \
.success()
# run the group
@ -170,21 +187,15 @@ class TestForeign(unittest.TestCase):
tnet.bbmd.start_state.success()
# remote sniffer node
remote_sniffer = SnifferNode("192.168.6.254/24", tnet.remote_vlan)
remote_sniffer = SnifferStateMachine("192.168.6.254/24", tnet.vlan_6)
tnet.append(remote_sniffer)
# sniffer pieces
registration_request = xtob('81.05.0006' # bvlci
'000a' # time-to-live
)
registration_ack = xtob('81.00.0006.0000') # simple ack
# remote sniffer sees registration
# sniffer traffic
remote_sniffer.start_state.doc("2-1-0") \
.receive(PDU, pduData=registration_request).doc("2-1-1") \
.receive(PDU, pduData=registration_ack).doc("2-1-2") \
.receive(PDU, pduData=registration_request).doc("2-1-3") \
.receive(PDU, pduData=registration_ack).doc("2-1-4") \
.receive(RegisterForeignDevice).doc("2-1-1") \
.receive(Result).doc("2-1-2") \
.receive(RegisterForeignDevice).doc("2-1-3") \
.receive(Result).doc("2-1-4") \
.success()
# run the group
@ -205,7 +216,7 @@ class TestForeign(unittest.TestCase):
# register, wait for ack, send some beef
tnet.fd.start_state.doc("3-1-0") \
.call(tnet.fd.bip.register, tnet.bbmd.address, 60).doc("3-1-1") \
.wait_event('fd-registered').doc("3-1-2") \
.wait_event('3-registered').doc("3-1-2") \
.send(pdu).doc("3-1-3") \
.success()
@ -215,24 +226,15 @@ class TestForeign(unittest.TestCase):
.success()
# remote sniffer node
remote_sniffer = SnifferNode("192.168.6.254/24", tnet.remote_vlan)
remote_sniffer = SnifferStateMachine("192.168.6.254/24", tnet.vlan_6)
tnet.append(remote_sniffer)
# sniffer pieces
registration_request = xtob('81.05.0006' # bvlci
'003c' # time-to-live (60)
)
registration_ack = xtob('81.00.0006.0000') # simple ack
unicast_pdu = xtob('81.0a.0008' # original unicast bvlci
'dead.beef' # PDU being unicast
)
# remote sniffer sees registration
# sniffer traffic
remote_sniffer.start_state.doc("3-2-0") \
.receive(PDU, pduData=registration_request).doc("3-2-1") \
.receive(PDU, pduData=registration_ack).doc("3-2-2") \
.set_event('fd-registered').doc("3-2-3") \
.receive(PDU, pduData=unicast_pdu).doc("3-2-4") \
.receive(RegisterForeignDevice).doc("3-2-1") \
.receive(Result).doc("3-2-2") \
.set_event('3-registered').doc("3-2-3") \
.receive(OriginalUnicastNPDU).doc("3-2-4") \
.success()
# run the group
@ -258,38 +260,29 @@ class TestForeign(unittest.TestCase):
.success()
# the bbmd is happy when it gets the pdu
tnet.bbmd.start_state \
.receive(PDU, pduSource=tnet.fd.address, pduData=pdu_data) \
.success()
# home sniffer node
home_node = SimpleNode("192.168.5.254/24", tnet.home_vlan)
tnet.append(home_node)
# home node happy when getting the pdu, broadcast by the bbmd
home_node.start_state.doc("4-2-0") \
tnet.bbmd.start_state.doc("4-2-0") \
.receive(PDU, pduSource=tnet.fd.address, pduData=pdu_data).doc("4-2-1") \
.success()
# home simple node
home_node = BIPSimpleStateMachine("192.168.5.254/24", tnet.vlan_5)
tnet.append(home_node)
# home node happy when getting the pdu, broadcast by the bbmd
home_node.start_state.doc("4-3-0") \
.receive(PDU, pduSource=tnet.fd.address, pduData=pdu_data).doc("4-3-1") \
.success()
# remote sniffer node
remote_sniffer = SnifferNode("192.168.6.254/24", tnet.remote_vlan)
remote_sniffer = SnifferStateMachine("192.168.6.254/24", tnet.vlan_6)
tnet.append(remote_sniffer)
# sniffer pieces
registration_request = xtob('81.05.0006' # bvlci
'003c' # time-to-live (60)
)
registration_ack = xtob('81.00.0006.0000') # simple ack
distribute_pdu = xtob('81.09.0008' # bvlci
'deadbeef' # PDU to broadcast
)
# remote sniffer sees registration
remote_sniffer.start_state.doc("4-3-0") \
.receive(PDU, pduData=registration_request).doc("4-3-1") \
.receive(PDU, pduData=registration_ack).doc("4-3-2") \
# remote traffic
remote_sniffer.start_state.doc("4-4-0") \
.receive(RegisterForeignDevice).doc("4-4-1") \
.receive(Result).doc("4-4-2") \
.set_event('4-registered') \
.receive(PDU, pduData=distribute_pdu).doc("4-3-3") \
.receive(DistributeBroadcastToNetwork).doc("4-4-3") \
.success()
# run the group

View File

@ -11,12 +11,15 @@ import unittest
from bacpypes.debugging import bacpypes_debugging, ModuleLogger, xtob
from bacpypes.pdu import PDU, LocalBroadcast
from bacpypes.bvll import OriginalUnicastNPDU, OriginalBroadcastNPDU
from bacpypes.vlan import IPNetwork
from ..state_machine import match_pdu, StateMachineGroup
from ..time_machine import reset_time_machine, run_time_machine
from .helpers import SnifferNode, SimpleNode
from .helpers import (
SnifferStateMachine, BIPSimpleStateMachine,
)
# some debugging
_debug = 0
@ -42,15 +45,15 @@ class TNetwork(StateMachineGroup):
self.vlan = IPNetwork()
# test device
self.td = SimpleNode("192.168.4.1/24", self.vlan)
self.td = BIPSimpleStateMachine("192.168.4.1/24", self.vlan)
self.append(self.td)
# implementation under test
self.iut = SimpleNode("192.168.4.2/24", self.vlan)
self.iut = BIPSimpleStateMachine("192.168.4.2/24", self.vlan)
self.append(self.iut)
# sniffer node
self.sniffer = SnifferNode("192.168.4.254/24", self.vlan)
self.sniffer = SnifferStateMachine("192.168.4.254/24", self.vlan)
self.append(self.sniffer)
@ -109,12 +112,10 @@ class TestSimple(unittest.TestCase):
tnet.iut.start_state.receive(PDU, pduSource=tnet.td.address).success()
# sniffer sees message on the wire
tnet.sniffer.start_state.receive(PDU,
tnet.sniffer.start_state.receive(OriginalUnicastNPDU,
pduSource=tnet.td.address.addrTuple,
pduDestination=tnet.iut.address.addrTuple,
pduData=xtob('81.0a.0008' # original unicast bvlci
'deadbeef' # PDU being unicast
),
pduData=pdu_data,
).timeout(1.0).success()
# run the group
@ -137,12 +138,10 @@ class TestSimple(unittest.TestCase):
tnet.iut.start_state.receive(PDU, pduSource=tnet.td.address).success()
# sniffer sees message on the wire
tnet.sniffer.start_state.receive(PDU,
pduSource=tnet.td.address.addrTuple,
pduDestination=('192.168.4.255', 47808),
pduData=xtob('81.0b.0008' # original broadcast bvlci
'deadbeef' # PDU being unicast
),
tnet.sniffer.start_state.receive(OriginalBroadcastNPDU,
pduSource=tnet.td.address.addrTuple,
# pduDestination=('192.168.4.255', 47808),
pduData=pdu_data,
).timeout(1.0).success()
# run the group

View File

@ -71,14 +71,14 @@ class NPDUCodec(Client, Server):
#
# SnifferNode
# SnifferStateMachine
#
@bacpypes_debugging
class SnifferNode(ClientStateMachine):
class SnifferStateMachine(ClientStateMachine):
def __init__(self, address, vlan):
if _debug: SnifferNode._debug("__init__ %r %r", address, vlan)
if _debug: SnifferStateMachine._debug("__init__ %r %r", address, vlan)
ClientStateMachine.__init__(self)
# save the name and address
@ -87,20 +87,20 @@ class SnifferNode(ClientStateMachine):
# create a promiscuous node, added to the network
self.node = Node(self.address, vlan, promiscuous=True)
if _debug: SnifferNode._debug(" - node: %r", self.node)
if _debug: SnifferStateMachine._debug(" - node: %r", self.node)
# bind this to the node
bind(self, self.node)
#
# NetworkLayerNode
# NetworkLayerStateMachine
#
@bacpypes_debugging
class NetworkLayerNode(ClientStateMachine):
class NetworkLayerStateMachine(ClientStateMachine):
def __init__(self, address, vlan):
if _debug: NetworkLayerNode._debug("__init__ %r %r", address, vlan)
if _debug: NetworkLayerStateMachine._debug("__init__ %r %r", address, vlan)
ClientStateMachine.__init__(self)
# save the name and address
@ -109,11 +109,11 @@ class NetworkLayerNode(ClientStateMachine):
# create a network layer encoder/decoder
self.codec = NPDUCodec()
if _debug: SnifferNode._debug(" - codec: %r", self.codec)
if _debug: SnifferStateMachine._debug(" - codec: %r", self.codec)
# create a node, added to the network
self.node = Node(self.address, vlan)
if _debug: SnifferNode._debug(" - node: %r", self.node)
if _debug: SnifferStateMachine._debug(" - node: %r", self.node)
# bind this to the node
bind(self, self.codec, self.node)
@ -158,14 +158,14 @@ class TestDeviceObject(LocalDeviceObject):
pass
#
# ApplicationLayerNode
# ApplicationLayerStateMachine
#
@bacpypes_debugging
class ApplicationLayerNode(ApplicationServiceElement, ClientStateMachine):
class ApplicationLayerStateMachine(ApplicationServiceElement, ClientStateMachine):
def __init__(self, address, vlan):
if _debug: ApplicationLayerNode._debug("__init__ %r %r", address, vlan)
if _debug: ApplicationLayerStateMachine._debug("__init__ %r %r", address, vlan)
# build a name, save the address
self.name = "app @ %s" % (address,)
@ -180,7 +180,7 @@ class ApplicationLayerNode(ApplicationServiceElement, ClientStateMachine):
# build an address and save it
self.address = Address(address)
if _debug: ApplicationLayerNode._debug(" - address: %r", self.address)
if _debug: ApplicationLayerStateMachine._debug(" - address: %r", self.address)
# continue with initialization
ApplicationServiceElement.__init__(self)
@ -209,17 +209,17 @@ class ApplicationLayerNode(ApplicationServiceElement, ClientStateMachine):
# create a node, added to the network
self.node = Node(self.address, vlan)
if _debug: ApplicationLayerNode._debug(" - node: %r", self.node)
if _debug: ApplicationLayerStateMachine._debug(" - node: %r", self.node)
# bind the stack to the local network
self.nsap.bind(self.node)
def indication(self, apdu):
if _debug: ApplicationLayerNode._debug("indication %r", apdu)
if _debug: ApplicationLayerStateMachine._debug("indication %r", apdu)
self.receive(apdu)
def confirmation(self, apdu):
if _debug: ApplicationLayerNode._debug("confirmation %r %r", apdu)
if _debug: ApplicationLayerStateMachine._debug("confirmation %r %r", apdu)
self.receive(apdu)
#

View File

@ -29,7 +29,7 @@ from bacpypes.npdu import (
from ..state_machine import match_pdu, StateMachineGroup
from ..time_machine import reset_time_machine, run_time_machine
from .helpers import SnifferNode, NetworkLayerNode, RouterNode
from .helpers import SnifferStateMachine, NetworkLayerStateMachine, RouterNode
# some debugging
_debug = 0
@ -58,11 +58,11 @@ class TNetwork(StateMachineGroup):
self.vlan1 = Network(name="vlan1", broadcast_address=LocalBroadcast())
# test device
self.td = NetworkLayerNode("1", self.vlan1)
self.td = NetworkLayerStateMachine("1", self.vlan1)
self.append(self.td)
# sniffer node
self.sniffer1 = SnifferNode("2", self.vlan1)
self.sniffer1 = SnifferStateMachine("2", self.vlan1)
self.append(self.sniffer1)
# add the network
@ -72,7 +72,7 @@ class TNetwork(StateMachineGroup):
self.vlan2 = Network(name="vlan2", broadcast_address=LocalBroadcast())
# sniffer node
self.sniffer2 = SnifferNode("4", self.vlan2)
self.sniffer2 = SnifferStateMachine("4", self.vlan2)
self.append(self.sniffer2)
# add the network
@ -82,7 +82,7 @@ class TNetwork(StateMachineGroup):
self.vlan3 = Network(name="vlan3", broadcast_address=LocalBroadcast())
# sniffer node
self.sniffer3 = SnifferNode("6", self.vlan3)
self.sniffer3 = SnifferStateMachine("6", self.vlan3)
self.append(self.sniffer3)
# add the network

View File

@ -30,7 +30,7 @@ from bacpypes.npdu import (
from ..state_machine import match_pdu, StateMachineGroup, TrafficLog
from ..time_machine import reset_time_machine, run_time_machine
from .helpers import SnifferNode, NetworkLayerNode, RouterNode
from .helpers import SnifferStateMachine, NetworkLayerStateMachine, RouterNode
# some debugging
_debug = 0
@ -64,11 +64,11 @@ class TNetwork(StateMachineGroup):
self.vlan1.traffic_log = self.traffic_log
# test device
self.td = NetworkLayerNode("1", self.vlan1)
self.td = NetworkLayerStateMachine("1", self.vlan1)
self.append(self.td)
# sniffer node
self.sniffer1 = SnifferNode("2", self.vlan1)
self.sniffer1 = SnifferStateMachine("2", self.vlan1)
self.append(self.sniffer1)
# connect vlan1 to iut1
@ -79,7 +79,7 @@ class TNetwork(StateMachineGroup):
self.vlan2.traffic_log = self.traffic_log
# sniffer node
self.sniffer2 = SnifferNode("4", self.vlan2)
self.sniffer2 = SnifferStateMachine("4", self.vlan2)
self.append(self.sniffer2)
# connect vlan2 to both routers
@ -91,7 +91,7 @@ class TNetwork(StateMachineGroup):
self.vlan3.traffic_log = self.traffic_log
# sniffer node
self.sniffer3 = SnifferNode("7", self.vlan3)
self.sniffer3 = SnifferStateMachine("7", self.vlan3)
self.append(self.sniffer3)
# connect vlan3 to the second router

View File

@ -38,7 +38,7 @@ from ..state_machine import match_pdu, StateMachineGroup
from ..time_machine import reset_time_machine, run_time_machine
from .helpers import (
SnifferNode, NetworkLayerNode, RouterNode, ApplicationLayerNode,
SnifferStateMachine, NetworkLayerStateMachine, RouterNode, ApplicationLayerStateMachine,
ApplicationNode,
)
@ -69,11 +69,11 @@ class TNetwork(StateMachineGroup):
self.vlan1 = Network(name="vlan1", broadcast_address=LocalBroadcast())
# test device
self.td = ApplicationLayerNode("1", self.vlan1)
self.td = ApplicationLayerStateMachine("1", self.vlan1)
self.append(self.td)
# sniffer node
self.sniffer1 = SnifferNode("2", self.vlan1)
self.sniffer1 = SnifferStateMachine("2", self.vlan1)
self.append(self.sniffer1)
# add the network
@ -86,7 +86,7 @@ class TNetwork(StateMachineGroup):
self.app2 = ApplicationNode("4", self.vlan2)
# sniffer node
self.sniffer2 = SnifferNode("5", self.vlan2)
self.sniffer2 = SnifferStateMachine("5", self.vlan2)
self.append(self.sniffer2)
# add the network

View File

@ -346,6 +346,30 @@ class TestRouter(unittest.TestCase):
csm_10_3.start_state.timeout(1).success()
csm_20_2.start_state.timeout(1).success()
def test_local_broadcast(self):
"""Test that a node can send a message to all of the other nodes on
the same network.
"""
if _debug: TestRouter._debug("test_local_broadcast")
# unpack the state machines
csm_10_2, csm_10_3, csm_20_2, csm_20_3 = self.smg.state_machines
# make a broadcast PDU from network 10 node 1
pdu = PDU(b'data',
source=('192.168.10.2', 47808),
destination=('192.168.10.255', 47808),
)
if _debug: TestVLAN._debug(" - pdu: %r", pdu)
# node 10-2 sends the pdu, node 10-3 gets pdu, nodes 20-2 and 20-3 dont
csm_10_2.start_state.send(pdu).success()
csm_10_3.start_state.receive(PDU,
pduSource=('192.168.10.2', 47808),
).success()
csm_20_2.start_state.timeout(1).success()
csm_20_3.start_state.timeout(1).success()
def test_remote_broadcast(self):
"""Test that a node can send a message to all of the other nodes on
a different network.