Wpa_gui是一个基于Wpa_supplicant的无线连接管理工具,可以简单的认为是由wpa_supplicant+Qt的一个小型软件,它可以运行在linux,Windows及Unix操作系统下,作为配置连接无线网络使用。目前,在最新的Ubuntu系统下面,已经自动集成了该软件。

其中具体界面可以查看:http://hostap.epitest.fi/wpa_supplicant/wpa_gui.html

如果要获取该软件,可以去网站http://hostap.epitest.fi/wpa_supplicant/,获取wpa_supplicant的源码包,在源码包里就包含了wpa_gui的源码,并且包含了分别由Qt3和Qt4完成界面,以供不同的Qt环境使用。

获取源码包后,解压,可以获得wpa_supplicant-0.x.x目录,Wpa_gui的Qt4源码目录位于其中的wpa_supplicant/wpa_gui-qt4下,可以使用Q他Creator打开对应的工程文件wpa_gui.pro,方便阅读分析。

该工具的本质其实就是为wpa_supplicant提供了一个友好的用户界面,交互的操作由Qt4提供,而实际的功能则由底层的wpa_supplicant完成。在wpa_gui源码中,可以发现,整个源码由以下几个类构成:

AddInterface类:用于增加硬件的驱动接口

EventListModel类:用来构成事件的模型

EventHistory类:用来纪录事件

NetworkConfig类:用来配置无线连接的参数

Peers类:显示搜索到的无线路由

ScanResults类:用来处理得到的扫描结果

StringQuery类:处理字符串询问

UserDataRequest类:处理用户的数据请求

WpaGui类:最核心的类,整合其他所有类,并且与wpa_supplicant进行数据报文的交换

WpaMsg类:简单的存储消息

可以说,整个源代码的类很少,代码量也不大,但是通过对其研究,却可以初步帮助我们学下Qt4作为前台界面,后台程序实现功能的一种模式。在这个程序类里面,最主要的的类就是WpaGui类,是整个程序的核心,并且该类里实现了与wpa_supplicant交互的功能,因此主要的分析就是围绕 WpaGui类进行。

首先要知道怎么样与后台的wpa_supplicant进行交互,wpa_supplicant本身就提供了一套C/C++的接口,供外面程序调用,接口的头文件为wpa_ctrl.h,在WpaGui类的cpp文件中,可以清楚的看见include的头文件里,有#include “common/wpa_ctrl.h”。

在wpa_ctrl.h头文件中,包含一组宏定义的事件消息和8个函数接口。由于wpa_supplicant交互的方式是基于数据报文的,通过向外界发送事先定义好的事件消息,而外面这根据这些事件消息来确定下步要执行的动作。

譬如:#define WPA_EVENT_CONNECTED “CTRL-EVENT-CONNECTED ”

当Wpa_gui程序从wpa_supplicant获得这个宏定义消息后,就可以确定已经连接上确定的Wifi网络了,而在获得消息后,外面程序则可以使用8个函数接口来操作wpa_spplicant的行为。

而这些函数接口为:

struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);

void wpa_ctrl_close(struct wpa_ctrl *ctrl);

int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len));

int wpa_ctrl_attach(struct wpa_ctrl *ctrl);

int wpa_ctrl_detach(struct wpa_ctrl *ctrl);

int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);

int wpa_ctrl_pending(struct wpa_ctrl *ctrl);

int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
wpa_ctrl_open接口用来打开wpa_supplicant的控制接口,在UNIX系统里使用UNIX domain sockets,而在Windows里则是使用UDP sockets,当然接口的路径并不是固定的,可以根据配置文件内的路径设置来改变。

wpa_ctrl_close接口自然是用于关闭控制接口。

wpa_ctrl_request接口是用来发送控制命令至wpa_supplicant,并且会接受命令成功执行与否的反馈消息。这是一个堵塞的动作,一般会至少等待2秒钟用来接受反馈的回复消息。如果有未经主动请求的消息接受,堵塞的时间则会更长。

