Hi all,

  I'm trying to write a disk based HBcomm plug-in for heartbeat. 

  My current implementation is:
     write:
           write to it's own slot
           sleep 0.2s
     read:
           scan all slots for new pkt
           if (found) {
              do {
                read the slot for new pkt
              } while (checksum of pkt is wrong)
           } else {
             sleep 0.1s
           }
                
  This plug-in suffers from packages losting as you can see. Using this 
plug-in, heartbeat stops itself about 2 minutes after its starting, as it 
finds more then 6 pkts missing. 

  Such a simple protocol is used because I failed to google out something 
better. :(

  You suggestions on how to improve are really appreciated. Thanks.
/*
 * dskcm.c: Disk based communication code for heartbeat.
 *
 * Copyright (C) 2007 Xinwei Hu <[EMAIL PROTECTED]>
 *	
 * 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
 *
 */

#define _GNU_SOURCE
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 199309

#include <lha_internal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>

#include <heartbeat.h>
#include <HBcomm.h>

#define PIL_PLUGINTYPE          HB_COMM_TYPE
#define PIL_PLUGINTYPE_S        HB_COMM_TYPE_S
#define PIL_PLUGIN              dskcm
#define PIL_PLUGIN_S            "dskcm"
#define PIL_PLUGINLICENSE 	LICENSE_LGPL
#define PIL_PLUGINLICENSEURL 	URL_LGPL
#include <pils/plugin.h>

/*
 * The SHA implementation is from mozilla.
 * TODO: reuse the code from HBauth
 *
 * The Original Code is SHA 180-1 Reference Implementation (Compact version)
 * 
 * The Initial Developer of the Original Code is Paul Kocher of
 * Cryptography Research.  Portions created by Paul Kocher are 
 * Copyright (C) 1995-9 by Cryptography Research, Inc.  All
 * Rights Reserved.
 * 
 * Contributor(s):
 *
 *     Paul Kocher
 */

typedef struct {
  unsigned int H[5];
  unsigned int W[80];
  int lenW;
  unsigned int sizeHi,sizeLo;
} SHA_CTX;

static SHA_CTX sha_ctx;

static void SHA1_Init(SHA_CTX *ctx);
static void SHA1_Update(SHA_CTX *ctx, const void *dataIn, int len);
static void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx);
static void shaHashBlock(SHA_CTX *ctx);

#define DSKCM_ALIGN_SZ 512
#define DISKMETA_SZ DSKCM_ALIGN_SZ
#define SLOTMETA_SZ DSKCM_ALIGN_SZ
#define DSKCM_SLOT_SZ MAXMSG
#define DSKCM_MAX_SLOTS 64
#define DSKCM_VERSION 1

struct diskmeta 
{
  int32_t version;
  int32_t slots;
  int32_t slot_bitmap[4];
  char padding[DISKMETA_SZ-24];
} __attribute__((__packed__));

struct slotmeta 
{
  int32_t gen_number;
  int32_t seq_number;
  int32_t chksum[5]; 
  int32_t lrgn[64];
  int32_t msg_size;
  int32_t msg_cont;
  char padding[SLOTMETA_SZ-292];
} __attribute__((__packed__));

struct slot 
{
  char msg[DSKCM_SLOT_SZ];
} __attribute__((__packed__));

static int is_valid_dev(const char* dev);
static void mysleep(double tm);
static void compute_chksum(char* msg, size_t msg_size, int32_t *sum);
static int check_chksum(char* msg, size_t msg_size, int32_t sum[5]);
static int dsk_slot_get(int dskfd, int slot, struct slot** sp, struct slotmeta** smp);
static int dsk_slot_set(int dskfd, int slot, struct slot* sp, struct slotmeta* smp);
static size_t dsk_read(int dskfd, int slot, void** rbuf);
static int dsk_write(int dskfd, int slot, const char* msg, size_t msg_size);
static size_t read_new_arrival(int dskfd, int slot, int* arri_slot, void** rbuf);
inline ssize_t dsk_get_impl(int dskfd, void** buf, size_t sz, off_t of);

//disk info
static int32_t dsk_max_slots;
static int32_t dsk_slot_start;
static int32_t dsk_slotmeta_start;

