Add the last_sent_packet_id to the candidate pair change signal
so that the call knows which packet ids were sent on the previous candidate pair.
Note that packet_id is actually 16bits, so we can use -1 for values that are not set.

Also moved the tests for candidate pair changes to TestSelectConnectionBeforeNomination.

BUG=
R=deadbeef@webrtc.org, pthatcher@webrtc.org

Review URL: https://codereview.webrtc.org/1842093002 .

Cr-Commit-Position: refs/heads/master@{#12184}
diff --git a/webrtc/base/networkroute.h b/webrtc/base/networkroute.h
index dcf9015..95c1c08 100644
--- a/webrtc/base/networkroute.h
+++ b/webrtc/base/networkroute.h
@@ -21,16 +21,24 @@
   bool connected;
   uint16_t local_network_id;
   uint16_t remote_network_id;
+  int last_sent_packet_id;  // Last packet id sent on the PREVIOUS route.
 
   NetworkRoute()
-      : connected(false), local_network_id(0), remote_network_id(0) {}
+      : connected(false),
+        local_network_id(0),
+        remote_network_id(0),
+        last_sent_packet_id(-1) {}
 
   // The route is connected if the local and remote network ids are provided.
-  NetworkRoute(uint16_t local_net_id, uint16_t remote_net_id)
+  NetworkRoute(uint16_t local_net_id,
+               uint16_t remote_net_id,
+               int last_packet_id)
       : connected(true),
         local_network_id(local_net_id),
-        remote_network_id(remote_net_id) {}
+        remote_network_id(remote_net_id),
+        last_sent_packet_id(last_packet_id) {}
 
+  // |last_sent_packet_id| does not affect the NetworkRoute comparison.
   bool operator==(const NetworkRoute& nr) const {
     return connected == nr.connected &&
            local_network_id == nr.local_network_id &&
diff --git a/webrtc/p2p/base/dtlstransportchannel.cc b/webrtc/p2p/base/dtlstransportchannel.cc
index 2006391..667b2c8 100644
--- a/webrtc/p2p/base/dtlstransportchannel.cc
+++ b/webrtc/p2p/base/dtlstransportchannel.cc
@@ -638,9 +638,11 @@
 
 void DtlsTransportChannelWrapper::OnSelectedCandidatePairChanged(
     TransportChannel* channel,
-    CandidatePairInterface* selected_candidate_pair) {
+    CandidatePairInterface* selected_candidate_pair,
+    int last_sent_packet_id) {
   ASSERT(channel == channel_);
-  SignalSelectedCandidatePairChanged(this, selected_candidate_pair);
+  SignalSelectedCandidatePairChanged(this, selected_candidate_pair,
+                                     last_sent_packet_id);
 }
 
 void DtlsTransportChannelWrapper::OnConnectionRemoved(
diff --git a/webrtc/p2p/base/dtlstransportchannel.h b/webrtc/p2p/base/dtlstransportchannel.h
index 0c6b303..96ea29f 100644
--- a/webrtc/p2p/base/dtlstransportchannel.h
+++ b/webrtc/p2p/base/dtlstransportchannel.h
@@ -218,7 +218,8 @@
   void OnRouteChange(TransportChannel* channel, const Candidate& candidate);
   void OnSelectedCandidatePairChanged(
       TransportChannel* channel,
-      CandidatePairInterface* selected_candidate_pair);
+      CandidatePairInterface* selected_candidate_pair,
+      int last_sent_packet_id);
   void OnConnectionRemoved(TransportChannelImpl* channel);
   void Reconnect();
 
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc
index fbac247..6653241 100644
--- a/webrtc/p2p/base/p2ptransportchannel.cc
+++ b/webrtc/p2p/base/p2ptransportchannel.cc
@@ -983,6 +983,7 @@
     return -1;
   }
 
+  last_sent_packet_id_ = options.packet_id;
   int sent = best_connection_->Send(data, len, options);
   if (sent <= 0) {
     ASSERT(sent < 0);
@@ -1176,7 +1177,8 @@
   }
   // TODO(honghaiz): rename best_connection_ with selected_connection_ or
   // selected_candidate pair_.
-  SignalSelectedCandidatePairChanged(this, best_connection_);
+  SignalSelectedCandidatePairChanged(this, best_connection_,
+                                     last_sent_packet_id_);
 }
 
 // Warning: UpdateState should eventually be called whenever a connection
