TooTallNate / Java-WebSocket

A barebones WebSocket client and server implementation written in 100% Java.
http://tootallnate.github.io/Java-WebSocket
MIT License
10.53k stars 2.58k forks source link

[Android & Node.js Server] Problem using PerMessageDeflateExtension with custom ping/pong messages ? #1164

Closed SaraHan774 closed 3 years ago

SaraHan774 commented 3 years ago

Hi, I have a question about using PerMessageDeflateExtension.

E/SessionManager: ◖[Session] WebSocket error #Network   ⚑[SessionManager$listenToEvents$6.accept:358]
E/SessionManager: ◖ org.java_websocket.exceptions.InvalidFrameException: RSV1 bit must be set for DataFrames.
E/SessionManager: ◖ at org.java_websocket.extensions.permessage_deflate.PerMessageDeflateExtension.isFrameValid(PerMessageDeflateExtension.java:321)
E/SessionManager: ◖ at org.java_websocket.drafts.Draft_6455.translateSingleFrame(Draft_6455.java:565)
E/SessionManager: ◖ at org.java_websocket.drafts.Draft_6455.translateFrame(Draft_6455.java:739)
E/SessionManager: ◖ at org.java_websocket.WebSocketImpl.decodeFrames(WebSocketImpl.java:398)
E/SessionManager: ◖ at org.java_websocket.WebSocketImpl.decode(WebSocketImpl.java:233)
E/SessionManager: ◖ at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:516)
E/SessionManager: ◖ at java.lang.Thread.run(Thread.java:923)
E/SessionManager: ◖ 

I ran into above error log, so I made a break point like below.

image

image

If you see the log, the payload contains our custom ping message which is being transferred in TextFrame. I would like to know if this kind of custom ping/pong message could interfere with using PerMessageDeflateExtensions properly. (I checked the RFC 6455 document and read that Ping/Pong Frames have different opcodes)

Also, I couldn't understand the purpose of the below lines.

    public void isFrameValid(Framedata inputFrame) throws InvalidDataException {
        if((inputFrame instanceof TextFrame || inputFrame instanceof BinaryFrame) && !inputFrame.isRSV1())
            throw new InvalidFrameException("RSV1 bit must be set for DataFrames.");

Does this mean that all TextFrame & BinaryFrame data should have isRSV1() set to true ? If so, how does it handle situations when server compresses data selectively?

Best Regards, Sara.


marci4 commented 3 years ago

Hey Could you provide an example application for both java and node js?

I may have to recheck the specification but I thought it is only compressed or uncompressed. Mixing not allowed.

Best regards, Marcel

EDIT: I have to be corrected. This document allocates the RSV1 bit of the WebSocket header for PMCEs and calls the bit the "Per-Message Compressed" bit. On a WebSocket connection where a PMCE is in use, this bit indicates whether a message is compressed or not.

SaraHan774 commented 3 years ago

Node.js Server added below code for supporting permessage-deflate. transformer: 'websockets' indicates that the server will use ws module for websocket. https://github.com/primus/primus#websockets

const primus = new Primus(createHttpServer(...), {
  transformer: 'websockets',
  compression: true, 
... 
image

compression : true enables permessage deflate.

In android, there is a WebSocketClient like below,

internal class WebSocketManager(private val wssUrl: URI) {
    companion object {
...
        // For receiving compressed data from the server
        private val perMessageDeflateDraft = Draft_6455(PerMessageDeflateExtension())
    }

    private inner class Client : WebSocketClient {
        constructor(wssUrl: URI) : super(wssUrl)
        constructor(wssUrl: URI, perMessageDeflateDraft: Draft_6455) : super(
            wssUrl,
            perMessageDeflateDraft
        )
...

// overrided functions from WebSocketClient ... 
    }

And when calling WebSocketManager.connect(), the client object is initialized like this

fun connect(): Boolean {
...
            client = Client(wssUrl, perMessageDeflateDraft).apply {
                connectionLostTimeout = DEFAULT_CONNECTION_CHECK_INTERVAL
                addHeader(USER_AGENT_HEADER_NAME, getUserAgentString())
            }
            client!!.connect()
...
}

For the android part, I basically followed this library's wiki on PerMessageDeflateExtension.

SaraHan774 commented 3 years ago

@marci4 Hi, is 1.5.3 scheduled for release in the near future?

PhilipRoman commented 3 years ago

FYI: you don't have to wait for new releases, you can always use https://oss.sonatype.org/content/repositories/snapshots/org/java-websocket/Java-WebSocket/1.5.3-SNAPSHOT/ or Jitpack (https://jitpack.io/#TooTallNate/Java-WebSocket/master-SNAPSHOT)

SaraHan774 commented 3 years ago

Thank you for the answer!

Best Regards, Sara.