Created
April 26, 2018 03:02
-
-
Save KISSMonX/4281c739152da9c1910ad32a43ea8e22 to your computer and use it in GitHub Desktop.
wifimanager.c 集服示例
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************************************************************** | |
** File Name: wifimanager.cpp | |
** Author: MingH | |
** Date: 25/04/2017 | |
** Copyright: 2017 RoboSys, Incorporated. All Rights Reserved. | |
** Description: 新的配网方式, 采用上传 wifi 列表的方式 | |
******************************************************************************/ | |
#include <stdio.h> | |
#include <cJSON.h> | |
#include <string> | |
#include <fstream> | |
#include <streambuf> | |
#include "Wifimanager.h" | |
#include <iwlib.h> | |
#include <wireless.h> | |
#include <errno.h> | |
#include <stdlib.h> | |
#include "RobotManager.h" | |
#define LOG_TAG "wifimanager" | |
#include <log/log.h> | |
//=================================================================================================== | |
// @Description : 当前无线网络的信息 | |
// @param : skfd: connect to kernel net | |
// @param : ifname: interface name | |
// @param : info: write result to this struct | |
// @return : 0: success other: error code | |
// @Author: MingH | |
// NOTE: Master 模式的时候 iwconfig 无 Quality, 信号质量为 0 | |
//=================================================================================================== | |
static int getWirelessInfo(int skfd, char * ifname, struct wireless_info *info) | |
{ | |
struct iwreq wrq; | |
memset((char *) info, 0, sizeof(struct wireless_info)); | |
/* Get basic information */ | |
if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0) { | |
/* If no wireless name : no wireless extensions */ | |
/* But let's check if the interface exists at all */ | |
struct ifreq ifr; | |
strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | |
if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) { | |
return(-ENODEV); | |
} | |
else { | |
return(-ENOTSUP); | |
} | |
} | |
/* Get ranges */ | |
if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0) { | |
info->has_range = 1; | |
} | |
/* Get AP address */ | |
if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0) { | |
info->has_ap_addr = 1; | |
memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr)); | |
} | |
/* Get bit rate */ | |
if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0) { | |
info->has_bitrate = 1; | |
memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam)); | |
} | |
/* Get Power Management settings */ | |
wrq.u.power.flags = 0; | |
if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { | |
info->has_power = 1; | |
memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam)); | |
} | |
/* Get stats */ | |
if (iw_get_stats(skfd, ifname, &(info->stats), &info->range, info->has_range) >= 0) { | |
info->has_stats = 1; | |
} | |
#ifndef WE_ESSENTIAL | |
/* Get NickName */ | |
wrq.u.essid.pointer = (caddr_t) info->nickname; | |
wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; | |
wrq.u.essid.flags = 0; | |
if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0) { | |
if(wrq.u.data.length > 1) { | |
info->has_nickname = 1; | |
} | |
} | |
if ((info->has_range) && (info->range.we_version_compiled > 9)) { | |
/* Get Transmit Power */ | |
if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { | |
info->has_txpower = 1; | |
memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); | |
} | |
} | |
/* Get sensitivity */ | |
if (iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0) { | |
info->has_sens = 1; | |
memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam)); | |
} | |
if ((info->has_range) && (info->range.we_version_compiled > 10)) { | |
/* Get retry limit/lifetime */ | |
if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { | |
info->has_retry = 1; | |
memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam)); | |
} | |
} | |
/* Get RTS threshold */ | |
if (iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0) { | |
info->has_rts = 1; | |
memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam)); | |
} | |
/* Get fragmentation threshold */ | |
if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0) { | |
info->has_frag = 1; | |
memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam)); | |
} | |
#endif /* WE_ESSENTIAL */ | |
return WIFI_MANAGER_OPERATION_SUCCESS; | |
} | |
//=================================================================================================== | |
// @Description : 将当前的获取到的结果写入到自定义字段的结构体内 | |
// @param : info: current wireless info (all) | |
// @param : iwconfInfoResult: write result to this struct | |
// @return : 0: success other: error code | |
// @Author: MingH | |
//=================================================================================================== | |
static void setIwconfigInfo(struct wireless_info *info, iwconfigInfo_t *iwconfInfoResult) | |
{ | |
char buffer[128]; /* Temporary buffer */ | |
/* Set ESSID (extended network), if any */ | |
if(info->b.has_essid) { | |
if(info->b.essid_on) { | |
sprintf(iwconfInfoResult->ESSID, "%s", info->b.essid); | |
} | |
} | |
/* Set the current mode of operation */ | |
if(info->b.has_mode) { | |
sprintf(iwconfInfoResult->Mode, "%s", iw_operation_mode[info->b.mode]); | |
} | |
/* Set frequency / channel */ | |
if(info->b.has_freq) { | |
double freq = info->b.freq; /* Frequency/channel */ | |
int channel = -1; /* Converted to channel */ | |
/* Some drivers insist of returning channel instead of frequency. | |
* This fixes them up. Note that, driver should still return | |
* frequency, because other tools depend on it. */ | |
if(info->has_range && (freq < KILO)) { | |
channel = iw_channel_to_freq((int) freq, &freq, &info->range); | |
channel = channel; | |
} | |
iw_print_freq_value(buffer, sizeof(buffer), freq); | |
sprintf(iwconfInfoResult->Frequency, "%s", buffer); | |
} | |
/* Set the address of the current Access Point */ | |
if(info->has_ap_addr) { | |
/* Oups ! No Access Point in Ad-Hoc mode */ | |
if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC)) { | |
sprintf(iwconfInfoResult->AccessPoint, "%s", "IW_MODE_ADHOC"); | |
} | |
else { | |
sprintf(iwconfInfoResult->AccessPoint, "%s", iw_sawap_ntop(&info->ap_addr, buffer)); | |
} | |
} | |
// AP 模式没有信号质量, STA 模式有信号质量 | |
if(info->has_stats) { | |
// Quality=5/5 | |
iwconfInfoResult->Quality = info->stats.qual.qual; | |
} | |
} | |
//=================================================================================================== | |
// @Description : 逐个处理扫描到的无线网络事件类型 | |
// @param : ... | |
// @return : 0: success other: error code | |
// @Author: MingH | |
//=================================================================================================== | |
static inline void getScanningToken( | |
struct stream_descr * stream, /* Stream of events */ | |
struct iw_event * event, /* Extracted token */ | |
struct iwscan_state * state, | |
struct iw_range * iw_range, /* Range info */ | |
int has_range, | |
iwlistScanInfo_t *iwScanInfo) | |
{ | |
char buffer[128]; /* Temporary buffer */ | |
// 解析事件类型获取指定的数值 | |
switch (event->cmd) { | |
case SIOCGIWAP: | |
sprintf(iwScanInfo->Address, "%s", iw_saether_ntop(&event->u.ap_addr, buffer)); | |
break; | |
case SIOCGIWNWID: | |
// NOTE: 2017年5月4日: 目前的小盒还不支持获取 NWID | |
break; | |
case SIOCGIWFREQ: | |
{ | |
double freq; /* Frequency/channel */ | |
int channel = -1; /* Converted to channel */ | |
freq = iw_freq2float(&(event->u.freq)); | |
/* Convert to channel if possible */ | |
if (has_range) { | |
channel = iw_freq_to_channel(freq, iw_range); | |
} | |
iw_print_freq_value(buffer, sizeof(buffer), freq); | |
sprintf(iwScanInfo->Frequency, "%s", buffer); | |
if (channel >= 0) { | |
iwScanInfo->Channel = channel; | |
} | |
} | |
break; | |
case SIOCGIWMODE: | |
// TODO: 暂不需要, 直接 break | |
break; | |
case SIOCGIWNAME: | |
// TODO: 暂不需要, 直接 break | |
break; | |
case SIOCGIWESSID: | |
{ | |
char essid[IW_ESSID_MAX_SIZE + 1]; | |
memset(essid, '\0', sizeof(essid)); | |
if ((event->u.essid.pointer) && (event->u.essid.length)) { | |
memcpy(essid, event->u.essid.pointer, event->u.essid.length); | |
} | |
if (event->u.essid.flags) { | |
/* Does it have an ESSID index ? */ | |
// TODO: 有一种单一频率路由可以设置两个 SSID | |
if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) { | |
sprintf(iwScanInfo->ESSID, "%s [%d]", essid, (event->u.essid.flags & IW_ENCODE_INDEX)); | |
} | |
else { | |
sprintf(iwScanInfo->ESSID, "%s", essid); | |
} | |
} | |
else { | |
ALOGW("SSID 被隐藏或者关闭\n"); | |
} | |
} | |
break; | |
case SIOCGIWENCODE: | |
{ | |
unsigned char key[IW_ENCODING_TOKEN_MAX]; | |
if(event->u.data.pointer) { | |
memcpy(key, event->u.data.pointer, event->u.data.length); | |
} | |
else { | |
event->u.data.flags |= IW_ENCODE_NOKEY; | |
} | |
if (event->u.data.flags & IW_ENCODE_DISABLED) { | |
sprintf(iwScanInfo->Encryption, "off"); | |
} | |
else { | |
/* Display the key */ | |
iw_print_key(buffer, sizeof(buffer), key, event->u.data.length, event->u.data.flags); | |
sprintf(iwScanInfo->Encryption, "%s", buffer); | |
/* Other info... */ | |
if((event->u.data.flags & IW_ENCODE_INDEX) > 1) { | |
ALOGD(" [%d]", event->u.data.flags & IW_ENCODE_INDEX); | |
} | |
if(event->u.data.flags & IW_ENCODE_RESTRICTED) { | |
ALOGD(" Security mode:restricted"); | |
} | |
if(event->u.data.flags & IW_ENCODE_OPEN) { | |
ALOGD(" Security mode:open"); | |
} | |
} | |
} | |
break; | |
case SIOCGIWRATE: | |
// TODO: 暂不需要, 直接 break | |
break; | |
case SIOCGIWMODUL: | |
// TODO: 暂不需要, 直接 break | |
break; | |
case IWEVQUAL: | |
// 最大值是 5 | |
iwScanInfo->Quality = event->u.qual.qual; | |
break; | |
#ifndef WE_ESSENTIAL | |
case IWEVGENIE: | |
// TODO: 暂不需要, 直接 break | |
break; | |
#endif /* WE_ESSENTIAL */ | |
default: | |
ALOGE("(Unknown Wireless Token 0x%04X)\n", event->cmd); | |
} /* switch(event->cmd) */ | |
} | |
//=================================================================================================== | |
// @Description : 逐个处理扫描到的无线网络事件类型, 拼接成自己想要的 | |
// @param : skfd: connect to kernel net | |
// @param : ifname: interface name | |
// @param : info: write result to this struct | |
// @param : listCnt: 扫描的结果数量 | |
// @param : listMax: 最大扫描结果数量 | |
// @return : 0: success other: error code | |
// @Author: MingH | |
//=================================================================================================== | |
static int getScanningInfo(int skfd, char *ifname, iwlistScanInfo_t *iwScanList, int *listCnt, int listMax) | |
{ | |
struct iwreq wrq; | |
int scanflags = 0; /* Flags for scan */ | |
unsigned char * buffer = NULL; /* Results */ | |
int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ | |
struct iw_range range; | |
int has_range; | |
struct timeval tv; /* Select timeout */ | |
int timeout = 15000000; /* 15s */ | |
if (!iwScanList || !listCnt) { | |
ALOGE("[ERROR]getScanningInfo: param invalid. iwScanList = %p, listCnt = %p\n", iwScanList, listCnt); | |
return WIFI_MANAGER_PARAMETER_INVALID; | |
} | |
/* Get range stuff */ | |
has_range = (iw_get_range_info(skfd, ifname, &range) >= 0); | |
/* Check if the interface could support scanning. */ | |
if((!has_range) || (range.we_version_compiled < 14)) { | |
ALOGE("%-8.16s Interface doesn't support scanning.\n", ifname); | |
return WIFI_MANAGER_GET_RANGE_ERROR; | |
} | |
/* Init timeout value -> 250ms between set and first get */ | |
tv.tv_sec = 0; | |
tv.tv_usec = 250000; | |
wrq.u.data.pointer = NULL; | |
wrq.u.data.flags = 0; | |
wrq.u.data.length = 0; | |
/* Initiate Scanning */ | |
if (iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) { | |
if((errno != EPERM) || (scanflags != 0)) { | |
fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n", ifname, strerror(errno)); | |
return WIFI_MANAGER_GET_WIFI_INFO_FAILED; | |
} | |
tv.tv_usec = 0; | |
} | |
timeout -= tv.tv_usec; | |
/* Forever */ | |
while(1) { | |
fd_set rfds; /* File descriptors for select */ | |
int last_fd; /* Last fd */ | |
int ret; | |
/* Guess what ? We must re-generate rfds each time */ | |
FD_ZERO(&rfds); | |
last_fd = -1; | |
/* In here, add the rtnetlink fd in the list */ | |
/* Wait until something happens */ | |
ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); | |
/* Check if there was an error */ | |
if (ret < 0) { | |
if(errno == EAGAIN || errno == EINTR) { | |
continue; | |
} | |
ALOGE("[ERROR] select() Unhandled signal - exiting...\n"); | |
return WIFI_MANAGER_SCAN_SELECT_FAILED; | |
} | |
/* Check if there was a timeout */ | |
if (ret == 0) { | |
unsigned char * newbuf; | |
REALLOC: | |
/* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ | |
newbuf = (unsigned char *)realloc(buffer, buflen); | |
if (newbuf == NULL) { | |
if (buffer) { | |
free(buffer); | |
} | |
ALOGE("%s: Allocation failed\n", __FUNCTION__); | |
return WIFI_MANAGER_ALLOC_MEMORY_FAILED; | |
} | |
buffer = newbuf; | |
/* Try to read the results */ | |
wrq.u.data.pointer = buffer; | |
wrq.u.data.flags = 0; | |
wrq.u.data.length = buflen; | |
if (iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) { | |
/* Check if buffer was too small (WE-17 only) */ | |
if ((errno == E2BIG) && (range.we_version_compiled > 16)) { | |
/* Some driver may return very large scan results, either | |
* because there are many cells, or because they have many | |
* large elements in cells (like IWEVCUSTOM). Most will | |
* only need the regular sized buffer. We now use a dynamic | |
* allocation of the buffer to satisfy everybody. Of course, | |
* as we don't know in advance the size of the array, we try | |
* various increasing sizes. Jean II */ | |
/* Check if the driver gave us any hints. */ | |
if(wrq.u.data.length > buflen) { | |
buflen = wrq.u.data.length; | |
} | |
else { | |
buflen *= 2; | |
} | |
/* Try again */ | |
goto REALLOC; | |
} | |
/* Check if results not available yet */ | |
if (errno == EAGAIN) { | |
/* Restart timer for only 100ms*/ | |
tv.tv_sec = 0; | |
tv.tv_usec = 100000; | |
timeout -= tv.tv_usec; | |
if (timeout > 0) { | |
continue; /* Try again later */ | |
} | |
} | |
/* Bad error */ | |
free(buffer); | |
ALOGE("%-8.16s Failed to read scan data : %s\n\n", ifname, strerror(errno)); | |
return WIFI_MANAGER_READ_SCANDATA_FAILED; | |
} | |
else { | |
/* We have the results, go to process them */ | |
break; | |
} | |
} | |
/* In here, check if event and event type | |
* if scan event, read results. All errors bad & no reset timeout */ | |
} | |
if (wrq.u.data.length) { | |
struct iw_event iwe; | |
struct stream_descr stream; | |
struct iwscan_state state = { .ap_num = 1, .val_index = 0 }; | |
int ret; | |
int count = 0; | |
iwlistScanInfo_t tempScanInfo; | |
memset(&tempScanInfo, 0, sizeof(iwlistScanInfo_t)); | |
iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); | |
do { | |
// 读取: ssid, address, freq/channel, Encryption, quality | |
ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); | |
if (ret > 0) { | |
getScanningToken(&stream, &iwe, &state, &range, has_range, &tempScanInfo); | |
} | |
// 当前的 wifi 所有需要的字段都要获取完整才能进行下一个 | |
if ((strlen(tempScanInfo.Encryption) > 0) && (strlen(tempScanInfo.Address) > 0) | |
&& (strlen(tempScanInfo.Frequency) > 0) && (strlen(tempScanInfo.ESSID) > 0) | |
&& (tempScanInfo.Quality >= 1) && (tempScanInfo.Channel >= 1)) | |
{ | |
memcpy(&iwScanList[count], &tempScanInfo, sizeof(iwlistScanInfo_t)); | |
memset(&tempScanInfo, 0, sizeof(iwlistScanInfo_t)); | |
if (count++ >= listMax) { | |
*listCnt = listMax; | |
break; | |
} | |
*listCnt = count; | |
} | |
} while (ret > 0); | |
} | |
else { | |
ALOGW("%-8.16s 没有扫描到可用 WIFI.\n", ifname); | |
} | |
free(buffer); | |
return WIFI_MANAGER_OPERATION_SUCCESS; | |
} | |
//=================================================================================================== | |
// @Description : 当前无线网络的统计及配置信息 | |
// @param : skfd: connect to kernel net | |
// @param : ifname: interface name | |
// @param : iwconfInfoResult: write result to this struct | |
// @return : 0: success other: error code | |
// @Author: MingH | |
//=================================================================================================== | |
static int getIWconfigInfo(int skfd, char *ifname, iwconfigInfo_t *iwconfInfoResult) | |
{ | |
struct wireless_info info; | |
int rc; | |
if (!ifname || !iwconfInfoResult) { | |
ALOGE("ERROR: getIwconfigInfo param invalid. ifname = %p, iwconfInfoResult = %p\n", | |
ifname, iwconfInfoResult); | |
return WIFI_MANAGER_PARAMETER_INVALID; | |
} | |
rc = getWirelessInfo(skfd, ifname, &info); | |
if (!rc) { | |
setIwconfigInfo(&info, iwconfInfoResult); | |
} | |
else { | |
ALOGE("[ERROR] getWirelessInfo: getWirelessInfo failed.\n"); | |
return WIFI_MANAGER_GET_WIFI_INFO_FAILED; | |
} | |
RobotManager *pRobotManager = NULL; | |
RobotManager_GetRobotManager(&pRobotManager); | |
RobotInfo *pRobotInfo = RobotManager_GetRobotInfo(pRobotManager); | |
sprintf(iwconfInfoResult->SN, "%s", pRobotInfo->sn); | |
return WIFI_MANAGER_OPERATION_SUCCESS; | |
} | |
//=================================================================================================== | |
// @Description : 将结果序列化成 json | |
// @param : dest: 要写入的buf | |
// @param : ifname: interface name | |
// @param : iwconfInfoResult: iwconfig 的当前连接信息 | |
// @param : iwScanList: 扫描到的结果 | |
// @param : resultCount: 结果数量 | |
// @return : 0: success other: error code | |
// @Author: MingH | |
// NOTE: Master 模式的时候 iwconfig 无 Quality, 信号质量为 0 | |
//=================================================================================================== | |
static int createResultJSON(char *dest, iwconfigInfo_t *iwconfInfoResult, iwlistScanInfo_t *iwScanList, int resultCount) | |
{ | |
cJSON *pJSONRoot = NULL; | |
cJSON *pJSONArray = NULL; | |
if (!dest || !iwconfInfoResult || !iwScanList) { | |
ALOGE("[ERROR] createResultJSON param invalid. dest: %p, iwScanList: %p\n", dest, iwScanList); | |
return WIFI_MANAGER_PARAMETER_INVALID; | |
} | |
// 当前连接信息 | |
pJSONRoot = cJSON_CreateObject(); | |
cJSON_AddStringToObject(pJSONRoot, "SN", iwconfInfoResult->SN); | |
cJSON_AddStringToObject(pJSONRoot, "ESSID", iwconfInfoResult->ESSID); | |
cJSON_AddStringToObject(pJSONRoot, "AccessPoint", iwconfInfoResult->AccessPoint); | |
cJSON_AddStringToObject(pJSONRoot, "Mode", iwconfInfoResult->Mode); | |
cJSON_AddStringToObject(pJSONRoot, "Frequency", iwconfInfoResult->Frequency); | |
// NOTE: 连接信号质量, 仅 Managed 模式 | |
if (!strcmp(iwconfInfoResult->Mode, "Managed")) { | |
cJSON_AddNumberToObject(pJSONRoot, "Quality", iwconfInfoResult->Quality); | |
} | |
// 扫描到的 wifi 列表 | |
pJSONArray = cJSON_CreateArray(); | |
cJSON_AddItemToObject(pJSONRoot, "Cells", pJSONArray); | |
for (int i = 0; i < resultCount; i++) { | |
cJSON *pArrayItem = cJSON_CreateObject(); | |
cJSON_AddItemToArray(pJSONArray, pArrayItem); | |
cJSON_AddStringToObject(pArrayItem, "Address", iwScanList[i].Address); | |
cJSON_AddStringToObject(pArrayItem, "ESSID", iwScanList[i].ESSID); | |
cJSON_AddStringToObject(pArrayItem, "Frequency", iwScanList[i].Frequency); | |
cJSON_AddNumberToObject(pArrayItem, "Channel", iwScanList[i].Channel); | |
cJSON_AddNumberToObject(pArrayItem, "Quality", iwScanList[i].Quality); | |
cJSON_AddStringToObject(pArrayItem, "Encryption", iwScanList[i].Encryption); | |
cJSON_AddBoolToObject(pArrayItem, "Registered", iwScanList[i].Registered); | |
// NOTE: 加密了才会有密码, 这样设置的时候会将已经存在的密码覆盖 | |
if (iwScanList[i].Registered) { | |
cJSON_AddStringToObject(pArrayItem, "Password", iwScanList[i].Password); | |
} | |
} | |
// 不格式化输出结果, 节省空间 | |
char *result = cJSON_PrintUnformatted(pJSONRoot); | |
// char *result = cJSON_Print(pJSONRoot); | |
strcpy(dest, result); | |
free(result); | |
cJSON_Delete(pJSONRoot); | |
return WIFI_MANAGER_OPERATION_SUCCESS; | |
} | |
//=================================================================================================== | |
// @Description : 将结果序列化成 json | |
// @param : resultJSON: 要写入的buf | |
// @param : ifname: interface name, default: wlan0 | |
// @return : 0: success other: error code | |
// @Author: MingH | |
// NOTE: Master 模式的时候 iwconfig 无 Quality, 信号质量为 0 | |
//=================================================================================================== | |
int getWifiList(char *resultJSON, char *ifname) | |
{ | |
int skfd = 0; | |
static iwconfigInfo_t iwconfInfoResult; // 当前连接的信息 | |
int listCount = 0; // 读取到的无线网络数量, 最大 SCANNING_LIST_MAX_ITEM | |
FILE *tmpFd = NULL; | |
char *wpaContent = NULL; | |
// 分配空间给扫描到的无线网络 | |
iwlistScanInfo_t *scanningListBuffer = (iwlistScanInfo_t *)malloc(SCANNING_LIST_MAX_ITEM * sizeof(iwlistScanInfo_t)); | |
if (!scanningListBuffer) { | |
ALOGE("[ERROR] malloc scanningListBuffer failed.\n"); | |
return WIFI_MANAGER_ALLOC_MEMORY_FAILED; | |
} | |
memset(&iwconfInfoResult, 0, sizeof(iwconfigInfo_t)); | |
memset(scanningListBuffer, 0, SCANNING_LIST_MAX_ITEM * sizeof(scanningListBuffer)); | |
// 创建 socket 与内核通信 | |
if ((skfd = iw_sockets_open()) < 0) { | |
ALOGE("[ERROR]getWifiList: iw_sockets_open failed: %s\n", strerror(errno)); | |
free(scanningListBuffer); | |
return WIFI_MANAGER_SOCKETS_OPEN_FAILED; | |
} | |
// 获取当前的连接信息 | |
int ret = getIWconfigInfo(skfd, ifname, &iwconfInfoResult); | |
if (ret < 0) { | |
ALOGE("[ERROR] getIWconfigInfo: get iwconfig information failed.\n"); | |
free(scanningListBuffer); | |
iw_sockets_close(skfd); | |
return ret; | |
} | |
// 获取扫描到的无线网络 | |
ret = getScanningInfo(skfd, ifname, scanningListBuffer, &listCount, SCANNING_LIST_MAX_ITEM); | |
if (ret < 0) { | |
ALOGE("[ERROR] getIwlistInfo failed.\n"); | |
free(scanningListBuffer); | |
iw_sockets_close(skfd); | |
return ret; | |
} | |
// 检查 wpa 文件是否存在 | |
if (0 == access(WIFI_SAVED_FILE, (F_OK | R_OK | W_OK))) { | |
// 读取 wpa 文件内容进行分析 | |
tmpFd = fopen(WIFI_SAVED_FILE, "r+"); | |
if (NULL == tmpFd) { | |
ALOGE("[ERROR] read %s file failed.\n", WIFI_SAVED_FILE); | |
free(scanningListBuffer); | |
return WIFI_MANAGER_SOCKETS_OPEN_FAILED; | |
} | |
fseek(tmpFd, 0, SEEK_END); | |
long fsize = ftell(tmpFd); | |
fseek(tmpFd, 0, SEEK_SET); //same as rewind(f); | |
wpaContent = (char *)malloc(fsize + 1); | |
if (!wpaContent) { | |
ALOGE("[ERROR]malloc wpa_supplicant.conf file wpaContent buffer failed.\n"); | |
free(scanningListBuffer); | |
iw_sockets_close(skfd); | |
fclose(tmpFd); | |
return WIFI_MANAGER_ALLOC_MEMORY_FAILED; | |
} | |
memset(wpaContent, 0, fsize + 1); | |
fread(wpaContent, sizeof(char), fsize, tmpFd); | |
char *wpaContentTemp = wpaContent; | |
bool isRegistered = false; | |
// 遍历 SSID 并获取密码 | |
for (int i = 0; i < listCount; i++) { | |
isRegistered = false; | |
char *firstPos = strstr(wpaContentTemp, scanningListBuffer[i].ESSID); | |
// 存在 WIFI 名称 | |
while (firstPos) { | |
char ssid[64] = {0}; | |
for (int j = 0; *firstPos != '\"'; j++, firstPos++) { | |
ssid[j] = *firstPos; | |
} | |
// 匹配 SSID, 注意子串 | |
if (!strcmp(ssid, scanningListBuffer[i].ESSID)) { | |
isRegistered = true; | |
char *psk = strstr(firstPos, "psk="); | |
// 提取 psk 密码 | |
if (psk) { | |
psk = psk + 5; | |
for (int j = 0; *psk != '\"'; j++, psk++) { | |
scanningListBuffer[i].Password[j] = *psk; | |
} | |
} | |
break; | |
} | |
else { | |
// NOTE: 不符合就在当前位置偏移一些, 继续往下找. | |
wpaContentTemp = wpaContentTemp + 6; | |
firstPos = strstr(wpaContentTemp, scanningListBuffer[i].ESSID); | |
} | |
memset(ssid, 0, sizeof(ssid)); | |
} | |
scanningListBuffer[i].Registered = isRegistered; | |
} | |
fclose(tmpFd); | |
free(wpaContent); | |
} | |
else { | |
// 没有 wpa 文件默认所有的扫描结果 registered 都为 false | |
for (int i = 0; i < listCount; i++) { | |
scanningListBuffer[i].Registered = false; | |
} | |
} | |
ret = createResultJSON(resultJSON, &iwconfInfoResult, scanningListBuffer, listCount); | |
if (ret < 0) { | |
ALOGE("[ERROR] createResultJSON: create Scanning Json failed.\n"); | |
free(scanningListBuffer); | |
iw_sockets_close(skfd); | |
return ret; | |
} | |
free(scanningListBuffer); | |
iw_sockets_close(skfd); | |
return WIFI_MANAGER_OPERATION_SUCCESS; | |
} | |
//=================================================================================================== | |
// @Description : 获取类似 iwconfig 的信息 | |
// @param : iwconfig: 要写入的 struct | |
// @param : ifname: interface name, default: wlan0 | |
// @return : 0: success other: error code | |
// @Author: MingH | |
// NOTE: Master 模式的时候 iwconfig 无 Quality, 信号质量为 0 | |
//=================================================================================================== | |
int getIwconfig(char *ifname, iwconfigInfo_t * iwconfig) | |
{ | |
int skfd = 0; | |
struct wireless_info info; | |
int rc; | |
if (!ifname || !iwconfig) { | |
ALOGE("ERROR: getIwconfig param invalid. ifname = %p, iwconfig = %p\n", | |
ifname, iwconfig); | |
return WIFI_MANAGER_PARAMETER_INVALID; | |
} | |
// 创建 socket 与内核通信 | |
if ((skfd = iw_sockets_open()) < 0) { | |
ALOGE("[ERROR]getIwconfig: iw_sockets_open failed: %s\n", strerror(errno)); | |
return WIFI_MANAGER_SOCKETS_OPEN_FAILED; | |
} | |
rc = getWirelessInfo(skfd, ifname, &info); | |
if (!rc) { | |
setIwconfigInfo(&info, iwconfig); | |
} | |
else { | |
ALOGE("[ERROR] getIwconfig: getWirelessInfo failed.\n"); | |
iw_sockets_close(skfd); | |
return WIFI_MANAGER_GET_WIFI_INFO_FAILED; | |
} | |
iw_sockets_close(skfd); | |
return WIFI_MANAGER_OPERATION_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment