Skip to content

Commit 71ea7e4

Browse files
authored
Move create_server to serve_forever(). (#889)
1 parent da0d42c commit 71ea7e4

File tree

3 files changed

+341
-493
lines changed

3 files changed

+341
-493
lines changed

pymodbus/server/async_io.py

Lines changed: 46 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ def _log_exception(self):
6161
_logger.error(
6262
"Handler for serial port has been cancelled")
6363
else:
64-
sock_name = self.protocol._sock.getsockname() # pylint: disable=protected-access,no-member
64+
if hasattr(self, "protocol"):
65+
sock_name = self.protocol._sock.getsockname() # pylint: disable=protected-access
66+
else:
67+
sock_name = "No socket"
6568
txt = f"Handler for UDP socket [{sock_name[1]}] has been canceled"
6669
_logger.error(txt)
6770

@@ -141,7 +144,6 @@ async def handle(self): # NOSONAR
141144
142145
For ModbusDisconnectedRequestHandler, a single handle() coroutine will
143146
be started and maintained. Calling server_close will cancel that task.
144-
145147
"""
146148
reset_frame = False
147149
while self.running:
@@ -477,19 +479,21 @@ def __init__(self, # pylint: disable=too-many-arguments
477479
# constructors cannot be declared async, so we have to
478480
# defer the initialization of the server
479481
self.server = None
480-
self.server_factory = self.loop.create_server(
481-
lambda: self.handler(self),
482-
*self.address,
483-
reuse_address=allow_reuse_address,
484-
reuse_port=allow_reuse_port,
485-
backlog=backlog,
486-
start_serving=not defer_start
487-
)
482+
self.factory_parms = {
483+
"reuse_address": allow_reuse_address,
484+
"reuse_port": allow_reuse_port,
485+
"backlog": backlog,
486+
"start_serving": not defer_start,
487+
}
488488

489489
async def serve_forever(self):
490490
"""Start endless loop."""
491491
if self.server is None:
492-
self.server = await self.server_factory
492+
self.server = await self.loop.create_server(
493+
lambda: self.handler(self),
494+
*self.address,
495+
**self.factory_parms,
496+
)
493497
self.serving.set_result(True)
494498
await self.server.serve_forever()
495499
else:
@@ -503,18 +507,19 @@ def server_close(self):
503507
_logger.warning(txt)
504508
v_item.handler_task.cancel()
505509
self.active_connections = {}
506-
self.server.close()
510+
if self.server is not None:
511+
self.server.close()
507512

508513

509-
class ModbusTlsServer(ModbusTcpServer): # pylint: disable=too-many-instance-attributes
514+
class ModbusTlsServer(ModbusTcpServer):
510515
"""A modbus threaded tls socket server.
511516
512517
We inherit and overload the socket server so that we
513518
can control the client threads as well as have a single
514519
server context instance.
515520
"""
516521

517-
def __init__(self, # NOSONAR pylint: disable=too-many-arguments,super-init-not-called
522+
def __init__(self, # NOSONAR pylint: disable=too-many-arguments
518523
context,
519524
framer=None,
520525
identity=None,
@@ -565,43 +570,22 @@ def __init__(self, # NOSONAR pylint: disable=too-many-arguments,super-init-not-
565570
:param response_manipulator: Callback method for
566571
manipulating the response
567572
"""
568-
self.active_connections = {}
569-
self.loop = loop or asyncio.get_event_loop()
570-
self.allow_reuse_address = allow_reuse_address
571-
self.decoder = ServerDecoder()
572-
self.framer = framer or ModbusTlsFramer
573-
self.address = address or ("", Defaults.Port)
574-
self.handler = handler or ModbusConnectedRequestHandler
575-
self.handler.server = self
576-
self.ignore_missing_slaves = kwargs.get('ignore_missing_slaves',
577-
Defaults.IgnoreMissingSlaves)
578-
self.broadcast_enable = kwargs.get('broadcast_enable',
579-
Defaults.broadcast_enable)
580-
self.response_manipulator = kwargs.get("response_manipulator", None)
581-
self.context = context or ModbusServerContext()
582-
self.control = ModbusControlBlock()
583-
584-
if isinstance(identity, ModbusDeviceIdentification):
585-
self.control.Identity.update(identity)
586-
587-
self.sslctx = sslctx_provider(sslctx, certfile, keyfile, password,
588-
reqclicert)
589-
590-
# asyncio future that will be done once server has started
591-
self.serving = self.loop.create_future()
592-
# constructors cannot be declared async, so we have to
593-
# defer the initialization of the server
594-
self.server = None
595-
# start_serving is new in version 3.7
596-
self.server_factory = self.loop.create_server(
597-
lambda: self.handler(self),
598-
*self.address,
599-
ssl=self.sslctx,
600-
reuse_address=allow_reuse_address,
601-
reuse_port=allow_reuse_port,
573+
super().__init__(
574+
context,
575+
framer=framer,
576+
identity=identity,
577+
address=address,
578+
handler=handler,
579+
allow_reuse_address=allow_reuse_address,
580+
allow_reuse_port=allow_reuse_port,
581+
defer_start=defer_start,
602582
backlog=backlog,
603-
start_serving=not defer_start
583+
loop=loop,
584+
**kwargs,
604585
)
586+
self.sslctx = sslctx_provider(sslctx, certfile, keyfile, password,
587+
reqclicert)
588+
self.factory_parms["ssl"] = self.sslctx
605589

606590

607591
class ModbusUdpServer: # pylint: disable=too-many-instance-attributes
@@ -659,18 +643,20 @@ def __init__(self, context, framer=None, identity=None, address=None, # pylint:
659643
self.stop_serving = self.loop.create_future()
660644
# asyncio future that will be done once server has started
661645
self.serving = self.loop.create_future()
662-
self.server_factory = self.loop.create_datagram_endpoint(
663-
lambda: self.handler(self),
664-
local_addr=self.address,
665-
reuse_address=allow_reuse_address,
666-
reuse_port=allow_reuse_port,
667-
allow_broadcast=True
668-
)
646+
self.factory_parms = {
647+
"local_addr": self.address,
648+
"reuse_address": allow_reuse_address,
649+
"reuse_port": allow_reuse_port,
650+
"allow_broadcast": True,
651+
}
669652

670653
async def serve_forever(self):
671654
"""Start endless loop."""
672655
if self.protocol is None:
673-
self.protocol, self.endpoint = await self.server_factory
656+
self.protocol, self.endpoint = await self.loop.create_datagram_endpoint(
657+
lambda: self.handler(self),
658+
**self.factory_parms,
659+
)
674660
self.serving.set_result(True)
675661
await self.stop_serving
676662
else:
@@ -680,10 +666,10 @@ async def serve_forever(self):
680666
def server_close(self):
681667
"""Close server."""
682668
self.stop_serving.set_result(True)
683-
if self.endpoint.handler_task is not None:
669+
if self.endpoint is not None and self.endpoint.handler_task is not None:
684670
self.endpoint.handler_task.cancel()
685-
686-
self.protocol.close()
671+
if self.protocol is not None:
672+
self.protocol.close()
687673

688674

689675
class ModbusSerialServer: # pylint: disable=too-many-instance-attributes

0 commit comments

Comments
 (0)