wpa_ctrl_attach接口是为控制接口注册一个事件监视,但注册成功后就可以开始接口事件消息。

wpa_ctrl_detach接口则是取消控制接口的事件监视。

wpa_ctrl_recv接口是在控制接口的事件监视注册成功后,用来接受事件消息,这是一个堵塞的操作,当没有可用的消息时,就会一直堵塞。

wpa_ctrl_pending接口是用来检测是否有即将到来的事件消息。

wpa_ctrl_get_fd接口则是来获得控制接口的文件描述符号。

了解了以上这些,就可以为全面深入Wpa_gui作一个铺垫。

在大致了接Wpa_gui的框架以及与wpa_supplicant交互的接口后,就可以详细分析源码。

正如前面所说的,WpaGui类是最为核心的部分,通过对该类源码的分析,就可以帮助我们了解整个程序,甚至是与wpa_supplicant的交互。

WpaGui类一共由三个文件组成:wpagui.ui,wpagui.h,wpagui.cpp。

wpagui.ui自然是由Qt设计器设计的界面文件,这部分不需要了解太多,使用Qt设计器打开后就可以看到控件和布局的细节部分。

wpagui.h头文件则声明变量函数等,因为函数可以在后面对wpagui.cpp文件的分析中,我将变量按照类型排列来分析:

QApplication *app;

定义了一个QApplicant的指针,用来在程序运行时指向wpagui对象的父对象。

ScanResults *scanres;
Peers *peers;
EventHistory *eh;
UserDataRequest *udr;
AddInterface *add_iface;
WpaMsgList msgs;
这些类已经在前面作过介绍,在这里声明了对应指针以便接下来实例化。
char *ctrl_iface;
char *ctrl_iface_dir;
bool networkMayHaveChanged;
struct wpa_ctrl *monitor_conn;
struct wpa_ctrl *ctrl_conn;
QSocketNotifier *msgNotifier;
QTimer *timer;
int pingsToStatusUpdate;
这里声明的是与wpa_supplican交互时所需要用到的变量
QAction *disconnectAction;
QAction *reconnectAction;
QAction *eventAction;
QAction *scanAction;
QAction *statAction;
QAction *showAction;
QAction *hideAction;
QAction *quitAction;
QAction *addInterfaceAction;
这里声明的是QAction的指针,实例化后来对应执行相应的动作
QMenu *tray_menu;
QSystemTrayIcon *tray_icon;
QMenu和QSystemTrayIcon的指针,用于程序隐藏于系统托盘时
bool ackTrayIcon;
bool startInTray;
bool wpsRunning;
bool connectedToService;
bool inTray;

判断各种状态的bool值变量

QString bssFromScan;

QString的字符串,用于获得扫描后使用bss得到的结果

#ifdef CONFIG_NATIVE_WINDOWS
QAction *fileStartServiceAction;
QAction *fileStopServiceAction;
bool serviceRunning();
#endif /* CONFIG_NATIVE_WINDOWS */

ifdef的宏,用于处理在windows平台时的行为。

wpagui.cpp里主要是各个函数的实现,通过这些函数,就能勾勒出系统运行全貌的大概,因此对每个函数一一进许分析:

static int wpagui_printf(const char *, …)

该静态函数的作用等同于printf,用于在向wpa_supplicant发送命令时接受不知名的反馈并打印出来。

WpaGui(QApplication *app, QWidget *parent = 0, const char *name = 0,Qt::WFlags fl = 0);

WpaGui类的构造函数,作用自然很清晰,就是实例化各个对象指针,连接了各个信号与槽,初始化了变量值,并且调用了如updateStatus()的函数。

~WpaGui()

WpaGui类的析构函数,作用也很清晰,就是在程序运行完毕时释放内存,作清理工作。

languageChange()

使用了Qt设计器的retranslateUi()函数用于语言的切换

parse_argv()

