完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

因為疫情的原因,很多公司通信採用了視頻會議的方式進行業務溝通。在視頻會議解決方案中,很多的用戶需要在進行視頻通話的同時還要和其他用戶共享某些客戶端的資源,例如文件,PPT等數據。這是視頻會議的一個基本需求。在基於SIP通信的網絡中,SIP視頻功能結合資源共享功能就可以實現這些視頻會議的功能需求。在視頻會議應用中,Binary Floor Control Protocol (BFCP,RFC4582)-雙流控制協議是其核心的協議,和基於SDP拓展實現BFCP的Session Description Protocol (SDP) Format for Binary Floor Control Protocol(RFC4583)。筆者在本討論中,首先會就RFC4582的概要和一些技術詳解(part 1),然後介紹關於BFCP中SDP拓展和其他應用場景(part 2)。其次,筆者會介紹幾個目前比較熱門的BFCP的應用場景。


關於雙流控制協議的背景介紹-RFC4582和RFC4583

在本文檔的討論中,我們僅涉及SIP和BFCP的功能討論,不涉及其他協議對BFCP的功能支持。在我們討論雙流控制協議之前,我們首先需要介紹幾個常用的定義。在一般的基於SIP的網絡環境中,不外乎語音視頻或者加一個圖片傳輸的通信方式。但是,目前大部分的企業通信要求不僅僅支持視頻,同時還要支持會議人員在進行視頻會議的同時,可以分享或者對其他用戶發送其他文本文件或者演講的其他資料,例如PPT文件。視頻會議同時完成以上這兩種功能就需要所謂的雙流數據來實現。


首先,我們介紹一下什麼是Floor Control(流控制)。Floor control 簡單來說就是一種處理機制,它支持應用程序或者用戶安全獲得相互對端獨有資源,訪問共享一些目標文件或者資源,例如對端文本文件,PPT等客戶數據資源。這裡需要讀者注意的是,這種機制必須以安全的方式,相互訪問一些特定的目標文件和資源。同時,Floor control 也可以實現會議和媒體的創建,會議策略管理,媒體控制等其他功能。當然,這些功能需要第三方協議來協助完成。


其次,我們需要關於Binary Floor Control Protocol(BFCP)的定義。BFCP是一種協議,它可以在視頻會議中協調各種資源。比較典型的示例就是利用BFCP實現的視頻會議服務:

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

本圖片和以下所有圖片均來自於互聯網資源


在會議服務中涉及了幾個核心的要素:

  • Floor Control Server(流控制服務器)
  • Floor(一個邏輯實體,流處理/獲得訪問權限訪問文件)
  • Floor Chair(一個邏輯實體,流管理/會議主持人,權限管理,流管理,喚醒流處理)
  • Floor Participant(一個邏輯實體,流成員者/會議人員)。在會議開始以後,一般會議主持人會按照約定的流程,首先讓每個人開始講話,然後第二個人開始講話或者分享其他的文件。


雙流控制協議(BFCP)概要-RFC4582

RFC4582規範是Binary Floor Control Protocol (BFCP)的標準協議。在此協議中規定了BFCP中多個方面的內容。其主要內容包括:規範處理範圍, 操作流程,數據包格式,傳輸,較底層的安全處理,協議事務, 籤權和認證,流會議成員操作,流會議主持人操作,一般會議人員操作,流控制服務器操作,和安全問題。下面,我們按照RFC4582的規範說明來進一步介紹以上這幾個方面的內容。


規範處理範圍(Scope),首先說明,此規範重點討論的是關於BFCP協議本身的內容,它所關心的是在會議狀態下如何通過BFCP來實現對資源的控制,它所遵守的要求是根據RFC4376來實現。另外,關於會議處理的介紹架構是通過RFC4597定義。關於流會議人員和限定的內容,讀者可以參考RFC4597做進一步學習研究。以下示例是BFCP所能夠提供的功能。

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

根據以上示例,BFCP提供的通信方式包括:

  • 對於流會議成員來說,發送請求到流控制服務器。
  • 對於流控制服務器來說,它可以允許或者拒絕流會議人員的請求。
  • 對於流會議主持人來說,它對流控制服務器發送一個針對流會議人員的請求的決定。
  • 對於流控制服務器來說,它負責維護流會議人員和流會議主持人針對流會議的消息狀態和流會議人員的請求。


