golang p2p网

Python013

golang p2p网,第1张

继续进入下一个初始化

n.netService, err = nebnet.NewNebService(n)

if err != nil {

logging.CLog().WithFields(logrus.Fields{

"err": err,

}).Fatal("Failed to setup net service.")

}

netservice有两个成员

type NebServicestruct {

node      *Node

dispatcher *Dispatcher

}

跳出stup()函数

先进入start()函数看一看

if err := n.netService.Start()err != nil {

logging.CLog().WithFields(logrus.Fields{

"err": err,

}).Fatal("Failed to start net service.")

}

进入netservice.start()

func (ns *NebService) Start() error {

logging.CLog().Info("Starting NebService...")

// start dispatcher.

  ns.dispatcher.Start()

// start node.

  if err := ns.node.Start()err != nil {

ns.dispatcher.Stop()

logging.CLog().WithFields(logrus.Fields{

"err": err,

}).Error("Failed to start NebService.")

return err

}

logging.CLog().Info("Started NebService.")

return nil

}

可以看到第一个start()的函数是dispatcher.start()

进入dispatch.start()

func (dp *Dispatcher) Start() {

logging.CLog().Info("Starting NebService Dispatcher...")

go dp.loop()

}

然后就出现一个新的线程、goruntime

go dp.loop()

进入该线程,看它干了些什么

timerChan := time.NewTicker(time.Second).C

for {

select {

case <-timerChan:

metricsDispatcherCached.Update(int64(len(dp.receivedMessageCh)))

case <-dp.quitCh:

logging.CLog().Info("Stoped NebService Dispatcher.")

return

  case msg := <-dp.receivedMessageCh:

msgType := msg.MessageType()

v, _ := dp.subscribersMap.Load(msgType)

if v == nil {

continue

      }

m, _ := v.(*sync.Map)

m.Range(func(key, valueinterface{}) bool {

select {

case key.(*Subscriber).msgChan <- msg:

default:

logging.VLog().WithFields(logrus.Fields{

"msgType": msgType,

}).Warn("timeout to dispatch message.")

}

return true

      })

}

}

一个有点长的循环

metricsDispatcherCached.Update(int64(len(dp.receivedMessageCh)))一秒钟刷新一次缓冲区

case msg := <-dp.receivedMessageCh:

msgType := msg.MessageType()如果能取出dp.receivedMessageCh

msgType := msg.MessageType()首先判断取出的信息类型

v, _ := dp.subscribersMap.Load(msgType)

if v == nil {

continue

}

根据类型取出相应的map

如果取不出,那么使用continue结束这个case

m, _ := v.(*sync.Map)

断言

m.Range(func(key, valueinterface{}) bool {

select {

case key.(*Subscriber).msgChan <- msg:

default:

logging.VLog().WithFields(logrus.Fields{

"msgType": msgType,

}).Warn("timeout to dispa+tch message.")

}

return true

})

将msg推入其他管道里面去。其他goruntime会循环等待该

介绍Wi-Fi联盟推出的另外一项重要技术规范WiFi P2P。 该规范的商品名为Wi-Fi Direct, 它支持多个Wi-Fi设备在没有AP的情况下相互连接.

在Android平台的Wi-Fi相关模块中, P2P的功能点主要集中在:

· Android Framework中的WifiP2pService, 其功能和WifiService类似, 用于处理

和P2P相关的工作。

· wpa_supplicant中的P2P模块。

Wi-Fi P2P技术是Wi-Fi Display 的基础。

http://blog.csdn.net/innost/article/details/8474683

P2P架构中定义了三个组件, 笔者将其称为“ 一个设备, 两种角色” , 分别如下

P2P Device : 它是P2P架构中角色的实体, 可把它当做一个Wi-Fi设备

P2P Group Owner : Group Owner( GO) 是一种角色, 其作用类似于Infrastructure BSS中的AP

P2P Client : 另外一种角色, 其作用类似于Infrastructure BSS中的STA

组建P2P Group( 即P2P Network) 之前, 智能终端都是一个一个的

P2P Device。 当这些P2P Device设备之间完成P2P协商后, 其中将有一个并且只能有一个Device来扮演GO的角色( 即充当AP) , 而其他Device来扮演Client的角色

