560 lines
12 KiB
C
560 lines
12 KiB
C
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdbool.h>
|
|
|
|
#include <Rk_softap.h>
|
|
#include <Rk_wifi.h>
|
|
|
|
#define DBG 1
|
|
|
|
#if DBG
|
|
#define DEBUG_INFO(M, ...) printf("Hostapd %d: " M, __LINE__, ##__VA_ARGS__)
|
|
#else
|
|
#define DEBUG_INFO(M, ...) do {} while (0)
|
|
#endif
|
|
#define DEBUG_ERR(M, ...) printf("Hostapd %d: " M, __LINE__, ##__VA_ARGS__)
|
|
|
|
static void exec_command(char cmdline[], char recv_buff[], int len)
|
|
{
|
|
printf("[BT_DEBUG] execute: %s\n", cmdline);
|
|
|
|
FILE *stream = NULL;
|
|
char *tmp_buff = recv_buff;
|
|
|
|
memset(recv_buff, 0, len);
|
|
|
|
if ((stream = popen(cmdline, "r")) != NULL) {
|
|
while (fgets(tmp_buff, len, stream)) {
|
|
//pr_info("tmp_buf[%d]: %s\n", strlen(tmp_buff), tmp_buff);
|
|
tmp_buff += strlen(tmp_buff);
|
|
len -= strlen(tmp_buff);
|
|
if (len <= 1)
|
|
break;
|
|
}
|
|
|
|
printf("[BT_DEBUG] execute_r: %s \n", recv_buff);
|
|
pclose(stream);
|
|
} else
|
|
printf("[popen] error: %s\n", cmdline);
|
|
}
|
|
|
|
static const int console_run(const char *cmdline)
|
|
{
|
|
int ret;
|
|
|
|
DEBUG_INFO("cmdline = %s\n", cmdline);
|
|
|
|
ret = system(cmdline);
|
|
if (ret < 0) {
|
|
DEBUG_ERR("Running cmdline failed: %s\n", cmdline);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int create_hostapd_file(char *ap, char *ssid, char *psk)
|
|
{
|
|
FILE* fp;
|
|
char cmdline[256] = {0};
|
|
static char HOSTAPD_CONF_DIR[] = "/userdata/bin/hostapd.conf";
|
|
|
|
fp = fopen(HOSTAPD_CONF_DIR, "wt+");
|
|
if (NULL == fp)
|
|
return -1;
|
|
|
|
sprintf(cmdline, "interface=%s\n", ap);
|
|
fputs(cmdline, fp);
|
|
fputs("ctrl_interface=/var/run/hostapd\n", fp);
|
|
fputs("driver=nl80211\n", fp);
|
|
fputs("ssid=", fp);
|
|
fputs(ssid, fp);
|
|
fputs("\n", fp);
|
|
fputs("channel=6\n", fp);
|
|
fputs("hw_mode=g\n", fp);
|
|
fputs("ieee80211n=1\n", fp);
|
|
fputs("ignore_broadcast_ssid=0\n", fp);
|
|
|
|
if (psk != NULL && 0 != strcmp(psk, "")) {
|
|
fputs("auth_algs=1\n", fp);
|
|
fputs("wpa=3\n", fp);
|
|
fputs("wpa_passphrase=", fp);
|
|
fputs(psk, fp);
|
|
fputs("\n", fp);
|
|
fputs("wpa_key_mgmt=WPA-PSK\n", fp);
|
|
fputs("wpa_pairwise=TKIP\n", fp);
|
|
fputs("rsn_pairwise=CCMP", fp);
|
|
}
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
static int creat_dnsmasq_file()
|
|
{
|
|
FILE* fp;
|
|
static char DNSMASQ_CONF_DIR[] = "/userdata/bin/dnsmasq.conf";
|
|
static char SOFTAP_INTERFACE_STATIC_IP[] = "10.201.126.1";
|
|
|
|
system("rm /userdata/bin/dnsmasq.conf -rf");
|
|
|
|
fp = fopen(DNSMASQ_CONF_DIR, "wt+");
|
|
if (NULL == fp)
|
|
return 0;
|
|
|
|
fputs("user=root\n", fp);
|
|
fputs("listen-address=", fp);
|
|
fputs(SOFTAP_INTERFACE_STATIC_IP, fp);
|
|
fputs("\n", fp);
|
|
fputs("dhcp-range=10.201.126.50,10.201.126.150\n", fp);
|
|
fputs("server=/google/8.8.8.8\n", fp);
|
|
fclose(fp);
|
|
return 1;
|
|
}
|
|
|
|
static int start_hostapd(char *ap, char *ssid, char *psk, char *ip)
|
|
{
|
|
char cmdline[256] = {0};
|
|
static char DNSMASQ_CONF_DIR[] = "/userdata/bin/dnsmasq.conf";
|
|
static char HOSTAPD_CONF_DIR[] = "/userdata/bin/hostapd.conf";
|
|
create_hostapd_file(ap, ssid, psk);
|
|
|
|
sprintf(cmdline, "ifconfig %s up", ap);
|
|
console_run(cmdline);
|
|
sleep(1);
|
|
sprintf(cmdline, "ifconfig %s 10.201.126.1 netmask 255.255.255.0", ap);
|
|
console_run(cmdline);
|
|
//sprintf(cmdline, "route add default gw %s %s", ip, ap);
|
|
//console_run(cmdline);
|
|
|
|
creat_dnsmasq_file();
|
|
memset(cmdline, 0, sizeof(cmdline));
|
|
sprintf(cmdline, "dnsmasq -C %s --interface=%s", DNSMASQ_CONF_DIR, ap);
|
|
console_run(cmdline);
|
|
|
|
memset(cmdline, 0, sizeof(cmdline));
|
|
sprintf(cmdline, "hostapd %s &", HOSTAPD_CONF_DIR);
|
|
console_run(cmdline);
|
|
|
|
int time = 100;
|
|
while (time-- > 0 && access("/var/run/hostapd", F_OK)) {
|
|
usleep(100 * 1000);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int wifi_start_hostapd(char *ssid, char *psk, char *ip)
|
|
{
|
|
char wifi_type[128];
|
|
char ap[64];
|
|
|
|
console_run("killall dnsmasq");
|
|
console_run("killall hostapd");
|
|
console_run("killall udhcpc");
|
|
|
|
exec_command("ifconfig -a | grep p2p0", wifi_type, 128);
|
|
if (strstr(wifi_type, "p2p0")) {
|
|
strcpy(ap, "p2p0");
|
|
console_run("ifconfig p2p0 down");
|
|
console_run("rm -rf /userdata/bin/p2p0");
|
|
} else {
|
|
strcpy(ap, "wlan1");
|
|
console_run("ifconfig wlan1 down");
|
|
console_run("rm -rf /userdata/bin/wlan1");
|
|
console_run("iw dev wlan1 del");
|
|
console_run("ifconfig wlan0 up");
|
|
|
|
if (!strncmp(wifi_type, "AP6181", 6))
|
|
console_run("iw dev wlan0 interface add wlan1 type __ap");
|
|
else
|
|
console_run("iw phy0 interface add wlan1 type managed");
|
|
}
|
|
|
|
return start_hostapd(ap, ssid, psk, ip);
|
|
}
|
|
|
|
int wifi_stop_hostapd(void)
|
|
{
|
|
char wifi_type[128];
|
|
|
|
console_run("killall hostapd");
|
|
console_run("killall dnsmasq");
|
|
exec_command("ifconfig -a | grep p2p0", wifi_type, 128);
|
|
if (strstr(wifi_type, "p2p0")) {
|
|
console_run("ifconfig p2p0 down");
|
|
} else {
|
|
console_run("ifconfig wlan1 down");
|
|
}
|
|
|
|
int time = 100;
|
|
while (time-- > 0 && !access("/var/run/hostapd", F_OK)) {
|
|
usleep(10 * 1000);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/prctl.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
|
|
typedef struct {
|
|
RK_SOFTAP_STATE_CALLBACK callback;
|
|
RK_SOFTAP_SERVER_TYPE server_type;
|
|
} RkSoftAp;
|
|
|
|
#define REQUEST_WIFI_LIST "/provision/wifiListInfo"
|
|
#define REQUEST_WIFI_SET_UP "/provision/wifiSetup"
|
|
#define REQUEST_IS_WIFI_CONNECTED "/provision/wifiState"
|
|
#define REQUEST_POST_CONNECT_RESULT "/provision/connectResult"
|
|
|
|
#define MSG_BUFF_LEN 8888
|
|
static char HTTP_RESPOSE_MESSAGE[] = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\nContent-Length:%d\r\n\r\n%s";
|
|
|
|
RkSoftAp m_softap;
|
|
|
|
#define SOCKET_PORT 8443
|
|
|
|
pthread_t m_thread;
|
|
bool m_isConnecting = false;
|
|
static int fd_server = -1;
|
|
static int m_port;
|
|
|
|
static RK_SOFTAP_STATE_CALLBACK m_cb = NULL;
|
|
static RK_SOFTAP_STATE m_state = RK_SOFTAP_STATE_IDLE;
|
|
|
|
static void sendState(RK_SOFTAP_STATE state, const char* data) {
|
|
if(m_cb != NULL)
|
|
m_cb(state, data);
|
|
}
|
|
|
|
static int initSocket(const unsigned int port)
|
|
{
|
|
int ret, fd_socket, val = 1;
|
|
struct sockaddr_in server_addr;
|
|
|
|
/* create a socket */
|
|
fd_socket = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (fd_socket < 0) {
|
|
printf("%s: create socket failed\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
/* set socket non-blocking */
|
|
//int flags;
|
|
//flags = fcntl(fd_socket, F_GETFL, 0);
|
|
//fcntl(sock, F_SETFL, flags | O_NONBLOCK);
|
|
|
|
ret = setsockopt(fd_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int));
|
|
if (ret < 0) {
|
|
printf("%s: setsockopt failed, ret: %d\n", __func__, ret);
|
|
return -2;
|
|
}
|
|
|
|
/* initialize server address */
|
|
bzero(&server_addr, sizeof(server_addr));
|
|
server_addr.sin_family = AF_INET;
|
|
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
server_addr.sin_port = htons(port);
|
|
|
|
/* bind with the local file */
|
|
ret = bind(fd_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
|
if (ret < 0) {
|
|
printf("%s: bind failed, ret: %d\n", __func__, ret);
|
|
close(fd_socket);
|
|
return -3;
|
|
}
|
|
|
|
/* listen */
|
|
ret = listen(fd_socket, 1);
|
|
if (ret < 0) {
|
|
printf("%s: listen failed, ret: %d\n", __func__, ret);
|
|
close(fd_socket);
|
|
return -4;
|
|
}
|
|
|
|
return fd_socket;
|
|
}
|
|
|
|
static int sendWifiList(const int fd, const char* buf)
|
|
{
|
|
char msg[MSG_BUFF_LEN] = {0};
|
|
char send_msg[MSG_BUFF_LEN] = {0};
|
|
size_t i, size = 0;
|
|
char *wifilist;
|
|
|
|
scan_retry:
|
|
printf("[RK] RK_wifi_scan ...\n");
|
|
RK_wifi_scan();
|
|
usleep(800000);
|
|
|
|
printf("[RK] RK_wifi_scan_r_sec ...\n");
|
|
wifilist = RK_wifi_scan_for_softap();
|
|
printf("[RK] RK_wifi_scan_r_sec end wifilist: %p\n", wifilist);
|
|
|
|
if (wifilist == NULL)
|
|
goto scan_retry;
|
|
if (wifilist && (strlen(wifilist) < 3)) {
|
|
free(wifilist);
|
|
goto scan_retry;
|
|
}
|
|
|
|
strcpy(msg, "{\"type\":\"WifiList\", \"content\":");
|
|
strcat(msg, wifilist);
|
|
strcat(msg, "}");
|
|
|
|
snprintf(send_msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, strlen(msg), msg);
|
|
|
|
printf("scan_r: %s\n", send_msg);
|
|
|
|
if (send(fd, send_msg, sizeof(send_msg), 0) < 0) {
|
|
return false;
|
|
}
|
|
|
|
free(wifilist);
|
|
return true;
|
|
}
|
|
|
|
static int isWifiConnected(const int fd, const char* buf)
|
|
{
|
|
char msg[MSG_BUFF_LEN] = {0};
|
|
bool isConn = 0;
|
|
|
|
RK_WIFI_INFO_Connection_s info;
|
|
|
|
if (!RK_wifi_running_getConnectionInfo(&info)) {
|
|
if (strncmp(info.wpa_state, "COMPLETED", 9) == 0)
|
|
isConn = 1;
|
|
}
|
|
|
|
memset(msg, 0, sizeof(msg));
|
|
snprintf(msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, 1, isConn ? "1" : "0");
|
|
|
|
m_isConnecting = false;
|
|
|
|
if (send(fd, msg, sizeof(msg), 0) < 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static char softap_ssid[128];
|
|
static char softap_psk[128];
|
|
|
|
static bool wifiSetup(const int fd, const char* buf)
|
|
{
|
|
char msg[MSG_BUFF_LEN] = {0};
|
|
char *str1, *str2;
|
|
char tmp[128];
|
|
int ret;
|
|
|
|
printf("enter %s\n", __func__);
|
|
|
|
memset(msg, 0, sizeof(msg));
|
|
snprintf(msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, 0, "");
|
|
if (send(fd, msg, sizeof(msg), 0) < 0) {
|
|
return false;
|
|
}
|
|
|
|
if (m_isConnecting == true)
|
|
return false;
|
|
|
|
memset(softap_ssid, 0, 128);
|
|
memset(softap_psk, 0, 128);
|
|
|
|
//{"ssid":"YHX","pwd":"rk123456789"}
|
|
str1 = strstr(buf, "\"ssid\"");
|
|
str2 = strstr(buf, "\"\,\"pwd\"");
|
|
strncpy(softap_ssid, str1 + 8, str2 - str1 - 8);
|
|
|
|
str1 = strstr(buf, "\"pwd\"");
|
|
str2 = strstr(str1, "\"\}");
|
|
strncpy(softap_psk, str1 + 7, str2 - str1 - 7);
|
|
|
|
printf("do connect ssid:\"%s\", psk:\"%s\", isConnecting:%d\n", softap_ssid, softap_psk, m_isConnecting);
|
|
|
|
sendState(RK_SOFTAP_STATE_CONNECTTING, NULL);
|
|
m_state = RK_SOFTAP_STATE_CONNECTTING;
|
|
|
|
system("wpa_cli -i wlan0 remove_network all");
|
|
|
|
ret = RK_wifi_connect(softap_ssid, softap_psk);
|
|
if (ret < 0) {
|
|
sendState(RK_SOFTAP_STATE_FAIL, NULL);
|
|
m_state = RK_SOFTAP_STATE_FAIL;
|
|
m_isConnecting = false;
|
|
return false;
|
|
}
|
|
|
|
m_isConnecting = true;
|
|
|
|
printf("exit %s\n", __func__);
|
|
return true;
|
|
}
|
|
|
|
static bool doConnectResult(const int fd, const char* buf)
|
|
{
|
|
char msg[MSG_BUFF_LEN] = {0};
|
|
char result[2];
|
|
char *str;
|
|
|
|
memset(msg, 0, sizeof(msg));
|
|
snprintf(msg, sizeof(msg), HTTP_RESPOSE_MESSAGE, 0, "");
|
|
if (send(fd, msg, sizeof(msg), 0) < 0) {
|
|
return false;
|
|
}
|
|
|
|
//{"result":"0"}
|
|
str = strstr(buf, "\"result\"");
|
|
strncpy(result, str + 10, 1);
|
|
printf("%s: %s", __func__, result);
|
|
|
|
if (strncmp(result, "1", 1) == 0) { // connect success, disable ap
|
|
sendState(RK_SOFTAP_STATE_SUCCESS, NULL);
|
|
m_state = RK_SOFTAP_STATE_SUCCESS;
|
|
wifi_stop_hostapd();
|
|
} else {
|
|
sendState(RK_SOFTAP_STATE_FAIL, NULL);
|
|
m_state = RK_SOFTAP_STATE_FAIL;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void handleRequest(const int fd_client)
|
|
{
|
|
size_t n;
|
|
char buf[2048] = {0};
|
|
|
|
n = recv(fd_client, buf, sizeof(buf), 0);
|
|
if (n <= 0) {
|
|
close(fd_client);
|
|
return;
|
|
}
|
|
buf[n] = '\0';
|
|
printf("TcpServer recv buf:\n[%s]\n", buf);
|
|
|
|
if (strstr(buf, REQUEST_WIFI_LIST)) {
|
|
sendWifiList(fd_client, buf);
|
|
} else if (strstr(buf, REQUEST_WIFI_SET_UP)) {
|
|
wifiSetup(fd_client, buf);
|
|
} else if (strstr(buf, REQUEST_IS_WIFI_CONNECTED)) {
|
|
isWifiConnected(fd_client, buf);
|
|
} else if (strstr(buf, REQUEST_POST_CONNECT_RESULT)) {
|
|
doConnectResult(fd_client, buf);
|
|
}
|
|
|
|
close(fd_client);
|
|
}
|
|
|
|
static void *threadAccept(void *arg)
|
|
{
|
|
int fd_client, port;
|
|
struct sockaddr_in addr_client;
|
|
socklen_t len_addr_client;
|
|
len_addr_client = sizeof(addr_client);
|
|
|
|
prctl(PR_SET_NAME, "threadAccept");
|
|
|
|
port = *(int *)arg;
|
|
|
|
printf("threadAccept port = %d\n", port);
|
|
fd_server = initSocket(port);
|
|
if (fd_server < 0) {
|
|
printf("TcpServer::threadAccept init tcp socket port %d fail. error:%d\n", port, fd_server);
|
|
goto end;
|
|
}
|
|
|
|
/* Accept connection all time */
|
|
while (1) {
|
|
printf("accept...\n");
|
|
fd_client = accept(fd_server, (struct sockaddr *)&addr_client, &len_addr_client);
|
|
printf("accept fd_client = %d\n", fd_client);
|
|
if (fd_client < 0)
|
|
goto end;
|
|
|
|
handleRequest(fd_client);
|
|
|
|
if (m_state == RK_SOFTAP_STATE_SUCCESS)
|
|
break;
|
|
}
|
|
|
|
end:
|
|
printf("Exit Tcp accept thread\n");
|
|
|
|
shutdown(fd_server, SHUT_RDWR);
|
|
close(fd_server);
|
|
fd_server = -1;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int startTcpServer(void)
|
|
{
|
|
int ret;
|
|
|
|
m_port = SOCKET_PORT;
|
|
m_state = RK_SOFTAP_STATE_IDLE;
|
|
printf("startTcpServer m_port = %d\n", m_port);
|
|
ret = pthread_create(&m_thread, NULL, threadAccept, &m_port);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int stopTcpServer()
|
|
{
|
|
if (m_thread <= 0)
|
|
return 0;
|
|
|
|
if (fd_server >= 0) {
|
|
shutdown(fd_server, SHUT_RDWR);
|
|
close(fd_server);
|
|
fd_server = -1;
|
|
}
|
|
|
|
if (0 != pthread_join(m_thread, NULL)) {
|
|
printf("stopTcpServer fail\n");
|
|
return -1;
|
|
}
|
|
|
|
m_thread = 0;
|
|
printf("stopTcpServer success\n");
|
|
return 0;
|
|
}
|
|
|
|
int RK_softap_start(char *name, RK_SOFTAP_SERVER_TYPE server_type)
|
|
{
|
|
RK_wifi_enable(1);
|
|
wifi_start_hostapd(name, NULL, NULL);
|
|
startTcpServer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int RK_softap_stop(void)
|
|
{
|
|
stopTcpServer();
|
|
wifi_stop_hostapd();
|
|
return 0;
|
|
}
|
|
|
|
|
|
int RK_softap_register_callback(RK_SOFTAP_STATE_CALLBACK cb) {
|
|
m_cb = cb;
|
|
return 0;
|
|
}
|
|
|
|
int RK_softap_getState(RK_SOFTAP_STATE *pState)
|
|
{
|
|
return m_state;
|
|
}
|