Binary eio v3 + Engine IO v3, v4 Interop JS integration tests - #228
Binary eio v3 + Engine IO v3, v4 Interop JS integration tests#228sanjomo wants to merge 68 commits into
Conversation
Add correct Engine.IO version handling and robust binary framing support across transports. Introduce Packet.withEngineIOVersion to avoid mutating shared Packet instances during broadcasts; update Namespace, SingleRoomBroadcastOperations, EncoderHandler, PacketEncoder and PacketDecoder to emit/parse EIOv2/v3 polling wrappers, EIOv3 'b4' base64 text, WebSocket prefixes (0x04) and EIOv4 text/plain behavior. Enhance packet decoding with transport-aware logic and multi-packet separator handling. Enable safe polymorphic Jackson typing in Kafka/Hazelcast/NATS serializers/deserializers. Add many integration tests and JS interop fixtures (js-interop resources, test clients), update test containers/configs (Hazelcast image/xsd, Kafka consumer group/offsets), improve logging and example to show Hazelcast-backed clustering. Update .gitignore and bump dependencies in examples/pom.xml.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR adds Engine.IO v2–v4 transport-aware packet processing, per-client packet isolation, shared event serialization, JavaScript and distributed integration tests, CI Node.js setup, Hazelcast updates, and a clustered Hazelcast-backed example. ChangesProtocol and serialization
Interoperability and tests
Build and example
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Add missing listener removals (ClientListeners/Namespace/SocketIOServer). Harden EncoderHandler/PacketDecoder parsing for Engine.IO polling: skip leading 0x1E delimiters, validate legacy length-prefixed polling wrappers, guard against unknown EngineIOVersion and use safe equals checks. Change PacketEncoder to emit 0x1E only for EIOv4 and use standard Base64 for EIOv4 polling attachments so browser clients decode '+' and '/'. Tweak EventMessageJsonSupport ObjectMapper to avoid empty-bean failures and related types. Add and update integration/unit tests and JS test client scenarios. Update test hazelcast container image and example pom dependency. Several test cleanup/logging robustness fixes.
Adjust polling encoding and HTTP headers to correctly support Engine.IO v4. EncoderHandler now selects text/plain for v4 polling (and for non-binary payloads), and PacketEncoder was rewritten to handle EIO v4 multi-packet polling (0x1E delimiter) with STANDARD Base64 for attachments, while preserving v2/v3 binary envelope behavior. Buffer handling, length-prefixing and resource releases were improved and unsupported versions now throw. Unit tests updated to reflect v4/v3 differences, JSONP behavior, and use StandardCharsets.
PacketDecoder: treat PONG like PING (read text payload), fix polling length-header digit validation, and add explicit ERROR body parsing with JSON fallback. Tests: significantly expand PacketDecoderTest and PacketEncoderTest to cover Engine.IO V2/V3/V4, binary attachments, XHR2 polling binary frames, ping/pong, ACKs and ERRORs. Integration tests and JS interop fixtures updated to improve distributed room/isolation/leave checks and to fail/pass cleanly; added connect/event presence assertions in JsClientInteropTest. Minor test whitespace cleanup. These changes improve protocol compatibility and increase test coverage for binary and cross-version behaviors.
Suppress XREAD error noise during shutdown in RedisStreamEventStore by checking the running flag and detecting Redisson shutdown (exception type/cause/message). Add a suite of robustness and edge-case unit tests: WrongUrlHandlerTest, ByteBufLeakTest (Netty PARANOID leak detection), PacketDecoderFuzzingTest, SocketSslServerRestartTest (rapid restarts), WebSocketTransportTest (binary frame + mocks), HttpTransportTest (polling headers), MemoryStoreTest (session expunge), and NamespaceTest (concurrent room joins). Also adjust test helpers/mocks where needed.
Remove an unused JsonTypeInfo import from Packet.java. Rework PacketDecoder branching for polling payloads: move the Base64 polling ('b') handling (and its separator-slicing logic) into the else-if branch and place the fallback binary polling payload in the final else branch. This clarifies control flow and ensures the polling attachment paths are handled correctly.
Use try-with-resources and finally to properly release ByteBuf/InputStream resources in PacketDecoder and PacketEncoder to prevent leaks and correctly handle JSONP framing. Add @OverRide annotations to PacketDecoderFuzzingTest lifecycle methods. Add Apache-2.0 license headers to JS test resource files. These changes improve resource safety and clarity without altering protocol behavior.
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Fixes Applied SuccessfullyFixed 2 file(s) based on 2 unresolved review comments. Files modified:
Commit: The changes have been pushed to the Time taken: |
Fixed 2 file(s) based on 2 unresolved review comments. Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
server always gets immutable copy of config so changing port have no effect
|
Note Docstrings generation - SUCCESS |
Docstrings generation was requested by @sanjomo. * #228 (comment) The following files were modified: * `netty-socketio-core/src/main/java/com/socketio4j/socketio/SingleRoomBroadcastOperations.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/handler/EncoderHandler.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/handler/InPacketHandler.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/listener/ClientListeners.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/namespace/Namespace.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/protocol/JacksonJsonSupport.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/protocol/Packet.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/protocol/PacketDecoder.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/protocol/PacketEncoder.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/store/event/EventMessageJsonSupport.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/store/hazelcast/HazelcastPubSubEventStore.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/store/kafka/serialization/EventMessageDeserializer.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/store/kafka/serialization/EventMessageSerializer.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/store/nats_pubsub/EventMessageCodec.java` * `netty-socketio-core/src/main/java/com/socketio4j/socketio/store/redis_stream/RedisStreamEventStore.java` * `netty-socketio-core/src/test/java/com/socketio4j/socketio/store/CustomizedHazelcastContainer.java` * `netty-socketio-examples/netty-socketio-core-example/src/main/java/com/socketio4j/example/core/CoreExampleMain.java`
| @AfterAll | ||
| static void stopKafka() { | ||
| TestResourceCleanup.runAll("Kafka test container cleanup", | ||
| () -> { if (KAFKA != null && KAFKA.isRunning()) KAFKA.close(); }); |
| @AfterAll | ||
| static void stopNats() { | ||
| TestResourceCleanup.runAll("NATS test container cleanup", | ||
| () -> { if (NATS_CONTAINER != null && NATS_CONTAINER.isRunning()) NATS_CONTAINER.stop(); }); |
| () -> { if (node2 != null) node2.stop(); }, | ||
| () -> { if (kafkaEventStore1 != null) kafkaEventStore1.shutdown(); }, | ||
| () -> { if (kafkaEventStore2 != null) kafkaEventStore2.shutdown(); }, | ||
| () -> { if (KAFKA != null && KAFKA.isRunning()) KAFKA.close(); }); |
| uses: ./.github/workflows/build.yml | ||
| with: | ||
| javaVersion: "21" | ||
| interopVersions: "full" | ||
|
|
||
| publish: |
| okWebSocket.send(ByteString.of(new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF})); | ||
|
|
||
| // 4. Send valid Engine.IO PING packet to verify server Netty pipeline is still healthy | ||
| CountDownLatch pongLatch = new CountDownLatch(1); |
Description
Brief description of the changes in this PR.
Type of Change
Related Issue
Closes #(issue number)
Changes Made
Testing
mvn testChecklist
Additional Notes
Any additional information, screenshots, or context that reviewers should know.
Summary by CodeRabbit