diff --git a/webrtc/p2p/base/p2ptransportchannel.h b/webrtc/p2p/base/p2ptransportchannel.h
index 23e4d7f..5be9d04 100644
--- a/webrtc/p2p/base/p2ptransportchannel.h
+++ b/webrtc/p2p/base/p2ptransportchannel.h
@@ -326,6 +326,7 @@
   int weak_ping_interval_ = WEAK_PING_INTERVAL;
   TransportChannelState state_ = TransportChannelState::STATE_INIT;
   IceConfig config_;
+  int last_sent_packet_id_ = -1;  // -1 indicates no packet was sent before.
 
   RTC_DISALLOW_COPY_AND_ASSIGN(P2PTransportChannel);
 };
diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
index e2ec44e..87e92a5 100644
--- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc
+++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
@@ -317,8 +317,6 @@
         this, &P2PTransportChannelTestBase::OnReadPacket);
     channel->SignalRoleConflict.connect(
         this, &P2PTransportChannelTestBase::OnRoleConflict);
-    channel->SignalSelectedCandidatePairChanged.connect(
-        this, &P2PTransportChannelTestBase::OnSelectedCandidatePairChanged);
     channel->SetIceCredentials(local_ice_ufrag, local_ice_pwd);
     if (clear_remote_candidates_ufrag_pwd_) {
       // This only needs to be set if we're clearing them from the
@@ -566,7 +564,7 @@
 
   void TestSendRecv(int channels) {
     for (int i = 0; i < 10; ++i) {
-    const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+      const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
       int len = static_cast<int>(strlen(data));
       // local_channel1 <==> remote_channel1
       EXPECT_EQ_WAIT(len, SendData(ep1_ch1(), data, len), 1000);
@@ -744,12 +742,6 @@
     channel->SetIceRole(new_role);
   }
 
-  void OnSelectedCandidatePairChanged(
-      cricket::TransportChannel* channel,
-      cricket::CandidatePairInterface* candidate_pair) {
-    ++num_selected_candidate_pair_changes_;
-  }
-
   int SendData(cricket::TransportChannel* channel,
                const char* data, size_t len) {
     rtc::PacketOptions options;
@@ -803,13 +795,6 @@
     force_relay_ = relay;
   }
 
-  int num_selected_candidate_pair_changes() {
-    return num_selected_candidate_pair_changes_;
-  }
-  void set_num_selected_candidate_pair_changes(int num) {
-    num_selected_candidate_pair_changes_ = num;
-  }
-
  private:
   rtc::Thread* main_;
   rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
@@ -824,7 +809,6 @@
   rtc::SocksProxyServer socks_server2_;
   Endpoint ep1_;
   Endpoint ep2_;
-  int num_selected_candidate_pair_changes_ = 0;
   bool clear_remote_candidates_ufrag_pwd_;
   bool force_relay_;
 };
@@ -1595,9 +1579,8 @@
   Test(kLocalUdpToLocalUdp);
 }
 
-// Test that we can quickly switch links if an interface goes down. This also
-// tests that when the link switches, |SignalSelectedCandidatePairChanged| will
-// be fired. The controlled side has two interfaces and one will die.
+// Test that we can quickly switch links if an interface goes down.
+// The controlled side has two interfaces and one will die.
 TEST_F(P2PTransportChannelMultihomedTest, TestFailoverControlledSide) {
   AddAddress(0, kPublicAddrs[0]);
   // Adding alternate address will make sure |kPublicAddrs| has the higher
@@ -1625,7 +1608,6 @@
   ep1_ch1()->SetIceConfig(config);
   ep2_ch1()->SetIceConfig(config);
 
-  set_num_selected_candidate_pair_changes(0);
   // Blackhole any traffic to or from the public addrs.
   LOG(LS_INFO) << "Failing over...";
   fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, kPublicAddrs[1]);
@@ -1646,15 +1628,12 @@
       RemoteCandidate(ep1_ch1())->address().EqualIPs(kAlternateAddrs[1]));
   EXPECT_TRUE(
       LocalCandidate(ep2_ch1())->address().EqualIPs(kAlternateAddrs[1]));
-  // It should have changed twice, one on each side.
-  EXPECT_EQ(2, num_selected_candidate_pair_changes());
 
   DestroyChannels();
 }
 
