小智机器人关键函数解析:MqttProtocol::SendAudio()对输入的音频数据进行加密处理,通过UDP发送加密后的音频数据
MqttProtocol::SendAudio()对输入的音频数据进行加密处理,通过UDP发送加密后的音频数据。
源码:
void MqttProtocol::SendAudio(const std::vector<uint8_t>& data) {
// 使用互斥锁保护临界区,确保同一时间只有一个线程可以访问该函数内的共享资源
std::lock_guard<std::mutex> lock(channel_mutex_);
// 检查udp_指针是否为空,如果为空则直接返回,避免后续操作出现空指针异常
if (udp_ == nullptr) {
return;
}
// 复制aes_nonce_到nonce字符串中,用于后续加密操作
std::string nonce(aes_nonce_);
// 将音频数据的大小(以网络字节序)存储到nonce字符串的第2个字节开始的位置
*(uint16_t*)&nonce[2] = htons(data.size());
// 将本地序列号(以网络字节序)存储到nonce字符串的第12个字节开始的位置,并递增本地序列号
*(uint32_t*)&nonce[12] = htonl(++local_sequence_);
// 创建一个字符串encrypted,用于存储加密后的数据,其大小为nonce的大小加上音频数据的大小
std::string encrypted;
encrypted.resize(aes_nonce_.size() + data.size());
// 将nonce数据复制到encrypted字符串的开头
memcpy(encrypted.data(), nonce.data(), nonce.size());
// 初始化计数器偏移量
size_t nc_off = 0;
// 初始化一个16字节的流块,用于AES加密
uint8_t stream_block[16] = {0};
// 使用AES-CTR模式对音频数据进行加密
if (mbedtls_aes_crypt_ctr(&aes_ctx_, data.size(), &nc_off, (uint8_t*)nonce.c_str(), stream_block,
(uint8_t*)data.data(), (uint8_t*)&encrypted[nonce.size()]) != 0) {
// 如果加密失败,记录错误日志并返回
ESP_LOGE(TAG, "Failed to encrypt audio data");
return;
}
// 通过UDP发送加密后的音频数据
udp_->Send(encrypted);
}
以下是对 MqttProtocol::SendAudio
函数的详细解释:
函数概述
MqttProtocol::SendAudio
函数的主要功能是对输入的音频数据进行加密处理,然后通过UDP(User Datagram Protocol)发送加密后的音频数据。
代码详细解释
void MqttProtocol::SendAudio(const std::vector<uint8_t>& data) {
// 使用互斥锁保护临界区,确保同一时间只有一个线程可以访问该函数内的共享资源
std::lock_guard<std::mutex> lock(channel_mutex_);
// 检查udp_指针是否为空,如果为空则直接返回,避免后续操作出现空指针异常
if (udp_ == nullptr) {
return;
}
// 复制aes_nonce_到nonce字符串中,用于后续加密操作
std::string nonce(aes_nonce_);
// 将音频数据的大小(以网络字节序)存储到nonce字符串的第2个字节开始的位置
*(uint16_t*)&nonce[2] = htons(data.size());
// 将本地序列号(以网络字节序)存储到nonce字符串的第12个字节开始的位置,并递增本地序列号
*(uint32_t*)&nonce[12] = htonl(++local_sequence_);
// 创建一个字符串encrypted,用于存储加密后的数据,其大小为nonce的大小加上音频数据的大小
std::string encrypted;
encrypted.resize(aes_nonce_.size() + data.size());
// 将nonce数据复制到encrypted字符串的开头
memcpy(encrypted.data(), nonce.data(), nonce.size());
// 初始化计数器偏移量
size_t nc_off = 0;
// 初始化一个16字节的流块,用于AES加密
uint8_t stream_block[16] = {0};
// 使用AES-CTR模式对音频数据进行加密
if (mbedtls_aes_crypt_ctr(&aes_ctx_, data.size(), &nc_off, (uint8_t*)nonce.c_str(), stream_block,
(uint8_t*)data.data(), (uint8_t*)&encrypted[nonce.size()]) != 0) {
// 如果加密失败,记录错误日志并返回
ESP_LOGE(TAG, "Failed to encrypt audio data");
return;
}
// 通过UDP发送加密后的音频数据
udp_->Send(encrypted);
}
各部分详细解释
-
互斥锁保护:
std::lock_guard<std::mutex> lock(channel_mutex_);
使用
std::lock_guard
来自动管理channel_mutex_
互斥锁,确保同一时间只有一个线程可以访问该函数内的共享资源,避免数据竞争。 -
空指针检查:
if (udp_ == nullptr) { return; }
检查
udp_
指针是否为空,如果为空则直接返回,避免后续操作出现空指针异常。 -
准备加密参数:
std::string nonce(aes_nonce_); *(uint16_t*)&nonce[2] = htons(data.size()); *(uint32_t*)&nonce[12] = htonl(++local_sequence_);
- 复制
aes_nonce_
到nonce
字符串中。 - 将音频数据的大小(以网络字节序)存储到
nonce
字符串的第2个字节开始的位置。 - 将本地序列号(以网络字节序)存储到
nonce
字符串的第12个字节开始的位置,并递增本地序列号。
- 复制
-
初始化加密结果字符串:
std::string encrypted; encrypted.resize(aes_nonce_.size() + data.size()); memcpy(encrypted.data(), nonce.data(), nonce.size());
- 创建一个字符串
encrypted
,用于存储加密后的数据,其大小为nonce
的大小加上音频数据的大小。 - 将
nonce
数据复制到encrypted
字符串的开头。
- 创建一个字符串
-
AES-CTR加密:
size_t nc_off = 0; uint8_t stream_block[16] = {0}; if (mbedtls_aes_crypt_ctr(&aes_ctx_, data.size(), &nc_off, (uint8_t*)nonce.c_str(), stream_block, (uint8_t*)data.data(), (uint8_t*)&encrypted[nonce.size()]) != 0) { ESP_LOGE(TAG, "Failed to encrypt audio data"); return; }
- 初始化计数器偏移量
nc_off
和流块stream_block
。 - 使用
mbedtls_aes_crypt_ctr
函数对音频数据进行加密,将加密结果存储在encrypted
字符串中。 - 如果加密失败,记录错误日志并返回。
- 初始化计数器偏移量
-
发送加密后的数据:
udp_->Send(encrypted);
通过UDP发送加密后的音频数据。