首先感谢各位兄弟姐妹们的耐心等待。根据今天获得的消息,本书预计在下周各大网店提供预订。注意,此处连载的是未经出版社编辑的原始稿件,因此样子会有些非专业。html
注意,以下是本章目录,本文节选7.1~7.2.2 7.4~7.4.1.2节,7.5sass
为了方便读者深刻学习,本系列连载都会将做者研究过安全
程中所学习的参考文献列出来网络
承接第6章介绍的WSC,本章将继续介绍Wi-Fi Alliance(Wi-Fi联盟)推出的另一项重要技术规范Wi-Fi P2P。该规范的商品名为Wi-Fi Direct,它支持多个Wi-Fi设备在没有AP的状况下相互链接。数据结构
在Android平台的Wi-Fi相关模块中,P2P的功能点主要集中在:架构
和WSC同样,本章的分析拟采用以下方法:并发
下面,先来认识一下P2P。框架
WFA定义的P2P协议文档全名为“Wi-Fi Peer-to-Peer(P2P) Technical Specification”,目前的版本为1.1,全长160页。P2P技术使得多个Wi-Fi设备在没有AP的状况下也能构成一个网络(P2P Network,也被称之为P2P Group)并相互通讯。less
Wi-Fi P2P技术是Wi-Fi Display(也称之为Miracast,详情请参考做者的一篇博文http://blog.csdn.net/innost/article/details/8474683)的基础。在Miracast应用场景中,一台支持P2P的智能手机可直接链接上一台支持P2P的智能电视,智能手机随后将本身的屏幕,或者媒体资源传送给电视机去显示或播放。显然,借助P2P技术,Wi-Fi设备之间的直接相连将极大拓展Wi-Fi技术的使用场景。socket
注意:根据笔者本身的判断,随着支持愈来愈多的设备支持P2P和Miracast,智能终端设备之间的多屏共享和互动功能将很快得以实现。另外,恰逢本章撰写之际,Google发布了Android 4.3。在此次发布盛会上,Google推出了ChromeCast设备。目前,ChromeCast的技术实现细节还不清楚,听说有多是Google本身定义的Google cast协议(可参考developers.google.com/cast)。
下面先简单介绍一下P2P的架构。
P2P架构中定义了三个组件,笔者将其称之为一个设备,两种角色。这三个组件分别是:
相信对本书的读者对上面这三个组件的概念并不陌生。实际上,P2P技术模仿了Infrastructure BSS网络结构:
最终构成的这个P2P Group组织结构如图7-1所示:
图7-1 P2P Group示意图
图7-1展现了一个典型P2P Group的构成,其中:
注意:“不支持P2P功能”更准确的定义是指不能处理P2P协议。在P2P网络中,GO等同于AP,因此Legacy Clients也能搜索到GO并关联上它。不过,因为Legacy Clients不能处理P2P协议,因此P2P一些特有功能在这些Legacy Clients中没法实现。
经过上述介绍读者会进一步发现P2P Group和Infrastructure BSS的类似性:
这部份内容和Infrastructure BSS中STA利用WSC先协商安全信息而后再关联至AP的流程彻底同样。正是这种类似性,使得P2P能充分利用现有的一些技术规范。图7-2所示为P2P及其依赖的技术项:
图7-2 P2P及其依赖的技术项
由图7-2可知:
在如图7-2所示的技术项中,P2P Discovery是P2P所特有的,也是其核心。本章将主要围绕它进行介绍。首先来看P2P Discovery。
提示:
1、P2P Group Operation讲得是GO如何管理一个Group,也就是GO的工做职责。这部份内容请读者自行学习参考资料[2]一节。
2、P2P PowerManagement和P2P设备的电源管理有关,用于节省没必要要的电力损耗。因为篇幅关系,本章不拟讨论它。请感兴趣的读者自行学习参考资料[3]。
P2P Discovery的目的很简单,就是使得多个P2P Device可以互相发现并构建一个Group。根据规范,它包括四个主要技术子项:
提示:Group分Persistent(永久性) Group和Temporary(临时性) Group两种。咱们举二个简单例子来讲明两者的区别:
Temporary Group:当你有份文件要传给一个同事时,双方打开手机的Wi-Fi P2P功能,创建一个Group,而后传输文件,最后关闭Wi-Fi P2P。在这个过程当中,GO和Client的角色分配由Group Formation来决定,这一次的GO多是你的设备,下一次则多是其余人的设备。对于这种Group,在创建Group过程当中所涉及的安全配置信息以及和Group相关的信息(之后咱们会见到它)都是临时的,即下一次再组建Group时,这些安全配置信息都将发生变化。
Persistent Group:在这种Group中,GO由指定设备来扮演,并且安全配置信息及Group相关信息一旦生成,后续就不会再发生变化(除非用户从新设置)。Persistent Group中的GO多见于固定用途的设备,例如打印机等。如此,除了第一次经过P2P链接到打印机时相对麻烦一点(须要利用WSC协商安全配置信息)外,后续使用的话,因为P2P设备将保存这些安全信息,因此下一次再使用打印机时就能利用这些信息直接和打印机进行关联了。
因为篇幅关系,本章将仅介绍上述四个知识点中最为基础的Device Discovery和Group Formation,而Service Discovery和P2P Invitation的内容请读者学习完本章后再仔细研读P2P规范。
P2P Device Discovery虽然也是利用802.11中的Probe Request和Probe Response帧来搜索周围的P2P设备,但其步骤却比Infrastructure BSS中的无线网络搜索要复杂。举一个简单的例子,一个P2P Device除了本身要发送Probe Request帧外,还得接收来自其余设备的Probe Request帧并回复Probe Response帧。而在Infrastructure BSS中,只有AP会发送Probe Response帧。
为了加快搜索速度,P2P为Device Discovery定义了两个状态和两个阶段。
P2P Device Discovery的工做流程包含两个状态和两个阶段。先来看两个状态,它们分别是:
再来看两个阶段,它们分别是:
图7-3所示为P2P Device Discovery的流程示意图。
图7-3 P2P Device Discovery流程示意图
图7-3所示为两个P2P Device的Discovery流程,其中:
提示:P2P规范对两个状态及两个阶段的描述很是细致,甚至于对每一个状态能干什么和不能干什么都有详细说明。不过,从如何快速掌握P2P框架的角度来看,笔者以为这些内容过于啰嗦。
了解了Device Discovery的大致工做流程后,下面咱们将经过实例来看看P2P使用到的Probe Request和Probe Response帧。
========================略略略略略略略略==========
在第5章5.2.3中“WifiNative介绍”一节中曾介绍了wpa_supplicant的启动,在那一节中,读者会发现wpa_supplicant进程由WifiStateMachine启动。在Android官方代码中,虽然Java层有WifiService和WifiP2pService两个几乎彻底不一样的Wifi服务,但两者都只和Native层的惟一一个wpa_supplicant进程交互。简单点说,Android原生代码中,一个wpa_supplicant进程将同时支持WifiService和WifiP2pService。
上述这种设计方法使得wpa_supplicant负担较重,因此,一些手机厂商会为WifiService和WifiP2pService各建立一个wpa_supplicant进程,使得它们能各司其职而互不干扰。以笔者的Galaxy Note2为例,它的,WifiService将和wpa_supplicant进程交互,而WifiP2pService将和一个名为p2p_supplicant(通过笔者测试,p2p_supplicant实际上就是wpa_supplicant,只不过名字不一样罢了)的进程交互。
图7-26所示为Galaxy Note2 init配置文件中关于p2p_supplicant服务的示意图:
图7-26 Galaxy Note2中p2p_supplicant服务配置项
由图7-26可知:
图7-27 p2p_supplicant.conf内容
提示:关于init配置文件中wpa_supplicant服务的说明,请读者参考第4章4.3“wpa_supplicant初始化流程分析”一节。
图7-27中,p2p_supplicant对于的ctrl_iface路径为/data/misc/wifi/sockets。因此,若是要使用wpa_cli和p2p_supplicant交互的话,必须指定正确的ctrl_iface路径。图7-28所示为笔者用wpa_cli测试p2p_supplicant时的示例截图:
图7-28 wpa_cli和p2p_supplicant交互
下面来分析wpa_supplicant中和P2P相关的代码。
注意:以Galaxy Note2为例,p2p_supplicant就是wpa_supplicant,只是编译时打开了P2P相关的选项。下面的分析将以wpa_supplicant中和P2P相关的代码及工做流程为主。
首先来看WPAS中P2P相关模块的初始化。该初始化工做咱们在第4章4.3.4中“wpa_supplicant_init_iface分析之五”曾提到过,其对应的函数wpas_p2p_init,立刻来看它
[p2p_supplicant.c::wpas_p2p_init]
int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
{
struct p2p_config p2p; //p2p变量指向一个p2p_config对象,表明P2P模块的配置信息
unsigned int r; int i;
//①WPA_DRIVER_FLAGS_P2P_CAPABLE:表明Wifi驱动对P2P支持的能力,详情见下文解释
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)) return 0;
if (global->p2p) return 0;
//若是wifi driver能完成P2P功能,就不用劳驾WPAS了
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {......}
//②初始化并设置p2p_config对象
os_memset(&p2p, 0, sizeof(p2p));
p2p.msg_ctx = wpa_s; p2p.cb_ctx = wpa_s;
p2p.p2p_scan = wpas_p2p_scan; //P2P对应的扫描函数
.......//设置一些回调函数
p2p.get_noa = wpas_get_noa; p2p.go_connected = wpas_go_connected;
//设置P2P Device address。
os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
//设置P2P模块配置信息,包括device name,model name,uuid等
p2p.dev_name = wpa_s->conf->device_name;
p2p.manufacturer = wpa_s->conf->manufacturer;
p2p.model_name = wpa_s->conf->model_name;
p2p.model_number = wpa_s->conf->model_number;
p2p.serial_number = wpa_s->conf->serial_number;
if (wpa_s->wps) {
os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);
p2p.config_methods = wpa_s->wps->config_methods;
}
//设置Operation Channel信息和listen channel信息
if (wpa_s->conf->p2p_listen_reg_class &&
wpa_s->conf->p2p_listen_channel) {
p2p.reg_class = wpa_s->conf->p2p_listen_reg_class;
p2p.channel = wpa_s->conf->p2p_listen_channel;
} else {......//设置默认值}
......
//设置国家码
if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
os_memcpy(p2p.country, wpa_s->conf->country, 2);
p2p.country[2] = 0x04;
} else//配置文件中没有设置国家,因此取值为"XX\x04"
os_memcpy(p2p.country, "XX\x04", 3);//读者可回顾图7-7
//判断wifi 驱动是否支持配置文件中设置的operationg channel和listen channel
if (wpas_p2p_setup_channels(wpa_s, &p2p.channels)) {......}
os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,WPS_DEV_TYPE_LEN);
p2p.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
os_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type,
p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN);
//是否支持concurrent operation
p2p.concurrent_operations = !!(wpa_s->drv_flags&WPA_DRIVER_FLAGS_P2P_CONCURRENT);
p2p.max_peers = 100;//最多能保存100个对端P2P Device信息
//配置文件中没有设置p2p_ssid_postfix,但P2pStateMachine在initializeP2pSettings函数中
//将设置P2P SSID后缀。以笔者的Galaxy Note2为例,其P2P SSID后缀为“Android_4aa9”
if (wpa_s->conf->p2p_ssid_postfix) {......}
p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
//③global->p2p指向一个p2p_data结构体,它是WPAS中P2P模块的表明
global->p2p = p2p_init(&p2p);
......
for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {//拷贝vendor厂商特定的WSC属性信息
if (wpa_s->conf->wps_vendor_ext[i] == NULL) continue;
p2p_add_wps_vendor_extension(global->p2p, wpa_s->conf->wps_vendor_ext[i]);
}
return 0;
}
由上述代码可知,wpas_p2p_init的工做很是简单,主要内容包括:
下面来介绍上述代码中涉及到的一些知识。
先来看上述代码中提到的drv_flags变量。WPAS中,Wifi驱动对P2P功能的支持状况就是由它来表达的。笔者的Galaxy Note2中该变量取值为0x2EAC0,其表达的含义以下:
[-->driver.h]
#define WPA_DRIVER_FLAGS_AP 0x00000040 //Wifi driver支持AP。它使得P2P设备能扮演GO
/*
标志标明association成功后,kernel driver须要设置WEP key
这个标志出现的缘由是因为kernel API发生了变更,使得只能在关联成功后才能设置key
*/
#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE 0x00000080
#define WPA_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200 //Wifi驱动支持STA和P2P的并发运行
#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800 //Wifi驱动支持P2P
/*
7.2.2.1.2“Probe Request帧设置”一节曾提到过说P2P包含Device Address和Interface Address
两种类型的地址。在实际实现过程当中,这两个地址分别表明两个virtual interface。显然,P2P中第一个和一直
存在的是拥有Device Address的vitural interface。下面这个标志表示该virtual interface能够参与
P2P管理(除P2P Group Operation以外的工做)工做以及非P2P相关的工做(例如利用这个virtual
interface 加入到一个BSS)
*/
#define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P 0x00002000
/*
该标志主要针对associate操做。当关联操做失败后,若是driver支持该选项,则代表driver能处理失败之
后的各类收尾工做(Key、timeout等工做)。不然,WPAS须要本身处理这些事情
*/
#define WPA_DRIVER_FLAGS_SANE_ERROR_CODES 0x00004000
//下面这个标志和off channel机制有关。读者可参考第4章4.3.4中“capability介绍”一节。当802.11
//MAC帧经过off channel发送的话,下面这个标志表示driver会反馈一个发送状况(TX Report)消息给WPAS
#define WPA_DRIVER_FLAGS_OFFCHANNEL_TX 0x00008000
//下面这两个标志表示kernel中的driver是否能反馈Deauthentication/Disassociation帧
//发送状况(TX Report)
#define WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS 0x00020000
下面来看wpas_p2p_init中出现的几个重要数据结构,首先是p2p_config和p2p_data,它们的成员如图7-29所示:
图7-29 p2p_config和p2p_data结构示意图
图7-29展现了p2p_config和p2p_data两个数据结构中一些重要的成员。其中:
下面来看另外几个重要数据结构的内容,如图7-30所示:
图7-30 p2p_device及其余数据结构示意图
图7-30展现了五种数据结构,其中:
提示: WPAS中定义了很是多的数据结构类型,这极大增长了初学者的学习难度。根据笔者本身的经验,建议读者在学习过程当中先简单了解这些数据结构的名字及做用,而后在具体代码分析时再结合代码逻辑来了解这些数据结构及其内部各个成员变量的具体做用。
本章对Wi-Fi P2P进行了详细介绍,主要内容包括:
最后,但愿读者在本章的基础上,完成下列的一些任务:
本章参考资料主要是Wifi P2P规范1.1版,读者可从http://www.doc88.com/p-908280242988.html上下载协议全文。
[1] WiFi P2P第2节“Architectural Overview”
[2] WiFi P2P第3.2节“P2P Group Operation”
[3] WiFi P2P第3.3节“P2P Power Management”
[4] WiFi P2P第3.1节“P2P Discovery”
[5] Part11:Wireless LAN Medium Access Control(MAC) and Phsyical Layer(PHY) Specifications附录J“Country information element and regulatory classes”
该文档下载地址为http://download.csdn.net/download/s_bird0529/2553723。附录J详细描述了国家码和管制信息方面的内容
[6] WiFi P2P第4.2节“Management Frames”
[7] 802.11-2012第8.4.1.11节“Action Field”
该节介绍了Action帧Category字段的取值状况
[8] WiFi P2P第4.1节“P2P Information Elements”
[9] WiFi P2P附录A“P2P State Machine”