root/include/crm/common/messages_internal.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. pcmk__request_origin_type
  2. pcmk__request_origin

   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 #ifdef __cplusplus
  20 extern "C" {
  21 #endif
  22 
  23 enum pcmk__request_flags {
  24     pcmk__request_none          = UINT32_C(0),
  25 
  26     /* It would be nice if we could check for synchronous requests generically,
  27      * but each daemon uses its own call options, so the daemons are responsible
  28      * for setting this flag when appropriate.
  29      */
  30     pcmk__request_sync          = (UINT32_C(1) << 0),
  31 
  32     /* Whether reply must use original call options (the library code does not
  33      * use this, so it is for internal daemon use)
  34      */
  35     pcmk__request_reuse_options = (UINT32_C(1) << 1),
  36 };
  37 
  38 // Server request (whether from an IPC client or cluster peer)
  39 typedef struct {
  40     // If request is from an IPC client
  41     pcmk__client_t *ipc_client;     // IPC client (NULL if not via IPC)
  42     uint32_t ipc_id;                // IPC message ID
  43     uint32_t ipc_flags;             // IPC message flags
  44 
  45     // If message is from a cluster peer
  46     const char *peer;       // Peer name (NULL if not via cluster)
  47 
  48     // Common information regardless of origin
  49     xmlNode *xml;                   // Request XML
  50     int call_options;               // Call options set on request
  51     uint32_t flags;                 // Flag group of pcmk__request_flags
  52     pcmk__action_result_t result;   // Where to store operation result
  53 
  54     /* It would be nice if we could pull the IPC command from the XML
  55      * generically, but each daemon uses a different XML attribute for it,
  56      * so the daemon is responsible for populating this field.
  57      *
  58      * This must be a copy of the XML field, and not just a pointer into xml,
  59      * because handlers might modify the original XML.
  60      *
  61      * @TODO Create a per-daemon struct with IPC handlers, IPC endpoints, etc.,
  62      * and the name of the XML attribute for IPC commands, then replace this
  63      * with a convenience function to copy the command.
  64      */
  65     char *op;                       // IPC command name
  66 } pcmk__request_t;
  67 
  68 #define pcmk__set_request_flags(request, flags_to_set) do {         \
  69         (request)->flags = pcmk__set_flags_as(__func__, __LINE__,   \
  70         LOG_TRACE, "Request", "message", (request)->flags,          \
  71         (flags_to_set), #flags_to_set);                             \
  72     } while (0)
  73 
  74 // Type for mapping a server command to a handler
  75 typedef struct {
  76     const char *command;
  77     xmlNode *(*handler)(pcmk__request_t *request);
  78 } pcmk__server_command_t;
  79 
  80 /*!
  81  * \internal
  82  * \brief Create message XML (for IPC or the cluster layer)
  83  *
  84  * Create standard, generic XML that can be used as a message sent via IPC or
  85  * the cluster layer. Currently, not all IPC and cluster layer messaging uses
  86  * this, but it should (eventually, keeping backward compatibility in mind).
  87  *
  88  * \param[in] server            Server whose protocol defines message semantics
  89  * \param[in] reply_to          If NULL, create message as a request with a
  90  *                              generated message ID, otherwise create message
  91  *                              as a reply to this message ID
  92  * \param[in] sender_system     Sender's subsystem (required; this is an
  93  *                              arbitrary string that may have meaning between
  94  *                              the sender and recipient)
  95  * \param[in] recipient_node    If not NULL, add as message's recipient node
  96  *                              (NULL typically indicates a broadcast message)
  97  * \param[in] recipient_system  If not NULL, add as message's recipient
  98  *                              subsystem (this is an arbitrary string that may
  99  *                              have meaning between the sender and recipient)
 100  * \param[in] task              Add as message's task (required)
 101  * \param[in] data              If not NULL, copy as message's data (callers
 102  *                              should not add attributes to the returned
 103  *                              message element, but instead pass any desired
 104  *                              information here, though this is not always
 105  *                              honored currently)
 106  *
 107  * \return Newly created message XML
 108  * \note The caller is responsible for freeing the return value using
 109  *       \c pcmk__xml_free().
 110  */
 111 #define pcmk__new_message(server, reply_to, sender_system,                  \
 112                           recipient_node, recipient_system, task, data)     \
 113     pcmk__new_message_as(__func__, (server), (reply_to),                    \
 114                          (sender_system), (recipient_node),                 \
 115                          (recipient_system), (task), (data))
 116 
 117 /*!
 118  * \internal
 119  * \brief Create a Pacemaker request (for IPC or cluster layer)
 120  *
 121  * \param[in] server            Server whose protocol defines message semantics
 122  * \param[in] sender_system     Sender's subsystem (required; this is an
 123  *                              arbitrary string that may have meaning between
 124  *                              the sender and recipient)
 125  * \param[in] recipient_node    If not NULL, add as message's recipient node
 126  *                              (NULL typically indicates a broadcast message)
 127  * \param[in] recipient_system  If not NULL, add as message's recipient
 128  *                              subsystem (this is an arbitrary string that may
 129  *                              have meaning between the sender and recipient)
 130  * \param[in] task              Add as message's task (required)
 131  * \param[in] data              If not NULL, copy as message's data (callers
 132  *                              should not add attributes to the returned
 133  *                              message element, but instead pass any desired
 134  *                              information here, though this is not always
 135  *                              honored currently)
 136  *
 137  * \return Newly created request XML
 138  * \note The caller is responsible for freeing the return value using
 139  *       \c pcmk__xml_free().
 140  */
 141 #define pcmk__new_request(server, sender_system, recipient_node,            \
 142                           recipient_system, task, data)                     \
 143     pcmk__new_message_as(__func__, (server), NULL,                          \
 144                          (sender_system), (recipient_node),                 \
 145                          (recipient_system), (task), (data))
 146 
 147 /*!
 148  * \internal
 149  * \brief Create a Pacemaker reply (for IPC or cluster layer)
 150  *
 151  * \param[in] original_request  XML of request being replied to
 152  * \param[in] data              If not NULL, copy as reply's data (callers
 153  *                              should not add attributes to the returned
 154  *                              message element, but instead pass any desired
 155  *                              information here, though this is not always
 156  *                              honored currently)
 157  *
 158  * \return Newly created reply XML
 159  * \note The caller is responsible for freeing the return value using
 160  *       \c pcmk__xml_free().
 161  */
 162 #define pcmk__new_reply(original_request, data) \
 163     pcmk__new_reply_as(__func__, (original_request), (data))
 164 
 165 xmlNode *pcmk__new_message_as(const char *origin, enum pcmk_ipc_server server,
 166                               const char *reply_to, const char *sender_system,
 167                               const char *recipient_node,
 168                               const char *recipient_system, const char *task,
 169                               xmlNode *data);
 170 
 171 xmlNode *pcmk__new_reply_as(const char *origin, const xmlNode *original_request,
 172                             xmlNode *data);
 173 
 174 GHashTable *pcmk__register_handlers(const pcmk__server_command_t handlers[]);
 175 xmlNode *pcmk__process_request(pcmk__request_t *request, GHashTable *handlers);
 176 void pcmk__reset_request(pcmk__request_t *request);
 177 
 178 /*!
 179  * \internal
 180  * \brief Get a loggable description of a request's origin
 181  *
 182  * \param[in] request
 183  *
 184  * \return "peer" if request was via CPG, "client" if via IPC, or "originator"
 185  *         if unknown
 186  */
 187 static inline const char *
 188 pcmk__request_origin_type(const pcmk__request_t *request)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190     if ((request != NULL) && (request->ipc_client != NULL)) {
 191         return "client";
 192     } else if ((request != NULL) && (request->peer != NULL)) {
 193         return "peer";
 194     } else {
 195         return "originator";
 196     }
 197 }
 198 
 199 /*!
 200  * \internal
 201  * \brief Get a loggable name for a request's origin
 202  *
 203  * \param[in] request
 204  *
 205  * \return Peer name if request was via CPG, client name if via IPC, or
 206  *         "(unspecified)" if unknown
 207  */
 208 static inline const char *
 209 pcmk__request_origin(const pcmk__request_t *request)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211     if ((request != NULL) && (request->ipc_client != NULL)) {
 212         return pcmk__client_name(request->ipc_client);
 213     } else if ((request != NULL) && (request->peer != NULL)) {
 214         return request->peer;
 215     } else {
 216         return "(unspecified)";
 217     }
 218 }
 219 
 220 #ifdef __cplusplus
 221 }
 222 #endif
 223 
 224 #endif // PCMK__CRM_COMMON_MESSAGES_INTERNAL__H

/* [previous][next][first][last][top][bottom][index][help] */