[TurnPort] Check if a matching connection exists before replying.

Add an override to TurnPort for SendBindingErrorResponse to check
if a matching connection object exists before continuing. This is
needed to match with the check in `TurnPort::DispatchPacket` whereby
we forward calls to `Port` when no matching connections exist.

Bug: chromium:1395625
Change-Id: Idf1f898c2a93de6bc2832268db1cadd52cae23a9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/287223
Reviewed-by: Sameer Vijaykar <samvi@google.com>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38871}
This commit is contained in:
Tommi 2022-12-11 13:04:40 +01:00 committed by WebRTC LUCI CQ
parent 46ad25119c
commit 29464b06c5
4 changed files with 54 additions and 0 deletions

View File

@ -316,10 +316,22 @@ class Connection : public CandidatePairInterface {
Port* PortForTest() { return port_.get(); }
const Port* PortForTest() const { return port_.get(); }
std::unique_ptr<IceMessage> BuildPingRequestForTest() {
RTC_DCHECK_RUN_ON(network_thread_);
return BuildPingRequest();
}
// Public for unit tests.
uint32_t acked_nomination() const;
void set_remote_nomination(uint32_t remote_nomination);
const std::string& remote_password_for_test() const {
return remote_candidate().password();
}
void set_remote_password_for_test(absl::string_view pwd) {
remote_candidate_.set_password(pwd);
}
protected:
// A ConnectionRequest is a simple STUN ping used to determine writability.
class ConnectionRequest;

View File

@ -687,6 +687,16 @@ bool TurnPort::CanHandleIncomingPacketsFrom(
return server_address_.address == addr;
}
void TurnPort::SendBindingErrorResponse(StunMessage* message,
const rtc::SocketAddress& addr,
int error_code,
absl::string_view reason) {
if (!GetConnection(addr))
return;
Port::SendBindingErrorResponse(message, addr, error_code, reason);
}
bool TurnPort::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
const char* data,
size_t size,

View File

@ -150,6 +150,14 @@ class TurnPort : public Port {
int64_t packet_time_us) override;
bool CanHandleIncomingPacketsFrom(
const rtc::SocketAddress& addr) const override;
// Checks if a connection exists for `addr` before forwarding the call to
// the base class.
void SendBindingErrorResponse(StunMessage* message,
const rtc::SocketAddress& addr,
int error_code,
absl::string_view reason) override;
virtual void OnReadPacket(rtc::AsyncPacketSocket* socket,
const char* data,
size_t size,

View File

@ -683,6 +683,30 @@ class TurnPortTest : public ::testing::Test,
// unknown address.
turn_unknown_address_ = false;
fake_clock_.AdvanceTime(webrtc::TimeDelta::Seconds(5 * 60));
// TODO(chromium:1395625): When `TurnPort` doesn't find connection objects
// for incoming packets, it forwards calls to the parent class, `Port`. This
// happens inside `TurnPort::DispatchPacket`. The `Port` implementation may
// need to send a binding error back over a connection which, unless the
// `TurnPort` implementation handles it, could result in a null deref.
// This special check tests if dispatching messages via `TurnPort` for which
// there's no connection, results in a no-op rather than crashing.
// See `TurnPort::SendBindingErrorResponse` for the check.
// This should probably be done in a neater way both from a testing pov and
// how incoming messages are handled in the `Port` class, when an assumption
// is made about connection objects existing and when those assumptions
// may not hold.
std::string pwd = conn1->remote_password_for_test();
conn1->set_remote_password_for_test("bad");
auto msg = conn1->BuildPingRequestForTest();
rtc::ByteBufferWriter buf;
msg->Write(&buf);
conn1->Send(buf.Data(), buf.Length(), options);
// Now restore the password before continuing.
conn1->set_remote_password_for_test(pwd);
conn1->Ping(0);
EXPECT_TRUE_SIMULATED_WAIT(turn_unknown_address_, kSimulatedRtt,
fake_clock_);