webrtc StunServer源码介绍

StunServer 是 WebRTC 中实现 STUN (Session Traversal Utilities for NAT) 协议服务器端逻辑的核心类。实现了 RFC 5389/8489 的核心交互逻辑,是 ICE 框架不可或缺的基础设施。

它的主要职责是监听 UDP 端口,接收客户端发出的 STUN 请求,解析消息,并根据请求类型生成相应的响应(主要是返回客户端的公网映射地址),从而帮助位于 NAT 后面的客户端发现其公共 IP 和端口。

一、角色功能

• NAT 穿透助手:STUN 协议本身不中继数据(那是 TURN 的工作),它只负责"探测"。StunServer 告诉客户端:"我从这个 IP 和端口收到了你的包",客户端由此推断出 NAT 为其分配的公网地址。

• 轻量级服务:与 TurnServer 不同,StunServer 是无状态的(Stateless)。它不需要维护会话、权限或分配中继端口,处理完一个请求即可忘记,因此性能极高,并发能力强。

二、成员介绍

1. socket (std::unique_ptr<rtc::AsyncUDPSocket>):

cpp 复制代码
class StunServer : public sigslot::has_slots<> {
 public:
  // Creates a STUN server, which will listen on the given socket.
  explicit StunServer(rtc::AsyncUDPSocket* socket);
  // Removes the STUN server from the socket and deletes the socket.
  ~StunServer() override;

 private:
  std::unique_ptr<rtc::AsyncUDPSocket> socket_;
};

• 底层 UDP Socket,绑定在特定端口(默认 3478)。

• 负责接收原始字节流并发送响应字节流。

• 在构造函数中传入,析构时销毁。

三、主要工作流程

3.1 接收数据包

这是入口函数,当 Socket 收到数据时被触发。

  1. 解析:将接收到的 buf 解析为 StunMessage 对象。

  2. 验证:检查消息格式是否合法。

  3. 路由根据 STUN 消息的类型(Method),分发到具体的处理函数:

• Binding Request -> OnBindingRequest

• Allocate Request -> OnAllocateRequest (通常用于 TURN,但 STUN 服务器可能返回错误或不支持)

• Shared Secret Request -> OnSharedSecretRequest (旧式认证机制,现已很少用)

• Send Request -> OnSendRequest (旧式机制)

3.2 处理Binding请求(OnBindingRequest)

这是最核心、最常用的功能。

  1. 获取源地址:从参数 addr 中获取客户端的源 IP 和端口(这是经过 NAT 转换后的公网地址)。

  2. 构建响应:调用 GetStunBindResponse。

• 创建一个 StunMessage 响应。

• 添加 XOR-MAPPED-ADDRESS 属性:将 addr 填入。使用 XOR 是为了防止某些 NAT 设备修改 STUN 载荷中的 IP 地址。

• 复制事务 ID(Transaction ID)以便客户端匹配请求和响应。

  1. 发送:调用 SendResponse 将包发回给 addr。

3.3 其它请求

• OnAllocateRequest: STUN 协议本身不支持分配中继资源。如果收到此请求,标准的 STUN 服务器通常会返回错误码 400 (Bad Request) 或 500 (Server Error),或者如果它是一个混合了 TURN 功能的服务器,可能会转发给 TURN 逻辑(但在纯 StunServer 实现中通常是不支持的或返回错误)。

• OnSharedSecretRequest / OnSendRequest: 这些属于旧的 STUN 规范(RFC 3489),在现代 WebRTC (RFC 5389/8489) 中已废弃。实现中通常返回错误或忽略。

3.4 发生响应(SendResponse / SendErrorResponse)

• 序列化:将 StunMessage 对象序列化为二进制字节流。

• 计算完整性:如果需要,添加 MESSAGE-INTEGRITY 或 FINGERPRINT 属性。

• UDP 发送:通过 socket_->SendTo 将数据发回给客户端的地址。

3.5 辅助方法

1。 GetStunBindResponse:

• 专门用于构造 Binding 响应的工具函数。

• 确保正确设置 XOR-MAPPED-ADDRESS,这是 NAT 穿透的关键。

  1. SendErrorResponse:

• 构造包含 ERROR-CODE 属性的 STUN 错误响应。

• 常见错误:400 (Bad Request), 401 (Unauthorized - 如果启用了认证), 500 (Server Error).

四、与TURNservice的区别

|------|----------------------------|--------------------------------|
| 特性 | StunServer | TurnServer |
| 主要功能 | 发现公网 IP/Port (NAT Mapping) | 中继媒体数据 (Relaying) |
| 状态 | 无状态 (Stateless) | 有状态 (Stateful, 维护 Allocation) |
| 资源消耗 | 极低 (仅 CPU 解析/打包) | 高 (带宽转发, Socket 维护) |
| 核心响应 | XOR-MAPPED-ADDRESS | RELAYED-ADDRESS, 数据转发 |
| 安全性 | 简单 (可选认证) | 复杂 (Permission, Channel, Auth) |
| 用途 | ICE 候选者收集阶段 | ICE 失败后的 fallback |

五、总结

StunServer 是 WebRTC P2P 连接建立过程中的第一个里程碑。

  1. 客户端向 StunServer 发送 Binding Request。

  2. StunServer 回复:"你的公网地址是 X.X.X.X:Port"。

  3. 客户端将这个地址作为 Server Reflexive Candidate (srflx) 加入 ICE 候选者列表。

  4. 如果没有这个类提供的信息,位于 NAT 后的客户端将无法告知对端如何连接自己,P2P 直连也就无从谈起。

相关推荐
换个昵称都难19 天前
webrtc peerconnection_server 模块介绍
运维·服务器·webrtc
EasyGBS19 天前
延迟直降90%!国标GB28181视频平台EasyGBS支持WebRTC WHIP推流设备接入,让万物互联更简单
音视频·webrtc
换个昵称都难20 天前
webrtc RtpRtcp模块化测试-MockRtpRtcp
webrtc
如意IT20 天前
指纹浏览器检测之BrowserScan的webrtc指纹检测和反检测
自动化·webrtc·chromium·浏览器开发
换个昵称都难20 天前
webrtc TURN 主要源码介绍
webrtc
换个昵称都难20 天前
webrtc RTC_P2P源码解析
asp.net·webrtc·p2p
数据知道21 天前
指纹浏览器:DNS 泄漏防范与 WebRTC 本地 IP 屏蔽的底层实现
爬虫·网络协议·tcp/ip·安全·webrtc·数据采集·指纹浏览器
换个昵称都难22 天前
webrtc源码解析概要介绍
webrtc
换个昵称都难22 天前
WebRTC 完整调用流程(前端纯 JS 实现,最简可运行)
webrtc