pymodbus-dev / pymodbus

A full modbus protocol written in python
Other
2.22k stars 907 forks source link

Enhancement: Listen on any address IPv4 and IPv6 #1915

Closed couling closed 6 months ago

couling commented 8 months ago

Versions

Pymodbus Specific

Description

The default bind address (local address) for the modbus server listens on any IPv4 address but offers no way to listen on simply any address. I noticed this when I was working on #1914.

Python does offer some ability to listen on any address, but it relies on having two listening sockets which could be complex to implement. I'm raising this as an enhancement request since the workaround might be just to run two servers side by side. But both for listening to any address and listening to localhost, it would be better if the default was dual stack.

There's a risk this will be more complex to weave into the code as it may require embedding mutliple sockets in places where there were only one previously. Despite some operating systems supporting sockets that can listen for both this doesn't seem to be ubiquotous or reccomended. This may require swapping a recvmsg or accept for a select.

janiversen commented 8 months ago

A modbus server emulates a physical device which listens on one interface.

Many devices can listen on either ipv6 or ipv4 but I do not know devices that listens on multiple interfaces so this is a feature outside the current scope of the server.

As mentioned a simple solution is to start multiple servers.

janiversen commented 8 months ago

for ipv4 it is allowed to use (0.0.0.0) to listen on multiple ipv4 interfaces as if all ipv4 interfaces were one, but there are no (as far as I know) single value for source_address that allows 1 listener for both ipv6 and ipv4 and thus it is outside the current definition.

I personally see 2 listeners as complicating the code for no good reason, but I am as always open to suggestions.

couling commented 8 months ago

A modbus server emulates a physical device which listens on one interface.

Many devices can listen on either ipv6 or ipv4 but I do not know devices that listens on multiple interfaces so this is a feature outside the current scope of the server.

Just to be clear, this is not about listening on multiple interfaces, just dual stack listening. I wouldn't ask to able to bind to a list of addresses for example. This feature request is really about avoiding adding artificial limitations over the top of underlying python API for creating server sockets.

On supported operating systems (on most I could name), listening to an AF_INET6 family socket bound to address :: with IPV6_V6ONLY set false, it will receive connections from both.

However I've picked up hints that there is a gradual move away from this approach, an hints that IPV6_V6ONLY may be turned on by default for some linux distributions. I've not read enough yet to offer an opinion on the use of non IPV6_V6ONLY sockets.

The mention of multiple listening sockets comes from reading about asyncio.loop.create_server with a None host. Again, I've not had time to investigate much deeper and I don't fully know how this would look in both a sync and async context.

If I get time, I'll draft a PR or two so you can assess the real complexity it might add. But it's likely to be a few months before I have the time to get to it.

janiversen commented 8 months ago

PR are welcome.

github-actions[bot] commented 6 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

janiversen commented 6 months ago

Closing due to lack of activity.