engine.io-client-java icon indicating copy to clipboard operation
engine.io-client-java copied to clipboard

Question about Polling transport's close implementation.

Open Piasy opened this issue 1 year ago • 0 comments

Hi, I've been working on porting Java implementation of EngineIO and SocketIO to Kotlin Multiplatform recently.

During the development and test process, I have a question about Polling transport's close implementation: https://github.com/socketio/engine.io-client-java/blob/main/src/main/java/io/socket/engineio/client/transports/Polling.java#L147C1-L167C6

    protected void doClose() {
        final Polling self = this;

        Emitter.Listener close = new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                logger.fine("writing close packet");
                self.write(new Packet[]{new Packet(Packet.CLOSE)});
            }
        };

        if (this.readyState == ReadyState.OPEN) {
            logger.fine("transport open - closing");
            close.call();
        } else {
            // in case we're trying to close while
            // handshaking is in progress (engine.io-client GH-164)
            logger.fine("transport not open - deferring close");
            this.once(EVENT_OPEN, close);
        }
    }

https://github.com/socketio/engine.io-client-java/blob/main/src/main/java/io/socket/engineio/client/Transport.java#L83C1-L94C6

    public Transport close() {
        EventThread.exec(new Runnable() {
            @Override
            public void run() {
                if (Transport.this.readyState == ReadyState.OPENING || Transport.this.readyState == ReadyState.OPEN) {
                    Transport.this.doClose();
                    Transport.this.onClose();
                }
            }
        });
        return this;
    }

Actually if we call transport.close() while the polling transport is still opening, EVENT_OPEN won't be triggered, because doClose will return immediately, and Transport.this.onClose() will be called, then readyState will be CLOSED, and any further response of poll won't trigger EVENT_OPEN, because code logic below: https://github.com/socketio/engine.io-client-java/blob/main/src/main/java/io/socket/engineio/client/transports/Polling.java#L109C1-L129C11

    private void _onData(Object data) {
        final Polling self = this;
        if (logger.isLoggable(Level.FINE)) {
            logger.fine(String.format("polling got data %s", data));
        }
        Parser.DecodePayloadCallback callback = new Parser.DecodePayloadCallback() {
            @Override
            public boolean call(Packet packet, int index, int total) {
                if (self.readyState == ReadyState.OPENING && Packet.OPEN.equals(packet.type)) {
                    self.onOpen();
                }

                ...
            }
        };

I think the problem is we shouldn't call Transport.this.onClose() in Transport.this.close(), am I right?

Piasy avatar Jan 01 '25 12:01 Piasy