WebRtc连接状态变化

WebRtc连接状态变化

  1. ICE收集完成的条件
  2. 连接状态的变化


ComputeState:一旦ICE收集完成,至少应该存在一个可用的连接
1.如果had_connection_ 为false,则状态为STATE_INIT
2.检查所有的Connection,看是否有active的
3.该函数应该是在ICE收集完成时才会调用
4.如果检查所有Connection,没有active的连接,则返回STATE_FAILED
// A channel is considered ICE completed once there is at most one active
// connection per network and at least one active connection.
IceTransportState P2PTransportChannel::ComputeState() const {
  if (!had_connection_) {
  return IceTransportState::STATE_INIT;
  }

  std::vector<Connection*> active_connections;
  for (Connection* connection : connections_) {
  if (connection->active()) {
  active_connections.push_back(connection);
  }
  }
  if (active_connections.empty()) {
  return IceTransportState::STATE_FAILED;
  }

  std::set<rtc::Network*> networks;
  for (Connection* connection : active_connections) {
  rtc::Network* network = connection->port()->Network();
  if (networks.find(network) == networks.end()) {
  networks.insert(network);
  } else {
  LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as "
  << network->ToString()
  << " has more than 1 connection.";
  return IceTransportState::STATE_CONNECTING;
  }
  }

  return IceTransportState::STATE_COMPLETED;
}





UpdateState :当一个连接被添加、删除或者任何连接改变了write state时才会被调用,以至于transport controller能够得到最新的状态。
然后,该函数不应该被调用太频繁,以防出现多个状态的改变,该函数应该在所有的状态改变后才会被调用。例如,我妈在SortConnectionsAndUpdate的最后调用。
1.首先得到当前的状态,如果当前状态和之前的状态不一样,则先判断状态转变是否合理,即不能从某种状态转变成另外一种状态
2.SingalStateChanged是产生状态改变的信号???
3.set_writable设置写的状态?应该是判断是否可以向对方发送数据???
4.set_receiving设置接受的状态?应该是判断是否可以接收对方的数据???

// Warning: UpdateState should eventually be called whenever a connection
// is added, deleted, or the write state of any connection changes so that the
// transport controller will get the up-to-date channel state. However it
// should not be called too often; in the case that multiple connection states
// change, it should be called after all the connection states have changed. For
// example, we call this at the end of SortConnectionsAndUpdateState.
void P2PTransportChannel::UpdateState() {
  IceTransportState state = ComputeState();
  if (state_ != state) {
  LOG_J(LS_INFO, this) << "Transport channel state changed from "
  << static_cast<int>(state_) << " to "
  << static_cast<int>(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 IceTransportState::STATE_INIT:
  // TODO(deadbeef): Once we implement end-of-candidates signaling,
  // we shouldn't go from INIT to COMPLETED.
  RTC_DCHECK(state == IceTransportState::STATE_CONNECTING ||
  state == IceTransportState::STATE_COMPLETED);
  break;
  case IceTransportState::STATE_CONNECTING:
  RTC_DCHECK(state == IceTransportState::STATE_COMPLETED ||
  state == IceTransportState::STATE_FAILED);
  break;
  case IceTransportState::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 == IceTransportState::STATE_CONNECTING ||
  state == IceTransportState::STATE_FAILED);
  break;
  case IceTransportState::STATE_FAILED:
  // TODO(deadbeef): Once we implement end-of-candidates signaling,
  // we shouldn't go from FAILED to CONNECTING or COMPLETED.
  RTC_DCHECK(state == IceTransportState::STATE_CONNECTING ||
  state == IceTransportState::STATE_COMPLETED);
  break;
  default:
  RTC_NOTREACHED();
  break;
  }
  state_ = state;
  SignalStateChanged(this);
  }

  // If our selected connection is "presumed writable" (TURN-TURN with no
  // CreatePermission required), act like we're already writable to the upper
  // layers, so they can start media quicker.
  bool writable =
  selected_connection_ && (selected_connection_->writable() ||
  PresumedWritable(selected_connection_));
  set_writable(writable);

  bool receiving = false;
  for (const Connection* connection : connections_) {
  if (connection->receiving()) {
  receiving = true;
  break;
  }
  }
  set_receiving(receiving);
}



SortConnectionsAndUpdateState:对可用的连接进行排序,找到最合适的连接。我们会监控这个可用连接数的变化以及当前的状态。
1.

// Sort the available connections to find the best one. We also monitor
// the number of available connections and the current state.
void P2PTransportChannel::SortConnectionsAndUpdateState() {
  RTC_DCHECK(network_thread_ == rtc::Thread::Current());

  // Make sure the connection states are up-to-date since this affects how they
  // will be sorted.
  UpdateConnectionStates();

  // Any changes after this point will require a re-sort.
  sort_dirty_ = false;

  // Find the best alternative connection by sorting. It is important to note
  // that amongst equal preference, writable connections, this will choose the
  // one whose estimated latency is lowest. So it is the only one that we
  // need to consider switching to.
  // TODO(honghaiz): Don't sort; Just use std::max_element in the right places.
  std::stable_sort(connections_.begin(), connections_.end(),
  [this](const Connection* a, const Connection* b) {
  int cmp = CompareConnections(
  a, b, rtc::Optional<int64_t>(), nullptr);
  if (cmp != 0) {
  return cmp > 0;
  }
  // Otherwise, sort based on latency estimate.
  return a->rtt() < b->rtt();
  });

  LOG(LS_VERBOSE) << "Sorting " << connections_.size()
  << " available connections:";
  for (size_t i = 0; i < connections_.size(); ++i) {
  LOG(LS_VERBOSE) << connections_[i]->ToString();
  }

  Connection* top_connection =
  (connections_.size() > 0) ? connections_[0] : nullptr;

  // If necessary, switch to the new choice. Note that |top_connection| doesn't
  // have to be writable to become the selected connection although it will
  // have higher priority if it is writable.
  MaybeSwitchSelectedConnection(top_connection, "sorting");

  // The controlled side can prune only if the selected connection has been
  // nominated because otherwise it may prune the connection that will be
  // selected by the controlling side.
  // TODO(honghaiz): This is not enough to prevent a connection from being
  // pruned too early because with aggressive nomination, the controlling side
  // will nominate every connection until it becomes writable.
  if (ice_role_ == ICEROLE_CONTROLLING ||
  (selected_connection_ && selected_connection_->nominated())) {
  PruneConnections();
  }

  // Check if all connections are timedout.
  bool all_connections_timedout = true;
  for (size_t i = 0; i < connections_.size(); ++i) {
  if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
  all_connections_timedout = false;
  break;
  }
  }

  // Now update the writable state of the channel with the information we have
  // so far.
  if (all_connections_timedout) {
  HandleAllTimedOut();
  }

  // Update the state of this channel.
  UpdateState();

  // Also possibly start pinging.
  // We could start pinging if:
  // * The first connection was created.
  // * ICE credentials were provided.
  // * A TCP connection became connected.
  MaybeStartPinging();
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值