-// Test that we can quickly switch links if an interface goes down. This also
-// tests that when the link switches, |SignalSelectedCandidatePairChanged| will
-// be fired. The controlling side has two interfaces and one will die.
+// Test that we can quickly switch links if an interface goes down.
+// The controlling side has two interfaces and one will die.
 TEST_F(P2PTransportChannelMultihomedTest, TestFailoverControllingSide) {
   // Adding alternate address will make sure |kPublicAddrs| has the higher
   // priority than others. This is due to FakeNetwork::AddInterface method.
@@ -1680,7 +1659,6 @@
   cricket::IceConfig config = CreateIceConfig(1000, false);
   ep1_ch1()->SetIceConfig(config);
   ep2_ch1()->SetIceConfig(config);
-  set_num_selected_candidate_pair_changes(0);
 
   // Blackhole any traffic to or from the public addrs.
   LOG(LS_INFO) << "Failing over...";
@@ -1702,7 +1680,6 @@
   EXPECT_TRUE(RemoteCandidate(ep1_ch1())->address().EqualIPs(kPublicAddrs[1]));
   EXPECT_TRUE(
       RemoteCandidate(ep2_ch1())->address().EqualIPs(kAlternateAddrs[0]));
-  EXPECT_EQ(2, num_selected_candidate_pair_changes());
 
   DestroyChannels();
 }
@@ -1920,6 +1897,8 @@
     ch->SetIceRole(cricket::ICEROLE_CONTROLLING);
     ch->SetIceCredentials(kIceUfrag[0], kIcePwd[0]);
     ch->SetRemoteIceCredentials(kIceUfrag[1], kIcePwd[1]);
+    ch->SignalSelectedCandidatePairChanged.connect(
+        this, &P2PTransportChannelPingTest::OnSelectedCandidatePairChanged);
     ch->SignalReadyToSend.connect(this,
                                   &P2PTransportChannelPingTest::OnReadyToSend);
   }
@@ -1971,10 +1950,31 @@
     return conn;
   }
 
+  int SendData(cricket::TransportChannel& channel,
+               const char* data,
+               size_t len,
+               int packet_id) {
+    rtc::PacketOptions options;
+    options.packet_id = packet_id;
+    return channel.SendPacket(data, len, options, 0);
+  }
+
+  void OnSelectedCandidatePairChanged(
+      cricket::TransportChannel* transport_channel,
+      cricket::CandidatePairInterface* selected_candidate_pair,
+      int last_sent_packet_id) {
+    last_selected_candidate_pair_ = selected_candidate_pair;
+    last_sent_packet_id_ = last_sent_packet_id;
+  }
+
   void OnReadyToSend(cricket::TransportChannel* channel) {
     channel_ready_to_send_ = true;
   }
 
+  cricket::CandidatePairInterface* last_selected_candidate_pair() {
+    return last_selected_candidate_pair_;
+  }
+  int last_sent_packet_id() { return last_sent_packet_id_; }
   bool channel_ready_to_send() { return channel_ready_to_send_; }
   void reset_channel_ready_to_send() { channel_ready_to_send_ = false; }
 
@@ -1982,6 +1982,8 @@
   rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
   rtc::scoped_ptr<rtc::VirtualSocketServer> vss_;
   rtc::SocketServerScope ss_scope_;
+  cricket::CandidatePairInterface* last_selected_candidate_pair_ = nullptr;
+  int last_sent_packet_id_ = -1;
   bool channel_ready_to_send_ = false;
 };
 
@@ -2172,8 +2174,9 @@
 // The controlled side will select a connection as the "best connection" based
 // on priority until the controlling side nominates a connection, at which
 // point the controlled side will select that connection as the