在BFCP中,流會議處理流程大概經過四個步驟:

  • 流創建,關聯一個給定的流和相關的資源
  • 獲得客戶端資源聯繫流控制服務器,客戶端需要各種相關數據來創建和BFCP 流控制服務器的連接。客戶端所需要的消息數據包括服務器端的傳輸地址,會議 ID和用戶ID。
  • 獲得流資源的關聯綁定,流綁定相關資源。流會議用戶和流會議主持人需要獲得相關的系統資源綁定信息,以及如何獲得這些綁定消息的機制等。例如,BFCP可以通過SDP =m行使用offer/answer的交互模式獲得的消息。當然,也可能通過其他的方式獲得資源信息。
  • 獲得流資源的優先權限,流會議人員被允許訪問某些特定的資源,決定何種流會議人員有權限訪問資源。


介紹完關於BFCP的一個規範使用範圍以後(Overview of Operation),我們再繼續瞭解關於BFCP的整個操作核心流程。在BFCP整體操作流程中,其實它就存在兩種流程的操作。一種是流會議成員和流控制服務器的接口操作,另外一種是流會議主持人和流控制服務器接口之間的操作。在BFCP的消息體的構造中,BFCP消息使用的是TLV (Type-Length-Value) binary編碼方式,其消息由公共的頭值和一系列的屬性設置構成。公共頭值包括一個32-bit的會議標識符(identifier),流會議成員方,媒體參與方,和一個會議主持人(一個16-bit 用戶標識符)。BFCP同時支持內嵌屬性(屬性中包含其他的屬性),這些內嵌屬性可以構成一個組屬性。在BFCP中支持兩種事務處理(client-initiated transactions 和 server-initiated transactions.)。我們從它們各自的含義都可以瞭解到,客戶端初始的事務包含一個從客戶端到服務器端的消息,和從服務器端到客戶端的響應消息。因為這兩種消息都在普通頭值的同一事務ID傳遞,因此,它們具有相關性。服務器端初始的事務由一個單個消息構成,事務ID是0,從流控制服務器發送到客戶端。下面,我們分別討論一下流成員到流控制服務器接口的流程和流主持人到控制服務器接口的流程。

現在,我們討論一下流成員到流控制服務器接口流程。根據前面的圖例,流成員如果需要請求一個流的話,它需要對流控制服務器發送一個FloorRequest消息到流控制服務器。這裡需要注意,BFCP也支持第三方的流請求。這種情況下,發送流請求的成員不需要和媒體一起配置發送,流請求同意以後,媒體可以直接獲得流。FloorRequest消息傳輸在公共頭值的用戶 ID傳遞請求者的身份標識,並且在BENEFICIARY-ID屬性中流受益者身份標識(在第三方流請求中)。FloorRequest消息確認流或者在FLOOR-ID屬性中傳輸的其他的流(通過16-bit 流身份標識符)。如果FloorRequest消息傳輸了一個以上的floor identifier 標識符,流控制服務器將把所有的流標識符看作一個atomic數據包。這也就是說,流控制服務器允許或者拒絕所有流成員的請求。流控制服務器接收到請求以後,它會返回一個FloorRequestStatus 消息,此消息中包含流請求的狀態。另外,FLOOR-REQUEST-INFORMATION屬性是一個非常重要的屬性,它涉及了流請求的狀態和流成員的一些綁定關係(包括Floor Request ID和事務ID等),讀者可以通過RFC4582做更多瞭解。


接下來,我們討論關於流主持人和流控制服務器接口的處理流程。此接口流程相對比較簡單。但是這裡需要說明的是,儘管流主持人可以對流控制服務器發送ChairAction消息獲取流控制服務器權限資源,但是,流控制服務器沒有必要允許流主持人的所有請求,流控制服務器根據ChairAction和流控制服務器的內部狀態來進行處理。例如,如果此流請求涉及到了atomic流請求的話,即使流主持人對某個流請求了獲得允許,流控制服務器仍然不會允許其他的流請求通過,直到流主持人獲得所有流請求通過,流控制服務器才允許所有的流請求通過。因此,流控制服務器最終根據其相關的流主持人命令的流狀態來決定其最終處理狀態。

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

  • 流主持人命令流控制服務器示意圖


