在WebRTC TURN客户端中,两个过程(创建权限和频道绑定请求)如下:
(1) 在
TurnEntry
构造函数中创建权限:
https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/p2p/base/turn_port.cc;l=1757
TurnEntry::TurnEntry(TurnPort* port, Connection* conn, int channel_id)
: port_(port),
channel_id_(channel_id),
ext_addr_(conn->remote_candidate().address()),
state_(STATE_UNBOUND),
connections_({conn}) {
// Creating permission for `ext_addr_`.
SendCreatePermissionRequest(0);
}
(2) 稍后发送频道绑定请求。关键词是
SendChannelBindRequest
:
https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/p2p/base/turn_port.cc;l=1817
int TurnEntry::Send(const void* data,
size_t size,
bool payload,
const rtc::PacketOptions& options) {
rtc::ByteBufferWriter buf;
if (state_ != STATE_BOUND ||
!port_->TurnCustomizerAllowChannelData(data, size, payload)) {
// If we haven't bound the channel yet, we have to use a Send Indication.
// The turn_customizer_ can also make us use Send Indication.
TurnMessage msg(TURN_SEND_INDICATION);
msg.AddAttribute(std::make_unique<StunXorAddressAttribute>(
STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
msg.AddAttribute(
std::make_unique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
port_->TurnCustomizerMaybeModifyOutgoingStunMessage(&msg);
const bool success = msg.Write(&buf);
RTC_DCHECK(success);
// If we're sending real data, request a channel bind that we can use later.
if (state_ == STATE_UNBOUND && payload) {
SendChannelBindRequest(0);
state_ = STATE_BINDING;
}
} else {
// If the channel is bound, we can send the data as a Channel Message.
buf.WriteUInt16(channel_id_);
buf.WriteUInt16(static_cast<uint16_t>(size));
buf.WriteBytes(reinterpret_cast<const char*>(data), size);
}
rtc::PacketOptions modified_options(options);
modified_options.info_signaled_after_sent.turn_overhead_bytes =
buf.Length() - size;
return port_->Send(buf.Data(), buf.Length(), modified_options);
}
根据 RFC 8656 (https://datatracker.ietf.org/doc/html/rfc8656),通道数据的开销较小(仅 4B),而指示有 36B 的开销。
为什么不只使用频道数据?我认为
SendCreatePermissionRequest
可以在SendChannelBindRequest
构造函数中替换为TurnEntry
.