You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
heartbeat/lib/plugins/HBcomm/tipc.c

455 lines
12 KiB

/*
* tipc.c - tipc communication module for heartbeat
*
* Author: Jia Ming Pan <jmltc@cn.ibm.com>
* Copyright (c) 2005 International Business Machines
*
* 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
*
*/
#include <lha_internal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <ctype.h>
#include <heartbeat.h>
#include <HBcomm.h>
#include <net/tipc/tipc.h>
#define PIL_PLUGINTYPE HB_COMM_TYPE
#define PIL_PLUGINTYPE_S HB_COMM_TYPE_S
#define PIL_PLUGIN tipc
#define PIL_PLUGIN_S "tipc"
#define PIL_PLUGINLICENSE LICENSE_LGPL
#define PIL_PLUGINLICENSEURL URL_LGPL
#include <pils/plugin.h>
struct tipc_private {
struct sockaddr_tipc maddr;
int recvfd;
int sendfd;
unsigned int name_type;
unsigned int seq_lower;
unsigned int seq_upper;
};
static struct hb_media *
tipc_new(unsigned int name_type,
unsigned int seq_lower, unsigned int seq_upper);
static int tipc_parse(const char * line);
static int tipc_open(struct hb_media * mp);
static int tipc_close(struct hb_media * mp);
static void * tipc_read(struct hb_media * mp, int * lenp);
static int tipc_write(struct hb_media * mp, void * msg, int len);
static int tipc_make_receive_sock(struct hb_media * mp);
static int tipc_make_send_sock(struct hb_media * mp);
static int tipc_descr(char ** buffer);
static int tipc_mtype(char ** buffer);
static int tipc_isping(void);
static struct hb_media_fns tipcOps;
PIL_PLUGIN_BOILERPLATE2("1.0", Debug)
static const PILPluginImports * PluginImports;
static PILPlugin * OurPlugin;
static PILInterface * OurInterface;
static struct hb_media_imports * OurImports;
static void * interfprivate;
#define LOG PluginImports->log
#define MALLOC PluginImports->alloc
#define STRDUP PluginImports->mstrdup
#define FREE PluginImports->mfree
#define IS_TIPC_OBJECT(mp) ((mp) && ((mp)->vf == (void*)&tipcOps))
#define TIPC_ASSERT(mp) g_assert(IS_TIPC_OBJECT(mp))
PIL_rc
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);
PIL_rc
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports)
{
/* Force the compiler to do a little type checking */
(void)(PILPluginInitFun)PIL_PLUGIN_INIT;
PluginImports = imports;
OurPlugin = us;
/* Register ourself as a plugin */
imports->register_plugin(us, &OurPIExports);
/* Register our interface implementation */
return imports->register_interface(us, PIL_PLUGINTYPE_S
, PIL_PLUGIN_S
, &tipcOps
, NULL /*close */
, &OurInterface
, (void*)&OurImports
, interfprivate);
}
static struct hb_media *
tipc_new(unsigned int name_type,
unsigned int seq_lower, unsigned int seq_upper)
{
struct tipc_private * tipc = NULL;
struct hb_media * mp = NULL;
mp = MALLOC(sizeof(struct hb_media));
if ( mp == NULL ){
PILCallLog(LOG, PIL_CRIT,
"%s: malloc failed for hb_media", __FUNCTION__);
return NULL;
}
memset(mp, 0, sizeof(*mp));
tipc = MALLOC(sizeof(struct tipc_private));
if ( tipc == NULL ){
PILCallLog(LOG, PIL_CRIT,
"%s: malloc failed for tipc_private", __FUNCTION__);
FREE(mp);
return NULL;
}
tipc->name_type = name_type;
tipc->seq_lower = seq_lower;
tipc->seq_upper = seq_upper;
/* setting mcast addr */
tipc->maddr.family = AF_TIPC;
tipc->maddr.addrtype = TIPC_ADDR_MCAST;
tipc->maddr.addr.name.domain = 0;
tipc->maddr.addr.nameseq.type = name_type;
tipc->maddr.addr.nameseq.lower = seq_lower;
tipc->maddr.addr.nameseq.upper = seq_upper;
mp->pd = (void *)tipc;
return mp;
}
/*
tipc name_type seq_lower seq_upper
*/
#define GET_NEXT_TOKEN(bp, token) do { \
int toklen; \
bp += strspn(bp, WHITESPACE); \
toklen = strcspn(bp, WHITESPACE); \
strncpy(token, bp, toklen); \
bp += toklen; \
token[toklen] = EOS; \
}while(0)
static int
tipc_parse(const char * line)
{
const char * bp = NULL;
struct hb_media * media = NULL;
char token[MAXLINE];
unsigned int name_type;
unsigned int seq_lower;
unsigned int seq_upper;
bp = line;
/* name_type */
GET_NEXT_TOKEN(bp, token);
name_type = (unsigned int)atoi(token);
/* seq_lower */
GET_NEXT_TOKEN(bp, token);
seq_lower = (unsigned int)atoi(token);
/* seq_upper */
GET_NEXT_TOKEN(bp, token);
seq_upper = (unsigned int)atoi(token);
PILCallLog(LOG, PIL_INFO,
"%s: name type: %u, sequence lower: %u, sequence upper: %u",
__FUNCTION__, name_type, seq_lower, seq_upper);
media = tipc_new (name_type, seq_lower, seq_upper );
if ( media == NULL ) {
PILCallLog(LOG, PIL_CRIT,
"%s: Could not create media", __FUNCTION__);
return HA_FAIL;
}
sprintf(token, "TIPC:<%u>", name_type);
media->name = STRDUP(token);
if ( media->name == NULL ) {
PILCallLog(LOG, PIL_CRIT,
"%s: Could not alloc media's name", __FUNCTION__);
FREE(media);
return HA_FAIL;
}
OurImports->RegisterNewMedium(media);
PILCallLog(LOG, PIL_INFO, "%s: register new medium OK", __FUNCTION__);
return HA_OK;
}
static int
tipc_open(struct hb_media * mp)
{
struct tipc_private * tipc = NULL;
tipc = (struct tipc_private *) mp->pd;
TIPC_ASSERT(mp);
tipc->recvfd = tipc_make_receive_sock(mp);
if ( tipc->recvfd < 0 ) {
PILCallLog(LOG, PIL_CRIT, "%s: Open receive socket failed",
__FUNCTION__);
return HA_FAIL;
}
tipc->sendfd = tipc_make_send_sock(mp);
if ( tipc->sendfd < 0 ) {
close(tipc->recvfd);
PILCallLog(LOG, PIL_CRIT, "%s: Open send socket failed",
__FUNCTION__);
return HA_FAIL;
}
PILCallLog(LOG, PIL_INFO, "%s: Open tipc successfully", __FUNCTION__);
return HA_OK;
}
static int
tipc_close(struct hb_media * mp)
{
struct tipc_private * tipc;
TIPC_ASSERT(mp);
tipc = (struct tipc_private *) mp->pd;
if ( tipc->recvfd >= 0 ) {
close(tipc->recvfd);
tipc->recvfd = -1;
}
if ( tipc->sendfd >= 0 ) {
close(tipc->sendfd);
tipc->sendfd = -1;
}
PILCallLog(LOG, PIL_INFO, "%s: tipc closed", __FUNCTION__);
return HA_OK;
}
char tipc_pkt[MAXMSG];
static void *
tipc_read(struct hb_media * mp, int * len)
{
struct sockaddr_tipc client_addr;
struct tipc_private * tipc;
socklen_t sock_len;
int numbytes;
TIPC_ASSERT(mp);
tipc = (struct tipc_private *) mp->pd;
sock_len = sizeof(struct sockaddr_tipc);
if (( numbytes = recvfrom(tipc->recvfd, tipc_pkt, MAXMSG, 0,
(struct sockaddr*)&client_addr, &sock_len)) < 0) {
if ( errno != EINTR ) {
PILCallLog(LOG, PIL_CRIT,
"%s: Error receiving message: %s",
__FUNCTION__, strerror(errno));
}
return NULL;
}
tipc_pkt[numbytes] = EOS;
*len = numbytes + 1;
if ( Debug >= PKTTRACE ) {
PILCallLog(LOG, PIL_INFO, "%s: Got %d bytes",
__FUNCTION__, numbytes);
}
return tipc_pkt;
}
static int
tipc_write(struct hb_media * mp, void * msg, int len)
{
struct tipc_private * tipc;
int numbytes;
TIPC_ASSERT(mp);
tipc = (struct tipc_private *) mp->pd;
if ( (numbytes = sendto(tipc->sendfd, msg, len, 0,
(struct sockaddr *)&tipc->maddr,
sizeof(struct sockaddr_tipc))) < 0 ){
if (!mp->suppresserrs) {
PILCallLog(LOG, PIL_CRIT, "%s: Unable to send message: %s",
__FUNCTION__, strerror(errno));
}
return HA_FAIL;
}
if ( numbytes != len ) {
PILCallLog(LOG, PIL_WARN,
"%s: Sent %d bytes, message length is %d",
__FUNCTION__, numbytes, len);
return HA_FAIL;
}
if ( Debug >= PKTTRACE ) {
PILCallLog(LOG, PIL_INFO, "%s: Sent %d bytes",
__FUNCTION__, numbytes);
}
return HA_OK;
}
static int
tipc_mtype(char ** buffer) {
*buffer = STRDUP(PIL_PLUGIN_S);
if (!*buffer) {
return 0;
}
return STRLEN_CONST(PIL_PLUGIN_S);
}
static int
tipc_descr(char ** buffer) {
const char constret[] = "tipc communication module";
*buffer = STRDUP(constret);
if (!*buffer) {
return 0;
}
return STRLEN_CONST(constret);
}
static int
tipc_isping(void) {
return 0;
}
static int
tipc_make_receive_sock(struct hb_media * mp)
{
struct sockaddr_tipc server_addr;
struct tipc_private * tipc = NULL;
int sd;
sd = socket (AF_TIPC, SOCK_RDM, 0);
tipc = (struct tipc_private *) mp->pd;
server_addr.family = AF_TIPC;
server_addr.addrtype = TIPC_ADDR_NAMESEQ;
server_addr.scope = TIPC_CLUSTER_SCOPE;
server_addr.addr.nameseq.type = tipc->name_type;
server_addr.addr.nameseq.lower = tipc->seq_lower;
server_addr.addr.nameseq.upper = tipc->seq_upper;
/* Bind port to sequence */
if (bind (sd, (struct sockaddr*)&server_addr,
sizeof(struct sockaddr_tipc)) != 0){
PILCallLog(LOG, PIL_CRIT,
"%s: Could not bind to sequence <%u,%u,%u> scope %u",
__FUNCTION__,
server_addr.addr.nameseq.type,
server_addr.addr.nameseq.lower,
server_addr.addr.nameseq.upper,
server_addr.scope);
return -1;
}
PILCallLog(LOG, PIL_INFO,
"%s: Bound to name sequence <%u,%u,%u> scope %u",
__FUNCTION__,
server_addr.addr.nameseq.type,
server_addr.addr.nameseq.lower,
server_addr.addr.nameseq.upper,
server_addr.scope);
return sd;
}
static int
tipc_make_send_sock(struct hb_media * mp)
{
int sd = socket (AF_TIPC, SOCK_RDM, 0);
return sd;
}
static struct hb_media_fns tipcOps ={
NULL,
tipc_parse,
tipc_open,
tipc_close,
tipc_read,
tipc_write,
tipc_mtype,
tipc_descr,
tipc_isping,
};