1 /* 2 * Intracluster message object (struct ha_msg) 3 * 4 * Copyright (C) 1999, 2000 Alan Robertson <alanr@unix.sh> 5 * This software licensed under the GNU LGPL. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 */ 22 23 #ifndef _HA_MSG_H 24 # define _HA_MSG_H 1 25 #include <stdio.h> 26 #include <clplumbing/cl_log.h> 27 #include <clplumbing/ipc.h> 28 #include <clplumbing/longclock.h> 29 #include <clplumbing/cl_uuid.h> 30 #include <compress.h> 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <fcntl.h> 34 35 36 enum cl_netstring_type{ 37 FT_STRING = 0, 38 FT_BINARY, 39 FT_STRUCT, 40 FT_LIST, 41 FT_COMPRESS, 42 FT_UNCOMPRESS 43 }; 44 45 enum cl_msgfmt{ 46 MSGFMT_NVPAIR, 47 MSGFMT_NETSTRING 48 }; 49 50 51 #define NEEDHEAD 1 52 #define NOHEAD 0 53 #define HA_MSG_ASSERT(X) do{ if(!(X)){ \ 54 cl_log(LOG_ERR, "Assertion failed on line %d in file \"%s\"" \ 55 , __LINE__, __FILE__); \ 56 abort(); \ 57 } \ 58 }while(0) 59 60 typedef struct hb_msg_stats_s { 61 unsigned long totalmsgs; /* Total # of messages */ 62 /* ever handled */ 63 unsigned long allocmsgs; /* # Msgs currently allocated */ 64 longclock_t lastmsg; 65 }hb_msg_stats_t; 66 67 struct ha_msg { 68 int nfields; 69 int nalloc; 70 char ** names; 71 size_t* nlens; 72 void ** values; 73 size_t* vlens; 74 int * types; 75 }; 76 77 typedef struct ha_msg HA_Message; 78 79 struct fieldtypefuncs_s{ 80 81 /* memfree frees the memory involved*/ 82 void (*memfree)(void*); 83 84 /* dup makes a complete copy of the field*/ 85 void* (*dup)(const void*, size_t); 86 87 /* display printout the field*/ 88 void (*display)(int, int, char* , void*, int); 89 90 /* add the field into a message*/ 91 int (*addfield) (struct ha_msg* msg, char* name, size_t namelen, 92 void* value, size_t vallen, int depth); 93 94 /* return the string length required to add this field*/ 95 int (*stringlen) (size_t namlen, size_t vallen, const void* value); 96 97 /* return the netstring length required to add this field*/ 98 int (*netstringlen) (size_t namlen, size_t vallen, const void* value); 99 100 /* print the field into the provided buffer, convert it first */ 101 /* if ncecessary*/ 102 int (*tostring)(char*, char*, void* ,size_t,int); 103 104 /* print the field into the provided buffer*/ 105 int (*tonetstring)(char*, char*, char*, size_t, 106 void*, size_t, int, size_t*); 107 108 /* convert the given string to a field 109 note: this functions involves allocate memory for 110 for the field 111 */ 112 int (*stringtofield)(void*, size_t, int depth, void**, size_t* ); 113 114 /* convert the given netstring to a field 115 note: this functions involves allocate memory for 116 for the field 117 */ 118 int (*netstringtofield)(const void*, size_t, void**, size_t*); 119 120 /* action before packing*/ 121 int (*prepackaction)(struct ha_msg* m, int index); 122 123 /* action before a user get the value of a field*/ 124 int (*pregetaction)(struct ha_msg* m, int index); 125 126 }; 127 128 #define NUM_MSG_TYPES 6 129 extern struct fieldtypefuncs_s fieldtypefuncs[NUM_MSG_TYPES]; 130 131 #define MSG_NEEDAUTH 0x01 132 #define MSG_ALLOWINTR 0X02 133 #define MSG_NEEDCOMPRESS 0x04 134 #define MSG_NOSIZECHECK 0x08 135 136 #define IFACE "!^!\n" 137 #define MSG_START ">>>\n" 138 #define MSG_END "<<<\n" 139 #define MSG_START_NETSTRING "###\n" 140 #define MSG_END_NETSTRING "%%%\n" 141 #define EQUAL "=" 142 143 #define MAXDEPTH 16 /* Maximum recursive message depth */ 144 #define MAXLENGTH 1024 145 146 /* Common field names for our messages */ 147 #define F_TYPE "t" /* Message type */ 148 #define F_SUBTYPE "subt" /* Message type */ 149 #define F_ORIG "src" /* Real Originator */ 150 #define F_ORIGUUID "srcuuid" /* Real Originator uuid*/ 151 #define F_NODE "node" /* Node being described */ 152 #define F_NODELIST "nodelist" /* Node list being described */ 153 #define F_DELNODELIST "delnodelist" /* Del node list being described */ 154 #define F_TO "dest" /* Destination (optional) */ 155 #define F_TOUUID "destuuid" /* Destination uuid(optional) */ 156 #define F_STATUS "st" /* New status (type = status) */ 157 #define F_WEIGHT "weight" /* weight of node */ 158 #define F_SITE "site" /* site of node */ 159 #define F_PROTOCOL "protocol" /* Protocol number for communication*/ 160 #define F_CLIENTNAME "cn" /* Client name */ 161 #define F_CLIENTSTATUS "cs" /* Client status */ 162 #define F_TIME "ts" /* Timestamp */ 163 #define F_SEQ "seq" /* Sequence number */ 164 #define F_LOAD "ld" /* Load average */ 165 #define F_COMMENT "info" /* Comment */ 166 #define F_TTL "ttl" /* Time To Live */ 167 #define F_AUTH "auth" /* Authentication string */ 168 #define F_HBGENERATION "hg" /* Heartbeat generation number */ 169 #define F_CLIENT_GENERATION "client_gen" /* client generation number*/ 170 #define F_FIRSTSEQ "firstseq" /* Lowest seq # to retransmit */ 171 #define F_LASTSEQ "lastseq" /* Highest seq # to retransmit */ 172 #define F_RESOURCES "rsc_hold" /* What resources do we hold? */ 173 #define F_FROMID "from_id" /* from Client id */ 174 #define F_TOID "to_id" /* To client id */ 175 #define F_PID "pid" /* PID of client */ 176 #define F_UID "uid" /* uid of client */ 177 #define F_GID "gid" /* gid of client */ 178 #define F_ISSTABLE "isstable" /* true/false for RESOURCES */ 179 #define F_APIREQ "reqtype" /* API request type for "hbapi" */ 180 #define F_APIRESULT "result" /* API request result code */ 181 #define F_IFNAME "ifname" /* Interface name */ 182 #define F_PNAME "pname" /* Parameter name */ 183 #define F_PVALUE "pvalue" /* Parameter name */ 184 #define F_DEADTIME "deadtime" /* Dead time interval in ms. */ 185 #define F_KEEPALIVE "keepalive" /* Keep alive time interval in ms. */ 186 #define F_LOGFACILITY "logfacility" /* Suggested cluster syslog facility */ 187 #define F_NODETYPE "nodetype" /* Type of node */ 188 #define F_NUMNODES "numnodes" /* num of total nodes(excluding ping nodes*/ 189 #define F_RTYPE "rtype" /* Resource type */ 190 #define F_ORDERSEQ "oseq" /* Order Sequence number */ 191 #define F_DT "dt" /* Dead time field for heartbeat*/ 192 #define F_ACKSEQ "ackseq" /* The seq number this msg is acking*/ 193 #define F_CRM_DATA "crm_xml" 194 #define F_XML_TAGNAME "__name__" 195 #define F_STATE "state" /*used in ccm for state info*/ 196 197 198 /* Message types */ 199 #define T_STATUS "status" /* Status (heartbeat) */ 200 #define T_IFSTATUS "ifstat" /* Interface status */ 201 #define T_ASKRESOURCES "ask_resources" /* Let other node ask my resources */ 202 #define T_ASKRELEASE "ip-request" /* Please give up these resources... */ 203 #define T_ACKRELEASE "ip-request-resp"/* Resources given up... */ 204 #define T_QCSTATUS "query-cstatus" /* Query client status */ 205 #define T_RCSTATUS "respond-cstatus"/* Respond client status */ 206 #define T_STONITH "stonith" /* Stonith return code */ 207 #define T_SHUTDONE "shutdone" /* External Shutdown complete */ 208 #define T_CRM "crmd" /* Cluster resource manager message */ 209 #define T_ATTRD "attrd" /* Cluster resource manager message */ 210 #define T_ADDNODE "addnode" /* Add node message*/ 211 #define T_DELNODE "delnode" /* Delete node message*/ 212 #define T_SETWEIGHT "setweight" /* Set node weight*/ 213 #define T_SETSITE "setsite" /* Set node site*/ 214 #define T_REQNODES "reqnodes" /* Request node list */ 215 #define T_REPNODES "repnodes" /* reply node list rquest*/ 216 217 #define T_APIREQ "hbapi-req" /* Heartbeat API request */ 218 #define T_APIRESP "hbapi-resp" /* Heartbeat API response */ 219 #define T_APICLISTAT "hbapi-clstat" /* Client status notification" */ 220 221 #define NOSEQ_PREFIX "NS_" /* PREFIX: Give no sequence number */ 222 /* Used for messages which can't be retransmitted */ 223 /* Either they're protocol messages or from dumb (ping) endpoints */ 224 #define T_REXMIT NOSEQ_PREFIX "rexmit" /* Rexmit request */ 225 #define T_NAKREXMIT NOSEQ_PREFIX "nak_rexmit" /* NAK Rexmit request */ 226 #define T_NS_STATUS NOSEQ_PREFIX "st" /* ping status */ 227 #define T_ACKMSG NOSEQ_PREFIX "ackmsg" /* ACK message*/ 228 229 /* Messages associated with nice_failback */ 230 #define T_STARTING "starting" /* Starting Heartbeat */ 231 /* (requesting resource report) */ 232 #define T_RESOURCES "resource" /* Resources report */ 233 234 /* Messages associated with stonith completion results */ 235 #define T_STONITH_OK "OK" /* stonith completed successfully */ 236 #define T_STONITH_BADHOST "badhost" /* stonith failed */ 237 #define T_STONITH_BAD "bad" /* stonith failed */ 238 #define T_STONITH_NOTCONFGD "n_stnth" /* no stonith device configured */ 239 #define T_STONITH_UNNEEDED "unneeded" /* STONITH not required */ 240 241 /* Set up message statistics area */ 242 243 int netstring_extra(int); 244 int cl_msg_stats_add(longclock_t time, int size); 245 246 void cl_msg_setstats(volatile hb_msg_stats_t* stats); 247 void cl_dump_msgstats(void); 248 void cl_set_compression_threshold(size_t threadhold); 249 void cl_set_traditional_compression(gboolean value); 250 251 /* Allocate new (empty) message */ 252 struct ha_msg * ha_msg_new(int nfields); 253 254 /* Free message */ 255 void ha_msg_del(struct ha_msg *msg); 256 257 /* Copy message */ 258 struct ha_msg* ha_msg_copy(const struct ha_msg *msg); 259 260 int ha_msg_expand(struct ha_msg* msg ); 261 262 /*Add a null-terminated name and binary value to a message*/ 263 int ha_msg_addbin(struct ha_msg * msg, const char * name, 264 const void * value, size_t vallen); 265 266 int ha_msg_adduuid(struct ha_msg * msg, const char * name, 267 const cl_uuid_t* uuid); 268 269 /* Add null-terminated name and a value to the message */ 270 int ha_msg_add(struct ha_msg * msg 271 , const char* name, const char* value); 272 273 int cl_msg_remove(struct ha_msg* msg, const char* name); 274 int cl_msg_remove_value(struct ha_msg* msg, const void* value); 275 int cl_msg_remove_offset(struct ha_msg* msg, int offset); 276 277 /* Modify null-terminated name and a value to the message */ 278 int cl_msg_modstring(struct ha_msg * msg, 279 const char* name, 280 const char* value); 281 int cl_msg_modbin(struct ha_msg * msg, 282 const char* name, 283 const void* value, 284 size_t vlen); 285 286 int cl_msg_moduuid(struct ha_msg * msg, const char * name, 287 const cl_uuid_t* uuid); 288 289 int cl_msg_modstruct(struct ha_msg * msg, 290 const char* name, 291 const struct ha_msg* value); 292 #define ha_msg_mod(msg, name, value) cl_msg_modstring(msg, name, value) 293 int cl_msg_replace(struct ha_msg* msg, int index, 294 const void* value, size_t vlen, int type); 295 int cl_msg_replace_value(struct ha_msg* msg, const void *old_value, 296 const void* value, size_t vlen, int type); 297 298 /* Add name, value (with known lengths) to the message */ 299 int ha_msg_nadd(struct ha_msg * msg, const char * name, int namelen 300 , const char * value, int vallen); 301 302 /* Add a name/value/type to a message (with sizes for name and value) */ 303 int ha_msg_nadd_type(struct ha_msg * msg, const char * name, int namelen 304 , const char * value, int vallen, int type); 305 306 /* Add name=value string to a message */ 307 int ha_msg_add_nv(struct ha_msg* msg, const char * nvline, const char * bufmax); 308 309 310 /* Return value associated with particular name */ 311 #define ha_msg_value(m,name) cl_get_string(m, name) 312 313 /* Call wait(in|out) but only for a finite time */ 314 int cl_ipc_wait_timeout( 315 IPC_Channel * chan, int (*waitfun)(IPC_Channel * chan), unsigned int timeout); 316 317 /* Reads an IPC stream -- converts it into a message */ 318 struct ha_msg * msgfromIPC_timeout(IPC_Channel *ch, int flag, unsigned int timeout, int *rc_out); 319 struct ha_msg * msgfromIPC(IPC_Channel * f, int flag); 320 321 IPC_Message * ipcmsgfromIPC(IPC_Channel * ch); 322 323 /* Reads a stream -- converts it into a message */ 324 struct ha_msg * msgfromstream(FILE * f); 325 326 /* Reads a stream with string format--converts it into a message */ 327 struct ha_msg * msgfromstream_string(FILE * f); 328 329 /* Reads a stream with netstring format--converts it into a message */ 330 struct ha_msg * msgfromstream_netstring(FILE * f); 331 332 /* Same as above plus copying the iface name to "iface" */ 333 struct ha_msg * if_msgfromstream(FILE * f, char *iface); 334 335 /* Writes a message into a stream */ 336 int msg2stream(struct ha_msg* m, FILE * f); 337 338 /* Converts a message into a string and adds the iface name on start */ 339 char * msg2if_string(const struct ha_msg *m, const char * iface); 340 341 /* Converts a string gotten via UDP into a message */ 342 struct ha_msg * string2msg(const char * s, size_t length); 343 344 /* Converts a message into a string */ 345 char * msg2string(const struct ha_msg *m); 346 347 /* Converts a message into a string in the provided buffer with certain 348 depth and with or without start/end */ 349 int msg2string_buf(const struct ha_msg *m, char* buf, 350 size_t len, int depth, int needhead); 351 352 /* Converts a message into wire format */ 353 char* msg2wirefmt(struct ha_msg *m, size_t* ); 354 char* msg2wirefmt_noac(struct ha_msg*m, size_t* len); 355 356 /* Converts wire format data into a message */ 357 struct ha_msg* wirefmt2msg(const char* s, size_t length, int flag); 358 359 /* Convets wire format data into an IPC message */ 360 IPC_Message* wirefmt2ipcmsg(void* p, size_t len, IPC_Channel* ch); 361 362 /* Converts an ha_msg into an IPC message */ 363 IPC_Message* hamsg2ipcmsg(struct ha_msg* m, IPC_Channel* ch); 364 365 /* Converts an IPC message into an ha_msg */ 366 struct ha_msg* ipcmsg2hamsg(IPC_Message*m); 367 368 /* Outputs a message to an IPC channel */ 369 int msg2ipcchan(struct ha_msg*m, IPC_Channel*ch); 370 371 /* Outpus a message to an IPC channel without authencating 372 the message */ 373 struct ha_msg* msgfromIPC_noauth(IPC_Channel * ch); 374 375 /* Reads from control fifo, and creates a new message from it */ 376 /* This adds the default sequence#, load avg, etc. to the message */ 377 struct ha_msg * controlfifo2msg(FILE * f); 378 379 /* Check if the message is authenticated */ 380 gboolean isauthentic(const struct ha_msg * msg); 381 382 /* Get the required string length for the given message */ 383 int get_stringlen(const struct ha_msg *m); 384 385 /* Get the requried netstring length for the given message*/ 386 int get_netstringlen(const struct ha_msg *m); 387 388 /* Add a child message to a message as a field */ 389 int ha_msg_addstruct(struct ha_msg * msg, const char * name, const void* ptr); 390 391 int ha_msg_addstruct_compress(struct ha_msg*, const char*, const void*); 392 393 /* Get binary data from a message */ 394 const void * cl_get_binary(const struct ha_msg *msg, const char * name, size_t * vallen); 395 396 /* Get uuid data from a message */ 397 int cl_get_uuid(const struct ha_msg *msg, const char * name, cl_uuid_t* retval); 398 399 /* Get string data from a message */ 400 const char * cl_get_string(const struct ha_msg *msg, const char *name); 401 402 /* Get the type for a field from a message */ 403 int cl_get_type(const struct ha_msg *msg, const char *name); 404 405 /* Get a child message from a message*/ 406 struct ha_msg *cl_get_struct(struct ha_msg *msg, const char* name); 407 408 /* Log the contents of a message */ 409 void cl_log_message (int log_level, const struct ha_msg *m); 410 411 /* Supply messaging system with old style authentication/authorization method */ 412 void cl_set_oldmsgauthfunc(gboolean (*authfunc)(const struct ha_msg*)); 413 414 /* Set default messaging format */ 415 void cl_set_msg_format(enum cl_msgfmt mfmt); 416 417 /* Add a string to a list*/ 418 int cl_msg_list_add_string(struct ha_msg* msg, const char* name, const char* value); 419 420 /* Return length of a list*/ 421 int cl_msg_list_length(struct ha_msg* msg, const char* name); 422 423 /* Return nth element of a list*/ 424 void* cl_msg_list_nth_data(struct ha_msg* msg, const char* name, int n); 425 426 /* Functions to add/mod/get an integer */ 427 int ha_msg_add_int(struct ha_msg * msg, const char * name, int value); 428 int ha_msg_mod_int(struct ha_msg * msg, const char * name, int value); 429 int ha_msg_value_int(const struct ha_msg * msg, const char * name, int* value); 430 431 /* Functions to add/mod/get an unsigned long */ 432 int ha_msg_add_ul(struct ha_msg * msg, const char * name, unsigned long value); 433 int ha_msg_mod_ul(struct ha_msg * msg, const char * name, unsigned long value); 434 int ha_msg_value_ul(const struct ha_msg * msg, const char * name, unsigned long* value); 435 436 /* Functions to add/get a string list*/ 437 GList* ha_msg_value_str_list(struct ha_msg * msg, const char * name); 438 439 int cl_msg_add_list_int(struct ha_msg* msg, const char* name, 440 int* buf, size_t n); 441 int cl_msg_get_list_int(struct ha_msg* msg, const char* name, 442 int* buf, size_t* n); 443 GList* cl_msg_get_list(struct ha_msg* msg, const char* name); 444 int cl_msg_add_list(struct ha_msg* msg, const char* name, GList* list); 445 int cl_msg_add_list_str(struct ha_msg* msg, const char* name, 446 char** buf, size_t n); 447 448 /* Function to add/get a string hash table*/ 449 GHashTable* ha_msg_value_str_table(struct ha_msg * msg, const char * name); 450 int ha_msg_add_str_table(struct ha_msg * msg, const char * name, 451 GHashTable* hash_table); 452 int ha_msg_mod_str_table(struct ha_msg * msg, const char * name, 453 GHashTable* hash_table); 454 455 /*internal use for list type*/ 456 size_t string_list_pack_length(const GList* list); 457 int string_list_pack(GList* list, char* buf, char* maxp); 458 GList* string_list_unpack(const char* packed_str_list, size_t length); 459 void list_cleanup(GList* list); 460 461 gboolean must_use_netstring(const struct ha_msg*); 462 463 464 #endif /* __HA_MSG_H */ 465