/* hua li de feng ge xian */

struct dskcm_private {
	char* dskn;
	int   slot;
	int   dskfd;
};

static struct hb_media*	dskcm_new(const char* dev, int slot);
static int      dskcm_parse(const char* line);
static int		dskcm_open(struct hb_media* mp);
static int		dskcm_close(struct hb_media* mp);
static void*		dskcm_read(struct hb_media* mp, int *lenp);
static int		dskcm_write(struct hb_media* mp, void* msg, int len);
static int		dskcm_descr(char** buffer);
static int		dskcm_mtype(char** buffer);
static int		dskcm_isping(void);

static struct hb_media_fns dskcmOps ={
	NULL,			/* Create single object function */
	dskcm_parse,		/* whole-line parse function */
	dskcm_open,
	dskcm_close,
	dskcm_read,
	dskcm_write,
	dskcm_mtype,
	dskcm_descr,
	dskcm_isping,
};

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;

/* XXX: why this ? */
static int
get_slot(const char* slot, int *s)
{
	*s = (int)atoi(slot);
	return 0;
}

#define LOG	PluginImports->log
#define MALLOC	PluginImports->alloc
#define STRDUP  PluginImports->mstrdup
#define FREE	PluginImports->mfree

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
	,	&dskcmOps
	,	NULL		/*close */
	,	&OurInterface
	,	(void*)&OurImports
	,	interfprivate); 
}

void mysleep(double tm)
{
	double t = tm * 1000000;
	if (random() % 2) 
		t += random() % 100000;
	else 
		t -= random() % 100000;
	
  usleep(t);
}

static void
compute_chksum(char* msg, size_t msg_size, int32_t *sum)
{
  unsigned char hashout[20];
  SHA1_Init(&sha_ctx);
  SHA1_Update(&sha_ctx, msg, msg_size);
  SHA1_Final(hashout, &sha_ctx);

  memcpy(sum, hashout, sizeof(unsigned char)*20);
}

static int
check_chksum(char* msg, size_t msg_size, int32_t sum[5])
{
  int32_t r[5];
  compute_chksum(msg, msg_size, r);

  if (memcmp(r, sum, sizeof(r)) == 0)
    return 0;
  else
    return -1;
}

int is_valid_dev(const char* dev)
{
  int dskfd = -1;
  void* vp;
  size_t sz;
  ssize_t rsz;
  int ri;
  int i;

  sz = DISKMETA_SZ > SLOTMETA_SZ ? DISKMETA_SZ : SLOTMETA_SZ;
  sz = sz > DSKCM_SLOT_SZ ? sz : DSKCM_SLOT_SZ;  

  dskfd = open(dev, O_RDWR | O_DIRECT);

  if (dskfd == -1) {
      perror("open(main)");
      return -1;
    }
  
  ri = posix_memalign(&vp,
                      DSKCM_ALIGN_SZ,
                      sz);
  if (ri != 0) {
    fprintf(stderr,
            "posix_memalign(check_dsk): %d\n", ri);
    return -1;
  }

  memset(vp, 0, sz);
  
  rsz = pread(dskfd, (struct diskmeta*)vp, sizeof(struct diskmeta), 0);
  if (rsz == -1) {
	  perror("pread(init_dsk)");
	  free(vp);
	  return -1;
  }

  if (((struct diskmeta*)vp)->version != DSKCM_VERSION) {
    printf("This version of disk is not supported\n");
    printf("Please re-initialize the disk.\n");
    free(vp);
    return -1;
  }

  i = ((struct diskmeta*)vp)->slots;
  if (i <= 0 || i > DSKCM_MAX_SLOTS) {
    printf("Wrong number of slots.\n");
    printf("Please re-initialize the disk.\n");
    free(vp);
    return -1;
  }
  
  dsk_max_slots = i;
  dsk_slotmeta_start = DISKMETA_SZ;
  dsk_slot_start = DISKMETA_SZ + SLOTMETA_SZ * dsk_max_slots;
  
  rsz = pread(dskfd, vp, DSKCM_SLOT_SZ, dsk_slot_start+DSKCM_SLOT_SZ*(i-1));
  if (rsz == -1) {
    perror("pread last slot(check_dsk)");
    free(vp);
    return -1;
  }
  free(vp);
  return 0;
}