P2P Discovery的作用很简单, 就是使多个P2P Device能够互相发现并构建一个

Group。 根据规范, 它包括四个主要技术子项

·** Device Discovery : 用于P2P设备搜索周围其他支持P2P的设备。

· Service Discovery : 该Device Discovery基础上, P2P还支持搜索指定的服务。 这

部分功能属于可选项。

· Group Formation : 用于决定两个P2P Device谁来扮演GO, 谁来扮演Client。

· P2P Invitation**: 用于激活一个Persistent Group( 见下文解释) , 或者用于邀请一个Client加入一个当前已存在的Group

P2P Device Discovery虽然也是利用802.11中的Probe Request和Probe Response

帧来搜索周围的P2P设备

为了加快搜索速度, P2P为Device Discovery定义了两个状态和两个阶段。

( 1) Device Discovery工作流程

先来看两个状态, 分别如下。

· Search State: 在该状态中, P2P Device将在2.4GHz的1, 6, 11频段上分别发送Probe Request帧。 这几个频段称为Social Channels。 为了区别非P2P的Probe Request帧, P2P Device Discovery要求必须在Probe Request帧中包含P2P IE。

· Listen State: 在该状态中, P2P Device将随机选择在1, 6, 11频段中的一个频段( 被选中的频段称为Listen Channel) 监听Probe Request帧并回复Probe Response帧。 值得指出的是, Listen Channel一旦选择好后, 在整个P2P Discovery阶段就不能更改。 另外, 在这个阶段中, P2P Device只处理包含P2P IE信息的Probe Request帧

再来看两个阶段, 分别如下。

·** Scan Phase**: 扫描阶段。 这一阶段和前面章节介绍的无线网络扫描一样, P2P

Device会在各个频段上发送Probe Request帧( 主动扫描) 。 P2P Device在这一阶段中不会处理来自其他设备的Probe Request帧。 这一阶段过后, P2P Device将进入下一个阶段, 即Find Phase。

· Find Phase : 虽然从中文翻译来看, Scan和Find意思比较接近, 但P2P的Find

Phase却和Scan Phase大不相同。 在这一阶段中, P2P Device将在Search State和ListenState之间来回切换。 Search State中, P2P Device将发送Probe Request帧, 而ListenState中, 它将接收其他设备的Probe Request帧并回复Probe Response帧

两个P2P Device的Discovery流程:

· Discovery启动后, Device首先进入Scan Phase。 在这一阶段, P2P设备在其支持的所有频段上都会发送Probe Request帧。

· Scan Phase完成后, Device进入Find Phase。 在这一阶段中, Device将在Listen和Search State中切换。

当Device处于Find Phase中的Search State时, 它将在1、 6、 11频段上发送Probe

Request帧。 注意, 只有当两个设备处于同一频段时, 一方发送的帧才能被对方接收到

P2P规范中对Probe Request帧的要求

· SSID IE必须设置为P2P Wildcard SSID, 即"DIRECT-"。

· 必须包含P2P IE。

· 802.11 MAC帧头的地址域① 中, Destination Address域( Address1) 必须为广播

地址( FF: FF: FF: FF: FF: FF) 或者为目标设备的P2P Device Address , BSSID域( Address3) 必须为广播地址

(P2P规范定义了两种类型的地址, 一种是P2P Device Address, 另外一种

是P2P Interface Address。 一个P2P Device在加入P2P Group前, 将使用Device Address开展Device Discovery等工作。 对一个P2P Device而言, 其P2P Device Address是唯一的( 作用等同于MAC地址) 。 而当P2P Device加入P2P Group后, 它和Group中其他成员交互时将使用P2P Interface Address。 另外, 由于一个P2P Device可同时加入多个P2P Group, 所以在每个P2P Group中, 该设备必须使用不同的P2P Interface Address。 最后, 当一个Group结束后, Device在该Group中使用的P2PInterface Address也就相应作废了)

Probe Response帧

P2P Probe Response帧包含WSC IE和P2P IE

当P2P Device A通过Device Discovery找到周围的一个P2P Device B后, Device A

