diff --git a/crm/common/Makefile.am b/crm/common/Makefile.am index 45a37613e8..edad54aadc 100644 --- a/crm/common/Makefile.am +++ b/crm/common/Makefile.am @@ -1,65 +1,65 @@ # # Copyright (C) 2004 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_builddir)/libltdl -I$(top_srcdir)/libltdl \ -I$(top_builddir)/linux-ha -I$(top_srcdir)/linux-ha \ -I$(top_builddir) -I$(top_srcdir) hadir = $(sysconfdir)/ha.d halibdir = $(libdir)/@HB_PKG@ commmoddir = $(halibdir)/modules/comm havarlibdir = $(localstatedir)/lib/@HB_PKG@ PIDFILE = $(localstatedir)/run/crmd.pid XML_FLAGS = `xml2-config --cflags` XML_LIBS = `xml2-config --libs` # sockets with path crmdir = $(havarlibdir)/crm apigid = @HA_APIGID@ crmuid = @HA_CCMUID@ crmreqsocket = $(havarlibdir)/api/crm.req crmressocket = $(havarlibdir)/api/crm.rsp LIBRT = @LIBRT@ AM_CFLAGS = @CFLAGS@ \ -DPIDFILE='"$(PIDFILE)"' \ $(CRM_DEBUG_FLAGS) ## libraries lib_LTLIBRARIES = libcrmcommon.la ## binary progs halib_PROGRAMS = ## SOURCES -noinst_HEADERS = crmutils.h ipcutils.h msgutils.h xmlutils.h +noinst_HEADERS = -libcrmcommon_la_SOURCES = ipcutils.c crmutils.c xmlutils.c msgutils.c +libcrmcommon_la_SOURCES = ipc.c msg.c utils.c xml.c ctrl.c libcrmcommon_la_LDFLAGS = -version-info 0:0:0 clean-generic: rm -f *.log *.debug *.xml *~ install-exec-local: uninstall-local: diff --git a/crm/common/crmutils.h b/crm/common/crmutils.h deleted file mode 100644 index f1349e26b8..0000000000 --- a/crm/common/crmutils.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $Id: crmutils.h,v 1.7 2004/05/06 12:13:45 andrew Exp $ */ -/* - * Copyright (C) 2004 Andrew Beekhof - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef CRM_UTILS__H -#define CRM_UTILS__H - - -#include -#include -#include -#include - -extern gboolean tickle_apphb_template(gpointer data); - -extern void register_pid( - const char *pid_file, - gboolean do_fork, - void (*shutdown)(int nsig)); - -extern long get_running_pid(const char *pid_file, gboolean* anypidfile); - -extern int init_status(const char *pid_file, const char *client_name); - -extern int init_stop(const char *pid_file); - -extern gboolean register_with_ha( - ll_cluster_t *hb_cluster, const char *client_name, - gboolean (*dispatch_method)(int fd, gpointer user_data), - void (*message_callback)(const struct ha_msg* msg, void* private_data), - GDestroyNotify cleanup_method); - -extern void register_with_apphb( - const char *client_name, - gboolean(*tickle_fn)(gpointer data)); - -extern char *crm_itoa(int an_int); - -extern gboolean subsystem_input_dispatch(IPC_Channel *sender, void *user_data); - -#endif diff --git a/crm/common/ctrl.c b/crm/common/ctrl.c new file mode 100644 index 0000000000..cb21bbf81e --- /dev/null +++ b/crm/common/ctrl.c @@ -0,0 +1,216 @@ +/* $Id: ctrl.c,v 1.1 2004/06/02 11:45:28 andrew Exp $ */ +/* + * Copyright (C) 2004 Andrew Beekhof + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + + +static int wdt_interval_ms = 10000; + + +void +register_pid(const char *pid_file, + gboolean do_fork, + void (*shutdown)(int nsig)) +{ + int j; + long pid; + FILE * lockfd; + + if (do_fork) { + pid = fork(); + + if (pid < 0) { + cl_log(LOG_CRIT, "cannot start daemon"); + exit(LSB_EXIT_GENERIC); + }else if (pid > 0) { + exit(LSB_EXIT_OK); + } + } + + lockfd = fopen(pid_file, "w"); + if (lockfd == NULL) { + cl_log(LOG_CRIT, "cannot create pid file: %s", pid_file); + exit(LSB_EXIT_GENERIC); + }else{ + pid = getpid(); + fprintf(lockfd, "%ld\n", pid); + fclose(lockfd); + } + + umask(022); + + for (j=0; j < 3; ++j) { + close(j); + (void)open("/dev/null", j == 0 ? O_RDONLY : O_RDONLY); + } +// CL_IGNORE_SIG(SIGINT); +// CL_IGNORE_SIG(SIGHUP); + CL_SIGNAL(SIGTERM, shutdown); +} + +long +get_running_pid(const char *pid_file, gboolean* anypidfile) +{ + long pid; + FILE * lockfd; + lockfd = fopen(pid_file, "r"); + + if (anypidfile) { + *anypidfile = (lockfd != NULL); + } + + if (lockfd != NULL + && fscanf(lockfd, "%ld", &pid) == 1 && pid > 0) { + if (CL_PID_EXISTS((pid_t)pid)) { + fclose(lockfd); + return(pid); + } + } + if (lockfd != NULL) { + fclose(lockfd); + } + return(-1L); +} + +int +init_stop(const char *pid_file) +{ + long pid; + int rc = LSB_EXIT_OK; + + FNIN(); + + if (pid_file == NULL) { + cl_log(LOG_ERR, "No pid file specified to kill process"); + return LSB_EXIT_GENERIC; + } + pid = get_running_pid(pid_file, NULL); + + if (pid > 0) { + if (CL_KILL((pid_t)pid, SIGTERM) < 0) { + rc = (errno == EPERM + ? LSB_EXIT_EPERM : LSB_EXIT_GENERIC); + fprintf(stderr, "Cannot kill pid %ld\n", pid); + }else{ + cl_log(LOG_INFO, + "Signal sent to pid=%ld," + " waiting for process to exit", + pid); + + while (CL_PID_EXISTS(pid)) { + sleep(1); + } + } + } + FNRET(rc); +} + +int +init_status(const char *pid_file, const char *client_name) +{ + gboolean anypidfile; + long pid = get_running_pid(pid_file, &anypidfile); + + if (pid > 0) { + fprintf(stderr, "%s is running [pid: %ld]\n" + , client_name, pid); + return LSB_STATUS_OK; + } + if (anypidfile) { + fprintf(stderr, "%s is stopped [pidfile exists]\n" + , client_name); + return LSB_STATUS_VAR_PID; + } + fprintf(stderr, "%s is stopped.\n", client_name); + return LSB_STATUS_STOPPED; +} + +void +register_with_apphb(const char *client_name, + gboolean(*tickle_fn)(gpointer data)) +{ + char app_instance[APPNAME_LEN]; + int hb_intvl_ms = wdt_interval_ms * 2; + int rc = 0; + + // Register with apphb + cl_log(LOG_INFO, "Signing in with AppHb"); + sprintf(app_instance, "%s_%ld", client_name, (long)getpid()); + + cl_log(LOG_INFO, "Client %s registering with apphb", app_instance); + + rc = apphb_register(client_name, app_instance); + + if (rc < 0) { + cl_perror("%s registration failure", app_instance); + exit(1); + } + + cl_log(LOG_DEBUG, "Client %s registered with apphb", app_instance); + + cl_log(LOG_INFO, + "Client %s setting %d ms apphb heartbeat interval" + , app_instance, hb_intvl_ms); + rc = apphb_setinterval(hb_intvl_ms); + if (rc < 0) { + cl_perror("%s setinterval failure", app_instance); + exit(2); + } + + // regularly tell apphb that we are alive + cl_log(LOG_INFO, "Setting up AppHb Heartbeat"); + Gmain_timeout_add(wdt_interval_ms, tickle_fn, NULL); +} + + +gboolean +tickle_apphb_template(gpointer data) +{ + char app_instance[APPNAME_LEN]; + int rc = 0; + sprintf(app_instance, "%s_%ld", "our_system_name", (long)getpid()); + + rc = apphb_hb(); + if (rc < 0) { + cl_perror("%s apphb_hb failure", app_instance); + + exit(3); + } + return TRUE; +} diff --git a/crm/common/ipc.c b/crm/common/ipc.c new file mode 100644 index 0000000000..95c0f61022 --- /dev/null +++ b/crm/common/ipc.c @@ -0,0 +1,392 @@ +/* $Id: ipc.c,v 1.1 2004/06/02 11:45:28 andrew Exp $ */ +/* + * Copyright (C) 2004 Andrew Beekhof + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#include +#include + + +#include + +IPC_Message *create_simple_message(char *text, IPC_Channel *ch); +gboolean send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg); + + +gboolean +send_xmlipc_message(IPC_Channel *ipc_client, xmlNodePtr msg) +{ + int log_level = LOG_DEBUG; + char *xml_message = NULL; + IPC_Message *cib_dump = NULL; + gboolean res; + FNIN(); + + xml_message = dump_xml(msg); + + cib_dump = + create_simple_message(xml_message, ipc_client); + res = send_ipc_message(ipc_client, cib_dump); + crm_free(xml_message); + + if(res == FALSE) { + log_level = LOG_ERR; + } + + cl_log(log_level, + "Sending IPC message (ref=%s) to %s@%s %s.", + xmlGetProp(msg, XML_ATTR_REFERENCE), + xmlGetProp(msg, XML_ATTR_SYSTO), + xmlGetProp(msg, XML_ATTR_HOSTTO), + res?"succeeded":"failed"); + + FNRET(res); +} + + +gboolean +send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg) +{ + int lpc = 0; + gboolean all_is_good = TRUE; + FNIN(); + + if (msg == NULL) { + cl_log(LOG_WARNING, "cant send NULL message"); + all_is_good = FALSE; + } + else if (msg->msg_len <= 0) { + cl_log(LOG_WARNING, "cant send 0 sized message"); + all_is_good = FALSE; + } + else if (msg->msg_len > MAXDATASIZE) { + cl_log(LOG_WARNING, "cant send msg... too big"); + all_is_good = FALSE; + } + +/* CRM_DEBUG("Sending message: %s", (char*)msg->msg_body); */ + CRM_DEBUG("Message is%s valid to send", all_is_good?"":" not"); + + if (ipc_client == NULL) { + all_is_good = FALSE; + } + CRM_DEBUG("IPC Client is%s set.", all_is_good?"":" not"); + if (all_is_good) { + while(lpc++ < MAX_IPC_FAIL + && ipc_client->ops->send(ipc_client, msg) == IPC_FAIL) + { + cl_log(LOG_WARNING, "ipc channel blocked"); + cl_shortsleep(); + } + } + + if (lpc == MAX_IPC_FAIL) { + cl_log(LOG_ERR, + "Could not send IPC, message. Channel is dead."); + all_is_good = FALSE; + } + + FNRET(all_is_good); +} + +IPC_Message * +create_simple_message(char *text, IPC_Channel *ch) +{ + // char str[256]; + IPC_Message *ack_msg = NULL; + + FNIN(); + if (text == NULL) FNRET(NULL); + + ack_msg = (IPC_Message *)crm_malloc(sizeof(IPC_Message)); + + ack_msg->msg_private = NULL; + ack_msg->msg_done = NULL; + ack_msg->msg_body = text; + ack_msg->msg_ch = ch; + + ack_msg->msg_len = strlen(text)+1; + + FNRET(ack_msg); +} + + +xmlNodePtr +find_xml_in_ipcmessage(IPC_Message *msg, gboolean do_free) +{ + char *buffer = NULL; + xmlDocPtr doc; + xmlNodePtr root; + + FNIN(); + if (msg == NULL) { + CRM_NOTE("IPC Message was empty..."); + FNRET(NULL); + } + + buffer = (char*)msg->msg_body; + doc = xmlParseMemory(buffer, strlen(buffer)); + + if (do_free) msg->msg_done(msg); + + if (doc == NULL) { + cl_log(LOG_INFO, + "IPC Message did not contain an XML buffer..."); + FNRET(NULL); + } + + root = xmlDocGetRootElement(doc); + if (root == NULL) { + cl_log(LOG_INFO, "Root node was NULL."); + FNRET(NULL); + } + FNRET(root); +} + + + +void +default_ipc_input_destroy(gpointer user_data) +{ + FNIN(); + FNOUT(); +} + + +IPC_Channel * +init_client_ipc_comms(const char *child, + gboolean (*dispatch)(IPC_Channel* source_data + ,gpointer user_data), + crmd_client_t *client_data) +{ + IPC_Channel *ch; + GHashTable * attrs; + GCHSource *the_source = NULL; + void *callback_data = client_data; + static char path[] = IPC_PATH_ATTR; + char *commpath = NULL; + int local_socket_len = 2; // 2 = '/' + '\0' + + FNIN(); + local_socket_len += strlen(child); + local_socket_len += strlen(WORKING_DIR); + + commpath = (char*)crm_malloc(sizeof(char)*local_socket_len); + sprintf(commpath, WORKING_DIR "/%s", child); + commpath[local_socket_len - 1] = '\0'; + + cl_log(LOG_DEBUG, "Attempting to talk on: %s", commpath); + + attrs = g_hash_table_new(g_str_hash,g_str_equal); + g_hash_table_insert(attrs, path, commpath); + + ch = ipc_channel_constructor(IPC_ANYTYPE, attrs); + g_hash_table_destroy(attrs); + + if (ch == NULL) { + cl_log(LOG_CRIT, + "Could not access channel on: %s", + commpath); + + } else if (ch->ops->initiate_connection(ch) != IPC_OK) { + cl_log(LOG_CRIT, "Could not init comms on: %s", commpath); + FNRET(NULL); + } + + if(callback_data == NULL) + callback_data = ch; + + ch->ops->set_recv_qlen(ch, 100); + ch->ops->set_send_qlen(ch, 100); + + the_source = G_main_add_IPC_Channel(G_PRIORITY_LOW, + ch, + FALSE, + dispatch, + callback_data, + default_ipc_input_destroy); + + cl_log(LOG_DEBUG, "Processing of %s complete", commpath); + + FNRET(ch); +} + + +/* + * This method adds a copy of xml_response_data + */ +gboolean +send_ipc_request(IPC_Channel *ipc_channel, + xmlNodePtr msg_options, xmlNodePtr msg_data, + const char *host_to, const char *sys_to, + const char *sys_from, const char *uuid_from, + const char *crm_msg_reference) +{ + gboolean was_sent = FALSE; + xmlNodePtr request = NULL; + FNIN(); + + request = create_request(msg_options, msg_data, + host_to, sys_to, + sys_from, uuid_from, + crm_msg_reference); + +// xml_message_debug(request, "Final request..."); + + was_sent = send_xmlipc_message(ipc_channel, request); + + free_xml(request); + + FNRET(was_sent); +} + + +/* + * This method adds a copy of xml_response_data + */ +gboolean +send_ipc_reply(IPC_Channel *ipc_channel, + xmlNodePtr xml_request, + xmlNodePtr xml_response_data) +{ + gboolean was_sent = FALSE; + xmlNodePtr reply; + FNIN(); + + reply = create_reply(xml_request, xml_response_data); + +// xml_message_debug(reply, "Final reply..."); + + if (reply != NULL) { + was_sent = send_xmlipc_message(ipc_channel, reply); + free_xml(reply); + } + FNRET(was_sent); +} + + +gboolean +subsystem_input_dispatch(IPC_Channel *sender, void *user_data) +{ + int lpc = 0; + char *buffer = NULL; + IPC_Message *msg = NULL; + gboolean all_is_well = TRUE; + xmlNodePtr root_xml_node = NULL; + const char *sys_to; + const char *type; + + + FNIN(); + + while(sender->ops->is_message_pending(sender)) { + if (sender->ch_status == IPC_DISCONNECT) { + /* The message which was pending for us is that + * the IPC status is now IPC_DISCONNECT */ + break; + } + if (sender->ops->recv(sender, &msg) != IPC_OK) { + perror("Receive failure:"); + FNRET(!all_is_well); + } + if (msg == NULL) { + cl_log(LOG_ERR, "No message this time"); + continue; + } + + lpc++; + + + buffer = (char*)msg->msg_body; + root_xml_node = string2xml(buffer); + + sys_to= xmlGetProp(root_xml_node, XML_ATTR_SYSTO); + type = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE); + if (root_xml_node == NULL) { + cl_log(LOG_ERR, "Root node was NULL!!"); + + } else if(sys_to == NULL) { + cl_log(LOG_ERR, "Value of %s was NULL!!", + XML_ATTR_SYSTO); + + } else if(type == NULL) { + cl_log(LOG_ERR, "Value of %s was NULL!!", + XML_ATTR_MSGTYPE); + + } else { + gboolean (*process_function) + (xmlNodePtr msg, IPC_Channel *sender) = NULL; + process_function = user_data; + + if(process_function(root_xml_node, sender) == FALSE) { + cl_log(LOG_WARNING, + "Received a message destined for %s" + " by mistake", sys_to); + } + + } + + free_xml(root_xml_node); + root_xml_node = NULL; + + msg->msg_done(msg); + msg = NULL; + } + + // clean up after a break + if(msg != NULL) + msg->msg_done(msg); + + if(root_xml_node != NULL) + free_xml(root_xml_node); + + CRM_DEBUG("Processed %d messages", lpc); + if (sender->ch_status == IPC_DISCONNECT) { + cl_log(LOG_ERR, "The server has left us: Shutting down...NOW"); + + exit(1); // shutdown properly later + + FNRET(!all_is_well); + } + FNRET(all_is_well); +} diff --git a/crm/common/ipcutils.c b/crm/common/ipcutils.c deleted file mode 100644 index 9579f4658f..0000000000 --- a/crm/common/ipcutils.c +++ /dev/null @@ -1,553 +0,0 @@ -/* $Id: ipcutils.c,v 1.30 2004/06/01 16:12:49 andrew Exp $ */ -/* - * Copyright (C) 2004 Andrew Beekhof - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include - -//#include // for getNow() - -#include -/* -#include -#include -*/ -#include -#include -#include - - -#include - -FILE *msg_out_strm = NULL; - -IPC_Message *create_simple_message(char *text, IPC_Channel *ch); - - -void -LinkStatus(const char * node, const char * lnk, - const char * status ,void * private) -{ - // put something here -} - -gboolean -send_xmlipc_message(IPC_Channel *ipc_client, xmlNodePtr msg) -{ - int log_level = LOG_DEBUG; - char *xml_message = NULL; - IPC_Message *cib_dump = NULL; - gboolean res; - FNIN(); - - xml_message = dump_xml(msg); - - cib_dump = - create_simple_message(xml_message, ipc_client); - res = send_ipc_message(ipc_client, cib_dump); - crm_free(xml_message); - - if(res == FALSE) { - log_level = LOG_ERR; - } - - cl_log(log_level, - "Sending IPC message (ref=%s) to %s@%s %s.", - xmlGetProp(msg, XML_ATTR_REFERENCE), - xmlGetProp(msg, XML_ATTR_SYSTO), - xmlGetProp(msg, XML_ATTR_HOSTTO), - res?"succeeded":"failed"); - - FNRET(res); -} - - -gboolean -send_xmlha_message(ll_cluster_t *hb_fd, xmlNodePtr root) -{ - int xml_len = -1; - int send_result = -1; - char *xml_text = NULL; - const char *host_to = NULL; - const char *sys_to = NULL; - struct ha_msg *msg = NULL; - gboolean all_is_good = TRUE; - gboolean broadcast = FALSE; - int log_level = LOG_DEBUG; - - xmlNodePtr opts = find_xml_node(root, XML_TAG_OPTIONS); - const char *op = xmlGetProp(opts, XML_ATTR_OP); - -#ifdef MSG_LOG - char *msg_text = NULL; -#endif - - FNIN(); - - if (root == NULL) { - cl_log(LOG_ERR, "Attempt to send NULL Message via HA failed."); - all_is_good = FALSE; - } - - host_to = xmlGetProp(root, XML_ATTR_HOSTTO); - sys_to = xmlGetProp(root, XML_ATTR_SYSTO); - - if (all_is_good) { - msg = ha_msg_new(4); - ha_msg_add(msg, F_TYPE, "CRM"); - ha_msg_add(msg, F_COMMENT, "A CRM xml message"); - xml_text = dump_xml(root); - xml_len = strlen(xml_text); - - if (xml_text == NULL || xml_len <= 0) { - cl_log(LOG_ERR, - "Failed sending an invalid XML Message via HA"); - all_is_good = FALSE; - xml_message_debug(root, "Bad message was"); - - } else { - if(ha_msg_add(msg, "xml", xml_text) == HA_FAIL) { - cl_log(LOG_ERR, - "Could not add xml to HA message"); - all_is_good = FALSE; - } - } - } - - if (all_is_good) { - if (sys_to == NULL || strlen(sys_to) == 0) - { - cl_log(LOG_ERR, - "You did not specify a destination sub-system" - " for this message."); - all_is_good = FALSE; - } - } - - - /* There are a number of messages may not need to be ordered. - * At a later point perhaps we should detect them and send them - * as unordered messages. - */ - if (all_is_good) { - if (host_to == NULL - || strlen(host_to) == 0) { - broadcast = TRUE; - send_result = - hb_fd->llc_ops->sendclustermsg(hb_fd, msg); - } - else { - send_result = hb_fd->llc_ops->send_ordered_nodemsg( - hb_fd, msg, host_to); - } - - if(send_result != HA_OK) - all_is_good = FALSE; - } - - if(all_is_good == FALSE) { - log_level = LOG_ERR; - } - - if(log_level == LOG_ERR - || (safe_str_neq(op, CRM_OP_HBEAT))) { - cl_log(log_level, - "Sending %s HA message (ref=%s, len=%d) to %s@%s %s.", - broadcast?"broadcast":"directed", - xmlGetProp(root, XML_ATTR_REFERENCE), xml_len, - sys_to, host_to==NULL?"":host_to, - all_is_good?"succeeded":"failed"); - } - -#ifdef MSG_LOG - msg_text = dump_xml(root); - if(msg_out_strm == NULL) { - msg_out_strm = fopen("/tmp/outbound.log", "w"); - } - fprintf(msg_out_strm, "[%d HA (%s:%d)]\t%s\n", - all_is_good, - xmlGetProp(root, XML_ATTR_REFERENCE), - send_result, - msg_text); - - fflush(msg_out_strm); - crm_free(msg_text); - if(msg != NULL) { - ha_msg_del(msg); - } -#endif - - FNRET(all_is_good); -} - - -gboolean -send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg) -{ - int lpc = 0; - gboolean all_is_good = TRUE; - FNIN(); - - if (msg == NULL) { - cl_log(LOG_WARNING, "cant send NULL message"); - all_is_good = FALSE; - } - else if (msg->msg_len <= 0) { - cl_log(LOG_WARNING, "cant send 0 sized message"); - all_is_good = FALSE; - } - else if (msg->msg_len > MAXDATASIZE) { - cl_log(LOG_WARNING, "cant send msg... too big"); - all_is_good = FALSE; - } - -/* CRM_DEBUG("Sending message: %s", (char*)msg->msg_body); */ - CRM_DEBUG("Message is%s valid to send", all_is_good?"":" not"); - - if (ipc_client == NULL) { - all_is_good = FALSE; - } - CRM_DEBUG("IPC Client is%s set.", all_is_good?"":" not"); - if (all_is_good) { - while(lpc++ < MAX_IPC_FAIL - && ipc_client->ops->send(ipc_client, msg) == IPC_FAIL) - { - cl_log(LOG_WARNING, "ipc channel blocked"); - cl_shortsleep(); - } - } - - if (lpc == MAX_IPC_FAIL) { - cl_log(LOG_ERR, - "Could not send IPC, message. Channel is dead."); - all_is_good = FALSE; - } - - FNRET(all_is_good); -} - -IPC_Message * -create_simple_message(char *text, IPC_Channel *ch) -{ - // char str[256]; - IPC_Message *ack_msg = NULL; - - FNIN(); - if (text == NULL) FNRET(NULL); - - ack_msg = (IPC_Message *)crm_malloc(sizeof(IPC_Message)); - - ack_msg->msg_private = NULL; - ack_msg->msg_done = NULL; - ack_msg->msg_body = text; - ack_msg->msg_ch = ch; - - ack_msg->msg_len = strlen(text)+1; - - FNRET(ack_msg); -} - -gboolean -default_ipc_input_dispatch(IPC_Channel *client, gpointer user_data) -{ - xmlNodePtr root; - xmlNodePtr options; - IPC_Message *msg = NULL; - const char *op; - - FNIN(); - msg = get_ipc_message(client); - if (msg) { - root = find_xml_in_ipcmessage(msg, TRUE); - validate_crm_message(root, NULL, NULL, NULL); - options = find_xml_node(root, XML_TAG_OPTIONS); - op = xmlGetProp(options, XML_ATTR_OP); - if(op != NULL && strcmp(op, CRM_OP_QUIT) == 0) { - cl_log(LOG_WARNING, - "The CRMd has asked us to exit... complying"); - exit(0); - } - - - } else if (client->ch_status == IPC_DISCONNECT) { - cl_log(LOG_ERR, "The server has left us: Shutting down...NOW"); - - exit(1); /* Server disconnects should be fatal, - * but I will do it a little more gracefully :) - */ - FNRET(FALSE); /* This conection is hosed */ - } - - FNRET(TRUE); /* TOBEDONE */ -} - -xmlNodePtr -find_xml_in_hamessage(const struct ha_msg* msg) -{ - const char *xml; - xmlDocPtr doc; - xmlNodePtr root; - - FNIN(); - if (msg == NULL) { - cl_log(LOG_INFO, - "**** ha_crm_msg_callback called on a NULL message"); - FNRET(NULL); - } - -#if 0 - cl_log(LOG_DEBUG, "[F_TYPE=%s]", ha_msg_value(msg, F_TYPE)); - cl_log(LOG_DEBUG, "[F_ORIG=%s]", ha_msg_value(msg, F_ORIG)); - cl_log(LOG_DEBUG, "[F_TO=%s]", ha_msg_value(msg, F_TO)); - cl_log(LOG_DEBUG, "[F_COMMENT=%s]", ha_msg_value(msg, F_COMMENT)); - cl_log(LOG_DEBUG, "[F_XML=%s]", ha_msg_value(msg, "xml")); -// cl_log(LOG_DEBUG, "[F_=%s]", ha_msg_value(ha_msg, F_)); -#endif - - if (strcmp("CRM", ha_msg_value(msg, F_TYPE)) != 0) { - cl_log(LOG_INFO, "Received a (%s) message by mistake.", - ha_msg_value(msg, F_TYPE)); - FNRET(NULL); - } - xml = ha_msg_value(msg, "xml"); - if (xml == NULL) { - cl_log(LOG_INFO, "No XML attached to this message."); - FNRET(NULL); - } - doc = xmlParseMemory(xml, strlen(xml)); - if (doc == NULL) { - cl_log(LOG_INFO, "XML Buffer was not valid."); - FNRET(NULL); - } - - root = xmlDocGetRootElement(doc); - if (root == NULL) { - cl_log(LOG_INFO, "Root node was NULL."); - FNRET(NULL); - } - FNRET(root); -} - -xmlNodePtr -find_xml_in_ipcmessage(IPC_Message *msg, gboolean do_free) -{ - char *buffer = NULL; - xmlDocPtr doc; - xmlNodePtr root; - - FNIN(); - if (msg == NULL) { - CRM_NOTE("IPC Message was empty..."); - FNRET(NULL); - } - - buffer = (char*)msg->msg_body; - doc = xmlParseMemory(buffer, strlen(buffer)); - - if (do_free) msg->msg_done(msg); - - if (doc == NULL) { - cl_log(LOG_INFO, - "IPC Message did not contain an XML buffer..."); - FNRET(NULL); - } - - root = xmlDocGetRootElement(doc); - if (root == NULL) { - cl_log(LOG_INFO, "Root node was NULL."); - FNRET(NULL); - } - FNRET(root); -} - - - -void -default_ipc_input_destroy(gpointer user_data) -{ - FNIN(); - FNOUT(); -} - -int -init_server_ipc_comms( - const char *child, - gboolean (*channel_client_connect)(IPC_Channel *newclient, - gpointer user_data), - void (*channel_input_destroy)(gpointer user_data)) -{ - /* the clients wait channel is the other source of events. - * This source delivers the clients connection events. - * listen to this source at a relatively lower priority. - */ - - char commpath[SOCKET_LEN]; - IPC_WaitConnection *wait_ch; - - FNIN(); - sprintf(commpath, WORKING_DIR "/%s", child); - - wait_ch = wait_channel_init(commpath); - - if (wait_ch == NULL) FNRET(1); - G_main_add_IPC_WaitConnection(G_PRIORITY_LOW, - wait_ch, - NULL, - FALSE, - channel_client_connect, - wait_ch, // user data passed to ?? - channel_input_destroy); - - cl_log(LOG_DEBUG, "Listening on: %s", commpath); - - FNRET(0); -} - -IPC_Channel * -init_client_ipc_comms(const char *child, - gboolean (*dispatch)(IPC_Channel* source_data - ,gpointer user_data), - crmd_client_t *client_data) -{ - IPC_Channel *ch; - GHashTable * attrs; - GCHSource *the_source = NULL; - void *callback_data = client_data; - static char path[] = IPC_PATH_ATTR; - char *commpath = NULL; - int local_socket_len = 2; // 2 = '/' + '\0' - - FNIN(); - local_socket_len += strlen(child); - local_socket_len += strlen(WORKING_DIR); - - commpath = (char*)crm_malloc(sizeof(char)*local_socket_len); - sprintf(commpath, WORKING_DIR "/%s", child); - commpath[local_socket_len - 1] = '\0'; - - cl_log(LOG_DEBUG, "Attempting to talk on: %s", commpath); - - attrs = g_hash_table_new(g_str_hash,g_str_equal); - g_hash_table_insert(attrs, path, commpath); - - ch = ipc_channel_constructor(IPC_ANYTYPE, attrs); - g_hash_table_destroy(attrs); - - if (ch == NULL) { - cl_log(LOG_CRIT, - "Could not access channel on: %s", - commpath); - - } else if (ch->ops->initiate_connection(ch) != IPC_OK) { - cl_log(LOG_CRIT, "Could not init comms on: %s", commpath); - FNRET(NULL); - } - - if(callback_data == NULL) - callback_data = ch; - - ch->ops->set_recv_qlen(ch, 100); - ch->ops->set_send_qlen(ch, 100); - - the_source = G_main_add_IPC_Channel(G_PRIORITY_LOW, - ch, - FALSE, - dispatch, - callback_data, - default_ipc_input_destroy); - - cl_log(LOG_DEBUG, "Processing of %s complete", commpath); - - FNRET(ch); -} - - -IPC_WaitConnection * -wait_channel_init(char daemonsocket[]) -{ - IPC_WaitConnection *wait_ch; - mode_t mask; - char path[] = IPC_PATH_ATTR; - GHashTable * attrs; - - FNIN(); - attrs = g_hash_table_new(g_str_hash,g_str_equal); - g_hash_table_insert(attrs, path, daemonsocket); - - mask = umask(0); - wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs); - if (wait_ch == NULL) { - cl_perror("Can't create wait channel of type %s", - IPC_ANYTYPE); - exit(1); - } - mask = umask(mask); - - g_hash_table_destroy(attrs); - - FNRET(wait_ch); -} - -IPC_Message * -get_ipc_message(IPC_Channel *a_channel) -{ - IPC_Message *msg = NULL; - - FNIN(); - if(a_channel->ops->is_message_pending(a_channel) == TRUE) { - if (a_channel->ch_status == IPC_DISCONNECT) { - /* The pending message was IPC_DISCONNECT */ - cl_log(LOG_INFO, "get_ipc_message: received HUP"); - FNRET(msg); - } - if(a_channel->ops->recv(a_channel, &msg) != IPC_OK) { - perror("Receive failure:"); - FNRET(msg); - } - cl_log(LOG_INFO, "Got message [body=%s]", - (char*)msg->msg_body); - } - FNRET(msg); -} - diff --git a/crm/common/ipcutils.h b/crm/common/ipcutils.h deleted file mode 100644 index af76777aa2..0000000000 --- a/crm/common/ipcutils.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $Id: ipcutils.h,v 1.8 2004/03/18 10:48:51 andrew Exp $ */ -/* - * Copyright (C) 2004 Andrew Beekhof - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef IPCUTILS_H -#define IPCUTILS_H - -#include -#include -#include - -#include - -typedef struct _crmd_client -{ - char *sub_sys; - char *uuid; - char *table_key; - IPC_Channel *client_channel; - GCHSource *client_source; -} crmd_client_t; - -extern void LinkStatus(const char * node, const char * lnk, - const char * status ,void * private); - -extern gboolean default_ipc_input_dispatch(IPC_Channel *, gpointer); - -extern void default_ipc_input_destroy(gpointer user_data); - -extern int init_server_ipc_comms( - const char *child, - gboolean (*channel_client_connect)(IPC_Channel *newclient, - gpointer user_data), - void (*channel_input_destroy)(gpointer user_data)); - -extern IPC_Channel *init_client_ipc_comms( - const char *child, - gboolean (*dispatch)(IPC_Channel* source_data, gpointer user_data), - crmd_client_t *user_data); - -extern IPC_WaitConnection *wait_channel_init(char daemonsocket[]); - -extern IPC_Message *get_ipc_message(IPC_Channel *client); - -extern char *dump_xml(xmlNodePtr msg); - -extern char *dump_xml_node(xmlNodePtr msg, gboolean whole_doc); - -extern xmlNodePtr find_xml_in_hamessage(const struct ha_msg* msg); - -extern xmlNodePtr find_xml_in_ipcmessage(IPC_Message *msg, - gboolean do_free); - -extern gboolean send_xmlipc_message(IPC_Channel *ipc_client, - xmlNodePtr msg); - -extern gboolean send_xmlha_message(ll_cluster_t *hb_fd, xmlNodePtr root); - -extern gboolean send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg); - -extern IPC_Message *get_ipc_message(IPC_Channel *client); - - -#endif - diff --git a/crm/common/msgutils.c b/crm/common/msg.c similarity index 59% rename from crm/common/msgutils.c rename to crm/common/msg.c index 879909425a..e57a6c9c0d 100644 --- a/crm/common/msgutils.c +++ b/crm/common/msg.c @@ -1,725 +1,407 @@ -/* $Id: msgutils.c,v 1.32 2004/06/01 16:03:31 andrew Exp $ */ +/* $Id: msg.c,v 1.1 2004/06/02 11:45:28 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include -#include #include #include -#include - -#include -#include -#include +#include #include - +#include #include xmlNodePtr create_common_message(xmlNodePtr original_request, xmlNodePtr xml_response_data); xmlNodePtr createPingAnswerFragment(const char *from, const char *status) { xmlNodePtr ping = NULL; FNIN(); ping = create_xml_node(NULL, XML_CRM_TAG_PING); set_xml_property_copy(ping, XML_PING_ATTR_STATUS, status); set_xml_property_copy(ping, XML_PING_ATTR_SYSFROM, from); FNRET(ping); } xmlNodePtr createPingRequest(const char *crm_msg_reference, const char *to) { xmlNodePtr root_xml_node = NULL; int sub_type_len; int msg_type_len; char *sub_type_target; char *msg_type_target; FNIN(); // 2 = "_" + '\0' sub_type_len = strlen(to) + strlen(XML_ATTR_REQUEST) + 2; sub_type_target = (char*)crm_malloc(sizeof(char)*(sub_type_len)); sprintf(sub_type_target, "%s_%s", to, XML_ATTR_REQUEST); root_xml_node = create_xml_node(NULL, sub_type_target); set_xml_property_copy(root_xml_node, XML_ATTR_REFERENCE, crm_msg_reference); msg_type_len = strlen(to) + 10 + 1; // + "_operation" + '\0' msg_type_target = (char*)crm_malloc(sizeof(char)*(msg_type_len)); sprintf(msg_type_target, "%s_operation", to); set_xml_property_copy(root_xml_node, msg_type_target, CRM_OP_PING); crm_free(msg_type_target); FNRET(root_xml_node); } -static uint ref_counter = 0; - -const char * -generateReference(const char *custom1, const char *custom2) -{ - - const char *local_cust1 = custom1; - const char *local_cust2 = custom2; - int reference_len = 4; - char *since_epoch = NULL; - - FNIN(); - - reference_len += 20; // too big - reference_len += 40; // too big - - if(local_cust1 == NULL) local_cust1 = "_empty_"; - reference_len += strlen(local_cust1); - - if(local_cust2 == NULL) local_cust2 = "_empty_"; - reference_len += strlen(local_cust2); - - since_epoch = (char*)crm_malloc(reference_len*(sizeof(char))); - FNIN(); - sprintf(since_epoch, "%s-%s-%ld-%u", - local_cust1, local_cust2, - (unsigned long)time(NULL), ref_counter++); - - FNRET(since_epoch); -} - xmlNodePtr validate_crm_message(xmlNodePtr root_xml_node, const char *sys, const char *uuid, const char *msg_type) { const char *from = NULL; const char *to = NULL; const char *type = NULL; const char *crm_msg_reference = NULL; xmlNodePtr action = NULL; const char *true_sys; FNIN(); - if (root_xml_node == NULL) + if (root_xml_node == NULL) { FNRET(NULL); + } from = xmlGetProp(root_xml_node, XML_ATTR_SYSFROM); to = xmlGetProp(root_xml_node, XML_ATTR_SYSTO); type = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE); crm_msg_reference = xmlGetProp(root_xml_node, XML_ATTR_REFERENCE); /* cl_log(LOG_DEBUG, "Recieved XML message with (version=%s)", xmlGetProp(root_xml_node, XML_ATTR_VERSION)); cl_log(LOG_DEBUG, "Recieved XML message with (from=%s)", from); cl_log(LOG_DEBUG, "Recieved XML message with (to=%s)" , to); cl_log(LOG_DEBUG, "Recieved XML message with (type=%s)", type); cl_log(LOG_DEBUG, "Recieved XML message with (ref=%s)" , crm_msg_reference); */ action = root_xml_node; true_sys = sys; if (uuid != NULL) true_sys = generate_hash_key(sys, uuid); if (to == NULL) { cl_log(LOG_INFO, "No sub-system defined."); action = NULL; } else if (true_sys != NULL && strcmp(to, true_sys) != 0) { cl_log(LOG_DEBUG, "The message is not for this sub-system (%s != %s).", to, true_sys); action = NULL; } if (type == NULL) { cl_log(LOG_INFO, "No message type defined."); FNRET(NULL); } else if (msg_type != NULL && strcmp(msg_type, type) != 0) { cl_log(LOG_INFO, "Expecting a (%s) message but receieved a (%s).", msg_type, type); action = NULL; } if (crm_msg_reference == NULL) { cl_log(LOG_INFO, "No message crm_msg_reference defined."); action = NULL; } /* if(action != NULL) cl_log(LOG_DEBUG, "XML is valid and node with message type (%s) found.", type); cl_log(LOG_DEBUG, "Returning node (%s)", xmlGetNodePath(action)); */ FNRET(action); } -gboolean -decodeNVpair(const char *srcstring, char separator, char **name, char **value) -{ - int lpc = 0; - int len = 0; - const char *temp = NULL; - - FNIN(); - - CRM_DEBUG("Attempting to decode: [%s]", srcstring); - if (srcstring != NULL) { - len = strlen(srcstring); - while(lpc < len) { - if (srcstring[lpc++] == separator) { - *name = (char*)crm_malloc(sizeof(char)*lpc); - strncpy(*name, srcstring, lpc-1); - (*name)[lpc-1] = '\0'; - - // this sucks but as the strtok *is* a bug - len = len-lpc+1; - *value = (char*)crm_malloc(sizeof(char)*len); - temp = srcstring+lpc; - strncpy(*value, temp, len-1); - (*value)[len-1] = '\0'; - - FNRET(TRUE); - } - } - } - - *name = NULL; - *value = NULL; - - FNRET(FALSE); -} - -char * -generate_hash_key(const char *crm_msg_reference, const char *sys) -{ - int ref_len = strlen(sys?sys:"none") + strlen(crm_msg_reference) + 2; - char *hash_key = (char*)crm_malloc(sizeof(char)*(ref_len)); - - FNIN(); - sprintf(hash_key, "%s_%s", sys?sys:"none", crm_msg_reference); - hash_key[ref_len-1] = '\0'; - cl_log(LOG_INFO, "created hash key: (%s)", hash_key); - FNRET(hash_key); -} - -char * -generate_hash_value(const char *src_node, const char *src_subsys) -{ - int ref_len; - char *hash_value; - - FNIN(); - if (src_node == NULL || src_subsys == NULL) { - FNRET(NULL); - } - - if (strcmp(CRM_SYSTEM_DC, src_subsys) == 0) { - hash_value = crm_strdup(src_subsys); - if (!hash_value) { - cl_log(LOG_ERR, - "memory allocation failed in " - "generate_hash_value()\n"); - FNRET(NULL); - } - FNRET(hash_value); - } - - ref_len = strlen(src_subsys) + strlen(src_node) + 2; - hash_value = (char*)crm_malloc(sizeof(char)*(ref_len)); - if (!hash_value) { - cl_log(LOG_ERR, - "memory allocation failed in " - "generate_hash_value()\n"); - FNRET(NULL); - } - - snprintf(hash_value, ref_len-1, "%s_%s", src_node, src_subsys); - hash_value[ref_len-1] = '\0';// make sure it is null terminated - - cl_log(LOG_INFO, "created hash value: (%s)", hash_value); - FNRET(hash_value); -} - -gboolean -decode_hash_value(gpointer value, char **node, char **subsys) -{ - char *char_value = (char*)value; - int value_len = strlen(char_value); - - FNIN(); - - cl_log(LOG_INFO, "Decoding hash value: (%s:%d)", - char_value, - value_len); - - if (strcmp(CRM_SYSTEM_DC, (char*)value) == 0) { - *node = NULL; - *subsys = (char*)crm_strdup(char_value); - if (!*subsys) { - cl_log(LOG_ERR, "memory allocation failed in " - "decode_hash_value()\n"); - FNRET(FALSE); - } - cl_log(LOG_INFO, "Decoded value: (%s:%d)", *subsys, - (int)strlen(*subsys)); - FNRET(TRUE); - } - else if (char_value != NULL) { - if (decodeNVpair(char_value, '_', node, subsys)) { - FNRET(TRUE); - } else { - *node = NULL; - *subsys = NULL; - FNRET(FALSE); - } - } - FNRET(FALSE); -} - void send_hello_message(IPC_Channel *ipc_client, const char *uuid, const char *client_name, const char *major_version, const char *minor_version) { xmlNodePtr hello_node = NULL; FNIN(); if (uuid == NULL || strlen(uuid) == 0 || client_name == NULL || strlen(client_name) == 0 || major_version == NULL || strlen(major_version) == 0 || minor_version == NULL || strlen(minor_version) == 0) { cl_log(LOG_ERR, "Missing fields, Hello message will not be valid."); return; } hello_node = create_xml_node(NULL, XML_TAG_OPTIONS); set_xml_property_copy(hello_node, "major_version", major_version); set_xml_property_copy(hello_node, "minor_version", minor_version); set_xml_property_copy(hello_node, "client_name", client_name); set_xml_property_copy(hello_node, "client_uuid", uuid); set_xml_property_copy(hello_node, XML_ATTR_OP, CRM_OP_HELLO); send_ipc_request(ipc_client, hello_node, NULL, NULL, NULL, client_name, uuid, NULL); free_xml(hello_node); } gboolean process_hello_message(xmlNodePtr hello, char **uuid, char **client_name, char **major_version, char **minor_version) { xmlNodePtr opts = NULL; const char *op = NULL; const char *local_uuid; const char *local_client_name; const char *local_major_version; const char *local_minor_version; FNIN(); *uuid = NULL; *client_name = NULL; *major_version = NULL; *minor_version = NULL; opts = find_xml_node(hello, XML_TAG_OPTIONS); op = xmlGetProp(opts, XML_ATTR_OP); local_uuid = xmlGetProp(opts, "client_uuid"); local_client_name = xmlGetProp(opts, "client_name"); local_major_version = xmlGetProp(opts, "major_version"); local_minor_version = xmlGetProp(opts, "minor_version"); if (op == NULL || strcmp(CRM_OP_HELLO, op) != 0) { FNRET(FALSE); } else if (local_uuid == NULL || strlen(local_uuid) == 0) { cl_log(LOG_ERR, "Hello message was not valid (field %s not found)", "uuid"); FNRET(FALSE); } else if (local_client_name==NULL || strlen(local_client_name)==0){ cl_log(LOG_ERR, "Hello message was not valid (field %s not found)", "client name"); FNRET(FALSE); } else if(local_major_version == NULL || strlen(local_major_version) == 0){ cl_log(LOG_ERR, "Hello message was not valid (field %s not found)", "major version"); FNRET(FALSE); } else if (local_minor_version == NULL || strlen(local_minor_version) == 0){ cl_log(LOG_ERR, "Hello message was not valid (field %s not found)", "minor version"); FNRET(FALSE); } *uuid = crm_strdup(local_uuid); *client_name = crm_strdup(local_client_name); *major_version = crm_strdup(local_major_version); *minor_version = crm_strdup(local_minor_version); FNRET(TRUE); } -gboolean -forward_ipc_request(IPC_Channel *ipc_channel, - xmlNodePtr xml_request, xmlNodePtr xml_response_data, - const char *sys_to, const char *sys_from) -{ - gboolean was_sent = FALSE; - xmlNodePtr forward; - - FNIN(); - forward = create_forward(xml_request, - xml_response_data, - sys_to); - - if (forward != NULL) - { - was_sent = send_xmlipc_message(ipc_channel, forward); - free_xml(forward); - } - - FNRET(was_sent); -} - -/* - * This method adds a copy of xml_response_data - */ -gboolean -send_ipc_request(IPC_Channel *ipc_channel, - xmlNodePtr msg_options, xmlNodePtr msg_data, - const char *host_to, const char *sys_to, - const char *sys_from, const char *uuid_from, - const char *crm_msg_reference) -{ - gboolean was_sent = FALSE; - xmlNodePtr request = NULL; - FNIN(); - - request = create_request(msg_options, msg_data, - host_to, sys_to, - sys_from, uuid_from, - crm_msg_reference); - -// xml_message_debug(request, "Final request..."); - - was_sent = send_xmlipc_message(ipc_channel, request); - - free_xml(request); - - FNRET(was_sent); -} - -/* - * This method adds a copy of xml_response_data - */ -gboolean -send_ha_request(ll_cluster_t *hb_fd, - xmlNodePtr msg_options, xmlNodePtr msg_data, - const char *host_to, const char *sys_to, - const char *sys_from, const char *uuid_from, - const char *crm_msg_reference) -{ - gboolean was_sent = FALSE; - xmlNodePtr request = NULL; - FNIN(); - - request = create_request(msg_options, msg_data, - host_to, sys_to, - sys_from, uuid_from, - crm_msg_reference); - -// xml_message_debug(request, "Final request..."); - - was_sent = send_xmlha_message(hb_fd, request); - - free_xml(request); - - FNRET(was_sent); -} - xmlNodePtr create_request(xmlNodePtr msg_options, xmlNodePtr msg_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *crm_msg_reference) { const char *true_from = sys_from; xmlNodePtr request; FNIN(); if (uuid_from != NULL) true_from = generate_hash_key(sys_from, uuid_from); // else make sure we are internal else { if (strcmp(CRM_SYSTEM_LRMD, sys_from) != 0 && strcmp(CRM_SYSTEM_PENGINE, sys_from) != 0 && strcmp(CRM_SYSTEM_TENGINE, sys_from) != 0 && strcmp(CRM_SYSTEM_DC, sys_from) != 0 && strcmp(CRM_SYSTEM_CRMD, sys_from) != 0) { cl_log(LOG_ERR, "only internal systems can leave uuid_from blank"); FNRET(FALSE); } } if (crm_msg_reference == NULL) { crm_msg_reference = generateReference( xmlGetProp(msg_options,XML_ATTR_OP),sys_from); } // host_from will get set for us if necessary by CRMd when routed request = create_xml_node(NULL, XML_MSG_TAG); set_node_tstamp(request); set_xml_property_copy(request, XML_ATTR_VERSION, CRM_VERSION); set_xml_property_copy(request, XML_ATTR_MSGTYPE, XML_ATTR_REQUEST); set_xml_property_copy(request, XML_ATTR_SYSTO, sys_to); set_xml_property_copy(request, XML_ATTR_SYSFROM, true_from); set_xml_property_copy(request, XML_ATTR_REFERENCE, crm_msg_reference); if(host_to != NULL && strlen(host_to) > 0) set_xml_property_copy(request, XML_ATTR_HOSTTO, host_to); if (msg_options != NULL) { add_node_copy(request, msg_options); } if (msg_data != NULL) { add_node_copy(request, msg_data); } FNRET(request); } -/* - * This method adds a copy of xml_response_data - */ -gboolean -send_ipc_reply(IPC_Channel *ipc_channel, - xmlNodePtr xml_request, - xmlNodePtr xml_response_data) -{ - gboolean was_sent = FALSE; - xmlNodePtr reply; - FNIN(); - - reply = create_reply(xml_request, xml_response_data); - -// xml_message_debug(reply, "Final reply..."); - - if (reply != NULL) { - was_sent = send_xmlipc_message(ipc_channel, reply); - free_xml(reply); - } - FNRET(was_sent); -} - -// required? or just send to self an let relay_message do its thing? -/* - * This method adds a copy of xml_response_data - */ -gboolean -send_ha_reply(ll_cluster_t *hb_cluster, - xmlNodePtr xml_request, - xmlNodePtr xml_response_data) -{ - gboolean was_sent = FALSE; - xmlNodePtr reply; - - FNIN(); - was_sent = FALSE; - reply = create_reply(xml_request, xml_response_data); - if (reply != NULL) { - was_sent = send_xmlha_message(hb_cluster, reply); - free_xml(reply); - } - FNRET(was_sent); -} - /* * This method adds a copy of xml_response_data */ xmlNodePtr create_reply(xmlNodePtr original_request, xmlNodePtr xml_response_data) { const char *host_from = NULL; const char *sys_from = NULL; const char *sys_to = NULL; xmlNodePtr reply; FNIN(); host_from = xmlGetProp(original_request, XML_ATTR_HOSTFROM); sys_from = xmlGetProp(original_request, XML_ATTR_SYSFROM); sys_to = xmlGetProp(original_request, XML_ATTR_SYSTO); - reply = create_common_message(original_request, - xml_response_data); + reply = create_common_message(original_request, xml_response_data); set_xml_property_copy(reply, XML_ATTR_MSGTYPE, XML_ATTR_RESPONSE); /* since this is a reply, we reverse the from and to */ // HOSTTO will be ignored if it is to the DC anyway. if(host_from != NULL && strlen(host_from) > 0) set_xml_property_copy(reply, XML_ATTR_HOSTTO, host_from); set_xml_property_copy(reply, XML_ATTR_SYSTO, sys_from); set_xml_property_copy(reply, XML_ATTR_SYSFROM, sys_to); FNRET(reply); } -/* - * This method adds a copy of xml_response_data - */ -xmlNodePtr -create_forward(xmlNodePtr original_request, - xmlNodePtr xml_response_data, - const char *sys_to) -{ - const char *host_from = NULL; - const char *host_to = NULL; - const char *sys_from = NULL; - xmlNodePtr forward; - - FNIN(); - host_from = xmlGetProp(original_request, XML_ATTR_HOSTFROM); - host_to = xmlGetProp(original_request, XML_ATTR_HOSTTO); - sys_from = xmlGetProp(original_request, XML_ATTR_SYSFROM); - forward = create_common_message(original_request, - xml_response_data); - - set_xml_property_copy(forward, - XML_ATTR_MSGTYPE, - XML_ATTR_REQUEST); - - // HOSTTO will be ignored if it is to the DC anyway. - if(host_to != NULL && strlen(host_to) > 0) - set_xml_property_copy(forward, XML_ATTR_HOSTTO, host_to); - if(host_from != NULL) - set_xml_property_copy(forward, XML_ATTR_HOSTFROM, host_from); - - set_xml_property_copy(forward, XML_ATTR_SYSTO, sys_to); - set_xml_property_copy(forward, XML_ATTR_SYSFROM, sys_from); - - FNRET(forward); -} - xmlNodePtr create_common_message(xmlNodePtr original_request, xmlNodePtr xml_response_data) { const char *crm_msg_reference = NULL; const char *type = NULL; const char *operation = NULL; xmlNodePtr options = NULL; xmlNodePtr new_message; FNIN(); crm_msg_reference = xmlGetProp(original_request, XML_ATTR_REFERENCE); type = xmlGetProp(original_request, XML_ATTR_MSGTYPE); operation = xmlGetProp(original_request, XML_ATTR_OP); if (type == NULL) { cl_log(LOG_ERR, "Cannot create new_message," " no message type in original message"); FNRET(NULL); #if 0 } else if (strcmp(XML_ATTR_REQUEST, type) != 0) { cl_log(LOG_ERR, "Cannot create new_message," " original message was not a request"); FNRET(NULL); #endif } new_message = create_xml_node(NULL, XML_MSG_TAG); set_node_tstamp(new_message); set_xml_property_copy(new_message, XML_ATTR_VERSION, CRM_VERSION); set_xml_property_copy(new_message, XML_ATTR_OP, operation); set_xml_property_copy(new_message, XML_ATTR_REFERENCE, crm_msg_reference); if (xml_response_data != NULL) { add_node_copy(new_message, xml_response_data); } options = find_xml_node(original_request, XML_TAG_OPTIONS); if (options != NULL) { add_node_copy(new_message, options); } FNRET(new_message); } diff --git a/crm/common/msgutils.h b/crm/common/msgutils.h deleted file mode 100644 index e7a7cfb45c..0000000000 --- a/crm/common/msgutils.h +++ /dev/null @@ -1,108 +0,0 @@ -/* $Id: msgutils.h,v 1.11 2004/05/12 14:27:16 andrew Exp $ */ -/* - * Copyright (C) 2004 Andrew Beekhof - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef MSG_UTILS__H -#define MSG_UTILS__H - -#include -#include -#include - -extern const char *generateReference(const char *custom1, const char *custom2); - -extern xmlNodePtr validate_crm_message(xmlNodePtr root, - const char *sys, - const char *uuid, - const char *msg_type); - -extern xmlNodePtr createPingAnswerFragment(const char *from, - const char *status); - -extern xmlNodePtr createPingRequest(const char *crm_msg_reference, - const char *to); - -gboolean decodeNVpair(const char *srcstring, - char separator, - char **name, - char **value); - -extern void send_hello_message(IPC_Channel *ipc_client, - const char *uuid, - const char *client_name, - const char *major_version, - const char *minor_version); -extern gboolean process_hello_message(xmlNodePtr hello, - char **uuid, - char **client_name, - char **major_version, - char **minor_version); - -extern gboolean forward_ipc_request(IPC_Channel *ipc_channel, - xmlNodePtr xml_request, - xmlNodePtr xml_response_data, - const char *sys_to, - const char *sys_from); -extern gboolean -send_ipc_request(IPC_Channel *ipc_channel, - xmlNodePtr xml_options, xmlNodePtr xml_data, - const char *host_to, const char *sys_to, - const char *sys_from, const char *uuid_from, - const char *crm_msg_reference); - -extern gboolean -send_ha_request(ll_cluster_t *hb_fd, - xmlNodePtr xml_options, xmlNodePtr xml_data, - const char *host_to, const char *sys_to, - const char *sys_from, const char *uuid_from, - const char *crm_msg_reference); - -extern gboolean send_ha_reply(ll_cluster_t *hb_cluster, - xmlNodePtr xml_request, - xmlNodePtr xml_response_data); - -extern gboolean send_ipc_reply(IPC_Channel *ipc_channel, - xmlNodePtr xml_request, - xmlNodePtr xml_response_data); - -extern xmlNodePtr create_forward(xmlNodePtr xml_request, - xmlNodePtr xml_response_data, - const char *sys_to); - -extern xmlNodePtr createCrmMsg(xmlNodePtr data, - gboolean is_request); - -extern xmlNodePtr create_reply(xmlNodePtr xml_request, - xmlNodePtr xml_response_data); - -extern char *generate_hash_key(const char *crm_msg_reference, - const char *sys); - -extern char *generate_hash_value(const char *src_node, - const char *src_subsys); - -extern gboolean decode_hash_value(gpointer value, - char **node, - char **subsys); - -extern xmlNodePtr -create_request(xmlNodePtr xml_options, xmlNodePtr xml_data, - const char *host_to, const char *sys_to, - const char *sys_from, const char *uuid_from, - const char *crm_msg_reference); - -#endif diff --git a/crm/common/utils.c b/crm/common/utils.c new file mode 100644 index 0000000000..f6d0ec56cb --- /dev/null +++ b/crm/common/utils.c @@ -0,0 +1,203 @@ +/* $Id: utils.c,v 1.1 2004/06/02 11:45:28 andrew Exp $ */ +/* + * Copyright (C) 2004 Andrew Beekhof + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include + + +static uint ref_counter = 0; + +const char * +generateReference(const char *custom1, const char *custom2) +{ + + const char *local_cust1 = custom1; + const char *local_cust2 = custom2; + int reference_len = 4; + char *since_epoch = NULL; + + FNIN(); + + reference_len += 20; // too big + reference_len += 40; // too big + + if(local_cust1 == NULL) local_cust1 = "_empty_"; + reference_len += strlen(local_cust1); + + if(local_cust2 == NULL) local_cust2 = "_empty_"; + reference_len += strlen(local_cust2); + + since_epoch = (char*)crm_malloc(reference_len*(sizeof(char))); + FNIN(); + sprintf(since_epoch, "%s-%s-%ld-%u", + local_cust1, local_cust2, + (unsigned long)time(NULL), ref_counter++); + + FNRET(since_epoch); +} + +gboolean +decodeNVpair(const char *srcstring, char separator, char **name, char **value) +{ + int lpc = 0; + int len = 0; + const char *temp = NULL; + + FNIN(); + + CRM_DEBUG("Attempting to decode: [%s]", srcstring); + if (srcstring != NULL) { + len = strlen(srcstring); + while(lpc < len) { + if (srcstring[lpc++] == separator) { + *name = (char*)crm_malloc(sizeof(char)*lpc); + strncpy(*name, srcstring, lpc-1); + (*name)[lpc-1] = '\0'; + + // this sucks but as the strtok *is* a bug + len = len-lpc+1; + *value = (char*)crm_malloc(sizeof(char)*len); + temp = srcstring+lpc; + strncpy(*value, temp, len-1); + (*value)[len-1] = '\0'; + + FNRET(TRUE); + } + } + } + + *name = NULL; + *value = NULL; + + FNRET(FALSE); +} + +char * +generate_hash_key(const char *crm_msg_reference, const char *sys) +{ + int ref_len = strlen(sys?sys:"none") + strlen(crm_msg_reference) + 2; + char *hash_key = (char*)crm_malloc(sizeof(char)*(ref_len)); + + FNIN(); + sprintf(hash_key, "%s_%s", sys?sys:"none", crm_msg_reference); + hash_key[ref_len-1] = '\0'; + cl_log(LOG_INFO, "created hash key: (%s)", hash_key); + FNRET(hash_key); +} + +char * +generate_hash_value(const char *src_node, const char *src_subsys) +{ + int ref_len; + char *hash_value; + + FNIN(); + if (src_node == NULL || src_subsys == NULL) { + FNRET(NULL); + } + + if (strcmp(CRM_SYSTEM_DC, src_subsys) == 0) { + hash_value = crm_strdup(src_subsys); + if (!hash_value) { + cl_log(LOG_ERR, + "memory allocation failed in " + "generate_hash_value()\n"); + FNRET(NULL); + } + FNRET(hash_value); + } + + ref_len = strlen(src_subsys) + strlen(src_node) + 2; + hash_value = (char*)crm_malloc(sizeof(char)*(ref_len)); + if (!hash_value) { + cl_log(LOG_ERR, + "memory allocation failed in " + "generate_hash_value()\n"); + FNRET(NULL); + } + + snprintf(hash_value, ref_len-1, "%s_%s", src_node, src_subsys); + hash_value[ref_len-1] = '\0';// make sure it is null terminated + + cl_log(LOG_INFO, "created hash value: (%s)", hash_value); + FNRET(hash_value); +} + +gboolean +decode_hash_value(gpointer value, char **node, char **subsys) +{ + char *char_value = (char*)value; + int value_len = strlen(char_value); + + FNIN(); + + cl_log(LOG_INFO, "Decoding hash value: (%s:%d)", + char_value, + value_len); + + if (strcmp(CRM_SYSTEM_DC, (char*)value) == 0) { + *node = NULL; + *subsys = (char*)crm_strdup(char_value); + if (!*subsys) { + cl_log(LOG_ERR, "memory allocation failed in " + "decode_hash_value()\n"); + FNRET(FALSE); + } + cl_log(LOG_INFO, "Decoded value: (%s:%d)", *subsys, + (int)strlen(*subsys)); + FNRET(TRUE); + } + else if (char_value != NULL) { + if (decodeNVpair(char_value, '_', node, subsys)) { + FNRET(TRUE); + } else { + *node = NULL; + *subsys = NULL; + FNRET(FALSE); + } + } + FNRET(FALSE); +} + + +char * +crm_itoa(int an_int) +{ + int len = 32; + char *buffer = crm_malloc(sizeof(char)*(len+1)); + snprintf(buffer, len, "%d", an_int); + + return buffer; +} diff --git a/crm/common/xmlutils.c b/crm/common/xml.c similarity index 99% rename from crm/common/xmlutils.c rename to crm/common/xml.c index 60aa3ad41f..4738acca7e 100644 --- a/crm/common/xmlutils.c +++ b/crm/common/xml.c @@ -1,836 +1,835 @@ -/* $Id: xmlutils.c,v 1.31 2004/06/01 16:12:49 andrew Exp $ */ +/* $Id: xml.c,v 1.1 2004/06/02 11:45:28 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include -#include #include - +#include #include void dump_array(int log_level, const char *message, const char **array, int depth); xmlNodePtr find_xml_node_nested(xmlNodePtr root, const char **search_path, int len) { int j; xmlNodePtr child; xmlNodePtr lastMatch; FNIN(); if (root == NULL) { FNRET(NULL); } if(search_path == NULL) { CRM_NOTE("Will never find NULL"); FNRET(NULL); } #ifdef XML_TRACE dump_array(LOG_DEBUG, "Looking for.", search_path, len); #endif child = root->children, lastMatch = NULL; for (j=0; j < len; ++j) { gboolean is_found = FALSE; if (search_path[j] == NULL) { len = j; /* a NULL also means stop searching */ break; } while(child != NULL) { const char * child_name = (const char*)child->name; #ifdef XML_TRACE CRM_DEBUG("comparing (%s) with (%s).", search_path[j], child->name); #endif if (strcmp(child_name, search_path[j]) == 0) { lastMatch = child; child = lastMatch->children; #ifdef XML_TRACE CRM_DEBUG("found node (%s) @line (%ld).", search_path[j], xmlGetLineNo(child)); #endif is_found = TRUE; break; } child = child->next; } if (is_found == FALSE) { #ifdef XML_TRACE CRM_DEBUG( "No more siblings left... %s cannot be found.", search_path[j]); #endif break; } } if (j == len && lastMatch != NULL && strcmp(lastMatch->name, search_path[j-1]) == 0) { #ifdef XML_TRACE CRM_DEBUG("returning node (%s).", xmlGetNodePath(lastMatch)); #endif FNRET(lastMatch); } dump_array(LOG_WARNING, "Could not find the full path to the node you specified.", search_path, len); cl_log(LOG_WARNING,"Closest point was node (%s) starting from %s.", xmlGetNodePath(lastMatch), root?root->name:NULL); FNRET(NULL); } const char * get_xml_attr(xmlNodePtr parent, const char *node_name, const char *attr_name, gboolean error) { if(node_name == NULL) { // get it from the current node return get_xml_attr_nested(parent, NULL, 0, attr_name, error); } return get_xml_attr_nested(parent, &node_name, 1, attr_name, error); } const char * get_xml_attr_nested(xmlNodePtr parent, const char **node_path, int length, const char *attr_name, gboolean error) { const char *attr_value = NULL; xmlNodePtr attr_parent = NULL; if(parent == NULL) { cl_log(LOG_ERR, "Can not find attribute %s in NULL parent", attr_name); return NULL; } if(attr_name == NULL || strlen(attr_name) == 0) { cl_log(LOG_ERR, "Can not find attribute with no name in %s", xmlGetNodePath(parent)); return NULL; } if(length == 0) { attr_parent = parent; } else { attr_parent = find_xml_node_nested(parent, node_path, length); if(attr_parent == NULL && error) { cl_log(LOG_ERR, "No node at the path you specified."); return NULL; } } attr_value = xmlGetProp(attr_parent, attr_name); if((attr_value == NULL || strlen(attr_value) == 0) && error) { cl_log(LOG_ERR, "No value present for %s at %s", attr_name, xmlGetNodePath(attr_parent)); return NULL; } return attr_value; } xmlNodePtr set_xml_attr(xmlNodePtr parent, const char *node_name, const char *attr_name, const char *attr_value, gboolean create) { if(node_name == NULL) { // set it on the current node return set_xml_attr_nested(parent, NULL, 0, attr_name, attr_value, create); } return set_xml_attr_nested(parent, &node_name, 1, attr_name, attr_value, create); } xmlNodePtr set_xml_attr_nested(xmlNodePtr parent, const char **node_path, int length, const char *attr_name, const char *attr_value, gboolean create) { xmlAttrPtr result = NULL; xmlNodePtr attr_parent = NULL; xmlNodePtr create_parent = NULL; xmlNodePtr tmp; if(parent == NULL && create == FALSE) { cl_log(LOG_ERR, "Can not set attribute in NULL parent"); return NULL; } if(attr_name == NULL || strlen(attr_name) == 0) { cl_log(LOG_ERR, "Can not set attribute to %s with no name", attr_value); return NULL; } if(length == 0 && parent != NULL) { attr_parent = parent; } else if(length == 0 || node_path == NULL || *node_path == NULL || strlen(*node_path) == 0) { cl_log(LOG_ERR, "Can not create parent to set attribute %s=%s on", attr_name, attr_value); return NULL; } else { attr_parent = find_xml_node_nested(parent, node_path, length); } if(create && attr_parent == NULL) { int j = 0; attr_parent = parent; for (j=0; j < length; ++j) { if (node_path[j] == NULL) { break; } tmp = find_xml_node(attr_parent, node_path[j]); if(tmp == NULL) { attr_parent = create_xml_node(attr_parent, node_path[j]); if(j==0) { create_parent = attr_parent; } } else { attr_parent = tmp; } } } else if(attr_parent == NULL) { cl_log(LOG_ERR, "Can not find parent to set attribute on"); return NULL; } result = set_xml_property_copy(attr_parent, attr_name, attr_value); if(result == NULL) { cl_log(LOG_WARNING, "Could not set %s=%s at %s", attr_name, attr_value, xmlGetNodePath(attr_parent)); } if(create_parent != NULL) { return create_parent; } return parent; } xmlNodePtr find_xml_node(xmlNodePtr root, const char * search_path) { if(root == NULL) return NULL; return find_xml_node_nested(root, &search_path, 1); } xmlNodePtr find_entity(xmlNodePtr parent, const char *node_name, const char *id, gboolean siblings) { return find_entity_nested(parent, node_name, NULL, NULL, id, siblings); } xmlNodePtr find_entity_nested(xmlNodePtr parent, const char *node_name, const char *elem_filter_name, const char *elem_filter_value, const char *id, gboolean siblings) { xmlNodePtr child; FNIN(); #ifdef XML_TRACE cl_log(LOG_DEBUG, "Looking for %s elem with id=%s.", node_name, id); #endif while(parent != NULL) { #ifdef XML_TRACE CRM_DEBUG("examining (%s).", xmlGetNodePath(parent)); #endif child = parent->children; while(child != NULL) { #ifdef XML_TRACE CRM_DEBUG("looking for (%s) [name].", node_name); #endif if (node_name != NULL && strcmp(child->name, node_name) != 0) { #ifdef XML_TRACE CRM_DEBUG( "skipping entity (%s=%s) [node_name].", xmlGetNodePath(child), child->name); #endif break; } else if (elem_filter_name != NULL && elem_filter_value != NULL) { const char* child_value = (const char*) xmlGetProp(child, elem_filter_name); #ifdef XML_TRACE cl_log(LOG_DEBUG, "comparing (%s) with (%s) [attr_value].", child_value, elem_filter_value); #endif if (strcmp(child_value, elem_filter_value)) { #ifdef XML_TRACE CRM_DEBUG("skipping entity (%s) [attr_value].", xmlGetNodePath(child)); #endif break; } } #ifdef XML_TRACE cl_log(LOG_DEBUG, "looking for entity (%s) in %s.", id, xmlGetNodePath(child)); #endif while(child != NULL) { #ifdef XML_TRACE cl_log(LOG_DEBUG, "looking for entity (%s) in %s.", id, xmlGetNodePath(child)); #endif xmlChar *child_id = xmlGetProp(child, XML_ATTR_ID); if (child_id == NULL) { cl_log(LOG_CRIT, "Entity (%s) has id=NULL..." "Cib not valid!", xmlGetNodePath(child)); } else if (strcmp(id, child_id) == 0) { #ifdef XML_TRACE CRM_DEBUG("found entity (%s).", id); #endif FNRET(child); } child = child->next; } } if (siblings == TRUE) { #ifdef XML_TRACE CRM_NOTE("Nothing yet... checking siblings"); #endif parent = parent->next; } else parent = NULL; } cl_log(LOG_INFO, "Couldnt find anything appropriate for %s elem with id=%s.", node_name, id); FNRET(NULL); } void copy_in_properties(xmlNodePtr target, xmlNodePtr src) { if(src == NULL) { cl_log(LOG_WARNING, "No node to copy properties from"); } else if (src->properties == NULL) { cl_log(LOG_INFO, "No properties to copy"); } else if (target == NULL) { cl_log(LOG_WARNING, "No node to copy properties into"); } else { #ifndef USE_BUGGY_LIBXML xmlAttrPtr prop_iter = NULL; FNIN(); prop_iter = src->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(src, local_prop_name); set_xml_property_copy(target, local_prop_name, local_prop_value); prop_iter = prop_iter->next; } #else xmlCopyPropList(target, src->properties); #endif } FNOUT(); } char * dump_xml(xmlNodePtr msg) { FNIN(); FNRET(dump_xml_node(msg, FALSE)); } void xml_message_debug(xmlNodePtr msg, const char *text) { char *msg_buffer; FNIN(); if(msg == NULL) { CRM_DEBUG("%s: %s", text==NULL?"":text,""); FNOUT(); } msg_buffer = dump_xml_node(msg, FALSE); CRM_DEBUG("%s: %s", text==NULL?"":text, msg_buffer==NULL?"":msg_buffer); crm_free(msg_buffer); FNOUT(); } char * dump_xml_node(xmlNodePtr msg, gboolean whole_doc) { int lpc = 0; int msg_size = -1; xmlChar *xml_message = NULL; xmlBufferPtr xml_buffer; FNIN(); if (msg == NULL) FNRET(NULL); xmlInitParser(); if (whole_doc) { if (msg->doc == NULL) { xmlDocPtr foo = xmlNewDoc("1.0"); xmlDocSetRootElement(foo, msg); xmlSetTreeDoc(msg,foo); } xmlDocDumpMemory(msg->doc, &xml_message, &msg_size); } else { #ifdef XML_TRACE CRM_DEBUG("mem used by xml: %d", xmlMemUsed()); xmlMemoryDump (); #endif xml_buffer = xmlBufferCreate(); msg_size = xmlNodeDump(xml_buffer, msg->doc, msg, 0, 0); xml_message = (xmlChar*)crm_strdup(xmlBufferContent(xml_buffer)); xmlBufferFree(xml_buffer); if (!xml_message) { cl_log(LOG_ERR, "memory allocation failed in dump_xml_node()"); } } xmlCleanupParser(); // HA wont send messages with newlines in them. for(; xml_message != NULL && lpc < msg_size; lpc++) if (xml_message[lpc] == '\n') xml_message[lpc] = ' '; FNRET((char*)xml_message); } xmlNodePtr add_node_copy(xmlNodePtr new_parent, xmlNodePtr xml_node) { xmlNodePtr node_copy = NULL; FNIN(); if(xml_node != NULL && new_parent != NULL) { node_copy = copy_xml_node_recursive(xml_node); xmlAddChild(new_parent, node_copy); } else if(xml_node == NULL) { cl_log(LOG_ERR, "Could not add copy of NULL node"); } else { cl_log(LOG_ERR, "Could not add copy of node to NULL parent"); } FNRET(node_copy); } xmlAttrPtr set_xml_property_copy(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { const char *parent_name = NULL; const char *local_name = NULL; const char *local_value = NULL; xmlAttrPtr ret_value = NULL; FNIN(); if(node != NULL) { parent_name = node->name; } #ifdef XML_TRACE CRM_DEBUG("[%s] Setting %s to %s", parent_name, name, value); #endif if (name == NULL || strlen(name) <= 0) { ret_value = NULL; } else if(node == NULL) { ret_value = NULL; } else if (value == NULL || strlen(value) <= 0) { ret_value = NULL; xmlUnsetProp(node, local_name); } else { local_value = crm_strdup(value); local_name = crm_strdup(name); ret_value = xmlSetProp(node, local_name, local_value); } FNRET(ret_value); } xmlNodePtr create_xml_node(xmlNodePtr parent, const char *name) { const char *local_name = NULL; const char *parent_name = NULL; xmlNodePtr ret_value = NULL; FNIN(); if (name == NULL || strlen(name) < 1) { ret_value = NULL; } else { local_name = crm_strdup(name); if(parent == NULL) ret_value = xmlNewNode(NULL, local_name); else { parent_name = parent->name; ret_value = xmlNewChild(parent, NULL, local_name, NULL); } } #ifdef XML_TRACE CRM_DEBUG("Created node [%s [%s]]", parent_name, local_name); #endif FNRET(ret_value); } void unlink_xml_node(xmlNodePtr node) { xmlUnlinkNode(node); /* this helps us with frees and really should be being done by * the library call */ node->doc = NULL; } void free_xml(xmlNodePtr a_node) { FNIN(); if (a_node == NULL) ; // nothing to do else if (a_node->doc != NULL) xmlFreeDoc(a_node->doc); else { /* make sure the node is unlinked first */ xmlUnlinkNode(a_node); #if 0 /* set a new doc, wont delete without one? */ xmlDocPtr foo = xmlNewDoc("1.0"); xmlDocSetRootElement(foo, a_node); xmlSetTreeDoc(a_node,foo); xmlFreeDoc(foo); #else xmlFreeNode(a_node); #endif } FNOUT(); } void set_node_tstamp(xmlNodePtr a_node) { char *since_epoch = (char*)crm_malloc(128*(sizeof(char))); FNIN(); sprintf(since_epoch, "%ld", (unsigned long)time(NULL)); set_xml_property_copy(a_node, XML_ATTR_TSTAMP, since_epoch); crm_free(since_epoch); } xmlNodePtr copy_xml_node_recursive(xmlNodePtr src_node) { #if XML_TRACE const char *local_name = NULL; xmlNodePtr local_node = NULL, node_iter = NULL, local_child = NULL; xmlAttrPtr prop_iter = NULL; FNIN(); if(src_node != NULL && src_node->name != NULL) { local_node = create_xml_node(NULL, src_node->name); prop_iter = src_node->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(src_node, local_prop_name); set_xml_property_copy(local_node, local_prop_name, local_prop_value); prop_iter = prop_iter->next; } node_iter = src_node->children; while(node_iter != NULL) { local_child = copy_xml_node_recursive(node_iter); if(local_child != NULL) { xmlAddChild(local_node, local_child); CRM_DEBUG("Copied node [%s [%s]", local_name, local_child->name); } node_iter = node_iter->next; } CRM_DEBUG("Returning [%s]", local_node->name); FNRET(local_node); } CRM_NOTE("Returning null"); FNRET(NULL); #else return xmlCopyNode(src_node, 1); #endif } xmlNodePtr string2xml(const char *input) { char ch = 0; int lpc = 0, input_len = strlen(input); gboolean more = TRUE; gboolean inTag = FALSE; xmlNodePtr xml_object = NULL; const char *the_xml; xmlDocPtr doc; xmlBufferPtr xml_buffer = xmlBufferCreate(); for(lpc = 0; (lpc < input_len) && more; lpc++) { ch = input[lpc]; switch(ch) { case EOF: case 0: ch = 0; more = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '>': case '<': inTag = TRUE; if(ch == '>') inTag = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '\n': case '\t': case ' ': ch = ' '; if(inTag) { xmlBufferAdd(xml_buffer, &ch, 1); } break; default: xmlBufferAdd(xml_buffer, &ch, 1); break; } } xmlInitParser(); the_xml = xmlBufferContent(xml_buffer); doc = xmlParseMemory(the_xml, strlen(the_xml)); xmlCleanupParser(); if (doc == NULL) { cl_log(LOG_ERR, "Malformed XML [xml=%s]", the_xml); xmlBufferFree(xml_buffer); return NULL; } xmlBufferFree(xml_buffer); xml_object = xmlDocGetRootElement(doc); return xml_object; } xmlNodePtr file2xml(FILE *input) { char ch = 0; gboolean more = TRUE; gboolean inTag = FALSE; xmlNodePtr xml_object = NULL; xmlBufferPtr xml_buffer = xmlBufferCreate(); const char *the_xml; xmlDocPtr doc; if(input == NULL) { cl_log(LOG_ERR, "File pointer was NULL"); return NULL; } while (more) { ch = fgetc(input); // cl_log(LOG_DEBUG, "Got [%c]", ch); switch(ch) { case EOF: case 0: ch = 0; more = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '>': case '<': inTag = TRUE; if(ch == '>') inTag = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '\n': case '\t': case ' ': ch = ' '; if(inTag) { xmlBufferAdd(xml_buffer, &ch, 1); } break; default: xmlBufferAdd(xml_buffer, &ch, 1); break; } } xmlInitParser(); the_xml = xmlBufferContent(xml_buffer); doc = xmlParseMemory(the_xml, strlen(the_xml)); xmlCleanupParser(); if (doc == NULL) { cl_log(LOG_ERR, "Malformed XML [xml=%s]", the_xml); xmlBufferFree(xml_buffer); return NULL; } xmlBufferFree(xml_buffer); xml_object = xmlDocGetRootElement(doc); xml_message_debug(xml_object, "Created fragment"); return xml_object; } void dump_array(int log_level, const char *message, const char **array, int depth) { int j; if(message != NULL) { cl_log(log_level, "%s", message); } cl_log(log_level, "Contents of the array:"); if(array == NULL || array[0] == NULL || depth == 0) { cl_log(log_level, "\t"); } for (j=0; j < depth && array[j] != NULL; j++) { if (array[j] == NULL) break; cl_log(log_level, "\t--> (%s).", array[j]); } } diff --git a/crm/common/xmlutils.h b/crm/common/xmlutils.h deleted file mode 100644 index 9b86e9642e..0000000000 --- a/crm/common/xmlutils.h +++ /dev/null @@ -1,233 +0,0 @@ -/* $Id: xmlutils.h,v 1.11 2004/03/30 15:10:20 andrew Exp $ */ -/* - * Copyright (C) 2004 Andrew Beekhof - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef XMLUTILS_H -#define XMLUTILS_H - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* - * Replacement function for xmlCopyPropList which at the very least, - * doesnt work the way *I* would expect it to. - * - * Copy all the attributes/properties from src into target. - * - * Not recursive, does not return anything. - * - */ -extern void copy_in_properties(xmlNodePtr target, xmlNodePtr src); - -/* - * Find a child named search_path[i] at level i in the XML fragment where i=0 - * is an immediate child of root. - * - * Terminate with success if i == len, or search_path[i] == NULL. - * - * On success, returns the sub-fragment described by search_path. - * On failure, returns NULL. - */ -extern xmlNodePtr find_xml_node_nested(xmlNodePtr root, - const char **search_path, - int len); - - -/* - * In parent, find a child named node_name whose value for - * elem_filter_name is elem_filter_value and or has id set - * to id. - * - * elem_filter_name, elem_filter_value and id.may all - * be set to NULL, in which case the filter they represent will be ignored. - * - * By setting siblings, you also have the option of searching all - * other nodes at the same level as parent - * - * On success, returns parent or the created parent create - * was specified. - * - * On failure, returns NULL. - */ -extern xmlNodePtr find_entity_nested(xmlNodePtr parent, - const char *node_name, - const char *elem_filter_name, - const char *elem_filter_value, - const char *id, - gboolean siblings); -/* - * Find a child named search_path[i] at level i in the XML fragment where i=0 - * is an immediate child of root. - * - * Once the last child specified by node_path is found, find the value - * of attr_name. - * - * If error is set to TRUE, then it is an error for the attribute not - * to be found and the function will log accordingly. - * - * On success, returns the value of attr_name. - * On failure, returns NULL. - */ -extern const char *get_xml_attr_nested(xmlNodePtr parent, - const char **node_path, int length, - const char *attr_name, gboolean error); - -/* - * Find a child named search_path[i] at level i in the XML fragment where i=0 - * is an immediate child of root. - * - * Once the last child specified by node_path is found, set the value - * of attr_name to be attr_value. - * - * On success, returns parent or the created parent create - * was specified. - * - * On failure, returns NULL. - */ -extern xmlNodePtr set_xml_attr_nested(xmlNodePtr parent, - const char **node_path, int length, - const char *attr_name, - const char *attr_value, - gboolean create); - - - - -extern char * dump_xml_node(xmlNodePtr msg, gboolean whole_doc); - -/* - * Free the XML "stuff" associated with a_node - * - * If a_node is part of a document, free the whole thing - * - * Otherwise, unlink it from its current location and free everything - * from there down. - * - * Wont barf on NULL. - * - */ -extern void free_xml(xmlNodePtr a_node); - -/* - * Dump out the message, print some identifying text and clean up afterwards. - */ -extern void xml_message_debug(xmlNodePtr msg, const char *text); - -/* - * Create a node named "name" as a child of "parent" - * If parent is NULL, creates an unconnected node. - * - * Returns the created node - * - */ -extern xmlNodePtr create_xml_node(xmlNodePtr parent, const char *name); - -/* - * Make a copy of name and value and use the copied memory to create - * an attribute for node. - * - * If node, name or value are NULL, nothing is done. - * - * If name or value are an empty string, nothing is done. - * - * Returns NULL on failure and the attribute created on success. - * - */ -extern xmlAttrPtr set_xml_property_copy(xmlNodePtr node, - const xmlChar *name, - const xmlChar *value); - -/* - * Unlink the node and set its doc pointer to NULL so free_xml() - * will act appropriately - */ -extern void unlink_xml_node(xmlNodePtr node); - -/* - * Set a timestamp attribute on a_node - */ -extern void set_node_tstamp(xmlNodePtr a_node); - -/* - * Returns a deep copy of src_node - * - * Either calls xmlCopyNode() or a home grown alternative (based on - * XML_TRACE being defined) that does more logging... - * helpful when part of the XML document has been freed :) - */ -extern xmlNodePtr copy_xml_node_recursive(xmlNodePtr src_node); - -/* - * Add a copy of xml_node to new_parent - */ -extern xmlNodePtr add_node_copy(xmlNodePtr new_parent, xmlNodePtr xml_node); - - -/* - * Read in the contents of a pre-opened file descriptor (until EOF) and - * produce an XML fragment (it will have an attached document). - * - * input will need to be closed on completion. - * - * Whitespace between tags is discarded. - * - */ -extern xmlNodePtr file2xml(FILE *input); - -/* - * Read in the contents of a string and produce an XML fragment (it will - * have an attached document). - * - * input will need to be freed on completion. - * - * Whitespace between tags is discarded. - * - */ -extern xmlNodePtr string2xml(const char *input); - - -/* convience "wrapper" functions */ -extern xmlNodePtr find_xml_node(xmlNodePtr cib, const char * node_path); - -extern xmlNodePtr find_entity(xmlNodePtr parent, - const char *node_name, - const char *id, - gboolean siblings); - -extern const char *get_xml_attr(xmlNodePtr parent, - const char *node_name, const char *attr_name, - gboolean error); - -extern xmlNodePtr set_xml_attr(xmlNodePtr parent, - const char *node_name, - const char *attr_name, - const char *attr_value, - gboolean create); - -extern char * dump_xml(xmlNodePtr msg); - -#endif