xref: /OK3568_Linux_fs/external/rkwifibt-app/test/softap/softap.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include <fcntl.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <stdbool.h>
7 
8 #include <Rk_softap.h>
9 #include <Rk_wifi.h>
10 
11 #define DBG 1
12 
13 #if DBG
14 #define DEBUG_INFO(M, ...) printf("Hostapd %d: " M, __LINE__, ##__VA_ARGS__)
15 #else
16 #define DEBUG_INFO(M, ...) do {} while (0)
17 #endif
18 #define DEBUG_ERR(M, ...) printf("Hostapd %d: " M, __LINE__, ##__VA_ARGS__)
19 
exec_command(char cmdline[],char recv_buff[],int len)20 static void exec_command(char cmdline[], char recv_buff[], int len)
21 {
22 	printf("[BT_DEBUG] execute: %s\n", cmdline);
23 
24 	FILE *stream = NULL;
25 	char *tmp_buff = recv_buff;
26 
27 	memset(recv_buff, 0, len);
28 
29 	if ((stream = popen(cmdline, "r")) != NULL) {
30 		while (fgets(tmp_buff, len, stream)) {
31 			//pr_info("tmp_buf[%d]: %s\n", strlen(tmp_buff), tmp_buff);
32 			tmp_buff += strlen(tmp_buff);
33 			len -= strlen(tmp_buff);
34 			if (len <= 1)
35 				break;
36 		}
37 
38 		printf("[BT_DEBUG] execute_r: %s \n", recv_buff);
39 		pclose(stream);
40 	} else
41 		printf("[popen] error: %s\n", cmdline);
42 }
43 
console_run(const char * cmdline)44 static const int console_run(const char *cmdline)
45 {
46 	int ret;
47 
48 	DEBUG_INFO("cmdline = %s\n", cmdline);
49 
50 	ret = system(cmdline);
51 	if (ret < 0) {
52 		DEBUG_ERR("Running cmdline failed: %s\n", cmdline);
53 		return 0;
54 	}
55 
56 	return 1;
57 }
58 
create_hostapd_file(char * ap,char * ssid,char * psk)59 static int create_hostapd_file(char *ap, char *ssid, char *psk)
60 {
61 	FILE* fp;
62 	char cmdline[256] = {0};
63 	static char HOSTAPD_CONF_DIR[] = "/userdata/bin/hostapd.conf";
64 
65 	fp = fopen(HOSTAPD_CONF_DIR, "wt+");
66 	if (NULL == fp)
67 		return -1;
68 
69 	sprintf(cmdline, "interface=%s\n", ap);
70 	fputs(cmdline, fp);
71 	fputs("ctrl_interface=/var/run/hostapd\n", fp);
72 	fputs("driver=nl80211\n", fp);
73 	fputs("ssid=", fp);
74 	fputs(ssid, fp);
75 	fputs("\n", fp);
76 	fputs("channel=6\n", fp);
77 	fputs("hw_mode=g\n", fp);
78 	fputs("ieee80211n=1\n", fp);
79 	fputs("ignore_broadcast_ssid=0\n", fp);
80 
81 	if (psk != NULL && 0 != strcmp(psk, "")) {
82 		fputs("auth_algs=1\n", fp);
83 		fputs("wpa=3\n", fp);
84 		fputs("wpa_passphrase=", fp);
85 		fputs(psk, fp);
86 		fputs("\n", fp);
87 		fputs("wpa_key_mgmt=WPA-PSK\n", fp);
88 		fputs("wpa_pairwise=TKIP\n", fp);
89 		fputs("rsn_pairwise=CCMP", fp);
90 	}
91 
92 	fclose(fp);
93 	return 0;
94 }
95 
creat_dnsmasq_file()96 static int creat_dnsmasq_file()
97 {
98 	FILE* fp;
99 	static char DNSMASQ_CONF_DIR[] = "/userdata/bin/dnsmasq.conf";
100 	static char SOFTAP_INTERFACE_STATIC_IP[] = "10.201.126.1";
101 
102 	system("rm /userdata/bin/dnsmasq.conf -rf");
103 
104 	fp = fopen(DNSMASQ_CONF_DIR, "wt+");
105 	if (NULL == fp)
106 		return 0;
107 
108 	fputs("user=root\n", fp);
109 	fputs("listen-address=", fp);
110 	fputs(SOFTAP_INTERFACE_STATIC_IP, fp);
111 	fputs("\n", fp);
112 	fputs("dhcp-range=10.201.126.50,10.201.126.150\n", fp);
113 	fputs("server=/google/8.8.8.8\n", fp);
114 	fclose(fp);
115 	return 1;
116 }
117 
start_hostapd(char * ap,char * ssid,char * psk,char * ip)118 static int start_hostapd(char *ap, char *ssid, char *psk, char *ip)
119 {
120 	char cmdline[256] = {0};
121 	static char DNSMASQ_CONF_DIR[] = "/userdata/bin/dnsmasq.conf";
122 	static char HOSTAPD_CONF_DIR[] = "/userdata/bin/hostapd.conf";
123 	create_hostapd_file(ap, ssid, psk);
124 
125 	sprintf(cmdline, "ifconfig %s up", ap);
126 	console_run(cmdline);
127 	sleep(1);
128 	sprintf(cmdline, "ifconfig %s 10.201.126.1 netmask 255.255.255.0", ap);
129 	console_run(cmdline);
130 	//sprintf(cmdline, "route add default gw %s %s", ip, ap);
131 	//console_run(cmdline);
132 
133 	creat_dnsmasq_file();
134 	memset(cmdline, 0, sizeof(cmdline));
135 	sprintf(cmdline, "dnsmasq -C %s --interface=%s", DNSMASQ_CONF_DIR, ap);
136 	console_run(cmdline);
137 
138 	memset(cmdline, 0, sizeof(cmdline));
139 	sprintf(cmdline, "hostapd %s &", HOSTAPD_CONF_DIR);
140 	console_run(cmdline);
141 
142 	int time = 100;
143 	while (time-- > 0 && access("/var/run/hostapd", F_OK)) {
144 		usleep(100 * 1000);
145 	}
146 	return 0;
147 }
148 
wifi_start_hostapd(char * ssid,char * psk,char * ip)149 int wifi_start_hostapd(char *ssid, char *psk, char *ip)
150 {
151 	char wifi_type[128];
152 	char ap[64];
153 
154 	console_run("killall dnsmasq");
155 	console_run("killall hostapd");
156 	console_run("killall udhcpc");
157 
158 	exec_command("ifconfig -a | grep p2p0", wifi_type, 128);
159 	if (strstr(wifi_type, "p2p0")) {
160 		strcpy(ap, "p2p0");
161 		console_run("ifconfig p2p0 down");
162 		console_run("rm -rf /userdata/bin/p2p0");
163 	} else {
164 		strcpy(ap, "wlan1");
165 		console_run("ifconfig wlan1 down");
166 		console_run("rm -rf /userdata/bin/wlan1");
167 		console_run("iw dev wlan1 del");
168 		console_run("ifconfig wlan0 up");
169 
170 		if (!strncmp(wifi_type, "AP6181", 6))
171 			console_run("iw dev wlan0 interface add wlan1 type __ap");
172 		else
173 			console_run("iw phy0 interface add wlan1 type managed");
174 	}
175 
176 	return start_hostapd(ap, ssid, psk, ip);
177 }
178 
wifi_stop_hostapd(void)179 int wifi_stop_hostapd(void)
180 {
181 	char wifi_type[128];
182 
183 	console_run("killall hostapd");
184 	console_run("killall dnsmasq");
185 	exec_command("ifconfig -a | grep p2p0", wifi_type, 128);
186 	if (strstr(wifi_type, "p2p0")) {
187 		console_run("ifconfig p2p0 down");
188 	} else {
189 		console_run("ifconfig wlan1 down");
190 	}
191 
192 	int time = 100;
193 	while (time-- > 0 && !access("/var/run/hostapd", F_OK)) {
194 		usleep(10 * 1000);
195 	}
196 
197 	return 0;
198 }
199 
200 #include <arpa/inet.h>
201 #include <netinet/in.h>
202 #include <sys/socket.h>
203 #include <sys/types.h>
204 #include <sys/wait.h>
205 #include <sys/prctl.h>
206 #include <unistd.h>
207 #include <pthread.h>
208 
209 typedef struct {
210 	RK_SOFTAP_STATE_CALLBACK callback;
211 	RK_SOFTAP_SERVER_TYPE server_type;
212 } RkSoftAp;
213 
214 #define REQUEST_WIFI_LIST					"/provision/wifiListInfo"
215 #define REQUEST_WIFI_SET_UP					"/provision/wifiSetup"
216 #define REQUEST_IS_WIFI_CONNECTED			"/provision/wifiState"
217 #define REQUEST_POST_CONNECT_RESULT			"/provision/connectResult"
218 
219 #define MSG_BUFF_LEN 8888
220 static char HTTP_RESPOSE_MESSAGE[] = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\nContent-Length:%d\r\n\r\n%s";
221 
222 RkSoftAp m_softap;
223 
224 #define SOCKET_PORT 8443
225 
226 pthread_t m_thread;
227 bool m_isConnecting = false;
228 static int fd_server = -1;
229 static int m_port;
230 
231 static RK_SOFTAP_STATE_CALLBACK m_cb = NULL;
232 static RK_SOFTAP_STATE m_state = RK_SOFTAP_STATE_IDLE;
233 
sendState(RK_SOFTAP_STATE state,const char * data)234 static void sendState(RK_SOFTAP_STATE state, const char* data) {
235 	if(m_cb != NULL)
236 		m_cb(state, data);
237 }
238 
initSocket(const unsigned int port)239 static int initSocket(const unsigned int port)
240 {
241 	int ret, fd_socket, val = 1;
242 	struct sockaddr_in server_addr;
243 
244 	/* create a socket */
245 	fd_socket = socket(AF_INET, SOCK_STREAM, 0);
246 	if (fd_socket < 0) {
247 		printf("%s: create socket failed\n", __func__);
248 		return -1;
249 	}
250 
251 	/* set socket non-blocking */
252 	//int flags;
253 	//flags = fcntl(fd_socket, F_GETFL, 0);
254 	//fcntl(sock, F_SETFL, flags | O_NONBLOCK);
255 
256 	ret = setsockopt(fd_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int));
257 	if (ret < 0) {
258 		printf("%s: setsockopt failed, ret: %d\n", __func__, ret);
259 		return -2;
260 	}
261 
262 	/* initialize server address */
263 	bzero(&server_addr, sizeof(server_addr));
264 	server_addr.sin_family = AF_INET;
265 	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
266 	server_addr.sin_port = htons(port);
267 
268 	/* bind with the local file */
269 	ret = bind(fd_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
270 	if (ret < 0) {
271 		printf("%s: bind failed, ret: %d\n", __func__, ret);
272 		close(fd_socket);
273 		return -3;
274 	}
275 
276 	/* listen */
277 	ret = listen(fd_socket, 1);
278 	if (ret < 0) {
279 		printf("%s: listen failed, ret: %d\n", __func__, ret);
280 		close(fd_socket);
281 		return -4;
282 	}
283 
284 	return fd_socket;
285 }
286 
sendWifiList(const int fd,const char * buf)287 static int sendWifiList(const int fd, const char* buf)
288 {
289 	char msg[MSG_BUFF_LEN] = {0};
290 	char send_msg[MSG_BUFF_LEN] = {0};
291 	size_t i, size = 0;
292 	char *wifilist;
293 
294 scan_retry:
295 	printf("[RK] RK_wifi_scan ...\n");
296 	RK_wifi_scan();
297 	usleep(800000);
298 
299 	printf("[RK] RK_wifi_scan_r_sec ...\n");
300 	wifilist = RK_wifi_scan_for_softap();
301 	printf("[RK] RK_wifi_scan_r_sec end wifilist: %p\n", wifilist);
302 
303 	if (wifilist == NULL)
304 		goto scan_retry;
305 	if (wifilist && (strlen(wifilist) < 3)) {
306 		free(wifilist);
307 		goto scan_retry;
308 	}
309 
310 	strcpy(msg, "{\"type\":\"WifiList\", \"content\":");
311 	strcat(msg, wifilist);
312 	strcat(msg, "}");
313 
314 	snprintf(send_msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, strlen(msg), msg);
315 
316 	printf("scan_r: %s\n", send_msg);
317 
318 	if (send(fd, send_msg, sizeof(send_msg), 0) < 0) {
319 		return false;
320 	}
321 
322 	free(wifilist);
323 	return true;
324 }
325 
isWifiConnected(const int fd,const char * buf)326 static int isWifiConnected(const int fd, const char* buf)
327 {
328 	char msg[MSG_BUFF_LEN] = {0};
329 	bool isConn = 0;
330 
331 	RK_WIFI_INFO_Connection_s info;
332 
333 	if (!RK_wifi_running_getConnectionInfo(&info)) {
334 		if (strncmp(info.wpa_state, "COMPLETED", 9) == 0)
335 			isConn = 1;
336 	}
337 
338 	memset(msg, 0, sizeof(msg));
339 	snprintf(msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, 1, isConn ? "1" : "0");
340 
341 	m_isConnecting = false;
342 
343 	if (send(fd, msg, sizeof(msg), 0) < 0) {
344 		return false;
345 	}
346 
347 	return true;
348 }
349 
350 static char softap_ssid[128];
351 static char softap_psk[128];
352 
wifiSetup(const int fd,const char * buf)353 static bool wifiSetup(const int fd, const char* buf)
354 {
355 	char msg[MSG_BUFF_LEN] = {0};
356 	char *str1, *str2;
357 	char tmp[128];
358 	int ret;
359 
360 	printf("enter %s\n", __func__);
361 
362 	memset(msg, 0, sizeof(msg));
363 	snprintf(msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, 0, "");
364 	if (send(fd, msg, sizeof(msg), 0) < 0) {
365 		return false;
366 	}
367 
368 	if (m_isConnecting == true)
369 		return false;
370 
371 	memset(softap_ssid, 0, 128);
372 	memset(softap_psk, 0, 128);
373 
374 	//{"ssid":"YHX","pwd":"rk123456789"}
375 	str1 = strstr(buf, "\"ssid\"");
376 	str2 = strstr(buf, "\"\,\"pwd\"");
377 	strncpy(softap_ssid, str1 + 8, str2 - str1 - 8);
378 
379 	str1 = strstr(buf, "\"pwd\"");
380 	str2 = strstr(str1, "\"\}");
381 	strncpy(softap_psk, str1 + 7, str2 - str1 - 7);
382 
383 	printf("do connect ssid:\"%s\", psk:\"%s\", isConnecting:%d\n", softap_ssid, softap_psk, m_isConnecting);
384 
385 	sendState(RK_SOFTAP_STATE_CONNECTTING, NULL);
386 	m_state = RK_SOFTAP_STATE_CONNECTTING;
387 
388 	system("wpa_cli -i wlan0 remove_network all");
389 
390 	ret = RK_wifi_connect(softap_ssid, softap_psk);
391 	if (ret < 0) {
392 		sendState(RK_SOFTAP_STATE_FAIL, NULL);
393 		m_state = RK_SOFTAP_STATE_FAIL;
394 		m_isConnecting = false;
395 		return false;
396 	}
397 
398 	m_isConnecting = true;
399 
400 	printf("exit %s\n", __func__);
401 	return true;
402 }
403 
doConnectResult(const int fd,const char * buf)404 static bool doConnectResult(const int fd, const char* buf)
405 {
406 	char msg[MSG_BUFF_LEN] = {0};
407 	char result[2];
408 	char *str;
409 
410 	memset(msg, 0, sizeof(msg));
411 	snprintf(msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, 0, "");
412 	if (send(fd, msg, sizeof(msg), 0) < 0) {
413 		return false;
414 	}
415 
416 	//{"result":"0"}
417 	str = strstr(buf, "\"result\"");
418 	strncpy(result, str + 10, 1);
419 	printf("%s: %s", __func__, result);
420 
421 	if (strncmp(result, "1", 1) == 0) { // connect success, disable ap
422 		sendState(RK_SOFTAP_STATE_SUCCESS, NULL);
423 		m_state = RK_SOFTAP_STATE_SUCCESS;
424 		wifi_stop_hostapd();
425 	} else {
426 		sendState(RK_SOFTAP_STATE_FAIL, NULL);
427 		m_state = RK_SOFTAP_STATE_FAIL;
428 	}
429 
430 	return true;
431 }
432 
handleRequest(const int fd_client)433 static void handleRequest(const int fd_client)
434 {
435 	size_t n;
436 	char buf[2048] = {0};
437 
438 	n = recv(fd_client, buf, sizeof(buf), 0);
439 	if (n <= 0) {
440 		close(fd_client);
441 		return;
442 	}
443 	buf[n] = '\0';
444 	printf("TcpServer recv buf:\n[%s]\n", buf);
445 
446 	if (strstr(buf, REQUEST_WIFI_LIST)) {
447 		sendWifiList(fd_client, buf);
448 	} else if (strstr(buf, REQUEST_WIFI_SET_UP)) {
449 		wifiSetup(fd_client, buf);
450 	} else if (strstr(buf, REQUEST_IS_WIFI_CONNECTED)) {
451 		isWifiConnected(fd_client, buf);
452 	} else if (strstr(buf, REQUEST_POST_CONNECT_RESULT)) {
453 		doConnectResult(fd_client, buf);
454 	}
455 
456 	close(fd_client);
457 }
458 
threadAccept(void * arg)459 static void *threadAccept(void *arg)
460 {
461 	int fd_client, port;
462 	struct sockaddr_in addr_client;
463 	socklen_t len_addr_client;
464 	len_addr_client = sizeof(addr_client);
465 
466 	prctl(PR_SET_NAME, "threadAccept");
467 
468 	port = *(int *)arg;
469 
470 	printf("threadAccept port = %d\n", port);
471 	fd_server = initSocket(port);
472 	if (fd_server < 0) {
473 		printf("TcpServer::threadAccept init tcp socket port %d fail. error:%d\n", port, fd_server);
474 		goto end;
475 	}
476 
477 	/* Accept connection all time */
478 	while (1) {
479 		printf("accept...\n");
480 		fd_client = accept(fd_server, (struct sockaddr *)&addr_client, &len_addr_client);
481 		printf("accept fd_client = %d\n", fd_client);
482 		if (fd_client < 0)
483 			goto end;
484 
485 		handleRequest(fd_client);
486 
487 		if (m_state == RK_SOFTAP_STATE_SUCCESS)
488 			break;
489 	}
490 
491 end:
492 	printf("Exit Tcp accept thread\n");
493 
494 	shutdown(fd_server, SHUT_RDWR);
495 	close(fd_server);
496 	fd_server = -1;
497 
498 	return NULL;
499 }
500 
startTcpServer(void)501 static int startTcpServer(void)
502 {
503 	int ret;
504 
505 	m_port = SOCKET_PORT;
506 	m_state = RK_SOFTAP_STATE_IDLE;
507 	printf("startTcpServer m_port = %d\n", m_port);
508 	ret = pthread_create(&m_thread, NULL, threadAccept, &m_port);
509 
510 	return ret;
511 }
512 
stopTcpServer()513 static int stopTcpServer()
514 {
515 	if (m_thread <= 0)
516 		return 0;
517 
518 	if (fd_server >= 0) {
519 		shutdown(fd_server, SHUT_RDWR);
520 		close(fd_server);
521 		fd_server = -1;
522 	}
523 
524 	if (0 != pthread_join(m_thread, NULL)) {
525 		printf("stopTcpServer fail\n");
526 		return -1;
527 	}
528 
529 	m_thread = 0;
530 	printf("stopTcpServer success\n");
531 	return 0;
532 }
533 
RK_softap_start(char * name,RK_SOFTAP_SERVER_TYPE server_type)534 int RK_softap_start(char *name, RK_SOFTAP_SERVER_TYPE server_type)
535 {
536 	RK_wifi_enable(1);
537 	wifi_start_hostapd(name, NULL, NULL);
538 	startTcpServer();
539 
540 	return 0;
541 }
542 
RK_softap_stop(void)543 int RK_softap_stop(void)
544 {
545 	stopTcpServer();
546 	wifi_stop_hostapd();
547 	return 0;
548 }
549 
550 
RK_softap_register_callback(RK_SOFTAP_STATE_CALLBACK cb)551 int RK_softap_register_callback(RK_SOFTAP_STATE_CALLBACK cb) {
552 	m_cb = cb;
553 	return 0;
554 }
555 
RK_softap_getState(RK_SOFTAP_STATE * pState)556 int RK_softap_getState(RK_SOFTAP_STATE *pState)
557 {
558 	return m_state;
559 }
560