#define		ISDSKCMOBJECT(mp) ((mp) && ((mp)->vf == (void*)&dskcmOps))
#define		DSKCMASSERT(mp)	g_assert(ISDSKCMOBJECT(mp))

static int 
dskcm_mtype(char** buffer) { 
	*buffer = STRDUP(PIL_PLUGIN_S);
	if (!*buffer) {
		return 0;
	}

	return STRLEN_CONST(PIL_PLUGIN_S);
}

static int
dskcm_descr(char **buffer) { 
	const char constret[] = "Disk based broadcast";
	*buffer = STRDUP(constret);
	if (!*buffer) {
		return 0;
	}

	return STRLEN_CONST(constret);
}

static int
dskcm_isping(void) {
    return 0;
}

/*
 *	Open UDP/IP broadcast heartbeat interface
 */
static int
dskcm_open(struct hb_media* mp)
{
	struct dskcm_private * dpi;

	DSKCMASSERT(mp);
	dpi = (struct dskcm_private*) mp->pd;

	if ((dpi->dskfd = open(dpi->dskn, O_RDWR | O_DIRECT)) < 0) {
		return HA_FAIL;
	}

	PILCallLog(LOG, PIL_INFO
	,	"Disk based broadcasting started on device %s slot %d."
	,	dpi->dskn, dpi->slot);

	if (DEBUGPKT) {
		PILCallLog(LOG, PIL_DEBUG
		,	"dskcm_open : fd %d opened for reading/writing"
		,	dpi->dskfd);
	}

	return(HA_OK);
}

static int
dskcm_close(struct hb_media* mp)
{
	struct dskcm_private * dpi;
	int	rc = HA_OK;

	DSKCMASSERT(mp);
	dpi = (struct dskcm_private *) mp->pd;

	if (dpi->dskfd >= 0) {
		if (close(dpi->dskfd) < 0) {
			rc = HA_FAIL;
		}
	}

	PILCallLog(LOG, PIL_INFO
	, "Disk based broadcast heartbeat closed on device %s slot %d - Status: %d"
	,  dpi->dskn, dpi->slot, rc);

	return(rc);
}

inline ssize_t
dsk_get_impl(int dskfd, void** buf, size_t sz, off_t of)
{
	int ri;
	ssize_t rsz;
	void* rp;

	*buf = 0;
	ri = posix_memalign(&rp, DSKCM_ALIGN_SZ, sz);
	if (ri != 0) {
		fprintf(stderr, "posix_memalign(dsk_get_impl): %d\n", ri);
		return -1;
	}

	rsz = pread(dskfd, rp, sz, of);
	if (rsz == -1) {
		perror("pread(dsk_get_imple)");
		free(rp);
		return -1;
	}

	*buf = rp;
	return rsz;
}

int
dsk_slot_get(int dskfd, int slot, struct slot** sp, struct slotmeta** smp)
{
  struct slot* rsp = NULL;
  struct slotmeta* rsmp = NULL;
  ssize_t rsz;

  if (slot < 0 || slot >= dsk_max_slots)
    return -1;
  
  rsz = dsk_get_impl(dskfd, (void**)&rsp, sizeof(struct slot),
		  dsk_slot_start + DSKCM_SLOT_SZ * slot);
  if (rsz == -1) {
	  perror("dsk_get_impl(dsk_slot_get)");
	  goto errout;
  }

  rsz = dsk_get_impl(dskfd, (void**)&rsmp, sizeof(struct slotmeta), 
		  dsk_slotmeta_start + SLOTMETA_SZ*slot);
  if (rsz == -1) {
	  perror("dsk_get_impl(dsk_get_imple)");
	  goto errout;
  }
  
  *sp = rsp;
  *smp = rsmp;
  return 0;

errout:
  if (rsp) free(rsp);
  if (rsmp) free(rsmp);
  *sp = NULL; *smp = NULL;
  return -1;
}

