Move the ICE state transition ASSERTS to a lower level.

They don't really belong in PeerConnection because the state at that
level can change when a transport channel is removed. That makes almost
any state transition possible.

The asserts are now in P2PTransportChannel (the equivalent to
IceTransport in the spec). Currently it has a reduced set of states,
that don't even take into account writability, but I plan to change
that soon.

BUG=webrtc:4757
R=pthatcher@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#12937}
diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc
index 80352cf..24eb593 100644
--- a/webrtc/api/webrtcsession.cc
+++ b/webrtc/api/webrtcsession.cc
@@ -1466,46 +1466,10 @@
     return;
   }
 
-  // ASSERT that the requested transition is allowed.  Note that
-  // WebRtcSession does not implement "kIceConnectionClosed" (that is handled
-  // within PeerConnection).  This switch statement should compile away when
-  // ASSERTs are disabled.
   LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
                << " => " << state;
-  switch (ice_connection_state_) {
-    case PeerConnectionInterface::kIceConnectionNew:
-      ASSERT(state == PeerConnectionInterface::kIceConnectionChecking);
-      break;
-    case PeerConnectionInterface::kIceConnectionChecking:
-      ASSERT(state == PeerConnectionInterface::kIceConnectionFailed ||
-             state == PeerConnectionInterface::kIceConnectionConnected);
-      break;
-    case PeerConnectionInterface::kIceConnectionConnected:
-      ASSERT(state == PeerConnectionInterface::kIceConnectionDisconnected ||
-             state == PeerConnectionInterface::kIceConnectionChecking ||
-             state == PeerConnectionInterface::kIceConnectionCompleted);
-      break;
-    case PeerConnectionInterface::kIceConnectionCompleted:
-      ASSERT(state == PeerConnectionInterface::kIceConnectionConnected ||
-             state == PeerConnectionInterface::kIceConnectionDisconnected);
-      break;
-    case PeerConnectionInterface::kIceConnectionFailed:
-      ASSERT(state == PeerConnectionInterface::kIceConnectionNew);
-      break;
-    case PeerConnectionInterface::kIceConnectionDisconnected:
-      ASSERT(state == PeerConnectionInterface::kIceConnectionChecking ||
-             state == PeerConnectionInterface::kIceConnectionConnected ||
-             state == PeerConnectionInterface::kIceConnectionCompleted ||
-             state == PeerConnectionInterface::kIceConnectionFailed);
-      break;
-    case PeerConnectionInterface::kIceConnectionClosed:
-      ASSERT(false);
-      break;
-    default:
-      ASSERT(false);
-      break;
-  }
-
+  RTC_DCHECK(ice_connection_state_ !=
+             PeerConnectionInterface::kIceConnectionClosed);
   ice_connection_state_ = state;
   if (ice_observer_) {
     ice_observer_->OnIceConnectionChange(ice_connection_state_);
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc
index f8466e2..b1de3e9 100644
--- a/webrtc/p2p/base/p2ptransportchannel.cc
+++ b/webrtc/p2p/base/p2ptransportchannel.cc
@@ -1212,6 +1212,34 @@
   if (state_ != state) {
     LOG_J(LS_INFO, this) << "Transport channel state changed from " << state_
                          << " to " << state;
+    // Check that the requested transition is allowed. Note that
+    // P2PTransportChannel does not (yet) implement a direct mapping of the ICE
+    // states from the standard; the difference is covered by
+    // TransportController and PeerConnection.
+    switch (state_) {
+      case STATE_INIT:
+        // TODO(deadbeef): Once we implement end-of-candidates signaling,
+        // we shouldn't go from INIT to COMPLETED.
+        RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED);
+        break;
+      case STATE_CONNECTING:
+        RTC_DCHECK(state == STATE_COMPLETED || state == STATE_FAILED);
+        break;
+      case STATE_COMPLETED:
+        // TODO(deadbeef): Once we implement end-of-candidates signaling,
+        // we shouldn't go from COMPLETED to CONNECTING.
+        // Though we *can* go from COMPlETED to FAILED, if consent expires.
+        RTC_DCHECK(state == STATE_CONNECTING || state == STATE_FAILED);
+        break;
+      case STATE_FAILED:
+        // TODO(deadbeef): Once we implement end-of-candidates signaling,
+        // we shouldn't go from FAILED to CONNECTING or COMPLETED.
+        RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED);
+        break;
+      default:
+        RTC_DCHECK(false);
+        break;
+    }
     state_ = state;
     SignalStateChanged(this);
   }