pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
messages.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2024 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdio.h>
13#include <time.h> // time()
14#include <sys/types.h>
15
16#include <glib.h>
17#include <libxml/tree.h>
18
19#include <crm/common/xml.h>
21
57xmlNode *
58pcmk__new_message_as(const char *origin, enum pcmk_ipc_server server,
59 const char *reply_to, const char *sender_system,
60 const char *recipient_node, const char *recipient_system,
61 const char *task, xmlNode *data)
62{
63 static unsigned int message_counter = 0U;
64
65 xmlNode *message = NULL;
66 char *message_id = NULL;
67 const char *subtype = PCMK__VALUE_RESPONSE;
68
69 CRM_CHECK(!pcmk__str_empty(origin)
70 && !pcmk__str_empty(sender_system)
71 && !pcmk__str_empty(task),
72 return NULL);
73
74 if (reply_to == NULL) {
75 subtype = PCMK__VALUE_REQUEST;
76 message_id = crm_strdup_printf("%s-%s-%llu-%u", task, sender_system,
77 (unsigned long long) time(NULL),
78 message_counter++);
79 reply_to = message_id;
80 }
81
82 message = pcmk__xe_create(NULL, PCMK__XE_MESSAGE);
83 pcmk__xe_set_props(message,
84 PCMK_XA_ORIGIN, origin,
86 PCMK__XA_SUBT, subtype,
88 PCMK_XA_REFERENCE, reply_to,
89 PCMK__XA_CRM_SYS_FROM, sender_system,
90 PCMK__XA_CRM_HOST_TO, recipient_node,
91 PCMK__XA_CRM_SYS_TO, recipient_system,
93 NULL);
94 if (data != NULL) {
95 xmlNode *wrapper = pcmk__xe_create(message, PCMK__XE_CRM_XML);
96
97 pcmk__xml_copy(wrapper, data);
98 }
99 free(message_id);
100 return message;
101}
102
122xmlNode *
123pcmk__new_reply_as(const char *origin, const xmlNode *original_request,
124 xmlNode *data)
125{
126 const char *message_type = crm_element_value(original_request, PCMK__XA_T);
127 const char *host_from = crm_element_value(original_request, PCMK__XA_SRC);
128 const char *sys_from = crm_element_value(original_request,
130 const char *sys_to = crm_element_value(original_request,
132 const char *type = crm_element_value(original_request, PCMK__XA_SUBT);
133 const char *operation = crm_element_value(original_request,
135 const char *crm_msg_reference = crm_element_value(original_request,
137 enum pcmk_ipc_server server = pcmk__parse_server(message_type);
138
139 if (server == pcmk_ipc_unknown) {
140 /* @COMPAT Not all requests currently specify a message type, so use a
141 * default that preserves past behavior.
142 *
143 * @TODO Ensure all requests specify a message type, drop this check
144 * after we no longer support rolling upgrades or Pacemaker Remote
145 * connections involving versions before that.
146 */
147 server = pcmk_ipc_controld;
148 }
149
150 if (type == NULL) {
151 crm_warn("Cannot reply to invalid message: No message type specified");
152 return NULL;
153 }
154
155 if (strcmp(type, PCMK__VALUE_REQUEST) != 0) {
156 /* Replies should only be generated for request messages, but it's possible
157 * we expect replies to other messages right now so this can't be enforced.
158 */
159 crm_trace("Creating a reply for a non-request original message");
160 }
161
162 // Since this is a reply, we reverse the sender and recipient info
163 return pcmk__new_message_as(origin, server, crm_msg_reference, sys_to,
164 host_from, sys_from, operation, data);
165}
166
180GHashTable *
182{
183 GHashTable *commands = g_hash_table_new(g_str_hash, g_str_equal);
184
185 if (handlers != NULL) {
186 int i;
187
188 for (i = 0; handlers[i].command != NULL; ++i) {
189 g_hash_table_insert(commands, (gpointer) handlers[i].command,
190 handlers[i].handler);
191 }
192 if (handlers[i].handler != NULL) {
193 // g_str_hash() can't handle NULL, so use empty string for default
194 g_hash_table_insert(commands, (gpointer) "", handlers[i].handler);
195 }
196 }
197 return commands;
198}
199
209xmlNode *
210pcmk__process_request(pcmk__request_t *request, GHashTable *handlers)
211{
212 xmlNode *(*handler)(pcmk__request_t *request) = NULL;
213
214 CRM_CHECK((request != NULL) && (request->op != NULL) && (handlers != NULL),
215 return NULL);
216
218 && (request->ipc_client != NULL)) {
219 CRM_CHECK(request->ipc_client->request_id == request->ipc_id,
220 return NULL);
221 }
222
223 handler = g_hash_table_lookup(handlers, request->op);
224 if (handler == NULL) {
225 handler = g_hash_table_lookup(handlers, ""); // Default handler
226 if (handler == NULL) {
227 crm_info("Ignoring %s request from %s %s with no handler",
228 request->op, pcmk__request_origin_type(request),
229 pcmk__request_origin(request));
230 return NULL;
231 }
232 }
233
234 return (*handler)(request);
235}
236
243void
245{
246 free(request->op);
247 request->op = NULL;
248
249 pcmk__reset_result(&(request->result));
250}
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:80
char data[0]
Definition cpg.c:10
enum pcmk_ipc_server type
Definition cpg.c:3
#define CRM_FEATURE_SET
Definition crm.h:66
pcmk_ipc_server
Available IPC interfaces.
Definition ipc.h:48
@ pcmk_ipc_controld
Controller.
Definition ipc.h:52
@ pcmk_ipc_unknown
Unknown or invalid.
Definition ipc.h:49
#define crm_info(fmt, args...)
Definition logging.h:365
#define crm_warn(fmt, args...)
Definition logging.h:360
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define crm_trace(fmt, args...)
Definition logging.h:370
xmlNode * pcmk__new_reply_as(const char *origin, const xmlNode *original_request, xmlNode *data)
Definition messages.c:123
xmlNode * pcmk__new_message_as(const char *origin, enum pcmk_ipc_server server, const char *reply_to, const char *sender_system, const char *recipient_node, const char *recipient_system, const char *task, xmlNode *data)
Definition messages.c:58
GHashTable * pcmk__register_handlers(const pcmk__server_command_t handlers[])
Definition messages.c:181
void pcmk__reset_request(pcmk__request_t *request)
Definition messages.c:244
xmlNode * pcmk__process_request(pcmk__request_t *request, GHashTable *handlers)
Definition messages.c:210
@ pcmk__request_sync
#define PCMK__VALUE_RESPONSE
#define PCMK__VALUE_REQUEST
void pcmk__reset_result(pcmk__action_result_t *result)
Definition results.c:1177
enum pcmk_ipc_server pcmk__parse_server(const char *text)
Definition servers.c:178
const char * pcmk__server_message_type(enum pcmk_ipc_server server)
Definition servers.c:162
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
pcmk__action_result_t result
pcmk__client_t * ipc_client
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition xml.c:832
#define PCMK_XA_ORIGIN
Definition xml_names.h:351
#define PCMK_XA_VERSION
Definition xml_names.h:444
#define PCMK_XA_REFERENCE
Definition xml_names.h:372
#define PCMK__XE_MESSAGE
#define PCMK__XA_CRM_TASK
#define PCMK__XA_CRM_SYS_TO
#define PCMK__XA_T
#define PCMK__XA_SUBT
#define PCMK__XA_CRM_HOST_TO
#define PCMK__XA_CRM_SYS_FROM
#define PCMK__XE_CRM_XML
#define PCMK__XA_SRC