Describe the bug
The pure-Python server logs an error when a client disconnects normally. Using the library's own client:
client = snap7.client.Client()
client.connect("127.0.0.1", 0, 0, 11102)
client.db_read(1, 0, 4)
client.disconnect()
ERROR Error handling client ('127.0.0.1', 58143): Expected COTP DT, got 0x80
0x80 is COTP_DR, defined in snap7/connection.py — Client.disconnect() calls _send_cotp_disconnect(), which sends it. ServerISOConnection.receive_data() accepts only COTP_DT and raises S7ConnectionError for anything else, so the disconnect reaches the general handler in _handle_client() and is logged at error level. COTP_DR and COTP_DC are defined in the server too, but nothing on the receiving side uses them.
A second case: a peer that goes away before the ISO handshake finishes — a port scan, a health check, a cancelled connect — is logged by accept_connection() as Error accepting ISO connection: Connection closed by peer.
To Reproduce
Start a server, then leave in each of these ways, watching the log:
| how the client leaves |
logged as |
Client.disconnect() after a request |
ERROR Expected COTP DT, got 0x80 |
Client.disconnect() without a request |
ERROR Expected COTP DT, got 0x80 |
| plain TCP close, no ISO handshake |
ERROR Error accepting ISO connection |
| abrupt reset |
ERROR Error accepting ISO connection |
Expected behavior
A disconnect request is how a client is supposed to say goodbye, so it should end the connection normally: confirm it with a COTP_DC and take the path _handle_client() already has for ConnectionResetError, which logs Client ... disconnected at info. A peer leaving before the handshake completes is routine and does not need error level either.
Anyone monitoring these servers currently sees an error for every clean disconnect, which buries the errors that matter.
Environment
python-snap7 master (8838aa9), Python 3.14, macOS. Reproduced against the pure-Python server with the library's own client and with a raw socket.
I have a fix with tests if it is wanted.
Describe the bug
The pure-Python server logs an error when a client disconnects normally. Using the library's own client:
0x80isCOTP_DR, defined insnap7/connection.py—Client.disconnect()calls_send_cotp_disconnect(), which sends it.ServerISOConnection.receive_data()accepts onlyCOTP_DTand raisesS7ConnectionErrorfor anything else, so the disconnect reaches the general handler in_handle_client()and is logged at error level.COTP_DRandCOTP_DCare defined in the server too, but nothing on the receiving side uses them.A second case: a peer that goes away before the ISO handshake finishes — a port scan, a health check, a cancelled connect — is logged by
accept_connection()asError accepting ISO connection: Connection closed by peer.To Reproduce
Start a server, then leave in each of these ways, watching the log:
Client.disconnect()after a requestERROR Expected COTP DT, got 0x80Client.disconnect()without a requestERROR Expected COTP DT, got 0x80ERROR Error accepting ISO connectionERROR Error accepting ISO connectionExpected behavior
A disconnect request is how a client is supposed to say goodbye, so it should end the connection normally: confirm it with a
COTP_DCand take the path_handle_client()already has forConnectionResetError, which logsClient ... disconnectedat info. A peer leaving before the handshake completes is routine and does not need error level either.Anyone monitoring these servers currently sees an error for every clean disconnect, which buries the errors that matter.
Environment
python-snap7 master (8838aa9), Python 3.14, macOS. Reproduced against the pure-Python server with the library's own client and with a raw socket.
I have a fix with tests if it is wanted.