WebRTC的ICE之TURN協議的交互流程中繼轉發Relay媒體數據的turnserver的測試

WebRTC的ICE之TURN協議的交互流程和中繼轉發Relay媒體數據的turnserver的測試

WebRTC的ICE之TURN協議的交互流程中繼轉發Relay媒體數據的turnserver的測試

  • WebRTC的ICE之TURN協議的交互流程和中繼轉發Relay媒體數據的turnserver的測試
  • 前言
  • 一、TURN協議
    • 1、連接Turn Server 流程
      • ① 抓包交換流程圖
      • ② TURN協議格式解析
        • 協議基礎與消息結構
        • 關鍵方法類型
        • 核心屬性類型
        • 錯誤碼與狀態?
        • 數據傳輸機制?
      • ③ 發送Allocate Request UDP 信息包信息
        • 再次發送 Allocate Request UDP 包 帶上 協議、用戶名和sha-1(user:realm:paasword)簽名
      • ④ 發送CreatePermission Request
      • 發送數據Send Indication
      • 接收 Data Indiaction
      • ⑤ Channel-Bind Request
        • 發送數據 ChannelData Message
    • 2、 TURN測試Demo
    • 二 、 iceCandidate收集的時機有兩種
      • 1、創建PeerConnection對象傳入的參數ice_candidate_pool_size大于0會創建連接池的個數, 如果沒有不會創建連接池ICE的速度就會有點慢
      • 2、 設置sdp時獲取 iceCandidate
  • 總結


前言

TURN協議:文檔RFC5766

文檔中TURN協議工作原理圖

                                     Peer AServer-Reflexive    +---------+Transport Address   |         |192.0.2.150:32102   |         ||              /|         |TURN              |            / ^|  Peer A |Client's              Server            |           /  ||         |Host Transport        Transport         |         //   ||         |Address               Address           |       //     |+---------+10.1.1.2:49721       192.0.2.15:3478     |+-+  //     Peer A|               |               ||N| /       Host Transport|   +-+         |               ||A|/        Address|   | |         |               v|T|     192.168.100.2:49582|   | |         |               /+-++---------+|   | |         |+---------+   /              +---------+|         ||   |N|         ||         | //               |         || TURN    |v   | |         v| TURN    |/                 |         || Client  |----|A|----------| Server  |------------------|  Peer B ||         |    | |^         |         |^                ^|         ||         |    |T||         |         ||                ||         |+---------+    | ||         +---------+|                |+---------+| ||                    |                || ||                    |                |+-+|                    |                ||                    |                ||                    |                |Client's                   |            Peer BServer-Reflexive    Relayed             TransportTransport Address   Transport Address   Address192.0.2.1:7000      192.0.2.15:50000     192.0.2.210:49191

WebRTC中走中繼Relay 調用流程圖

在這里插入圖片描述

一、TURN協議

TURN                                 TURN           Peer          Peerclient                               server          A             B|-- Allocate request --------------->|             |             ||                                    |             |             ||<--------------- Allocate failure --|             |             ||                 (401 Unauthorized) |             |             ||                                    |             |             ||-- Allocate request --------------->|             |             ||                                    |             |             ||<---------- Allocate success resp --|             |             ||            (192.0.2.15:50000)      |             |             |//                                   //            //            //|                                    |             |             ||-- Refresh request ---------------->|             |             ||                                    |             |             ||<----------- Refresh success resp --|             |             ||                                    |             |             |
TURN                                 TURN           Peer          Peerclient                               server          A             B|                                    |             |             ||-- CreatePermission req (Peer A) -->|             |             ||<-- CreatePermission success resp --|             |             ||                                    |             |             ||--- Send ind (Peer A)-------------->|             |             ||                                    |=== data ===>|             ||                                    |             |             ||                                    |<== data ====|             ||<-------------- Data ind (Peer A) --|             |             ||                                    |             |             ||                                    |             |             ||--- Send ind (Peer B)-------------->|             |             ||                                    | dropped     |             ||                                    |             |             ||                                    |<== data ==================||                            dropped |             |             ||                                    |             |             |
--------------------------------------------------------------------------------------

