Skip to content

Commit 4245044

Browse files
committed
fix(core): avoid blocking THP when send buffer is full
[no changelog]
1 parent 6e45c37 commit 4245044

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

core/src/trezor/wire/thp/channel.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
conditionally_replace_channel,
2121
is_there_a_channel_to_replace,
2222
)
23-
from trezor import protobuf, utils, workflow
23+
from trezor import loop, protobuf, utils, workflow
2424
from trezor.loop import Timeout
2525

2626
from ..protocol_common import Message
@@ -51,6 +51,8 @@
5151
_MAX_RETRANSMISSION_COUNT = const(50)
5252
_MIN_RETRANSMISSION_COUNT = const(2)
5353

54+
_WRITE_TIMEOUT_MS = const(5_000)
55+
5456

5557
class Reassembler:
5658
def __init__(self, cid: int, read_buf: ThpBuffer) -> None:
@@ -395,16 +397,27 @@ async def write_encrypted_payload(self, ctrl_byte: int, payload: bytes) -> None:
395397
# ACK is needed before sending more data
396398
ABP.set_sending_allowed(self.channel_cache, False)
397399

400+
write_timeout = loop.sleep(_WRITE_TIMEOUT_MS)
401+
398402
for i in range(_MAX_RETRANSMISSION_COUNT):
399-
await self.ctx.write_payload(header, payload)
403+
res = await loop.race(
404+
self.ctx.write_payload(header, payload), write_timeout
405+
)
406+
if isinstance(res, int):
407+
# When using USB, the writer can get stuck if there is no matching reader.
408+
# Let's stop retransmission in this case, to allow handling other channels.
409+
if __debug__:
410+
self._log("Sending is stuck", logger=log.error)
411+
break
412+
400413
# starting from 100ms till ~3.42s
401414
timeout_ms = round(10200 - 1010000 / (100 + i))
402415
try:
403416
# wait and return after receiving an ACK, or raise in case of an unexpected message.
404417
await self.recv_payload(expected_ctrl_byte=None, timeout_ms=timeout_ms)
405418
except Timeout:
406419
if __debug__:
407-
log.warning(__name__, "Retransmit after %d ms", timeout_ms)
420+
self._log(f"Retransmit after {timeout_ms} ms", logger=log.warning)
408421
continue
409422
# `ABP.set_sending_allowed()` will be called after a valid ACK
410423
if ABP.is_sending_allowed(self.channel_cache):

0 commit comments

Comments
 (0)