Skip to content

Commit

Permalink
retrying_create_datagram_endpoint feature
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelBender committed Jan 20, 2024
1 parent b7d79a4 commit 05be6fa
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 18 deletions.
2 changes: 1 addition & 1 deletion bacpypes3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# Project Metadata
#

__version__ = "0.0.87"
__version__ = "0.0.88"
__author__ = "Joel Bender"
__email__ = "joel@carrickbender.com"

Expand Down
36 changes: 25 additions & 11 deletions bacpypes3/ipv4/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
_debug = 0
_log = ModuleLogger(globals())

# move this to settings sometime
BACPYPES_ENDPOINT_RETRY_INTERVAL = 1.0


@bacpypes_debugging
class IPv4DatagramProtocol(asyncio.DatagramProtocol):

_debug: Callable[..., None]

server: "IPv4DatagramServer"
Expand Down Expand Up @@ -62,7 +64,6 @@ def connection_lost(self, exc: Optional[Exception]) -> None:

@bacpypes_debugging
class IPv4DatagramServer(Server[PDU]):

_debug: Callable[..., None]
_exception: Callable[..., None]
_transport_tasks: List[Any]
Expand Down Expand Up @@ -98,11 +99,7 @@ def __init__(

# easy call to create a local endpoint
local_endpoint_task = loop.create_task(
loop.create_datagram_endpoint(
IPv4DatagramProtocol,
local_addr=address.addrTuple,
allow_broadcast=True,
)
self.retrying_create_datagram_endpoint(loop, address.addrTuple)
)
if _debug:
IPv4DatagramServer._debug(
Expand Down Expand Up @@ -130,10 +127,8 @@ def __init__(
# Windows takes care of the broadcast, but Linux needs a broadcast endpoint
if "nt" not in os.name:
broadcast_endpoint_task = loop.create_task(
loop.create_datagram_endpoint(
IPv4DatagramProtocol,
local_addr=address.addrBroadcastTuple,
allow_broadcast=True,
self.retrying_create_datagram_endpoint(
loop, address.addrBroadcastTuple
)
)
if _debug:
Expand All @@ -145,6 +140,25 @@ def __init__(
)
self._transport_tasks.append(broadcast_endpoint_task)

async def retrying_create_datagram_endpoint(
self, loop: asyncio.events.AbstractEventLoop, addrTuple: Tuple[str, int]
):
"""
Repeat attempts to create datagram endpoint, sometimes during boot
the interface isn't ready. Contributed by PretentiousPotatoPeeler.
"""
while True:
try:
return await loop.create_datagram_endpoint(
IPv4DatagramProtocol, local_addr=addrTuple, allow_broadcast=True
)
except OSError:
if _debug:
IPv4DatagramServer._debug(
" - Could not create datagram endpoint, retrying..."
)
await asyncio.sleep(BACPYPES_ENDPOINT_RETRY_INTERVAL)

def set_local_transport_protocol(self, address, task):
if _debug:
IPv4DatagramServer._debug(
Expand Down
26 changes: 20 additions & 6 deletions bacpypes3/ipv6/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
_debug = 0
_log = ModuleLogger(globals())

# move this to settings sometime
BACPYPES_ENDPOINT_RETRY_INTERVAL = 1.0


@bacpypes_debugging
class IPv6DatagramProtocol(asyncio.DatagramProtocol):

_debug: Callable[..., None]

server: "IPv6DatagramServer"
Expand All @@ -48,7 +50,6 @@ def connection_lost(self, exc: Optional[Exception]) -> None:

@bacpypes_debugging
class IPv6DatagramServer(Server[PDU]):

_debug: Callable[..., None]
_exception: Callable[..., None]
_transport_tasks: List[Any]
Expand Down Expand Up @@ -101,10 +102,7 @@ def __init__(

# easy call to create a local endpoint
local_endpoint_task = loop.create_task(
loop.create_datagram_endpoint(
IPv6DatagramProtocol,
sock=local_socket,
)
self.retrying_create_datagram_endpoint(loop, local_socket)
)
if _debug:
IPv6DatagramServer._debug(
Expand All @@ -117,6 +115,22 @@ def __init__(
# keep a list of things that need to complete before sending stuff
self._transport_tasks = [local_endpoint_task]

async def retrying_create_datagram_endpoint(
self, loop: asyncio.events.AbstractEventLoop, local_socket: socket.socket
):
while True:
try:
return await loop.create_datagram_endpoint(
IPv6DatagramProtocol,
sock=local_socket,
)
except OSError:
if _debug:
IPv6DatagramServer._debug(
" - Could not create datagram endpoint, retrying..."
)
await asyncio.sleep(BACPYPES_ENDPOINT_RETRY_INTERVAL)

def set_local_transport_protocol(self, address, task):
if _debug:
IPv6DatagramServer._debug(
Expand Down

0 comments on commit 05be6fa

Please sign in to comment.