Skip to content

Pure-Python server logs a normal client disconnect as an error #846

Description

@Poseidonas

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.pyClient.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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions