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 "zbxjson.h"
23 #include "log.h"
24
25 /******************************************************************************
26 * *
27 * Function: zbx_send_response_ext *
28 * *
29 * Purpose: send json SUCCEED or FAIL to socket along with an info message *
30 * *
31 * Parameters: sock - [IN] socket descriptor *
32 * result - [IN] SUCCEED or FAIL *
33 * info - [IN] info message (optional) *
34 * version - [IN] the version data (optional) *
35 * protocol - [IN] the transport protocol *
36 * timeout - [IN] timeout for this operation *
37 * *
38 * Return value: SUCCEED - data successfully transmitted *
39 * NETWORK_ERROR - network related error occurred *
40 * *
41 * Author: Alexander Vladishev, Alexei Vladishev *
42 * *
43 ******************************************************************************/
zbx_send_response_ext(zbx_socket_t * sock,int result,const char * info,const char * version,int protocol,int timeout)44 int zbx_send_response_ext(zbx_socket_t *sock, int result, const char *info, const char *version, int protocol,
45 int timeout)
46 {
47 const char *__function_name = "zbx_send_response_ext";
48
49 struct zbx_json json;
50 const char *resp;
51 int ret = SUCCEED;
52
53 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
54
55 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
56
57 resp = SUCCEED == result ? ZBX_PROTO_VALUE_SUCCESS : ZBX_PROTO_VALUE_FAILED;
58
59 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, resp, ZBX_JSON_TYPE_STRING);
60
61 if (NULL != info && '\0' != *info)
62 zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, info, ZBX_JSON_TYPE_STRING);
63
64 if (NULL != version)
65 zbx_json_addstring(&json, ZBX_PROTO_TAG_VERSION, version, ZBX_JSON_TYPE_STRING);
66
67 zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s'", __function_name, json.buffer);
68
69 if (FAIL == (ret = zbx_tcp_send_ext(sock, json.buffer, strlen(json.buffer), protocol, timeout)))
70 {
71 zabbix_log(LOG_LEVEL_DEBUG, "Error sending result back: %s", zbx_socket_strerror());
72 ret = NETWORK_ERROR;
73 }
74
75 zbx_json_free(&json);
76
77 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
78
79 return ret;
80 }
81
82 /******************************************************************************
83 * *
84 * Function: zbx_recv_response *
85 * *
86 * Purpose: read a response message (in JSON format) from socket, optionally *
87 * extract "info" value. *
88 * *
89 * Parameters: sock - [IN] socket descriptor *
90 * timeout - [IN] timeout for this operation *
91 * error - [OUT] pointer to error message *
92 * *
93 * Return value: SUCCEED - "response":"success" successfully retrieved *
94 * FAIL - otherwise *
95 * Comments: *
96 * Allocates memory. *
97 * *
98 * If an error occurs, the function allocates dynamic memory for an error *
99 * message and writes its address into location pointed to by "error" *
100 * parameter. *
101 * *
102 * When the "info" value is present in the response message then function *
103 * copies the "info" value into the "error" buffer as additional *
104 * information *
105 * *
106 * IMPORTANT: it is a responsibility of the caller to release the *
107 * "error" memory ! *
108 * *
109 ******************************************************************************/
zbx_recv_response(zbx_socket_t * sock,int timeout,char ** error)110 int zbx_recv_response(zbx_socket_t *sock, int timeout, char **error)
111 {
112 const char *__function_name = "zbx_recv_response";
113
114 struct zbx_json_parse jp;
115 char value[16];
116 int ret = FAIL;
117
118 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
119
120 if (SUCCEED != zbx_tcp_recv_to(sock, timeout))
121 {
122 /* since we have successfully sent data earlier, we assume the other */
123 /* side is just too busy processing our data if there is no response */
124 *error = zbx_strdup(*error, zbx_socket_strerror());
125 goto out;
126 }
127
128 zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s'", __function_name, sock->buffer);
129
130 /* deal with empty string here because zbx_json_open() does not produce an error message in this case */
131 if ('\0' == *sock->buffer)
132 {
133 *error = zbx_strdup(*error, "empty string received");
134 goto out;
135 }
136
137 if (SUCCEED != zbx_json_open(sock->buffer, &jp))
138 {
139 *error = zbx_strdup(*error, zbx_json_strerror());
140 goto out;
141 }
142
143 if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_RESPONSE, value, sizeof(value), NULL))
144 {
145 *error = zbx_strdup(*error, "no \"" ZBX_PROTO_TAG_RESPONSE "\" tag");
146 goto out;
147 }
148
149 if (0 != strcmp(value, ZBX_PROTO_VALUE_SUCCESS))
150 {
151 char *info = NULL;
152 size_t info_alloc = 0;
153
154 if (SUCCEED == zbx_json_value_by_name_dyn(&jp, ZBX_PROTO_TAG_INFO, &info, &info_alloc, NULL))
155 *error = zbx_strdup(*error, info);
156 else
157 *error = zbx_dsprintf(*error, "negative response \"%s\"", value);
158 zbx_free(info);
159 goto out;
160 }
161
162 ret = SUCCEED;
163 out:
164 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
165
166 return ret;
167 }
168