TurnCustomizer - an interface for modifying stun messages sent by TurnPort

This patch adds an interface that allows modification of stun messages
sent by TurnPort. A user can inject a TurnCustomizer on the RTCConfig
and the TurnCustomizer will be invoked by TurnPort before sending
message. This allows user to e.g add custom attributes as described
in rtf5389.

BUG=webrtc:8313

Change-Id: I6f4333e9f8ff7fd20f32677be19285f15e1180b6
Reviewed-on: https://webrtc-review.googlesource.com/7618
Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20233}
diff --git a/pc/peerconnection_integrationtest.cc b/pc/peerconnection_integrationtest.cc
index e012301..580bfd4 100644
--- a/pc/peerconnection_integrationtest.cc
+++ b/pc/peerconnection_integrationtest.cc
@@ -31,6 +31,7 @@
 #include "p2p/base/p2pconstants.h"
 #include "p2p/base/portinterface.h"
 #include "p2p/base/sessiondescription.h"
+#include "p2p/base/testturncustomizer.h"
 #include "p2p/base/testturnserver.h"
 #include "p2p/client/basicportallocator.h"
 #include "pc/dtmfsender.h"
@@ -2992,6 +2993,7 @@
   cricket::TestTurnServer turn_server_2(network_thread(),
                                         turn_server_2_internal_address,
                                         turn_server_2_external_address);
+
   // Bypass permission check on received packets so media can be sent before
   // the candidate is signaled.
   turn_server_1.set_enable_permission_checks(false);
@@ -3038,6 +3040,71 @@
   delete SetCalleePcWrapperAndReturnCurrent(nullptr);
 }
 
+// Verify that a TurnCustomizer passed in through RTCConfiguration
+// is actually used by the underlying TURN candidate pair.
+// Note that turnport_unittest.cc contains more detailed, lower-level tests.
+TEST_F(PeerConnectionIntegrationTest,           \
+       TurnCustomizerUsedForTurnConnections) {
+  static const rtc::SocketAddress turn_server_1_internal_address{"88.88.88.0",
+                                                                 3478};
+  static const rtc::SocketAddress turn_server_1_external_address{"88.88.88.1",
+                                                                 0};
+  static const rtc::SocketAddress turn_server_2_internal_address{"99.99.99.0",
+                                                                 3478};
+  static const rtc::SocketAddress turn_server_2_external_address{"99.99.99.1",
+                                                                 0};
+  cricket::TestTurnServer turn_server_1(network_thread(),
+                                        turn_server_1_internal_address,
+                                        turn_server_1_external_address);
+  cricket::TestTurnServer turn_server_2(network_thread(),
+                                        turn_server_2_internal_address,
+                                        turn_server_2_external_address);
+
+  PeerConnectionInterface::RTCConfiguration client_1_config;
+  webrtc::PeerConnectionInterface::IceServer ice_server_1;
+  ice_server_1.urls.push_back("turn:88.88.88.0:3478");
+  ice_server_1.username = "test";
+  ice_server_1.password = "test";
+  client_1_config.servers.push_back(ice_server_1);
+  client_1_config.type = webrtc::PeerConnectionInterface::kRelay;
+  auto customizer1 = rtc::MakeUnique<cricket::TestTurnCustomizer>();
+  client_1_config.turn_customizer = customizer1.get();
+
+  PeerConnectionInterface::RTCConfiguration client_2_config;
+  webrtc::PeerConnectionInterface::IceServer ice_server_2;
+  ice_server_2.urls.push_back("turn:99.99.99.0:3478");
+  ice_server_2.username = "test";
+  ice_server_2.password = "test";
+  client_2_config.servers.push_back(ice_server_2);
+  client_2_config.type = webrtc::PeerConnectionInterface::kRelay;
+  auto customizer2 = rtc::MakeUnique<cricket::TestTurnCustomizer>();
+  client_2_config.turn_customizer = customizer2.get();
+
+  ASSERT_TRUE(
+      CreatePeerConnectionWrappersWithConfig(client_1_config, client_2_config));
+  ConnectFakeSignaling();
+
+  // Set "offer to receive audio/video" without adding any tracks, so we just
+  // set up ICE/DTLS with no media.
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.offer_to_receive_audio = 1;
+  options.offer_to_receive_video = 1;
+  caller()->SetOfferAnswerOptions(options);
+  caller()->CreateAndSetAndSignalOffer();
+  ASSERT_TRUE_WAIT(DtlsConnected(), kDefaultTimeout);
+
+  EXPECT_GT(customizer1->allow_channel_data_cnt_, 0u);
+  EXPECT_GT(customizer1->modify_cnt_, 0u);
+
+  EXPECT_GT(customizer2->allow_channel_data_cnt_, 0u);
+  EXPECT_GT(customizer2->modify_cnt_, 0u);
+
+  // Need to free the clients here since they're using things we created on
+  // the stack.
+  delete SetCallerPcWrapperAndReturnCurrent(nullptr);
+  delete SetCalleePcWrapperAndReturnCurrent(nullptr);
+}
+
 // Test that audio and video flow end-to-end when codec names don't use the
 // expected casing, given that they're supposed to be case insensitive. To test
 // this, all but one codec is removed from each media description, and its