参数的解析函数,用于解析程序被执行时获取的参数,参数可以用来设定与wpa_supplicant交互用的套接字口及是否启动隐藏于任务栏。

openCtrlConnection(const char *ifname)

建立ctrl连接函数,在与wpa_supplicant交互前,首先要使用wpa_supllicant的接口来建立连接,该函数会通过默认的参数或者程序执行时提供的参数,到指定目录下去寻找套接口文件,一旦找到,就建立连接。一般情况下,会建立两个连接,一个用于发送命令,一个用于监视状态,也就是头文件里声明的变量monitor_conn和ctrl_conn;

ctrlRequest(const char *cmd, char *buf, size_t *buflen)

ctrl请求函数,用于向wpa_supplicnat发送各种命令,该函数需要openCtrlConnection函数先建立了与 wpa_supplicant的连接才能正常执行,使用发送命令的连接ctrl_conn来发送,函数内其实使用的是在前篇文章中提到的 wpa_ctrl_request接口函数。

wpaStateTranslate(char *state)

该函数的作用十分简单,就是将获得的状态字符串使用tr函数国际化。

updateStatus()

状态更新函数,使用ctrlRequest函数向wpa_supplicant发送STATUS命令,当执行成功后,wpa_supplicant会反馈具有固定格式的字符串,程序可以根据自己的需要来解析字符串,该函数解析完字符串后即将所需要的信息显示界面上。

updateNetworks()

类似于updateStatue函数,但是也有所不同,它更新的是wifi的network,使用的是LIST_NETWORKS命令,机制也十分简单,当wpa_supplicant连接过或连接上一个wifi的ap,它会在定义好的配置文件里保存下该wifi节点的各种属性,而 LIST_NETWORKS命令使wpa_supplicant去读取该配置文件,然后反馈回去。updateNetworks()在封装了这一步骤的同时,将读取出来的各个wifi的信息显示在界面上。

helpIndex(),helpContents(),helpAbout()

这几个函数只是打印帮助索引和内容,以及显示关于信息。

disconnect()

断开连接函数,当有与wifi的连接存在时,使用该函数即可断开网络连接,实际上是向wpa_supplicant发送了DISCONNECT命令。

scan()

扫描函数,用于扫描周边的wifi节点,实际上上是有ScanResults类来执行。

eventHistory()

事件历史函数,同上个类似,也是有EventHistory类来执行。

ping()

这个函数在WpaGui类中占了相当重要的地位,我们知道,wpa_supplicant的运行实际上是个循环,WpaGui类设置了一个定时器,每过1秒就将执行ping函数,而后在该函数里将调用如updateStatus的函数来进行整体内容的更新。

str_match(const char *a, const char *b)

封装了strcmp函数用于字符串的对比。

通过以上函数,我们可以大致得发现,程序运行的关键在于向wpa_supplicant发送命令,然后得到反馈信息的字符串,最后处理。由于的WpaGui类函数众多,剩余的函数我会在第三部分继续分析。

//////////////////////////////////////////////////////

紧接着上章未完结的,继续分析WpaGui类中的函数。

void processMsg(char *msg)

从名字上可以看出,这是处理消息的函数,处理的消息当然是wpa_supplicant向上层传递的函数。从前面的文章的分析我们可以得知,控制 wpa_supplicant的主要发式就是使用特定接口,将特定的命令字符串传送过去,而wpa_supplicant作为反馈的是及时的字符串消息,以及当完成某项任务后的消息。比如,当扫描完成后,wpa_supplicant就会发送WPA_EVENT_SCAN_RESULTS表示已经可以接受扫描结果了。而该函数,自然就根据wpa_spplicant发送过来的消息做相对应的处理。

void processCtrlReq(const char *req)

用来处理界面上用户发出的请求,具体有UserDataRequest类来完成。

void receiveMsgs()

既然要处理消息,就首先要获得消息,该函数就是用来接受wpa_supplicant发送过来的消息。