TURN                                 TURN           Peer          Peerclient                               server          A             B|                                    |             |             ||-- ChannelBind req ---------------->|             |             || (Peer A to 0x4001)                 |             |             ||                                    |             |             ||<---------- ChannelBind succ resp --|             |             ||                                    |             |             ||-- [0x4001] data ------------------>|             |             ||                                    |=== data ===>|             ||                                    |             |             ||                                    |<== data ====|             ||<------------------ [0x4001] data --|             |             ||                                    |             |             ||--- Send ind (Peer A)-------------->|             |             ||                                    |=== data ===>|             ||                                    |             |             ||                                    |<== data ====|             ||<------------------ [0x4001] data --|             |             ||                                    |             |             |Figure 4

1、連接Turn Server 流程

和國標gb28181的協議差不多 都是先發送一包AllocateRequest到服務返回一個錯誤碼然后在發送一個AllocateRequest請求帶上 用戶名和密碼 然后Trunserver返回映射turn上ip地址和port端口

在這里插入圖片描述

① 抓包交換流程圖

在這里插入圖片描述

② TURN協議格式解析

協議基礎與消息結構

TURN協議基于STUN協議擴展,采用STUN消息格式(頭部+屬性列表),同時新增了專用于中繼功能的方法和屬性?

  1. 消息頭(Header):
  • Class?:固定為0x00(請求)或0x10(指示消息)?

  • Method?:定義操作類型(如Allocate、ChannelBind等)?

  • Length?:消息總長度(不含頭部)?
    ?

  • Transaction ID?:16字節唯一標識符,用于匹配請求與響應?

?2. 屬性列表(Attribute)?:

  • 每個屬性由Type(2字節)、Length(2字節)和Value(可變長)組成?

  • 例如:XOR-RELAYED-ADDRESS表示中繼地址,CHANNEL-NUMBER標識信道號?

關鍵方法類型

TURN協議新增以下STUN方法

  • Allocate?:客戶端向服務器申請中繼地址,響應中包含XOR-RELAYED-ADDRESS屬性?
  • Refresh?:延長中繼地址的生命周期(通過LIFETIME屬性設置超時時間)?
  • ChannelBind?:綁定信道號(CHANNEL-NUMBER)與特定Peer地址,啟用ChannelData傳輸?
  • Send/Data Indication?:用于中繼數據傳輸(Send為客戶端→服務器,Data為服務器→客戶端
核心屬性類型

新增屬性包括:

  • XOR-RELAYED-ADDRESS?:服務器分配的中繼地址(IP+端口),用于標識客戶端的中繼端點?
  • XOR-MAPPRE-ADDRES: 本機映射外網地址(IP+port)
  • CHANNEL-NUMBER?:2字節信道號(范圍0x4000-0x7FFF),用于ChannelData報文的高效傳輸?
  • LIFETIME?:中繼地址有效期(默認10分鐘),客戶端需定期刷新?
  • DONT-FRAGMENT?:標志位,指示客戶端支持IP分片重組?
錯誤碼與狀態?

TURN協議擴展了STUN錯誤碼:

  • 401(未認證)?:請求未攜帶有效憑證,需重新發送認證信息?78?
  • 437(Allocation Mismatch)?:客戶端嘗試使用未分配的信道或地址?
  • 508(Insufficient Capacity)?:服務器資源不足,無法分配中繼地址?
數據傳輸機制?

1?. Send/Data Indication?:

  • 使用STUN消息格式,Send攜帶應用數據發送至服務器,Data由服務器轉發至Peer?
  • 頭部包含XOR-PEER-ADDRESS屬性,標識目標Peer地址?67。
    ?
  1. ChannelData消息?:
  • 非STUN格式,頭部僅4字節(信道號+數據長度),減少傳輸開銷?
  • 需通過ChannelBind預先綁定信道號與Peer地址?

③ 發送Allocate Request UDP 信息包信息

在這里插入圖片描述

第一次返回 401 Unauthorized 信息 帶有NONE(新生成的一次性隨機數),REALM(標識服務器或服務的域)
在這里插入圖片描述

再次發送 Allocate Request UDP 包 帶上 協議、用戶名和sha-1(user:realm:paasword)簽名

密碼

TURN服務返回 本機映射外網地址和TURN服務分配中繼地址、有效時間
在這里插入圖片描述

④ 發送CreatePermission Request

在這里插入圖片描述
返回數據
在這里插入圖片描述

發送數據Send Indication

!【】
在這里插入圖片描述

接收 Data Indiaction

在這里插入圖片描述

⑤ Channel-Bind Request

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgithub.com%2Fchensongpoixs%2Fcturn_relay_demo&pos_id=img-B8Tiv02W-1743192961278)

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fchensongpoixs.github.io%2F&pos_id=img-om16XyoI-1743192922198)
在這里插入圖片描述

