webrtc-java
webrtc-java copied to clipboard
Fragmentation support for DataChannel
Is your feature request related to a problem? Please describe. I learned today, that DataChannel only supports message sizes around 16 KB. When I tried to send around 770 KB the channel was closed. Now I have to fragment my data.
Describe the solution you'd like It would be nice if I could just send any amount of data. The lib would only deliver the message as a byte array and notify the receiver when the whole message is complete. Additional events for start of transmission and x bytes received would be nice to. This way the receiver can display a progress bar.
Describe alternatives you've considered Write the fragmentation support myself.
I went with
ByteBuffer buffer = ByteBuffer.allocate(message.length + Integer.BYTES);
buffer.putInt(message.length).put(message).rewind();
int chunkSize = 16 * 1024;
while (buffer.remaining() > 0) {
var amountToSend = buffer.remaining() <= chunkSize ? buffer.remaining() : chunkSize;
ByteBuffer part = buffer;
if (amountToSend != buffer.capacity()) {
// we need to allocation a new ByteBuffer because send calls ByteBuffer.array()
// which would return
// the whole byte[] and not only the slice. But the lib doesn't use
// ByteBuffer.arrayOffset().
var slice = buffer.slice(buffer.position(), amountToSend);
part = ByteBuffer.allocate(amountToSend);
part.put(slice);
}
buffer.position(buffer.position() + amountToSend);
localDataChannel.send(new RTCDataChannelBuffer(part, true));
log.debug(prefix() + " sent " + part.capacity() + " bytes");
}
for sending and
private ByteBuffer messageBuffer = null;
public final byte[] readMessage(ByteBuffer part) {
if (messageBuffer == null) {
int length = part.getInt();
notifyListeners(Direction.Inbound, State.Start, length, 0);
if (part.remaining() == length) {
var ret = new byte[length];
part.get(ret);
notifyListeners(Direction.Inbound, State.Complete, length, length);
return ret;
}
messageBuffer = ByteBuffer.allocate(length);
}
messageBuffer.put(part);
notifyListeners(
Direction.Inbound, State.Progress, messageBuffer.capacity(), messageBuffer.position());
if (messageBuffer.capacity() == messageBuffer.position()) {
notifyListeners(
Direction.Inbound, State.Complete, messageBuffer.capacity(), messageBuffer.capacity());
var ret = messageBuffer.array();
messageBuffer = null;
return ret;
}
return null;
}
plus null checking for receiving.
look to this article https://stackoverflow.com/questions/35381237/webrtc-data-channel-max-data-size
plus you should understand that it's UDP and part of the data may lost in network, I saw this case on transmitting files great than 500kb on slow network connection (at the moment not sure is it bug of the library or success part of data transmission via webrtc technology)