void connectB()

从字面上来看,是用来进行连接的,其实如果用网络链接的术语来说,是进行关联,使用的是REASSOCIATE命令让wpa_supplicant去连接上无线网络。

void selectNetwork( const QString &sel )

用来选择无线网络,非常好理解,使用SELECT_NETWORK命令操作。

void enableNetwork(const QString &sel)

void disableNetwork(const QString &sel)

这两个函数是想对应的,在连接一个无线网络之前,首先要使这个网络的参数配置可用,如果不想使用,则可以使它不可用。分别使用ENABLE_NETWORK和DISABLE_NETWORK命令。

void editNetwork(const QString &sel)

void editSelectedNetwork()

void editListedNetwork()

配置无线网络的各项参数,具体部分由NetworkConfig来完成,而editSelectNetwork()是配置选择好的无线网络,是通过调用editNetwork()实现的,editListedNetwork()也同样是通过调用editNetwork()实现,作用是配置已经列出来的无线网络。
void triggerUpdate()

触发更新,用来更新网络的状态和参数。

void addNetwork()

增加一个新的网络,一般可以用来连接隐藏的无线网络,具体实现也是由NetworkConfig()完成。

void removeNetwork(const QString &sel)

void removeSelectedNetwork()

void removeListedNetwork()

与上面配置无线网络的三个函数类似,但作用不同在于是移除无线网络的配置。当从一个地点到里另外一个地点后,原有的无线网络可能会不存在,但是它的配置参数依旧还存在,这时可以使用这几个函数来移除无线网络无效的配置。使用的是REMOVE_NETWORK命令。

void enableAllNetworks()

void disableAllNetworks()

简单的两个函数,使全部配置好的无线网络可用或不可用,是在原来的ENABLE_NETWORK和DISABLE_NETWORK命令基础上,加上all参数来表示对全部网络生效。

void removeAllNetworks()

移除全部网络,是REMOVE_NETWORK命令后加上all的参数实现。

void saveConfig()

其实配置一个网络,在过程中都是在内存中进行的,如果这是没有保存,关闭程序的话,当下次重新启动时,会发现认为配置好的网络参数依旧不存在。而saveConfig()函数的作用就是将内存中的配置保存到文件中,使用的是SAVE_CONFIG命令。

以上就是大部分WpaGui类中函数的分析,其实还有很多函数并没有详细介绍,但是有一部分是与win下套接字变成有关,我并不是非常了解,还有一部分只是单纯的与程序的运行,比如隐藏在系统托盘上等有关,对我们了解wpa_gui的整体框架并不是有很大的帮助。

最后可以总结下,其实wpa_gui就是为wpa_supplicant底层程序增加了一套Qt4的图形交互界面,而这样的构架可以在对未来我们实际项目的设计上有一定的帮助,比如如何做到后台功能和前台界面的分离,如何做到跨平台,都有某种程度的启发。

