【对端发送的invitation req中channel list和operating channel的operating class不对应】

问题背景

问题场景

在某些 PC 设备(特别是 Windows 10/11 的 Miracast 实现)中,发送 P2P Invitation Request 时可能出现以下情况:

  1. Channel List attribute 中可能包含某些信道,但这些信道的 operating class 编码可能不完整或有问题
  2. Operating Channel attribute 中指定的信道本身是有效的,本地设备也支持
  3. 但由于 Channel List 的问题,导致计算出的 intersection(信道交集) 不包含 Operating Channel 中指定的信道
  4. 原代码只检查 Operating Channel 是否在 intersection 中,导致连接失败

实际表现

  • 对端 PC 发起 Invitation Request
  • 本地设备计算双方信道交集(intersection)
  • 检查对端的 Operating Channel 是否在交集中
  • 如果不在交集中,直接返回 P2P_SC_FAIL_NO_COMMON_CHANNELS 失败
  • 但实际上 Operating Channel 本身是有效的,本地也支持

改动内容详细分析

改动位置

文件 : src/p2p/p2p_invitation.c
函数 : p2p_process_invitation_req()
位置: 约第 325-333 行

改动前(原代码)

c 复制代码
if (req_freq > 0 &&
    p2p_channels_includes(&intersection,
                          msg.operating_channel[3],
                          msg.operating_channel[4])) {
    // 使用对端的 operating channel
    p2p->op_reg_class = msg.operating_channel[3];
    p2p->op_channel = msg.operating_channel[4];
}

逻辑 : 只检查对端的 Operating Channel 是否在 双方信道的交集(intersection) 中。

改动后(新代码)

c 复制代码
if (req_freq > 0 &&
    (p2p_channels_includes(&intersection,
                          msg.operating_channel[3],
                          msg.operating_channel[4]) ||
     p2p_channels_includes(&p2p->cfg->channels,
                          msg.operating_channel[3],
                          msg.operating_channel[4]))) {
    // 使用对端的 operating channel
    p2p->op_reg_class = msg.operating_channel[3];
    p2p->op_channel = msg.operating_channel[4];
}

逻辑 : 检查对端的 Operating Channel 是否在 intersection或者本地配置的信道列表(p2p->cfg->channels) 中。


改动原因分析

为什么这样改?

  1. 兼容性考虑:

    • 某些 PC 设备的 P2P 实现可能有 bug,导致 Channel List 和 Operating Channel 的 operating class 不对应
    • 如果 Operating Channel 本身是有效的且本地支持,应该接受它,而不是因为 Channel List 的问题而拒绝
  2. 更宽松的信道检查:

    • 原逻辑:Operating Channel 必须在双方都支持的交集中
    • 新逻辑:Operating Channel 在交集中 或者 在本地支持的信道列表中即可
    • 这样可以绕过对端 Channel List 的问题
  3. 实际效果:

    • 提高了与有缺陷的 PC 设备的兼容性
    • 减少了因 Channel List 编码问题导致的连接失败

潜在影响分析

✅ 正面影响

  1. 提高兼容性: 能够连接 Channel List 有问题的 PC 设备
  2. 减少失败率 : 避免因对端实现缺陷导致的 P2P_SC_FAIL_NO_COMMON_CHANNELS 错误
  3. 更灵活的协商: 即使交集中没有对端偏好的信道,只要本地支持就接受

