diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a93531..0c854ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,5 +58,6 @@ add_custom_target("install-program" COMMAND ${CMAKE_COMMAND} ARGS -DCOMPONENT=Pr add_custom_target("install-profile" COMMAND ${CMAKE_COMMAND} ARGS -DCOMPONENT=Profile -P cmake_install.cmake) add_subdirectory(platform) +add_subdirectory(script) install(FILES conf/hasp-tools.conf DESTINATION /etc/ld.so.conf.d/ COMPONENT Profile) \ No newline at end of file diff --git a/cmake/PostInstall.in b/cmake/PostInstall.in new file mode 100644 index 0000000..e79abf8 --- /dev/null +++ b/cmake/PostInstall.in @@ -0,0 +1,2 @@ +%systemd_post hasp_monitor.service +/sbin/ldconfig \ No newline at end of file diff --git a/cmake/PostUninstall.in b/cmake/PostUninstall.in new file mode 100644 index 0000000..3020cd6 --- /dev/null +++ b/cmake/PostUninstall.in @@ -0,0 +1,2 @@ +%systemd_postun_with_restart hasp_monitor.service +/sbin/ldconfig \ No newline at end of file diff --git a/cmake/PreUninstall.in b/cmake/PreUninstall.in new file mode 100644 index 0000000..2f48288 --- /dev/null +++ b/cmake/PreUninstall.in @@ -0,0 +1 @@ +%systemd_preun hasp_monitor.service \ No newline at end of file diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 7319f95..9a5ce27 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -6,12 +6,12 @@ target_link_libraries(hasp_update ${CMAKE_SOURCE_DIR}/lib/libhasp_linux_x86_64_2 install(TARGETS hasp_update RUNTIME DESTINATION bin COMPONENT Program) # compile lib hasp-tools -add_library(hasp-tools SHARED src/hasp_verify.c) +add_library(hasp-tools SHARED src/hasp_verify.c src/hasp_shm.c) target_include_directories(hasp-tools PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) -target_link_libraries(hasp-tools pthread) +target_link_libraries(hasp-tools pthread rt) target_link_libraries(hasp-tools ${CMAKE_SOURCE_DIR}/lib/libhasp_linux_x86_64_25743.a) install(TARGETS hasp-tools LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/ COMPONENT LIBRARIES) install(FILES include/hasp_verify.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ COMPONENT LIBRARIES) # compile hasp_verify -add_subdirectory(test) \ No newline at end of file +add_subdirectory(tool) \ No newline at end of file diff --git a/platform/include/hasp_log.h b/platform/include/hasp_log.h new file mode 100644 index 0000000..70d1fc9 --- /dev/null +++ b/platform/include/hasp_log.h @@ -0,0 +1,69 @@ +#ifndef _HASP_LOG_H +#define _HASP_LOG_H + +#ifdef __cpluscplus +extern "C" +{ +#endif + +#include +#include + +#if ENABLD_LOG_FIEL +#define LOG_FILE(time, format, ...) \ + { \ + FILE *fp = fopen("licenses.log", "a+"); \ + if (fp == NULL) \ + { \ + break; \ + } \ + fprintf(fp, "%s " format "\n", time, ##__VA_ARGS__); \ + fflush(fp); \ + fclose(fp); \ + } +#else +#define LOG_FILE(time, format, ...) +#endif + +#define LOG_STOUT(time, format, ...) \ + { \ + fprintf(stderr, "%s " format "\n", time, ##__VA_ARGS__); \ + } + +#define LOG_INFO(format, ...) \ + do \ + { \ + char buffer[64] = {0}; \ + local_time_string(buffer, sizeof(buffer)); \ + LOG_STOUT(buffer, format, ##__VA_ARGS__); \ + LOG_FILE(buffer, format, ##__VA_ARGS__); \ + } while (0) + +static void local_time_string(char *buff, int size) +{ + static unsigned char weekday_str[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + static unsigned char month_str[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + time_t now; + struct tm local_time; + time(&now); + if (NULL == (localtime_r(&now, &local_time))) + { + return; + } + snprintf(buff, size, + "%s %s %d %02d:%02d:%02d %d", + weekday_str[local_time.tm_wday], + month_str[local_time.tm_mon], + local_time.tm_mday, + local_time.tm_hour, + local_time.tm_min, + local_time.tm_sec, + local_time.tm_year + 1900); +} + +#ifdef __cpluscplus +} +#endif + +#endif diff --git a/platform/include/hasp_shm.h b/platform/include/hasp_shm.h new file mode 100644 index 0000000..b595423 --- /dev/null +++ b/platform/include/hasp_shm.h @@ -0,0 +1,23 @@ +#ifndef _HASP_SHM_H +#define _HASP_SHM_H + +#ifdef __cpluscplus +extern "C" +{ +#endif + +struct hasp_shm; + +struct hasp_shm *hasp_shm_new(const char *name); +void hasp_shm_free(struct hasp_shm *shm); + +void hasp_shm_lock(struct hasp_shm *shm); +void hasp_shm_unlock(struct hasp_shm *shm); +void hasp_shm_write(struct hasp_shm *shm, char *data, int len); +void hasp_shm_read(struct hasp_shm *shm, char *buff, int size); + +#ifdef __cpluscplus +} +#endif + +#endif diff --git a/platform/include/hasp_verify.h b/platform/include/hasp_verify.h index 263755d..5528acd 100644 --- a/platform/include/hasp_verify.h +++ b/platform/include/hasp_verify.h @@ -8,7 +8,8 @@ extern "C" #include -void hasp_verify(uint64_t feature_id, uint64_t interval_s); +void hasp_monitor(uint64_t feature_id, uint64_t interval); +void hasp_verify(uint64_t feature_id); #ifdef __cpluscplus } diff --git a/platform/src/hasp_shm.c b/platform/src/hasp_shm.c new file mode 100644 index 0000000..0947f78 --- /dev/null +++ b/platform/src/hasp_shm.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include + +#include "hasp_log.h" + +#define MAX_SHM_BUFF_SIZE 4096 + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +struct hasp_shm +{ + pthread_mutex_t lock; + void *buff; + int size; +}; + +static void hasp_shm_lock_init(struct hasp_shm *shm) +{ + pthread_mutexattr_t ma; + pthread_mutexattr_init(&ma); + pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); + pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); + pthread_mutex_init(&shm->lock, &ma); +} + +struct hasp_shm *hasp_shm_new(const char *name) +{ + char path[256]; + char path_old[512]; + char path_new[512]; + + int size = sizeof(struct hasp_shm) + MAX_SHM_BUFF_SIZE; + int fd = shm_open(name, O_RDWR, 0777); + if (fd < 0) + { + sprintf(path, "%s.%d", name, getpid()); + fd = shm_open(path, O_CREAT | O_RDWR, 0777); + if (fd < 0) + { + LOG_INFO("hasp_shm: Unable create shared memory %s: fd %d, error %d: %s", name, fd, errno, strerror(errno)); + return NULL; + } + + if (ftruncate(fd, size) < 0) + { + LOG_INFO("hasp_shm: Unable truncate file %s, error %d: %s", path, errno, strerror(errno)); + return NULL; + } + + void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SEEK_SET); + if (addr == NULL) + { + LOG_INFO("hasp_shm: Unable mmap memory for file %s, error %d: %s", path, errno, strerror(errno)); + return NULL; + } + + memset(addr, 0, size); + hasp_shm_lock_init((struct hasp_shm *)addr); + munmap(addr, size); + + sprintf(path_old, "/dev/shm/%s", path); + sprintf(path_new, "/dev/shm/%s", name); + + int r = link(path_old, path_new); + LOG_INFO("hasp_shm: Create link(%s, %s): %d", path_old, path_new, r); + unlink(path_old); + + fd = shm_open(name, O_RDWR, 0777); + if (fd < 0) + { + LOG_INFO("hasp_shm: Unable create shared memory %s: fd %d, error %d: %s", name, fd, errno, strerror(errno)); + return NULL; + } + } + + struct hasp_shm *shm = (struct hasp_shm *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SEEK_SET); + if (shm == NULL) + { + LOG_INFO("hasp_shm: Unable mmap memory for fd %d, error %d: %s", fd, errno, strerror(errno)); + return NULL; + } + + shm->buff = (void *)shm + sizeof(struct hasp_shm); + shm->size = MAX_SHM_BUFF_SIZE; + + return shm; +} + +void hasp_shm_lock(struct hasp_shm *shm) +{ + if (pthread_mutex_lock(&shm->lock) == EOWNERDEAD) + { + pthread_mutex_consistent(&shm->lock); + LOG_INFO("hasp_shm: Mutex lock mark consistent"); + } +} + +void hasp_shm_unlock(struct hasp_shm *shm) +{ + pthread_mutex_unlock(&shm->lock); +} + +void hasp_shm_write(struct hasp_shm *shm, char *data, int len) +{ + int wlen = MIN(shm->size, len); + memset(shm->buff, 0, shm->size); + memcpy(shm->buff, data, wlen); +} + +void hasp_shm_read(struct hasp_shm *shm, char *buff, int size) +{ + int rlen = MIN(shm->size, size); + memset(buff, 0, size); + memcpy(buff, shm->buff, rlen); +} + +void hasp_shm_free(struct hasp_shm *shm) +{ + munmap(shm, sizeof(struct hasp_shm) + MAX_SHM_BUFF_SIZE); +} diff --git a/platform/src/hasp_verify.c b/platform/src/hasp_verify.c index d02532e..9352288 100644 --- a/platform/src/hasp_verify.c +++ b/platform/src/hasp_verify.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -8,63 +7,25 @@ #include "hasp_api.h" #include "hasp_vcode.h" - -#define LOG_STOUT(time, format, ...) \ - { \ - fprintf(stdout, "%s " format "\n", time, ##__VA_ARGS__); \ - } - -#if ENABLD_LOG_FIEL -#define LOG_FILE(time, format, ...) \ - { \ - FILE *fp = fopen("licenses.log", "a+"); \ - if (fp == NULL) \ - { \ - break; \ - } \ - fprintf(fp, "%s " format "\n", time, ##__VA_ARGS__); \ - fflush(fp); \ - fclose(fp); \ - } -#else -#define LOG_FILE(time, format, ...) -#endif - -#define LOG_INFO(format, ...) \ - do \ - { \ - char buffer[64] = {0}; \ - local_time_string(buffer, sizeof(buffer)); \ - LOG_STOUT(buffer, format, ##__VA_ARGS__); \ - LOG_FILE(buffer, format, ##__VA_ARGS__); \ - } while (0) +#include "hasp_log.h" +#include "hasp_shm.h" #define DEFAULT_INTERVAL_S (30 * 60) +#define MAX_INTERVAL_S (24 * 60 * 60) -static uint64_t g_interval_s = 0; -static uint64_t g_feature_id = 0; +static char *shm_key = "hasp_verify"; -static void local_time_string(char *buff, int size) +static uint64_t app_expect_feature_id = 0; + +/****************************************************************************** + * Utils + ******************************************************************************/ + +static uint64_t current_timestamp() { - static unsigned char weekday_str[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - static unsigned char month_str[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - time_t now; - struct tm local_time; - time(&now); - if (NULL == (localtime_r(&now, &local_time))) - { - return; - } - snprintf(buff, size, - "%s %s %d %02d:%02d:%02d %d", - weekday_str[local_time.tm_wday], - month_str[local_time.tm_mon], - local_time.tm_mday, - local_time.tm_hour, - local_time.tm_min, - local_time.tm_sec, - local_time.tm_year + 1900); + struct timespec temp; + clock_gettime(CLOCK_MONOTONIC, &temp); + return temp.tv_sec; } // return 0: error @@ -164,67 +125,113 @@ static int verify(uint64_t feature_id) return ret; } -// APP 启动时若 licenses 无效则直接退出 -// APP 启动后,每隔 g_interval_s 检查一次 licenses;如 2 * g_interval_s 时间内出现两次 licenses 无效则退出 -static void *thread_cycle(void *arg) +static void write_status(uint64_t feature_id, uint64_t status, uint64_t timestamp, uint64_t interva) { - uint64_t last_timestamp = 0; + char buff[4096] = {0}; + struct hasp_shm *shm = hasp_shm_new(shm_key); + snprintf(buff, sizeof(buff), "%ld\t%ld\t%ld\t%ld", feature_id, status, timestamp, interva); + hasp_shm_write(shm, buff, strlen(buff)); + hasp_shm_free(shm); +} - if (verify(g_feature_id) == 0) +static void read_status(char *buff, int size) +{ + struct hasp_shm *shm = hasp_shm_new(shm_key); + hasp_shm_read(shm, buff, size); + hasp_shm_free(shm); +} + +/****************************************************************************** + * For Hasp Verify Master Process + ******************************************************************************/ + +void hasp_monitor(uint64_t feature_id, uint64_t interval) +{ + if (interval >= MAX_INTERVAL_S) { - exit(0); + interval = MAX_INTERVAL_S; } + if (interval == 0) + { + interval = DEFAULT_INTERVAL_S; + } + + LOG_INFO("hasp_verify: Feature ID: %ld, Interval: %ld s", feature_id, interval); + while (1) { - sleep(g_interval_s); - - if (verify(g_feature_id) == 1) + if (verify(feature_id) == 1) { - continue; + write_status(feature_id, 1, current_timestamp(), interval); } - else - { - struct timespec current_ts; - clock_gettime(CLOCK_MONOTONIC, ¤t_ts); - if (last_timestamp == 0) - { - last_timestamp = current_ts.tv_sec; - continue; - } - - if (current_ts.tv_sec - last_timestamp < g_interval_s * 2) - { - exit(0); - } - else - { - last_timestamp = current_ts.tv_sec; - } - } + sleep(interval); } } -void hasp_verify(uint64_t feature_id, uint64_t interval_s) +/****************************************************************************** + * For Hasp Verify Slave Process + ******************************************************************************/ + +void *hasp_verify_cycle(void *arg) +{ + char buff[4096] = {0}; + int size = sizeof(buff); + + uint64_t feature_id = 0; + uint64_t status = 0; + uint64_t timestamp = 0; + uint64_t interva = 0; + + while (1) + { + read_status(buff, size); + + if (strlen(buff) == 0) + { + LOG_INFO("hasp_verify: Could not get shared data"); + exit(0); + } + + if (sscanf(buff, "%ld\t%ld\t%ld\t%ld", &feature_id, &status, ×tamp, &interva) != 4) + { + LOG_INFO("hasp_verify: Invalid shared data"); + exit(0); + } + + if (app_expect_feature_id != feature_id) + { + LOG_INFO("hasp_verify: Unexpected feature id"); + exit(0); + } + + if (current_timestamp() - timestamp > interva) + { + LOG_INFO("hasp_verify: Timestamp not updated for a long time"); + exit(0); + } + + if (status == 0) + { + LOG_INFO("hasp_verify: Invalid authorization information"); + exit(0); + } + + sleep(1); + } + + return NULL; +} + +void hasp_verify(uint64_t feature_id) { pthread_t tid; - - g_feature_id = feature_id; - if (interval_s == 0) + app_expect_feature_id = feature_id; + LOG_INFO("hasp_verify: Feature ID: %ld", app_expect_feature_id); + if (pthread_create(&tid, NULL, hasp_verify_cycle, NULL) < 0) { - g_interval_s = DEFAULT_INTERVAL_S; - } - else - { - g_interval_s = interval_s; - } - - LOG_INFO("hasp_verify: Feature ID: %ld, Check Interval %ld s", g_feature_id, g_interval_s); - - if (pthread_create(&tid, NULL, thread_cycle, NULL) < 0) - { - LOG_INFO("hasp_verify: unable to create thread, error %d: %s", errno, strerror(errno)); + LOG_INFO("hasp_verify: Unable create hasp verify thread, error %d: %s", errno, strerror(errno)); exit(0); } } \ No newline at end of file diff --git a/platform/test/CMakeLists.txt b/platform/test/CMakeLists.txt deleted file mode 100644 index 6914e4b..0000000 --- a/platform/test/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_definitions(-DENABLD_LOG_FIEL) -add_executable(hasp_verify ${CMAKE_SOURCE_DIR}/platform/src/hasp_verify.c ${CMAKE_SOURCE_DIR}/platform/test/hasp_verify_test.c) -target_include_directories(hasp_verify PUBLIC ${CMAKE_SOURCE_DIR}/platform/include/) -target_link_libraries(hasp_verify pthread) -target_link_libraries(hasp_verify ${CMAKE_SOURCE_DIR}/lib/libhasp_linux_x86_64_25743.a) -install(TARGETS hasp_verify RUNTIME DESTINATION bin COMPONENT Program) \ No newline at end of file diff --git a/platform/test/hasp_verify_test.c b/platform/test/hasp_verify_test.c deleted file mode 100644 index 8303ae8..0000000 --- a/platform/test/hasp_verify_test.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -#include "hasp_verify.h" - -int main(int argc, char **argv) -{ - uint64_t interval_s = 0; - uint64_t feature_id = 0; - if (argc != 3) - { - fprintf(stdout, "Usage: %s [feature_id] [interval_s]\n", argv[0]); - exit(0); - } - else - { - feature_id = atol(argv[1]); - interval_s = atol(argv[2]); - } - - hasp_verify(feature_id, interval_s); - - while (1) - { - sleep(1); - } - - return 0; -} \ No newline at end of file diff --git a/platform/tool/CMakeLists.txt b/platform/tool/CMakeLists.txt new file mode 100644 index 0000000..f730965 --- /dev/null +++ b/platform/tool/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(hasp_verify_demo ${CMAKE_SOURCE_DIR}/platform/tool/hasp_verify_demo.c) +target_link_libraries(hasp_verify_demo pthread rt hasp-tools) +install(TARGETS hasp_verify_demo RUNTIME DESTINATION bin COMPONENT Program) + +add_executable(hasp_monitor ${CMAKE_SOURCE_DIR}/platform/tool/hasp_monitor.c) +target_link_libraries(hasp_monitor pthread rt hasp-tools) +install(TARGETS hasp_monitor RUNTIME DESTINATION bin COMPONENT Program) \ No newline at end of file diff --git a/platform/tool/hasp_monitor.c b/platform/tool/hasp_monitor.c new file mode 100644 index 0000000..8940007 --- /dev/null +++ b/platform/tool/hasp_monitor.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "hasp_verify.h" + +static void usage(char *cmd) +{ + fprintf(stderr, "USAGE: %s [OPTIONS]\n", cmd); + fprintf(stderr, " -f -- set feature id\n"); + fprintf(stderr, " -i -- set interval second\n"); + fprintf(stderr, " -h -- show help\n"); +} + +int main(int argc, char **argv) +{ + int opt; + uint64_t interval_s = 0; + uint64_t feature_id = 100; + + while ((opt = getopt(argc, argv, "f:i:h")) != -1) + { + switch (opt) + { + case 'i': + interval_s = atoi(optarg); + break; + case 'f': + feature_id = atoi(optarg); + break; + case 'h': /* fall through */ + default: + usage(argv[0]); + return 0; + } + } + + hasp_monitor(feature_id, interval_s); + + return 0; +} diff --git a/platform/tool/hasp_verify_demo.c b/platform/tool/hasp_verify_demo.c new file mode 100644 index 0000000..df67b45 --- /dev/null +++ b/platform/tool/hasp_verify_demo.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "hasp_verify.h" + +static void usage(char *cmd) +{ + fprintf(stderr, "USAGE: %s [OPTIONS]\n", cmd); + fprintf(stderr, " -f -- set feature id\n"); + fprintf(stderr, " -h -- show help\n"); +} + +int main(int argc, char **argv) +{ + int opt; + uint64_t feature_id = 0; + + while ((opt = getopt(argc, argv, "f:h")) != -1) + { + switch (opt) + { + case 'f': + feature_id = atoi(optarg); + break; + case 'h': /* fall through */ + default: + usage(argv[0]); + return 0; + } + } + + hasp_verify(feature_id); + + while (1) + { + sleep(1); + } + + return 0; +} \ No newline at end of file diff --git a/script/CMakeLists.txt b/script/CMakeLists.txt new file mode 100644 index 0000000..780b02c --- /dev/null +++ b/script/CMakeLists.txt @@ -0,0 +1 @@ +install(FILES service/hasp_monitor.service DESTINATION /usr/lib/systemd/system/ COMPONENT Program) \ No newline at end of file diff --git a/script/service/hasp_monitor.service b/script/service/hasp_monitor.service new file mode 100644 index 0000000..ccc8382 --- /dev/null +++ b/script/service/hasp_monitor.service @@ -0,0 +1,6 @@ +[Unit] +Description=Hasp Monitor +After=network.target + +[Service] +ExecStart=/opt/tsg/hasp-tools/bin/hasp_monitor