就可以开展Group Formation流程以准备构造一个P2P Group。 Group Formation也包含

两个阶段, 分别如下。

· GO Negotiation : 在这一阶段中, 两个Device要协商好由谁来做GO。

· Provisioning : GO和Client角色确定后, 两个Device要借助WSC来交换安全配置

信息。 此后, Client就可以利用安全配置信息关联上GO。

GO Negotiation过程中P2P设备会利用一种名为P2P Public Action类型的帧交换信

( 1) P2P Public Action帧

GO Negotiation流程, 包含三次P2P Public Action帧交换

GO Negotiation( 以后简称GON) 流程包括GON Request、 GON

Response和GON Confirmation三次帧交换。 这三次帧交换并不涉及什么复杂的计算, 只

是双方交换一些信息, 从而谁来扮演GO

P2P Public Action帧中还存在着"Provision Discovery Request/Response"类型的帧,P2P规范定义了Provision Discovery( PD) 流程, 该流程就是为了确定交互双方使用的WSC方法

WifiP2pSettings是Settings应用中负责处理P2P相关UI/UE逻辑的主要类, 与之交互

的则是位于SystemServer进程中的WifiP2pService

WifiService处理和WLAN网络连接相关的工作, 而WifiP2pService则专门负责处理和Wi-Fi P2P相关的工作

#######P2pStateMachine是WifiP2pService的核心

1.CMD_ENABLE_P2P处理流程

1.1WifiStateMachine将创建一个名为mWifiP2pChannel的AsyncChannel对象用于向P2pStateMachine发送消息

1.2在Android平台中, 如果用户打开Wi-Fi功能, P2pStateMachine就会收到第一个消息CMD_ENABLE_P2P。 该消息是WifiStateMachine进入DriverStartedState后, 在其EA中借助mWifiP2pChannel向P2pStateMachine发送的.(P2pDisabledState: enter)

1.3处理完CMD_ENABLE_P2P消息后, P2pStateMachine将创建一个WifiMonitor用于接收来自wpa_supplicant的消息, 同时状态机将转入P2pEnablingState.

1.4WifiMonitor连接wpa_supplicant之后, WifiMonitor会发送一个SUP_CONNECTION_EVENT给P2pStateMachine。 该消息将由P2pEnablingState处理

2.SUP_CONNECTION_EVENT处理流程

WifiP2pService.java: : P2pEnablingState: processMessage

2.1.当状态机转入InactiveState后, 首先执行的是其父状态P2pEnabledState的EA, 然后才是InactiveState自己的EA.

WifiP2pService.java: : P2pEnabledState: enter

2.2.P2pStateMachine就算初始化完毕, 接下来的工作就是处理用户发起的操作

3.DISCOVER_PEERS处理流程

用户在界面中进行操作以搜索周围的设备,WifiP2pSettings中WifiP2pManager的discoverPeers函数, 它将发送DISCOVER_PEERS消息给P2pStateMachine

3.1.P2pStateMachine当前处于InactiveState, 不过DISCOVER_PEERS消息却是由其父状态P2pEnabledState来处理的

3.2.当WPAS搜索到周围的P2P Device后, 将发送以下格式的消息给WifiMonitor。

3.3.WifiMonitor将根据这些信息构建一个WifiP2pDevice对象, 然后发送

P2P_DEVICE_FOUND_EVENT给P2pStateMachine

4.P2P_DEVICE_FOUND_EVENT处理流程

P2P_DEVICE_FOUND_EVENT也由InactiveState的父状态P2pEnabledState来处理

5.CONNECT处理流程

5.1.当用户在WifiP2pSettings界面中选择连接某个P2P Device后,WifiP2pManager的connect函数将发送CONNECT消息给P2pStateMachine, 该消息由InactiveState状态自己来处理

WifiP2pSettings.java: : InactiveState: processMessage

WifiP2pService.java: : connect

5.2.connect将返回NEEDS_PROVISON_REQ, 所以P2pStateMachine将

转入ProvisionDiscoveryState

WifiP2pService.java: : ProvisionDiscoveryState: enter

5.3.由于WSC配置方法为PBC, 所以对端设备的P2pStateMachine将收到一个