static size_t
dsk_read(int dskfd, int slot, void** rbuf)
{
  struct slot* sp;
  struct slotmeta* smp;
  char *msg = NULL;
  size_t size = 0;
  int cont = 0;
  int32_t seq_number = -1;
  int32_t gen_number = 0;
  int ri;
  
  do {
    ri = dsk_slot_get(dskfd, slot, &sp, &smp);
    if (ri != 0) { //failed to read disk
      PILCallLog(LOG, PIL_CRIT
                 ,  "Error preading disk: %s"
                 ,  strerror(errno));
      if (msg != NULL) free(msg);
      *rbuf = NULL;
      return -1;
    }
   
    //    print_chksum("dsk_read", smp->chksum);

    if (gen_number == 0) {
      gen_number = smp->gen_number;
    } else if (gen_number != smp->gen_number) {
      if (seq_number <= 0) {
        // we are waiting for the first segment, but missed it.
        // skip that and start to waiting for next pkt.
        seq_number = -1;
        gen_number = smp->gen_number;
      } else {
        // we are in the half way receiving a pkt
        // give up.
        PILCallLog(LOG, PIL_CRIT
                   ,  "Sending too fast. expect %d, get %d"
                   ,  gen_number, smp->gen_number);
        free(msg); msg = NULL;
        free(sp); free(smp);
        return -1;
      }
    } 
        
    if (seq_number == -1)
      seq_number = smp->seq_number;
    else if (seq_number == smp->seq_number) {
      free(sp); free(smp);
      cont = 1;
      continue;
    }
    
    if (check_chksum(sp->msg, smp->msg_size, smp->chksum) < 0) {
      free(sp); free(smp);
      cont = 1;
      continue;
    } else {
      size += smp->msg_size;        
      
      if (msg == NULL) {
        msg = malloc(sizeof(char) * size); 
        memset(msg, 0, sizeof(char) * size);
      } else {
        msg = realloc(msg, sizeof(char) * size);
        memset(msg + size - smp->msg_size, 0, sizeof(char)*smp->msg_size);
      }
      
      if (msg == NULL) {
        free(sp);
        free(smp);
        *rbuf = NULL;
        return 0;
      }
      
      memcpy(msg + size - smp->msg_size, sp->msg, smp->msg_size);
      if (smp->msg_cont == 1)
        cont = 1;
      else
        cont = 0;
      free(sp); free(smp);
    }
    if (cont == 1) {
      PILCallLog(LOG, PIL_CRIT
                 ,  "We should never meet so big pkt!");
    }
  } while (cont);

  *rbuf = msg;
  return size;
}

static size_t
read_new_arrival(int dskfd, int slot, int* arri_slot, void** rbuf)
{
  int i = 0;
  
  static int lrgn_init = 0;
  static int32_t lrgn[64];
  static struct slotmeta* smps = NULL;
  
  if (lrgn_init == 0 ) {
    struct slotmeta* smp;
    struct slot* sp;
    int ri;
    ri = dsk_slot_get(dskfd, slot, &sp, &smp);
    if (ri != 0) {
		PILCallLog(LOG, PIL_CRIT
				,  "Error get slot from disk: %s"
				,  strerror(errno));
      return -1;
    }
    memcpy(lrgn, smp->lrgn, sizeof(int32_t)*64);
    free(smp);
    free(sp);
    lrgn_init = 1;
  }
  
  if (smps == NULL) {
    int ri;
    ri = posix_memalign((void**)&smps,
                        DSKCM_ALIGN_SZ,
                        sizeof(struct slotmeta) * dsk_max_slots);
	  if (ri != 0) {
		  PILCallLog(LOG, PIL_CRIT
				  ,  "Error allocing aligned memory: %s"
				  ,  strerror(ri));
        *rbuf = NULL;
        return -1;
	  }
  }

  for (;;) {
      
    size_t rsz;
    rsz = pread(dskfd, smps, sizeof(struct slotmeta) * dsk_max_slots, 
                dsk_slotmeta_start);
    if (rsz == -1) {
	  PILCallLog(LOG, PIL_CRIT
                 ,  "Error preading disk: %s"
                 ,  strerror(errno));
	  *rbuf = NULL;
	  return -1;
    }

    for (i = 0; i < dsk_max_slots; i++) {
      if ((smps+i)->gen_number > lrgn[i]) {
        lrgn[i] = (smps+i)->gen_number;
        *arri_slot = i;
        return dsk_read(dskfd, i, rbuf);
      }
    }

    mysleep(0.1);
  }
  *rbuf = NULL;
  return 0;
}