接下來,我們繼續討論關於BCFP的數據包格式(Packet Format)。BFCP的數據包格式一個12-octet的公共頭(COMMON-HEADER)和其屬性構成。公共頭的格式如下:

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

BFCP公共頭格式

我們經常需要注意的或者比較重要的是Primitive(消息目的和方向),Conference ID(會議ID),Transaction ID和User ID。

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

BFCP的數據包格式除了公共頭的格式以外,還有一個屬性的格式。

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1


其中,Type 包括了各種類型定義,內容和格式。

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

BFCP屬性

這裡,讀者需要注意經常見到的一下錯誤代碼-ERROR-CODE,和其他的錯誤引申含義。因為篇幅關於,筆者不再介紹BFCP的其他格式內容,讀者可以參考RFC4582來進一步研究。

完整雙流控制協議 (BFCP),SDP拓展和應用概論-part 1

BFCP會議錯誤碼


BFCP實體之間的的傳輸方式(Transport)是通過TCP連接實現。大家都知道,TCP可以提供可靠按序傳輸方式,保證其資源訪問的穩定性。在會議中,流會議客戶端只能使用一個TCP連接來連接流控制服務器,不能使用多於一個以上的連接。但是,如果同樣的物理終端支持了不同的流會議終端的話(例如,流會議成員和會議主持人),它們本身具有各自的用戶ID的話,可以支持不同的TCP連接來連接流控制服務器,不同終端對流控制服務器的獨立的連接方式是允許的。


如果BFCP實體(流客戶端或流控制服務器端)從TCP收到數據,此數據不能被實體正確解析的話,此實體就會關閉TCP連接,需要重新創建一個新的連接。同樣的,如果TCP連接不能傳遞BFCP消息或者出現超時的話,TCP連接也需要重新創建。重新創建TCP連接方式的規則取決於流客戶端從流控制服務器獲得的消息來決定,例如,使用SDP offer/answer交互模式實現。關於SDP 的offer/answer 交互模式,讀者可以參考作者歷史文檔來進一步學習,這裡不再做更多討論。


WebRTC-ICE/RFC5245中文詳解發布關於SDP answer/offer介紹。

一旦重新TCP連接創建以後,流客戶端可以重新對流控制服務器端發送上次沒有從流控制服務器端收到響應的消息。如果流控制服務器端檢測到其中一個流客戶端的TCP連接斷開的話,流控制服務器將會使用本地策略,流控制服務器根據自己的策略對待處理請求進行進一步處理。RFC4582建議,無論在何種場景中,重新TCP建立連接時,流控制服務器都要保持流請求,不能被取消。如果流客戶端希望斷開對BFCP流控制服務器的連接時,它可以使用相對比較合理的方式斷開流控制服務器TCP連接。如果流控制服務器希望斷開流客戶端BFCP連接,流控制服務器需要使用比較合理的處理方式斷開BFCP流客戶端連接。


BFCP使用了較低層(Lower-Layer Security)的安全機制來實現回放和完整的安全保護。BFCP 服務器端和客戶端都必須支持TLS。任何BFCP實體可以支持其他的安全機制。BFCP必須至少支持TLSTLS_RSA_WITH_AES_128_CBC_SHA ciphersuite算法。當然,目前發佈了很多比較新的安全算法,很多終端特別是SIP業務方面的的安全算法也有很多更新。關於安全機制的算法,讀者可以查閱RFC3268, RFC4366和TLS拓展RFC6066。關於TLS設置一定要注意。在TLS設置支持時,TSL服務器端的設置取決於流客戶端和流控制服務器的TCP連接方式處理流程。不一定是流控制服務器端就是TLS服務器端。如果TCP連接協商機制使用的是SDP offer/answer交互模式時,answerer方(無論是流客戶端或流控制服務器端)總是TLS服務器端。


