//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
//-----------------------------------------------------------------------------
//
// Description:
//      Implementation of rsvcCbk class
//
// Author:  Jie Chen
//
// Revision History:
//   rsvcCbk.cc,v
// Revision 1.1  1998/01/22  17:08:01  akers
// Addition of new NameServer
//
//
//
#include <stdio.h>
#include <string.h>
#include <sys/types.h>

#ifdef _WIN32
	#include <WinSock2.h>
#else
	#include <netinet/in.h>
#endif

#include <rsvcConfig.h>
#include "rsvcCbk.h"

rsvcCbk::rsvcCbk (void)
:rsvcStreamable (), rsvcHashable (),
 opcode_ (RSVC_OP_UNKNOWN), cbkid_ (0), reqid_ (0), 
 clientid_ (0), socketid_ (0), status_ (RSVC_SUCCESS), private_ (0)
{
#ifdef _TRACE_OBJECTS
  printf ("Create rsvcCbk Class Object\n");
#endif

  // empty
}

rsvcCbk::rsvcCbk (int opcode, int cbkid, int reqid,  
		  int clientid, int socketid, int status, void* ptr)
:rsvcStreamable (), rsvcHashable (), 
 opcode_ (opcode), cbkid_ (cbkid), reqid_ (reqid), 
 clientid_ (clientid), socketid_ (socketid), 
 status_ (status), private_ (ptr)
{
#ifdef _TRACE_OBJECTS
  printf ("Create rsvcCbk Class Object\n");
#endif
  // empty
}

rsvcCbk::rsvcCbk (const rsvcCbk& cbk)
:rsvcStreamable (), rsvcHashable (),
 opcode_ (cbk.opcode_), cbkid_ (cbk.cbkid_), reqid_ (cbk.reqid_), 
 clientid_ (cbk.clientid_), socketid_ (cbk.socketid_), 
 status_ (cbk.status_), private_ (cbk.private_)
{
#ifdef _TRACE_OBJECTS
  printf ("Create rsvcCbk Class Object\n");
#endif
  // empty
}

rsvcCbk &
rsvcCbk::operator = (const rsvcCbk& cbk)
{
  if (this != &cbk) {
    opcode_ = cbk.opcode_;
    cbkid_ = cbk.cbkid_;
    reqid_ = cbk.reqid_;
    clientid_ = cbk.clientid_;
    socketid_ = cbk.socketid_;
    status_ = cbk.status_;
    private_ = cbk.private_;
  }
  return *this;
}

rsvcCbk::~rsvcCbk (void)
{
#ifdef _TRACE_OBJECTS
  printf ("Delete rsvcCbk Class Object\n");
#endif
  // empty
}


void
rsvcCbk::cleanup (void)
{
  opcode_ = 0;
  cbkid_ = 0;
  reqid_ = 0;
  clientid_ = 0;
  socketid_ = 0;
  status_ = 0;
  private_ = 0;
}

void
rsvcCbk::socketid (int socketid)
{
  socketid_ = socketid;
}

int
rsvcCbk::socketid (void) const
{
  return socketid_;
}

void
rsvcCbk::cbkstatus (int st)
{
  status_ = st;
}

int
rsvcCbk::cbkstatus (void) const
{
  return status_;
}

int
rsvcCbk::opcode (void) const
{
  return opcode_;
}

void
rsvcCbk::opcode (int op)
{
  opcode_ = op;
}

int
rsvcCbk::reqid (void) const
{
  return reqid_;
}

void
rsvcCbk::reqid (int req)
{
  reqid_ = req;
}

int
rsvcCbk::cbkid (void) const
{
  return cbkid_;
}

void
rsvcCbk::cbkid (int id)
{
  cbkid_ = id;
}

int
rsvcCbk::clientid (void) const
{
  return clientid_;
}

void
rsvcCbk::clientid (int cid)
{
  clientid_ = cid;
}

void *
rsvcCbk::userptr (void) const
{
  return private_;
}

void
rsvcCbk::userptr (void* ptr)
{
  private_ = ptr;
}

size_t
rsvcCbk::streamSize (void)
{
  return 6*sizeof (int);
}

