gusavila92 / java-android-websocket-client

Java/Android WebSocket Client
Apache License 2.0
148 stars 40 forks source link

Messages longer than 65k are sent with wrong size #11

Closed pupssman closed 5 years ago

pupssman commented 5 years ago

The problem is in the Utils.to8ByteArray function, which is used if length of the sent message is over 65k. Per RFC 6455 (https://tools.ietf.org/html/rfc6455#page-28) body size should be encoded in 8 byte array and it tries to construct the said array from the int length. But in Java ints are only 32 bits (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html) and the cyclic shift causes problems because we output array twice.

The sample code is:

    @Test
    void fooTest() {
        int test = 123123;

        System.out.print("[");

        for (byte b: Utils.to8ByteArray(test)) {
            System.out.print(b);
            System.out.print(", ");
        }
        System.out.println("]");
    }
// outputs [0, 1, -32, -13, 0, 1, -32, -13, ]

As soon as the method takes an int we can safely fill first 4 bytes with zeroes as a fix.

pupssman commented 5 years ago

Or we can change method signature to take long as an argument:

    @Test
    void fooTest() {
        int test = 123123;

        System.out.print("Old: [");

        for (byte b: to8ByteArrayOld(test)) {
            System.out.print(b);
            System.out.print(", ");
        }
        System.out.println("]");

        System.out.print("New: [");

        for (byte b: to8ByteArrayNew(test)) {
            System.out.print(b);
            System.out.print(", ");
        }
        System.out.println("]");
    }

    static byte[] to8ByteArrayOld(int value) {
        return new byte[] { (byte) (value >>> 56), (byte) (value >>> 48), (byte) (value >>> 40), (byte) (value >>> 32),
                (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value };
    }

    static byte[] to8ByteArrayNew(long value) {
        return new byte[] { (byte) (value >>> 56), (byte) (value >>> 48), (byte) (value >>> 40), (byte) (value >>> 32),
                (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value };
    }

// outputs
// Old: [0, 1, -32, -13, 0, 1, -32, -13, ]
// New: [0, 0, 0, 0, 0, 1, -32, -13, ]
gusavila92 commented 5 years ago

Thanks for your help, version 1.2.1 is live with these fixes!