IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 鸿蒙通信softbus_lite组件分析 -> 正文阅读

[系统运维]鸿蒙通信softbus_lite组件分析

概述

softbus_lite组件是在受限设备上提供数据传输服务,除此之外,还提供设备发现,设备认证,通信安全功能。

运行机理

内部结构

softbus_lite由coap服务器,消息队列处理线程,设备认证服务器,会话管理服务器四部分组成。其中coap服务器是UDP服务器,端口为5684,用于设备发现。消息队列用于内部消息传递,目前仅用在创建设备认证服务器和会话管理服务器上,不对外提供服务。设备认证服务器是TCP服务器,其端口不固定,用于设备认证,密钥协商。会话管理服务器是TCP服务器,其端口不固定,用于数据传输。
softbus_lite内部结构图

softbus_lite
Coap Server
消息队列处理线程
认证服务器
会话服务器
TCP
数据传输
TCP
设备认证
消息队列处理
UDP:5684
设备发现

softbus_lite支持网口和Wifi两种通信方式。

PublishService函数

PublishService函数的功能是创建coap服务器,消息队列处理线程,设备认证服务器,会话管理服务器,声明一个功能模块。只有调用了PublishService函数,softbus_lite才能向外提供服务。
PublishService函数处理流程如下。

PublishService
InitService
CoapInitDiscovery
CoapWifiEventThread
DoRegistService
写CoapHandleWifiEvent/1
DoRegistService
AddPublishModule
InitService
CoapRegistService
GetCapablityAndData
消息队列
handle.handler
ReadMsgQue
CreateCoapListenThread
CreateMsgQueThread
CoapInitWifiEvent
CoapInitSocket
CoapWriteMsgQueue:UPDATE_IP_EVENT
CoapInitDiscovery
CoapInit
RegisterWifiCallback:WifiEventTrigger
InitCommonManager

由于CoapInitDiscovery函数已打开消息队列处理线程,而CoapWriteMsgQueue(UPDATE_IP_EVENT)函数向消息队列发送了消息,将触发消息队列处理流程,将调用g_wifiCallback(para),这时g_wifiCallback为WifiEventTrigger,para为1,所以处理流程如下。

WifiEventTrigger
DoRegistService:COAP
CoapRegisterDeviceInfo
BusManager:1
CoapGetIp
GetCommonDeviceInfo

主要函数说明:

函数名功能说明
InitCommonManager()为g_deviceInfo赋值,包括deviceId,deviceName,version
RegisterWifiCallback(WifiEventTrigger)将g_wifiCallback赋值为WifiEventTrigger
CoapInitSocket()在端口5684上创建coap服务器,设置其socket为g_serverFd,设置g_msgId为0
CoapInitWifiEvent()创建消息队列“/wifiQue” ,设置其ID为g_wifiQueueId
CreateMsgQueThread()创建消息队列处理线程
CreateCoapListenThread()创建coap服务器处理线程
CoapWriteMsgQueue(UPDATE_IP_EVENT)向消息队列发送消息(消息结构为AddressEventHandler,handler为CoapHandleWifiEvent,state为UPDATE_IP_EVENT),触发消息队列处理
CoapWifiEventThread()消息队列处理线程,不停的从消息队列中取消息,执行消息的处理函数
WifiEventTrigger(para)para为1时打开认证服务器和会话管理服务器,否则关闭认证服务器和会话管理服务器,同时更新相关信息
GetCommonDeviceInfo()返回g_deviceInfo
CoapGetIp(wifiIp, MAX_DEV_IP_LEN, 0)获取本地IP,先读网口,网口不存在则读wifi地址
BusManager(1)为g_baseLister的onConnectEvent和onDataEvent赋值;启动认证服务器及处理线程;启动会话服务器及处理线程;保存认证端口为g_authPort,会话端口为g_sessionPort;
CoapRegisterDeviceInfo()从g_deviceInfo中获取deviceIp,deviceName,deviceId,deviceType,更新g_localDeviceInfo,g_interfaceList,g_networkType
DoRegistService(COAP)获取capabilityBitmap,更新g_capabilityData,g_localDeviceInfo.capabilityBitmap,g_localDeviceInfo.serviceData(认证端口)
AddPublishModule(moduleName, info)保存模块信息,包括名称,能力数据,publishId
GetCapablityAndData(capabilityBitmap, g_capabilityData, MAX_SERVICE_DATA_LEN)获取所有模块的能力bitmap和能力数据
CoapRegistService(capabilityBitmap, MAX_CAPABILITY_NUM, g_capabilityData)将能力bitmap和能力数据保存到g_localDeviceInfo中

coap服务器

coap服务器用于响应设备发现,检查接收报文是否合法,向外部设备提供自身的设备名称,设备ID,版本,模式,认证端口,IP地址,能力值等信息。其处理流程如下。

CoapReadHandle
PostServiceDiscover
COAP_SoftBusDecode
CoapSocketRecv
CoapResponseService
GetServiceDiscoverInfo

主要函数说明:

函数名功能说明
CoapReadHandle()coap服务器处理线程,不停监听coap服务器端口,收到报文后向对端发送自身设备信息
CoapSocketRecv(socketFd, recvBuffer, COAP_MAX_PDU_SIZE)从coap服务器端口获取报文
COAP_SoftBusDecode(&decodePacket, recvBuffer, nRead)从接收报文中解析信息,填充到COAP_Packet结构中
PostServiceDiscover(&decodePacket)解析信息,组织发送报文并发送
GetServiceDiscoverInfo(pkt->payload.buffer, pkt->payload.len, &deviceInfo, &remoteUrl)从接收报文中解析信息,填充deviceInfo和remoteUrl
CoapResponseService(pkt, remoteUrl, wifiIpAddr)从g_localDeviceInfo中获取设备名称,设备ID,版本,模式,认证端口,IP地址,能力值等,发送给对端5684端口

设备认证服务器

设备认证服务器用于设备认证,建立认证会话密钥,向外提供会话端口。其处理流程如下。

WaitProcess
ProcessConnectEvent
ProcessDataEvent
ProcessAuthData
AuthInterfaceOnDataReceived
OnDataReceived
ParsePacketHead
AuthConnRecv
OnModuleMessageReceived
DecryptMessage
AddAuthConnToList
创建AuthConn结构并赋值fd/ip

由于AuthInterfaceOnDataReceived函数主要处理流程在base/security/deviceauth目录下,这里不再展开。
OnModuleMessageReceived函数处理流程如下:

OnModuleMessageReceived
OnVerifyIp
获取CODE值
AuthConnPostMessage
MsgVerifyIpPack
MsgVerifyIpUnPack
BusGetLocalDeviceInfo

可见,如果客户端发送报文体中CODE域值为CODE_VERIFY_IP(即为1)时,服务器会将自身的会话端口返回给客户端。

从上可以看出,认证服务器主要工作有两个:

  1. 认证连接维护:接收客户端认证连接,记录到g_fdMap;
  2. 响应认证数据:解析客户端的认证数据,解析,并作相应处理;

主要函数说明:

