2015-12-28 08:13:02 +01:00
// WiFi Event Monitor
# include "module.h"
# include "lauxlib.h"
# include "platform.h"
# include "c_string.h"
# include "c_stdlib.h"
# include "c_types.h"
# include "user_interface.h"
# include "smart.h"
# include "smartconfig.h"
# include "user_config.h"
# include "wifi_common.h"
# if defined(LUA_USE_MODULES_WIFI)
# ifdef WIFI_SDK_EVENT_MONITOR_ENABLE
//variables for wifi event monitor
static task_handle_t wifi_event_monitor_task_id ; //variable to hold task id for task handler(process_event_queue)
static int wifi_event_cb_ref [ EVENT_MAX + 1 ] = { [ 0 . . . EVENT_MAX ] = LUA_NOREF } ; //holds references to registered Lua callbacks
2018-01-10 21:24:41 +01:00
# ifdef LUA_USE_MODULES_WIFI_MONITOR
static int ( * hook_fn ) ( System_Event_t * ) ;
void wifi_event_monitor_register_hook ( int ( * fn ) ( System_Event_t * ) ) {
hook_fn = fn ;
}
# endif
2015-12-28 08:13:02 +01:00
// wifi.eventmon.register()
2017-05-21 16:18:56 +02:00
int wifi_event_monitor_register ( lua_State * L )
2015-12-28 08:13:02 +01:00
{
uint8 id = ( uint8 ) luaL_checknumber ( L , 1 ) ;
if ( id > EVENT_MAX ) //Check if user is trying to register a callback for a valid event.
{
return luaL_error ( L , " valid wifi events:0-%d " , EVENT_MAX ) ;
}
else
{
if ( lua_type ( L , 2 ) = = LUA_TFUNCTION | | lua_type ( L , 2 ) = = LUA_TLIGHTFUNCTION ) //check if 2nd item on stack is a function
{
lua_pushvalue ( L , 2 ) ; // copy argument (func) to the top of stack
register_lua_cb ( L , & wifi_event_cb_ref [ id ] ) ; //pop function from top of the stack, register it in the LUA_REGISTRY, then assign lua_ref to wifi_event_cb_ref[id]
}
else // unregister user's callback
{
unregister_lua_cb ( L , & wifi_event_cb_ref [ id ] ) ;
}
return 0 ;
}
}
2018-05-20 09:46:04 +02:00
static sint32_t event_queue_ref = LUA_NOREF ;
2015-12-28 08:13:02 +01:00
static void wifi_event_monitor_handle_event_cb ( System_Event_t * evt )
{
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " was called (Event:%d) " , evt - > event ) ;
2015-12-28 08:13:02 +01:00
2018-01-10 21:24:41 +01:00
# ifdef LUA_USE_MODULES_WIFI_MONITOR
if ( hook_fn & & hook_fn ( evt ) ) {
return ;
}
# endif
2015-12-28 08:13:02 +01:00
if ( ( wifi_event_cb_ref [ evt - > event ] ! = LUA_NOREF ) | | ( ( wifi_event_cb_ref [ EVENT_MAX ] ! = LUA_NOREF ) & &
! ( evt - > event = = EVENT_STAMODE_CONNECTED | | evt - > event = = EVENT_STAMODE_DISCONNECTED | |
2017-05-15 09:05:22 +02:00
evt - > event = = EVENT_STAMODE_AUTHMODE_CHANGE | | evt - > event = = EVENT_STAMODE_GOT_IP | |
evt - > event = = EVENT_STAMODE_DHCP_TIMEOUT | | evt - > event = = EVENT_SOFTAPMODE_STACONNECTED | |
evt - > event = = EVENT_SOFTAPMODE_STADISCONNECTED | | evt - > event = = EVENT_SOFTAPMODE_PROBEREQRECVED | |
evt - > event = = EVENT_OPMODE_CHANGED ) ) )
2015-12-28 08:13:02 +01:00
{
2018-05-20 09:46:04 +02:00
lua_State * L = lua_getstate ( ) ;
if ( event_queue_ref = = LUA_NOREF ) { //if event queue has not been created, create it now
lua_newtable ( L ) ;
event_queue_ref = luaL_ref ( L , LUA_REGISTRYINDEX ) ;
2015-12-28 08:13:02 +01:00
}
2018-05-20 09:46:04 +02:00
lua_rawgeti ( L , LUA_REGISTRYINDEX , event_queue_ref ) ;
2015-12-28 08:13:02 +01:00
2018-05-20 09:46:04 +02:00
System_Event_t * evt_tmp = lua_newuserdata ( L , sizeof ( System_Event_t ) ) ;
c_memcpy ( evt_tmp , evt , sizeof ( System_Event_t ) ) ; //copy event data to new struct
sint32_t evt_ud_ref = luaL_ref ( L , LUA_REGISTRYINDEX ) ;
size_t queue_len = lua_objlen ( L , - 1 ) ;
//add event to queue
lua_pushnumber ( L , queue_len + 1 ) ;
lua_pushnumber ( L , evt_ud_ref ) ;
lua_rawset ( L , - 3 ) ;
if ( queue_len = = 0 ) { //if queue was empty, post task
EVENT_DBG ( " Posting task " ) ;
2015-12-28 08:13:02 +01:00
task_post_low ( wifi_event_monitor_task_id , false ) ;
}
2018-05-20 09:46:04 +02:00
else {
EVENT_DBG ( " Appending queue, items in queue: %d " , lua_objlen ( L , - 1 ) ) ;
2015-12-28 08:13:02 +01:00
}
2018-05-20 09:46:04 +02:00
lua_pop ( L , 1 ) ;
} //else{} //there are no callbacks registered, so the event can't be processed
2015-12-28 08:13:02 +01:00
}
static void wifi_event_monitor_process_event_queue ( task_param_t param , uint8 priority )
{
lua_State * L = lua_getstate ( ) ;
2018-05-20 09:46:04 +02:00
lua_rawgeti ( L , LUA_REGISTRYINDEX , event_queue_ref ) ;
int index = 1 ;
lua_rawgeti ( L , 1 , index ) ;
sint32 event_ref = lua_tonumber ( L , - 1 ) ;
lua_pop ( L , 1 ) ;
//remove event reference from queue
int queue_length = lua_objlen ( L , 1 ) ;
lua_rawgeti ( L , 1 , index ) ;
for ( ; index < queue_length ; index + + ) {
lua_rawgeti ( L , 1 , index + 1 ) ;
lua_rawseti ( L , 1 , index ) ;
}
lua_pushnil ( L ) ;
lua_rawseti ( L , 1 , queue_length ) ;
lua_pop ( L , 1 ) ;
2015-12-28 08:13:02 +01:00
2018-05-20 09:46:04 +02:00
lua_rawgeti ( L , LUA_REGISTRYINDEX , event_ref ) ; //get event userdata from registry
System_Event_t * evt = lua_touserdata ( L , - 1 ) ;
lua_pop ( L , 1 ) ; //pop userdata from stack
queue_length = lua_objlen ( L , 1 ) ;
if ( queue_length > 0 ) {
task_post_low ( wifi_event_monitor_task_id , false ) ; //post task to process next item in queue
EVENT_DBG ( " %d events left in queue, posting task " , queue_length ) ;
}
lua_pop ( L , 1 ) ; //pop event queue from stack
2015-12-28 08:13:02 +01:00
if ( wifi_event_cb_ref [ evt - > event ] ! = LUA_NOREF ) // check if user has registered a callback
{
lua_rawgeti ( L , LUA_REGISTRYINDEX , wifi_event_cb_ref [ evt - > event ] ) ; //get user's callback
}
else if ( ( wifi_event_cb_ref [ EVENT_MAX ] ! = LUA_NOREF ) & &
! ( evt - > event = = EVENT_STAMODE_CONNECTED | | evt - > event = = EVENT_STAMODE_DISCONNECTED | |
evt - > event = = EVENT_STAMODE_AUTHMODE_CHANGE | | evt - > event = = EVENT_STAMODE_GOT_IP | |
evt - > event = = EVENT_STAMODE_DHCP_TIMEOUT | | evt - > event = = EVENT_SOFTAPMODE_STACONNECTED | |
evt - > event = = EVENT_SOFTAPMODE_STADISCONNECTED | | evt - > event = = EVENT_SOFTAPMODE_PROBEREQRECVED ) )
{ //if user has registered an EVENT_MAX(default) callback and event is not implemented...
lua_rawgeti ( L , LUA_REGISTRYINDEX , wifi_event_cb_ref [ EVENT_MAX ] ) ; //get user's callback
}
lua_newtable ( L ) ;
switch ( evt - > event )
{
case EVENT_STAMODE_CONNECTED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_CONNECTED) " , EVENT_STAMODE_CONNECTED ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " SSID " , ( char * ) evt - > event_info . connected . ssid ) ;
wifi_add_sprintf_field ( L , " BSSID " , MACSTR , MAC2STR ( evt - > event_info . connected . bssid ) ) ;
wifi_add_int_field ( L , " channel " , evt - > event_info . connected . channel ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Connected to SSID %s, Channel %d " ,
2015-12-28 08:13:02 +01:00
evt - > event_info . connected . ssid ,
evt - > event_info . connected . channel ) ;
break ;
case EVENT_STAMODE_DISCONNECTED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_DISCONNECTED) " , EVENT_STAMODE_DISCONNECTED ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " SSID " , ( char * ) evt - > event_info . disconnected . ssid ) ;
wifi_add_int_field ( L , " reason " , evt - > event_info . disconnected . reason ) ;
wifi_add_sprintf_field ( L , " BSSID " , MACSTR , MAC2STR ( evt - > event_info . disconnected . bssid ) ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Disconnect from SSID %s, reason %d " ,
2015-12-28 08:13:02 +01:00
evt - > event_info . disconnected . ssid ,
evt - > event_info . disconnected . reason ) ;
break ;
case EVENT_STAMODE_AUTHMODE_CHANGE :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_AUTHMODE_CHANGE) " , EVENT_STAMODE_AUTHMODE_CHANGE ) ;
2015-12-28 08:13:02 +01:00
wifi_add_int_field ( L , " old_auth_mode " , evt - > event_info . auth_change . old_mode ) ;
wifi_add_int_field ( L , " new_auth_mode " , evt - > event_info . auth_change . new_mode ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Authmode: %u -> %u " ,
2015-12-28 08:13:02 +01:00
evt - > event_info . auth_change . old_mode ,
evt - > event_info . auth_change . new_mode ) ;
break ;
case EVENT_STAMODE_GOT_IP :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_GOT_IP) " , EVENT_STAMODE_GOT_IP ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " IP " , IPSTR , IP2STR ( & evt - > event_info . got_ip . ip ) ) ;
wifi_add_sprintf_field ( L , " netmask " , IPSTR , IP2STR ( & evt - > event_info . got_ip . mask ) ) ;
wifi_add_sprintf_field ( L , " gateway " , IPSTR , IP2STR ( & evt - > event_info . got_ip . gw ) ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " IP: " IPSTR " ,Mask: " IPSTR " ,GW: " IPSTR " " ,
2015-12-28 08:13:02 +01:00
IP2STR ( & evt - > event_info . got_ip . ip ) ,
IP2STR ( & evt - > event_info . got_ip . mask ) ,
IP2STR ( & evt - > event_info . got_ip . gw ) ) ;
break ;
case EVENT_STAMODE_DHCP_TIMEOUT :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (STAMODE_DHCP_TIMEOUT) " , EVENT_STAMODE_DHCP_TIMEOUT ) ;
2015-12-28 08:13:02 +01:00
break ;
case EVENT_SOFTAPMODE_STACONNECTED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (SOFTAPMODE_STACONNECTED) " , EVENT_SOFTAPMODE_STACONNECTED ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " MAC " , MACSTR , MAC2STR ( evt - > event_info . sta_connected . mac ) ) ;
wifi_add_int_field ( L , " AID " , evt - > event_info . sta_connected . aid ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Station: " MACSTR " join, AID = %d " ,
2015-12-28 08:13:02 +01:00
MAC2STR ( evt - > event_info . sta_connected . mac ) ,
evt - > event_info . sta_connected . aid ) ;
break ;
case EVENT_SOFTAPMODE_STADISCONNECTED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (SOFTAPMODE_STADISCONNECTED) " , EVENT_SOFTAPMODE_STADISCONNECTED ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " MAC " , MACSTR , MAC2STR ( evt - > event_info . sta_disconnected . mac ) ) ;
wifi_add_int_field ( L , " AID " , evt - > event_info . sta_disconnected . aid ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " station: " MACSTR " leave, AID = %d " ,
2015-12-28 08:13:02 +01:00
MAC2STR ( evt - > event_info . sta_disconnected . mac ) ,
evt - > event_info . sta_disconnected . aid ) ;
break ;
case EVENT_SOFTAPMODE_PROBEREQRECVED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (SOFTAPMODE_PROBEREQRECVED) " , EVENT_SOFTAPMODE_PROBEREQRECVED ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " MAC " , MACSTR , MAC2STR ( evt - > event_info . ap_probereqrecved . mac ) ) ;
wifi_add_int_field ( L , " RSSI " , evt - > event_info . ap_probereqrecved . rssi ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Station PROBEREQ: " MACSTR " RSSI = %d " ,
2015-12-28 08:13:02 +01:00
MAC2STR ( evt - > event_info . ap_probereqrecved . mac ) ,
evt - > event_info . ap_probereqrecved . rssi ) ;
break ;
2017-05-15 09:05:22 +02:00
case EVENT_OPMODE_CHANGED :
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (OPMODE_CHANGED) " , EVENT_OPMODE_CHANGED ) ;
2017-05-15 09:05:22 +02:00
wifi_add_int_field ( L , " old_mode " , evt - > event_info . opmode_changed . old_opmode ) ;
wifi_add_int_field ( L , " new_mode " , evt - > event_info . opmode_changed . new_opmode ) ;
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " opmode: %u -> %u " ,
2017-05-15 09:05:22 +02:00
evt - > event_info . opmode_changed . old_opmode ,
evt - > event_info . opmode_changed . new_opmode ) ;
break ;
default : //if event is not implemented, return event id
2018-05-20 09:46:04 +02:00
EVENT_DBG ( " Event: %d (switch/case default) " , evt - > event ) ;
2015-12-28 08:13:02 +01:00
wifi_add_sprintf_field ( L , " info " , " event %u not implemented " , evt - > event ) ;
break ;
}
2018-05-20 09:46:04 +02:00
luaL_unref ( L , LUA_REGISTRYINDEX , event_ref ) ; //the userdata containing event info is no longer needed
event_ref = LUA_NOREF ;
2015-12-28 08:13:02 +01:00
2018-05-20 09:46:04 +02:00
lua_call ( L , 1 , 0 ) ; //execute user's callback and pass Lua table
return ;
2015-12-28 08:13:02 +01:00
}
# ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
static const LUA_REG_TYPE wifi_event_monitor_reason_map [ ] =
{
{ LSTRKEY ( " UNSPECIFIED " ) , LNUMVAL ( REASON_UNSPECIFIED ) } ,
{ LSTRKEY ( " AUTH_EXPIRE " ) , LNUMVAL ( REASON_AUTH_EXPIRE ) } ,
{ LSTRKEY ( " AUTH_LEAVE " ) , LNUMVAL ( REASON_AUTH_LEAVE ) } ,
{ LSTRKEY ( " ASSOC_EXPIRE " ) , LNUMVAL ( REASON_ASSOC_EXPIRE ) } ,
{ LSTRKEY ( " ASSOC_TOOMANY " ) , LNUMVAL ( REASON_ASSOC_TOOMANY ) } ,
{ LSTRKEY ( " NOT_AUTHED " ) , LNUMVAL ( REASON_NOT_AUTHED ) } ,
{ LSTRKEY ( " NOT_ASSOCED " ) , LNUMVAL ( REASON_NOT_ASSOCED ) } ,
{ LSTRKEY ( " ASSOC_LEAVE " ) , LNUMVAL ( REASON_ASSOC_LEAVE ) } ,
{ LSTRKEY ( " ASSOC_NOT_AUTHED " ) , LNUMVAL ( REASON_ASSOC_NOT_AUTHED ) } ,
{ LSTRKEY ( " DISASSOC_PWRCAP_BAD " ) , LNUMVAL ( REASON_DISASSOC_PWRCAP_BAD ) } ,
{ LSTRKEY ( " DISASSOC_SUPCHAN_BAD " ) , LNUMVAL ( REASON_DISASSOC_SUPCHAN_BAD ) } ,
{ LSTRKEY ( " IE_INVALID " ) , LNUMVAL ( REASON_IE_INVALID ) } ,
{ LSTRKEY ( " MIC_FAILURE " ) , LNUMVAL ( REASON_MIC_FAILURE ) } ,
{ LSTRKEY ( " 4WAY_HANDSHAKE_TIMEOUT " ) , LNUMVAL ( REASON_4WAY_HANDSHAKE_TIMEOUT ) } ,
{ LSTRKEY ( " GROUP_KEY_UPDATE_TIMEOUT " ) , LNUMVAL ( REASON_GROUP_KEY_UPDATE_TIMEOUT ) } ,
{ LSTRKEY ( " IE_IN_4WAY_DIFFERS " ) , LNUMVAL ( REASON_IE_IN_4WAY_DIFFERS ) } ,
{ LSTRKEY ( " GROUP_CIPHER_INVALID " ) , LNUMVAL ( REASON_GROUP_CIPHER_INVALID ) } ,
{ LSTRKEY ( " PAIRWISE_CIPHER_INVALID " ) , LNUMVAL ( REASON_PAIRWISE_CIPHER_INVALID ) } ,
{ LSTRKEY ( " AKMP_INVALID " ) , LNUMVAL ( REASON_AKMP_INVALID ) } ,
{ LSTRKEY ( " UNSUPP_RSN_IE_VERSION " ) , LNUMVAL ( REASON_UNSUPP_RSN_IE_VERSION ) } ,
{ LSTRKEY ( " INVALID_RSN_IE_CAP " ) , LNUMVAL ( REASON_INVALID_RSN_IE_CAP ) } ,
{ LSTRKEY ( " 802_1X_AUTH_FAILED " ) , LNUMVAL ( REASON_802_1X_AUTH_FAILED ) } ,
{ LSTRKEY ( " CIPHER_SUITE_REJECTED " ) , LNUMVAL ( REASON_CIPHER_SUITE_REJECTED ) } ,
{ LSTRKEY ( " BEACON_TIMEOUT " ) , LNUMVAL ( REASON_BEACON_TIMEOUT ) } ,
{ LSTRKEY ( " NO_AP_FOUND " ) , LNUMVAL ( REASON_NO_AP_FOUND ) } ,
{ LSTRKEY ( " AUTH_FAIL " ) , LNUMVAL ( REASON_AUTH_FAIL ) } ,
{ LSTRKEY ( " ASSOC_FAIL " ) , LNUMVAL ( REASON_ASSOC_FAIL ) } ,
{ LSTRKEY ( " HANDSHAKE_TIMEOUT " ) , LNUMVAL ( REASON_HANDSHAKE_TIMEOUT ) } ,
{ LNILKEY , LNILVAL }
} ;
# endif
const LUA_REG_TYPE wifi_event_monitor_map [ ] =
{
{ LSTRKEY ( " register " ) , LFUNCVAL ( wifi_event_monitor_register ) } ,
{ LSTRKEY ( " unregister " ) , LFUNCVAL ( wifi_event_monitor_register ) } ,
{ LSTRKEY ( " STA_CONNECTED " ) , LNUMVAL ( EVENT_STAMODE_CONNECTED ) } ,
{ LSTRKEY ( " STA_DISCONNECTED " ) , LNUMVAL ( EVENT_STAMODE_DISCONNECTED ) } ,
{ LSTRKEY ( " STA_AUTHMODE_CHANGE " ) , LNUMVAL ( EVENT_STAMODE_AUTHMODE_CHANGE ) } ,
{ LSTRKEY ( " STA_GOT_IP " ) , LNUMVAL ( EVENT_STAMODE_GOT_IP ) } ,
{ LSTRKEY ( " STA_DHCP_TIMEOUT " ) , LNUMVAL ( EVENT_STAMODE_DHCP_TIMEOUT ) } ,
{ LSTRKEY ( " AP_STACONNECTED " ) , LNUMVAL ( EVENT_SOFTAPMODE_STACONNECTED ) } ,
{ LSTRKEY ( " AP_STADISCONNECTED " ) , LNUMVAL ( EVENT_SOFTAPMODE_STADISCONNECTED ) } ,
{ LSTRKEY ( " AP_PROBEREQRECVED " ) , LNUMVAL ( EVENT_SOFTAPMODE_PROBEREQRECVED ) } ,
2017-05-15 09:05:22 +02:00
{ LSTRKEY ( " WIFI_MODE_CHANGED " ) , LNUMVAL ( EVENT_OPMODE_CHANGED ) } ,
2015-12-28 08:13:02 +01:00
{ LSTRKEY ( " EVENT_MAX " ) , LNUMVAL ( EVENT_MAX ) } ,
# ifdef WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
{ LSTRKEY ( " reason " ) , LROVAL ( wifi_event_monitor_reason_map ) } ,
# endif
{ LNILKEY , LNILVAL }
} ;
void wifi_eventmon_init ( )
{
wifi_event_monitor_task_id = task_get_id ( wifi_event_monitor_process_event_queue ) ; //get task id from task interface
wifi_set_event_handler_cb ( wifi_event_monitor_handle_event_cb ) ;
return ;
}
# endif
# endif