#include "dms_interface.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "json_api.h"
#include "libcompat.h"
static arp_scanner_t *g_scanner = NULL;
static dms_handler_t *g_dms_handler = NULL;
int dms_interface_init(arp_scanner_t *scanner)
{
g_scanner = scanner;
// 创建DMS handler
g_dms_handler = dms_create_handler(ARP_SCANNER_UID);
if (!g_dms_handler)
{
fprintf(stderr, "Failed to create DMS handler\n");
return -1;
}
// 注册消息回调
dms_attach_event(g_dms_handler, MSG_SET_CONFIG, dms_message_callback);
dms_attach_event(g_dms_handler, MSG_GET_CONFIG, dms_message_callback);
dms_attach_event(g_dms_handler, MSG_START_SCAN, dms_message_callback);
dms_attach_event(g_dms_handler, MSG_STOP_SCAN, dms_message_callback);
dms_attach_event(g_dms_handler, MSG_GET_STATUS, dms_message_callback);
dms_attach_event(g_dms_handler, MSG_GET_RESULT, dms_message_callback);
dms_attach_event(g_dms_handler, MSG_CLEAR_RESULT, dms_message_callback);
// 注册DS配置
ds_register_arp_config();
// 从DS加载配置
ds_load_config(&g_scanner->config);
return 0;
}
int dms_interface_cleanup()
{
if (g_dms_handler)
{
dms_destroy_handler(g_dms_handler);
g_dms_handler = NULL;
}
return 0;
}
S32 dms_message_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id)
{
if (!mbuf || mlen < sizeof(U32))
{
return -1;
}
U32 msg_type = *(U32 *)mbuf;
U8 *data = mbuf + sizeof(U32);
U32 data_len = mlen - sizeof(U32);
switch (msg_type)
{
case MSG_SET_CONFIG:
return handle_set_config(handler, data, data_len, sender_dms_id);
case MSG_GET_CONFIG:
return handle_get_config(handler, data, data_len, sender_dms_id);
case MSG_START_SCAN:
return handle_start_scan(handler, data, data_len, sender_dms_id);
case MSG_STOP_SCAN:
return handle_stop_scan(handler, data, data_len, sender_dms_id);
case MSG_GET_STATUS:
return handle_get_status(handler, data, data_len, sender_dms_id);
case MSG_GET_RESULT:
return handle_get_result(handler, data, data_len, sender_dms_id);
case MSG_CLEAR_RESULT:
return handle_clear_result(handler, data, data_len, sender_dms_id);
default:
fprintf(stderr, "Unknown message type: %u\n", msg_type);
return -1;
}
}
S32 handle_set_config(dms_handler_t *handler, U8 *data, U32 len, U32 sender)
{
if (!g_scanner || len < sizeof(arp_ds_config_t))
{
return -1;
}
arp_ds_config_t *ds_config = (arp_ds_config_t *)data;
pthread_mutex_lock(&g_scanner->lock);
g_scanner->config.enabled = ds_config->enabled;
g_scanner->config.scan_interval = ds_config->scan_interval;
g_scanner->config.validity_period = ds_config->validity_period;
g_scanner->config.packet_interval = ds_config->packet_interval;
g_scanner->config.start_ip = ip_to_int(ds_config->start_ip);
g_scanner->config.end_ip = ip_to_int(ds_config->end_ip);
pthread_mutex_unlock(&g_scanner->lock);
// 保存配置到DS
ds_save_config(&g_scanner->config);
// 发送响应
U32 response = 0; // 成功
S32 ret = dms_sendto(handler, dms_get_sockfd(handler), MSG_SET_CONFIG,
(U8 *)&response, sizeof(response), sender);
if (ret != 0)
{
fprintf(stderr, "Failed to send response for set_config: %d\n", ret);
}
return 0;
}
S32 handle_get_config(dms_handler_t *handler, U8 *data, U32 len, U32 sender)
{
if (!g_scanner)
{
return -1;
}
arp_ds_config_t ds_config;
pthread_mutex_lock(&g_scanner->lock);
ds_config.enabled = g_scanner->config.enabled;
ds_config.scan_interval = g_scanner->config.scan_interval;
ds_config.validity_period = g_scanner->config.validity_period;
ds_config.packet_interval = g_scanner->config.packet_interval;
int_to_ip(g_scanner->config.start_ip, ds_config.start_ip);
int_to_ip(g_scanner->config.end_ip, ds_config.end_ip);
pthread_mutex_unlock(&g_scanner->lock);
// 发送响应
dms_sendto(handler, dms_get_sockfd(handler), MSG_GET_CONFIG,
(U8 *)&ds_config, sizeof(ds_config), sender);
if (ret != 0)
{
fprintf(stderr, "Failed to send response for set_config: %d\n", ret);
}
return 0;
}
S32 handle_start_scan(dms_handler_t *handler, U8 *data, U32 len, U32 sender)
{
if (!g_scanner)
{
return -1;
}
int result = arp_scanner_start(g_scanner);
// 发送响应
U32 response = (result == 0) ? 0 : 1;
dms_sendto(handler, dms_get_sockfd(handler), MSG_START_SCAN,
(U8 *)&response, sizeof(response), sender);
return 0;
}
S32 handle_stop_scan(dms_handler_t *handler, U8 *data, U32 len, U32 sender)
{
if (!g_scanner)
{
return -1;
}
int result = arp_scanner_stop(g_scanner);
// 发送响应
U32 response = (result == 0) ? 0 : 1;
dms_sendto(handler, dms_get_sockfd(handler), MSG_STOP_SCAN,
(U8 *)&response, sizeof(response), sender);
return 0;
}
S32 handle_get_status(dms_handler_t *handler, U8 *data, U32 len, U32 sender)
{
if (!g_scanner)
{
return -1;
}
struct
{
BOOL enabled;
BOOL scanning;
U32 entry_count;
time_t last_scan_time;
} status;
pthread_mutex_lock(&g_scanner->lock);
status.enabled = g_scanner->config.enabled;
status.scanning = g_scanner->scanning;
status.entry_count = g_scanner->entry_count;
status.last_scan_time = g_scanner->last_scan_time;
pthread_mutex_unlock(&g_scanner->lock);
dms_sendto(handler, dms_get_sockfd(handler), MSG_GET_STATUS,
(U8 *)&status, sizeof(status), sender);
return 0;
}
S32 handle_get_result(dms_handler_t *handler, U8 *data, U32 len, U32 sender)
{
if (!g_scanner)
{
return -1;
}
pthread_mutex_lock(&g_scanner->lock);
// 构建JSON格式的结果
JSON_OBJPTR root = json_object_new_object();
JSON_OBJPTR entries = json_object_new_array();
for (int i = 0; i < g_scanner->entry_count; i++)
{
JSON_OBJPTR entry = json_object_new_object();
char ip_str[MAX_IP_LEN];
int_to_ip(g_scanner->entries[i].ip, ip_str);
json_object_object_add(entry, "ip", json_object_new_string(ip_str));
json_object_object_add(entry, "mac", json_object_new_string(g_scanner->entries[i].mac));
json_object_object_add(entry, "first_seen",
json_object_new_int64(g_scanner->entries[i].first_seen));
json_object_object_add(entry, "last_seen",
json_object_new_int64(g_scanner->entries[i].last_seen));
json_object_array_add(entries, entry);
}
json_object_object_add(root, "entries", entries);
json_object_object_add(root, "count",
json_object_new_int(g_scanner->entry_count));
const char *json_str = json_object_to_json_string(root);
dms_sendto(handler, dms_get_sockfd(handler), MSG_GET_RESULT,
(U8 *)json_str, strlen(json_str) + 1, sender);
json_object_put(root);
pthread_mutex_unlock(&g_scanner->lock);
return 0;
}
S32 handle_clear_result(dms_handler_t *handler, U8 *data, U32 len, U32 sender)
{
if (!g_scanner)
{
return -1;
}
pthread_mutex_lock(&g_scanner->lock);
g_scanner->entry_count = 0;
pthread_mutex_unlock(&g_scanner->lock);
U32 response = 0;
dms_sendto(handler, dms_get_sockfd(handler), MSG_CLEAR_RESULT,
(U8 *)&response, sizeof(response), sender);
return 0;
}
int ds_register_arp_config()
{
// 注册ARP扫描器配置表
DS_TBL_DESC arp_config_table = {
.name = "arp_config",
.data_size = sizeof(arp_ds_config_t),
.max_num = 1,
.option = NULL};
return ds_register_table_to("nsd", &arp_config_table, 1);
}
int ds_save_config(const arp_config_t *config)
{
arp_ds_config_t ds_config;
ds_config.enabled = config->enabled;
ds_config.scan_interval = config->scan_interval;
ds_config.validity_period = config->validity_period;
ds_config.packet_interval = config->packet_interval;
int_to_ip(config->start_ip, ds_config.start_ip);
int_to_ip(config->end_ip, ds_config.end_ip);
return ds_save_single_usr_cfg("nsd", "arp_config", (U8 *)&ds_config, sizeof(ds_config));
}
int ds_load_config(arp_config_t *config)
{
arp_ds_config_t ds_config;
U32 len = sizeof(ds_config);
if (ds_load_usr_cfg() == 0)
{
// 从DS加载配置
if (ds_array_transfer("nsd", "arp_config", NULL) == 0)
{
config->enabled = ds_config.enabled;
config->scan_interval = ds_config.scan_interval;
config->validity_period = ds_config.validity_period;
config->packet_interval = ds_config.packet_interval;
config->start_ip = ip_to_int(ds_config.start_ip);
config->end_ip = ip_to_int(ds_config.end_ip);
return 0;
}
}
// 默认配置
config->enabled = FALSE;
config->scan_interval = 60; /* s */
config->validity_period = 300; /* s */
config->packet_interval = 100; /* ms */
config->start_ip = ip_to_int("192.168.1.100");
config->end_ip = ip_to_int("192.168.1.200");
return 0;
}这个里面如果要用ds_read和ds_write函数实现怎么办
#include "ds_common.h"
#include <sys/shm.h> /* for shmget() */
#include <sys/sem.h> /* for semget() */
#include "sslApi.h"
#ifdef DEBUG
#define PRINT(fmt, ...) printf("[%s:%u] "fmt"\n", __FUNCTION__, __LINE__, ## __VA_ARGS__)
#else
#define PRINT(fmt, ...)
#endif
/* 根据相同的key值,能够找到同一块共享内存,或者同一个信号量 */
#define DS_SHM_KEY 0x6c796c
#define DS_SEM_KEY 0x6c796c
#ifdef _SEM_SEMUN_UNDEFINED
union semun
{
S32 val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
U16 *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
#endif
LOCAL DS_HANDLE* g_libds_handle = NULL;
/* 初始化信号量,在使用信号量前必须这样做 */
LOCAL int set_sem_val(int sem_id)
{
union semun sem_union;
sem_union.val = 1;
return semctl(sem_id, 0, SETVAL, sem_union);
}
/* yl todo: 要考虑同一个进程多次调用的情况 */
DS_HANDLE* ds_create_shm(U32 data_size)
{
int shm_id = -1;
BIN_AREA *bin_area = NULL;
int sem_id = -1;
g_libds_handle = DS_MALLOC(sizeof(DS_HANDLE));
if (NULL == g_libds_handle)
{
PRINT("DS handle malloc failed.\n");
return NULL;
}
memset(g_libds_handle, 0, sizeof(DS_HANDLE));
/* 分配共享内存块。如不存在,则新建。
* 新建的内存块已初始化为0 --from "man shmget" */
shm_id = shmget(DS_SHM_KEY, data_size + sizeof(BIN_AREA), 0640 | IPC_CREAT);
if (-1 == shm_id)
{
PRINT("Get shared memory failed, errno.%02d is: %s", errno, strerror(errno));
goto error_return;
}
/* 将共享内存块附加到进程自己的地址空间,内核自己决定一个合适的地址位置 */
bin_area = shmat(shm_id, NULL, 0);
if ((void *)-1 == bin_area)
{
PRINT("Map shared memory failed, errno.%02d is: %s", errno, strerror(errno));
goto error_return;
}
/* 新建内存块时要记录大小 */
if (0 != data_size)
{
/* 将共享内存显式初始化为0,防止重启时shm存在导致动态配置没有重置 */
memset((void*)bin_area, 0, data_size + sizeof(BIN_AREA));
bin_area->data_size = data_size;
}
g_libds_handle->cfg_blob_buf = (U8 *)bin_area->data;
g_libds_handle->cfg_blob_buf_size = bin_area->data_size;
/* 分配信号量 */
sem_id = semget(DS_SEM_KEY, 1, 0666);
if (-1 == sem_id)
{
if (ENOENT != errno)
{
PRINT("Get semaphore failed, errno.%02d is: %s", errno, strerror(errno));
goto error_return;
}
/* 信号量不存在,则创建 */
PRINT("Create semaphore");
sem_id = semget(DS_SEM_KEY, 1, 0666 | IPC_CREAT);
if (-1 == sem_id)
{
PRINT("Create semaphore failed, errno.%02d is: %s", errno, strerror(errno));
goto error_return;
}
/* 初始化信号量 */
if (-1 == set_sem_val(sem_id))
{
PRINT("Set semaphore failed, errno.%02d is: %s", errno, strerror(errno));
goto error_return;
}
}
g_libds_handle->sem_id = sem_id;
return g_libds_handle;
error_return:
ds_destroy_shm();
return NULL;
}
S32 ds_destroy_shm()
{
/* 将共享内存块从进程自己的地址空间删掉 */
if (NULL == g_libds_handle)
{
return ERROR;
}
if (NULL != g_libds_handle->cfg_blob_buf)
{
/* 从记录的data地址算出area的地址 */
shmdt((void *)((u_int32_t)g_libds_handle->cfg_blob_buf - sizeof(BIN_AREA)));
g_libds_handle->cfg_blob_buf = NULL;
}
DS_FREE(g_libds_handle);
return 0;
}
DS_HANDLE* ds_get_handle()
{
return g_libds_handle;
}
/* 对信号量减1操作,即等待P(SV) */
int ds_lock()
{
struct sembuf sem_b;
/* 预防进程未调用ds_create_shm初始化就开始使用DS */
if (NULL == g_libds_handle)
{
PRINT("DS uninitialized");
return -1;
}
sem_b.sem_num = 0;
sem_b.sem_op = -1; /* P() */
sem_b.sem_flg = SEM_UNDO;
return semop(g_libds_handle->sem_id, &sem_b, 1);
}
/* 释放操作,使信号量变为可用,即V(SV) */
int ds_unlock()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; /* V() */
sem_b.sem_flg = SEM_UNDO;
return semop(g_libds_handle->sem_id, &sem_b, 1);
}
/* 计算BLOB ID */
void ds_calc_id(const char *path, BLOB_ID *blob_id)
{
Md5 md5;
if ((NULL == path) || (NULL == blob_id))
{
return;
}
tpssl_InitMd5(&md5);
tpssl_Md5Update(&md5, (U8 *)path, strlen(path));
tpssl_Md5Final(&md5, blob_id->u8);
/*PRINT("ID [%s] => %08x%08x%08x%08x", path, ntohl(blob_id->u32[0]), ntohl(blob_id->u32[1]), ntohl(blob_id->u32[2]), ntohl(blob_id->u32[3]));*/
}
BOOL ds_id_exist(BLOB_ID *id, U32 num, const BLOB_ID *blob_id)
{
U32 index = 0;
for (index = 0; index < num; index++, id++)
{
if ((id->u32[0] == blob_id->u32[0]) && (id->u32[1] == blob_id->u32[1]) &&
(id->u32[2] == blob_id->u32[2]) && (id->u32[3] == blob_id->u32[3]))
{
return TRUE;
}
}
return FALSE;
}
BOOL ds_path_id_exist(BLOB_ID *id, U32 num, const char *path)
{
BLOB_ID blob_id;
ds_calc_id(path, &blob_id);
return ds_id_exist(id, num, &blob_id);
}
/****************************************************************************
Function : ds_check_buf_modification
Description : 对比blob中的旧据和准备写入的data_buf,检查是否有修改
Input : blob为待覆盖的旧数据,data_buf为新数据,size为data_buf的长度
Output : 如果有修改返回TRUE,否则返回FALSE
*****************************************************************************/
BOOL ds_check_buf_modification(BLOB_DATA *blob, void *data_buf, U32 size)
{
if(0 != memcmp(data_buf, blob->data, size))
{
return TRUE;
}
return FALSE;
}
BLOB_DATA* ds_find_blob(BIN_AREA *bin_area, const BLOB_ID *blob_id)
{
BLOB_DATA *blob = NULL;
if ((NULL == bin_area) || (NULL == blob_id))
{
return NULL;
}
/* 在二进制数据区里按key查找对应的二进制数据块 */
/* 表格blob要继续深入解析 */
for (blob = (BLOB_DATA *)bin_area->data; blob < (BLOB_DATA *)((U32)bin_area->data + bin_area->data_size);
blob = (BLOB_TYPE_TABLE == blob->type) ? SUB_BLOB(blob) : NEXT_BLOB(blob))
{
/*PRINT("BLOB %#x ID %08x%08x%08x%08x size %d|%d", (U32)blob, ntohl(blob->id.u32[0]), ntohl(blob->id.u32[1]),
ntohl(blob->id.u32[2]), ntohl(blob->id.u32[3]), blob->data_size, ALIGN4(blob->data_size));*/
if ((blob->id.u32[0] == blob_id->u32[0]) && (blob->id.u32[1] == blob_id->u32[1]) &&
(blob->id.u32[2] == blob_id->u32[2]) && (blob->id.u32[3] == blob_id->u32[3]))
{
return blob;
}
}
return NULL;
}
/* 从外部指定的二进制数据区读取二进制数据 */
U32 ds_ext_read(BIN_AREA *bin_area, const char *path, void *data_buf, U32 data_size)
{
BLOB_DATA *blob = NULL;
U32 size = 0;
BLOB_ID blob_id;
if ((NULL == bin_area) || (NULL == path) || (NULL == data_buf))
{
return 0;
}
ds_calc_id(path, &blob_id);
/* 寻找blob */
if (NULL == (blob = ds_find_blob(bin_area, &blob_id)))
{
PRINT("No match segment in [%s]", path);
return 0;
}
/* 不够空间返回,可能是前一版的数据块,只返回前面部分 */
size = min(blob->data_size, data_size);
memcpy(data_buf, blob->data, size);
/* 返回实际读取大小 */
return size;
}
/* 二进制读 */
/* yl todo: 传入版本号实现前、后向兼容读取? 先不考虑传入table的情况 */
U32 ds_read(const char *path, void *data_buf, U32 data_size)
{
BLOB_DATA *blob = NULL;
U32 size = 0;
BLOB_ID blob_id;
if ((NULL == path) || (NULL == data_buf))
{
return 0;
}
ds_calc_id(path, &blob_id);
if (-1 == ds_lock())
{
PRINT("Lock failed, errno.%02d is: %s", errno, strerror(errno));
return 0;
}
/******************** 临界区开始 ********************/
/* 寻找blob */
if (NULL == (blob = ds_find_blob((BIN_AREA *)((U32)g_libds_handle->cfg_blob_buf - sizeof(BIN_AREA)), &blob_id)))
{
PRINT("No match segment in [%s]", path);
goto unlock_return;
}
/* 不够空间返回,可能是前一版的数据块,只返回前面部分 */
size = min(blob->data_size, data_size);
memcpy(data_buf, blob->data, size);
/******************** 临界区结束 ********************/
unlock_return:
ds_unlock();
/* 返回实际读取大小 */
return size;
}
/* 二进制写 */
U32 ds_write(const char *path, void *data_buf, U32 data_size)
{
BLOB_DATA *blob = NULL;
U32 size = 0;
BLOB_ID blob_id;
if ((NULL == path) || (NULL == data_buf))
{
return 0;
}
ds_calc_id(path, &blob_id);
if (-1 == ds_lock())
{
PRINT("Lock failed, errno.%02d is: %s", errno, strerror(errno));
return 0;
}
/******************** 临界区开始 ********************/
/* 寻找blob */
if (NULL == (blob = ds_find_blob((BIN_AREA *)((U32)g_libds_handle->cfg_blob_buf - sizeof(BIN_AREA)), &blob_id)))
{
PRINT("No match segment in [%s]", path);
goto unlock_return;
}
/* 不够空间填满,可能是前一版的数据块,只回写已修改的部分 */
size = min(blob->data_size, data_size);
if(FALSE == ds_check_buf_modification(blob, data_buf, size))
{
goto unlock_return;
}
memcpy(blob->data, data_buf, size);
/******************** 临界区结束 ********************/
unlock_return:
ds_unlock();
/* 返回实际写入大小 */
return size;
}
U32 ds_advanced_write(const char *path, void *data_buf, U32 data_size, U32 flags)
{
BLOB_DATA *blob = NULL;
U32 size = 0;
U32 bin_area_size = 0;
BOOL is_list_table = FALSE;
BOOL data_change = TRUE;
BLOB_ID blob_id;
BIN_AREA *bin_area = NULL;
TABLE_DESC *table = NULL;
BLOB_DATA *table_blob = NULL;
if ((NULL == path) || (NULL == data_buf))
{
return 0;
}
ds_calc_id(path, &blob_id);
if (-1 == ds_lock())
{
PRINT("Lock failed, errno.%02d is: %s", errno, strerror(errno));
return 0;
}
/******************** 临界区开始 ********************/
/* 寻找blob */
if (NULL == (blob = ds_find_blob((BIN_AREA *)((U32)g_libds_handle->cfg_blob_buf - sizeof(BIN_AREA)), &blob_id)))
{
/******************** 临界区结束 ********************/
ds_unlock();
PRINT("No match segment in [%s]", path);
goto ret;
}
/* 不够空间填满,可能是前一版的数据块,只回写已修改的部分 */
size = min(blob->data_size, data_size);
/* 针对 DS_FLAG_SAVE_FLASH 检查待写入数据和内存中数据是否变化,没有变化则跳过后续操作,
* 但对 DS_FLAG_NOTIFY ,如果数据未修改,则记录标记位,后续不进行写flash操作 */
if(FALSE == ds_check_buf_modification(blob, data_buf, size))
{
if (flags & DS_FLAG_NOTIFY)
{
data_change = FALSE;
}
else
{
/******************** 临界区结束 ********************/
DS_CMD_PRINT("Data not change, %s flag operation %x is ignored\n", path, flags);
ds_unlock();
goto ret;
}
}
bin_area_size = sizeof(BIN_AREA) + CALC_BLOB_SIZE(size);
table = ((SEGMENT_DESC *)(blob->segment))->section->table;
is_list_table = IS_LIST_TABLE(table);
if (is_list_table)
{
bin_area_size += sizeof(BLOB_DATA);
}
if (flags & (DS_FLAG_CHECK | DS_FLAG_NOTIFY))
{
/* 构造包含该blob的bin area,用于check和notify */
/* bin_area的长度 = bin_area的头部长度 + BLOB的头部长度 + 实际数据长度 */
if (NULL != (bin_area = ds_new_bin_area(bin_area_size)))
{
memcpy(bin_area->data, blob, sizeof(BLOB_DATA));
memcpy(bin_area->data + sizeof(BLOB_DATA), data_buf, size);
/* 如果section属于表格数据,要格式化table blob(不含数据) */
if (is_list_table)
{
table_blob = (BLOB_DATA *)(bin_area->data + sizeof(BLOB_DATA) + size);
ds_format_table(&table_blob, table);
}
if (flags & DS_FLAG_CHECK)
{
/******************** 临界区结束 ********************/
ds_unlock();
if (SLP_ENONE != ds_check_module(bin_area))
{
size = 0;
goto ret;
}
ds_lock();
/******************** 临界区开始 ********************/
}
}
}
memcpy(blob->data, data_buf, size);
/******************** 临界区结束 ********************/
ds_unlock();
if (data_change && (flags & DS_FLAG_SAVE_FLASH) && IS_CONFIG(((SEGMENT_DESC *)(blob->segment))->section->table))
{
ds_save_usr_cfg();
}
if ((flags & DS_FLAG_NOTIFY) && (NULL != bin_area))
{
do_srvcb_async(bin_area);
}
ret:
ds_free_bin_area(bin_area);
/* 返回实际写入大小 */
return size;
}
最新发布