⚠️ 潜在风险

  1. 可能违反协议规范:

    • 理论上,Operating Channel 应该在使用双方信道的交集中
    • 如果对端在 Channel List 中没有包含某个信道,但又在 Operating Channel 中指定它,这可能表示对端实现有问题
    • 但为了兼容性,放宽检查是合理的
  2. 后续信道验证:

    • 虽然这里接受了对端的 Operating Channel,但后续(第 344-359 行)还会检查最终选择的信道是否在交集中
    • 如果是 GO 角色,还会重新选择信道(p2p_reselect_channel
    • 所以实际使用的信道最终还是会通过验证

代码流程说明

Invitation Request 处理流程(简化)

  1. 解析 Invitation Request

    • 提取对端的 Channel List
    • 提取对端的 Operating Channel preference
    • 计算双方信道的交集(intersection)
  2. 检查 Operating Channel(本 patch 改动点)

    • 原逻辑: 只检查是否在 intersection 中
    • 新逻辑 : 检查是否在 intersection 中 在本地 channels 中
    • 如果通过,使用对端的 Operating Channel preference
  3. 后续验证(如果本端是 GO)

    • 检查最终选择的信道是否在 intersection 中
    • 如果不在,重新选择信道(p2p_reselect_channel
    • 如果重新选择后仍不在交集中,返回失败

关键点

  • 本 patch 的作用: 放宽了接受对端 Operating Channel 的条件,允许即使在交集中没有,只要本地支持就接受
  • 后续保护机制: 后续的信道重新选择逻辑会确保最终使用的信道是双方都支持的

总结

改动目的

修复因对端 PC 设备 Channel List 和 Operating Channel 不对应导致的连接失败问题。

改动方式

放宽 Operating Channel 的检查条件:不仅检查是否在双方信道的交集中,也检查是否在本地支持的信道列表中。

实际效果

  • ✅ 提高与有缺陷的 PC 设备的兼容性
  • ✅ 减少 P2P_SC_FAIL_NO_COMMON_CHANNELS 错误
  • ✅ 保持协议安全性(后续还有信道验证)

适用场景

  • 对端 PC 发送的 Invitation Request 中 Channel List 编码有问题
  • 但 Operating Channel 本身是有效的
  • 本地设备支持该 Operating Channel
c 复制代码
    fix status is P2P_SC_FAIL_NO_COMMON_CHANNELS when computer channel list error
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index d39aa38..a0b7f5f 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -322,9 +322,12 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
 			p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
 				req_freq);
 			if (req_freq > 0 &&
-			    p2p_channels_includes(&intersection,
-						  msg.operating_channel[3],
-						  msg.operating_channel[4])) {
+				(p2p_channels_includes(&intersection,
+									  msg.operating_channel[3],
+									  msg.operating_channel[4]) ||
+				p2p_channels_includes(&p2p->cfg->channels,
+									  msg.operating_channel[3],
+									  msg.operating_channel[4]))) {
 				p2p->op_reg_class = msg.operating_channel[3];
 				p2p->op_channel = msg.operating_channel[4];
 				p2p_dbg(p2p, "Use peer preference op_class %d channel %d",
相关推荐
报错小能手39 分钟前
数据结构 哈希表(链地址法)
数据结构·哈希算法·散列表
液态不合群1 小时前
链表的基本操作,用链表实现线性表
数据结构·链表
步步为营DotNet2 小时前
深度剖析ASP.NET Core Middleware:构建高效请求处理管道的关键
后端·asp.net
_OP_CHEN2 小时前
【C++数据结构进阶】从 Redis 底层到手写实现!跳表(Skiplist)全解析:手把手带你吃透 O (logN) 查找的神级结构!
数据结构·数据库·c++·redis·面试·力扣·跳表
名誉寒冰2 小时前
Redis 常用数据结构与实战避坑指南
数据结构·数据库·redis
girl-07262 小时前
2025.12.26代码分析
数据结构·算法
蒙奇D索大2 小时前
【数据结构】排序算法精讲|折半插入排序全解:高效优化、性能对比、实战剖析
数据结构·学习·考研·算法·排序算法·改行学it
聆风吟º3 小时前
【数据结构手札】顺序表实战指南(四):头插 | 头删
数据结构·顺序表·头插·头删
zore_c3 小时前
【C语言】排序算法——快速排序详解(含多种变式)!!!
c语言·数据结构·笔记·算法·排序算法·深度优先·推荐算法