在BFCP協議中支持兩種事務類型(Protocol Transactions)。一種是基於客戶端初始化的事務,另外一種是服務器端初始的事務(notifications,流控制服務器對流會議終端發送的提示消息)。基於客戶端發起的事務由客戶端到服務器端的一個請求和一個由服務器端發送到客戶端的響應消息構成。請求中會在公共頭中傳遞一個Transaction ID,流控制服務器端會拷貝這個ID到響應消息中。流客戶端會使用這個ID來匹配響應消息,流客戶端檢查是否和前一次發送的請求匹配。基於服務器發起的事務由一個單個從流控制服務器端發送到流客戶端的消息構成。基於服務器發起的事務因為沒有觸發任何響應消息,因此,它的Transaction ID為0。下面,我們分別討論關於客戶端處理流程和服務器端處理流程。如果一個流客戶端發起了客戶端事務的話,這個客戶端必須把消息的公共頭中Conference ID設置為會議的ID,這個會議ID是客戶端前面獲得的ID。另外,客戶端必須把公共頭中的Transaction ID設置為一個數值,這個數值是從0開始的不同的數值,並且,這個數值一定不能在客戶端消息中重新使用,直到流客戶端從流控制服務器收到一個針對此事務的響應以後,此數值才能變化。流客戶端使用Transaction ID來匹配從流控制服務器返回的響應消息。流控制服務器端的處理有兩種情況。流控制服務器在基於客戶端發起的事務中發送響應,流控制服務器端必須從請求中拷貝Conference ID,Transaction ID和User ID到響應中。如果是基於服務器端發起的事務,則必須包含一個Transaction ID,這個ID為0。


BFCP實體之間的資源訪問需要認證和籤權的處理機制(Authentication 和 Authorization)。BFCP客戶端應該在對流控制服務器發送消息或者接收消息前,它首先對流控制服務器進行驗證處理。同樣的,流控制服務器端對流客戶端發送或者接收消息前也要進行認證處理。在RFC4582中規定,BFCP的流客戶端和控制服務器支持基於TLS的相互認證的機制。這是BFCP推薦的認證機制,當然,BFCP也應該支持TLS未來拓展的認證機制。更多關於BFCP TLS安全機制處理,讀者可以參考RFC4582-9.1章節。除了認證以外,BFCP的流控制服務器也需要對消息進行籤權處理。流控制服務器在收到認證消息以後,它需要對消息進行籤權處理,它會檢查流客戶端發送的消息是否是通過籤權處理。如果流客戶端沒有被允許進行某些操作的話,流控制服務器將會對流客戶端生成一個錯誤響應,錯誤代碼為5(Unauthorized Operation)。沒有被流控制服務器允許的消息不會被進行進一步的處理。


以上介紹了關於BFCP中的一些基本操作和處理流程。接下來,我們具體介紹BFCP實體操作的流程細節。


首先,我們介紹流會議成員的操作流程(Floor Participant Operations)。流客戶端首先需要對流控制服務器發送一個FloorRequest消息。它發送的消息中包括一個公共頭和屬性值,其中包括一些必要選項和一些可選選項。FloorRequest需要在公共頭中設置Transaction ID和Conference ID,同時流成員需要把在公共頭中的User ID設置為流成員標識符。此用戶ID將被流控制服務器作為認證和籤權的主要憑證。注意,如果FloorRequest發送方不是會議成員(它將獲得流資源),例如第三方發送的流請求,請求發送方應該在消息中增加一個BENEFICIARY-ID屬性,表示其是流資源的第三方收益方。

流會議成員必須在FloorRequest消息中插入一個FLOOR-ID屬性值。如果流會議成員在其floor請求中插入一個以上的FLOOR-ID,流控制服務器會認為這個流請求是一個atomic package,流控制服務器就會允許或者拒絕FloorRequest消息中所有的流。當然,流會議成員也可以使用PARTICIPANT-PROVIDED-INFO屬性來說明流或者其他流是流成員要求的請求,可以在PARTICIPANT-PROVIDED-INFO屬性中增加文本說明來聲明其原因。流控制服務器端收到FloorRequest消息以後,對其請求進行處理,然後流控制服務器生成一個或多個FloorRequestStatus消息。流會議成員從返回的FloorRequestStatus消息中獲得必要的屬性參數,例如FLOOR-REQUEST-INFORMATION,OVERALL-REQUEST-STATUS,STATUS-INFO,FLOOR-REQUEST-STATUS,BENEFICIARY-INFORMATION和PRIORITY屬性。當然,返回的信息也可能是錯誤響應。具體以上這些屬性的具體內容,讀者可以查閱RFC4582-10.1.2,這裡不再做過多解釋。


