For bluetooth in KDE Connect, we set up only a single connection between two KDE Connect clients (one as bluetooth server, one as client). This is in contrast to the LAN/TCP backend, where payloads are transferred over separate network connections.
## Why do we do this?
Bluetooth has several issues, compared to TCP. Among these is that the amount of connections between two devices is limited, and that a lot of devices only support a single "server" socket. Also, not all devices can operate in a server mode, only the "master" bluetooth device can.
However, just simply putting the payload directly in the existing connection also has problems. For example, streams without a known size are impossible to support in this scheme. Also, we'd prefer KDE Connect to keep working while a large file is transferring.
## What is the chosen solution?
To solve all this, we implemented a multiplexing protocol. This way, the bluetooth connection is divided up into any number of channels, which can send and receive data independently from each other.
The protocol is agnostic for server/client roles, requires no start-up communication and does not depend on bluetooth peculiarities (so could even by used in e.g. LAN).
# Protocol description
*Protocol version 1*
Every channel on the connection is identified by a randomly chosen UUID. To communicate over the channel, or to communicate *about* a channel, messages are send. The following section explains the general message format, and the sections thereafter describe each type of message.
The first message sent must be the `MESSAGE_PROTOCOL_VERSION` message. After that, other messages can be send in any order, but messages about unknown channels should be ignored.
The multiplexed connection starts with a single default/main channel with UUID **`a0d0aaf4-1072-4d81-aa35-902a954b1266`**. This channel works like any other channel, but requires no communication to set up.
## General message format
Every message send between the two endpoints has the following format.
```
| Message type | Message length | Channel UUID | Message data |
This message should be the first message to send. Use the maximum version supported by both endpoints (if any), or otherwise close the connection. The other data field is not used (and should be empty for protocol version 1), but it implies that message lengths of more than 4 need to be supported for future compatability.
Currently, no client will send this message with a version other than 1, but you *must* accept and check it, for forward compatibility.
## MESSAGE_OPEN_CHANNEL
Before sending other messages about a channel, first send a `MESSAGE_OPEN_CHANNEL` message, so the other endpoint knows the channel exists. A channel UUID should be chosen randomly and not reused.
This message always has length 0.
## MESSAGE_CLOSE_CHANNEL
To close a channel, send a `MESSAGE_CLOSE_CHANNEL` message. In your implementation, take care that your code gets to see the channel if it's quickly opened, little data is written, and then gets closed again.
This message always has length 0.
## MESSAGE_READ
To prevent getting too much data on a channel unable to cope with that data, each channel needs to indicate that it wants to receive more data. To do so, send a `MESSAGE_READ` message as follows:
```
| MESSAGE_READ header | Amount of additional data requested |
| 19 bytes | 2 bytes (Big-Endian) |
```
Note that the amount of data you request is in *addition* to the amounts you requested before.
## MESSAGE_WRITE
To write data in a channel, you must first wait until the other endpoint indicates that it wants some data (with `MESSAGE_READ` messages). Once you have this indication, you must not write more data than has been requested (writing less is allowed). The `MESSAGE_WRITE` message has the following format:
```
| MESSAGE_WRITE header | Data to write in channel |