int
dsk_slot_set(int dskfd, int slot, struct slot* sp, struct slotmeta* smp) 
{
  ssize_t rsz;

  if (slot < 0 || slot >= DSKCM_MAX_SLOTS)
    return -1;

  rsz = pwrite(dskfd, sp, sizeof(struct slot), 
		  dsk_slot_start+DSKCM_SLOT_SZ*slot); 
  if (rsz == -1) {
	  perror("pwrite slot(dsk_slot_set)");
	  return errno;
  }
  rsz = pwrite(dskfd, smp, sizeof(struct slotmeta), 
		  dsk_slotmeta_start+SLOTMETA_SZ*slot); 
  if (rsz == -1) {
	  perror("pwrite slotmeta(dsk_slot_set)");
	  return errno;
  }

  return 0;
}

int
dsk_write(int dskfd, int slot, const char* msg, size_t msg_size)
{
  struct slot *sp;
  struct slotmeta *smp;
  const char *msg_ptr = msg;
  int ri;
  
  ri = dsk_slot_get(dskfd, slot, &sp, &smp);
  if (ri != 0) return -1;

  smp->seq_number = -1;
  smp->gen_number = smp->gen_number + 1;

  while (msg_size > DSKCM_SLOT_SZ) {
    
    smp->seq_number = smp->seq_number + 1;
    smp->msg_size = DSKCM_SLOT_SZ;
    smp->msg_cont = 1;
    memcpy(sp->msg, msg_ptr, DSKCM_SLOT_SZ);
    msg_ptr += DSKCM_SLOT_SZ;
    msg_size -= DSKCM_SLOT_SZ;

    compute_chksum(sp->msg, DSKCM_SLOT_SZ, smp->chksum);
    
    //    print_chksum("smp->chksum 1", smp->chksum);
    
          
    if (dsk_slot_set(dskfd, slot, sp, smp) == -1) {
      free(sp); free(smp);
      return -1;
    }
    /*
     * just assume peers recv it in time
     * yes, we are not reliable :)
     */
    //mysleep(0.5);
    mysleep(0.2);
  }
  
  smp->seq_number = smp->seq_number + 1;
  smp->msg_size = msg_size;
  smp->msg_cont = 0;
  
  memcpy(sp->msg, msg_ptr, msg_size);

  compute_chksum(sp->msg, smp->msg_size, smp->chksum);
  if (dsk_slot_set(dskfd, slot, sp, smp) == -1) {
    free(sp); free(smp);
    return -1;
  }
  free(sp); free(smp);
  return 0;
}

/*
 * Receive a heartbeat broadcast packet from DSKCM interface
 */

char			dskcm_pkt[MAXMSG];
void *
dskcm_read(struct hb_media* mp, int * lenp)
{

	struct dskcm_private *	dpi;
	int	numbytes;
    int arri_slot;
    void* buf;
    
	DSKCMASSERT(mp);
	dpi = (struct dskcm_private *) mp->pd;

	if (DEBUGPKT) {
		PILCallLog(LOG, PIL_DEBUG
		,	"dskcm_read : reading from device %s slot %d"
			   , dpi->dskn, dpi->slot);
	}

    /* read available */

    //read_new_arrival(int dskfd, int slot, int* arri_slot, void** rbuf);
    numbytes = read_new_arrival(dpi->dskfd, dpi->slot, &arri_slot, &buf);
    if (numbytes == -1) {
      PILCallLog(LOG, PIL_CRIT
                 ,	"Error receiving from disk %s: %s"
                 ,	dpi->dskn, strerror(errno));
      return NULL;
    }
    
    memcpy(dskcm_pkt, buf, numbytes);
    free(buf);

	/* Avoid possible buffer overruns */
	dskcm_pkt[numbytes] = EOS;

	if (DEBUGPKT) {
		PILCallLog(LOG, PIL_DEBUG, "got %d byte packet from %s slot %d"
                   ,	numbytes, dpi->dskn, dpi->slot);
	}
	if (DEBUGPKTCONT && numbytes > 0) {
		PILCallLog(LOG, PIL_DEBUG, "%s", dskcm_pkt);
	}
	
	*lenp = numbytes +1;
	return dskcm_pkt;
}