如果流會議成員希望取消正在發送的請求的話,它可以對流控制服務器發送一個FloorRelease消息。另外注意,流會議成員也可以通過FloorRelease消息來實現流等待請求,然後釋放流資源。FloorRelease發送和接收需要流會議成員和流控制服務器雙方協商處理,通過公共頭中的Conference ID和Transaction ID實現釋放匹配處理。另外,流控制服務器需要處理錯誤響應等流程。


除了上面介紹的流成員方的操作以外,另外一個實體是流主持人(Chair Operations)。這裡,我們再繼續介紹關於流會議主持人的操作流程。流會議主持人的作用就是對流控制服務器發出指令,使用前面章節中的協議通過流控制服務器獲得或者取消流資源。流會議主持人通過對流控制服務器發送ChairAction消息來實現對流控制服務器的指令。當然,按照正常的響應處理流程,流會議主持人通過發送ChairAction和接收ChairAction的響應消息實現對流控制服務器的指令操作。首先,流會議主持人對流控制服務器端發送ChairAction消息,在公共頭中設置Conference ID,Transaction ID和user ID。User ID將被流控制服務器用來對流會議主持人進行認證和籤權處理。在ChairAction請求消息中包含對流控制服務器的指令,在一個特定的流請求中,這些指令可以應用在一個流或多個流的場景中。流會議主持人可以使用FLOOR-REQUEST-STATUS提供一個新的流請求狀態,這個狀態可以關聯到一個特定的流資源(其狀態可以支持隊列位置,允許或者拒絕權限訪問)。流會議主持人也可以在ChairAction消息中添加一個OVERALL-REQUEST-STATUS,對其流請求提供一個整體狀態的說明。流會議主持人也可以通過STATUS-INFO屬性說明流被接受,解決或者取消的原因,此描述是文本格式。流會議主持人可以收到從流控制服務器返回的ChairActionAck消息,此消息確認流控制服務器收到了ChairAction請求消息。如果流會議主持人收到一個錯誤消息的話,它說明流控制服務器因為某些原因,它不能處理ChairAction消息,原因需要查看錯誤消息。


以上我們討論了針對流會議成員和流會議主持人的操作流程。除了這兩個實體的特定操作以外,BFCP仍然有一些不針對特定一方的非常基本的操作流程(General Client Operation)。這些操作流程不僅針對流會議成員或者流會議主持人,也可能同時支持兩種角色的操作。這些操作包括:

  • 關於流的信息,包括操作流程是發送FloorQuery消息和接收響應消息。
  • 關於流請求的信息,包括的操作流程是FloorRequestQuery消息和接收其相應的響應消息。
  • 關於對用戶的請求消息操作,包括髮送UserQuery消息,接收其響應消息。
  • 關於獲得流控制服務器的支持能力的操作,包括髮送Hello 消息,接收其響應能力支持消息。


以上章節介紹流流會議成員操作,流會議主持人操作和它們的一些一般操作流程。接下來,我們將介紹最後的一個操作,那就是流控制服務器端的操作流程(Floor Control Server Operations)。流控制服務器端的流程涉及了八個不同的消息處理流程,這八個處理流程分別針對的是流會議成員,流會議主持人。


  • FloorRequest消息接收,流控制服務器收到FloorRequest消息以後,檢查其認證和籤權狀態。(注意,以下其他消息也必須經過同樣的認證和籤權流程和消息解析)在處理其請求過程中,如果不理解消息內容,服務器端生成一個錯誤響應。如果流控制服務器成功解析其請求消息,則返回一個或多個FloorRequestStatus 消息,說明其是否接受或者拒絕流請求。當然,流請求也可能繼續進行,流控制服務器也可以獲得其它狀態消息。


  • FloorRequestQuery消息接收,流控制服務器收到請求查詢消息以後,流控制服務器需要處理幾個必要的屬性參數,例如,Conference ID, Transaction ID 和 User ID,添加FLOOR-REQUEST-STATUS,提供REQUESTED-BY-INFORMATION,增加PARTICIPANT-PROVIDED-INFO說明添加的理由,添加PRIORITY來表示流請求組控制的優先級。


