discovery_service.c
前言
分布式軟總線是鴻蒙系統的基石,它不僅負責設備間的發現和服務的發布,還要負責實現設備間的數據傳輸。鴻蒙其他模塊,比如設備認證等,都是需要通過軟總線來與其他設備進行通信。本篇將基於OpenHarmony(v1.x)對其軟總線進行分析。
發布與訂閱
概述
分布式軟總線實現設備間無感發現,我覺得其一就是這種發布與訂閱模式,OpenHarmony系統的服務發布與訂閱是基於COAP輕量級協議進行實現的。
主控設備可以提前訂閱自己想要的服務,一旦有某個設備發布了這個服務,就可以立刻保存它的設備信息,對應發現端和被發現端的發現邏輯如下:
發現端通過coap廣播自己的發現請求,同時被發現端發布自己的服務,當被發現段接收到一個發現請求,那么單播響應該請求。發現端收到響應之后,保存被發現端的設備信息。(OpenHarmony(v1.0.0)dsoft_lite 只具有右邊部分,並不具有訂閱服務部分,這部分在2.0版 本已經實現)。
服務發布
discovery_service.c實現了輕量級設備端的服務發布功能。
首先介紹服務發布模塊的服務結構信息,它包含服務模塊的屬性:
/* 發布模塊結構 publishId : 服務發布ID 標識服務 medium : 服務發布的媒介(wifi 藍牙..) capabilityBitmap : 對應的功能位圖 capabilityData : 服務發布的功能數據 dataLength : 數據長度 */ typedef struct { char package[MAX_PACKAGE_NAME]; int publishId; unsigned short medium; unsigned short capabilityBitmap; char *capabilityData; unsigned short dataLength; unsigned short used; } PublishModule;
首先它的入口函數為 PublishService ,這個函數實現服務發布的總流程。
/* 函數參數: moduleName : 服務模塊名 info : 發布的服務信息 IPublishCallback: 服務發布成功或者失敗的回調函數 發布成功后會創建會話,等待發現端連接 */ int PublishService(const char *moduleName, const struct PublishInfo *info, const struct IPublishCallback *cb)
在 PublishService 需要做的事主要有:
- 軟總線權限和參數檢查(目前是查看總線是否開啟)
- 初始化功能模塊
- 向g_publishModule 添加相應的模塊
- 注冊服務(將服務數據和功能添加到設備信息中)
- 調用發布服務回調函數
服務發布流程樹
發布服務將其他模塊緊密結合在一起,理解它的運行流程有助於理清各個模塊的關系。下面給出發布服務的流程樹(自左往右,自上往下):
一開始對總線權限和參數進行檢查,檢查完之后就是發布服務初始化,這個初始化分為:初始化基本的設備信息、初始化發布模塊和服務數據存儲空間、注冊回調函數、coap相關初始化、處理IP更新事件、注冊設備信息。 這個部分是發布服務中的重中之重,初始化完成之后就將發布info添加到發布模塊存儲空間,然后注冊服務,之后調用發布回調函數。
現在依次分析初始化:
- 初始化基本的設備信息:這一部分很簡單,初始化為0,然后初始接口、是否可信賬戶、設備名、類型、ID、系統版本;
- 初始化發布模塊和服務數據存儲空間: calloc分配空間;
- 注冊wifi事件回調函數(wifiEventTrigger) : 這個函數的觸發體現在IP地址事件處理上,它用於獲取或清除IP,調用總線管理器開啟或關閉軟總線、注冊設備信息和服務(清空,全部置0)
- coap相關初始化:
-
- CJSON_init 就是使用默認分配和釋放函數(malloc/free)。
- 重要的是初始化coap設備發現,這個初始化過程它會創建服務端套接字(g_serverFd)和coap消息ID,並且在創建套接字時,由於當前設備IP為(0.0.0.0),所以內核會隨機分配可用IP(INADDR_ANY),然后該套接字綁定該IP(當前還沒有存儲在設備信息結構體中)。
- 創建一個wifi事件消息隊列,這個消息隊列存儲wifi地址事件的處理信息,並創建一個消息隊列監聽線程不斷的讀這個消息隊列,一旦有地址事件,那么利用其中的處理函數( wifiEventTrigger )處理。
- 最后,創建coap監聽線程監聽g_serverFd,調用select等待g_serverFd可讀事件發生,因為可讀事件發生表示收到了一個發現請求,那么設備就需要進行響應。
5. 處理IP更新事件 : 當前g_serverFd綁定的IP地址,但是IP地址沒有存儲在設備信息結構體當中,且未開啟軟總線初始設備信息和服務,所以在coap初始化之后,立即向消息隊列中寫入一個IP更新事件,然后消息隊列監聽線程讀取出事件信息,創建一個線程調用事件處理函數(wifiEventTrigger),將剛剛綁定的IP存儲到設備信息中,然后開啟軟總線、初始設備信息和服務。
發現請求與響應
服務發布之后,發現設備發現服務,需要對該服務響應請求。
一旦coap監聽線程,發現g_serverFd可讀了,那么表示收到了一個請求,那么要對請求數據分析,然后來響應這個請求,如圖: