📌往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)
①📖 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
②📖嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
③📖 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
④📖 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
⑤📖 记录一场鸿蒙开发岗位面试经历~
⑥📖 持续更新中……
一、概述
在HiChain本端接收数据的处理过程中:(1)在正确解析并处理完接收的数据之后,应构造相应的通知消息回复给对端。(2)在消息处理过程中会有出现错误的情况,在发现错误之后,应针对相应的错误情况通知对端,否则对端会一直处于未知状态。本文将介绍回复通知的相应过程。
二、源码分析
这一模块的源码位于:/base/security/deviceauth。
- 在receive_data函数中,出现错误会跳转到inform处,在inform阶段,首先调用函数encap_inform_message为通知消息申请内存空间,详细分析如下:
//为通知消息负载申请空间
static void encap_inform_message(int32_t error_code, struct message *send)
{
if ((error_code == HC_OK) || (send->msg_code != INFORM_MESSAGE) || (send->payload != NULL)) {
return;//如果错误码为0或者不等于INFORM_MESSAGE或者发送负载为空就直接返回
}
int32_t *err = (int32_t *)MALLOC(sizeof(int32_t));//申请内存空间
if (err == NULL) {
LOGE("Malloc for encape inform message failed");
return;
}
*err = error_code;//赋值错误码
send->payload = err;//赋值负载地址
}
- 紧接着执行build_send_data_by_struct函数,构造通知消息,详细分析如下:
/*
函数功能:构造结构化的发送消息
函数参数:
message:输出参数,消息地址
send_data:输出参数,消息有效载荷地址
send_data_len:输出参数,消息有效载荷长度
函数返回值:
成功:返回0
失败:返回错误码
*/
static int32_t build_send_data_by_struct(const struct message *message, void **send_data, uint32_t *send_data_len)
{
//消息构造表
const struct make_message_map map[] = { { PAKE_REQUEST, make_pake_request },//构造pake请求消息
{ PAKE_RESPONSE, make_pake_response },//构造pake响应消息
{ PAKE_CLIENT_CONFIRM, make_pake_client_confirm },//构造pake协议客户端认证消息
{ PAKE_SERVER_CONFIRM_RESPONSE, make_pake_server_confirm },//构造pake协议服务端认证消息
{ AUTH_START_REQUEST, make_auth_start_request },//构造认证开始请求消息
{ AUTH_START_RESPONSE, make_auth_start_response },//构造认证开始响应消息
{ AUTH_ACK_REQUEST, make_auth_ack_request },//构造认证确认请求消息
{ AUTH_ACK_RESPONSE, make_auth_ack_response },//构造认证确认响应消息
{ ADD_AUTHINFO_REQUEST, make_add_auth_info_request },//构造添加认证信息请求消息
{ REMOVE_AUTHINFO_REQUEST, make_rmv_auth_info_request },//构造移除认证信息请求消息
{ ADD_AUTHINFO_RESPONSE, make_add_auth_info_response },//构造添加认证信息响应消息
{ REMOVE_AUTHINFO_RESPONSE, make_rmv_auth_info_response },//构造移除认证信息响应消息
{ EXCHANGE_REQUEST, make_exchange_request },//构造交换信息请求消息
{ EXCHANGE_RESPONSE, make_exchange_response },//构造交换信息响应消息
{ SEC_CLONE_START_RESPONSE, sec_clone_make_srv_proof },
{ SEC_CLONE_ACK_RESPONSE, sec_clone_make_clone_ret },
{ INFORM_MESSAGE, make_inform_message } };//构造通知消息
if (message->msg_code == INVALID_MESSAGE) {//如果消息码为无效,则返回“无消息发送”
return HC_NO_MESSAGE_TO_SEND;
}
if (message->payload == NULL) {//如果发送负载为空,则返回错误码
LOGE("Message payload is null");
return HC_BUILD_SEND_DATA_FAILED;
}
for (uint32_t i = 0; i < sizeof(map) / sizeof(struct make_message_map); i++) {//遍历消息构造表
if (map[i].msg_code != message->msg_code) {
continue;
}
*send_data = map[i].make_message(message->payload);//调用构造消息回调函数!!!
if (*send_data == NULL) {//构造消息失败
return HC_BUILD_SEND_DATA_FAILED;
}
*send_data_len = strlen(*send_data);//构造消息成功,获取长度
return HC_OK;
}
LOGE("Unsupport encape 0x%04x message", message->msg_code);
return HC_INNER_ERROR;
}
- 然后调用软总线模块的数据传输模块发送通知消息,最后执行set_result函数设置hichain的处理结果及状态,该函数的分析如下:
/*
函数功能:设置最终结果信息,即HiChain状态
函数参数:
hichain:hichain实例对象
rcv_msg_code:接收消息码
snd_msg_code:发送消息码
error_code:错误码
函数返回值:无
*/
static void set_result(struct hichain *hichain, uint16_t rcv_msg_code, uint16_t snd_msg_code, int32_t error_code)
{
if (error_code != HC_OK) {//如果错误码不是0,则直接跳转到error,按对应错误码设置结果
LOGE("Error code is not ok, and set end failed");
goto error;
}
if (snd_msg_code == INFORM_MESSAGE) {//如果发送消息码为通知消息,则直接跳转到error
LOGE("Send an inform message, and set end failed");
goto error;
}
//消息结果表
const struct msg_result_map map[] = { { PAKE_REQUEST, KEY_AGREEMENT_PROCESSING, KEY_AGREEMENT_STATE },//密钥协商过程中
{ PAKE_RESPONSE, KEY_AGREEMENT_PROCESSING, KEY_AGREEMENT_STATE },//密钥协商过程中
{ PAKE_CLIENT_CONFIRM, KEY_AGREEMENT_END, OPERATION_STATE },//密钥协商结束
{ PAKE_SERVER_CONFIRM_RESPONSE, KEY_AGREEMENT_END, OPERATION_STATE },//密钥协商结束
{ EXCHANGE_REQUEST, END_SUCCESS, OVER_STATE },
{ EXCHANGE_RESPONSE, END_SUCCESS, OVER_STATE },
{ AUTH_START_REQUEST, KEY_AGREEMENT_PROCESSING, KEY_AGREEMENT_STATE },
{ AUTH_START_RESPONSE, KEY_AGREEMENT_PROCESSING, KEY_AGREEMENT_STATE },
{ AUTH_ACK_REQUEST, KEY_AGREEMENT_END, OPERATION_STATE },
{ AUTH_ACK_RESPONSE, KEY_AGREEMENT_END, OPERATION_STATE },
{ ADD_AUTHINFO_REQUEST, END_SUCCESS, OVER_STATE },
{ ADD_AUTHINFO_RESPONSE, END_SUCCESS, OVER_STATE },
{ REMOVE_AUTHINFO_REQUEST, END_SUCCESS, OVER_STATE },
{ REMOVE_AUTHINFO_RESPONSE, END_SUCCESS, OVER_STATE },
{ SEC_CLONE_START_REQUEST, OPERATION_PROCESSING, OPERATION_STATE },
{ SEC_CLONE_ACK_REQUEST, END_SUCCESS, OVER_STATE },
{ INFORM_MESSAGE, END_FAILED, OVER_STATE },
{ INVALID_MESSAGE, KEY_AGREEMENT_PROCESSING, KEY_AGREEMENT_STATE } };
const struct msg_result_map *map_ptr = select_result_map(rcv_msg_code, map,
sizeof(map) / sizeof(struct msg_result_map));//根据接收的消息码查找结果表
set_result_by_map(hichain, map_ptr);//根据结果表内容设置最终结果
return;
error:
hichain->last_state = hichain->state;//将hc当前状态赋给last_state
hichain->state = OVER_STATE;//设置hc当前状态为OVER_STATE
hichain->cb.set_service_result(&hichain->identity, END_FAILED);//调用软总线模块回调函数设置服务结果为END_FAILED
}
//查找结果表
const struct msg_result_map *select_result_map(uint16_t rcv_msg_code, const struct msg_result_map *map, uint32_t n)
{
for (uint32_t i = 0; i < n; i++) {//遍历结果表,通过接收消息码查找对应结果及状态
if (rcv_msg_code == map[i].msg_code) {
return &map[i];
}
}
return NULL;
}
/*
函数功能:根据结果表内容设置最终结果
函数参数:
hichain:hichain实例对象
map:结果表对应表项
函数返回值:无
*/
static void set_result_by_map(struct hichain *hichain, const struct msg_result_map *map)
{
if (map == NULL) {//如果结果表为空,则直接返回
return;
}
if (map->state != OPERATION_STATE) {//如果hc状态不是操作状态,跳转到out
goto out;
}
if ((hichain->operation_code != AUTHENTICATE) && (hichain->operation_code != AUTH_KEY_AGREEMENT)) {//如果hc操作码不是身份认证和密钥协商,则跳转out
goto out;
}
if (hichain->state != OVER_STATE) {//如果hc当前状态不是OVER_STATE
hichain->last_state = hichain->state;//将hc当前状态赋给last_state
hichain->state = OVER_STATE;//设置当前状态为OVER_STATE
}
hichain->cb.set_service_result(&hichain->identity, END_SUCCESS);//调用软总线模块回调函数设置服务结果为END_SUCCESS
return;
out:
if (hichain->state != map->state) {//如果hc当前状态不是结果表对应状态
hichain->last_state = hichain->state;//将hc当前状态赋给last_state
hichain->state = map->state;//设置当前状态为结果表对应状态
}
hichain->cb.set_service_result(&hichain->identity, map->result);//调用软总线模块回调函数设置服务结果为结果表对应结果
}