Kenny
Kenny

Reputation: 1152

Handling binary packets

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;
    }
}

Upvotes: 0

Views: 119

Answers (1)

user207421
user207421

Reputation: 311052

  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

Upvotes: 1

Related Questions