【对端发送的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",
相关推荐
骇客野人1 小时前
JAVA获取一个LIST中的最大值
java·linux·list
傻小胖1 小时前
第3讲:BTC-数据结构-北大肖臻老师客堂笔记
数据结构
xlq223222 小时前
23.二叉树搜索树(下)
数据结构·c++·算法
lzh200409192 小时前
【数据结构】二叉搜索树
数据结构·算法
古月居GYH2 小时前
数据结构算法——排序算法解析
数据结构·算法·排序算法
人得思变~谁会嫌自己帅呢?2 小时前
希尔排序算法
数据结构·算法·排序算法
福尔摩斯张2 小时前
C语言文件操作详解(一):文件的打开与关闭(详细)
java·linux·运维·服务器·c语言·数据结构·算法
K哥11252 小时前
【9天Redis系列】数据结构+string
数据结构·数据库·redis
minji...2 小时前
Linux 进程控制(二) (进程等待wait/waitpid)
linux·运维·服务器·数据结构