發送數據 ChannelData Message

在這里插入圖片描述

2、 TURN測試Demo

TURN測試demo
在這里插入圖片描述

二 、 iceCandidate收集的時機有兩種

1、創建PeerConnection對象傳入的參數ice_candidate_pool_size大于0會創建連接池的個數, 如果沒有不會創建連接池ICE的速度就會有點慢

設置ice配置


bool Conductor::CreatePeerConnection(bool dtls) {RTC_DCHECK(peer_connection_factory_);RTC_DCHECK(!peer_connection_);RTC_LOG(LS_INFO) << __FUNCTION__;webrtc::PeerConnectionInterface::RTCConfiguration config;config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; //這個 config.enable_dtls_srtp = dtls; //是否加密webrtc::PeerConnectionInterface::IceServer server;server.uri = GetPeerConnectionString();config.ice_candidate_pool_size = 0; // 大于0 就在sdp之前進行stun和turn連接創建, 反之啥事情都不做server.username = user_name_;server.password = pass_word_;std::vector<std::string> turnservers;turnservers.push_back(turn_url_);server.urls = turnservers;// 設置走 turn server 進行轉發媒體數據 哈config.type = webrtc::PeerConnectionInterface::kRelay;config.servers.push_back(server);peer_connection_ = peer_connection_factory_->CreatePeerConnection(config, nullptr, nullptr, this);return peer_connection_ != nullptr;
}

在CreatePeerConnection方法中

  1. 異步創建BasicPortAllocator對象中如果ice_candidate_pool_size大于在SetConfiguration方法中就會進行連接turn和stun服務
  2. 創建負責ICE管理類JsepTransportController
