欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【瑞芯微Rockchip Linux平台】P2P需求实现,重写wpa_cli代码实现启动P2P

程序员文章站 2022-07-01 10:55:31
...


由于在瑞芯微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主要工作为:

  1. 启动 wpa_supplicant 进程,命令为 wpa_supplicant -B -i wlan0 -c /data/cfg/wpa_supplicant.conf
  2. 配置回调函数
  3. 配置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
  1. 初始化 wpa_cli 环境
  2. 创建P2P ,实际对应的命令为:p2p_group_add persistent=1 freq=5745, 同时此处会阻塞进程
  3. 当收到取消阻塞信号时,会往下运行,开始销毁相关资源。
  4. 停止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_connectioneloop_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);
	}
}
相关标签: Wifi & P2P