Atmosphere / wasync

WebSockets with fallback transports client library for Node.js, Android and Java
http://async-io.org
161 stars 47 forks source link

TrackMessageSize delivers extra message for multipart messages #141

Closed byteit101 closed 7 years ago

byteit101 commented 8 years ago

When a multipart message arrives, java callback is notified of the raw first to n-1 parts, then the processed full part at the end.

Test case:

import org.atmosphere.wasync.ClientFactory;
import org.atmosphere.wasync.Event;
import org.atmosphere.wasync.Function;
import org.atmosphere.wasync.Request;
import org.atmosphere.wasync.Socket;
import org.atmosphere.wasync.Request.TRANSPORT;
import org.atmosphere.wasync.impl.AtmosphereClient;

public class BugTester {
    public static void main(String[] args) {
        try {
            AtmosphereClient atmoClient = ClientFactory.getDefault().newClient(AtmosphereClient.class);
            Socket socket = atmoClient.create();
            Request request = atmoClient.newRequestBuilder()
                .method(Request.METHOD.GET)
                .uri("http://localhost:5555/hello")
                .transport(TRANSPORT.WEBSOCKET)
                .trackMessageLength(true)
                .build();
            socket.on(Event.MESSAGE, new Function<String>() {
                @Override
                public void on(String message) {
                    System.out.println(message.length() + " -- " + message);
                }
            });
            socket.open(request);
        Thread.sleep(5000);
        } catch (Throwable e) { }
    }
}

I've also attached a sample dump & test websocket server to help illustrate, which can be run using:

# if you have ruby installed
ruby websocketserver.rb websocketdump.txt 5555

or if you need ruby, download jruby.jar and run:

# if you have JRuby
java -jar jruby-complete-9.1.5.0.jar websocketserver.rb websocketdump.txt 5555

Once you have the server running, running the java client will connect on port 5555 and trigger the ruby server to dump the messages back to the java client.

The demo session dump is split into the following message sent 0.3 seconds apart:

#1 (generated) = http switching
#2 = session info
#3 = heartbeat & events
#4 = big/truncated
#5 = continuation of #4
#6 = extra message
#7 = heartbeat and abnormal close

Note that the java client prints out (truncated, length -- data)):

27 -- {"heartbeat":1474483533488}
4216 -- {"events":[....]}
8192 -- 8356|{"events":[.....{"type":"string
8356 -- {"events":......}}]}}]}
76 -- {"events":[{"type":"end_snapshot","qid":5},{"type":"end_snapshot","qid":6}]}
27 -- {"heartbeat":1474483538577}

When I expected:

27 -- {"heartbeat":1474483533488}
4216 -- {"events":[....]}
8356 -- {"events":......}}]}}]}
76 -- {"events":[{"type":"end_snapshot","qid":5},{"type":"end_snapshot","qid":6}]}
27 -- {"heartbeat":1474483538577}

which correspond to websocket messages:

#3 (a)
#3 (b)
#4+#5
#6

whereas it actually got:

#3 (a)
#3 (b)
raw #4
#4+#5
#6
jfarcand commented 7 years ago

@byteit101 Pull request welcomed if you have found the solution!

byteit101 commented 7 years ago

Sorry, but I only have a sketchy workaround to avoid this bug by ignoring messages with a pipe in the first 6 characters

thabach commented 7 years ago

@byteit101 thank you for the nice report, did our fix rectify your problem ?

byteit101 commented 7 years ago

Just tested, and yes, it did. Thanks!