* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <stdlib.h>
#include <osal_mem.h>
#include <pthread.h>
#include "hdf_log.h"
#include "securec.h"
#include "wpa_client.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#ifndef EOK
#define EOK 0
#endif
#define MAX_CALL_BACK_COUNT 10
static struct WpaCallbackEvent *g_wpaCallbackEventMap[MAX_CALL_BACK_COUNT] = {NULL};
static pthread_rwlock_t g_wpaCallbackMutex = PTHREAD_RWLOCK_INITIALIZER;
bool HasRegisterCallback(const char *ifName, int nameLen)
{
if (ifName == NULL || nameLen > IFNAMSIZ) {
return false;
}
pthread_rwlock_rdlock(&g_wpaCallbackMutex);
for (int i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_wpaCallbackEventMap[i] != NULL &&
(strncmp(g_wpaCallbackEventMap[i]->ifName, ifName, nameLen) == 0)) {
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return true;
}
}
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return false;
}
int32_t WpaRegisterEventCallback(OnReceiveFunc onRecFunc, uint32_t eventType, const char *ifName)
{
uint32_t i;
struct WpaCallbackEvent *callbackEvent = NULL;
int ifNameLen = 0;
if (ifName != NULL) {
ifNameLen = (int)strnlen(ifName, IFNAMSIZ + 1);
}
if (onRecFunc == NULL || ifName == NULL || ifNameLen == (IFNAMSIZ + 1)) {
HDF_LOGE("%s: input parameter invalid, line: %d", __FUNCTION__, __LINE__);
return -1;
}
pthread_rwlock_wrlock(&g_wpaCallbackMutex);
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_wpaCallbackEventMap[i] != NULL && (strcmp(g_wpaCallbackEventMap[i]->ifName, ifName) == 0)
&& g_wpaCallbackEventMap[i]->onRecFunc == onRecFunc) {
HDF_LOGI("%s the onRecFunc has been registered!", __FUNCTION__);
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return 0;
}
}
callbackEvent = (struct WpaCallbackEvent *)malloc(sizeof(struct WpaCallbackEvent));
if (callbackEvent == NULL) {
HDF_LOGE("%s fail: malloc fail!", __FUNCTION__);
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return -1;
}
callbackEvent->eventType = eventType;
if (memcpy_s(callbackEvent->ifName, IFNAMSIZ, ifName, ifNameLen) != 0) {
free(callbackEvent);
HDF_LOGE("%s: ifName memcpy_s fail", __FUNCTION__);
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return -1;
}
callbackEvent->ifName[ifNameLen] = '\0';
callbackEvent->onRecFunc = onRecFunc;
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_wpaCallbackEventMap[i] == NULL) {
g_wpaCallbackEventMap[i] = callbackEvent;
HDF_LOGD("%s: WifiRegisterEventCallback successful", __FUNCTION__);
HDF_LOGD("%s: callbackEvent->eventType =%d ", __FUNCTION__, callbackEvent->eventType);
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return 0;
}
}
pthread_rwlock_unlock(&g_wpaCallbackMutex);
free(callbackEvent);
HDF_LOGE("%s fail: register onRecFunc num more than %d!", __FUNCTION__, MAX_CALL_BACK_COUNT);
return -1;
}
int32_t WpaUnregisterEventCallback(OnReceiveFunc onRecFunc, uint32_t eventType, const char *ifName)
{
uint32_t i;
if (onRecFunc == NULL || ifName == NULL) {
HDF_LOGE("%s: input parameter invalid, line: %d", __FUNCTION__, __LINE__);
return HDF_FAILURE;
}
pthread_rwlock_wrlock(&g_wpaCallbackMutex);
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_wpaCallbackEventMap[i] != NULL && g_wpaCallbackEventMap[i]->eventType == eventType &&
(strcmp(g_wpaCallbackEventMap[i]->ifName, ifName) == 0) &&
g_wpaCallbackEventMap[i]->onRecFunc == onRecFunc) {
g_wpaCallbackEventMap[i]->onRecFunc = NULL;
free(g_wpaCallbackEventMap[i]);
g_wpaCallbackEventMap[i] = NULL;
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return HDF_SUCCESS;
}
}
pthread_rwlock_unlock(&g_wpaCallbackMutex);
return HDF_FAILURE;
}
void ReleaseEventCallback(void)
{
pthread_rwlock_wrlock(&g_wpaCallbackMutex);
for (uint32_t i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_wpaCallbackEventMap[i] != NULL) {
g_wpaCallbackEventMap[i]->onRecFunc = NULL;
free(g_wpaCallbackEventMap[i]);
g_wpaCallbackEventMap[i] = NULL;
}
}
pthread_rwlock_unlock(&g_wpaCallbackMutex);
}
static void RemoveIfaceCallback(const char *ifName)
{
if (ifName == NULL) {
return;
}
for (int i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_wpaCallbackEventMap[i] != NULL && (strcmp(g_wpaCallbackEventMap[i]->ifName, ifName) == 0)) {
g_wpaCallbackEventMap[i]->onRecFunc = NULL;
free(g_wpaCallbackEventMap[i]);
g_wpaCallbackEventMap[i] = NULL;
}
}
}
void WpaEventReport(const char *ifName, uint32_t event, void *data)
{
uint32_t i;
if (event == WPA_EVENT_IFACE_REMOVED) {
RemoveIfaceCallback(ifName);
return;
}
OnReceiveFunc callbackEventMap[MAX_CALL_BACK_COUNT] = {NULL};
pthread_rwlock_rdlock(&g_wpaCallbackMutex);
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_wpaCallbackEventMap[i] != NULL && ((strstr(ifName, g_wpaCallbackEventMap[i]->ifName))
|| (strcmp(g_wpaCallbackEventMap[i]->ifName, ifName) == 0)) &&
(((1 << event) & g_wpaCallbackEventMap[i]->eventType) != 0)) {
HDF_LOGI("%s: send event = %u, ifName = %s", __FUNCTION__, event, ifName);
callbackEventMap[i] = g_wpaCallbackEventMap[i]->onRecFunc;
}
}
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (callbackEventMap[i] != NULL) {
HDF_LOGI("%s: call event = %u, ifName = %s", __FUNCTION__, event, ifName);
callbackEventMap[i](event, data, ifName);
}
}
pthread_rwlock_unlock(&g_wpaCallbackMutex);
}