Add stats collection for the data channel.

BUG=1805
R=bemasc@chromium.org, hta@webrtc.org, pthatcher@webrtc.org, tommi@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/34619004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@8083 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/datachannelinterface.h b/talk/app/webrtc/datachannelinterface.h
index 5684cc2..eb8a0b7 100644
--- a/talk/app/webrtc/datachannelinterface.h
+++ b/talk/app/webrtc/datachannelinterface.h
@@ -35,6 +35,7 @@
 
 #include "webrtc/base/basictypes.h"
 #include "webrtc/base/buffer.h"
+#include "webrtc/base/checks.h"
 #include "webrtc/base/refcount.h"
 
 
@@ -106,6 +107,21 @@
     kClosed
   };
 
+  static const char* DataStateString(DataState state) {
+    switch (state) {
+      case kConnecting:
+        return "connecting";
+      case kOpen:
+        return "open";
+      case kClosing:
+        return "closing";
+      case kClosed:
+        return "closed";
+    }
+    CHECK(false) << "Unknown DataChannel state: " << state;
+    return "";
+  }
+
   virtual void RegisterObserver(DataChannelObserver* observer) = 0;
   virtual void UnregisterObserver() = 0;
   // The label attribute represents a label that can be used to distinguish this
diff --git a/talk/app/webrtc/mediastreamsignaling.h b/talk/app/webrtc/mediastreamsignaling.h
index d4b1be8..7b8cf97 100644
--- a/talk/app/webrtc/mediastreamsignaling.h
+++ b/talk/app/webrtc/mediastreamsignaling.h
@@ -162,6 +162,7 @@
  public:
   typedef std::map<std::string, rtc::scoped_refptr<DataChannel> >
       RtpDataChannels;
+  typedef std::vector<rtc::scoped_refptr<DataChannel>> SctpDataChannels;
 
   MediaStreamSignaling(rtc::Thread* signaling_thread,
                        MediaStreamSignalingObserver* stream_observer,
@@ -255,6 +256,10 @@
   void OnDtlsRoleReadyForSctp(rtc::SSLRole role);
   void OnRemoteSctpDataChannelClosed(uint32 sid);
 
+  const SctpDataChannels& sctp_data_channels() const {
+    return sctp_data_channels_;
+  }
+
  private:
   struct RemotePeerInfo {
     RemotePeerInfo()
@@ -392,8 +397,6 @@
   int last_allocated_sctp_even_sid_;
   int last_allocated_sctp_odd_sid_;
 
-  typedef std::vector<rtc::scoped_refptr<DataChannel> > SctpDataChannels;
-
   RtpDataChannels rtp_data_channels_;
   SctpDataChannels sctp_data_channels_;
 };
diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc
index 1e3a1d9..05695c0 100644
--- a/talk/app/webrtc/statscollector.cc
+++ b/talk/app/webrtc/statscollector.cc
@@ -403,7 +403,8 @@
 }
 
 StatsCollector::StatsCollector(WebRtcSession* session)
-    : session_(session), stats_gathering_started_(0) {
+    : session_(session),
+      stats_gathering_started_(0) {
   ASSERT(session_);
 }
 
@@ -516,6 +517,7 @@
     ExtractSessionInfo();
     ExtractVoiceInfo();
     ExtractVideoInfo(level);
+    ExtractDataInfo();
   }
 }
 
@@ -756,14 +758,16 @@
         channel_report->timestamp = stats_gathering_started_;
         channel_report->AddValue(StatsReport::kStatsValueNameComponent,
                                  channel_iter->component);
-        if (!local_cert_report_id.empty())
+        if (!local_cert_report_id.empty()) {
           channel_report->AddValue(
               StatsReport::kStatsValueNameLocalCertificateId,
               local_cert_report_id);
-        if (!remote_cert_report_id.empty())
+        }
+        if (!remote_cert_report_id.empty()) {
           channel_report->AddValue(
               StatsReport::kStatsValueNameRemoteCertificateId,
               remote_cert_report_id);
+        }
         for (size_t i = 0;
              i < channel_iter->connection_infos.size();
              ++i) {
@@ -880,6 +884,22 @@
   }
 }
 
