1 /*
2 * Copyright 2018-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 #ifndef PCMK__CRM_COMMON_MESSAGES_INTERNAL__H
11 #define PCMK__CRM_COMMON_MESSAGES_INTERNAL__H
12
13 #include <stdint.h> // uint32_t
14 #include <libxml/tree.h> // xmlNode
15 #include <crm/common/ipc_internal.h> // pcmk__client_t
16 #include <crm/common/results_internal.h> // pcmk__action_result_t
17 #include <crm/common/xml_internal.h> // pcmk__xml_copy()
18
19 enum pcmk__request_flags {
20 pcmk__request_none = UINT32_C(0),
21
22 /* It would be nice if we could check for synchronous requests generically,
23 * but each daemon uses its own call options, so the daemons are responsible
24 * for setting this flag when appropriate.
25 */
26 pcmk__request_sync = (UINT32_C(1) << 0),
27
28 /* Whether reply must use original call options (the library code does not
29 * use this, so it is for internal daemon use)
30 */
31 pcmk__request_reuse_options = (UINT32_C(1) << 1),
32 };
33
34 // Server request (whether from an IPC client or cluster peer)
35 typedef struct {
36 // If request is from an IPC client
37 pcmk__client_t *ipc_client; // IPC client (NULL if not via IPC)
38 uint32_t ipc_id; // IPC message ID
39 uint32_t ipc_flags; // IPC message flags
40
41 // If message is from a cluster peer
42 const char *peer; // Peer name (NULL if not via cluster)
43
44 // Common information regardless of origin
45 xmlNode *xml; // Request XML
46 int call_options; // Call options set on request
47 uint32_t flags; // Flag group of pcmk__request_flags
48 pcmk__action_result_t result; // Where to store operation result
49
50 /* It would be nice if we could pull the IPC command from the XML
51 * generically, but each daemon uses a different XML attribute for it,
52 * so the daemon is responsible for populating this field.
53 *
54 * This must be a copy of the XML field, and not just a pointer into xml,
55 * because handlers might modify the original XML.
56 *
57 * @TODO Create a per-daemon struct with IPC handlers, IPC endpoints, etc.,
58 * and the name of the XML attribute for IPC commands, then replace this
59 * with a convenience function to copy the command.
60 */
61 char *op; // IPC command name
62 } pcmk__request_t;
63
64 #define pcmk__set_request_flags(request, flags_to_set) do { \
65 (request)->flags = pcmk__set_flags_as(__func__, __LINE__, \
66 LOG_TRACE, "Request", "message", (request)->flags, \
67 (flags_to_set), #flags_to_set); \
68 } while (0)
69
70 // Type for mapping a server command to a handler
71 typedef struct {
72 const char *command;
73 xmlNode *(*handler)(pcmk__request_t *request);
74 } pcmk__server_command_t;
75
76 const char *pcmk__message_name(const char *name);
77 GHashTable *pcmk__register_handlers(const pcmk__server_command_t handlers[]);
78 xmlNode *pcmk__process_request(pcmk__request_t *request, GHashTable *handlers);
79 void pcmk__reset_request(pcmk__request_t *request);
80
81 /*!
82 * \internal
83 * \brief Get a loggable description of a request's origin
84 *
85 * \param[in] request
86 *
87 * \return "peer" if request was via CPG, "client" if via IPC, or "originator"
88 * if unknown
89 */
90 static inline const char *
91 pcmk__request_origin_type(const pcmk__request_t *request)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
92 {
93 if ((request != NULL) && (request->ipc_client != NULL)) {
94 return "client";
95 } else if ((request != NULL) && (request->peer != NULL)) {
96 return "peer";
97 } else {
98 return "originator";
99 }
100 }
101
102 /*!
103 * \internal
104 * \brief Get a loggable name for a request's origin
105 *
106 * \param[in] request
107 *
108 * \return Peer name if request was via CPG, client name if via IPC, or
109 * "(unspecified)" if unknown
110 */
111 static inline const char *
112 pcmk__request_origin(const pcmk__request_t *request)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
113 {
114 if ((request != NULL) && (request->ipc_client != NULL)) {
115 return pcmk__client_name(request->ipc_client);
116 } else if ((request != NULL) && (request->peer != NULL)) {
117 return request->peer;
118 } else {
119 return "(unspecified)";
120 }
121 }
122
123 #endif // PCMK__CRM_COMMON_MESSAGES_INTERNAL__H