P2P_PROV_DISC_PBC_REQ_EVENT消息。 当对端设备处理完毕后, 将收到一个P2P_PROV_DISC_PBC_RSP_EVENT消息

6.P2P_PROV_DISC_PBC_RSP_EVENT处理流程

6.1.P2pStateMachine当前处于ProvisionDiscoveryState

WifiP2pService.java: : ProvisionDiscoveryState: processMessage

6.2.P2pStateMachine通过p2pConnectWithPinDisplay向对端发起Group

Negotiation Request请求。 接下来的工作就由WPAS来处理。 当Group Formation结束后, P2pStateMachine将收到一个P2P_GROUP_STARTED_EVENT消息以通知Group建立完毕

7.P2P_GROUP_STARTED_EVENT处理流程

7.1.P2P_GROUP_STARTED_EVENT消息由GroupNegotiationState处理

WifiP2pService.java: : GroupNegotiationState: processMessage

7.2.P2pStateMachine将转入GroupCreatedState

WifiP2pService.java: : GroupCreatedState: enter

8.AP_STA_CONNECTED_EVENT处理流程

8.1.当对端P2P设备成功关联到本机后, WifiMonitor又将发送一个名为

AP_STA_CONNECTED_EVENT的消息

WifiP2pService.java: : GroupCreatedState: processMessage

8.2.至此, 一个P2P Device( 扮演Client) 就成功关联上本机的P2P Device( 扮演GO)

wpa_supplicant进程由WifiStateMachine启动.

手机厂商会为WifiService和WifiP2pService各创建一个wpa_supplicant进程, 使得它们能各司其职而互不干扰。 WifiService将和wpa_supplicant进程交互, 而WifiP2pService将和一个名为p2p_supplicant

p2p_supplicant使用的配置文件名为/data/misc/wifi/p2p_supplicant.conf

p2p_supplicant对应的ctrl_iface路径为/data/misc/wifi/sockets。 所以, 如果要使用wpa_cli和p2p_supplicant交互, 必须指定正确的ctrl_iface路径

p2p_supplicant.c: : wpas_p2p_init

· 初始化一个p2p_config对象, 然后根据p2p_supplicant.conf文件的信息来设置其中的内容, 同时还需要为P2P模块设置一些回调函数。

· 调用p2p_init函数以初始化P2P模块

1.Driver Flags和重要数据结构

drv_flags变量, WPAS中, Wi-Fi驱动对P2P功能的支持情况就是由它来表达的

· p2p_config定义了20个回调函数。 这些回调函数定义了P2P模块和外界交互的接口。 在wpas_p2p_init中, 这些回调函数均指向p2p_supplicant.c中对应的函数, 例如p2p_scan指向wpas_p2p_scan, dev_lost指向wpas_dev_lost

· p2p_data指向一个p2p_config对象。

· p2p_device代表一个P2P设备。 其中设备名、 Device CapabilityBitmap等信息保存在一个类型为p2p_peer_info的对象中。

· p2p_group代表一个P2P Group的信息, 其内部包含一个p2p_group_config对象和一个p2p_group_member链表。 p2p_group_config表示该Group的配置信

息, p2p_group_member代表Group Member即P2P Client的信息

2.p2p_init函数

p2p.c: : p2p_init

3.注册Action帧监听事件

driver_nl80211.c: : wpa_driver_nl80211_set_mode

3.1nl80211_mgmt_subscribte_non_ap将注册对Action帧的监听事件, 其作用就是当设备收到Action帧后, Wi-Fi驱动将发送对应的netlink消息给WPAS

driver_nl80211.c: : nl80211_mgmt_subscribte_non_ap

3.2.注册了两种类型的帧监

听事件。

· P2P Public Action帧监听事件: 根据P2P规范, 目前使用的均是802.11 PublicAction帧, 即Category的值为0x04。 目前GON、 P2P Invitation、 Provision Discovery以及Device Discoverability使用P2P Public Action帧。

· P2P Action帧监听事件: 这种类型的帧属于802.11 Action帧的一种, 其Category取值为0x7F, OUI指定为WFA的OUI( 即50-6F-9A) , 而OUI-Type指定为P2P( 取值为0x09) 。 目前Notice of Absence、 P2P Presence、 GO Discoverability使用P2PAction帧。

