/* ** Copyright (C) 2001-2025 Zabbix SIA ** ** This program is free software: you can redistribute it and/or modify it under the terms of ** the GNU Affero General Public License as published by the Free Software Foundation, version 3. ** ** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU Affero General Public License for more details. ** ** You should have received a copy of the GNU Affero General Public License along with this program. ** If not, see <https://www.gnu.org/licenses/>. **/ #include "proxypoller.h" #include "proxyconfigread/proxyconfigread.h" #include "trapper/trapper_server.h" #include "cachehistory/cachehistory_server.h" #include "discovery/discovery_server.h" #include "autoreg/autoreg_server.h" #include "zbxexpression.h" #include "zbxdbwrap.h" #include "zbxnix.h" #include "zbxself.h" #include "zbxdbhigh.h" #include "zbxlog.h" #include "zbxcompress.h" #include "zbxrtc.h" #include "zbxcommshigh.h" #include "zbxnum.h" #include "zbxtime.h" #include "zbxversion.h" #include "zbx_rtc_constants.h" #include "zbxcacheconfig.h" #include "zbxipcservice.h" #include "zbxjson.h" static zbx_get_program_type_f zbx_get_program_type_cb = NULL; static int connect_to_proxy(const zbx_dc_proxy_t *proxy, zbx_socket_t *sock, int timeout, const char *config_source_ip) { int ret = FAIL; const char *tls_arg1, *tls_arg2; zabbix_log(LOG_LEVEL_DEBUG, "In %s() address:%s port:%hu timeout:%d conn:%u", __func__, proxy->addr, proxy->port, timeout, (unsigned int)proxy->tls_connect); switch (proxy->tls_connect) { case ZBX_TCP_SEC_UNENCRYPTED: tls_arg1 = NULL; tls_arg2 = NULL; break; #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) case ZBX_TCP_SEC_TLS_CERT: tls_arg1 = proxy->tls_issuer; tls_arg2 = proxy->tls_subject; break; case ZBX_TCP_SEC_TLS_PSK: tls_arg1 = proxy->tls_psk_identity; tls_arg2 = proxy->tls_psk; break; #else case ZBX_TCP_SEC_TLS_CERT: case ZBX_TCP_SEC_TLS_PSK: zabbix_log(LOG_LEVEL_ERR, "TLS connection is configured to be used with passive proxy \"%s\"" " but support for TLS was not compiled into %s.", proxy->name, get_program_type_string(zbx_get_program_type_cb())); ret = CONFIG_ERROR; goto out; #endif default: THIS_SHOULD_NEVER_HAPPEN; goto out; } if (FAIL == (ret = zbx_tcp_connect(sock, config_source_ip, proxy->addr, proxy->port, timeout, proxy->tls_connect, tls_arg1, tls_arg2))) { zabbix_log(LOG_LEVEL_ERR, "cannot connect to proxy \"%s\": %s", proxy->name, zbx_socket_strerror()); ret = NETWORK_ERROR; } out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } static int send_data_to_proxy(const zbx_dc_proxy_t *proxy, zbx_socket_t *sock, const char *data, size_t size, size_t reserved, int flags) { int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (FAIL == (ret = zbx_tcp_send_ext(sock, data, size, reserved, flags, 0))) { zabbix_log(LOG_LEVEL_ERR, "cannot send data to proxy \"%s\": %s", proxy->name, zbx_socket_strerror()); ret = NETWORK_ERROR; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } static int recv_data_from_proxy(const zbx_dc_proxy_t *proxy, zbx_socket_t *sock) { int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (FAIL == (ret = zbx_tcp_recv(sock))) { zabbix_log(LOG_LEVEL_ERR, "cannot obtain data from proxy \"%s\": %s", proxy->name, zbx_socket_strerror()); } else { zabbix_log(LOG_LEVEL_DEBUG, "obtained data from proxy \"%s\": [%s]", proxy->name, sock->buffer); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } static void disconnect_proxy(zbx_socket_t *sock) { zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); zbx_tcp_close(sock); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } /******************************************************************************** * * * Purpose: get historical data from proxy * * * * Parameters: proxy - [IN/OUT] proxy data * * request - [IN] requested data type * * config_timeout - [IN] * * config_trapper_timeout - [IN] * * config_source_ip - [IN] * * data - [OUT] data received from proxy * * ts - [OUT] timestamp when the proxy * * connection was established * * * * Return value: SUCCESS - processed successfully * * other code - an error occurred * * * * Comments: The proxy->compress property is updated depending on the * * protocol flags sent by proxy. * * * ********************************************************************************/ static int get_data_from_proxy(zbx_dc_proxy_t *proxy, const char *request, int config_timeout, int config_trapper_timeout, const char *config_source_ip, char **data, zbx_timespec_t *ts) { zbx_socket_t s; struct zbx_json j; int ret, flags = ZBX_TCP_PROTOCOL | ZBX_TCP_COMPRESS; char *buffer = NULL; size_t buffer_size, reserved = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s() request:'%s'", __func__, request); zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&j, "request", request, ZBX_JSON_TYPE_STRING); if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size)) { zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror()); ret = FAIL; goto out; } reserved = j.buffer_size; zbx_json_free(&j); /* json buffer can be large, free as fast as possible */ if (SUCCEED == (ret = connect_to_proxy(proxy, &s, config_trapper_timeout, config_source_ip))) { /* get connection timestamp if required */ if (NULL != ts) zbx_timespec(ts); ret = send_data_to_proxy(proxy, &s, buffer, buffer_size, reserved, flags); zbx_free(buffer); if (SUCCEED == ret) { if (SUCCEED == (ret = recv_data_from_proxy(proxy, &s))) { if (!ZBX_IS_RUNNING()) { int flags_response = ZBX_TCP_PROTOCOL; if (0 != (s.protocol & ZBX_TCP_COMPRESS)) flags_response |= ZBX_TCP_COMPRESS; zbx_send_response_ext(&s, FAIL, "Zabbix server shutdown in progress", NULL, flags_response, config_timeout); zabbix_log(LOG_LEVEL_WARNING, "cannot process proxy data from passive proxy at" " \"%s\": Zabbix server shutdown in progress", s.peer); ret = FAIL; } else { ret = zbx_send_proxy_data_response(proxy, &s, NULL, SUCCEED, ZBX_PROXY_UPLOAD_UNDEFINED, 0); if (SUCCEED == ret) *data = zbx_strdup(*data, s.buffer); } } } disconnect_proxy(&s); } out: zbx_json_free(&j); zbx_free(buffer); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } /****************************************************************************** * * * Purpose: sends configuration data to proxy * * * * Parameters: proxy - [IN/OUT] proxy data * * config_vault - [IN] * * config_trapper_timeout - [IN] * * config_source_ip - [IN] * * config_ssl_ca_location - [IN] * * config_ssl_cert_location - [IN] * * config_ssl_key_location - [IN] * * * * Return value: SUCCEED - processed successfully * * other code - an error occurred * * * * Comments: This function updates proxy version, compress and lastaccess * * properties. * * * ******************************************************************************/ static int proxy_send_configuration(zbx_dc_proxy_t *proxy, const zbx_config_vault_t *config_vault, int config_trapper_timeout, const char *config_source_ip, const char *config_ssl_ca_location, const char *config_ssl_cert_location, const char *config_ssl_key_location) { char *error = NULL, *buffer = NULL; int ret, flags = ZBX_TCP_PROTOCOL | ZBX_TCP_COMPRESS, loglevel; zbx_socket_t s; struct zbx_json j; struct zbx_json_parse jp; size_t buffer_size, reserved = 0; zbx_proxyconfig_status_t status = ZBX_PROXYCONFIG_STATUS_DATA; zbx_json_init(&j, 512 * ZBX_KIBIBYTE); zbx_json_addstring(&j, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_PROXY_CONFIG, ZBX_JSON_TYPE_STRING); if (SUCCEED != (ret = connect_to_proxy(proxy, &s, config_trapper_timeout, config_source_ip))) goto out; if (SUCCEED != (ret = send_data_to_proxy(proxy, &s, j.buffer, j.buffer_size, reserved, ZBX_TCP_PROTOCOL))) goto clean; if (FAIL == (ret = zbx_tcp_recv_ext(&s, 0, 0))) { zabbix_log(LOG_LEVEL_WARNING, "cannot receive configuration information from proxy \"%s\": %s", proxy->name, zbx_socket_strerror()); goto clean; } if (SUCCEED != (ret = zbx_json_open(s.buffer, &jp))) { zabbix_log(LOG_LEVEL_WARNING, "cannot parse configuration information from proxy \"%s\": %s", proxy->name, zbx_socket_strerror()); goto clean; } zbx_json_clean(&j); if (SUCCEED != (ret = zbx_proxyconfig_get_data(proxy, &jp, &j, &status, config_vault, config_source_ip, config_ssl_ca_location, config_ssl_cert_location, config_ssl_key_location, &error))) { zabbix_log(LOG_LEVEL_ERR, "cannot collect configuration data for proxy \"%s\": %s", proxy->name, error); goto clean; } if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size)) { zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror()); ret = FAIL; goto clean; } reserved = j.buffer_size; zbx_json_free(&j); /* json buffer can be large, free as fast as possible */ loglevel = (ZBX_PROXYCONFIG_STATUS_DATA == status ? LOG_LEVEL_WARNING : LOG_LEVEL_DEBUG); zabbix_log(loglevel, "sending configuration data to proxy \"%s\" at \"%s\", datalen " ZBX_FS_SIZE_T ", bytes " ZBX_FS_SIZE_T " with compression ratio %.1f", proxy->name, s.peer, (zbx_fs_size_t)reserved, (zbx_fs_size_t)buffer_size, (double)reserved / buffer_size); ret = send_data_to_proxy(proxy, &s, buffer, buffer_size, reserved, flags); zbx_free(buffer); /* json buffer can be large, free as fast as possible */ if (SUCCEED == ret) { if (SUCCEED != (ret = zbx_recv_response(&s, 0, &error))) { zabbix_log(LOG_LEVEL_WARNING, "cannot send configuration data to proxy" " \"%s\" at \"%s\": %s", proxy->name, s.peer, error); } else { if (SUCCEED != zbx_json_open(s.buffer, &jp)) { zabbix_log(LOG_LEVEL_WARNING, "invalid configuration data response received from proxy" " \"%s\" at \"%s\": %s", proxy->name, s.peer, zbx_json_strerror()); } else { char *version_str; version_str = zbx_get_proxy_protocol_version_str(&jp); zbx_strlcpy(proxy->version_str, version_str, sizeof(proxy->version_str)); proxy->version_int = zbx_get_proxy_protocol_version_int(version_str); proxy->lastaccess = time(NULL); zbx_free(version_str); } } } clean: disconnect_proxy(&s); out: zbx_free(buffer); zbx_free(error); zbx_json_free(&j); #ifdef HAVE_MALLOC_TRIM /* avoid memory not being released back to the system if large proxy configuration is retrieved from database */ if (ZBX_PROXYCONFIG_STATUS_DATA == status) malloc_trim(ZBX_MALLOC_TRIM); #endif return ret; } /****************************************************************************** * * * Purpose: processes proxy data request * * * * Parameters: proxy - [IN/OUT] proxy data * * answer - [IN] data received from proxy * * ts - [IN] timestamp when the proxy connection * * was established * * events_cbs - [IN] * * proxydata_frequency - [IN] * * more - [OUT] available data flag * * * * Return value: SUCCEED - data were received and processed successfully * * FAIL - otherwise * * * * Comments: The proxy->version property is updated with the version number * * sent by proxy. * * * ******************************************************************************/ static int proxy_process_proxy_data(zbx_dc_proxy_t *proxy, const char *answer, zbx_timespec_t *ts, const zbx_events_funcs_t *events_cbs, int proxydata_frequency, int *more) { struct zbx_json_parse jp; char *error = NULL, *version_str = NULL; int version_int, ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); *more = ZBX_PROXY_DATA_DONE; if ('\0' == *answer) { zabbix_log(LOG_LEVEL_WARNING, "proxy \"%s\" at \"%s\" returned no proxy data:" " check allowed connection types and access rights", proxy->name, proxy->addr); goto out; } if (SUCCEED != zbx_json_open(answer, &jp)) { zabbix_log(LOG_LEVEL_WARNING, "proxy \"%s\" at \"%s\" returned invalid proxy data: %s", proxy->name, proxy->addr, zbx_json_strerror()); goto out; } version_str = zbx_get_proxy_protocol_version_str(&jp); version_int = zbx_get_proxy_protocol_version_int(version_str); zbx_strlcpy(proxy->version_str, version_str, sizeof(proxy->version_str)); proxy->version_int = version_int; if (SUCCEED != zbx_check_protocol_version(proxy, version_int)) { goto out; } if (SUCCEED != (ret = zbx_process_proxy_data(proxy, &jp, ts, PROXY_OPERATING_MODE_PASSIVE, events_cbs, proxydata_frequency, zbx_discovery_update_host_server, zbx_discovery_update_service_server, zbx_discovery_update_service_down_server, zbx_discovery_find_host_server, zbx_discovery_update_drule_server, zbx_autoreg_host_free_server, (zbx_autoreg_flush_hosts_func_t)zbx_autoreg_flush_hosts_server, (zbx_autoreg_prepare_host_func_t)zbx_autoreg_prepare_host_server, more, &error))) { zabbix_log(LOG_LEVEL_WARNING, "proxy \"%s\" at \"%s\" returned invalid proxy data: %s", proxy->name, proxy->addr, error); } out: zbx_free(error); zbx_free(version_str); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } /****************************************************************************** * * * Purpose: gets data from proxy ('proxy data' request) * * * * Parameters: proxy - [IN/OUT] proxy data * * config_timeout - [IN] * * config_trapper_timeout - [IN] * * events_cbs - [IN] * * proxydata_frequency - [IN] * * config_source_ip - [IN] * * more - [OUT] available data flag * * * * Return value: SUCCEED - data were received and processed successfully * * other code - an error occurred * * * * Comments: This function updates proxy version, compress and lastaccess * * properties. * * * ******************************************************************************/ static int proxy_get_data(zbx_dc_proxy_t *proxy, int config_timeout, int config_trapper_timeout, const zbx_events_funcs_t *events_cbs, int proxydata_frequency, const char *config_source_ip, int *more) { char *answer = NULL; int ret; zbx_timespec_t ts; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (SUCCEED != (ret = get_data_from_proxy(proxy, ZBX_PROTO_VALUE_PROXY_DATA, config_timeout, config_trapper_timeout, config_source_ip, &answer, &ts))) { goto out; } /* handle pre 3.4 proxies that did not support proxy data request and active/passive configuration mismatch */ if ('\0' == *answer) { zbx_strlcpy(proxy->version_str, ZBX_VERSION_UNDEFINED_STR, sizeof(proxy->version_str)); proxy->version_int = ZBX_COMPONENT_VERSION_UNDEFINED; zbx_free(answer); ret = FAIL; goto out; } proxy->lastaccess = time(NULL); ret = proxy_process_proxy_data(proxy, answer, &ts, events_cbs, proxydata_frequency, more); zbx_free(answer); out: if (SUCCEED == ret) zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s more:%d", __func__, zbx_result_string(ret), *more); else zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } /****************************************************************************** * * * Purpose: gets data from proxy ('proxy data' request) * * * * Parameters: proxy - [IN/OUT] proxy data * * config_timeout - [IN] * * config_trapper_timeout - [IN] * * config_source_ip - [IN] * * events_cbs - [IN] * * proxydata_frequency - [IN] * * * * Return value: SUCCEED - data were received and processed successfully * * other code - an error occurred * * * * Comments: This function updates proxy version, compress and lastaccess * * properties. * * * ******************************************************************************/ static int proxy_get_tasks(zbx_dc_proxy_t *proxy, int config_timeout, int config_trapper_timeout, const char *config_source_ip, const zbx_events_funcs_t *events_cbs, int proxydata_frequency) { char *answer = NULL; int ret = FAIL, more; zbx_timespec_t ts; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (SUCCEED != (ret = get_data_from_proxy(proxy, ZBX_PROTO_VALUE_PROXY_TASKS, config_timeout, config_trapper_timeout, config_source_ip, &answer, &ts))) { goto out; } /* handle pre 3.4 proxies that did not support proxy data request and active/passive configuration mismatch */ if ('\0' == *answer) { zbx_strlcpy(proxy->version_str, ZBX_VERSION_UNDEFINED_STR, sizeof(proxy->version_str)); proxy->version_int = ZBX_COMPONENT_VERSION_UNDEFINED; zbx_free(answer); ret = FAIL; goto out; } proxy->lastaccess = time(NULL); ret = proxy_process_proxy_data(proxy, answer, &ts, events_cbs, proxydata_frequency, &more); zbx_free(answer); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } /****************************************************************************** * * * Purpose: retrieve values of metrics from monitored hosts * * * ******************************************************************************/ static int process_proxy(const zbx_config_vault_t *config_vault, int config_timeout, int config_trapper_timeout, const char *config_source_ip, const char *config_ssl_ca_location, const char *config_ssl_cert_location, const char *config_ssl_key_location, const zbx_events_funcs_t *events_cbs, int proxyconfig_frequency, int proxydata_frequency) { zbx_dc_proxy_t proxy, proxy_old; int num, i; time_t now; zbx_dc_um_handle_t *um_handle; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (0 == (num = zbx_dc_config_get_proxypoller_hosts(&proxy, 1))) goto exit; now = time(NULL); um_handle = zbx_dc_open_user_macros(); for (i = 0; i < num; i++) { int ret = FAIL; unsigned char update_nextcheck = 0; memcpy(&proxy_old, &proxy, sizeof(zbx_dc_proxy_t)); if (proxy.proxy_config_nextcheck <= now) update_nextcheck |= ZBX_PROXY_CONFIG_NEXTCHECK; if (proxy.proxy_data_nextcheck <= now) update_nextcheck |= ZBX_PROXY_DATA_NEXTCHECK; if (proxy.proxy_tasks_nextcheck <= now) update_nextcheck |= ZBX_PROXY_TASKS_NEXTCHECK; /* Check if passive proxy has been misconfigured on the server side. If it has happened more */ /* recently than last synchronisation of cache then there is no point to retry connecting to */ /* proxy again. The next reconnection attempt will happen after cache synchronisation. */ if (proxy.last_cfg_error_time < zbx_dc_config_get_last_sync_time()) { char *port = NULL; int check_tasks = 0; proxy.addr = zbx_strdup(NULL, proxy.addr_orig); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &proxy.addr, ZBX_MACRO_TYPE_COMMON, NULL, 0); port = zbx_strdup(port, proxy.port_orig); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &port, ZBX_MACRO_TYPE_COMMON, NULL, 0); if (FAIL == zbx_is_ushort(port, &proxy.port)) { zabbix_log(LOG_LEVEL_ERR, "invalid proxy \"%s\" port: \"%s\"", proxy.name, port); ret = CONFIG_ERROR; zbx_free(port); goto error; } zbx_free(port); if (proxy.proxy_config_nextcheck <= now && proxy.compatibility == ZBX_PROXY_VERSION_CURRENT) { if (SUCCEED != (ret = proxy_send_configuration(&proxy, config_vault, config_trapper_timeout, config_source_ip, config_ssl_ca_location, config_ssl_cert_location, config_ssl_key_location))) { goto error; } } if (proxy.proxy_tasks_nextcheck <= now) check_tasks = 1; if (proxy.proxy_data_nextcheck <= now && (proxy.compatibility == ZBX_PROXY_VERSION_CURRENT || proxy.compatibility == ZBX_PROXY_VERSION_OUTDATED)) { int more; do { if (FAIL == zbx_hc_check_proxy(proxy.proxyid) || SUCCEED == zbx_vps_monitor_capped()) { break; } if (SUCCEED != (ret = proxy_get_data(&proxy, config_timeout, config_trapper_timeout, events_cbs, proxydata_frequency, config_source_ip, &more))) { goto error; } check_tasks = 0; } while (ZBX_PROXY_DATA_MORE == more); } if (1 == check_tasks) { if (SUCCEED != (ret = proxy_get_tasks(&proxy, config_timeout, config_trapper_timeout, config_source_ip, events_cbs, proxydata_frequency))) { goto error; } } } error: zbx_free(proxy.addr); if (0 != strcmp(proxy_old.version_str, proxy.version_str) || proxy_old.lastaccess != proxy.lastaccess) { zbx_update_proxy_data(&proxy_old, proxy.version_str, proxy.version_int, proxy.lastaccess, 0); } zbx_dc_requeue_proxy(proxy.proxyid, update_nextcheck, ret, proxyconfig_frequency, proxydata_frequency); } zbx_dc_close_user_macros(um_handle); exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); return num; } ZBX_THREAD_ENTRY(proxypoller_thread, args) { zbx_thread_proxy_poller_args *proxy_poller_args_in = (zbx_thread_proxy_poller_args *) (((zbx_thread_args_t *)args)->args); int nextcheck, sleeptime = -1, processed = 0, old_processed = 0; double sec, total_sec = 0.0, old_total_sec = 0.0; time_t last_stat_time; zbx_ipc_async_socket_t rtc; const zbx_thread_info_t *info = &((zbx_thread_args_t *)args)->info; int server_num = ((zbx_thread_args_t *)args)->info.server_num; int process_num = ((zbx_thread_args_t *)args)->info.process_num; unsigned char process_type = ((zbx_thread_args_t *)args)->info.process_type; zbx_uint32_t rtc_msgs[] = {ZBX_RTC_PROXYPOLLER_PROCESS}; zbx_get_program_type_cb = proxy_poller_args_in->zbx_get_program_type_cb_arg; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(info->program_type), server_num, get_process_type_string(process_type), process_num); zbx_update_selfmon_counter(info, ZBX_PROCESS_STATE_BUSY); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(proxy_poller_args_in->config_tls, zbx_get_program_type_cb, zbx_dc_get_psk_by_identity); #endif zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); last_stat_time = time(NULL); zbx_db_connect(ZBX_DB_CONNECT_NORMAL); zbx_rtc_subscribe(process_type, process_num, rtc_msgs, ARRSIZE(rtc_msgs), proxy_poller_args_in->config_timeout, &rtc); while (ZBX_IS_RUNNING()) { zbx_uint32_t rtc_cmd; unsigned char *rtc_data; sec = zbx_time(); zbx_update_env(get_process_type_string(process_type), sec); if (0 != sleeptime) { zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec," " exchanging data%s]", get_process_type_string(process_type), process_num, old_processed, old_total_sec, zbx_vps_monitor_status()); } processed += process_proxy(proxy_poller_args_in->config_vault, proxy_poller_args_in->config_timeout, proxy_poller_args_in->config_trapper_timeout, proxy_poller_args_in->config_source_ip, proxy_poller_args_in->config_ssl_ca_location, proxy_poller_args_in->config_ssl_cert_location, proxy_poller_args_in->config_ssl_key_location, proxy_poller_args_in->events_cbs, proxy_poller_args_in->proxyconfig_frequency, proxy_poller_args_in->proxydata_frequency); total_sec += zbx_time() - sec; nextcheck = zbx_dc_config_get_proxypoller_nextcheck(); sleeptime = zbx_calculate_sleeptime(nextcheck, POLLER_DELAY); if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time) { if (0 == sleeptime) { zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec," " exchanging data%s]", get_process_type_string(process_type), process_num, processed, total_sec, zbx_vps_monitor_status()); } else { zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec," " idle %d sec%s]", get_process_type_string(process_type), process_num, processed, total_sec, sleeptime, zbx_vps_monitor_status()); old_processed = processed; old_total_sec = total_sec; } processed = 0; total_sec = 0.0; last_stat_time = time(NULL); } if (SUCCEED == zbx_rtc_wait(&rtc, info, &rtc_cmd, &rtc_data, sleeptime) && 0 != rtc_cmd) { if (ZBX_RTC_SHUTDOWN == rtc_cmd) break; } } zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num); while (1) zbx_sleep(SEC_PER_MIN); #undef STAT_INTERVAL }