From 388938e02bf33ce9a5cf329b93a2015cb4ccd9d8 Mon Sep 17 00:00:00 2001
From: cppla <i@cpp.la>
Date: Wed, 3 Apr 2024 16:39:08 +0800
Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=BA=86=E7=BD=91=E7=BB=9C?=
 =?UTF-8?q?=E9=97=AA=E6=96=AD=E5=AF=BC=E8=87=B4=E7=9A=84=E9=94=99=E8=AF=AF?=
 =?UTF-8?q?=E6=8A=A5=E8=AD=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 server/src/main.cpp | 110 +++++++++++++++++++++++++++++++++++++++++---
 server/src/main.h   |   4 +-
 2 files changed, 106 insertions(+), 8 deletions(-)

diff --git a/server/src/main.cpp b/server/src/main.cpp
index 9eb6a4a..743fe91 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -117,13 +117,9 @@ void CMain::OnDelClient(int ClientNetID)
 		Client(ClientID)->m_ClientNetType = NETTYPE_INVALID;
 		mem_zero(&Client(ClientID)->m_Stats, sizeof(CClient::CStats));
 	}
-    //copy offline message for watchdog
-    WatchdogMessage(ClientNetID,
-                    0, 0, 0, 0, 0, 0,
-                    0, 0, 0,0, 0, 0,
-                    0, 0, 0, 0, 0, 0,
-                    0, 0, 0,0, 0, 0,
-                    0, 0, 0, 0);
+    m_OfflineAlarmThreadData.pClients = m_aClients;
+    m_OfflineAlarmThreadData.pWatchDogs = m_aCWatchDogs;
+    thread_create(offlineAlarmThread, &m_OfflineAlarmThreadData);
 }
 
 int CMain::HandleMessage(int ClientNetID, char *pMessage)
@@ -503,6 +499,105 @@ void CMain::JSONUpdateThread(void *pUser)
     fs_rename(pConfig->m_aJSONFile, aJSONFileTmp);
 }
 
+void CMain::offlineAlarmThread(void *pUser)
+{
+    CJSONUpdateThreadData *m_OfflineAlarmThreadData = (CJSONUpdateThreadData *)pUser;
+    CClient *pClients = m_OfflineAlarmThreadData->pClients;
+    CWatchDog *pWatchDogs = m_OfflineAlarmThreadData->pWatchDogs;
+    thread_sleep(6000);
+    if(!pClients->m_Connected)
+    {
+        int ID = 0;
+        while (strcmp(pWatchDogs[ID].m_aName, "NULL"))
+        {
+            typedef exprtk::symbol_table<double> symbol_table_t;
+            typedef exprtk::expression<double>   expression_t;
+            typedef exprtk::parser<double>       parser_t;
+            const std::string expression_string = pWatchDogs[ID].m_aRule;
+            std::string username = pClients->m_aUsername;
+            std::string name = pClients->m_aName;
+            std::string type = pClients->m_aType;
+            std::string host = pClients->m_aHost;
+            std::string location = pClients->m_aLocation;
+            std::double_t online4 = pClients->m_Stats.m_Online4;
+            std::double_t online6 = pClients->m_Stats.m_Online6;
+
+            symbol_table_t symbol_table;
+            symbol_table.add_stringvar("username", username);
+            symbol_table.add_stringvar("name", name);
+            symbol_table.add_stringvar("type", type);
+            symbol_table.add_stringvar("host", host);
+            symbol_table.add_stringvar("location", location);
+            symbol_table.add_variable("online4",online4);
+            symbol_table.add_variable("online6",online6);
+            symbol_table.add_constants();
+
+            expression_t expression;
+            expression.register_symbol_table(symbol_table);
+
+            parser_t parser;
+            parser.compile(expression_string,expression);
+
+            if (expression.value() > 0)
+            {
+                time_t currentStamp = (long long)time(/*ago*/0);
+                if ((currentStamp-pClients->m_AlarmLastTime) > pWatchDogs[ID].m_aInterval)
+                {
+                    printf("客户端下线, Client disconnects and sends alert information\n");
+                    pClients->m_AlarmLastTime = currentStamp;
+                    CURL *curl;
+                    CURLcode res;
+                    curl_global_init(CURL_GLOBAL_ALL);
+
+                    curl = curl_easy_init();
+                    if(curl) {
+                        //standard time
+                        char standardTime[32]= { 0 };
+                        strftime(standardTime, sizeof(standardTime), "%Y-%m-%d %H:%M:%S",localtime(&currentStamp));
+
+                        //url encode, Rules conflict with url special characters,eg:&, del rules, by https://cpp.la, 2023-10-09
+                        char encodeBuffer[2048] = { 0 };
+                        sprintf(encodeBuffer, "【告警名称】 %s \n\n【告警时间】 %s  \n\n【用户名】 %s \n\n【节点名】 %s \n\n【虚拟化】 %s \n\n【主机名】 %s \n\n【位  置】 %s",
+                                pWatchDogs[ID].m_aName,
+                                standardTime,
+                                pClients->m_aUsername,
+                                pClients->m_aName,
+                                pClients->m_aType,
+                                pClients->m_aHost,
+                                pClients->m_aLocation);
+                        char *encodeUrl = curl_easy_escape(curl, encodeBuffer, strlen(encodeBuffer));
+
+                        //standard url
+                        char urlBuffer[2048] = { 0 };
+                        sprintf(urlBuffer, "%s%s",pWatchDogs[ID].m_aCallback, encodeUrl);
+
+
+                        curl_easy_setopt(curl, CURLOPT_POST, 1L);
+                        curl_easy_setopt(curl, CURLOPT_URL, urlBuffer);
+                        curl_easy_setopt(curl, CURLOPT_POSTFIELDS,"signature=ServerStatus");
+                        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+                        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
+                        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
+                        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 6L);
+                        res = curl_easy_perform(curl);
+                        if(res != CURLE_OK)
+                            fprintf(stderr, "watchdog failed: %s\n", curl_easy_strerror(res));
+                        if(encodeUrl)
+                            curl_free(encodeUrl);
+                        curl_easy_cleanup(curl);
+                    }
+                    curl_global_cleanup();
+                }
+            }
+            ID++;
+        }
+    }
+    else
+    {
+        printf("网络波动,No alarm information is sent due to network fluctuations\n");
+    }
+}
+
 int CMain::ReadConfig()
 {
 	// read and parse config
@@ -701,6 +796,7 @@ int CMain::Run()
 	m_JSONUpdateThreadData.m_ReloadRequired = 2;
 	m_JSONUpdateThreadData.pClients = m_aClients;
 	m_JSONUpdateThreadData.pConfig = &m_Config;
+    m_JSONUpdateThreadData.pWatchDogs = m_aCWatchDogs;
 	void *LoadThread = thread_create(JSONUpdateThread, &m_JSONUpdateThreadData);
 	//thread_detach(LoadThread);
 
diff --git a/server/src/main.h b/server/src/main.h
index 848d246..3649661 100644
--- a/server/src/main.h
+++ b/server/src/main.h
@@ -101,10 +101,12 @@ class CMain
 	{
 		CClient *pClients;
 		CConfig *pConfig;
+        CWatchDog *pWatchDogs;
 		volatile short m_ReloadRequired;
-	} m_JSONUpdateThreadData;
+	} m_JSONUpdateThreadData, m_OfflineAlarmThreadData;
 
 	static void JSONUpdateThread(void *pUser);
+    static void offlineAlarmThread(void *pUser);
 public:
 	CMain(CConfig Config);