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 "comms.h"
22 #include "db.h"
23 #include "log.h"
24 #include "daemon.h"
25 #include "zbxjson.h"
26 #include "proxy.h"
27 #include "zbxself.h"
28 #include "dbcache.h"
29 
30 #include "datasender.h"
31 #include "../servercomms.h"
32 #include "../../libs/zbxcrypto/tls.h"
33 
34 extern unsigned char	process_type, program_type;
35 extern int		server_num, process_num;
36 
37 /******************************************************************************
38  *                                                                            *
39  * Function: host_availability_sender                                         *
40  *                                                                            *
41  ******************************************************************************/
host_availability_sender(struct zbx_json * j)42 static void	host_availability_sender(struct zbx_json *j)
43 {
44 	const char	*__function_name = "host_availability_sender";
45 	zbx_socket_t	sock;
46 	int		ts;
47 
48 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
49 
50 	zbx_json_clean(j);
51 	zbx_json_addstring(j, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_HOST_AVAILABILITY, ZBX_JSON_TYPE_STRING);
52 	zbx_json_addstring(j, ZBX_PROTO_TAG_HOST, CONFIG_HOSTNAME, ZBX_JSON_TYPE_STRING);
53 
54 	if (SUCCEED == get_host_availability_data(j, &ts))
55 	{
56 		char	*error = NULL;
57 
58 		connect_to_server(&sock, 600, CONFIG_PROXYDATA_FREQUENCY); /* retry till have a connection */
59 
60 		if (SUCCEED != put_data_to_server(&sock, j, &error))
61 		{
62 			zabbix_log(LOG_LEVEL_WARNING, "cannot send host availability data to server at \"%s\": %s",
63 					sock.peer, error);
64 		}
65 		else
66 			zbx_set_availability_diff_ts(ts);
67 
68 		zbx_free(error);
69 		disconnect_server(&sock);
70 	}
71 
72 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
73 }
74 
75 /******************************************************************************
76  *                                                                            *
77  * Function: history_sender                                                   *
78  *                                                                            *
79  ******************************************************************************/
history_sender(struct zbx_json * j,int * records,const char * tag,int (* f_get_data)(),void (* f_set_lastid)())80 static void	history_sender(struct zbx_json *j, int *records, const char *tag,
81 		int (*f_get_data)(), void (*f_set_lastid)())
82 {
83 	const char	*__function_name = "history_sender";
84 
85 	zbx_socket_t	sock;
86 	zbx_uint64_t	lastid;
87 	zbx_timespec_t	ts;
88 	int		ret = SUCCEED;
89 
90 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
91 
92 	zbx_json_clean(j);
93 	zbx_json_addstring(j, ZBX_PROTO_TAG_REQUEST, tag, ZBX_JSON_TYPE_STRING);
94 	zbx_json_addstring(j, ZBX_PROTO_TAG_HOST, CONFIG_HOSTNAME, ZBX_JSON_TYPE_STRING);
95 
96 	zbx_json_addarray(j, ZBX_PROTO_TAG_DATA);
97 
98 	*records = f_get_data(j, &lastid);
99 
100 	zbx_json_close(j);
101 
102 	if (*records > 0)
103 	{
104 		char	*error = NULL;
105 
106 		connect_to_server(&sock, 600, CONFIG_PROXYDATA_FREQUENCY); /* retry till have a connection */
107 
108 		zbx_timespec(&ts);
109 		zbx_json_adduint64(j, ZBX_PROTO_TAG_CLOCK, ts.sec);
110 		zbx_json_adduint64(j, ZBX_PROTO_TAG_NS, ts.ns);
111 
112 		if (SUCCEED != (ret = put_data_to_server(&sock, j, &error)))
113 		{
114 			*records = 0;
115 			zabbix_log(LOG_LEVEL_WARNING, "cannot send history data to server at \"%s\": %s",
116 					sock.peer, error);
117 		}
118 
119 		zbx_free(error);
120 		disconnect_server(&sock);
121 	}
122 
123 	if (SUCCEED == ret && 0 != lastid)
124 	{
125 		DBbegin();
126 		f_set_lastid(lastid);
127 		DBcommit();
128 	}
129 
130 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
131 }
132 
133 /******************************************************************************
134  *                                                                            *
135  * Function: main_datasender_loop                                             *
136  *                                                                            *
137  * Purpose: periodically sends history and events to the server               *
138  *                                                                            *
139  ******************************************************************************/
ZBX_THREAD_ENTRY(datasender_thread,args)140 ZBX_THREAD_ENTRY(datasender_thread, args)
141 {
142 	int		records = 0, r;
143 	double		sec = 0.0;
144 	struct zbx_json	j;
145 
146 	process_type = ((zbx_thread_args_t *)args)->process_type;
147 	server_num = ((zbx_thread_args_t *)args)->server_num;
148 	process_num = ((zbx_thread_args_t *)args)->process_num;
149 
150 	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
151 			server_num, get_process_type_string(process_type), process_num);
152 
153 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
154 	zbx_tls_init_child();
155 #endif
156 	zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));
157 
158 	DBconnect(ZBX_DB_CONNECT_NORMAL);
159 
160 	zbx_json_init(&j, 16 * ZBX_KIBIBYTE);
161 
162 	for (;;)
163 	{
164 		zbx_handle_log();
165 
166 		zbx_setproctitle("%s [sent %d values in " ZBX_FS_DBL " sec, sending data]",
167 				get_process_type_string(process_type), records, sec);
168 
169 		sec = zbx_time();
170 		host_availability_sender(&j);
171 
172 		records = 0;
173 retry_history:
174 		history_sender(&j, &r, ZBX_PROTO_VALUE_HISTORY_DATA,
175 				proxy_get_hist_data, proxy_set_hist_lastid);
176 		records += r;
177 
178 		if (ZBX_MAX_HRECORDS <= r)
179 			goto retry_history;
180 retry_dhistory:
181 		history_sender(&j, &r, ZBX_PROTO_VALUE_DISCOVERY_DATA,
182 				proxy_get_dhis_data, proxy_set_dhis_lastid);
183 		records += r;
184 
185 		if (ZBX_MAX_HRECORDS <= r)
186 			goto retry_dhistory;
187 retry_autoreg_host:
188 		history_sender(&j, &r, ZBX_PROTO_VALUE_AUTO_REGISTRATION_DATA,
189 				proxy_get_areg_data, proxy_set_areg_lastid);
190 		records += r;
191 
192 		if (ZBX_MAX_HRECORDS <= r)
193 			goto retry_autoreg_host;
194 
195 		sec = zbx_time() - sec;
196 
197 		zbx_setproctitle("%s [sent %d values in " ZBX_FS_DBL " sec, idle %d sec]",
198 				get_process_type_string(process_type), records, sec, CONFIG_PROXYDATA_FREQUENCY);
199 
200 		zbx_sleep_loop(CONFIG_PROXYDATA_FREQUENCY);
201 
202 #if !defined(_WINDOWS) && defined(HAVE_RESOLV_H)
203 		zbx_update_resolver_conf();	/* handle /etc/resolv.conf update */
204 #endif
205 	}
206 }
207