-// "best connection". Plus, the channel will fire SignalReadyToSend if the new
-// best connection is writable.
+// "best connection". Plus, SignalSelectedCandidatePair will be fired if the
+// best connection changes and SignalReadyToSend will be fired if the new best
+// connection is writable.
 TEST_F(P2PTransportChannelPingTest, TestSelectConnectionBeforeNomination) {
   cricket::FakePortAllocator pa(rtc::Thread::Current(), nullptr);
   cricket::P2PTransportChannel ch("receiving state change", 1, &pa);
@@ -2185,20 +2188,29 @@
   cricket::Connection* conn1 = WaitForConnectionTo(&ch, "1.1.1.1", 1);
   ASSERT_TRUE(conn1 != nullptr);
   EXPECT_EQ(conn1, ch.best_connection());
-  // Channel is not ready because it is not writable.
+  EXPECT_EQ(conn1, last_selected_candidate_pair());
+  EXPECT_EQ(-1, last_sent_packet_id());
+  // Channel is not ready to send because it is not writable.
   EXPECT_FALSE(channel_ready_to_send());
 
+  int last_packet_id = 0;
+  const char* data = "ABCDEFGH";
+  int len = static_cast<int>(strlen(data));
+  SendData(ch, data, len, ++last_packet_id);
   // When a higher priority candidate comes in, the new connection is chosen
   // as the best connection.
   ch.AddRemoteCandidate(CreateHostCandidate("2.2.2.2", 2, 10));
   cricket::Connection* conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2);
   ASSERT_TRUE(conn2 != nullptr);
   EXPECT_EQ(conn2, ch.best_connection());
+  EXPECT_EQ(conn2, last_selected_candidate_pair());
+  EXPECT_EQ(last_packet_id, last_sent_packet_id());
   EXPECT_FALSE(channel_ready_to_send());
 
   // If a stun request with use-candidate attribute arrives, the receiving
   // connection will be set as the best connection, even though
   // its priority is lower.
+  SendData(ch, data, len, ++last_packet_id);
   ch.AddRemoteCandidate(CreateHostCandidate("3.3.3.3", 3, 1));
   cricket::Connection* conn3 = WaitForConnectionTo(&ch, "3.3.3.3", 3);
   ASSERT_TRUE(conn3 != nullptr);
@@ -2210,11 +2222,14 @@
   conn3->set_nominated(true);
   conn3->SignalNominated(conn3);
   EXPECT_EQ(conn3, ch.best_connection());
+  EXPECT_EQ(conn3, last_selected_candidate_pair());
+  EXPECT_EQ(last_packet_id, last_sent_packet_id());
   EXPECT_TRUE(channel_ready_to_send());
 
   // Even if another higher priority candidate arrives,
   // it will not be set as the best connection because the best connection
   // is nominated by the controlling side.
+  SendData(ch, data, len, ++last_packet_id);
   ch.AddRemoteCandidate(CreateHostCandidate("4.4.4.4", 4, 100));
   cricket::Connection* conn4 = WaitForConnectionTo(&ch, "4.4.4.4", 4);
   ASSERT_TRUE(conn4 != nullptr);
@@ -2229,6 +2244,8 @@
   // The best connection switches after conn4 becomes writable.
   conn4->ReceivedPingResponse();
   EXPECT_EQ(conn4, ch.best_connection());
+  EXPECT_EQ(conn4, last_selected_candidate_pair());
+  EXPECT_EQ(last_packet_id, last_sent_packet_id());
   // SignalReadyToSend is fired again because conn4 is writable.
   EXPECT_TRUE(channel_ready_to_send());
 }
diff --git a/webrtc/p2p/base/transportchannel.h b/webrtc/p2p/base/transportchannel.h
index 0dba02f..d21d607 100644
--- a/webrtc/p2p/base/transportchannel.h
+++ b/webrtc/p2p/base/transportchannel.h
@@ -155,8 +155,9 @@
 
   // Signalled when the current selected candidate pair has changed.
   // The first parameter is the transport channel that signals the event.
-  // The second parameter is the new selected candidate pair.
-  sigslot::signal2<TransportChannel*, CandidatePairInterface*>
+  // The second parameter is the new selected candidate pair. The third
+  // parameter is the last packet id sent on the previous candidate pair.
+  sigslot::signal3<TransportChannel*, CandidatePairInterface*, int>
       SignalSelectedCandidatePairChanged;
 
   // Invoked when the channel is being destroyed.