<code>UserQuery 消息接收,流控制服務器收到用戶查詢消息後,它會快速生成/<code>
<code>        一個UserStatus消息。它經過同樣的處理流程,流控制服務器需要把/<code> 
<code>       Conference ID, Transaction ID 和 User ID拷貝到UserStatus消息中。/<code>
<code>        流控制服務器在響應消息中添加BENEFICIARY-ID(受益人ID)。/<code>
<code>/<code>
  • FloorRelease 消息接收處理,流控制服務器收到釋放請求消息以後,它會生成一個FloorRequestStatus。它會它經過同樣的處理流程,流控制服務器需要把Conference ID, Transaction ID和用戶ID拷貝到FloorRequestStatus消息中。流控制服務器必須在狀態消息中添加FLOOR-REQUEST-INFORMATION組屬性。流控制服務器必須從釋放消息中拷貝FLOOR-REQUEST-ID到FLOOR-REQUEST-INFORMATION屬性中的Floor Request ID。流控制服務器也必須確認其流請求的身份,通過添加FLOOR-REQUEST-ID來實現。最後,流控制服務器必須在FLOOR-REQUEST-INFORMATION組屬性中增加一個OVERALL-REQUEST-STATUS屬性。


  • FloorQuery消息接收處理,流控制服務器收到流查詢消息以後,它會通過FloorStatus 消息不斷通知流客戶端。單個的FloorStatus傳遞單個的流狀態消息。如果流客戶端需要多個流狀態消息的話,流控制服務器端需要分開獨立發送其狀態消息。取決於用戶對不同狀態的請求不同,FloorQuery也可以查詢待處理請求的狀態等消息。


  • ChairAction消息接收處理,流控制服務器收到主持人的請求以後,它會生成一個ChairActionAck響應消息。它會它經過同樣的處理流程,流控制服務器需要把Conference ID, Transaction ID和用戶ID拷貝到ChairActionAck消息中。當然,流控制服務器會根據本地策略,對流會議主持人返回拒絕或者接受請求等消息。


  • Hello消息接收處理,流控制服務器收到Hello消息以後,它會生成一個HelloAck消息。它會它經過同樣的處理流程,流控制服務器需要把Conference ID, Transaction ID和用戶ID拷貝到HelloAck消息中。最後,流控制服務器必須在HelloAck增加一個SUPPORTED-PRIMITIVES屬性,表示流控制服務器支持的BFCP消息。流控制服務器在HelloAck中必須增加一個SUPPORTED-ATTRIBUTES,在屬性列表中列出流控制服務器所支持的屬性能力。


  • Error 消息生成處理,錯誤消息是一個響應消息,它是由客戶端發出的,它是基於客戶端事務的一個部分。它會它經過同樣的處理流程,流控制服務器需要把Conference ID, Transaction ID和用戶ID拷貝到錯誤消息中。在錯誤消息中必須增加一個ERROR-CODE,此屬性錯誤碼包含一個錯誤代碼。另外,流控制服務器也可以增加一個ERROR-INFO屬性來說明具體的錯誤原因。
<code>/<code>
<code>以上討論基本上涵蓋了RFC4582關於BFCP的基本處理流程。最後一個需要討論的是BFCP的安全問題。/<code>
<code>BFCP本身默認支持了TLS的安全機制,只要支持的參數類似,BFCP同時它也可以增加其他的安全機制。/<code>
<code>在BFCP安全討論中,主要的幾個攻擊威脅是冒充流會議成員或者流會議主持人獲得流資源權限。/<code>
<code>另外,可以冒充一個流控制服務器端,讓流會議成員和主持人訪問來獲得終端用戶信息。/<code>
<code>攻擊者修改相關的交互信息來獲得認證權限。攻擊者也可能盜取相關的安全交互信息,然後訪問其流資源服務器內容。/<code>

規範推薦會議用戶使用TLS加密方式來進行流會議實體之間的交互,這樣可以避免攻擊者非法盜取相關的會議信息。


參考資料:

https://www.rfc-editor.org/rfc/rfc4582.html

https://www.hjp.at/doc/rfc/rfc5018.html

https://www.hjp.at/doc/rfc/rfc5567.html

https://sci-hub.st/https://ieeexplore.ieee.org/abstract/document/8599589/

www.asterisk.org.cn


分享到:


相關文章: