1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "daemon.h"
22 #include "log.h"
23 #include "zbxjson.h"
24 #include "zbxself.h"
25
26 #include "heart.h"
27 #include "../servercomms.h"
28 #include "zbxcrypto.h"
29 #include "zbxcompress.h"
30
31 extern unsigned char process_type, program_type;
32 extern int server_num, process_num;
33
34 /******************************************************************************
35 * *
36 * Function: send_heartbeat *
37 * *
38 ******************************************************************************/
send_heartbeat(void)39 static int send_heartbeat(void)
40 {
41 zbx_socket_t sock;
42 struct zbx_json j;
43 int ret = SUCCEED;
44 char *error = NULL, *buffer = NULL;
45 size_t buffer_size, reserved;
46
47 zabbix_log(LOG_LEVEL_DEBUG, "In send_heartbeat()");
48
49 zbx_json_init(&j, 128);
50 zbx_json_addstring(&j, "request", ZBX_PROTO_VALUE_PROXY_HEARTBEAT, ZBX_JSON_TYPE_STRING);
51 zbx_json_addstring(&j, "host", CONFIG_HOSTNAME, ZBX_JSON_TYPE_STRING);
52 zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING);
53
54 if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size))
55 {
56 zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror());
57 goto clean;
58 }
59
60 reserved = j.buffer_size;
61
62 if (FAIL == (ret = connect_to_server(&sock, CONFIG_HEARTBEAT_FREQUENCY, 0))) /* do not retry */
63 goto clean;
64
65 if (SUCCEED != (ret = put_data_to_server(&sock, &buffer, buffer_size, reserved, &error)))
66 {
67 zabbix_log(LOG_LEVEL_WARNING, "cannot send heartbeat message to server at \"%s\": %s", sock.peer,
68 error);
69 }
70
71 disconnect_server(&sock);
72 zbx_free(error);
73 clean:
74 zbx_free(buffer);
75 zbx_json_free(&j);
76
77 return ret;
78 }
79
80 /******************************************************************************
81 * *
82 * Function: main_heart_loop *
83 * *
84 * Purpose: periodically send heartbeat message to the server *
85 * *
86 ******************************************************************************/
ZBX_THREAD_ENTRY(heart_thread,args)87 ZBX_THREAD_ENTRY(heart_thread, args)
88 {
89 int start, sleeptime = 0, res;
90 double sec, total_sec = 0.0, old_total_sec = 0.0;
91 time_t last_stat_time;
92
93 #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */
94 /* once in STAT_INTERVAL seconds */
95
96 process_type = ((zbx_thread_args_t *)args)->process_type;
97 server_num = ((zbx_thread_args_t *)args)->server_num;
98 process_num = ((zbx_thread_args_t *)args)->process_num;
99
100 zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
101 server_num, get_process_type_string(process_type), process_num);
102
103 update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
104
105 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
106 zbx_tls_init_child();
107 #endif
108 last_stat_time = time(NULL);
109
110 zbx_setproctitle("%s [sending heartbeat message]", get_process_type_string(process_type));
111
112 while (ZBX_IS_RUNNING())
113 {
114 sec = zbx_time();
115 zbx_update_env(sec);
116
117 if (0 != sleeptime)
118 {
119 zbx_setproctitle("%s [sending heartbeat message %s in " ZBX_FS_DBL " sec, "
120 "sending heartbeat message]",
121 get_process_type_string(process_type),
122 SUCCEED == res ? "success" : "failed", old_total_sec);
123 }
124
125 start = time(NULL);
126 res = send_heartbeat();
127 total_sec += zbx_time() - sec;
128
129 sleeptime = CONFIG_HEARTBEAT_FREQUENCY - (time(NULL) - start);
130
131 if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time)
132 {
133 if (0 == sleeptime)
134 {
135 zbx_setproctitle("%s [sending heartbeat message %s in " ZBX_FS_DBL " sec, "
136 "sending heartbeat message]",
137 get_process_type_string(process_type),
138 SUCCEED == res ? "success" : "failed", total_sec);
139
140 }
141 else
142 {
143 zbx_setproctitle("%s [sending heartbeat message %s in " ZBX_FS_DBL " sec, "
144 "idle %d sec]",
145 get_process_type_string(process_type),
146 SUCCEED == res ? "success" : "failed", total_sec, sleeptime);
147
148 old_total_sec = total_sec;
149 }
150 total_sec = 0.0;
151 last_stat_time = time(NULL);
152 }
153
154 zbx_sleep_loop(sleeptime);
155 }
156
157 zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num);
158
159 while (1)
160 zbx_sleep(SEC_PER_MIN);
161 #undef STAT_INTERVAL
162 }
163