Skip to content

Commit 4b8d2bd

Browse files
authored
fix(rtc): send and receive data packets without a new ctypes array type (#912)
1 parent 7f60f35 commit 4b8d2bd

3 files changed

Lines changed: 47 additions & 10 deletions

File tree

‎livekit-rtc/livekit/rtc/participant.py‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
from __future__ import annotations
1616

17-
import ctypes
1817
import asyncio
1918
import functools
2019
import inspect
@@ -42,7 +41,7 @@
4241
from ._proto.track_pb2 import (
4342
ParticipantTrackPermission,
4443
)
45-
from ._utils import BroadcastQueue
44+
from ._utils import BroadcastQueue, get_address
4645
from .track import LocalTrack
4746
from .track_publication import (
4847
LocalTrackPublication,
@@ -336,11 +335,10 @@ async def publish_data(
336335
payload = payload.encode("utf-8")
337336

338337
data_len = len(payload)
339-
cdata = (ctypes.c_byte * data_len)(*payload)
340338

341339
req = proto_ffi.FfiRequest()
342340
req.publish_data.local_participant_handle = self._ffi_handle.handle
343-
req.publish_data.data_ptr = ctypes.addressof(cdata)
341+
req.publish_data.data_ptr = get_address(payload)
344342
req.publish_data.data_len = data_len
345343
req.publish_data.reliable = reliable
346344
req.publish_data.topic = topic

‎livekit-rtc/livekit/rtc/room.py‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,12 +1115,7 @@ def _on_room_event(self, event: proto_room.RoomEvent) -> None:
11151115
if which_val == "user":
11161116
owned_buffer_info = packet.user.data
11171117
buffer_info = owned_buffer_info.data
1118-
native_data = ctypes.cast(
1119-
buffer_info.data_ptr,
1120-
ctypes.POINTER(ctypes.c_byte * buffer_info.data_len),
1121-
).contents
1122-
1123-
data = bytes(native_data)
1118+
data = ctypes.string_at(buffer_info.data_ptr, buffer_info.data_len)
11241119
FfiHandle(owned_buffer_info.handle.id).dispose()
11251120
rparticipant = cast(
11261121
RemoteParticipant,

‎livekit-rtc/tests/test_dc.py‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from __future__ import annotations
1313

1414
import asyncio
15+
import ctypes
16+
import gc
1517
from typing import Optional
1618

1719
import pytest
@@ -277,3 +279,45 @@ async def test_data_targeted_with_topic() -> None:
277279
await _assert_no_data(other, other_collector)
278280

279281
await asyncio.gather(sender.disconnect(), target.disconnect(), other.disconnect())
282+
283+
284+
@skip_if_no_credentials() # type: ignore[untyped-decorator]
285+
@pytest.mark.asyncio
286+
async def test_publish_data_makes_no_ctypes_array_type() -> None:
287+
"""Sending and receiving payloads of new lengths makes no ctypes array type."""
288+
room_name = unique_room_name("py-dc-array-type")
289+
290+
sender = rtc.Room()
291+
receiver = rtc.Room()
292+
293+
await connect_room("sender", room_name, room=sender)
294+
await connect_room("receiver", room_name, room=receiver)
295+
await ensure_rooms_all_connected([sender, receiver])
296+
await ensure_participants_visible(sender, ["receiver"])
297+
298+
collector = _DataCollector(receiver, sender_identity="sender")
299+
lengths = range(1001, 1011)
300+
payloads = [bytes([i]) * n for i, n in enumerate(lengths)]
301+
302+
gc.collect()
303+
gc.disable()
304+
try:
305+
for payload in payloads:
306+
await sender.local_participant.publish_data(payload)
307+
await wait_until(
308+
lambda: len(collector.packets) >= len(payloads),
309+
message="receiver did not get all payloads",
310+
)
311+
array_types = [
312+
o
313+
for o in gc.get_objects()
314+
if isinstance(o, type)
315+
and issubclass(o, ctypes.Array)
316+
and getattr(o, "_length_", None) in lengths
317+
]
318+
finally:
319+
gc.enable()
320+
assert array_types == []
321+
assert collector.payloads() == payloads
322+
323+
await asyncio.gather(sender.disconnect(), receiver.disconnect())

0 commit comments

Comments
 (0)