Android wpa_supplicant源码分析–扫描scan过程
来源:互联网 发布:apache web 压力测试 编辑:程序博客网 时间:2024/05/24 16:16
1 扫描过程
一个完整的扫描过程 下发命令–>wpa_s构建扫描参数–>驱动扫描–>wpa_s接收到驱动的扫描结果
接收到framework/wpa_cli下发的SCAN命令
if (os_strncmp(buf, "SCAN ", 5) == 0) { wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
1.1 wpa_supplicant_scan
做一些检测配置工作,然后将扫描的发起动作添加到radio_work中
wpa_supplicant_scan( wpa_supplicant *wpa_s ){ //检查环境配置 // !wpa_s->pno //非pno状态 !wpa_s->wpa_state == WPA_INTERFACE_DISABLED //网口在可用状态 //wpa_s中的scan一共有3种类型 NORMAL_SCAN_REQ wpa_s自主发起的,INITIAL_SCAN_REQ 对网口第一次发起的扫描, MANUAL_SCAN_REQ 上层命令发起的扫描 //当前wifi为断开状态,并且是wpa_s发起的扫描,则直接设置wpa_s状态为断开,不再扫描 !(wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); //如果已经在扫描,则延后1秒再发起扫描 if (wpa_s->scanning) wpa_supplicant_req_scan(wpa_s, 1, 0); //conf文件中没有使能/可用的网络,并且是wpa_s自主发起的扫描,则直接返回,并设置状态 (!wpa_supplicant_enabled_networks(wpa_s) && wpa_s->scan_req == NORMAL_SCAN_REQ)) wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); //设置扫描类型为正常扫描 wpa_s->scan_req = NORMAL_SCAN_REQ; //设置wpa_s的状态为 SCANNING wpa_supplicant_set_state(wpa_s, WPA_SCANNING); //如果设置了autosan, 直接扫描 if (wpa_s->autoscan_params != NULL) //如果该项不为空,则直接关联,跳过扫描步骤,在stat模式中没有这一项,p2p中可能会用到 if(wpa_s->connect_without_scan) wpa_supplicant_associate(wpa_s, NULL, ssid); //android中的扫描都是扫描所有,也可以扫描单个ssid wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; //wps和p2p会用到指定扫描的频率 wpa_supplicant_optimize_freqs(wpa_s, ¶ms); //如果conf中定义了filter_bssid使能,那么扫描结果中只包含conf中已有的ssid params.filter_ssids = wpa_supplicant_build_filter_ssids(wpa_s->conf, ¶ms.num_filter_ssids); //触发扫描 ret = wpa_supplicant_trigger_scan(wpa_s, scan_params); { //添加到ridio work中, ridio work会在eloop循环中调用执行 radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) { //将scan用的raido work添加到 wpa_s radio的工作链表中 dl_list_add_tail(&wpa_s->radio->work, &work->list); } } }
1.2 radio_work调用CB
当radio_work执行到wpas_trigger_scan_cb时,调用驱动中的扫描方法,然后通过初始化过程中创建的genl socket 下发扫描动作然后等待驱动处理
//驱动中的扫描ret = wpa_drv_scan(wpa_s, params); wpa_s->driver->scan2(wpa_s->drv_priv, params) driver_nl80211_scan2 wpa_driver_nl80211_scan(bss, params) { //生成nl msg struct nl_msg *msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params, bss->wdev_id_set ? &bss->wdev_id : NULL); //通过nl发送消息,扫描返回的event接收到后再处理 ret = send_and_recv_msgs(drv, msg, NULL, NULL); //如果驱动不支持上报扫描结果的event,那么注册超时10秒,如果支持,注册超时30秒, 利用wpa_driver_nl80211_scan_timeout读取扫描结果 eloop_register_timeout(10/30, 0, wpa_driver_nl80211_scan_timeout,drv, drv->ctx); //最终会调用wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);接收扫描结果 }
1.3 scan耗时统计
wpa_s中关于扫描统计了两个耗时
1 下发驱动扫描命令到驱动执行扫描的时间
//正式运行radio work时间radio_start_next_work() os_get_reltime(&now); work->cb(work, 0); wpas_trigger_scan_cb() os_get_reltime(&wpa_s->scan_trigger_time);//下发驱动扫描后,接收到driver EVENT_SCAN_STARTED(这个event就是为了输出log,没有什么实际的操作)//计算开始扫描时间os_get_reltime(&wpa_s->scan_start_time);//输出socket调用时间os_reltime_sub(&wpa_s->scan_start_time, &wpa_s->scan_trigger_time, &diff);wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %ld.%06ld seconds", diff.sec, diff.usec);
2 驱动执行扫描的耗时
//计算dirver发送上EVENT_SCAN_STARTED 和 EVENT_SCAN_RESULTS 耗时 os_reltime_sub(&now, &wpa_s->scan_start_time, &diff); wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %ld.%06ld seconds",diff.sec, diff.usec);
1.4 接收扫描结果
wpa_s接收到扫描结果,并保存在wpa_s bss链表中
wpa_supplicant_event(wpa_supplicant *wpa_s, EVENT_SCAN_RESULTS, NULL);{ //计算dirver发送上EVENT_SCAN_STARTED 和 EVENT_SCAN_RESULTS 耗时 os_reltime_sub(&now, &wpa_s->scan_start_time, &diff); wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %ld.%06ld seconds",diff.sec, diff.usec); //获取扫描结果, 如果返回值为0,则成功获取到扫描结果 wpa_supplicant_event_scan_results() _wpa_supplicant_event_scan_results(wpa_s, data, 1) { //从驱动获取扫描结果, struct wpa_scan_results *scan_res = wpa_supplicant_get_scan_results(wpa_s, data ? &data->scan_info : NULL, 1); { //从驱动中获取结果 scan_res = wpa_drv_get_scan_results2(wpa_s); wpa_driver_nl80211_get_scan_results(void *priv) { //生成msg 并从驱动中获取,bss_info_handler 为处理结果的函数 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN); ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); } //检查wpa_s->bssid_filter,如果不为空则进行filter filter_scan_res(wpa_s, scan_res); //进行一次排序 qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), compar); //for 更新每一个扫描结果,存储到wpa_s bbs链表和 bssid中 wpa_bss_update_scan_res(wpa_s, scan_res->res[i], &scan_res->fetch_time); } //处理下一次radio work radio_work_done(work); //一般来说,这里不会选取网络连接,忽略不计 wpas_select_network_from_last_scan(wpa_s, 1, own_request); { //从扫描结果中选取一个bss网络 selected = wpa_supplicant_pick_network(wpa_s, &ssid(null)); //判断是否需要漫游,这里不太明白,没看到匹配加密方式的, skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid); { //根据当前连接的bss网络信号强度和选择的网络信号强度的差值判断是否需要漫游 //这是wpa_s自主决定的漫游,有三个地方可以决定漫游 framework wpa_s driver current_bss->level < -85 : min_diff = 1; current_bss->level < -80 : min_diff = 2; current_bss->level < -75 : min_diff = 3; current_bss->level < -70 : min_diff = 4; current_bss->level > -70 : min_diff = 5; } } } }
1.5 流程图
2 连接过程
待补充
0 0
- Android wpa_supplicant源码分析–扫描scan过程
- Android wpa_supplicant源码分析--bss扫描结果
- Android wpa_supplicant源码分析–连接AP过程
- spring启动component-scan类扫描加载过程---源码分析
- spring启动component-scan类扫描加载过程---源码分析
- spring启动component-scan类扫描加载过程---源码分析
- spring启动component-scan类扫描加载过程---源码分析
- spring启动component-scan类扫描加载过程---源码分析
- Android应用程序包扫描过程源码分析
- Android应用程序包扫描过程源码分析
- Android应用程序包扫描过程源码分析
- android蓝牙扫描(scan)设备分析
- Android wpa_supplicant源码分析--conf配置文件
- Android wpa_supplicant源码分析--运行方式
- Android wpa_supplicant源码分析--conf配置文件
- Android wpa_supplicant源码分析--conf配置文件
- wpa_supplicant--连接过程分析
- wpa_supplicant 源码分析
- oracle11g的smart flash cache功能
- Ubuntu 安装软件时遇到过的问题整理
- luajit 2.1beta2 bytecode windows mac 下32 64编译文件
- 网站颜色设计
- apache kafka消息服务
- Android wpa_supplicant源码分析–扫描scan过程
- 简述HttpResponse.SetCookie、HttpResponse.AppendCookie、HttpResponse.Cookies.Add三者的区别
- Java Socket通信(TCP/UDP)
- MySQL修改root密码的多种方法
- C#泛型 泛型类扩展
- 如何分析三极管在电路中的作用
- proc means
- C# WebBrowser控件打开Echarts无效解决办法
- struts2中使用jQuery+ajax实现无刷新提交