函数名功能说明
WaitProcess()设备认证服务器处理线程
ProcessAuthData(g_listenFd, &readSet)接收客户端设备认证连接,接收客户端认证数据,进行认证处理
ProcessConnectEvent(g_dataFd, inet_ntoa(addrClient.sin_addr)将客户端的socket,ip保存到g_fdMap中
AddAuthConnToList(aconn)将客户端的AuthConn保存到g_fdMap中
AuthConnRecv(fd, buf, used, size - used, 0)接收客户端的认证报文并保存
ParsePacketHead(buf, processed, used - processed, size)解析报文头部
OnDataReceived(conn, pkt, buf + processed)处理接收报文,当头部module为MODULE_AUTH_SDK时调用AuthInterfaceOnDataReceived,其他则调用OnModuleMessageReceived
AuthInterfaceOnDataReceived(conn, pkt->module, pkt->seq, data, pkt->dataLen)执行设备认证
DecryptMessage(pkt->module, data, pkt->dataLen)解密报文体
OnModuleMessageReceived(conn, pkt->module, pkt->flags, pkt->seq, msg)获取设备其他信息,如会话端口
BusGetLocalDeviceInfo()返回g_deviceInfo
MsgVerifyIpUnPack(request, &connInfo, conn)接收报文验证;获取公共版本,对端设备名称,设备类型,认证端口,会话端口,保存到connInfo中
MsgVerifyIpPack(&connInfo, localDevInfo, g_authPort, g_sessionPort)构造Json对象,填入自身的CODE/版本/认证端口/会话端口/CONN_CAP/设备名称/设备类型/设备ID
AuthConnPostMessage(conn->fd, MODULE_CONNECTION, FLAG_REPLY, seq, reply)发送回复报文(内容加密)

会话管理服务器

会话管理服务器用于数据传输。进行数据传输之前需要如下条件:1)客户端与服务器做设备认证,建立认证会话密钥;2)服务器需要调用CreateSessionServer函数,来设置用于响应某个session的处理函数。
会话管理服务器处理流程如下。

SelectSessionLoop
ProcessConnection
ProcessSesssionData
ProcessConnection
ProcessSesssionData
listener->onSessionOpened
ResponseToClient
GetSessionListenerByName
AssignValue2Session
TransFirstPkg2Json
接收客户端数据
新连接
listener->onBytesReceived
TcpSessionRecv
GetSessionListenerByName
为session的deviceId/fd赋值
CreateTcpSession
accept
AddSession

主要函数说明:

函数名功能说明
SelectSessionLoop(tsm)会话管理服务器处理线程
ProcessConnection(tsm)处理会话连接请求
ProcessSesssionData(tsm, rfds)处理会话数据
CreateTcpSession()创建TcpSession对象并赋初置(sessionName为"softbus_Lite_unknown")
AddSession(tsm, session)将TcpSession对象保存到tsm的sessionMap_中;此场景stm为g_sessionMgr
TransFirstPkg2Json(data, dataLen + AUTH_PACKET_HEAD_SIZE)解析报文体为json对象并返回
AssignValue2Session(session, receiveObj)从json对象中获取sessionName和sessionKey,保存到session对象中
GetSessionListenerByName(session->sessionName, strlen(session->sessionName))根据sessionName获取对应的sessionListener
ResponseToClient(session)向客户端发送回复报文
TcpSessionRecv(session, buf, RECIVED_BUFF_SIZE, 0)接收客户端报文,保存到buf中

对外接口

设备发现接口

源码foundation/communication/softbus_lite/interfaces/kits/discovery/discovery_service.h定义了设备发现的对外函数接口和数据结构。
函数接口如下

函数声明参数说明功能说明
int PublishService(const char moduleName, const struct PublishInfo info, const struct IPublishCallback *cb)1)moduleName:服务名称,长度不大于63;2)info:服务的其他信息;3)cb:回调函数;4)返回值,0表示成功,-1 表示失败发布服务
int UnPublishService(const char *moduleName, int publishId)1)moduleName:服务名称,长度不大于63;2)publishId:服务ID;3)返回值,0表示成功,非0表示失败删除已发布的服务
int SetCommonDeviceInfo(const struct CommonDeviceInfo *devInfo, unsigned int num)1)devInfo:设备信息数组;2)num:设备信息数目;3)返回值,0表示成功,非0表示失败设置设备信息,如设备名称,设备ID,设备类型等信息

数据结构如下