int
rsvcCbk::streamOut (char** buf, size_t* len)
{
  char* buffer = new char[6*sizeof (int)];
  
  if (buffer == 0) {
    fprintf (stderr, "Allocate buffer for rsvcCbk error, quit\n");
    exit (1);
  }

  *len = 6*sizeof (int);
  *buf = buffer;

  int tmp; 
  int i = 0;

  tmp = htonl (opcode_);
  memcpy (&(buffer[i]), &tmp, sizeof (int));
  i += sizeof (int);

  tmp = htonl (cbkid_);
  memcpy (&(buffer[i]), &tmp, sizeof (int));  
  i += sizeof (int);

  tmp = htonl (reqid_);
  memcpy (&(buffer[i]), &tmp, sizeof (int));  
  i += sizeof (int);

  tmp = htonl (clientid_);
  memcpy (&(buffer[i]), &tmp, sizeof (int));  
  i += sizeof (int);

  tmp = htonl (socketid_);
  memcpy (&(buffer[i]), &tmp, sizeof (int));  
  i += sizeof (int);

  tmp = htonl (status_);
  memcpy (&(buffer[i]), &tmp, sizeof (int));  
  i += sizeof (int);

  return RSVC_SUCCESS;
}

int
rsvcCbk::streamOut (char* buffer, size_t len)
{
   if (buffer == 0) {
    fprintf (stderr, "Allocate buffer for rsvcCbk error, quit\n");
    exit (1);
  }

   if (len < 6*sizeof (int)) {
     fprintf (stderr, "Streaming out rsvcCbk has not enough buffer size\n");
     return RSVC_OVERFLOW;
   }

   int tmp; 
   int i = 0;

   tmp = htonl (opcode_);
   memcpy (&(buffer[i]), &tmp, sizeof (int));
   i += sizeof (int);

   tmp = htonl (cbkid_);
   memcpy (&(buffer[i]), &tmp, sizeof (int));  
   i += sizeof (int);

   tmp = htonl (reqid_);
   memcpy (&(buffer[i]), &tmp, sizeof (int));  
   i += sizeof (int);

   tmp = htonl (clientid_);
   memcpy (&(buffer[i]), &tmp, sizeof (int));  
   i += sizeof (int);

   tmp = htonl (socketid_);
   memcpy (&(buffer[i]), &tmp, sizeof (int));  
   i += sizeof (int);

   tmp = htonl (status_);
   memcpy (&(buffer[i]), &tmp, sizeof (int));  
   i += sizeof (int);

   return RSVC_SUCCESS;
}

int
rsvcCbk::streamIn (char* buffer, size_t len)
{
  if (buffer == 0) {
    fprintf (stderr, "Stream in buffer == 0 error, quit\n");
    exit (1);
  }

  if (len < 6*sizeof (int)) {
     fprintf (stderr, "Streaming in rsvcCbk has not enough buffer size\n");
     return RSVC_OVERFLOW;
  }

  int tmp; 
  int i = 0;

  memcpy (&tmp, &(buffer[i]), sizeof (int));
  i += sizeof (int);
  opcode_ = ntohl (tmp);

  memcpy (&tmp, &(buffer[i]), sizeof (int));
  i += sizeof (int);
  cbkid_ = ntohl (tmp);

  memcpy (&tmp, &(buffer[i]), sizeof (int));
  i += sizeof (int);
  reqid_ = ntohl (tmp);

  memcpy (&tmp, &(buffer[i]), sizeof (int));
  i += sizeof (int);
  clientid_ = ntohl (tmp);

  memcpy (&tmp, &(buffer[i]), sizeof (int));
  i += sizeof (int);
  socketid_ = ntohl (tmp);

  memcpy (&tmp, &(buffer[i]), sizeof (int));
  i += sizeof (int);
  status_ = ntohl (tmp);

  return RSVC_SUCCESS;
}

int
rsvcCbk::sameCallback (rsvcCbk* cbk1, rsvcCbk* cbk2,
		       int checkreq)
{
  if (checkreq) {
    if (cbk1->reqid_  == cbk2->reqid_  &&
	cbk1->clientid_ == cbk2->clientid_ &&
	cbk1->socketid_ == cbk2->socketid_ &&
	cbk1->cbkid_ == cbk2->cbkid_)
      return 1;
    else
      return 0;
  }
  else {
    if (cbk1->clientid_ == cbk2->clientid_ &&
	cbk1->socketid_ == cbk2->socketid_ &&
	cbk1->cbkid_ == cbk2->cbkid_)
      return 1;
    else
      return 0;
  }
}


int
rsvcCbk::match (rsvcCbk* cbk)
{
  if (opcode_ == cbk->opcode_ &&
      reqid_  == cbk->reqid_  &&
      clientid_ == cbk->clientid_ &&
      cbkid_ == cbk->cbkid_)
    return 1;
  return 0;
}

unsigned int
rsvcCbk::hash (void)
{
  // return hash value of callback id
  unsigned int h = 0;
  unsigned char *k, *e;

  k = (unsigned char *)&cbkid_;
  e = k + sizeof (int);
  for (h = 0; k < e; ++k) {
    h *= 16777619;
    h ^= *k;
  }
  return h;
}  