+void StatsCollector::ExtractDataInfo() {
+  ASSERT(session_->signaling_thread()->IsCurrent());
+
+  for (const auto& dc :
+           session_->mediastream_signaling()->sctp_data_channels()) {
+    StatsReport* report = reports_.ReplaceOrAddNew(
+        StatsId(StatsReport::kStatsReportTypeDataChannel, dc->label()));
+    report->type = StatsReport::kStatsReportTypeDataChannel;
+    report->AddValue(StatsReport::kStatsValueNameLabel, dc->label());
+    report->AddValue(StatsReport::kStatsValueNameDataChannelId, dc->id());
+    report->AddValue(StatsReport::kStatsValueNameProtocol, dc->protocol());
+    report->AddValue(StatsReport::kStatsValueNameState,
+                     DataChannelInterface::DataStateString(dc->state()));
+  }
+}
+
 StatsReport* StatsCollector::GetReport(const std::string& type,
                                        const std::string& id,
                                        TrackDirection direction) {
diff --git a/talk/app/webrtc/statscollector.h b/talk/app/webrtc/statscollector.h
index f8d19c1..45626af 100644
--- a/talk/app/webrtc/statscollector.h
+++ b/talk/app/webrtc/statscollector.h
@@ -36,6 +36,7 @@
 #include <vector>
 
 #include "talk/app/webrtc/mediastreaminterface.h"
+#include "talk/app/webrtc/mediastreamsignaling.h"
 #include "talk/app/webrtc/peerconnectioninterface.h"
 #include "talk/app/webrtc/statstypes.h"
 #include "talk/app/webrtc/webrtcsession.h"
@@ -60,7 +61,7 @@
 
   // The caller is responsible for ensuring that the session outlives the
   // StatsCollector instance.
-  explicit StatsCollector(WebRtcSession* session);
+  StatsCollector(WebRtcSession* session);
   virtual ~StatsCollector();
 
   // Adds a MediaStream with tracks that can be used as a |selector| in a call
@@ -119,6 +120,7 @@
   // returns the leaf certificate's report's ID.
   std::string AddCertificateReports(const rtc::SSLCertificate* cert);
 
+  void ExtractDataInfo();
   void ExtractSessionInfo();
   void ExtractVoiceInfo();
   void ExtractVideoInfo(PeerConnectionInterface::StatsOutputLevel level);
diff --git a/talk/app/webrtc/statscollector_unittest.cc b/talk/app/webrtc/statscollector_unittest.cc
index 539bf23..cba4003 100644
--- a/talk/app/webrtc/statscollector_unittest.cc
+++ b/talk/app/webrtc/statscollector_unittest.cc
@@ -31,11 +31,13 @@
 
 #include "talk/app/webrtc/mediastream.h"
 #include "talk/app/webrtc/mediastreaminterface.h"
+#include "talk/app/webrtc/mediastreamsignaling.h"
 #include "talk/app/webrtc/mediastreamtrack.h"
+#include "talk/app/webrtc/test/fakedatachannelprovider.h"
+#include "talk/app/webrtc/test/fakemediastreamsignaling.h"
 #include "talk/app/webrtc/videotrack.h"
 #include "talk/media/base/fakemediaengine.h"
 #include "talk/media/devices/fakedevicemanager.h"
-#include "webrtc/p2p/base/fakesession.h"
 #include "talk/session/media/channelmanager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -43,6 +45,7 @@
 #include "webrtc/base/fakesslidentity.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/base/network.h"
+#include "webrtc/p2p/base/fakesession.h"
 
 using cricket::StatsOptions;
 using testing::_;
@@ -81,6 +84,7 @@
   }
   MOCK_METHOD0(voice_channel, cricket::VoiceChannel*());
   MOCK_METHOD0(video_channel, cricket::VideoChannel*());
+  MOCK_CONST_METHOD0(mediastream_signaling, const MediaStreamSignaling*());
   // Libjingle uses "local" for a outgoing track, and "remote" for a incoming
   // track.
   MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32, std::string*));
@@ -438,9 +442,12 @@
           new cricket::ChannelManager(media_engine_,
                                       new cricket::FakeDeviceManager(),
                                       rtc::Thread::Current())),
+      signaling_(channel_manager_.get()),
       session_(channel_manager_.get()) {
     // By default, we ignore session GetStats calls.
     EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
+    EXPECT_CALL(session_, mediastream_signaling()).WillRepeatedly(
+        Return(&signaling_));
   }
 
   ~StatsCollectorTest() {}
@@ -587,7 +594,8 @@
                               const std::vector<std::string>& local_ders,
                               const rtc::FakeSSLCertificate& remote_cert,
                               const std::vector<std::string>& remote_ders) {
-    webrtc::StatsCollector stats(&session_);  // Implementation under test.
+    webrtc::StatsCollector stats(&session_);
+
     StatsReports reports;  // returned values.
 
     // Fake stats to process.
@@ -665,15 +673,53 @@
   cricket::FakeMediaEngine* media_engine_;
   rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
   MockWebRtcSession session_;
+  FakeMediaStreamSignaling signaling_;
+  FakeDataChannelProvider data_channel_provider_;
   cricket::SessionStats session_stats_;
   rtc::scoped_refptr<webrtc::MediaStream> stream_;
   rtc::scoped_refptr<webrtc::VideoTrack> track_;
   rtc::scoped_refptr<FakeAudioTrack> audio_track_;
 };
 
