Skip to content

Commit 32238ff

Browse files
Merge pull request #1554 from arvidn/message-race
Fix race between DTLS ClientHello and registerIncoming()
2 parents 9a64f88 + 4198dde commit 32238ff

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

src/impl/transport.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,24 @@ void Transport::unregisterIncoming() {
3838

3939
Transport::State Transport::state() const { return mState; }
4040

41-
void Transport::onRecv(message_callback callback) { mRecvCallback = std::move(callback); }
41+
void Transport::onRecv(message_callback callback) {
42+
std::vector<message_ptr> pending;
43+
{
44+
std::lock_guard lock(mPendingMutex);
45+
mRecvCallback = std::move(callback);
46+
if (mRecvCallback)
47+
pending = std::move(mPendingRecv);
48+
else
49+
mPendingRecv.clear();
50+
}
51+
for (auto &msg : pending) {
52+
try {
53+
mRecvCallback(msg);
54+
} catch (const std::exception &e) {
55+
PLOG_WARNING << e.what();
56+
}
57+
}
58+
}
4259

4360
void Transport::onStateChange(state_callback callback) {
4461
mStateChangeCallback = std::move(callback);
@@ -52,6 +69,17 @@ bool Transport::send(message_ptr message) { return outgoing(message); }
5269

5370
void Transport::recv(message_ptr message) {
5471
try {
72+
std::unique_lock lock(mPendingMutex);
73+
if (!mRecvCallback) {
74+
// No callback registered yet; buffer the message for replay when
75+
// onRecv() is called. Bounded to avoid unbounded growth.
76+
if (mPendingRecv.size() < 8)
77+
mPendingRecv.push_back(std::move(message));
78+
else
79+
PLOG_WARNING << "dropping incoming message, no receive callback";
80+
return;
81+
}
82+
lock.unlock();
5583
mRecvCallback(message);
5684
} catch (const std::exception &e) {
5785
PLOG_WARNING << e.what();

src/impl/transport.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <atomic>
1818
#include <functional>
1919
#include <memory>
20+
#include <mutex>
21+
#include <vector>
2022

2123
namespace rtc::impl {
2224

@@ -53,6 +55,13 @@ class Transport {
5355
synchronized_callback<message_ptr> mRecvCallback;
5456

5557
std::atomic<State> mState = State::Disconnected;
58+
59+
// Packets received before a callback is registered are held here and
60+
// replayed when onRecv() is first called with a non-null callback.
61+
// This prevents the ICE->DTLS and DTLS->SCTP races where one side
62+
// sends its first packet before the other side has called registerIncoming().
63+
std::mutex mPendingMutex;
64+
std::vector<message_ptr> mPendingRecv;
5665
};
5766

5867
} // namespace rtc::impl

0 commit comments

Comments
 (0)