typedef enum {
    /** Automatic medium selection */
    AUTO = 0,
    /** Bluetooth */
    BLE = 1,
    /** Wi-Fi */
    COAP = 2,
    /** USB */
    USB = 3,
} ExchangeMedium;
typedef enum {
    /** Low */
    LOW = 0,
   /** Medium */
    MID = 1,
   /** High */
    HIGH = 2,
   /** Super-high */
    SUPER_HIGH = 3,
} ExchangeFreq;
typedef struct PublishInfo {
  /** Service publishing ID */
    int publishId;
  /** Service publishing mode, which can be {@link DISCOVER_MODE_PASSIVE} or {@link DISCOVER_MODE_ACTIVE } */
    int mode;
  /** Service publishing medium */
    ExchangeMedium medium;
  /** Service publishing frequency */
    ExchangeFreq freq;
  /** Service publishing capabilities. For details, see {@link g_capabilityMap}. */
    const char *capability;
  /** Capability data for service publishing */
    unsigned char *capabilityData;
  /** Maximum length of the capability data for service publishing (2 bytes) */
    unsigned int dataLen;
} PublishInfo;

typedef enum {
   /** Unsupported medium */
    PUBLISH_FAIL_REASON_NOT_SUPPORT_MEDIUM = 1,
   /** Invalid parameter */
    PUBLISH_FAIL_REASON_PARAMETER_INVALID = 2,
   /** Unknown reason */
    PUBLISH_FAIL_REASON_UNKNOWN = 0xFF
} PublishFailReason;
typedef struct IPublishCallback {
    /** Callback for successful publishing */
    void (*onPublishSuccess)(int publishId);
    /** Callback for failed publishing */
    void (*onPublishFail)(int publishId, PublishFailReason reason);
} IPublishCallback;

typedef enum {
    /** Device ID. The value contains a maximum of 64 characters. */
    COMM_DEVICE_KEY_DEVID = 0,
    /** Device type. Currently, only <b>ddmpCapability</b> is supported. */
    COMM_DEVICE_KEY_DEVTYPE = 1,
    /** Device name. The value contains a maximum of 63 characters. */
    COMM_DEVICE_KEY_DEVNAME = 2,
    /** Reserved */
    COMM_DEVICE_KEY_MAX
} CommonDeviceKey;
typedef struct CommonDeviceInfo {
    /** Device information type. For details, see {@link CommonDeviceKey}. */
    CommonDeviceKey key;
    /** Content to set */
    const char *value;
} CommonDeviceInfo;

数据传输接口

源码foundation/communication/softbus_lite/interfaces/kits/transport/sesion.h定义了数据传输的对外函数接口和数据结构。
函数接口如下

函数声明参数说明功能说明
int CreateSessionServer(const char *mouduleName, const char *sessionName, struct ISessionListener *listener)1)mouduleName 服务名,长度不大于64;2)会话名,长度不大于64;3)listener 回调函数;4)返回值,0表示成功,-1表示失败根据服务名和会话名创建一个会话服务器
int RemoveSessionServer(const char *mouduleName, const char *sessionName)1)mouduleName 服务名,长度不大于64;2)会话名,长度不大于64;3)返回值,0表示成功,-1表示失败按服务名和会话名检索,移除该会话服务器
int SendBytes(int sessionId, const unsigned char *data, unsigned int len)1)sessionId 会话ID;2)data 发送数据buffer;3)len 发送数据长度,不能大雨984;4)返回值,0表示成功,-1表示失败向sessionId表示的连接发送数据
int GetMySessionName(int sessionId, char *sessionName, unsigned int len)1)sessionId 会话ID;2)sessionName 会话名称接收buffer;3)len 会话名称接收buffer大小;4)返回值,0表示成功,-1表示失败由sessionId获取会话名
int GetPeerSessionName(int sessionId, char *sessionName, unsigned int len)1)sessionId 会话ID;2)sessionName 会话名称接收buffer;3)len 会话名称接收buffer大小;4)返回值,0表示成功,-1表示失败由sessionId获取会话对端的会话名
int GetPeerDeviceId(int sessionId, char *devId, unsigned int len)1)sessionId 会话ID;2)devId 设备ID接收buffer;3)len 设备ID接收buffer大小;4)返回值,0表示成功,-1表示失败由sessionId获取会话对端的设备ID
void CloseSession(int sessionId)1)sessionId 会话ID关闭sessionId对应的会话连接