+// Verify that ExtractDataInfo populates reports.
+TEST_F(StatsCollectorTest, ExtractDataInfo) {
+  const std::string label = "hacks";
+  const int id = 31337;
+  const std::string state = DataChannelInterface::DataStateString(
+      DataChannelInterface::DataState::kConnecting);
+
+  EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
+  EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
+
+  InternalDataChannelInit config;
+  config.id = id;
+  signaling_.AddDataChannel(DataChannel::Create(
+      &data_channel_provider_, cricket::DCT_SCTP, label, config));
+  webrtc::StatsCollector stats(&session_);
+
+  stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
+
+  StatsReports reports;
+  stats.GetStats(NULL, &reports);
+  EXPECT_EQ(label, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel,
+                                     reports,
+                                     StatsReport::kStatsValueNameLabel));
+  EXPECT_EQ(rtc::ToString<int64>(id),
+            ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel,
+                              reports,
+                              StatsReport::kStatsValueNameDataChannelId));
+  EXPECT_EQ(state, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel,
+                                     reports,
+                                     StatsReport::kStatsValueNameState));
+  EXPECT_EQ("", ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel,
+                                  reports,
+                                  StatsReport::kStatsValueNameProtocol));
+}
+
 // This test verifies that 64-bit counters are passed successfully.
 TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(rtc::Thread::Current(),
       media_engine_, media_channel, &session_, "", false, NULL);
@@ -706,7 +752,8 @@
 
 // Test that BWE information is reported via stats.
 TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(rtc::Thread::Current(),
       media_engine_, media_channel, &session_, "", false, NULL);
@@ -750,7 +797,8 @@
 // This test verifies that an object of type "googSession" always
 // exists in the returned stats.
 TEST_F(StatsCollectorTest, SessionObjectExists) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   StatsReports reports;  // returned values.
   EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
@@ -764,7 +812,8 @@
 // This test verifies that only one object of type "googSession" exists
 // in the returned stats.
 TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   StatsReports reports;  // returned values.
   EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
@@ -782,7 +831,8 @@
 // This test verifies that the empty track report exists in the returned stats
 // without calling StatsCollector::UpdateStats.
 TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(rtc::Thread::Current(),
       media_engine_, media_channel, &session_, "", false, NULL);
@@ -806,7 +856,8 @@
 // This test verifies that the empty track report exists in the returned stats
 // when StatsCollector::UpdateStats is called with ssrc stats.
 TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(rtc::Thread::Current(),
       media_engine_, media_channel, &session_, "", false, NULL);
@@ -861,7 +912,8 @@
 // This test verifies that an SSRC object has the identifier of a Transport
 // stats object, and that this transport stats object exists in stats.
 TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   // Ignore unused callback (logspam).
   EXPECT_CALL(session_, GetTransport(_))
       .WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
@@ -910,7 +962,8 @@
 // This test verifies that a remote stats object will not be created for
 // an outgoing SSRC where remote stats are not returned.
 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   // The content_name known by the video channel.
   const std::string kVcName("vcname");
@@ -933,7 +986,8 @@
 // This test verifies that a remote stats object will be created for
 // an outgoing SSRC where stats are returned.
 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   // Ignore unused callback (logspam).
   EXPECT_CALL(session_, GetTransport(_))
       .WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
@@ -981,7 +1035,8 @@
 // This test verifies that the empty track report exists in the returned stats
 // when StatsCollector::UpdateStats is called with ssrc stats.
 TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(rtc::Thread::Current(),
       media_engine_, media_channel, &session_, "", false, NULL);
@@ -1026,7 +1081,8 @@
 // This test verifies the Ice Candidate report should contain the correct
 // information from local/remote candidates.
 TEST_F(StatsCollectorTest, IceCandidateReport) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   StatsReports reports;                     // returned values.
 
   const int local_port = 2000;
@@ -1157,7 +1213,8 @@
 // This test verifies that the stats are generated correctly when no
 // transport is present.
 TEST_F(StatsCollectorTest, NoTransport) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   StatsReports reports;  // returned values.
 
   // Fake stats to process.
@@ -1203,7 +1260,8 @@
 // This test verifies that the stats are generated correctly when the transport
 // does not have any certificates.
 TEST_F(StatsCollectorTest, NoCertificates) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   StatsReports reports;  // returned values.
 
   // Fake stats to process.
@@ -1271,7 +1329,8 @@
 // Verifies the correct optons are passed to the VideoMediaChannel when using
 // verbose output level.
 TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(rtc::Thread::Current(),
       media_engine_, media_channel, &session_, "", false, NULL);