bool PortAllocator::SetConfiguration(const ServerAddresses& stun_servers,const std::vector<RelayServerConfig>& turn_servers,int candidate_pool_size,bool prune_turn_ports,webrtc::TurnCustomizer* turn_customizer,const absl::optional<int>& stun_candidate_keepalive_interval) 
{CheckRunOnValidThreadIfInitialized();// A positive candidate pool size would lead to the creation of a pooled// allocator session and starting getting ports, which we should only do on// the network thread.RTC_DCHECK(candidate_pool_size == 0 || thread_checker_.IsCurrent());bool ice_servers_changed = (stun_servers != stun_servers_ || turn_servers != turn_servers_);stun_servers_ = stun_servers;turn_servers_ = turn_servers;prune_turn_ports_ = prune_turn_ports;if (candidate_pool_frozen_) {if (candidate_pool_size != candidate_pool_size_) {RTC_LOG(LS_ERROR) << "Trying to change candidate pool size after pool was frozen.";return false;}return true;}if (candidate_pool_size < 0) {RTC_LOG(LS_ERROR) << "Can't set negative pool size.";return false;}candidate_pool_size_ = candidate_pool_size;// If ICE servers changed, throw away any existing pooled sessions and create// new ones.///// 20250328 ice[stun、turn]信息改變 就清除當前端口連接池會話if (ice_servers_changed) {pooled_sessions_.clear();}turn_customizer_ = turn_customizer;// If |candidate_pool_size_| is less than the number of pooled sessions, get// rid of the extras.while (candidate_pool_size_ < static_cast<int>(pooled_sessions_.size())) {pooled_sessions_.back().reset(nullptr);pooled_sessions_.pop_back();}///// |stun_candidate_keepalive_interval_| will be used in STUN port allocation// in future sessions. We also update the ready ports in the pooled sessions.// Ports in sessions that are taken and owned by P2PTransportChannel will be// updated there via IceConfig.// ICE的心跳包  的stun_candidate_keepalive_interval_ = stun_candidate_keepalive_interval;for (const auto& session : pooled_sessions_) {session->SetStunKeepaliveIntervalForReadyPorts(stun_candidate_keepalive_interval_);}// 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_) {IceParameters iceCredentials = IceCredentialsIterator::CreateRandomIceCredentials();PortAllocatorSession* pooled_session = CreateSessionInternal("", 0, iceCredentials.ufrag, iceCredentials.pwd);pooled_session->set_pooled(true);//20250327  觸發MSG_CONFIG_START信號   探測stun和turn 服務連通性 pooled_session->StartGettingPorts();pooled_sessions_.push_back(std::unique_ptr<PortAllocatorSession>(pooled_session));}return true;
}

2、 設置sdp時獲取 iceCandidate

整體調用流程

在這里插入圖片描述

調用流程圖
在這里插入圖片描述


