ITPub博客

首页 > 数据库 > 数据库开发技术 > 【OpenHarmony开发案例6】分布式软总线流程分析

【OpenHarmony开发案例6】分布式软总线流程分析

数据库开发技术 作者:服务端猎手 时间:2024-08-08 12:55:17 0 删除 编辑
源码目录:
authmanager 【提供设备认证机制和设备知识库管理】
discovery 【提供基于 coap 协议的设备发现机制】
os_adapter 【操作系统适配层】
trans_service 【提供认证和数据传输通道】
一、如何初始化软总线
一、被发现端,发布服务。【 discovery 目录】
1. 初始化 InitService() 发现服务
1.1. 初始化 g_deviceInfo 结构体
1.2. 初始化全局 g_publishModule 和 g_capabilityData
1.3. 初始化 COAP 协议服务
a.COAP 初始化 Socket
b.COAP 初始化 wifi 事件
c. 创建 COAP 监听线程 , HandleReadEvent()
2. 模块增加到 g_publishModule
3.CoapRegisterDefualtService()
总结:
二、当接入网络,触发 WifiEventTrigger() ,开启软总线
1. 获取本设备 ip
2.BusManager() 启动软总线
2.1. 启动监听 ,StartListener(), 监听与发现端建立连接
2.2. 启动会话 ,StartSession()
总结:
三、当发现端(比如手机)发送广播
1. 当检测到局域网内 UDP 广播包 ,HandleReadEvent()
2. 当检测到新连接 ,ProcessAuthData()
2.1 当建立新连接 ,OnConnectEvent()
2.2 当接收到新数据 ,OnDataEvent()
auth. 设备认证机制
authmanager 【提供设备认证机制和设备知识库管理】
reference :
源码目录:
主目录 \foundation\communication\softbus_lite
authmanager 【提供设备认证机制和设备知识库管理】
├── authmanager 【提供设备认证机制和设备知识库管理】
├── discovery 【提供基于 coap 协议的设备发现机制】
├── interfaces
├── os_adapter 【操作系统适配层】
├── trans_service 【提供认证和数据传输通道】
└── BUILD.gn
通过 BUILD.gn 的分析,我们知道整个 softbus_lite 目录下的所有源码文件将被编译到一个动态库中。
其他依赖软总线的模块在编译的时候加上这个动态库的依赖就可以了。
例如:分布式调度子系统所在的 foundation 这个 bin 文件的编译就依赖这个动态库。 discovery 【提供基于 coap 协议的设备发现机制】
当发现有请求时,调用 ProcessDataEvent 函数,收包,检验包头,根据数据包的类型确定不同的处理方式。
类型主要包括以下三种:
MODULE_AUTH_SDK 加密数据类型
MODULE_TRUST_ENGINE 可信类型,直接进行数据传输
MODULE_CONNECTION 进行 ip 及设备认证
├── BUILD.gn
├── include
│ ├── auth_conn.h
│ ├── auth_interface.h
│ ├── bus_manager.h
│ ├── msg_get_deviceid.h
│ └── wifi_auth_manager.h
└── source
├── auth_conn.c 【提供发送、接收、认证、获取秘钥功能】
├── auth_interface.c 【管理各个会话节点、各个链接节点、各个秘钥节点,提供包括增删改查等功
能】
├── bus_manager.c 【主要通过 deviceIp 创建两个不同的 listen ,主要用来监听系统上有哪些
device 及新的 device 节点的创建 ; 其中有两个回调函数 OnConnectEvent 和 OnDataEvent, 分别是用来处理
设备节点的基本操作及节点数据的处理】
├── msg_get_deviceid.c 【提供以 cJSON 格式获取各个设备的信息,包括设备 id 、链接信息、设备
名、设备类型等】
└── wifi_auth_manager.c 【主要实现了连接管理和数据接收功能。连接管理包括连接的建立、断开
及连接的查找。数据接收包括数据获取、包头及包长等的校验,并且为了简化包头数据读取,单独实现了对一
个 int 型和一个 long 型数据的接收函数】
├── BUILD.gn
├── coap 【目录主要是负责 COAP 协议的部分】
│ ├── include
│ │ ├── coap_adapter.h
│ │ ├── coap_def.h
│ │ ├── coap_discover.h
│ │ ├── coap_socket.h
│ │ ├── json_payload.h
│ │ ├── nstackx_common.h
│ │ ├── nstackx_database.h
│ │ ├── nstackx_device.h
│ │ ├── nstackx_error.h
│ │ └── nstackx.h
│ └── source
│ ├── coap_adapter.c
│ ├── coap_discover.c 【实现了基于 COAP 的设备发现功能】
│ ├── coap_socket.c
│ ├── json_payload.c
│ ├── nstackx_common.c
│ └── nstackx_device.c
└── discovery_service 【基于 coap 协议实现了轻量设备端的服务发布的能力】
├── include
│ ├── coap_service.h
│ ├── common_info_manager.h
│ └── discovery_error.h
└── source
├── coap_service.c
├── common_info_manager.c
└── discovery_service.c os_adapter 【操作系统适配层】
trans_service 【提供认证和数据传输通道】
一、如何初始化软总线
调用软总线模块并不复杂,需要准备 2 个结构体就可以召唤神龙,简称 StartBus() 。以下我们以 Hi3861 为
例写一个简单的例子。
discovery 的实现前提是确保发现端设备与接收端设备在同一个局域网内且能互相收到对方的报文。大致流程
是:
发现端设备,使用 coap 协议在局域网内发送广播;
接收端设备使用 PublishService 接口发布服务,接收端收到广播后,发送 coap 协议单播给发现端;
发现端设备收到报文会更新设备信息。
├── include
│ └── os_adapter.h
└── source
├── L0
│ └── os_adapter.c
└── L1
└── os_adapter.c
它主要封装了 socket 、 cJSON 、线程锁接口,实现了用户的创建、监听、会话管理,以及设备、指令、数据等
信息的获取,最终提供加密和解密传输两种传输通道。
├── BUILD.gn
├── include
│ ├── libdistbus
│ │ ├── auth_conn_manager.h
│ │ └── tcp_session_manager.h
│ └── utils
│ ├── aes_gcm.h
│ ├── comm_defs.h
│ ├── data_bus_error.h
│ ├── message.h
│ └── tcp_socket.h
└── source
├── libdistbus
│ ├── auth_conn_manager.c 【用户创建,监听,连接等服务管理】
│ ├── tcp_session.c 【会话管理】
│ ├── tcp_session.h
│ ├── tcp_session_manager.c
│ ├── trans_lock.c 【互斥锁初始化以及互斥锁资源获取与释放】
│ └── trans_lock.h
└── utils
├── aes_gcm.c 【提供加密传输和解密传输接口】
├── message.c 【用于获取以 cJSON 格式管理的设备(包括设备名、设备类型、设备 ID
等 ) 、指令、数据、会话(包括用户端口、会话端口等 ) 等信息】
└── tcp_socket.c 【端口号管理以及数据传输管理】
static void InitSoftbus ( void )
{ printf ( ">>>>>%s:%d:%s()\n" , __FILE__ , __LINE__ , __FUNCTION__ ); 一、被发现端,发布服务。【 discovery 目
录】
在分布式软总线子系统中,设备分为发现端和被发现端。这里我们使用手机作为发现端, Hi3861 开发板
发布服务,作为被发现端。
发布服务主要是通过 PublishService() 这个函数,相关的代码在:主目录
\foundation\communication\softbus_lite\discovery_service 文件夹下。
如果设备要发布软总线服务,就需要调用下面这个函数。
static PublishInfo g_publishInfo = {
. capabilityData = ( unsigned char * ) "1" ,
. capability = "ddmpCapability" ,
. dataLen = 1 ,
. publishId = 1 ,
. mode = DISCOVER_MODE_ACTIVE ,
. medium = COAP ,
. freq = MID ,
};
static IPublishCallback g_publishCallback = {
. onPublishSuccess = OnSuccess ,
. onPublishFail = OnFail ,
};
int ret = PublishService ( g_demoModuleName , & g_publishInfo ,
& g_publishCallback );
if ( ret != 0 ) {
printf ( "PublishService err\n" );
}
sleep ( 5 );
ret = CreateSessionServer ( g_demoModuleName , g_demoSessionName ,
& g_sessionCallback );
if ( ret != 0 ) {
printf ( "CreateSessionServer err\n" );
}
printf ( "InitSoftbus ok\n" );
}
//moduleName :调用模块名
//info : PublishInfo 结构体
//cb :发布成功或者失败的回调函数
int PublishService ( const char * moduleName , const struct PublishInfo * info , const
struct IPublishCallback * cb )
{ printf ( ">>>>>%s:%d:%s()[soft bus init
start]\n" , __FILE__ , __LINE__ , __FUNCTION__ );
// 许可检查,首先将检查是否有发布权限。这里调用的 os_adapter 【操作系统适配层】相关部分。
if ( SoftBusCheckPermission ( SOFTBUS_PERMISSION ) != 0 || info == NULL || cb ==
NULL ) {
SOFTBUS_PRINT ( "[DISCOVERY] PublishService invalid para(info or cb)\n" );
return ERROR_INVALID ;
}
// 参数有效性检查,检查了一些发布参数的合法性,其次确认发布协议是不是 COAP 。
if ( moduleName == NULL || strlen ( moduleName ) >= MAX_PACKAGE_NAME || info -
> publishId <= 0 || info -> dataLen > MAX_CAPABILITY_DATA_LEN ) {
SOFTBUS_PRINT ( "[DISCOVERY] PublishService invliad para\n" );
PublishCallback ( info -> publishId , PUBLISH_FAIL_REASON_PARAMETER_INVALID ,
NULL , cb );
return ERROR_INVALID ;
} // 如果参数检查失败,调用 PublishCallback() 来回调 cb 里面的失败回调函数
if ( info -> medium != COAP ) {
PublishCallback ( info -> publishId , PUBLISH_FAIL_REASON_NOT_SUPPORT_MEDIUM ,
NULL , cb );
return ERROR_INVALID ;
}
// 用 g_discoveryMutex 防止多个设备对外发布服务产生的冲突
if ( g_discoveryMutex == NULL ) {
g_discoveryMutex = MutexInit ();
if ( g_discoveryMutex == NULL ) {
PublishCallback ( info -> publishId , PUBLISH_FAIL_REASON_UNKNOWN , NULL ,
cb );
return ERROR_FAIL ;
}
}
MutexLock ( g_discoveryMutex ); // 解除互斥锁
//InitService() 这个函数比较重要。参考 1. 初始化 InitService() 发现服务
if ( InitService () != ERROR_SUCCESS ) {
SOFTBUS_PRINT ( "[DISCOVERY] PublishService InitService fail\n" );
PublishCallback ( info -> publishId , PUBLISH_FAIL_REASON_UNKNOWN , NULL , cb );
MutexUnlock ( g_discoveryMutex );
return ERROR_FAIL ;
}
//AddPublishModule() 函数,参考 2. 模块增加到 g_publishModule
PublishModule * findModule = AddPublishModule ( moduleName , info );
if ( findModule == NULL ) {
SOFTBUS_PRINT ( "[DISCOVERY] PublishService AddPublishModule fail\n" );
PublishCallback ( info -> publishId , PUBLISH_FAIL_REASON_UNKNOWN , NULL , cb );
MutexUnlock ( g_discoveryMutex );
return ERROR_FAIL ;
}
// 注册 COAP 服务,参考 3.CoapRegisterDefualtService()
int ret = ERROR_SUCCESS ;
if ( info -> capability == NULL || info -> capabilityData == NULL ) {
( void ) CoapRegisterDefualtService ();
} else {
ret = DoRegistService ( info -> medium );
}
MutexUnlock ( g_discoveryMutex );
// 这个 PublishCallback() 就很简单了,上面出现好多次了,初始化成功或者失败的回调函数。
if ( ret != ERROR_SUCCESS ) {
PublishCallback ( info -> publishId , PUBLISH_FAIL_REASON_UNKNOWN ,
findModule , cb );
return ERROR_FAIL ;
} else {
PublishCallback ( info -> publishId , ERROR_SUCCESS , findModule , cb );
return ERROR_SUCCESS ; 1. 初始化 InitService() 发现服务
}
}
Z : \harmony110\foundation\communication\softbus_lite\discovery\discovery_service\
source\discovery_service . c
int InitService ( void )
{
if ( g_isServiceInit != 0 ) { // 全局变量 g_isServiceInit :确认服务是否启动。如果其他模
块启动过,那么直接返回成功。
return ERROR_SUCCESS ;
}
// 初始化 g_deviceInfo 结构体。参考 1.1. 初始化 g_deviceInfo 结构体,相关文件
【 common_info_manager.c 】
if ( InitCommonManager () != 0 ) {
SOFTBUS_PRINT ( "[DISCOVERY] InitService InitCommonManager fail\n" );
DeinitService ();
return ERROR_FAIL ;
}
// 分配内存,参考: 1.2. 初始化全局 g_publishModule 和 g_capabilityData
g_publishModule = calloc ( 1 , sizeof ( PublishModule ) * MAX_MODULE_COUNT );
if ( g_publishModule == NULL ) {
DeinitService ();
return ERROR_NOMEMORY ;
}
g_capabilityData = calloc ( 1 , MAX_SERVICE_DATA_LEN );
if ( g_capabilityData == NULL ) {
DeinitService ();
return ERROR_NOMEMORY ;
}
// 软总线注册第一个监听函数 WifiEventTrigger() ,当接入网络时 trigger
// 注册 wifi Callback ,将 WifiEventTrigger()↓ 函数,赋值给全局变量 g_wifiCallback ,参考
b.COAP 初始化 wifi 事件
RegisterWifiCallback ( WifiEventTrigger );
//COAP 初始化。参考 1.3. 初始化 COAP 协议服务,相关文件【 coap_service.c 】
int ret = CoapInit ();
if ( ret != ERROR_SUCCESS ) {
SOFTBUS_PRINT ( "[DISCOVERY] InitService CoapInit fail\n" );
DeinitService ();
return ret ;
} printf ( ">>>>>%s:%d[Register WifiEventTring()]\n" , __FILE__ , __LINE__ ); // 添加打
印调试
//COAP 写入消息队列,这样会触发上面 ↑ 消息回调函数, WifiEventTrigger() ,这个函数比较重要,
TODO 1.4.
CoapWriteMsgQueue ( UPDATE_IP_EVENT );
//COAP 注册设备信息
ret = CoapRegisterDeviceInfo ();
if ( ret != ERROR_SUCCESS ) {
SOFTBUS_PRINT ( "[DISCOVERY] InitService CoapRegisterDeviceInfo fail\n" );
DeinitService ();
return ret ; 1.1. 初始化 g_deviceInfo 结构体
}
g_isServiceInit = 1 ;
SOFTBUS_PRINT ( "[DISCOVERY] InitService ok\n" );
return ERROR_SUCCESS ;
}
Z : \harmony110\foundation\communication\softbus_lite\discovery\discovery_service\
source\common_info_manager . c
int InitCommonManager ( void )
{
if ( InitLocalDeviceInfo () != 0 ) { // 初始化本地设备信息
SOFTBUS_PRINT ( "[DISCOVERY] InitCommonManager fail\n" );
return ERROR_FAIL ;
}
return ERROR_SUCCESS ;
}
================================================================================
================
int InitLocalDeviceInfo ( void ) // 初始化本地设备信息
{
char deviceId [ DEVICEID_MAX_NUM ] = { 0 };
if ( g_deviceInfo != NULL ) { // 初始化一个 g_deviceInfo 的结构体。包含本地设备的各种信
息。
memset_s ( g_deviceInfo , sizeof ( DeviceInfo ), 0 , sizeof ( DeviceInfo ));
} else {
g_deviceInfo = ( DeviceInfo * ) calloc ( 1 , sizeof ( DeviceInfo ));
if ( g_deviceInfo == NULL ) {
return ERROR_FAIL ;
}
}
g_deviceInfo -> devicePort = - 1 ; // 默认, g_deviceInfo. 设备端口 -1
g_deviceInfo -> isAccountTrusted = 1 ; // 默认, g_deviceInfo. 账户是可信的
unsigned int ret ;
// 从文件获取设备 id ,这个函数还有好几层,就不继续深挖了。大体就是从 DEVICE_ID_FILE 文件中读
取。
//#define DEVICE_ID_FILE "/storage/data/softbus/deviceid"
ret = GetDeviceIdFromFile ( deviceId , MAX_VALUE_SIZE );
if ( ret != ERROR_SUCCESS ) {
SOFTBUS_PRINT ( "[DISCOVERY] Get device fail\n" );
return ERROR_FAIL ;
}
#if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__) //g_deviceInfo. 设备的类型,
目前分为 L0 和 L1
g_deviceInfo -> deviceType = L0 ;
ret = ( unsigned int ) strcpy_s ( g_deviceInfo -> deviceName , sizeof ( g_deviceInfo -
> deviceName ), L0_DEVICE_NAME );
#else
g_deviceInfo -> deviceType = L1 ; 1.2. 初始化全局 g_publishModule 和 g_capabilityData
1.3. 初始化 COAP 协议服务
ret = ( unsigned int ) strcpy_s ( g_deviceInfo -> deviceName , sizeof ( g_deviceInfo -
> deviceName ), L1_DEVICE_NAME );
#endif
ret |= ( unsigned int ) strcpy_s ( g_deviceInfo -> deviceId , sizeof ( g_deviceInfo -
> deviceId ), deviceId ); //g_deviceInfo. 设备 id
ret |= ( unsigned int ) strcpy_s ( g_deviceInfo -> version , sizeof ( g_deviceInfo -
> version ), "1.0.0" ); //g_deviceInfo. 版本号
if ( ret != 0 ) {
return ERROR_FAIL ;
}
SOFTBUS_PRINT ( "[DISCOVERY] InitLocalDeviceInfo ok\n" );
return ERROR_SUCCESS ;
}
Z : \harmony110\foundation\communication\softbus_lite\discovery\discovery_service\
source\discovery_service . c
// 首先, discovery_service.c 开头定义了这两个全局变量。
PublishModule * g_publishModule = NULL ; // 存放发布的模块
char * g_capabilityData = NULL

原文作者:青少年编程作品集;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-08-02

  • 博文量
    18
  • 访问量
    1543