//#include "sys_config.h" #include "typesdef.h" #include "list.h" #include "osal/task.h" #include "osal/string.h" #include "osal/sleep.h" #include "osal/mutex.h" #include "osal/semaphore.h" #include "osal/work.h" #include "lwip/opt.h" #include "lwip/sockets.h" #include "lwip/inet_chksum.h" #include "netif/etharp.h" #include "netif/ethernetif.h" #include "lwip/ip.h" #include "lwip/init.h" #include "lib/net/skmonitor/skmonitor.h" #define skmntr_dbg(fmt, ...) //os_printf("%s:%d::"fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__) #define SKMNTR_STATIS (0) #define SKMONITOR_PORT (61753) struct skmonitor_entry { struct skmonitor_entry *next; uint16 sock; uint8 flags; uint8 disable: 1, rev: 7; uint32 priv; skmonitor_cb cb; #if SKMNTR_STATIS uint32 trig_rd, trig_wr, trig_err; #endif }; struct skmonitor_mgr { struct skmonitor_entry *entrys; os_mutex_t lock; os_semaphore_t run; struct os_work work; os_task_t task; fd_set rset, wset, eset; int32 sock; } g_skmonitor; static void sock_monitor_reset() { uint8 val = 0; struct sockaddr_in addr; os_memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(SKMONITOR_PORT); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); sendto(g_skmonitor.sock, &val, 1, 0, (struct sockaddr *)&addr, sizeof(addr)); } static void sock_monitor_task(void *args) { int32 ret = 0; struct timeval tv; struct skmonitor_entry *mntr = NULL; while (1) { os_sema_down(&g_skmonitor.run, osWaitForever); FD_ZERO(&g_skmonitor.rset); FD_ZERO(&g_skmonitor.wset); FD_ZERO(&g_skmonitor.eset); ret = g_skmonitor.sock; FD_SET(g_skmonitor.sock, &g_skmonitor.rset); os_mutex_lock(&g_skmonitor.lock, osWaitForever); mntr = g_skmonitor.entrys; while (mntr) { if (!mntr->disable) { if (mntr->flags & SOCK_MONITOR_READ) { FD_SET(mntr->sock, &g_skmonitor.rset); } if (mntr->flags & SOCK_MONITOR_WRITE) { FD_SET(mntr->sock, &g_skmonitor.wset); } if (mntr->flags & SOCK_MONITOR_ERROR) { FD_SET(mntr->sock, &g_skmonitor.eset); } if (mntr->sock > ret) { ret = mntr->sock; } } mntr = mntr->next; } os_mutex_unlock(&g_skmonitor.lock); tv.tv_sec = 0; tv.tv_usec = 100 * 1000; ret = select(ret + 1, &g_skmonitor.rset, &g_skmonitor.wset, &g_skmonitor.eset, &tv); if (ret == 0) { os_sema_up(&g_skmonitor.run); } else { os_run_work(&g_skmonitor.work); } } } static int32 sock_monitor_work(struct os_work *work) { uint8 val; uint8 flags; socklen_t len = 0; struct sockaddr_in addr; struct skmonitor_entry *mntr = NULL; struct skmonitor_entry *next = NULL; skmonitor_cb cb; uint32 priv; int32 sock; os_mutex_lock(&g_skmonitor.lock, osWaitForever); mntr = g_skmonitor.entrys; while (mntr) { next = mntr->next; flags = 0; if (FD_ISSET(mntr->sock, &g_skmonitor.rset)) { flags |= SOCK_MONITOR_READ; #if SKMNTR_STATIS mntr->trig_rd++; #endif } if (FD_ISSET(mntr->sock, &g_skmonitor.wset)) { flags |= SOCK_MONITOR_WRITE; #if SKMNTR_STATIS mntr->trig_wr++; #endif } if (FD_ISSET(mntr->sock, &g_skmonitor.eset)) { flags |= SOCK_MONITOR_ERROR; #if SKMNTR_STATIS mntr->trig_err++; #endif } if (flags && mntr->cb) { cb = mntr->cb; priv = mntr->priv; sock = mntr->sock; os_mutex_unlock(&g_skmonitor.lock); skmntr_dbg("callback start ..., cb=%p\r\n", cb); cb(sock, flags, priv); skmntr_dbg("callback done, cb=%p\r\n", cb); os_mutex_lock(&g_skmonitor.lock, osWaitForever); } mntr = next; } os_mutex_unlock(&g_skmonitor.lock); if (FD_ISSET(g_skmonitor.sock, &g_skmonitor.rset)) { recvfrom(g_skmonitor.sock, &val, 1, 0, (struct sockaddr *)&addr, &len); } os_sema_up(&g_skmonitor.run); return 0; } int32 sock_monitor_add(uint16 sock, skmonitor_flags flags, skmonitor_cb cb, uint32 priv) { int32 ret = -1; struct skmonitor_entry *mntr = NULL; if ((int16)sock < 0 || cb == NULL) { return -EINVAL; } skmntr_dbg("sock_monitor_add enter ...\r\n"); os_mutex_lock(&g_skmonitor.lock, osWaitForever); mntr = g_skmonitor.entrys; while (mntr) { if (mntr->sock == sock) { mntr->cb = cb; mntr->priv = priv; mntr->flags = flags; ret = 0; break; } mntr = mntr->next; } if (ret) { mntr = os_zalloc(sizeof(struct skmonitor_entry)); if (mntr) { mntr->cb = cb; mntr->sock = sock; mntr->priv = priv; mntr->flags = flags; mntr->next = g_skmonitor.entrys; g_skmonitor.entrys = mntr; ret = 0; } } os_mutex_unlock(&g_skmonitor.lock); skmntr_dbg("sock_monitor_add leave\r\n"); sock_monitor_reset(); return ret; } void sock_monitor_del(uint16 sock) { struct skmonitor_entry *mntr = NULL; struct skmonitor_entry *prev = NULL; skmntr_dbg("sock_monitor_del enter ...\r\n"); os_mutex_lock(&g_skmonitor.lock, osWaitForever); mntr = g_skmonitor.entrys; while (mntr) { if (mntr->sock == sock) { if (prev) { prev->next = mntr->next; } else { g_skmonitor.entrys = mntr->next; } os_free(mntr); break; } prev = mntr; mntr = mntr->next; } os_mutex_unlock(&g_skmonitor.lock); skmntr_dbg("sock_monitor_del leave\r\n"); } void sock_monitor_disable(uint16 sock, uint8 disable) { struct skmonitor_entry *mntr = NULL; skmntr_dbg("sock_monitor_disable enter ...\r\n"); os_mutex_lock(&g_skmonitor.lock, osWaitForever); mntr = g_skmonitor.entrys; while (mntr) { if (mntr->sock == sock && mntr->disable != disable) { mntr->disable = disable; if (!disable) { sock_monitor_reset(); } break; } mntr = mntr->next; } os_mutex_unlock(&g_skmonitor.lock); skmntr_dbg("sock_monitor_disable leave\r\n"); } void sock_monitor_dump(void) { #if SKMNTR_STATIS struct skmonitor_entry *mntr = NULL; skmntr_dbg("sock monitor dump:\r\n"); os_mutex_lock(&g_skmonitor.lock, osWaitForever); mntr = g_skmonitor.entrys; while (mntr) { if (!mntr->disable) { os_printf(" sock %d, cb:%p, read:%d, write:%d, error:%d\r\n", mntr->sock, mntr->cb, mntr->trig_rd, mntr->trig_wr, mntr->trig_err); mntr->trig_rd = 0; mntr->trig_wr = 0; mntr->trig_err = 0; } mntr = mntr->next; } os_mutex_unlock(&g_skmonitor.lock); #endif } __init int32 sock_monitor_init(void) { struct sockaddr_in local_addr; os_memset(&g_skmonitor, 0, sizeof(g_skmonitor)); g_skmonitor.sock = socket(AF_INET, SOCK_DGRAM, 0); if (g_skmonitor.sock == -1) { os_printf("socket monitor init failed\r\n"); return RET_ERR; } local_addr.sin_family = AF_INET; local_addr.sin_port = htons(SKMONITOR_PORT); local_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (bind(g_skmonitor.sock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) < 0) { closesocket(g_skmonitor.sock); os_printf("socket monitor init failed\r\n"); return RET_ERR; } os_mutex_init(&g_skmonitor.lock); os_sema_init(&g_skmonitor.run, 1); OS_WORK_INIT(&g_skmonitor.work, sock_monitor_work, 0); OS_TASK_INIT("skmntr", &g_skmonitor.task, sock_monitor_task, &g_skmonitor, OS_TASK_PRIORITY_NORMAL, NULL, 768); return RET_OK; }