数据结构如下

struct ISessionListener {
    /**@brief Called when a session is opened.
     * This function can be used to verify the session or initialize resources related to the session.
     * @param sessionId Indicates the session ID.
     * @return Returns <b>0</b> if the session connection is accepted; returns a non-zero value
     * otherwise (you do not need to call {@link CloseSession} to close the session).
     * @since 1.0
     * @version 1.0
     */
    int (*onSessionOpened)(int sessionId);
    /**
     * @brief Called when a session is closed.
     * This function can be used to release resources related to the session.
     * You do not need to call {@link CloseSession}.
     * @param sessionId Indicates the session ID.
     * @since 1.0
     * @version 1.0
     */
    void (*onSessionClosed)(int sessionId);
    /**
     * @brief Called when data is received.
     * This function is used to notify that data is received.
     * @param sessionId Indicates the session ID.
     * @param data Indicates the pointer to the data received.
     * @param dataLen Indicates the length of the data received.
     * @since 1.0
     * @version 1.0
     */
    void (*onBytesReceived)(int sessionId, const void *data, unsigned int dataLen);
};

使用示例

标准使用方法

客户端 服务器 PublishService 客户端向服务器5684端口发送设备信息 服务器向客户端5684端口发送自身设备信息/认证端口 客户端向服务器认证端口发送设备信息/密钥信息 服务器回复自身设备信息/密钥信息 客户端向服务器认证端口发送验证IP消息 服务器回复自身会话端口 CreateSessionServer 客户端向服务器会话端口发送会话密钥 服务器响应 客户端向服务器会话端口发送消息 服务器响应 客户端 服务器

测试方法

由于对密钥交换,认证会话密钥的生成流程不清楚,要测试softbus_lite的数据传输功能,需要屏蔽与加解密相关的操作,也需要coap server将认证端口直接暴露出来。

数据传输报文(未加密)格式如下

序号字段偏移长度含义
1identified04识别码,用0xBABEFACE
2module44模块代码,可以不管
3seq88报文序号
4flags164flags,可以不管
5datalen204payload长度,以字节为单位
6payload24n报文体

数据传输报文(认证密钥加密)格式如下

序号字段偏移长度含义
1identified04识别码,用0xBABEFACE
2module44模块代码,可以不管
3seq88报文序号
4flags164flags,可以不管
5datalen204payload长度,以字节为单位
6authkey-index244认证会话对应的索引
7iv2812iv
8encrypt-playload40n报文体
9tag40+n16tag

数据传输报文(会话密钥加密)格式如下

序号字段偏移长度含义
1identified04识别码,用0xBABEFACE
2module44模块代码,可以不管
3seq88报文序号
4iv2812iv
5encrypt-playload40n报文体
6tag40+n16tag

测试1,设备发现。目标:获得认证端口与会话端口。
步骤如下。

  1. 服务端调用PublishService发布一个服务"softbus-server"
  2. 客户端向服务器5684端口发送coap发现请求
  3. 客户端收到服务器的返回报文后,确认该报文中含有服务器的设备信息,认证端口和会话端口

测试2,回声服务器(回声服务器是将收到的报文原封不动的发送回去)。目标:验证数据传输通路正确;
步骤如下。

  1. 服务端调用PublishService发布一个服务"softbus-server"
  2. 服务端调用CreateSessionServer创建一个会话服务器"echo-server"
  3. 客户端向服务器5684端口发送coap发现请求
  4. 客户端收到服务器的返回报文后,确认该报文中含有服务器的设备信息,认证端口和会话端口
  5. 客户端连接服务器会话端口
  6. 客户端向服务器会话端口发送报文后,服务器回复后,确认该报文中是否含有服务器的设备信息
  7. 客户端向服务器会话端口发送报文后,服务器回复后,确认该报文报文体与发送报文体一样
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:51:11  更:2022-04-04 12:55:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 21:26:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码