文件互传在传输层的操作分析

文件互传在传输层的操作分析
前言文件消息在业务层经过组装成帧了以后这里分析的文件消息是指文件数据发送完后会发送文件列表到对端进行完整性核对完整的帧会发送到传输层进行分片、打包、加密第一步确认是否支持TLV打包格式以及是否需要ACK确认函数签名int32_t GetSupportTlvAndNeedAckById( int32_t channelId, int32_t channelType, bool *supportTlv, bool *needAck)参数含义channelId通道 IDchannelType通道类型代理通道/直连通道等supportTlv输出参数是否支持 TLV 格式可为 NULL表示不关心needAck输出参数是否需要 ACK 确认可为 NULL表示不关心可靠传输supportTlv和needAck是在通道建立时协商的——双方在握手过程中交换能力信息决定是否使用 TLV 新格式、是否启用可靠传输ACK然后存入SessionInfo中。这个函数只是读取协商结果。第二步打包加密分支一传统打包流程图1.获取加密所需信息从通道获取加密所需的信息int32_t seq info-sequence; char *sessionKey info-sessionKey;2.计算输出长度并分配缓冲区outlen:输出长度 原始帧序列长度 加密开销 协议头大小加密开销OVERHEAD_LEN AES-GCM 的额外开销 IV(12B) Tag(16B) 28B协议头大小: sizeof(PacketHead) 分片个数 * (int32)dataInfo-outLen dataInfo-inLen OVERHEAD_LEN sizeof(PacketHead); dataInfo-outData (uint8_t *)SoftBusCalloc(dataInfo-outLen);3.准备加密密钥cipherKey.keyLen SESSION_KEY_LENGTH; if (memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, sessionKey, SESSION_KEY_LENGTH) ! EOK) { TRANS_LOGE(TRANS_SDK, memcpy key error.); SoftBusFree(dataInfo-outData); return SOFTBUS_MEM_ERR; }将会话密钥拷贝到加密结构体中供AES-GCM使用。4.加密char *outData (char *)dataInfo-outData sizeof(PacketHead); int32_t ret SoftBusEncryptDataWithSeq(cipherKey, dataInfo-inData, dataInfo-inLen, // 明文输入 (unsigned char *)outData, outLen, // 密文输出写在 PacketHead 之后 seq); // 序列号参与加密输出密文写在缓冲区sizeof(PacketHead)的位置前面留出 16 字节给协议头。SoftBusEncryptDataWithSeq用序列号参与加密使得即使相同明文 相同密钥不同序列号产生的密文也不同防止重放攻击。5.加密后立即清零密钥安全措施防止残存栈中(void)memset_s(cipherKey.key, SESSION_KEY_LENGTH, 0, SESSION_KEY_LENGTH);6.校验加密结果校验结果必须精确等于inLen OVERHEAD_LEN28字节开销否则加密出错if (ret ! SOFTBUS_OK || outLen ! dataInfo-inLen OVERHEAD_LEN) { SoftBusFree(dataInfo-outData); return SOFTBUS_TRANS_PROXY_SESS_ENCRYPT_ERR; }7.填充协议头PacketHead将协议头填充到前面的16字节然后转换成网络字节序大端字节序PacketHead *pktHead (PacketHead *)dataInfo-outData; pktHead-magicNumber MAGIC_NUMBER; // 0xBABEFACE pktHead-seq seq; // 序列号 pktHead-flags flag; // 帧类型 pktHead-dataLen outLen - sizeof(PacketHead); // 密文数据长度 ClientPackPacketHead(pktHead); // 转网络字节序分支二TLV打包函数签名/foundation/communication/dsoftbus/sdk/transmission/trans_channel/proxy/src/client_trans_proxy_manager.cstatic int32_t ClientTransProxyPackTlvBytes( int32_t channelId, ClientProxyDataInfo *dataInfo, ProxyChannelInfoDetail *info, uint32_t dataSeq, SessionPktType flag)参数和传统打包一致只是内部走TLV格式。TLV介绍简单来说是Type-Length-ValueTLV 就是一种自带说明书的编码方式——每个字段前面标注我是什么Type和我有多长Length接收端不需要预先知道数据格式就能解析遇到不认识的字段跳过即可天然支持扩展和兼容传统的打包包头是固定结构体struct PacketHead { int32_t magicNumber; // 偏移0固定4字节 int32_t seq; // 偏移4固定4字节 int32_t flags; // 偏移8固定4字节 int32_t dataLen; // 偏移12固定4字节 };TLV是可变的结构体在包头的结构体中每一个项都是上面那样的结构根据type识别字段不认识就跳过与固定结构体的区别--可扩展[Type0][Len4][seq的值] [Type2][Len4][flags的值] [Type4][Len4][dataLen的值] [Type3][Len1][needAck的值] ← 新增字段 [Type1][Len4][dataSeq的值] ← 新增字段1.准备参数tlv支持加入ack确认int32_t seq info-sequence; char *sessionKey info-sessionKey; uint32_t dataLen dataInfo-inLen OVERHEAD_LEN; // 加密后的数据长度 bool needAck false; GetSupportTlvAndNeedAckById(channelId, CHANNEL_TYPE_PROXY, NULL, needAck);2.构建tlv数据头DataHead pktHead; int32_t tlvBufferSize 0; ProxyBuildTlvDataHead(pktHead, seq, flag, dataLen, tlvBufferSize); ProxyBuildNeedAckTlvData(pktHead, needAck, dataSeq, tlvBufferSize);这两步把各个字段组装成 TLV 元素ProxyBuildTlvDataHead构建基础字段seq、flag、dataLenProxyBuildNeedAckTlvData构建扩展字段needAck、dataSeq3.序列化tlv头部dataInfo-outData TransProxyPackTlvData(pktHead, tlvBufferSize, dataLen);把datahead结构内存中的tlv元素列表序列化为连续的字节流输出缓冲区布局为[magicNum(4B)][tlvCount(1B)][TLV元素1][TLV元素2]...[预留加密数据空间]4.计算输出总长度int32_t newDataHeadSize MAGICNUM_SIZE TLVCOUNT_SIZE tlvBufferSize; dataInfo-outLen dataInfo-inLen OVERHEAD_LEN (uint32_t)newDataHeadSize;总长度 TLV头部大小 加密数据大小 (魔数 TLV计数 TLV元素总长) (原始数据 AES-GCM开销)5.加密与传统打包没有太大的区别加密结果写在头部的后面只不过头部大小参数从原来的固定16字节变成了可变的newDataHeadSizechar *outData (char *)dataInfo-outData newDataHeadSize; SoftBusEncryptDataWithSeq(cipherKey, dataInfo-inData, dataInfo-inLen, (unsigned char *)outData, outLen, seq);6.清零密钥和传统打包没区别回归主线文件互传模块我之前是以为看的差不多了直到分片看完了我才发现softbus SDK还是属于在应用层还没到软总线层把业务线设计的好复杂不是说难就字面意思怎么这么多校验总结一下目前的进度已经看的没看的层所在进程核心职责1. NAPI应用JS→C 桥接2. Session 服务应用权限检查、sessionId→channelId 映射3. 通道管理应用按通道类型UDP/Proxy分发4. 文件管理应用文件锁、发送上下文、流程控制5. 文件发送控制应用逐文件发送、读文件、分帧6. 流发送应用查通道信息、委托打包发送7. 打包分片应用加密、TLV/PacketHead、4KB 分片8. IPC 代理应用序列化、Binder 跨进程9. 服务端系统服务反序列化、socket 网络发送