#include #include #include #include #include #include #include #include #include #include #include struct watchdog_3rd_device { struct tfe_proxy *proxy; void *logger; const char *profile; pthread_t pthread; unsigned int http_keepalive_enable; unsigned int http_keepalive_port; char http_keepalive_path[TFE_PATH_MAX]; char http_keepalive_addr[TFE_SYMBOL_MAX]; }; static long long g_steering_device_is_available = 1; static int http_keepalive(struct watchdog_3rd_device *__ctx) { static char req_buff[1024] = { 0 }; static char rsp_buff[4096] = { 0 }; struct sockaddr_in addr; const char *expect= "HTTP/1.1 200 OK"; char http_head[] = "GET %s HTTP/1.1\r\n" "Host: %s:%d\r\n" "User-Agent: curl/7.47.0\r\n" "Accept: */*\r\n\r\n"; sprintf(req_buff, http_head, __ctx->http_keepalive_path, __ctx->http_keepalive_addr, __ctx->http_keepalive_port); int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { TFE_LOG_ERROR(__ctx->logger, "Watchdog 3rd thread fail to create socket(), %s", strerror(errno)); goto error; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(__ctx->http_keepalive_port); addr.sin_addr.s_addr = inet_addr(__ctx->http_keepalive_addr); if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(addr)) == -1) { TFE_LOG_ERROR(__ctx->logger, "Watchdog 3rd thread fail to connect(), %s", strerror(errno)); goto error; } if (write(sockfd, req_buff, strlen(req_buff)) == -1) { TFE_LOG_ERROR(__ctx->logger, "Watchdog 3rd thread fail to write(), %s", strerror(errno)); goto error; } if (read(sockfd, rsp_buff, sizeof(rsp_buff)) == -1) { TFE_LOG_ERROR(__ctx->logger, "Watchdog 3rd thread fail to read(), %s", strerror(errno)); goto error; } if (strncmp(rsp_buff, expect, strlen(expect)) != 0) { TFE_LOG_ERROR(__ctx->logger, "Watchdog 3rd thread get unexpect http response"); goto error; } close(sockfd); return 0; error: if (sockfd) { close(sockfd); } return -1; } static void * watchdog_3rd_device_thread(void * arg) { struct watchdog_3rd_device * __ctx = (struct watchdog_3rd_device *)arg; char thread_name[16]; snprintf(thread_name, sizeof(thread_name), "watchdog:3rd"); prctl(PR_SET_NAME, (unsigned long long)thread_name, NULL, NULL, NULL); while (1) { if (http_keepalive(__ctx) == -1) { ATOMIC_ZERO(&g_steering_device_is_available); TFE_LOG_ERROR(__ctx->logger, "Watchdog 3rd thread on fail: 3rd steering device is unavailable !!!"); } else { ATOMIC_INC(&g_steering_device_is_available); } sleep(1); } TFE_LOG_ERROR(__ctx->logger, "Watchdog 3rd thread exit"); return NULL; } int steering_device_is_available() { return ATOMIC_READ(&g_steering_device_is_available); } struct watchdog_3rd_device *watchdog_3rd_device_create(struct tfe_proxy *proxy, const char *profile, void *logger) { struct watchdog_3rd_device *__ctx = ALLOC(struct watchdog_3rd_device, 1); __ctx->proxy = proxy; __ctx->logger = logger; __ctx->profile = profile; MESA_load_profile_uint_def(profile, "traffic_steering", "http_keepalive_enable", &(__ctx->http_keepalive_enable), 0); MESA_load_profile_uint_def(profile, "traffic_steering", "http_keepalive_port", &(__ctx->http_keepalive_port), 80); MESA_load_profile_string_def(profile, "traffic_steering", "http_keepalive_path", __ctx->http_keepalive_path, sizeof(__ctx->http_keepalive_path), "/"); MESA_load_profile_string_def(profile, "traffic_steering", "http_keepalive_addr", __ctx->http_keepalive_addr, sizeof(__ctx->http_keepalive_addr), "127.0.0.1"); if (!__ctx->http_keepalive_enable) { return __ctx; } if (pthread_create(&__ctx->pthread, NULL, watchdog_3rd_device_thread, (void *)__ctx) < 0) { TFE_LOG_ERROR(__ctx->logger, "Fail to create 3rd watchdog thread: %s", strerror(errno)); return NULL; } TFE_LOG_INFO(__ctx->logger, "Watchdog 3rd module init successfully."); return __ctx; };