static int
dskcm_write(struct hb_media* mp, void *pkt, int len)
{

  struct dskcm_private *	dpi;
  int			rc;

  DSKCMASSERT(mp);
  dpi = (struct dskcm_private *) mp->pd;

  //  int
  //dsk_write(int dskfd, int slot, const char* msg, size_t msg_size)
  rc = dsk_write(dpi->dskfd, dpi->slot, (const char*)pkt, len);
  if (rc == -1) {

    struct ha_msg* m;

    int		err = errno;
    PILCallLog(LOG, PIL_CRIT, "Unable to send dskcm [%d] packet(len=%d): %s",
			   rc,len,  strerror(err));
		
    m =  wirefmt2msg(pkt, len,MSG_NEEDAUTH);
    if (m){
      cl_log_message(LOG_ERR, m);
      ha_msg_del(m);
    }
    errno = err;
    return(HA_FAIL);
  }

  if (DEBUGPKT) {
    PILCallLog(LOG, PIL_DEBUG
               ,	"dskcm_write : writing %d bytes to %s (slot %d)"
               ,	rc, dpi->dskn, dpi->slot);
  }

  if (DEBUGPKTCONT) {
    PILCallLog(LOG, PIL_DEBUG, "dskcm pkt out: [%s]", (char*)pkt);
  }
  
  mysleep(0.3);
  return(HA_OK);
}


static int
dskcm_parse(const char* line)
{
	const char* bp = line;
	char        dev[MAXLINE];
	char        token[MAXLINE];
	int         slot;
	int         toklen;
	struct hb_media *mp;

	bp += strspn(bp, WHITESPACE);
	toklen = strcspn(bp, WHITESPACE);
	strncpy(dev, bp, toklen);	
	bp += toklen;
	dev[toklen] = EOS;

	if (*dev == EOS) {
		PILCallLog(LOG, PIL_CRIT, "dskcm device is not set");
		return HA_FAIL;
	}
	if (is_valid_dev(dev) == -1) {
		PILCallLog(LOG, PIL_CRIT, "dskcm device [%s] is invalid or not set up properly", dev);
		return HA_FAIL;
	}

	bp += strspn(bp, WHITESPACE);
	toklen = strcspn(bp, WHITESPACE);
	strncpy(token, bp, toklen);
	bp += toklen;
	token[toklen] = EOS;

	if (*token == EOS) {
		PILCallLog(LOG, PIL_CRIT, "dskcm [%s] missing slot", dev);
		return HA_FAIL;
	}
	if (get_slot(token, &slot) < 0) {
		PILCallLog(LOG, PIL_CRIT, "dskcm [%s] invalid slot [%d]", dev, slot);
		return HA_FAIL;
	}

	if ((mp = dskcm_new(dev, slot)) == NULL) {
		return HA_FAIL;
	}
	OurImports->RegisterNewMedium(mp);
	return HA_OK;
}

static struct dskcm_private*
new_dskcm_private(const char* dev, int slot)
{
	struct dskcm_private *dpi;
	dpi = MALLOC(sizeof(struct dskcm_private));
	if (dpi == NULL)
		return NULL;
	dpi->dskn = (char*)STRDUP(dev);
	if (dpi->dskn == NULL) {
		FREE(dpi);
		return NULL;
	}
	dpi->slot = slot;
	dpi->dskfd = -1;
	return dpi;
}

