⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client_lib.c

📁 linux集群服务器软件代码包
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: client_lib.c,v 1.21 2005/02/17 18:20:03 gshi Exp $ *//*  * client_lib: heartbeat API client side code * * Copyright (C) 2000 Alan Robertson <alanr@unix.sh> *  * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 library 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 * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser 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 *//* *	Here's our approach: * *	Have each application connect to heartbeat via our IPC layer. *		This IPC layer currently uses sockets and provides *		a suitable authorization API. * *	We can validate permissions for "sniffing" using the builtin *		IPC authorization API. * *	This code thankfully no longer uses FIFOs. * */#include <portability.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/utsname.h>#include <sys/time.h>#include <sys/stat.h>#include <stdarg.h>#include <heartbeat.h>#include <hb_api_core.h>#include <hb_api.h>#include <clplumbing/ttylock.h>#include <glib.h>struct sys_config *		config  = NULL;int			netstring_format = TRUE;struct stringlist {	char *			value;	struct stringlist *	next;};/* *	Queue of messages to be read later... */struct MsgQueue {	struct ha_msg *		value;	struct MsgQueue *	next;	struct MsgQueue *	prev;};typedef struct gen_callback {	char *			msgtype;	llc_msg_callback_t 	cf;	void *			pd;	struct gen_callback*	next;}gen_callback_t;#define	MXFIFOPATH	128#define	HBPREFIX	"LCK..hbapi:"/* Order sequence */typedef struct order_seq {	char			to_node[HOSTLENG];	seqno_t			seqno;	struct order_seq *	next;}order_seq_t;/* Order Queue */struct orderQ {	struct ha_msg *		orderQ[MAXMSGHIST];	int			curr_index;	seqno_t			curr_oseqno;	seqno_t			curr_gen;	seqno_t			curr_client_gen;	seqno_t			first_msg_seq;	seqno_t			first_msg_gen;	seqno_t			first_msg_client_gen;	struct orderQ		*backupQ;};typedef struct order_queue {	char			from_node[HOSTLENG];	struct orderQ		node;	struct orderQ		cluster;	struct order_queue*	next;	struct ha_msg*		leave_msg;        int			client_leaving;}order_queue_t;/* *	Our heartbeat private data */typedef struct llc_private {	const char *		PrivateId;	/* A "magic cookie */	llc_nstatus_callback_t	node_callback;	/* Node status callback fcn */	void*			node_private;	/* node status callback data*/	llc_ifstatus_callback_t	if_callback;	/* IF status callback fcn */	void*			if_private;	/* IF status callback data */	llc_cstatus_callback_t	cstatus_callback;/*Client status callback fcn */	void*			client_private;	/* client status callback data*/	struct gen_callback*	genlist;	/* List of general callbacks*/	IPC_Channel*		chan;		/* IPC communication channel*/	struct stringlist *	nodelist;	/* List of nodes from query */	struct stringlist *	iflist;		/* List of IFs from query */	int			SignedOn;	/* 1 if we're signed on */	int			iscasual;	/* 1 if casual client */	long			deadtime_ms;	/* heartbeat's deadtime */	long			keepalive_ms;	/* HB's keepalive time*/	int			logfacility;	/* HB's logging facility */	struct stringlist*	nextnode;	/* Next node for walknode */	struct stringlist*	nextif;		/* Next interface for walkif*/	/* Messages to be read after current call completes */	struct MsgQueue *	firstQdmsg;	struct MsgQueue *	lastQdmsg;	/* The next two items are for ordered message delivery */	order_seq_t		order_seq_head;	/* head of order_seq list */	order_queue_t*		order_queue_head;/* head of order queue */}llc_private_t;static const char * OurID = "Heartbeat private data";	/* "Magic cookie" */#define ISOURS(l) (l && l->ll_cluster_private &&			\		(((llc_private_t*)(l->ll_cluster_private))->PrivateId) == OurID)#define SEQGAP		16#define DEBUGORDER	0static void		ClearLog(void);			/* Common code for request messages */static struct ha_msg*	hb_api_boilerplate(const char * apitype);static int		hb_api_signon(struct ll_cluster*, const char * clientid);static int		hb_api_signoff(struct ll_cluster*);static int		hb_api_setfilter(struct ll_cluster*, unsigned);static void		destroy_stringlist(struct stringlist *);static struct stringlist*			new_stringlist(const char *);static int		get_nodelist(llc_private_t*);static void		zap_nodelist(llc_private_t*);static int		get_iflist(llc_private_t*, const char *host);static void		zap_iflist(llc_private_t*);static void		zap_order_seq(llc_private_t* pi);static void		zap_order_queue(llc_private_t* pi);static int		enqueue_msg(llc_private_t*,struct ha_msg*);static struct ha_msg*	dequeue_msg(llc_private_t*);static gen_callback_t*	search_gen_callback(const char * type, llc_private_t*);static int		add_gen_callback(const char * msgtype,	llc_private_t*, llc_msg_callback_t, void*);static int		del_gen_callback(llc_private_t*, const char * msgtype);static struct ha_msg*	read_api_msg(llc_private_t*);static struct ha_msg*	read_cstatus_respond_msg(llc_private_t*pi, int timeout);static struct ha_msg*	read_hb_msg(ll_cluster_t*, int blocking);static int		hb_api_setsignal(ll_cluster_t*, int nsig);static int set_msg_callback			(ll_cluster_t*, const char * msgtype,			llc_msg_callback_t callback, void * p);static intset_nstatus_callback (ll_cluster_t*,		llc_nstatus_callback_t cbf, 	void * p);static intset_cstatus_callback (ll_cluster_t*,		llc_cstatus_callback_t cbf, void * p);static intset_ifstatus_callback (ll_cluster_t* ci,		llc_ifstatus_callback_t cbf, void * p);static int init_nodewalk (ll_cluster_t*);static const char * nextnode (ll_cluster_t* ci);static int init_ifwalk (ll_cluster_t* ci, const char * host);static const char *	get_nodestatus(ll_cluster_t*, const char *host);static const char *get_clientstatus(ll_cluster_t*, const char *host, const char *clientid,	int timeout);static const char *	get_nodetype(ll_cluster_t*, const char *host);static const char *	get_ifstatus(ll_cluster_t*, const char *host,	const char * intf);static char *		get_parameter(ll_cluster_t*, const char* pname);static const char *	get_resources(ll_cluster_t*);static int		get_inputfd(ll_cluster_t*);static IPC_Channel*	get_ipcchan(ll_cluster_t*);static int		msgready(ll_cluster_t*);static int		setfmode(ll_cluster_t*, unsigned mode);static int		sendclustermsg(ll_cluster_t*, struct ha_msg* msg);static int		sendnodemsg(ll_cluster_t*, struct ha_msg* msg,			const char * nodename);STATIC void		add_order_seq(llc_private_t*, struct ha_msg* msg);static int		send_ordered_clustermsg(ll_cluster_t* lcl, struct ha_msg* msg);static int		send_ordered_nodemsg(ll_cluster_t* lcl, struct ha_msg* msg,			const char * nodename);static const char *	APIError(ll_cluster_t*);static int		CallbackCall(llc_private_t* p, struct ha_msg * msg);static struct ha_msg *	read_msg_w_callbacks(ll_cluster_t* llc, int blocking);static int		rcvmsg(ll_cluster_t* llc, int blocking);volatile struct process_info *	curproc = NULL;static char		OurPid[16];static const char *	OurClientID = NULL;static char 		OurNode[SYS_NMLN];static ll_cluster_t*	hb_cluster_new(void);static void ha_api_perror(const char * fmt, ...) G_GNUC_PRINTF(1,2);static void ha_api_log(int priority, const char * fmt, ...) G_GNUC_PRINTF(2,3);#define	ZAPMSG(m)	{ha_msg_del(m); (m) = NULL;}/* * All the boilerplate common to creating heartbeat API request * messages. */static struct ha_msg*hb_api_boilerplate(const char * apitype){	struct ha_msg*	msg;	if ((msg = ha_msg_new(4)) == NULL) {		ha_api_log(LOG_ERR, "boilerplate: out of memory");		return msg;	}	/* Message type: API request */	if (ha_msg_add(msg, F_TYPE, T_APIREQ) != HA_OK) {		ha_api_log(LOG_ERR, "boilerplate: cannot add F_TYPE field");		ZAPMSG(msg);		return msg;	}	/* Add field for API request type */	if (ha_msg_add(msg, F_APIREQ, apitype) != HA_OK) {		ha_api_log(LOG_ERR, "boilerplate: cannot add F_APIREQ field");		ZAPMSG(msg);		return msg;	}	/* Add field for destination */	if (ha_msg_add(msg, F_TO, OurNode) != HA_OK) {		ha_api_log(LOG_ERR, "boilerplate: cannot add F_TO field");		ZAPMSG(msg);		return msg;	}	/* Add our PID to the message */	if (ha_msg_add(msg, F_PID, OurPid) != HA_OK) {		ha_api_log(LOG_ERR, "boilerplate: cannot add F_PID field");		ZAPMSG(msg);		return msg;	}		/* Add our client ID to the message */	if (ha_msg_add(msg, F_FROMID, OurClientID) != HA_OK) {		ha_api_log(LOG_ERR, "boilerplate: cannot add F_FROMID field");		ZAPMSG(msg);		return msg;	}	return(msg);}/* * Sign ourselves on as a heartbeat client process. */static inthb_api_signon(struct ll_cluster* cinfo, const char * clientid){	struct ha_msg*	request;	struct ha_msg*	reply;	struct utsname	un;	int		rc;	const char *	result;	int		iscasual;	llc_private_t* pi;	const char	*tmpstr;        char		regpath[] = API_REGSOCK;	char		path[] = IPC_PATH_ATTR;	GHashTable*	wchanattrs;	char		cuid[20];	char		cgid[20];	if (!ISOURS(cinfo)) {		ha_api_log(LOG_ERR, "hb_api_signon: bad cinfo");		return HA_FAIL;	}	pi = (llc_private_t*)cinfo->ll_cluster_private;	/* Re-sign ourselves back on */	if (pi->SignedOn) {		hb_api_signoff(cinfo);	}	snprintf(OurPid, sizeof(OurPid), "%d", getpid());	/* Create our client id */	if (clientid != NULL) {		OurClientID = clientid;		iscasual = 0;	}else{		OurClientID = OurPid;		iscasual = 1;	}	pi->iscasual = iscasual;	if (uname(&un) < 0) {		ha_api_perror("uname failure");		return HA_FAIL;	}        memset(OurNode, 0, sizeof(OurNode));	strncpy(OurNode, un.nodename, sizeof(OurNode)-1);	g_strdown(OurNode);	/* Initialize order_seq_head */	pi->order_seq_head.seqno = 1;	pi->order_seq_head.to_node[0] = '\0';	pi->order_seq_head.next = NULL;	/* Initialize order_queue_head */	pi->order_queue_head = NULL;	/* Crank out the boilerplate */	if ((request = hb_api_boilerplate(API_SIGNON)) == NULL) {		return HA_FAIL;	}	snprintf(cuid, sizeof(cuid)-1, "%ld",  (long)geteuid());	/* Add our UID to the message */	if (ha_msg_add(request, F_UID, cuid) != HA_OK) {		ha_api_log(LOG_ERR, "hb_api_signon: cannot add F_UID field");		ZAPMSG(request);		return HA_FAIL;	}	snprintf(cgid, sizeof(cgid)-1, "%ld",  (long)getegid());	/* Add our GID to the message */	if (ha_msg_add(request, F_GID, cgid) != HA_OK) {		ha_api_log(LOG_ERR, "hb_api_signon: cannot add F_GID field");		ZAPMSG(request);		return HA_FAIL;	}	wchanattrs = g_hash_table_new(g_str_hash, g_str_equal);        g_hash_table_insert(wchanattrs, path, regpath);	/* Connect to the heartbeat API server */	if ((pi->chan = ipc_channel_constructor(IPC_ANYTYPE, wchanattrs))	==	NULL) {		ha_api_log(LOG_ERR, "hb_api_signon: Can't connect"		" to heartbeat");		ZAPMSG(request);		return HA_FAIL;	}	pi->chan->should_send_blocking = TRUE;        if (pi->chan->ops->initiate_connection(pi->chan) != IPC_OK) {		ha_api_log(LOG_ERR, "hb_api_signon: Can't initiate"		" connection  to heartbeat");		ZAPMSG(request);                return HA_FAIL;        }	/* Send the registration request message */	if (msg2ipcchan(request, pi->chan) != HA_OK) {		pi->chan->ops->destroy(pi->chan);		pi->chan = NULL;		ha_api_perror("can't send message to IPC");		ZAPMSG(request);		return HA_FAIL;	}		ZAPMSG(request);	pi->chan->ops->waitout(pi->chan);	/* Read the reply... */	if ((reply=read_api_msg(pi)) == NULL) {		return HA_FAIL;	}	/* Get the return code */	if ((result = ha_msg_value(reply, F_APIRESULT)) != NULL	&&	strcmp(result, API_OK) == 0) {		rc = HA_OK;		pi->SignedOn = 1;		if ((tmpstr = ha_msg_value(reply, F_DEADTIME)) == NULL		||	sscanf(tmpstr, "%lx", (unsigned long*)&(pi->deadtime_ms)) != 1) {			ha_api_log(LOG_ERR			,	"hb_api_signon: Can't get deadtime ");			ZAPMSG(reply);			return HA_FAIL;		}		if ((tmpstr = ha_msg_value(reply, F_KEEPALIVE)) == NULL		||	sscanf(tmpstr, "%lx", (unsigned long*)&(pi->keepalive_ms)) != 1) {			ha_api_log(LOG_ERR			,	"hb_api_signon: Can't get keepalive time ");			ZAPMSG(reply);			return HA_FAIL;		}		if ((tmpstr = ha_msg_value(reply, F_NODENAME)) == NULL		||	strlen(tmpstr) >= sizeof(OurNode)) {			ha_api_log(LOG_ERR			,	"hb_api_signon: Can't get local node name");			ZAPMSG(reply);			return HA_FAIL;		}else{			strncpy(OurNode, tmpstr, sizeof(OurNode)-1);			OurNode[sizeof(OurNode)-1] = EOS;		}		/* Sometimes they don't use syslog logging... */		tmpstr = ha_msg_value(reply, F_LOGFACILITY);		if (tmpstr == NULL		||	sscanf(tmpstr, "%d", &(pi->logfacility)) != 1) {			pi->logfacility = -1;		}	}else{		rc = HA_FAIL;	}	ZAPMSG(reply);	return rc;}/* * Sign off (disconnect) as a heartbeat client process. */static inthb_api_signoff(struct ll_cluster* cinfo){	struct ha_msg*	request;	llc_private_t* pi;	if (!ISOURS(cinfo)) {		ha_api_log(LOG_ERR, "hb_api_signoff: bad cinfo");		return HA_FAIL;	}	pi = (llc_private_t*)cinfo->ll_cluster_private;	if (!pi->SignedOn) {		/* Already signed off... No value in returning an error... */		return HA_OK;	}	if ((request = hb_api_boilerplate(API_SIGNOFF)) == NULL) {		ha_api_log(LOG_ERR, "hb_api_signoff: can't create msg");		return HA_FAIL;	}		/* Send the message */	if (msg2ipcchan(request, pi->chan) != HA_OK) {		ZAPMSG(request);		ha_api_perror("can't send message to IPC");		return HA_FAIL;	}	pi->chan->ops->waitout(pi->chan);	ZAPMSG(request);	OurClientID = NULL;	pi->chan->ops->destroy(pi->chan);	pi->SignedOn = 0;	zap_order_seq(pi);	zap_order_queue(pi);	return HA_OK;}/* * delete:  destroy the heartbeat API object */static inthb_api_delete(struct ll_cluster* ci){	llc_private_t* pi;	if (!ISOURS(ci)) {		ha_api_log(LOG_ERR, "hb_api_delete: bad cinfo");		return HA_FAIL;	}	pi = (llc_private_t*)ci->ll_cluster_private;	/* Sign off */	hb_api_signoff(ci);	/* Free up interface and node lists */	zap_iflist(pi);	zap_nodelist(pi);	/* What about our message queue? */	/* Free up the private information */	memset(pi, 0, sizeof(*pi));	ha_free(pi);	/* Free up the generic (llc) information */	memset(ci, 0, sizeof(*ci));	ha_free(ci);	return HA_OK;}/* * Set message filter mode. */static inthb_api_setfilter(struct ll_cluster* ci, unsigned fmask){	struct ha_msg*	request;	struct ha_msg*	reply;	int		rc;	const char *	result;	char		filtermask[32];	llc_private_t* pi;	if (!ISOURS(ci)) {		ha_api_log(LOG_ERR, "hb_api_setfilter: bad cinfo");		return HA_FAIL;	}	pi = (llc_private_t*)ci->ll_cluster_private;	if (!pi->SignedOn) {		ha_api_log(LOG_ERR, "not signed on");		return HA_FAIL;	}	if ((request = hb_api_boilerplate(API_SETFILTER)) == NULL) {		ha_api_log(LOG_ERR, "hb_api_setfilter: can't create msg");		return HA_FAIL;	}	/* Format the filtermask information in hex */	snprintf(filtermask, sizeof(filtermask), "%x", fmask);	if (ha_msg_add(request, F_FILTERMASK, filtermask) != HA_OK) {		ha_api_log(LOG_ERR, "hb_api_setfilter: cannot add field/2");		ZAPMSG(request);		return HA_FAIL;	}		/* Send the message */	if (msg2ipcchan(request, pi->chan) != HA_OK) {		ZAPMSG(request);		ha_api_perror("can't send message to IPC");		return HA_FAIL;	}	ZAPMSG(request);	/* Read reply... */	if ((reply=read_api_msg(pi)) == NULL) {		return HA_FAIL;	}	if ((result = ha_msg_value(reply, F_APIRESULT)) != NULL	&&	strcmp(result, API_OK) == 0) {		rc = HA_OK;	}else{		rc = HA_FAIL;	}	ZAPMSG(reply);	return rc;}/* * Set signal for message notification. * This is not believed to be a security hole :-) */static inthb_api_setsignal(ll_cluster_t* lcl, int nsig){	struct ha_msg*	request;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -