diff --git a/pc/data_channel.cc b/pc/data_channel.cc index cd4ddedf34..f4a3818624 100644 --- a/pc/data_channel.cc +++ b/pc/data_channel.cc @@ -28,6 +28,16 @@ namespace webrtc { static size_t kMaxQueuedReceivedDataBytes = 16 * 1024 * 1024; static size_t kMaxQueuedSendDataBytes = 16 * 1024 * 1024; +namespace { + +static std::atomic g_unique_id{0}; + +int GenerateUniqueId() { + return ++g_unique_id; +} + +} // namespace + InternalDataChannelInit::InternalDataChannelInit(const DataChannelInit& base) : DataChannelInit(base), open_handshake_role(kOpener) { // If the channel is externally negotiated, do not send the OPEN message. @@ -144,7 +154,8 @@ bool DataChannel::IsSctpLike(cricket::DataChannelType type) { DataChannel::DataChannel(DataChannelProviderInterface* provider, cricket::DataChannelType dct, const std::string& label) - : label_(label), + : internal_id_(GenerateUniqueId()), + label_(label), observer_(nullptr), state_(kConnecting), messages_sent_(0), @@ -705,4 +716,9 @@ bool DataChannel::SendControlMessage(const rtc::CopyOnWriteBuffer& buffer) { return retval; } +// static +void DataChannel::ResetInternalIdAllocatorForTesting(int new_value) { + g_unique_id = new_value; +} + } // namespace webrtc diff --git a/pc/data_channel.h b/pc/data_channel.h index e4166dd3b1..728226cc35 100644 --- a/pc/data_channel.h +++ b/pc/data_channel.h @@ -142,6 +142,7 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { virtual std::string protocol() const { return config_.protocol; } virtual bool negotiated() const { return config_.negotiated; } virtual int id() const { return config_.id; } + virtual int internal_id() const { return internal_id_; } virtual uint64_t buffered_amount() const; virtual void Close(); virtual DataState state() const { return state_; } @@ -214,6 +215,10 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { // channel's sid is free. sigslot::signal1 SignalClosed; + // Reset the allocator for internal ID values for testing, so that + // the internal IDs generated are predictable. Test only. + static void ResetInternalIdAllocatorForTesting(int new_value); + protected: DataChannel(DataChannelProviderInterface* client, cricket::DataChannelType dct, @@ -267,6 +272,7 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer); bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer); + const int internal_id_; std::string label_; InternalDataChannelInit config_; DataChannelObserver* observer_; diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index 55735c0b83..8336812081 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -1224,7 +1224,7 @@ void RTCStatsCollector::ProduceDataChannelStats_s( pc_->sctp_data_channels()) { std::unique_ptr data_channel_stats( new RTCDataChannelStats( - "RTCDataChannel_" + rtc::ToString(data_channel->id()), + "RTCDataChannel_" + rtc::ToString(data_channel->internal_id()), timestamp_us)); data_channel_stats->label = data_channel->label(); data_channel_stats->protocol = data_channel->protocol(); diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index cd50346491..edbfac1d88 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -942,7 +942,20 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) { ExpectReportContainsCertificateInfo(report, *remote_certinfo); } +TEST_F(RTCStatsCollectorTest, CollectTwoRTCDataChannelStatsWithPendingId) { + pc_->AddSctpDataChannel( + new MockDataChannel(/*id=*/-1, DataChannelInterface::kConnecting)); + pc_->AddSctpDataChannel( + new MockDataChannel(/*id=*/-1, DataChannelInterface::kConnecting)); + + rtc::scoped_refptr report = stats_->GetStatsReport(); +} + TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) { + // Note: The test assumes data channel IDs are predictable. + // This is not a safe assumption, but in order to make it work for + // the test, we reset the ID allocator at test start. + DataChannel::ResetInternalIdAllocatorForTesting(-1); pc_->AddSctpDataChannel(new MockDataChannel(0, "MockDataChannel0", DataChannelInterface::kConnecting, "udp", 1, 2, 3, 4));