static struct hb_media *
dskcm_new(const char * dev, int slot)
{
	struct dskcm_private*	dpi;
	struct hb_media *	    ret;

	dpi = new_dskcm_private(dev, slot);
	if (dpi == NULL) {
		PILCallLog(LOG, PIL_CRIT, "Create dskcm_private failed");
		return(NULL);
	}
	ret = (struct hb_media*) MALLOC(sizeof(struct hb_media));
	if (ret != NULL) {
		char * name;
		memset(ret, 0, sizeof(*ret));
		ret->pd = (void*)dpi;
		name = STRDUP(dev);
		if (name != NULL) {
			ret->name = name;
		} else {
			FREE(ret);
			ret = NULL;
		}
	}
	if (ret != NULL) {
		if (DEBUGPKT) {
			PILCallLog(LOG, PIL_DEBUG, 
					"dskcm_new: returning ret (%s)", 
					ret->name);
		}
	}else{
		FREE(dpi->dskn);
		FREE(dpi);
		if (DEBUGPKT) {
			PILCallLog(LOG, PIL_DEBUG, "dskcm_new: ret was NULL");
		}
	}
	return(ret);
}

static void SHA1_Init(SHA_CTX *ctx) {
  int i;

  ctx->lenW = 0;
  ctx->sizeHi = ctx->sizeLo = 0;

  /* Initialize H with the magic constants (see FIPS180 for constants)
   */
  ctx->H[0] = 0x67452301;
  ctx->H[1] = 0xefcdab89;
  ctx->H[2] = 0x98badcfe;
  ctx->H[3] = 0x10325476;
  ctx->H[4] = 0xc3d2e1f0;

  for (i = 0; i < 80; i++)
    ctx->W[i] = 0;
}

static void SHA1_Update(SHA_CTX *ctx, const void *_dataIn, int len) {
  const unsigned char *dataIn = _dataIn;
  int i;

  /* Read the data into W and process blocks as they get full
   */
  for (i = 0; i < len; i++) {
    ctx->W[ctx->lenW / 4] <<= 8;
    ctx->W[ctx->lenW / 4] |= (unsigned int)dataIn[i];
    if ((++ctx->lenW) % 64 == 0) {
      shaHashBlock(ctx);
      ctx->lenW = 0;
    }
    ctx->sizeLo += 8;
    ctx->sizeHi += (ctx->sizeLo < 8);
  }
}


static void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx) {
  unsigned char pad0x80 = 0x80;
  unsigned char pad0x00 = 0x00;
  unsigned char padlen[8];
  int i;

  /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
   */
  padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255);
  padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255);
  padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255);
  padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255);
  padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255);
  padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255);
  padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255);
  padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255);
  SHA1_Update(ctx, &pad0x80, 1);
  while (ctx->lenW != 56)
    SHA1_Update(ctx, &pad0x00, 1);
  SHA1_Update(ctx, padlen, 8);

  /* Output hash
   */
  for (i = 0; i < 20; i++) {
    hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24);
    ctx->H[i / 4] <<= 8;
  }

  /*
   *  Re-initialize the context (also zeroizes contents)
   */
  SHA1_Init(ctx);
}


#define SHA_ROT(X,n) (((X) << (n)) | ((X) >> (32-(n))))

static void shaHashBlock(SHA_CTX *ctx) {
  int t;
  unsigned int A,B,C,D,E,TEMP;

  for (t = 16; t <= 79; t++)
    ctx->W[t] =
      SHA_ROT(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1);

  A = ctx->H[0];
  B = ctx->H[1];
  C = ctx->H[2];
  D = ctx->H[3];
  E = ctx->H[4];

  for (t = 0; t <= 19; t++) {
    TEMP = SHA_ROT(A,5) + (((C^D)&B)^D)     + E + ctx->W[t] + 0x5a827999;
    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
  }
  for (t = 20; t <= 39; t++) {
    TEMP = SHA_ROT(A,5) + (B^C^D)           + E + ctx->W[t] + 0x6ed9eba1;
    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
  }
  for (t = 40; t <= 59; t++) {
    TEMP = SHA_ROT(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdc;
    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
  }
  for (t = 60; t <= 79; t++) {
    TEMP = SHA_ROT(A,5) + (B^C^D)           + E + ctx->W[t] + 0xca62c1d6;
    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
  }

  ctx->H[0] += A;
  ctx->H[1] += B;
  ctx->H[2] += C;
  ctx->H[3] += D;
  ctx->H[4] += E;
}
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to