Performs the allocation of ports, in a sequenced (timed) manner, for a given network and IP address.
按照顺序(定时)的方式为给定的网络和 IP 地址执行端口分配
阅读本文之后你将了解到:1、AllocationSequence的作用是什么?
2、何时创建 AllocationSequence?
3、AllocationSequence 有哪些相关类?相互关系是什么?
4、数据流转方向?
类图
重要的成员变量:
-
network_:一个AllocationSequence持有一个 Network 对象,一一对应
-
session_:在BasicPortAllocatorSession中创建的AllocationSequence,sequence 创建 port 成功的通知要回调给BasicPortAllocatorSession
-
config_:PortConfiguration,创建 port 需要username、password等一些基本信息
-
udp_socket_:创建具体的udp socket,并且socket 的数据也会回调到 sequence
-
udp_port_: 每个 AllocationSequence 对象持有一个 UDPPort 对象,一一对应
-
state_:AllocationSequence 有个状态机:kInit --> kRunning --> {kCompleted|kStopped}
-
phase_:M146 中由
Process()根据phase_依次执行PHASE_UDP -> PHASE_RELAY -> PHASE_TCP。 -
epoch_:
Start/Stop/Clear期间用来丢弃旧 task,避免已经停止的 sequence 继续执行旧的Process()。
触发堆栈
BasicPortAllocatorSession::DoAllocate 函数遍历 Networks数组,为每一个Network 创建AllocationSequence对象
之后AllocationSequence创建 udp socket和 udpport
-
BasicPortAllocatorSession::OnAllocate
-
BasicPortAllocatorSession::DoAllocate
-
new AllocationSequence // 构造 sequence
-
AllocationSequence::Init // 创建 udp socket。参考 webrtc 之物理 socket 的创建
PORTALLOCATOR_ENABLE_SHARED_SOCKET默认开启时,一个 sequence 会优先创建一个共享 UDP socket,并把 socket 收包回调注册到AllocationSequence::OnReadPacket。
-
AllocationSequence::Start // 投递 Process task,分阶段创建 port 对象,尤其是 UDPPort
-
-
AllocationSequence::Start()
M146 中该函数直接在 network thread 上投递
Process(epoch)task,用于触发创建 port 对象。
c++
void AllocationSequence::Start() {
state_ = kRunning;
session_->network_thread()->PostTask(
SafeTask(safety_.flag(), [this, epoch = epoch_] { Process(epoch); }));
previous_best_ip_ = network_->GetBestIP();
}
AllocationSequence::Process()
M146 中阶段推进入口是
Process()。Process()按照 "Udp"、"Relay"、"Tcp" 的顺序挨个调用创建相应 port 对象。但并不是所有相应的 port 对象都会被创建。
c++
void AllocationSequence::Process(int epoch) {
if (epoch != epoch_) {
return;
}
switch (phase_) {
case PHASE_UDP:
CreateUDPPorts();
CreateStunPorts();
break;
case PHASE_RELAY:
CreateRelayPorts();
break;
case PHASE_TCP:
CreateTCPPorts();
state_ = kCompleted;
break;
}
if (state() == kRunning) {
++phase_;
session_->network_thread()->PostDelayedTask(
SafeTask(safety_.flag(), [this, epoch = epoch_] { Process(epoch); }),
TimeDelta::Millis(session_->allocator()->step_delay()));
} else {
++epoch_;
port_allocation_complete_callback_();
}
}
-
case PHASE_UDP:
-
CreateUDPPorts();
-
UDPPort::Create // 创建 UDPPort 对象
-
BasicPortAllocatorSession::AddAllocatedPort // 把创建完成的port 对象加入到session的ports数组中
-
这里主要是设置回调函数,比如 port 收集完 candidate 后回调 session 的 OnCandidateReady 函数
-
UDPPort::PrepareAddress()
-
UDPPort::OnLocalAddressReady
-
UDPPort::MaybeSetDefaultLocalAddress
-
Port::AddAddress
-
**Candidate() // 构造Candidate对象。参考 webrtc 之 ice 建联 **
-
Port::FinishAddingAddress
-
Port::SignalCandidateReady / SubscribeCandidateReadyCallback
- 通过 BasicPortAllocatorSession 注册的 callback 调用 OnCandidateReady
-
UDPPort::PostAddAddress
-
UDPPort::MaybeSetPortCompleteOrError
- 发送 port 创建成功或失败的通知给BasicPortAllocatorSession
-
-
-
-
UDPPort::MaybePrepareStunCandidate
-
-
-
-
-
CreateStunPorts();
-
首先会检查是否配置了:PORTALLOCATOR_DISABLE_STUN,即禁止创建 STUN Port
-
再检查是否开启了共享 socket:PORTALLOCATOR_ENABLE_SHARED_SOCKET,也就是使用已存在的 udp socket,这个默认是开启的,则无需再创建 stunport
-
StunPort 继承 UDPPort,构造函数仅仅多了一个 ServerAddresses,也就是stun 服务器的地址,一般都是空的。
-
-
Break;
-
-
case PHASE_RELAY:
-
CreateRelayPorts();
-
break;
-
-
case PHASE_TCP:
-
CreateTCPPorts();
-
该函数内部首先会检查是否配置了:PORTALLOCATOR_DISABLE_TCP,也就是禁用 TCP ports
-
如果没有禁用则创建 TCPPort 对象,在 TCPPort 内部会创建 TCP socket。
-
-
state_ = kCompleted;
-
break;
-
总结:
-
AllocationSequence的作用:
- AllocationSequence 能创建 UDPPort、StunPort、RelayPort 和 TCPPort,而 candidate 又是在这些 port 中创建的。candidate 创建完成后,port 通过 BasicPortAllocatorSession 注册的 callback 回调 session,所以总体来说 AllocationSequence 就是封装了这几类 Port 对象的创建过程,便于 session 调用。
-
何时创建 AllocationSequence?
- M146 中是 BasicPortAllocatorSession::OnAllocate 调用 DoAllocate 时触发创建,遍历 Networks 数组,依次创建 sequence 对象,每个 sequence 对象持有一个 network 对象,每个 sequence 对象也持有当前的 session 对象。
-
AllocationSequence 有哪些相关类?相互关系是什么?
-
和 sequence 相关的类是:BasicPortAllocatorSession 和 UDPPort。
-
BasicPortAllocatorSession 创建 sequence 对象,创建完后加入到sequences_数组中。
-
sequence 对象又持有该 session,为的是在 sequence 里面创建了 UDPPort 对象后,把 udpport 对象加入到 session 的 ports_ 数组中。
-
sequence 的 start 函数开始触发创建 UDPPort,port 创建完成会回调给 session 的OnPortAllocationComplete
-
UDPPort 类中会创建具体的 candidate 对象,port 对象会把 OnCandidateReady、OnPortComplete、OnPortDestroyed、OnPortError回调给 session。
-
-
数据流转方向?
-
SocketDispatcher::OnEvent
-
AsyncUDPSocket::OnReadEvent
-
AllocationSequence::OnReadPacket
-
UDPPort::HandleIncomingPacket
-
UDPPort::OnReadPacket
-
Connection::OnReadPacket
-
P2PTransportChannel::OnReadPacket
-
DtlsTransport::OnReadPacket
-
RtpTransport::OnReadPacket
-
RtpTransport::OnRtpPacketReceived RTP 包
-
RtpTransport::OnRtcpPacketReceived RTCP 包
-
-
-
-
-
-
-
-
-