【瑞芯微Rockchip Linux平台】P2P需求实现,重写wpa_cli代码实现启动P2P
【瑞芯微Rockchip Linux平台】P2P需求实现,重写wpa_cli代码实现启动P2P
由于在瑞芯微Rockchip Linux
平台中,并没有提供操作P2P
相关的接口给到上层,
因此,根据上层的需求,我需要写一个库,供上层调用来实现打开和关闭P2P
。
操作P2P 相关的命令可以参考我之前写的博文:《如何使用wpa_supplicant及wpa_cli 创建p2p》
本需求,我准备通过重写 wpa_cli.cpp
来实现,wpa_cli
中提供了一系列的操作P2P 的接口,最简单的方法就是直接改写wpa_cli.cpp
, 在其中添加需求相关的代码。
1. 重写wpa_cli.c的编译规则为CMakeLists.txt
ROCKCHIP 平台中,wpa_cli.c的代码中径位于。./buildroot/output/rockchip_px30_64/build/wpa_supplicant-2.6/wpa_supplicant/wpa_cli.c
根据它的依赖信息,最终
确认需要这几个源文件,头文件的话,根据编译,有啥报错就加啥。
common.c
wpa_debug.c
os_unix.c
eloop.c
edit.c
cli.c
wpa_ctrl.c
wpa_cli.c
编写 CMakeLists.txt 内容如下:
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
add_definitions("-DWPA_IGNORE_CONFIG_ERRORS")
set(VERSION_STR_POSTFIX "-$(PLATFORM_VERSION)")
set(ANDROID_LOG_NAME "wpa_supplicant")
add_definitions("-DANDROID_P2P")
add_definitions("-DCONFIG_FST")
add_definitions("-DCONFIG_MATCH_IFACE")
add_definitions(-DVERSION="2.78")
if(CONFIG_NO_ROAMING)
add_definitions("-DCONFIG_NO_ROAMING")
endif(CONFIG_NO_ROAMING)
set(CONFIG_CTRL_IFACE_CLIENT_DIR "/data/misc/wifi/sockets")
set(CONFIG_CTRL_IFACE_DIR "/data/misc/wifi/sockets")
set(CONFIG_WPA_CLI_HISTORY_DIR "/data/misc/wifi")
if(CONFIG_IEEE80211N)
add_definitions("-DCONFIG_IEEE80211N")
if(CONFIG_IEEE80211AC)
add_definitions("-DCONFIG_IEEE80211AC")
endif(CONFIG_IEEE80211AC)
endif(CONFIG_IEEE80211N)
add_definitions("-DCONFIG_CTRL_IFACE")
add_definitions("-DCONFIG_CTRL_IFACE_UNIX")
set(P2P_SRC_FILES
common.c
wpa_debug.c
os_unix.c
eloop.c
edit.c
cli.c
wpa_ctrl.c
wpa_cli.c
)
add_executable(p2p_bin ${P2P_SRC_FILES})
target_include_directories(p2p_bin PUBLIC "./" )
target_link_libraries(p2p_bin pthread DeviceIo)
install(TARGETS p2p_bin DESTINATION bin)
add_library (p2p SHARED ${P2P_SRC_FILES})
target_include_directories(p2p PUBLIC "./" )
install (TARGETS p2p DESTINATION lib )
最终,编译出来的两个文件,一个是可执行程序 p2p_bin,另一个是libp2p.so
2. 改写wpa_cli.c的main() ,启动P2P
注释原来的 wpa_cli.c
中的main
函数,改成我们自已的main
代码:
如下,p2p_create_group
会实现创建P2P前阻塞进程,
如果是直接执行可程序的话,直接kill 进程即可,
如果是调用的库的话,调用p2p_remove_group()
函数,就会退出阻塞状态,关闭P2P
int main(int argc, char *argv[]){
p2p_create_group("P2P_5G", 5785, "123456789",
on_p2p_device_connected_cb, on_p2p_device_disconnected_cb, on_p2p_group_destroyed_cb);
p2p_remove_group();
return 0;
}
3. p2p_create_group() 函数实现
在p2p_create_group
主要工作为:
- 启动
wpa_supplicant
进程,命令为wpa_supplicant -B -i wlan0 -c /data/cfg/wpa_supplicant.conf
- 配置回调函数
- 配置P2P 的频段,此处我们需求是5G,所以必须传入5G 的频段信息,如5785
有关频段信息,可以参考如下:
Mode[G] Channels:
1 = 2412 MHz 4 = 2427 MHz 7 = 2442 MHz 10 = 2457 MHz
2 = 2417 MHz 5 = 2432 MHz 8 = 2447 MHz 11 = 2462 MHz
3 = 2422 MHz 6 = 2437 MHz 9 = 2452 MHz
Mode[A] Channels:
36 = 5180 MHz 64 = 5320 MHz 124 = 5620 MHz 153 = 5765 MHz
40 = 5200 MHz 100 = 5500 MHz 128 = 5640 MHz 157 = 5785 MHz
44 = 5220 MHz 104 = 5520 MHz 132 = 5660 MHz 161 = 5805 MHz
48 = 5240 MHz 108 = 5540 MHz 136 = 5680 MHz 165 = 5825 MHz
52 = 5260 MHz 112 = 5560 MHz 140 = 5700 MHz
56 = 5280 MHz 116 = 5580 MHz 144 = 5720 MHz
60 = 5300 MHz 120 = 5600 MHz 149 = 5745 MHz
Mode[B] Channels:
1 = 2412 MHz 5 = 2432 MHz 9 = 2452 MHz
2 = 2417 MHz 6 = 2437 MHz 10 = 2457 MHz
3 = 2422 MHz 7 = 2442 MHz 11 = 2462 MHz
4 = 2427 MHz 8 = 2447 MHz
- 初始化
wpa_cli
环境 - 创建
P2P
,实际对应的命令为:p2p_group_add persistent=1 freq=5745
, 同时此处会阻塞进程 - 当收到取消阻塞信号时,会往下运行,开始销毁相关资源。
- 停止
wpa_supplicant
进程
int p2p_create_group(const char* device_name, int freq_index, const char* passwd,
on_p2p_device_connected on_conn_cb,
on_p2p_device_disconnected on_disconnect_cb,
on_p2p_group_destroyed on_distroy_cb)
{
int ret = 0;
// 1. 启动 wpa_supplicant 进程,命令为 wpa_supplicant -B -i wlan0 -c /data/cfg/wpa_supplicant.conf
start_wpa_supplicant(device_name, passwd);
printf_t("===>[%s][%d] - device_name=%s, freq_index=%d, passwd=%s\n", __func__, __LINE__,device_name, freq_index, passwd);
#ifdef ON_P2P_CB
// 2. 配置回调函数
g_on_conn_cb = &on_conn_cb;
g_on_disconnect_cb = &on_disconnect_cb;
g_on_distroy_cb = &on_distroy_cb;
#endif
// 3. 配置P2P 的频段,此处我们需求是5G,所以必须传入5G 的频段信息,如5785
if(freq_index > 5000)
g_freq = freq_index;
g_p2p_remote = (struct p2p_device *)malloc(sizeof(struct p2p_device));
g_p2p_remote->mac = (char *) malloc(sizeof(char) * 20);
g_p2p_remote->name = (char *) malloc(sizeof(char) * 50);
g_p2p_remote->ip = (char *) malloc(sizeof(char) * 20);
memset(g_p2p_remote->mac, 0, 20);
memset(g_p2p_remote->name, 0, 50);
memset(g_p2p_remote->ip, 0, 20);
sprintf(g_p2p_remote->mac, "%s", "UNKNOW");
sprintf(g_p2p_remote->name, "%s", "UNKNOW");
sprintf(g_p2p_remote->ip, "%s", "UNKNOW");
g_argv = (char **) malloc(sizeof(char *) * 5);
for(ret = 0; ret<5; ret++){
*(g_argv+ret) = (char *) malloc(sizeof(char) * 50);
memset( *(g_argv+ret), 0, 50);
sprintf(*(g_argv+ret), "%s", "NA");
}
for(ret = 0; ret<g_p2p_device_MAX; ret++){
memset( g_p2p_device[ret].name, 0, 50);
memset( g_p2p_device[ret].mac, 0, 20);
memset( g_p2p_device[ret].vir_mac, 0, 20);
memset( g_p2p_device[ret].ip, 0, 20);
sprintf(g_p2p_device[ret].name, "%s", "UNKNOW");
sprintf(g_p2p_device[ret].mac, "%s", "UNKNOW");
sprintf(g_p2p_device[ret].vir_mac, "%s", "UNKNOW");
sprintf(g_p2p_device[ret].ip, "%s", "UNKNOW");
g_p2p_device[ret].use_cnt = 0;
}
// 4. 初始化 wpa_cli环境
if (os_program_init())
return -1;
interactive = 1;
if (eloop_init())
return -1;
eloop_register_signal_terminate(wpa_cli_terminate, NULL);
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
// 5. 创建P2P ,实际对应的命令为:p2p_group_add persistent=1 freq=5745, 同时此处会阻塞进程
wpa_cli_interactive();
// 6. 当收到取消阻塞信号时,会往下运行,开始销毁相关资源。
os_free(ctrl_ifname);
eloop_destroy();
wpa_cli_cleanup();
for(ret = 0; ret<5; ret++){
if(*(g_argv+ret) != NULL)
free(*(g_argv+ret));
}
if(g_argv != NULL) free(g_argv); g_argv=NULL;
if(g_p2p_remote->mac) free(g_p2p_remote->mac); g_p2p_remote->mac=NULL;
if(g_p2p_remote->name) free(g_p2p_remote->name); g_p2p_remote->name=NULL;
if(g_p2p_remote->ip) free(g_p2p_remote->ip); g_p2p_remote->ip=NULL;
if(g_p2p_remote) free(g_p2p_remote); g_p2p_remote=NULL;
// 7. 停止wpa_supplicant进程
stop_wpa_supplicant();
return 0;
}
4. wpa_cli_interactive() 函数实现
在 wpa_cli_interactive 中,最主要的两个函数就是 try_connection
和 eloop_run
。
在try_connection
中会与 wpa_supplicant 进行链接绑定,此时wpa_cli就和wpa_supplicant建立了相关的通信。
在eloop_run
主要是会循环监听wpa_supplican中的信息的收发,阻塞就是在这实现的。
此处我们重点关注下 try_connection
。
void wpa_cli_interactive(void)
{
eloop_register_timeout(0, 0, try_connection, NULL, NULL);
eloop_run();
eloop_cancel_timeout(try_connection, NULL, NULL);
cli_txt_list_flush(&p2p_peers);
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
cli_txt_list_flush(&ifnames);
cli_txt_list_flush(&networks);
if (edit_started){
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
}
os_free(hfile);
eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
wpa_cli_close_connection();
}
进入 try_connection
函数看下:
可以看到,我们启动P2P 的函数,就放在 done 标签之后。
通过 wpa_cli_cmd_p2p_group_add(ctrl_conn, 2, g_argv);
代码就可以实现以group 组的方式创建P2P 。
void try_connection(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_conn)
goto done;
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
if (wpa_cli_open_connection(ctrl_ifname, 1)) {
if (!warning_displayed) {
printf_t("Could not connect to wpa_supplicant: "
"%s - re-trying\n",
ctrl_ifname ? ctrl_ifname : "(nil)");
warning_displayed = 1;
}
eloop_register_timeout(1, 0, try_connection, NULL, NULL);
return;
}
update_bssid_list(ctrl_conn);
update_networks(ctrl_conn);
if (warning_displayed)
printf_t("Connection established.\n");
done:
wpa_cli_cmd_reconnect(ctrl_conn, 0, NULL);
printf_t("===>开始连接wifi\n");
memset(g_argv[0], 0, 50);
memset(g_argv[1], 0, 50);
memset(g_argv[2], 0, 50);
// p2p_group_add persistent=1 freq=5745
sprintf(g_argv[0], "persistent=%d", 1);
sprintf(g_argv[1], "freq=%d", g_freq);
wpa_cli_cmd_p2p_group_add(ctrl_conn, 2, g_argv);
//start_edit();
}
5. wpa_cli_recv_pending()函数 P2P相关消息处理
前面,我们通过 wpa_cli_cmd_p2p_group_add(ctrl_conn, 2, g_argv);
创建好P2P 后,
接下来,就是循环监听消息,有前消息处理的函数在wpa_cli_recv_pending()
中
可以看出,wpa_supplicant 发过来的消息,就保存在buf 中,通过解析 buf 中的数据,就能够解析到对应的消息。
static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
{
int i = 0;
if (ctrl_conn == NULL) {
wpa_cli_reconnect();
return;
}
while (wpa_ctrl_pending(ctrl) > 0) {
char buf[4096];
char *p_str = NULL, *p_str_1 = NULL;
size_t len = sizeof(buf) - 1;
if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
buf[len] = '\0';
if(strstr(buf, "P2P-DEVICE-FOUND") != NULL){
// P2P-DEVICE-FOUND 12:ea:ca:a9:77:2e p2p_dev_addr=52:7c:85:b2:de:34 pri_dev_type=10-0050F204-5 name='HUAWEI Mate 30 Pro' config_methods=0x188 dev_capab=0x25 group_capab=0x0 vendor_elems=1 new=1
memset(g_p2p_vir_mac, '\0', 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "P2P-DEVICE-FOUND") + 17;
memcpy(g_p2p_vir_mac, p_str, 17); // 截取MAC地址
g_p2p_vir_mac[17] = '\0';
memset(g_p2p_mac, '\0', 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "p2p_dev_addr=") + 13;
memcpy(g_p2p_mac, p_str, 17); // 截取MAC地址
g_p2p_mac[17] = '\0';
memset(g_p2p_name, '\0', 50);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "name=")+6;
p_str_1 = strstr(buf, "config_methods")-2;
memcpy(g_p2p_name, p_str, p_str_1-p_str); // name
g_p2p_name[p_str_1-p_str] = '\0';
printf_t("===>找到新P2P设备: MAC地址:%s, 虚拟MAC地址:%s, 设备名:%s\n", g_p2p_mac,g_p2p_vir_mac, g_p2p_name);
if(is_in_g_p2p_device(g_p2p_vir_mac) == 0){
push_g_p2p_device(g_p2p_name, g_p2p_mac, g_p2p_vir_mac, NULL);
}
printf_p2p_device("新增设备");
}
else if( strstr(buf, "P2P-PROV-DISC-PBC-REQ") != NULL ){
// P2P-PROV-DISC-PBC-REQ f2:84:1f:03:a6:55 p2p_dev_addr=f2:84:1f:03:a6:55 pri_dev_type=10-0050F204-5 name='MI 9' config_methods=0x188 dev_capab=0x25 group_capab=0x0
//<3>P2P-PROV-DISC-PBC-REQ f2:84:1f:03:a6:55 p2p_dev_addr=f2:84:1f:03:a6:55 pri_dev_type=10-0050F204-5 name='MI 9' config_methods=0x188 dev_capab=0x25 group_capab=0x0
memset(g_p2p_vir_mac, '\0', 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "PBC-REQ");
if(p_str != NULL){
p_str += 8;
memcpy(g_p2p_vir_mac, p_str, 17); // 截取MAC地址
g_p2p_vir_mac[17] = '\0';
}
memset(g_p2p_mac, '\0', 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "p2p_dev_addr=");
if(p_str != NULL){
p_str += 13;
memcpy(g_p2p_mac, p_str, 17); // 截取MAC地址
g_p2p_mac[17] = '\0';
}
memset(g_p2p_name, '\0', 50);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "name=");
if(p_str != NULL){
p_str += 6;
p_str_1 = strstr(buf, "config_methods")-2;
memcpy(g_p2p_name, p_str, p_str_1-p_str); // name
g_p2p_name[p_str_1-p_str] = '\0';
}
if(is_in_g_p2p_device(g_p2p_vir_mac) == 0){
push_g_p2p_device(g_p2p_name, g_p2p_mac, g_p2p_vir_mac, NULL);
}
printf_t("===>收到P2P设备请求: MAC地址:%s, 虚拟MAC地址:%s, 设备名:%s\n", g_p2p_mac,g_p2p_vir_mac, g_p2p_name);
char buff_tmp[100]={0};
// wpa_cli -i p2p-wlan0-0 wps_pbc
sprintf(buff_tmp, "wpa_cli -i %s wps_pbc", g_p2p_wlanname);
system(buff_tmp);
}
else if(strstr(buf, "P2P-GROUP-STARTED") != NULL){
// P2P-GROUP-STARTED p2p-wlan0-0 client ssid="DIRECT-CA-MI 9" freq=5745 psk=e6a5c695f22dfc4d778d4ffab953096058d86cd3f0d0735ed30d2a88ff8b9b6b go_dev_addr=f2:84:1f:03:a6:55 [PERSISTENT]
memset(g_discon_reason, '\0', 20);
p_str=NULL;
p_str = strstr(buf, "P2P-GROUP-STARTED");
if(p_str != NULL){
p_str += 18;
i = 0;
while( i<49 && p_str!=NULL && p_str[i]!=' ' && p_str[i]!= '\0'){
g_p2p_wlanname[i] = p_str[i];
i++;
}
g_p2p_wlanname[i] = '\0';
printf_t("===>P2P Group创建成功: %s\n", buf);
// 配置IP,DNS
pthread_t pthreaddns;
if(pthread_create(&pthreaddns,NULL,dnsmasq_thread,NULL))
printf_t("can't create dnsmasq_thread\n");
if(pthreaddns != 0)
pthread_detach(pthreaddns);
}
}
else if(strstr(buf, "P2P-GROUP-REMOVED") != NULL){
//P2P-GROUP-REMOVED p2p-wlan0-0 client reason=GO_ENDING_SESSION
memset(g_discon_reason, '\0', 20);
p_str=NULL;
p_str = strstr(buf, "reason=");
if(p_str != NULL){
i = 0;
p_str += 7;
while( i<19 && p_str!=NULL && p_str[i]!= '\0'){
g_discon_reason[i] = p_str[i];
i++;
}
g_discon_reason[i] = '\0';
printf_t("===>P2P Group销毁成功,reason=%s\n", g_discon_reason);
#ifdef ON_P2P_CB
(*g_on_distroy_cb)(0); // 回调
#endif
}
}
else if(strstr(buf, "AP-STA-CONNECTED") != NULL){
//AP-STA-CONNECTED 42:a4:1d:26:f6:75 p2p_dev_addr=52:7c:85:b2:de:34
printf_t("===>P2P连接成功: %s\n", buf);
memset(g_p2p_vir_mac, 0, 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "AP-STA-CONNECTED");
if(p_str != NULL){
p_str += 17;
memcpy(g_p2p_vir_mac, p_str, 17);
}
memset(g_p2p_remote->mac, 0, 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "p2p_dev_addr=");
if(p_str != NULL){
p_str += 13;
memcpy(g_p2p_remote->mac, p_str, 17);
}else{
memcpy(g_p2p_remote->mac, g_p2p_vir_mac, 17);
}
arp_get_ip(g_p2p_vir_mac);
printf_t("===>P2P连接成功: 真实mac:%s, 虚拟mac:%s, ip=%s\n", g_p2p_remote->mac, g_p2p_vir_mac, g_p2p_remote->ip);
// 本地备份ip 及 mac 信息
struct S_p2p_device* p_device = search_g_p2p_device(g_p2p_remote->mac, g_p2p_vir_mac, 1); // 备份虚拟mac 及IP
if(p_device != NULL){
memset(g_p2p_remote->name, 0, 50);
p_str=NULL; p_str_1=NULL;
p_str=g_p2p_remote->name; p_str_1=p_device->name; while(p_str_1!=NULL && *p_str_1!='\0') *p_str++=*p_str_1++; // 读取name
memset(p_device->vir_mac, 0, 20);
p_str=NULL; p_str_1=NULL;
p_str=p_device->vir_mac; p_str_1=g_p2p_vir_mac; while(p_str_1!=NULL && *p_str_1!='\0') *p_str++=*p_str_1++; // 备份虚拟mac
memset(p_device->ip, 0, 20);
p_str=NULL; p_str_1=NULL;
p_str=p_device->ip; p_str_1=g_p2p_remote->ip; while(p_str_1!=NULL && *p_str_1!='\0') *p_str++=*p_str_1++; // 备份ip
p_device->use_cnt++;
p_device->connected = 1;
printf_p2p_device("连接成功");
}
#ifdef ON_P2P_CB
(*g_on_conn_cb)(g_p2p_remote); // 回调
#endif
}
else if(strstr(buf, "AP-STA-DISCONNECTED") != NULL){
//AP-STA-DISCONNECTED 42:a4:1d:26:f6:75 p2p_dev_addr=52:7c:85:b2:de:34
printf_t("===>P2P断开连接: %s\n", buf);
memset(g_p2p_vir_mac, 0, 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "DISCONNECTED");
if(p_str != NULL){
p_str += +13;
memcpy(g_p2p_vir_mac, p_str, 17); // pri_dev_type
}
memset(g_p2p_remote->mac, 0, 20);
p_str=NULL; p_str_1=NULL;
p_str = strstr(buf, "p2p_dev_addr=");
if(p_str != NULL){
p_str += +13;
memcpy(g_p2p_remote->mac, p_str, 17); // pri_dev_type
}else{
memcpy(g_p2p_remote->mac, g_p2p_vir_mac, 17); // pri_dev_type
}
// 读取本地备份的ip 及 mac 信息
struct S_p2p_device* p_device = search_g_p2p_device(g_p2p_remote->mac, g_p2p_vir_mac, 0); // 通过虚拟拟mac 查找
if(p_device != NULL){
memset(g_p2p_remote->name, 0, 50);
p_str=NULL; p_str_1=NULL;
p_str=g_p2p_remote->name; p_str_1=p_device->name; while(p_str_1!=NULL && *p_str_1!='\0') *p_str++=*p_str_1++; // 读取name
memset(g_p2p_remote->ip, 0, 20);
p_str=NULL; p_str_1=NULL;
p_str=g_p2p_remote->ip; p_str_1=p_device->ip; while(p_str_1!=NULL && *p_str_1!='\0') *p_str++=*p_str_1++; // 读取ip
p_device->connected = 0;
//printf_p2p_device("断开成功");
}
// 清空地址备份的信息, wait do
printf_t("===>P2P断开成功: 真实mac:%s, 虚拟mac:%s, ip=%s\n", g_p2p_remote->mac, g_p2p_vir_mac, g_p2p_remote->ip);
#ifdef ON_P2P_CB
(*g_on_disconnect_cb)(g_p2p_remote); // 回调
#endif
}
if (action_monitor)
wpa_cli_action_process(buf);
else {
cli_event(buf);
if (wpa_cli_show_event(buf)) {
//if(!( strstr(buf, "P2P-DEVICE-FOUND")||strstr(buf, "P2P-GROUP-REMOVED")||
// strstr(buf, "P2P-GROUP-STARTED")||
// /*strstr(buf, "P2P-PROV-DISC-PBC-REQ")||strstr(buf, "P2P-GO-NEG-REQUEST")||*/
// strstr(buf, "P2P-FIND-STOPPED")||strstr(buf, "AP-STA-CONNECTED")||strstr(buf, "AP-STA-DISCONNECTED")||
// strstr(buf, "CTRL-EVENT-SCAN-STARTED") || strstr(buf, "CTRL-EVENT-SCAN-RESULTS") ))
if(!(strstr(buf, "CTRL-EVENT-SCAN-RESULTS") || strstr(buf, "P2P-DEVICE-FOUND") || strstr(buf, "P2P-GROUP-STARTED")
|| strstr(buf, "AP-STA-CONNECTED") ||strstr(buf, "AP-STA-DISCONNECTED") ))
{
edit_clear_line();
printf_t("\r%s\n", buf);
//edit_redraw();
}
}
if (interactive && check_terminating(buf) > 0)
return;
}
} else {
printf_t("Could not read pending message.\n");
break;
}
}
if (wpa_ctrl_pending(ctrl) < 0) {
printf_t("Connection to wpa_supplicant lost - trying to "
"reconnect\n");
wpa_cli_reconnect();
}
}
6. dnsmasq_thread() 线程 配置dns服务
P2P Group创建好后,当有设备连接上默认是不会给它们分配IP地址的,需要配置dns。
从上面代码中,当我们收到 P2P-GROUP-STARTED
消息时,说明P2P group已经创建成功。
此时,我们建立一个线程运行dnsmasq_thread
函数,进行配置dns.
else if(strstr(buf, "P2P-GROUP-STARTED") != NULL){
// P2P-GROUP-STARTED p2p-wlan0-0 client ssid="DIRECT-CA-MI 9" freq=5745 psk=e6a5c695f22dfc4d778d4ffab953096058d86cd3f0d0735ed30d2a88ff8b9b6b go_dev_addr=f2:84:1f:03:a6:55 [PERSISTENT]
memset(g_discon_reason, '\0', 20);
p_str=NULL;
p_str = strstr(buf, "P2P-GROUP-STARTED");
if(p_str != NULL){
p_str += 18;
i = 0;
while( i<49 && p_str!=NULL && p_str[i]!=' ' && p_str[i]!= '\0'){
g_p2p_wlanname[i] = p_str[i];
i++;
}
g_p2p_wlanname[i] = '\0';
printf_t("===>P2P Group创建成功: %s\n", buf);
// 配置IP,DNS
pthread_t pthreaddns;
if(pthread_create(&pthreaddns,NULL,dnsmasq_thread,NULL))
printf_t("can't create dnsmasq_thread\n");
if(pthreaddns != 0)
pthread_detach(pthreaddns);
}
}
我们来看看 dnsmasq_thread
的实现过程。
这个函数中,我写的比较简单,总结起来,其实就是这两个命令:ifconfig p2p_wlan0 192.168.49.1 netmask 255.255.255.0
dnsmasq -C /data/bin/dnsmasq.conf --interface=p2p_wlan0 --except-interface=usb0
代码如下:
void *dnsmasq_thread(void *arg){
char buff_tmp[300]={0}, *p_str=NULL, *p_str_1=NULL;
sprintf(buff_tmp, "ifconfig %s 192.168.49.1 netmask 255.255.255.0", g_p2p_wlanname);
printf_t("===>配置静态IP: %s\n", buff_tmp);
system(buff_tmp);
FILE *fp = NULL;
int pid = 0;
fp = popen("ps -A | grep dnsmasq", "r");
if(fp){
memset(buff_tmp, 0, 300);
while(fgets(buff_tmp, sizeof(buff_tmp)-1, fp) >0){
p_str = buff_tmp;
while(p_str!=NULL && *p_str!='\0' && *p_str==' ') p_str++;
p_str_1 = p_str;
while(p_str_1!=NULL && *p_str_1!='\0' && *p_str_1!=' ') p_str_1++;
*p_str_1 = '\0';
pid = atoi(p_str);
if( kill(pid, 9) == 0)
printf_t("===>杀死后台dnsmasq进程(%d) success\n", pid);
}
pclose(fp);
}
memset(buff_tmp, 0, 300);
sprintf(buff_tmp, "dnsmasq -C /data/bin/dnsmasq.conf --interface=%s --except-interface=usb0", g_p2p_wlanname);
printf_t("===>配置DNS服务: %s\n", buff_tmp);
system(buff_tmp);
return (void *)0;
}
7. start_wpa_supplicant() 启动wpa_supplicant服务
void start_wpa_supplicant(const char* t_device_name, const char* t_passwd)
{
FILE *fp = NULL;
char device_name[100]={0};
char ssid[100]={0};
char bssid[100]={0}, bssid_bak[100]={0}, wlan0_mac[20]={0};
char psk[100]={0};
int flag_name=-1, flag_ssid=-1, flag_psk=-1, flag_bssid=-1, flag_bssid_bak=-1, i=0;
char linedata[100]={0}, temp[100]={0}, *p_buff=NULL, *p_buff1=NULL;
memset(device_name, 0, 50);
memset(ssid, 0, 50);
memset(psk, 0, 50);
fp = fopen("/data/cfg/wpa_supplicant.conf", "r");
i = 0;
if(fp){
while(fgets(linedata, sizeof(linedata)-1, fp)){
i++;
printf_t("--->%s", linedata);
if(strstr(linedata, "device_name=") != NULL){
p_buff = strstr(linedata, "device_name=") ; //+ 12;
p_buff1 = device_name;
while(p_buff!=NULL && *p_buff!=0xa && *p_buff!='\0' ){
*p_buff1++ = *p_buff++;
}
flag_name = i;
}else if( strstr(linedata, "ssid=")!= NULL && strstr(linedata, "bssid=")==NULL && strstr(linedata, "ssid=\"SSID\"")== NULL){
p_buff = strstr(linedata, "ssid="); // + 6;
p_buff1 = ssid;
//while(p_buff!=NULL && *p_buff!=0x22)
while(p_buff!=NULL && *p_buff!=0xa && *p_buff!='\0' )
*p_buff1++ = *p_buff++;
flag_ssid = i;
}
else if( strstr(linedata, "bssid")!= NULL){
p_buff = strstr(linedata, "bssid"); // + 6;
p_buff1 = bssid;
//while(p_buff!=NULL && *p_buff!=0x20 && *p_buff!=0xa )
while(p_buff!=NULL && *p_buff!=0xa && *p_buff!='\0' )
*p_buff1++ = *p_buff++;
printf_t("解析wpa_supplicant.conf: %s\n", bssid);
flag_bssid = i;
}
else if(strstr(linedata, "psk=") != NULL && strstr(linedata, "PASSWORD")==NULL){
p_buff = strstr(linedata, "psk="); // + 5;
p_buff1 = psk;
//while(p_buff!=NULL && *p_buff!=0x22)
while(p_buff!=NULL && *p_buff!=0xa && *p_buff!='\0' )
*p_buff1++ = *p_buff++;
flag_psk = i;
}
if(flag_name>=0 && flag_ssid>=0 && flag_psk>=0 && strstr(linedata, "mode=3") != NULL){
memset(linedata, 0, 100);
break;
}
memset(linedata, 0, 100);
}
fclose(fp);
}
// 解析 /data/cfg/wpa_supplicant_for_bssid.conf 的bssid ,如果一样的话,则直接使用,如果不一样,则重新生成一个
fp = fopen("/data/cfg/wpa_supplicant_for_bssid.conf", "r");
i = 0;
if(fp){
while(fgets(linedata, sizeof(linedata)-1, fp)){
i++;
printf_t("--->%s", linedata);
if( strstr(linedata, "bssid=")!= NULL){
p_buff = strstr(linedata, "bssid="); // + 6;
p_buff1 = bssid_bak;
//while(p_buff!=NULL && *p_buff!=0x20 && *p_buff!=0xa )
while(p_buff!=NULL && *p_buff!=0xa && *p_buff!='\0' )
*p_buff1++ = *p_buff++;
printf_t("解析wpa_supplicant_for_bssid.conf: %s\n", bssid_bak);
flag_bssid_bak = i;
}
memset(linedata, 0, 100);
}
fclose(fp);
}
if( !(flag_bssid >=0 && flag_bssid_bak >= 0 && os_strcmp(bssid, bssid_bak) == 0 ) ){
while(flag_bssid_bak < 0){
printf_t("conf文件中的bssid有误,重新生成一个并替换\n", bssid_bak);
stop_wpa_supplicant();
usleep(100000);
printf_t("wpa_supplicant -B -i wlan0 -c /data/cfg/wpa_supplicant_for_bssid.conf\n", bssid);
system("wpa_supplicant -B -i wlan0 -c /data/cfg/wpa_supplicant_for_bssid.conf");
printf_t("wpa_cli p2p_group_add persistent\n", bssid);
system("wpa_cli p2p_group_add persistent");
usleep(100000);
printf_t("wpa_cli p2p_group_remove p2p-wlan0-0\n", bssid);
system("wpa_cli p2p_group_remove p2p-wlan0-0");
usleep(100000);
// 解析 /data/cfg/wpa_supplicant_for_bssid.conf 的bssid ,如果一样的话,则直接使用,如果不一样,则重新生成一个
fp = fopen("/data/cfg/wpa_supplicant_for_bssid.conf", "r");
i = 0;
if(fp){
printf_t("--->%s\n", linedata);
while(fgets(linedata, sizeof(linedata)-1, fp)){
i++;
if( strstr(linedata, "bssid=")!= NULL){
p_buff = strstr(linedata, "bssid="); // + 6;
p_buff1 = bssid_bak;
//while(p_buff!=NULL && *p_buff!=0x20 && *p_buff!=0xa )
while(p_buff!=NULL && *p_buff!=0xa && *p_buff!='\0' )
*p_buff1++ = *p_buff++;
printf_t("解析wpa_supplicant_for_bssid.conf: %s\n", bssid_bak);
flag_bssid_bak = i;
}
memset(linedata, 0, 100);
}
fclose(fp);
}
}
if(flag_bssid >= 0){
memset(temp, 0, 100); memset(linedata, 0, 100);
sprintf(temp, "s/%s/%s/", bssid, bssid_bak);
sprintf(linedata, "sed -i '%d %s' /data/cfg/wpa_supplicant.conf", flag_bssid, temp);
printf_t("%s\n", linedata);
system(linedata);
p_buff1 = bssid;
p_buff = bssid_bak;
while(p_buff!=NULL && *p_buff!=0xa && *p_buff!='\0' )
*p_buff1++ = *p_buff++;
}else
printf_t("解析bssid 出错,flag_bssid=%d\n", flag_bssid);
}
if(flag_name >= 0){
memset(temp, 0, 100); memset(linedata, 0, 100);
sprintf(temp, "s/%s/device_name=%s-%c%c%c%c/", device_name, t_device_name, bssid[18], bssid[19], bssid[21], bssid[22]);
sprintf(linedata, "sed -i '%d %s' /data/cfg/wpa_supplicant.conf", flag_name, temp);
printf_t("%s\n", linedata);
system(linedata);
}else
printf_t("解析name 出错,flag_name=%d\n", flag_name);
if(flag_ssid >= 0){
memset(temp, 0, 100); memset(linedata, 0, 100);
sprintf(temp, "s/%s/ssid=\"DIRECT-%s-%c%c%c%c\"/", ssid, t_device_name, bssid[18], bssid[19], bssid[21], bssid[22]);
sprintf(linedata, "sed -i '%d %s' /data/cfg/wpa_supplicant.conf", flag_ssid, temp);
printf_t("%s\n", linedata);
system(linedata);
}else
printf_t("解析ssid 出错,flag_ssid=%d\n", flag_ssid);
if(flag_psk >= 0){
memset(temp, 0, 100); memset(linedata, 0, 100);
sprintf(temp, "s/%s/psk=\"%s\"/", psk, t_passwd);
sprintf(linedata, "sed -i '%d %s' /data/cfg/wpa_supplicant.conf", flag_psk, temp);
printf_t("%s\n", linedata);
system(linedata);
}else
printf_t("解析psk 出错,flag_psk=%d\n", flag_psk);
stop_wpa_supplicant();
usleep(200000);
system("wpa_supplicant -B -i wlan0 -c /data/cfg/wpa_supplicant.conf");
system("wpa_cli -i wlan0 reconnect");
}
8. stop_wpa_supplicant() 停止wpa_supplicant服务
void stop_wpa_supplicant(void)
{
FILE *fp = NULL;
int pid = 0;
char buff_tmp[100]={0}, *p_buff=NULL, *p_buff1=NULL;
fp = popen("ps -A | grep wpa_supplicant", "r");
if(fp){
memset(buff_tmp, 0, 100);
while(fgets(buff_tmp, sizeof(buff_tmp)-1, fp) >0){
p_buff = buff_tmp;
while(p_buff!=NULL && *p_buff!='\0' && *p_buff==' ') p_buff++;
p_buff1 = p_buff;
while(p_buff1!=NULL && *p_buff1!='\0' && *p_buff1!=' ') p_buff1++;
*p_buff1 = '\0';
pid = atoi(p_buff);
if( kill(pid, 9) == 0)
printf_t("===>杀死后台wpa_supplicant进程(%d) success\n", pid);
}
pclose(fp);
}
fp = popen("ps -A | grep dnsmasq", "r");
if(fp){
memset(buff_tmp, 0, 100);
while(fgets(buff_tmp, sizeof(buff_tmp)-1, fp) >0){
p_buff = buff_tmp;
while(p_buff!=NULL && *p_buff!='\0' && *p_buff==' ') p_buff++;
p_buff1 = p_buff;
while(p_buff1!=NULL && *p_buff1!='\0' && *p_buff1!=' ') p_buff1++;
*p_buff1 = '\0';
pid = atoi(p_buff);
if( kill(pid, 9) == 0)
printf_t("===>杀死后台dnsmasq进程(%d) success\n", pid);
}
pclose(fp);
}
}
上一篇: 历史上有一位皇帝先皇驾崩,大臣让他哭丧,他的回答让人哭笑不得!
下一篇: 一个简单的mvc实现