From 6fcb7c9e471269c9256efdc0f38c4c579eb7f4bd Mon Sep 17 00:00:00 2001 From: PshySimon Date: Fri, 7 Feb 2025 10:45:14 +0800 Subject: [PATCH] add bidirectional communication for xalarm --- src/libs/libxalarm/register_xalarm.c | 154 +++++++++++++++++++++++++++ src/libs/libxalarm/register_xalarm.h | 21 +++- 2 files changed, 174 insertions(+), 1 deletion(-) diff --git a/src/libs/libxalarm/register_xalarm.c b/src/libs/libxalarm/register_xalarm.c index deca575..9ff0f7c 100644 --- a/src/libs/libxalarm/register_xalarm.c +++ b/src/libs/libxalarm/register_xalarm.c @@ -655,3 +655,157 @@ int report_result(const char *task_name, enum RESULT_LEVEL result_level, const c return RETURE_CODE_SUCCESS; } +int xalarm_register_event(struct alarm_register **register_info, struct alarm_subscription_info id_filter) +{ + int i; + // check whether id_filter is valid + if (register_info == NULL || !alarm_subscription_verify(id_filter)) { + return -EINVAL; + } + + *register_info = (struct alarm_register *)malloc(sizeof(struct alarm_register)); + // failed to malloc memory for register_info struct + if (*register_info == NULL) { + return -ENOMEM; + } + + // transform id_filter(eg:[1001, 1002]) into bitmap(eg:[true, true, false, ..., false]) + memset((*register_info)->alarm_enable_bitmap, 0, MAX_NUM_OF_ALARM_ID * sizeof(char)); + for (i = 0; i < id_filter.len; i++) { + (*register_info)->alarm_enable_bitmap[id_filter.id_list[i] - MIN_ALARM_ID] = ALARM_ENABLED; + } + + // establish connection between xalarmd and this program + (*register_info)->register_fd = create_unix_socket(PATH_REG_ALARM); + if ((*register_info)->register_fd == -1) { + free(*register_info); + return -ENOTCONN; + } + + return 0; +} + +void xalarm_unregister_event(struct alarm_register *register_info) +{ + if (register_info == NULL) { + return; + } + // close client fd socket connection resource + if (register_info->register_fd != -1) { + (void)close(register_info->register_fd); + register_info->register_fd = -1; + } + + free(register_info); +} + +int xalarm_get_event(struct alarm_msg* msg, struct alarm_register *register_info) +{ + struct alarm_info info; + + if (msg == NULL || register_info == NULL) { + return -EINVAL; + } + + while (true) { + int recvlen = recv(register_info->register_fd, &info, sizeof(struct alarm_info), 0); + + // recvlen < 0 means that we meet with error when recv. + if (recvlen < 0) { + // when recv EINTR or EAGAIN or EWOULDBLOCK signal, we should try again. + // EINTR means recv func interrupted by signal + // EAGIAN and EWOULDBLOCK means recv has been blocked(in nonblock mode) + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + usleep(RECV_DELAY_MSEC * TIME_UNIT_MILLISECONDS); + continue; + } else { + // otherwise means we meet up with some unrecoverable error + // ECONNRESET means server closed the connection for some error + // EBADF means this filr descriptor is invalid + // ENOMEM means out of memory + // EFAULT means invalid buffer address + close(register_info->register_fd); + return -errno; + } + } + // recvlen == 0 means the connection has been properly closed, + // and the remote end has no more data to send. + if (recvlen == 0) { + close(register_info->register_fd); + return -ENOTCONN; + } + // if recvlen == sizeof(alarm_info), that means we recieved data correctlly + // why use alarm_info rather than alarm_msg? alarm_info is used for old + // api, it's a communication protocol between xalarmd service and libxalarm. + // to be compatible with old api and reduce modification to xalarmd, use + // alarm_info for communication and return alarm_msg(alarm_msg is subset of + // alarm_info). + if (recvlen == (int)sizeof(struct alarm_info)) { + // filter alarm id, alarm id reciecved which is not registered by this program + // will be ignored and continue to wait for next msg + if (info.usAlarmId < MIN_ALARM_ID || info.usAlarmId > MAX_ALARM_ID || + register_info->alarm_enable_bitmap[info.usAlarmId - MIN_ALARM_ID] != ALARM_ENABLED) { + continue; + } + msg->usAlarmId = info.usAlarmId; + msg->AlarmTime = info.AlarmTime; + strncpy((char *)msg->pucParas, (char *)info.pucParas, MAX_PARAS_LEN - 1); + // no need to close fd because get_event() can be reused after recv one msg + return 0; + } + // if recvlen > 0 but not equal to sizeof alarm_info, loop to wait for msg + } +} + +int xalarm_report_event(unsigned short usAlarmId, char *pucParas) +{ + int ret, fd; + struct alarm_info info; + struct sockaddr_un alarm_addr; + + if (usAlarmId < MIN_ALARM_ID || usAlarmId > MAX_ALARM_ID) { + return -EINVAL; + } + + if (pucParas == NULL || (int)strlen(pucParas) > MAX_PARAS_LEN) { + return -EINVAL; + } + + memset(&info, 0, sizeof(struct alarm_info)); + info.usAlarmId = usAlarmId; + info.ucAlarmLevel = MINOR_ALM; + info.ucAlarmType = ALARM_TYPE_OCCUR; + gettimeofday(&info.AlarmTime, NULL); + strncpy((char *)info.pucParas, (char *)pucParas, MAX_PARAS_LEN - 1); + + + fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) { + return -ENOTCONN; + } + + ret = init_report_addr(&alarm_addr, PATH_REPORT_ALARM); + if (ret == -1) { + close(fd); + return -ENOTCONN; + } + + while (true) { + ret = sendto(fd, &info, sizeof(struct alarm_info), 0, (struct sockaddr *)&alarm_addr, + sizeof(alarm_addr.sun_family) + strlen(alarm_addr.sun_path)); + // if errno == EINTR means sendto has been interrupted by system, should retry + if (ret < 0 && errno == EINTR) { + continue; + } + break; + } + + close(fd); + + if (ret != (int)sizeof(struct alarm_info)) { + return -ECOMM; + } + return (ret > 0) ? 0 : -errno; +} + + diff --git a/src/libs/libxalarm/register_xalarm.h b/src/libs/libxalarm/register_xalarm.h index c56561a..7a485ff 100644 --- a/src/libs/libxalarm/register_xalarm.h +++ b/src/libs/libxalarm/register_xalarm.h @@ -19,6 +19,9 @@ #define MEMORY_ALARM_ID 1001 +#define ALARM_REBOOT_EVENT 1003 +#define ALARM_REBOOT_ACK_EVENT 1004 + #define MINOR_ALM 1 #define MAJOR_ALM 2 #define CRITICAL_ALM 3 @@ -77,6 +80,22 @@ struct alarm_subscription_info { unsigned int len; }; +struct alarm_msg { + unsigned short usAlarmId; + struct timeval AlarmTime; + char pucParas[ALARM_INFO_MAX_PARAS_LEN]; +}; + +struct alarm_register { + int register_fd; + char alarm_enable_bitmap[MAX_NUM_OF_ALARM_ID]; +}; + +int xalarm_report_event(unsigned short usAlarmId, char *pucParas); +int xalarm_register_event(struct alarm_register** register_info, struct alarm_subscription_info id_filter); +int xalarm_get_event(struct alarm_msg* msg, struct alarm_register *register_info); +void xalarm_unregister_event(struct alarm_register *register_info); + int xalarm_Register(alarm_callback_func callback, struct alarm_subscription_info id_filter); void xalarm_UnRegister(int client_id); bool xalarm_Upgrade(struct alarm_subscription_info id_filter, int client_id); @@ -118,4 +137,4 @@ extern int report_result(const char *task_name, extern int send_data_to_socket(const char *socket_path, const char *message); -#endif \ No newline at end of file +#endif -- 2.27.0