@@ -1316,7 +1375,8 @@
 // This test verifies that a local stats object can get statistics via
 // AudioTrackInterface::GetStats() method.
 TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   // Ignore unused callback (logspam).
   EXPECT_CALL(session_, GetTransport(_))
       .WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
@@ -1349,7 +1409,8 @@
 // This test verifies that audio receive streams populate stats reports
 // correctly.
 TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   // Ignore unused callback (logspam).
   EXPECT_CALL(session_, GetTransport(_))
       .WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
@@ -1375,7 +1436,8 @@
 // This test verifies that a local stats object won't update its statistics
 // after a RemoveLocalAudioTrack() call.
 TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   // Ignore unused callback (logspam).
   EXPECT_CALL(session_, GetTransport(_))
       .WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
@@ -1432,7 +1494,8 @@
 // This test verifies that when ongoing and incoming audio tracks are using
 // the same ssrc, they populate stats reports correctly.
 TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   // Ignore unused callback (logspam).
   EXPECT_CALL(session_, GetTransport(_))
       .WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
@@ -1514,7 +1577,8 @@
 // TODO(xians): Figure out if it is possible to encapsulate the setup and
 // avoid duplication of code in test cases.
 TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) {
-  webrtc::StatsCollector stats(&session_);  // Implementation under test.
+  webrtc::StatsCollector stats(&session_);
+
   // Ignore unused callback (logspam).
   EXPECT_CALL(session_, GetTransport(_))
       .WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
diff --git a/talk/app/webrtc/statstypes.cc b/talk/app/webrtc/statstypes.cc
index fd96b10..b15dba5 100644
--- a/talk/app/webrtc/statstypes.cc
+++ b/talk/app/webrtc/statstypes.cc
@@ -41,6 +41,7 @@
 const char StatsReport::kStatsReportTypeComponent[] = "googComponent";
 const char StatsReport::kStatsReportTypeCandidatePair[] = "googCandidatePair";
 const char StatsReport::kStatsReportTypeCertificate[] = "googCertificate";
+const char StatsReport::kStatsReportTypeDataChannel[] = "datachannel";
 
 const char StatsReport::kStatsReportVideoBweId[] = "bweforvideo";
 
@@ -109,14 +110,22 @@
       return "packetsSent";
     case kStatsValueNameBytesReceived:
       return "bytesReceived";
+    case kStatsValueNameLabel:
+      return "label";
     case kStatsValueNamePacketsReceived:
       return "packetsReceived";
     case kStatsValueNamePacketsLost:
       return "packetsLost";
+    case kStatsValueNameProtocol:
+      return "protocol";
     case kStatsValueNameTransportId:
       return "transportId";
     case kStatsValueNameSsrc:
       return "ssrc";
+    case kStatsValueNameState:
+      return "state";
+    case kStatsValueNameDataChannelId:
+      return "datachannelid";
 
     // 'goog' prefixed constants.
     case kStatsValueNameActiveConnection:
diff --git a/talk/app/webrtc/statstypes.h b/talk/app/webrtc/statstypes.h
index bca771c..15a12d8 100644
--- a/talk/app/webrtc/statstypes.h
+++ b/talk/app/webrtc/statstypes.h
@@ -79,11 +79,14 @@
     kStatsValueNameAudioOutputLevel,
     kStatsValueNameBytesReceived,
     kStatsValueNameBytesSent,
+    kStatsValueNameDataChannelId,
     kStatsValueNamePacketsLost,
     kStatsValueNamePacketsReceived,
     kStatsValueNamePacketsSent,
+    kStatsValueNameProtocol,
     kStatsValueNameReadable,
     kStatsValueNameSsrc,
+    kStatsValueNameState,
     kStatsValueNameTransportId,
 
     // Internal StatsValue names.
@@ -143,6 +146,7 @@
     kStatsValueNameIssuerId,
     kStatsValueNameJitterBufferMs,
     kStatsValueNameJitterReceived,
+    kStatsValueNameLabel,
     kStatsValueNameLocalAddress,
     kStatsValueNameLocalCandidateId,
     kStatsValueNameLocalCandidateType,
@@ -262,6 +266,10 @@
 
   // The id of StatsReport of type VideoBWE.
   static const char kStatsReportVideoBweId[];
+
+  // A StatsReport of |type| = "datachannel" with statistics for a
+  // particular DataChannel.
+  static const char kStatsReportTypeDataChannel[];
 };
 
 // This class is provided for the cases where we need to keep
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index 1d8281c..e3f71a5 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -137,6 +137,10 @@
     return data_channel_.get();
   }
 
+  virtual const MediaStreamSignaling* mediastream_signaling() const {
+    return mediastream_signaling_;
+  }
+
   void SetSdesPolicy(cricket::SecurePolicy secure_policy);
   cricket::SecurePolicy SdesPolicy() const;