bool TurnPort::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,const char* data,size_t size,const rtc::SocketAddress& remote_addr,int64_t packet_time_us) {if (socket != socket_) {// The packet was received on a shared socket after we've allocated a new// socket for this TURN port.return false;}// This is to guard against a STUN response from previous server after// alternative server redirection. TODO(guoweis): add a unit test for this// race condition.if (remote_addr != server_address_.address) {RTC_LOG(LS_WARNING) << ToString()<< ": Discarding TURN message from unknown address: "<< remote_addr.ToString() << " server_address_: "<< server_address_.address.ToString();return false;}// The message must be at least the size of a channel header.if (size < TURN_CHANNEL_HEADER_SIZE) {RTC_LOG(LS_WARNING) << ToString()<< ": Received TURN message that was too short";return false;}if (state_ == STATE_DISCONNECTED) {RTC_LOG(LS_WARNING)<< ToString()<< ": Received TURN message while the TURN port is disconnected";return false;}// Check the message type, to see if is a Channel Data message.// The message will either be channel data, a TURN data indication, or// a response to a previous request.uint16_t msg_type = rtc::GetBE16(data);if (IsTurnChannelData(msg_type)) {HandleChannelData(msg_type, data, size, packet_time_us);return true;}if (msg_type == TURN_DATA_INDICATION) {HandleDataIndication(data, size, packet_time_us);return true;}if (SharedSocket() && (msg_type == STUN_BINDING_RESPONSE ||msg_type == STUN_BINDING_ERROR_RESPONSE)) {RTC_LOG(LS_VERBOSE)<< ToString()<< ": Ignoring STUN binding response message on shared socket.";return false;}// This must be a response for one of our requests.// Check success responses, but not errors, for MESSAGE-INTEGRITY.
#if TURN_LOGstd::cout << "[turn][hash()  = " << hash() << "]" << std::endl;RTC_LOG(LS_INFO) << "[turn][hash()  = " << hash() << "]";
#endif // #if TURN_LOGif (IsStunSuccessResponseType(msg_type) &&!StunMessage::ValidateMessageIntegrity(data, size, hash())) {RTC_LOG(LS_WARNING) << ToString()<< ": Received TURN message with invalid ""message integrity, msg_type: "<< msg_type;return true;}request_manager_.CheckResponse(data, size);return true;
}

總結

WebRTC源碼分析地址:https://github.com/chensongpoixs/cwebrtc

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75329.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75329.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75329.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Redis + Caffeine多級緩存電商場景深度解析

Redis Caffeine多級緩存 Redis Caffeine多級緩存電商場景深度解析一、實施目的二、具體實施2.1 架構設計2.2 組件配置2.3 核心代碼實現 三、實施效果3.1 性能指標對比3.2 業務指標改善3.3 系統穩定性 四、關鍵策略4.1 緩存預熱4.2 一致性保障4.3 監控配置Prometheus監控指標 …

前端開發3D-基于three.js

基于 three.js 渲染任何畫面&#xff0c;都要基于這 3 個要素來實現 1場景scene&#xff1a;放置物體的容器 2攝像機&#xff1a;類似人眼&#xff0c;可調整位置&#xff0c;角度等信息&#xff0c;展示不同畫面 3渲染器&#xff1a;接收場景和攝像機對象&#xff0c;計算在瀏…

代碼隨想錄算法訓練營--打卡day4

一.移除鏈表元素 1.題目鏈接 203. 移除鏈表元素 - 力扣&#xff08;LeetCode&#xff09; 2.思路 通過 while 循環來遍歷鏈表&#xff0c;只要 cur 的下一個節點不為空&#xff0c;就繼續循環。在循環中&#xff0c;對 cur 的下一個節點的值進行判斷&#xff1a; 值不等于…

虛擬電廠:多元能源聚合,開啟綠色電力新時代

虛擬電廠&#xff1a;多元能源聚合&#xff0c;開啟綠色電力新時代 在“雙碳”目標驅動下&#xff0c;電力系統正經歷從集中式向分布式、從單一能源向多能互補的深刻變革。 作為能源互聯網的核心載體&#xff0c;虛擬電廠通過數字化技術整合多種能源資源&#xff0c;而是像指…

高通Android10 鈴聲通話音頻80%音量修改

先修改最高的音量step --- a/SC60_AP/frameworks/base/services/core/java/com/android/server/audio/AudioService.javab/SC60_AP/frameworks/base/services/core/java/com/android/server/audio/AudioService.java-311,14 311,14 public class AudioService extends IAudio…

類加載過程?類隔離了解過嗎?

類加載過程詳解 類加載是 JVM 將類的字節碼從磁盤、網絡或其他來源加載到內存&#xff0c;并轉換為 Class 對象的過程&#xff0c;主要分為以下 五個階段&#xff1a; 1. 加載&#xff08;Loading&#xff09; 任務&#xff1a;查找類的二進制字節流&#xff08;如 .class 文…

使用msmtp和mutt在CentOS上發送指定目錄下的所有文件作為郵件附件

1.安裝 msmtp&#xff1a; 如果尚未安裝&#xff0c;請先通過以下命令安裝msmtp。 sudo yum install msmtp 2.配置 msmtp 使用新浪郵箱&#xff1a; 創建或編輯配置文件~/.msmtprc&#xff0c;輸入以下內容&#xff08;記得替換授權碼&#xff09;。 defaults tls on tls_st…

Vue+Elementui首頁看板

源碼 <template><!-- 查詢條件--><div class="optimize-norm" v-loading="selectDataLoading"><el-form :model="queryParams" ref="queryRef" style="padding-bottom:8px" :inline="true"…

匯編學習之《指針寄存器大小端學習》

什么是指針寄存器&#xff1f; 操作棧的寄存器 棧&#xff1a; 保存函數里面傳遞的參數&#xff0c;局部變量等。 EBP&#xff1a; 指向棧底的指針 ESP&#xff1a; 指向棧頂的指針。 計算入棧地址變化規則 通過OllDbg查看 有可能點擊安裝的時候棧區域第一次查看會沒有顯…

Oracle數據庫數據編程SQL<3.7 PL/SQL 觸發器(Trigger)>

觸發器是Oracle數據庫中的一種特殊存儲過程&#xff0c;它會在特定數據庫事件發生時自動執行。觸發器通常用于實現復雜的業務規則、數據驗證、審計跟蹤等功能。 目錄 一、觸發器基本概念 1. 觸發器特點 2. 觸發器組成要素 二、觸發器類型 1. DML觸發器 2. DDL觸發器 3.…

2025年滲透測試面試題總結-某 攜程旅游-基礎安全工程師(題目+回答)

網絡安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 攜程旅游-基礎安全工程師 反序列化原理 核心原理 擴展分析 SQL注入本質 核心原理 擴展分析 SQL注…

CSS 邊框(Border)樣式詳解

CSS 邊框&#xff08;Border&#xff09;樣式詳解 CSS 提供了多種邊框樣式&#xff0c;使我們能夠控制元素的外觀。本文將詳細介紹 CSS 邊框的各種屬性及應用示例。 1. 基本邊框屬性 CSS 主要使用 border 相關屬性定義邊框&#xff0c;基本語法如下&#xff1a; border: [邊…

SpringCould微服務架構之Docker(6)

容器的基本命令&#xff1a; 1. docker exec &#xff1a;進入容器執行命令 2. docker logs: -f 持續查看容器的運行日志 3. docker ps&#xff1a;查看所有運行的容器和狀態 案例&#xff1a;創建運行一個容Nginx容器 docker run--name myNginx -p 80:80 -d nginx 命…

unity3d端監聽 uri scheme

一、消息監聽 1.創建一個腳本命名為 “URISchemeListener” &#xff0c;用于接收URI消息&#xff08;代碼如下&#xff09;。 using System; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.UI;public class URISchemeListener : MonoBehavio…

網絡信息安全應急演練方案

信息安全應急演練方案 總則 &#xff08;一&#xff09;編制目的 旨在建立并完善應對病毒入侵、Webshell 攻擊以及未授權訪問等信息安全突發事件的應急機制&#xff0c;提升組織對這類事件的快速響應、協同處理和恢復能力&#xff0c;最大程度降低事件對業務運營、數據安全和…

電商場景下高穩定性數據接口的選型與實踐

在電商系統開發中&#xff0c;API接口需要應對高并發請求、動態數據更新和復雜業務場景。我將重點解析電商場景對數據接口的特殊需求及選型方案。 一、電商API必備的四大核心能力 千萬級商品數據實時同步 支持SKU基礎信息/價格/庫存多維度更新每日增量數據抓取與歷史版本對比…

Android R adb remount 調用流程

目的&#xff1a;調查adb remount 與adb shell進去后執行remount的差異 調試方法&#xff1a;添加log編譯adbd,替換system\apex\com.android.adbd\bin\adbd 一、調查adb remount實現 關鍵代碼&#xff1a;system\core\adb\daemon\services.cpp unique_fd daemon_service_to…

多模態大語言模型arxiv論文略讀(二)

Identifying the Correlation Between Language Distance and Cross-Lingual Transfer in a Multilingual Representation Space ?? 論文標題&#xff1a;Identifying the Correlation Between Language Distance and Cross-Lingual Transfer in a Multilingual Representat…

【運維】負載均衡

老規矩&#xff0c;先占坑&#xff0c;后續更新。 開頭先理解一下所謂的“均衡”&#xff0c;不能狹義地理解為分配給所有實際服務器一樣多的工作量&#xff0c;因為多臺服務器的承載能力各不相同&#xff0c;這可能體現在硬件配置、網絡帶寬的差異&#xff0c;也可能因為某臺…

大型語言模型Claude的“思維模式”最近被公開解剖

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…