wpa_supplicant demo 分析相关推荐

  1. qml demo分析(threadedanimation-线程动画)

    一.效果预览 使用过qml的同学都知道,使用qml做动画效果是非常简单的,再也不需要像QWidget那样,自己模拟一个动画,费时又费力,往往还达不到效果.今天我们就来分析下qml的两种动画实现方式,如 ...

  2. go-pitaya学习笔记(9)-rate_limiting demo分析

    学习笔记: 我家别墅靠大海/pitaya-learn 尝试集成功能:我家别墅靠大海/pitaya-game 如果你正在看此笔记,请你左边放笔记,右边放chatdemo的代码!! 我是按代码的顺序记的笔 ...

  3. wpa_supplicant软件架构分析

    wpa_supplicant软件架构分析 1. 启动命令 wpa supplicant 在启动时,启动命令可以带有很多参数,目前我们的启动命令如下: wpa_supplicant /system/bi ...

  4. go-pitaya学习笔记(6)-cluster-protobuf demo分析

    学习笔记: 我家别墅靠大海/pitaya-learn 尝试集成功能:我家别墅靠大海/pitaya-game 如果你正在看此笔记,请你左边放笔记,右边放chatdemo的代码!! 我是按代码的顺序记的笔 ...

  5. go-pitaya学习笔记(7)-custom_metrics demo分析

    学习笔记: 我家别墅靠大海/pitaya-learn 尝试集成功能:我家别墅靠大海/pitaya-game 如果你正在看此笔记,请你左边放笔记,右边放chatdemo的代码!! 我是按代码的顺序记的笔 ...

  6. motan学习笔记 三 motan Demo 分析

    motan学习笔记 一 微博轻量级RPC框架Motan motan学习笔记 二 motan架构分析 motan学习笔记 三 motan Demo 分析 motan学习笔记 四 motan Demo 之 ...

  7. (原创)cocos2dx-lua TableView官方demo分析

    本来是想看看网上的教程文章,结果看了好几篇,复制代码各种报错,有很多不存在的类和变量,根本用不了. 所以干脆自己去看官方demo,经过自己分析测试,已经大概会用了,顺便记录一下. 以下是代码,复制粘贴 ...

  8. 红橙Darren视频笔记 从AIDL Demo分析Android源码走向

    一 AIDL demo 1.1 服务端搭建 新建AIDL文件 // IUserCalc.aidl package com.example.aidlserver;// Declare any non-d ...

  9. 有关wifi配置工具wpa_cli以及wpa_supplicant简单分析

    最近在公司开发新产品智能Android机器人,开始使用的是rk3229开发板,在调试wifi的时候经常用到工具wap_cli,开始使用demo板调试的时候wpa_cli可以正常使用.但是由于产品需要支 ...

最新文章

  1. CodeForces 768E Game of Stones 打表找规律
  2. Leetcode1701. 平均等待时间[C++题解]:模拟题
  3. 深度学习入门教程UFLDL学习实验笔记一:稀疏自编码器
  4. java rmi 还有用吗_java rmi使用后的感想
  5. 回文链表—leetcode234
  6. 前端学习(395):京东制作页面4自己制作icon图标
  7. Jenkins+Gitlab+ansible-playbook上线流程
  8. 盘点语音识别技术在人工智能中的应用
  9. 女孩必读:打死不能嫁的36种男人
  10. 业务流程图_你会用Visio制作专业的业务流程图吗?
  11. vue 圆形 水波_canvas 水滴图、液体进度条、仿加速球、圆球水波图
  12. 高频分类ISO1443, ISO15693, ISO18000-3
  13. spring aop 和Transaction一起使用执行顺序问题
  14. ctf解密图片得到flag_图片隐藏flag怎么找
  15. FastAdmin 文件图片上传失败File size error
  16. 编写程序的目的?为什么要学习编程
  17. 阿里推送 NodeJS 给iOS及ANDROID 发推送。
  18. 1分钟快速了解MindMapper 与MindManager间的不同点
  19. 陪审团(01背包, 难)
  20. 【纪中受难记】——Day23:受刑

热门文章

  1. 半实物仿真测试工具——ETest
  2. 周阳老师springcloud学习总结
  3. 尚硅谷2020最新版周阳SpringCloud(H版alibaba)框架开发教程 学习笔记
  4. 删除加减 高德地图_网上叫个车就这么简单!活用手机地图软件其实不难|银发智慧学堂...
  5. Paper reading: SinGAN(ICCV 2019)
  6. delphi xe 10.3 用FastReport打印预览当前记录
  7. 2016:iOS开发趋势思考--写的有趣~
  8. Oracle 之 proces、session 关系
  9. 随机密码生成。编写程序,接收列表在26个字母大小写和10个数字组成的列表中随机生成10个8位密码。
  10. Google Earth Engine——地球科学激光测高系统(GLAS)的空间激光雷达数据(2005年)融合的全球树木高度数据集1000m分辨率下载(墨西哥为例)