藍牙SDP協議概述
之前寫了一篇 bluedroid對於sdp的實現的源碼分析 ,他其實對於sdp 協議本身的分析並不多,而是側重於 sdp 處於Android bluedroid 架構中的代碼流程,這篇文章,是針對SDP 的規範來整理SDP 協議本身的一些要點。
概要:
我們想一想,兩個陌生的設備(之前未有過交互)如何去發現對方支持什麽服務呢?很容易想到,我們需要一種協議,這種協議規定了服務在服務器上面是如何存儲的以及對方如何能夠通過這個協議來獲取到數據,以及雙方共同遵守的一些規定等等。
SDP全稱是Service Discovery Protocol,它是一種服務發現的協議,它可以達成我們上面提出的問題。這部分參考core_spec,Vol3-PartB。
這樣的一個協議應該具體實現一些什麽?
那肯定是會規定特定的數據格式,以及交互的流程。
下面就分如下的幾部分來介紹SDP:
- 基本概念。
- 數據格式
- 交互流程
- 實例
基本概念:
Service Record:服務就是可以提供特定信息或者進行特定的行為,或者是能進行控制某些資源的一個實體。它的實現可以基於軟件或者硬件,也可以是兩者兼有。在服務器上面維護的關於一個servcie的所有信息的集合就是一個service record。它的所有信息往往都是用service attributes來表示的。
service attribute:它是對於service 各種屬性的一種描述。比如service ID,service的name。一些常見的屬性如下:
從上面的圖中發現service attribute 由 attribute ID和attribute Value組成的。
Attribute ID:它是一個16位的無符號整數,它用來區分在同一個Service Record之中的不同attribute,同時它也往往暗含與它相關的 Attribute Value的語義。註意它的用data element 來表示的。
Attribute Value:它是一串不定長的數據,它的含義是由與它對應的Attribute ID以及它所在的service類別來決定的。註意它的數據格式的是data element。(後續介紹)
Service class:它就是一種service的類別,它提供了所有屬於這個類別的attributes的定義,它類似面向對象編程裏面的類,具體的service是類的實例,一個具體的service 它可能隸屬多個類別。類似面向對象的裏面的繼承。當然每個class本身也是要和別的class來做以區分的,承擔這項任務的變量叫service class identifier,在service裏面總由一個attribute叫做ServiceClassIDList,這個service class identifier就存儲在這個attribute的attribute value 裏面,這個值是一個UUID。
UUID:A UUID is a universally unique identifier that is guaranteed to be unique across all space and all time。註意它具有全局的唯一性。 它是128bit的值。
Service Search Patterns:這個是一串UUID,是用來搜索用的。
Data element:它由header和data兩部分組成。其中,header部分又由兩部分組成:類型描述符和大小描述符,前者是來描述data的類別,後者是來描述data 的大小。此概念非常重要。類型描述符是用header部分的高5bits來表示的。大小描述符是用header部分的低3個字節來描述的。下面看看這兩個描述符具體的類別以及大小:
下面舉個例子來說明:
接下來 我們看看:
數據格式:
數據的格式如下圖:
PDU ID 表示這個PDU是作用,是用以區別其他的PDU
TransactionID:用以區別其他的Transaction
另外還有一個概念Continuation State:當SDP 服務器返回client 結果的時候,如果數據太大,那麽就會分包,下面額度變量就是分包的標誌,如果部分包,其值為0
接下來 ,我們看看交互的基本的流程:
交互流程:
根據PUD id 的不同,交互的流程也不同,但是思路都是一樣,都是CS的架構。
因為基本上面所有的交互流程都是一樣的,下面只講其中一個交互的流程。
下面來解析一下它的參數:
ServiceSearchPattern:這個匹配模式是由一串UUID組成的,一次最多包含12個UUID,UUID的表現形式是data element
MaximumAttributeByteCount:從response中返回的最大的PDU
AttributeIDList:這個參數包含的是一串attribute ID或者是attribute ID的範圍,也可以是兩者的組合。
ContinuationState: 這個參數的第一個字節代表長度,然後後面跟該長度個字節。這個state 是從reponse中返回的。然後再一次請求的時候放在參數裏面。如何沒有剩余的字節需要讀取,那麽設置為0
下面是對應的response 的PDU:
相應的參數解釋如下:
AttributeListsByteCount:這裏是count就是AttributeLists這裏的字節數。
AttributeLists:這裏的元素都是data element sequence,它是由attribute IDs和attribute values 來組成的pair
這裏先結合btsnoop來分析一下,具體的SDP 流程是怎麽樣的?
相應的log:btsnoop_a2dp.cfa
從上面的log 可以看出,其PDU ID: SDP_ServiceSearchAttributeRequest ,這個命令是要先根據patterns來搜索特定的service,然後在搜索到service裏面進行attribute的搜索。那麽我們看看這條命名對應的具體參數。
我們應該還記得 pattern是第一個參數,其中包含的UUID是L2cap,那意味著只要包含L2cap的service都會match這個pattern,接下來的參數是說最多返回656 個字節。接下來的參數AttributeLists上面講過,既可以是UUID,也可以是UUID的範圍。這裏參數是0x00 --0xFF
也就是說 返回match pattern的service的所有的attribute。
SDP裏面是有專門的PDU來做browsing的,這裏不作介紹。從上面的描述可以看出,雖然它沒有做browsing,但是也相當於是browsing。
接下來,我們看看對應這個request的response:
我們按照數據格式,來分析一下,如果忘記了PDU的數據格式,可以回頭看看上面寫的。
07:PDU ID: SDP_ServiceSearchAttributeResponse
00 00 :Transaction ID: 0x0000
00 2b:Parameter Length: 43
根據 數據包格式,我們知道接下來是Parameters了,我們再次把這個parameter相關的PDU 放在這裏:
00 26:Attribute List Byte Count: 38 代表這一包數據的AttributeLists 的byte的數量。
接下來就是AttributeLists的表達方式:
從上面的圖可以知道其是Data Element Sequence
接著分析:
0x36 0x01 0xd7 = 0b00110 0b110 0x01 0xd7
其中0b00110 說明Type是 Data element sequence
0b110 說明參數的長度部分是由16個bits來表示的,也就是後面的0x01 0xd7,這個長度代表所有的返回的參數的長度,(後續的包是分包返回)並不是這個包的長度。這裏還需要註意一點的是這裏的type是Data element sequence ,意味著接下來parameter部分都是Data element的格式。
接著分析:
接下來肯定還是data element的header部分
36 00 3b :0b00110 0b110 0x00 0x3b 說明接下來的 AttributeList 裏面的數據元素還是Data Element,並且 這個AttributeList的長度是的0x003b ,
接下來的數據是 :
09 00 00 = 0b00001 0b001 00 00 對應上面的data element說明Attribute ID的Type是Unsigned Integer,(註意根據上面的格式,第一個element是Attribute ID,接著是Attribute value),Attribute ID的SizeIndex是2 bytes,Attribute ID = 0x00 0x00
下面看下一個element 這個element 是對應上面的Attribute ID的Attribute value:
0a 00 01 00 00 = 0b00001 0b010 說明這個data element的Type是Unsigned Integer,用4個字節來表示 也即00 01 00 00
接下來的就是 下一個 attribute 了,其格式都是類似,只是代表的attribute不同。在此不再贅述。
最後再舉個profile的例子,看看profile中是如何定義它的service的:
這裏看A2dp 中關於其自身service的描述:這裏只描述sink的情況:
從上面的service class ID 看出它是一個audio sink的service,涉及到protocol 有L2cap和AVDTP,與其相對應的profile 是A2dp
Supported Features是它有可能支持的feature,接下來還有provider name和Service name的描述。
下面看一下log實際的 搜索的情況,和上面的規範是一致:
ed
藍牙SDP協議概述