上述注册的Action帧监听事件对应的处理函数是process_bss_event

3.3.至此, P2P模块以及Action帧监听事件注册等工作都已完成, WPAS马上可为WifiP2pService提供P2P相关的服务了

P2pStateMachine将发送"P2P_FIND 120"命令给WPAS以触发P2P Device Discovery流程

ctrl_iface.c: : wpa_supplicant_ctrl_iface_process

ctrl_iface.c: : p2p_ctrl_find

P2P_FIND支持三种不同的Discovery Type

· P2P_FIND_START_WITH_FULL: 默认设置。 表示先扫描所有频段, 然后再扫描social channels。 这种搜索方式如图7-3所示。

· P2P_FIND_ONLY_SOCIAL: 只扫描social channels。 它将跳过“ 扫描所有频段” 这一过程。 这种搜索方式能加快搜索的速度。

· P2P_FIND_PROGRESSIVE: 它和P2P_FIND_START_WITH_FULL类似, 只不过在Search State阶段将逐个扫描所有频段

1.P2P设备扫描流程

P2P设备扫描流程从wpas_p2p_find开始

p2p_supplicant.c: : wpas_p2p_find

p2p.c: : p2p_find

p2p_supplicant.c: : wpas_p2p_scan

2.P2P设备扫描结果处理流程

当scan_res_handler不为空的时候, 扫描结果将交给scan_res_handler来处理

对P2P设备扫描时将设置scan_res_handler为wpas_p2p_scan_res_handler

p2p_supplicant.c: : wpas_p2p_scan_res_handler

P2pStateMachine的ProvisionDiscoveryState在其EA中将发送形如"P2P_PROV_DISC 8a: 32: 9b: 6c: d1: 80 pbc"的命令给WPAS 去执行, 其核心处理函数是p2p_ctrl_prov_disc

1.PD Request帧发送流程

p2p.c: : p2p_prov_disc_req

p2p_pd.c: : p2p_send_prov_disc_req

2.Action帧接收流程

PD Response帧属于Public Action帧的一种, 当收到对端设备发来的PD Response帧后, process_bss_event函数将被调用

3.PD Response帧处理流程

p2p_pd.c: : p2p_process_prov_disc_resp

p2p_supplicant.c: : wpas_prov_disc_resp

wpa_msg将发送P2P_EVENT_PROV_DISC_PBC_RESP( 字符串, 值为"P2P-PROV-DISC-PBCRESP") 消息给客户端

P2pStateMachine收到P2P_PROV_DISC_PBC_RSP_EVENT消息后, 将在

ProvisionDiscoveryState中调用p2pConnectWithPinDisplay, 该函数内部将发送P2P_CONNECT命令给WPAS

1.P2P_CONNECT处理流程

ctrl_iface.c: : p2p_ctrl_connect

p2p_supplicant.c: : wpas_p2p_connect

2.GON Request发送流程

p2p.c: : p2p_connect

p2p_go_neg.c: : p2p_connect_send

3.GON Response帧处理流程

p2p_go_neg.c: : p2p_process_go_neg_resp

当GON Confirmation帧发送出去后, wifi driver将向WPAS发送一个NL80211_CMD_FRAME_TX_STATUS消息, 而该消息将导致driver wrapper发送EVENT_TX_STATUS消息给WPAS

4.EVENT_TX_STATUS处理流程

在events.c中, 和P2P以及EVENT_TX_STATUS相关的处理函数是offchannel_send_action_tx_status

offchannel.c: : offchannel_send_action_tx_status

当Group Negotiation完成后, WPAS将新创建一个wpa_supplicant对象, 它将用于管理和操作专门用于P2P Group的virtual interface

· 一个interface对应一个wpa_supplicant对象。

· 此处新创建的wpa_supplicant对象用于GO, 即扮演AP的角色, 专门处理和P2PGroup相关的事情, 其MAC地址为P2P Interface Address。

· 之前使用的wpa_supplicant用于非P2P Group操作, 其MAC地址为P2P DeviceAddress