Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client connection closed immediately on re-connection after ping timeout #495

Open
MichelJansson opened this issue Nov 29, 2023 · 1 comment

Comments

@MichelJansson
Copy link

Description

Hi, thanks for this package!

I'm running on 11.4.4 as a client on windows and have configured a short ping/heartbeat interval (1s) to combat the issue where a close event is not emitted when the remote server is terminated and does not send a close message (there exist multiple issues for that, so I won't go deeper into it here).

The issue I'm seeing now instead is that the connection gets closed immediately on re-connection after the connection was closed due to ping time-out.

Ie.:

  • Start
  • Connection open
  • (remote server killed etc)
  • Ping timeout
  • Connection closed
  • (remote server restarted etc)
  • Automatic reconnection...
  • Connection open
  • Connection closed !
  • Automatic reconnection...
  • Connection open

Root cause

I've after some time managed to track down the root cause of this:

When the ping times out, the connection is closed via the close method here, which in turn sends a close frame here, which of course fails since the server is stopped which is why we wanted to close the connection in the first place.

And here lies the problem; When the send fails here the close frame is never removed from the send buffer.

Later when the server comes back online and we reconnect the first thing that gets sent to the server is the close frame that still lies in the txbuffer, which it of course listens to and sends us back a close frame that we listen to and close the connection again.

Expected behavior

I'm not sure what the most appropriate remedy for this would be, but the first thing that comes to mind is to clear the send buffer when the connection is closed. But there is probably a case where re-transmission is desired when the connection is established again, so a better solution perhaps is to only clear it when transmission fails while in CLOSING state or something.

For now I made an own vcpkg port that adds a public clearSendBuffer() method that I call when receiving a close event that is due ping timeout.

// Setup a callback to be fired when a message or an event (open, close, error) is received
m_websocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg)
    {
        if (msg->type == ix::WebSocketMessageType::Close)
        {
            if (msg->closeInfo.code == 1011) // Closed due to ping timeout
            {
                // Hack to clear the TX buffer that is not cleared when closing due ping timeout.
                m_websocket.clearSendBuffer();
            }
        }
    });

Any other ideas? I'd be happy to create a PR..

Thanks!

@bsergean
Copy link
Collaborator

Thanks for the detailed bug report. If you want to make a PR to add your clearSendBuffer I'll gladly review it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants