Skip to content

Commit 2a7449c

Browse files
fix: honor the buffer window in every send path (#245)
1 parent 56cf721 commit 2a7449c

1 file changed

Lines changed: 30 additions & 11 deletions

File tree

webrtc/src/main/java/dev/onvoid/webrtc/RTCDataChannel.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ private RTCDataChannel() {
143143
public native void dispose();
144144

145145
/**
146-
* Sends data in the provided buffer to the remote peer.
146+
* Sends data in the provided buffer to the remote peer. Only the bytes
147+
* between the buffer's position and limit are sent, for heap and direct
148+
* buffers alike. The buffer is read through a duplicate, so the caller's
149+
* position is left untouched.
147150
*
148151
* @param buffer The buffer to be queued for transmission.
149152
*
@@ -154,21 +157,37 @@ public void send(RTCDataChannelBuffer buffer) throws Exception {
154157
ByteBuffer data = buffer.data;
155158

156159
if (data.isDirect()) {
157-
sendDirectBuffer(data, buffer.binary);
158-
}
159-
else {
160-
byte[] arrayBuffer;
161-
162-
if (data.hasArray()) {
163-
arrayBuffer = data.array();
160+
if (data.position() == 0 && data.limit() == data.capacity()) {
161+
sendDirectBuffer(data, buffer.binary);
164162
}
165163
else {
166-
arrayBuffer = new byte[data.remaining()];
167-
data.get(arrayBuffer);
164+
ByteBuffer window = ByteBuffer.allocateDirect(data.remaining());
165+
window.put(data.duplicate());
166+
window.flip();
167+
sendDirectBuffer(window, buffer.binary);
168168
}
169+
}
170+
else {
171+
sendByteArrayBuffer(copyWindow(data), buffer.binary);
172+
}
173+
}
169174

170-
sendByteArrayBuffer(arrayBuffer, buffer.binary);
175+
/**
176+
* Copies the readable window of a heap buffer, position to limit, into a
177+
* fresh array for the byte array send path, which transmits whole arrays.
178+
* The backing array is handed over directly only when the window covers
179+
* it exactly; bytes outside the window (a nonzero position, a short
180+
* limit, an array offset) must never reach the wire. Reads through a
181+
* duplicate, so the caller's position is left untouched.
182+
*/
183+
private static byte[] copyWindow(ByteBuffer data) {
184+
if (data.hasArray() && data.arrayOffset() == 0 && data.position() == 0
185+
&& data.remaining() == data.array().length) {
186+
return data.array();
171187
}
188+
byte[] window = new byte[data.remaining()];
189+
data.duplicate().get(window);
190+
return window;
172191
}
173192

174193
private native void sendDirectBuffer(ByteBuffer buffer, boolean binary);

0 commit comments

Comments
 (0)