接着上一篇一开始提出的问题,如何获取没有连接成功的客户端信息,主要指MAC地址,其他的信息未必拿得到。
WifiDevice类是指望不上了,因为它只代表连接成功的客户端。
不过从前面的分析可以看出来,连接成功的客户端信息,全部来自于hostapd发送的消息中携带了我们所需的信息。
找找消息是从哪发来的?ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, int authorized)
中发送的。
if (authorized) {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s", buf);
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_CONNECTED "%s", buf);
sta->flags |= WLAN_STA_AUTHORIZED;
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_DISCONNECTED "%s", buf);
sta->flags &= ~WLAN_STA_AUTHORIZED;
}
就这个里,什么时候发送connect和disconnect已经很清楚了,不过这里是连接成功的,连接失败的走不到这里,看看这段代码的上面。
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
return;这个双非,真让人头晕有木有,不过意思就是判断当前这个sta有没有通过鉴权。没有通过的,就一律return,不让往后面走了。我们可以
在这个给那些没有通过鉴权的sta放放水,把消息传递下去吧。这块修改的办法很多,我这里给sta_info这个结构体增加了一个成员report_flags.
struct sta_info {
struct sta_info *next; /* next entry in sta list */
struct sta_info *hnext; /* next entry in hash table list */
u8 addr[6];
u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
u32 flags; /* Bitfield of WLAN_STA_* */
u16 capability;
u16 listen_interval; /* or beacon_int for APs */
u8 supported_rates[WLAN_SUPP_RATES_MAX];
int supported_rates_len;
u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
........
u32 session_timeout; /* valid only if session_timeout_set == 1 */
u32 report_flags; /**/
}; 增加这个flag后,在以上的函数中增加一个新的消息:"
AP-STA-REPORT"
if(!(sta->flags & WLAN_STA_AUTHORIZED)&& !sta->report_flags){
wpa_printf(MSG_DEBUG, "report hal there is a sta associate");
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
wpa_msg(hapd->msg_ctx, MSG_INFO, "AP-STA-REPORT " "%s", buf);
sta->report_flags = 1;
}
if(!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)){
return;
}
如果此sta是没有通过鉴权的,先发送一个report消息给上层,然后就该干啥干啥,很简单。至于上层对于消息的处理,
就仿照其他消息一样处理了。一路消息都是透传的,么有什么处理,一直到Tethering.java中的
interfaceMessageRecevied(String message)。
public void interfaceMessageRecevied(String message) {
// if softap extension feature not enabled, do nothing
if (!mContext.getResources().getBoolean(com.android.internal.R.bool.config_softap_extention)) {
return;
}
if (DBG) Log.d(TAG, "interfaceMessageRecevied: message=" + message);
try {
WifiDevice device = new WifiDevice(message);
......
message是在WifiDevice中分解的,先在WifiDevice中修改一下吧:
public WifiDevice(String dataString) throws IllegalArgumentException {
String[] tokens = dataString.split(" ");
if (tokens.length < 2) {
throw new IllegalArgumentException();
}
if (tokens[0].indexOf(AP_STA_CONNECTED_STR) != -1) {
deviceState = CONNECTED;
} else if (tokens[0].indexOf(AP_STA_DISCONNECTED_STR) != -1) {
deviceState = DISCONNECTED;
}else if (tokens[0].indexOf(AP_STA_REPORT_STR) != -1) {
deviceState = BLACKLISTED;
} else {
throw new IllegalArgumentException();
}
deviceAddress = tokens[1];
}
把携带“AP_STA_REPORT_STR”字段消息的device定义为BLACKLISTED,这个是本来类中定义的,但是没有用到,我暂用一下,
其实自己定义一个其他的更好。interfaceMessageRecevied()中再增加一个判断,将所有blacklist的设备存储到新定义的一个hashMap中。
}else if(device.deviceState == WifiDevice.BLACKLISTED) {
Log.d(TAG, "@@@@ put device to asscoation MAP,mac= " + device.deviceAddress);
mAssocDeviceMap.put(device.deviceAddress, device);
}
新增一个接口public List getTetherAsscoationStaAddr() ,用于查询关联过改热点,但是没有连接成功的sta。
public List getTetherAsscoationStaAddr() {
Iterator it;
List TetherAsscoationStaList = new ArrayList();
if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_softap_extention)) {
it = mAssocDeviceMap.keySet().iterator();
while(it.hasNext()) {
String key = (String)it.next();
WifiDevice device = (WifiDevice)mAssocDeviceMap.get(key);
Log.d(TAG, "getTetherAsscoationStaAddr: addr=" + key + " name=" + device.deviceName);
TetherAsscoationStaList.add(device);
}
}
return TetherAsscoationStaList;
}
当然,如果是供上层调用,ConnectivityManager和
ConnectivitySevic以及
I
ConnectivityManager.aidl中都要同步增加接口。