0

I coded this packet handler but I can imagine scenarios in which it will get stuck or won't be able to read incomplete data. My questions are:

  1. Should I use two buffers, one for the current incoming data and other to append incomplete data to?
  2. I'm being stupidly over-complicated?

Code:

byte[] buffer;
int bufferLength;
int bytesRead;

buffer = new byte[1024];

while (bluetoothConnected) {
    try {
        // Wait for packet header
        if (mmInStream.available() >= 8) {
            bufferLength = mmInStream.read(buffer);
            bytesRead = 0;

            // Parse every packet
            while (true) {
                int commandType = ByteBuffer.wrap(buffer, 0, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
                int payloadSize = ByteBuffer.wrap(buffer, 2, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
                int packetSize = PACKET_HEADER_SIZE + payloadSize;

                // Break if payload is incomplete
                if (bufferLength < (bytesRead + packetSize)) {
                    // Append to other buffer
                    break;
                }

                byte[] packet = new byte[packetSize];
                System.arraycopy(buffer, bytesRead, packet, 0, packetSize);

                parsePacketSequence(socket, packet);
                bytesRead += packetSize;

                // Break if all bytes are read
                if (bufferLength == bytesRead)
                {
                    break;
                }

                // Break if more bytes are needed
                // Packet header incomplete
                if ((bufferLength - bytesRead) < PACKET_HEADER_SIZE)
                {
                    // Append to other buffer
                    break;
                }
            }
        }
    } 
    catch (IOException e) {
        bluetoothConnected = false;
        Log.d(TAG, "Error " + e);
        break;
    }
}
0

1 Answer 1

1
  1. Should I use two buffers, one for the current incoming data and other to append incomplete data to?

No.

  1. I'm being stupidly over-complicated?

Yes.

Here's a simple version using DataInputStream:

DataInputStream din = new DataInputStream(mmInStream);

while (bluetoothConnected) {
    try {
        // Read packet header
        int commandType = swap(din.readShort());
        int payloadSize = swap(din.readShort());
        int packetSize = PACKET_HEADER_SIZE + payloadSize;
        byte[] packet = new byte[packetSize];
        din.readFully(packet);
        parsePacketSequence(socket, packet);
    } 
    catch (IOException e) {
        bluetoothConnected = false;
        Log.d(TAG, "Error " + e);
        break;
    }
}

The swap() method which converts a short in litte-endian byte order to Java byte order is left as an exercise for the reader.

NB I don't see how parsePacketSequence() can work if it doesn't know commandType.

E&OE

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much. I wanted to use DataInputStream to improve the code but didn't figure out how to change the byte order.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.