WebRTC之STUN、TURN和ICE研究

本文深入研究WebRTC中的STUN、TURN和ICE协议,通过分析源码探讨它们在建立P2P连接中的作用。首先介绍了STUN、TURN、ICE的基本概念,然后详细讲解了在WebRTC PeerConnection初始化过程中的PortAllocator和PortAllocatorSession如何工作,特别是UDPPort和StunPort的创建。最后,分析了TURN服务的TurnPort,强调了在TurnPort中username和password的重要性,指出当前WebRTC版本不支持TURN的OAuth验证。
摘要由CSDN通过智能技术生成

准备查看WebRTC源码对应以下这些文章中的协议格式深入研究一下ICE。

这三篇文章是目前我看过的最好的ICE文章:
P2P通信标准协议(一)之STUN
P2P通信标准协议(二)之TURN
P2P通信标准协议(三)之ICE

这个可以做为补充:
P2P技术详解(三):P2P技术之STUN、TURN、ICE详解


先学习上面文章的基础知识,然后开始分析WebRTC创建PeerConnection直到连接Stun和Turn的流程:

bool PeerConnection::InitializePortAllocator_n(
...
  if (ParseIceServers(configuration.servers, &stun_servers, &turn_servers) !=
...
port_allocator_->SetConfiguration(
      stun_servers, turn_servers, configuration.ice_candidate_pool_size,
      configuration.prune_turn_ports, configuration.turn_customizer,
      configuration.stun_candidate_keepalive_interval);
...
}
bool PortAllocator::SetConfiguration(
...
  stun_servers_ = stun_servers;
  turn_servers_ = turn_servers;
...
// If |candidate_pool_size_| is greater than the number of pooled sessions,
  // create new sessions.
  while (static_cast<int>(pooled_sessions_.size()) < candidate_pool_size_) {
    PortAllocatorSession* pooled_session = CreateSessionInternal("", 0, "", "");
    pooled_session->StartGettingPorts();
    pooled_sessions_.push_back(
        std::unique_ptr<PortAllocatorSession>(pooled_session));
  }
  return true;
}

PeerConnection在初始化时创建了port_allocator_,同时调用了PortAllocator::SetConfiguration把stun_servers和turn_servers存储起来。
并且调用了BasicPortAllocatorSession::StartGettingPorts()


void BasicPortAllocatorSession::StartGettingPorts() {
...
network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_START);
...
}
void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
  switch (message->message_id) {
  case MSG_CONFIG_START:
    RTC_DCHECK(rtc::Thread::Current() == network_thread_);
    GetPortConfigurations();
...
}

void BasicPortAllocatorSession::GetPortConfigurations() {
  PortConfiguration* config = new PortConfiguration(allocator_->stun_servers(),
                                                    username(),
                                                    password());

  for (const RelayServerConfig& turn_server : allocator_->turn_servers()) {
    config->AddRelay(turn_server);
  }
  ConfigReady(config);
}

void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
  network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_READY, config);
}
void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
  switch (message->message_id) {
...
  case MSG_CONFIG_READY:
    RTC_DCHECK(rtc::Thread::Current() == network_thread_);
    OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
    break;
...
}
// Adds a configuration to the list.
void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
  if (config) {
    configs_.push_back(config);
  }

  AllocatePorts();
}

// For each network, see if we have a sequence that covers it already.  If not,
// create a new sequence to create the appropriate ports.
void BasicPortAllocatorSession::DoAllocate(bool disable_equivalent) {
...
 AllocationSequence* sequence =
          new AllocationSequence(this, networks[i], config, sequence_flags);
      sequence->SignalPortAllocationComplete.connect(
          this, &BasicPortAllocatorSession::OnPortAllocationComplete);
      sequence->Init();
      sequence->Start();
      sequences_.push_back(sequence);
...
}

一路把PortConfiguration *config传进来,创建AllocationSequence* sequence,并且调用了Start()方法


void AllocationSequence::Start() {
  state_ = kRunning;
  session_->network_thread()->Post(RTC_FROM_HERE, this, MSG_ALLOCATION_PHASE);
  // Take a snapshot of the best IP, so that when DisableEquivalentPhases is
  // called next time, we enable all phases if the best IP has since changed.
  previous_best_ip_ = network_->GetBestIP();
}
void AllocationSequence::OnMessage(rtc::Message* msg) {
  RTC_DCHECK(rtc::Thread::Current() == session_->network_thread());
  RTC_DCHECK(msg->message_id == MSG_ALLOCATION_PHASE);

  const char* const PHASE_NAMES[kNumPhases] = {
  "Udp", "Relay", 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值