Skip to content

Handle reconnection for godot-socketio#7

Open
garciaf wants to merge 6 commits into
msabaeian:mainfrom
garciaf:feature/improvment
Open

Handle reconnection for godot-socketio#7
garciaf wants to merge 6 commits into
msabaeian:mainfrom
garciaf:feature/improvment

Conversation

@garciaf

@garciaf garciaf commented Apr 5, 2026

Copy link
Copy Markdown

Bug fixes

_on_noop() treated NOOP as an error

NOOP is a normal Engine.IO packet sent during polling to unblock a long-poll request. The handler was calling push_error(). It now calls _poll(), matching the behaviour of _on_message().

disconnect_socket() emitted socket_disconnected twice

disconnect_socket() called engine_close() which already emits engine_connection_closed_on_engine_io_connection_closed()socket_disconnected. The duplicate direct socket_disconnected.emit() at the end of disconnect_socket() was removed.

Upgrade PONG and heartbeat PONG not distinguished

_on_pong() was unconditionally triggering the WebSocket upgrade flow. It now receives the raw payload and only upgrades when the payload is "probe", correctly ignoring plain heartbeat PONGs from the server.

State and TransportType enum type annotation error

In Godot 4, inner enums on a class_name class cause a type mismatch between the unqualified (State) and fully qualified (EngineIO.State) names when used as type annotations. Removed the explicit type annotations on state and _transport_type, letting GDScript infer them from their initialisers.

Client-initiated PINGs broke Engine.IO v4

In Engine.IO v4 only the server sends PINGs — client-initiated PINGs are v3 behaviour and cause the server to disconnect with transport error. A heartbeat timer that was sending unsolicited PINGs on pingInterval has been removed. The existing _on_ping() → PONG response path is sufficient for keepalive.


New feature: automatic reconnection

When the WebSocket closes unexpectedly, the client now attempts to reconnect automatically with linear backoff instead of immediately calling engine_close().

Three new exported variables are exposed in the Inspector:

Variable Default Description
auto_reconnect true Enable/disable automatic reconnection
max_reconnect_attempts 5 Give up after this many attempts
reconnect_base_delay 1.0 Delay multiplied by attempt count (1 s, 2 s, 3 s…)

A new signal reconnect_attempt(attempt: int, max: int) is emitted on each retry so the game UI can show feedback like "Reconnecting 2/5…".

On a successful reconnection _reconnect_attempts resets to 0 at both success paths (polling in _on_open, WebSocket in _on_pong). If all attempts are exhausted, engine_close() is called normally and engine_connection_closed fires once.

- Implement reconnect logic
- Handle _on_noop
@garciaf garciaf changed the title [FEATURE] Implement reconnect and noop handler ## Bug fixes and reconnection for godot-socketio Apr 5, 2026
@garciaf
garciaf marked this pull request as ready for review April 5, 2026 06:22
@garciaf garciaf changed the title ## Bug fixes and reconnection for godot-socketio Handle reconnection for godot-socketio Apr 5, 2026
@garciaf

garciaf commented Apr 6, 2026

Copy link
Copy Markdown
Author

Thanks again for this amazing addon @msabaeian, thanks to you, I could make my card game so much more reliable.
It worked like a charm.

If this PR makes sense to you, I am really happy to contribute; otherwise, I will remain on the fork I have.

Thanks again for taking care of such a complicated problem

[FEATURE] Implement reconnect and noop handler
@msabaeian

Copy link
Copy Markdown
Owner

Hey @garciaf! thanks for your work! I’ll review this in the coming week and if everything looks good, merge it.
sorry for the late response I kinda lost track of this repo

@msabaeian
msabaeian self-requested a review April 16, 2026 12:04
@garciaf

garciaf commented Apr 20, 2026

Copy link
Copy Markdown
Author

All good @msabaeian if you want to review it in the game I am working on, I can give you further access to the prototype I have.

But basically, I use this plugin to allow people to play the Godot game on their phone (With a web browser).

And Socket IO is so much more reliable than Websocket. Your work is incredible.
Also, I fixed a small typo in this PR to allow working with Godot 4.6

@msabaeian msabaeian left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for your effort, i've some question and suggestions

Comment thread addons/godot-socketio/engineio.gd Outdated
Comment thread addons/godot-socketio/engineio.gd Outdated
Comment thread addons/godot-socketio/engineio.gd Outdated
Comment thread addons/godot-socketio/engineio.gd Outdated
Comment thread addons/godot-socketio/engineio.gd Outdated
Comment thread addons/godot-socketio/socketio.gd
Comment thread addons/godot-socketio/engineio.gd
@garciaf

garciaf commented May 4, 2026

Copy link
Copy Markdown
Author

@msabaeian thank you so much for looking into it, and very good comment. I will fix it and push it.

We might also consider changing the Readme afterward.

var t := Timer.new()
t.wait_time = reconnect_base_delay_seconds * _reconnect_attempts
t.one_shot = true
t.timeout.connect(_emit_reconnection_attempted)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@msabaeian does the emit event work when it is done this way?

I did not want to change the other method engine_make_connection to avoid having this event emitted for other reason.

@garciaf

garciaf commented May 14, 2026

Copy link
Copy Markdown
Author

@msabaeian thanks for your patience with your comment and feedbacks.

I took care of all comments and did my best to answer the questions to the best of my abilities. I tested this version on my game; nothing to report so far.

Hope that would work for you

@garciaf
garciaf requested a review from msabaeian May 14, 2026 10:38
@msabaeian

Copy link
Copy Markdown
Owner

The code looks good to me, I need to run a test on my system then merge, thanks for your effort!
Bdw I would be happy to test your game as well, send me the link if possible

@msabaeian

Copy link
Copy Markdown
Owner

Hi @garciaf I tested this on Godot and unfortunately it does not work for me, my steps are:

  • start socket.js
  • run godot example
  • press on "Connect to server", it connects successfully
  • terminate socket.js for 2-3 seconds
  • start socket.js again but godot does not re-connect
    I can see godot example attempts to connect to server only once, it seems its because of setting _transport_type to TransportType.POLLING inside _clear_values, could you please test this on your side and let me know?

@garciaf

garciaf commented Jun 18, 2026

Copy link
Copy Markdown
Author

@msabaeian very good catch. I also used the opportunity to give some explanation on how to test in the README.If you want, I could put this part in a different place. But I think it would be useful to have a small guide on how to test your development yourself

I made the fix. Maybe you have a different setup for testing your addon; if that's the case, feel free to correct the assumption I made in the README.md

I tested the scenario you found, and it works now with the change

@msabaeian

Copy link
Copy Markdown
Owner

@garciaf could you please mention your test steps and maybe attach a video of it? i tested again and it's not working still

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

Successfully merging this pull request may close these issues.

2 participants