diff --git a/webrtc/p2p/quic/quictransportchannel.cc b/webrtc/p2p/quic/quictransportchannel.cc
index 7e68612..cc0576d 100644
--- a/webrtc/p2p/quic/quictransportchannel.cc
+++ b/webrtc/p2p/quic/quictransportchannel.cc
@@ -391,9 +391,11 @@
 
 void QuicTransportChannel::OnSelectedCandidatePairChanged(
     TransportChannel* channel,
-    CandidatePairInterface* selected_candidate_pair) {
+    CandidatePairInterface* selected_candidate_pair,
+    int last_sent_packet_id) {
   ASSERT(channel == channel_);
-  SignalSelectedCandidatePairChanged(this, selected_candidate_pair);
+  SignalSelectedCandidatePairChanged(this, selected_candidate_pair,
+                                     last_sent_packet_id);
 }
 
 void QuicTransportChannel::OnConnectionRemoved(TransportChannelImpl* channel) {
diff --git a/webrtc/p2p/quic/quictransportchannel.h b/webrtc/p2p/quic/quictransportchannel.h
index a3c0106..ab02c77 100644
--- a/webrtc/p2p/quic/quictransportchannel.h
+++ b/webrtc/p2p/quic/quictransportchannel.h
@@ -232,7 +232,8 @@
   void OnRouteChange(TransportChannel* channel, const Candidate& candidate);
   void OnSelectedCandidatePairChanged(
       TransportChannel* channel,
-      CandidatePairInterface* selected_candidate_pair);
+      CandidatePairInterface* selected_candidate_pair,
+      int last_sent_packet_id);
   void OnConnectionRemoved(TransportChannelImpl* channel);
 
   // Callbacks for |quic_|.
diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc
index 25ba2c0..b76d7bd 100644
--- a/webrtc/pc/channel.cc
+++ b/webrtc/pc/channel.cc
@@ -509,13 +509,15 @@
 
 void BaseChannel::OnSelectedCandidatePairChanged(
     TransportChannel* channel,
-    CandidatePairInterface* selected_candidate_pair) {
+    CandidatePairInterface* selected_candidate_pair,
+    int last_sent_packet_id) {
   ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
   NetworkRoute network_route;
   if (selected_candidate_pair) {
     network_route =
         NetworkRoute(selected_candidate_pair->local_candidate().network_id(),
-                     selected_candidate_pair->remote_candidate().network_id());
+                     selected_candidate_pair->remote_candidate().network_id(),
+                     last_sent_packet_id);
   }
   media_channel()->OnNetworkRouteChanged(channel->transport_name(),
                                          network_route);
diff --git a/webrtc/pc/channel.h b/webrtc/pc/channel.h
index e22196c..e05b6e5 100644
--- a/webrtc/pc/channel.h
+++ b/webrtc/pc/channel.h
@@ -209,7 +209,8 @@
 
   void OnSelectedCandidatePairChanged(
       TransportChannel* channel,
-      CandidatePairInterface* selected_candidate_pair);
+      CandidatePairInterface* selected_candidate_pair,
+      int last_sent_packet_id);
 
   bool PacketIsRtcp(const TransportChannel* channel, const char* data,
                     size_t len);
diff --git a/webrtc/pc/channel_unittest.cc b/webrtc/pc/channel_unittest.cc
index 9d20def..a423842 100644
--- a/webrtc/pc/channel_unittest.cc
+++ b/webrtc/pc/channel_unittest.cc
@@ -970,7 +970,7 @@
     media_channel1_->set_num_network_route_changes(0);
     // The transport channel becomes disconnected.
     transport_channel1->SignalSelectedCandidatePairChanged(transport_channel1,
-                                                           nullptr);
+                                                           nullptr, -1);
     EXPECT_EQ(1, media_channel1_->num_network_route_changes());
     EXPECT_FALSE(media_channel1->last_network_route().connected);
 
@@ -980,14 +980,18 @@
     rtc::SocketAddress remote_address("192.168.1.2", 2000 /* port number */);
     uint16_t local_net_id = 1;
     uint16_t remote_net_id = 2;
+    int last_packet_id = 100;
     rtc::scoped_ptr<cricket::CandidatePairInterface> candidate_pair(
         transport_controller1_.CreateFakeCandidatePair(
             local_address, local_net_id, remote_address, remote_net_id));
     transport_channel1->SignalSelectedCandidatePairChanged(
-        transport_channel1, candidate_pair.get());
+        transport_channel1, candidate_pair.get(), last_packet_id);
     EXPECT_EQ(1, media_channel1_->num_network_route_changes());
-    cricket::NetworkRoute expected_network_route(local_net_id, remote_net_id);
+    cricket::NetworkRoute expected_network_route(local_net_id, remote_net_id,
+                                                 last_packet_id);
     EXPECT_EQ(expected_network_route, media_channel1->last_network_route());
+    EXPECT_EQ(last_packet_id,
+              media_channel1->last_network_route().last_sent_packet_id);
   }
 
   // Test setting up a call.