//-----------------------------------------------------------------------------
// 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 rsvcNetData Class
//
// Author:  Jie Chen
//
// Revision History:
//   rsvcNetData.cc,v
// Revision 1.1  1998/01/22  17:08:18  akers
// Addition of new NameServer
//
//
//
#include <rsvcDataStreamer.h>
#include "rsvcNetData.h"

rsvcNetData::rsvcNetData (void)
:cbk_ (), data_ ()
{
#ifdef _TRACE_OBJECTS
  printf ("    Create rsvcNetData Class Object\n");
#endif
  // empty
}

rsvcNetData::rsvcNetData (rsvcData& data, long opcode, long cbkid,
			  long reqid, long clientid, long socketid,
			  long status)
:cbk_ (opcode, cbkid, reqid, clientid, socketid, status), data_ (data)
{
#ifdef _TRACE_OBJECTS
  printf ("    Create rsvcNetData Class Object\n");
#endif
  // empty
}

rsvcNetData::rsvcNetData (rsvcData& data, rsvcCbk& cbk)
:cbk_ (cbk), data_ (data)
{
#ifdef _TRACE_OBJECTS
  printf ("    Create rsvcNetData Class Object\n");
#endif
  // empty
}

rsvcNetData::rsvcNetData (rsvcData& data)
: cbk_ (), data_ (data)
{
#ifdef _TRACE_OBJECTS
  printf ("    Create rsvcNetData Class Object\n");
#endif
  // empty
}

rsvcNetData::rsvcNetData (rsvcCbk& cbk)
:cbk_ (cbk), data_ ()
{
#ifdef _TRACE_OBJECTS
  printf ("    Create rsvcNetData Class Object\n");
#endif
  // empty
}

rsvcNetData::rsvcNetData (const rsvcNetData& data)
:cbk_ (data.cbk_), data_ (data.data_)
{
#ifdef _TRACE_OBJECTS
  printf ("    Create rsvcNetData Class Object\n");
#endif
  // empty
}

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

void
rsvcNetData::set (rsvcData& data, rsvcCbk& cbk)
{
  data_ = data;
  cbk_ = cbk;
}

void
rsvcNetData::set (rsvcCbk& cbk)
{
   cbk_ = cbk;
}


void
rsvcNetData::cleanup (void)
{
  cbk_.cleanup ();
  data_.remove ();
}

long
rsvcNetData::opcode (void) const
{
  return cbk_.opcode ();
}

void
rsvcNetData::opcode (long op)
{
  cbk_.opcode (op);
}

long
rsvcNetData::cbkid (void) const
{
  return cbk_.cbkid ();
}

void
rsvcNetData::cbkid (long cid)
{
  cbk_.cbkid (cid);
}

long
rsvcNetData::reqid (void) const
{
  return cbk_.reqid ();
}

void
rsvcNetData::reqid (long req)
{
  cbk_.reqid (req);
}

long
rsvcNetData::clientid (void) const
{
  return cbk_.clientid ();
}

void
rsvcNetData::clientid (long cid)
{
  cbk_.clientid (cid);
}

long
rsvcNetData::socketid (void) const
{
  return cbk_.socketid ();
}

void
rsvcNetData::socketid (long sid)
{
  cbk_.socketid (sid);
}

void
rsvcNetData::cbkstatus (long status)
{
  cbk_.cbkstatus (status);
}

long
rsvcNetData::cbkstatus (void) const
{
  return cbk_.cbkstatus ();
}

rsvcData& 
rsvcNetData::data (void)
{
  return data_;
}

rsvcCbk&
rsvcNetData::cbk (void)
{
  return cbk_;
}

size_t
rsvcNetData::streamSize (void)
{
  int st = RSVC_SUCCESS;
  size_t dataSize = 0;
  long   size = 0;

  // First is magic number
  dataSize  += rsvcStreamSize (_RSVC_MAGIC_NUM);  

  // Size of the data to follow after this
  dataSize += rsvcStreamSize  (size);

  // send all cbk information
  dataSize += cbk_.streamSize ();

  // send data itself
  size_t buflen, count;
  data_.streamSize (&buflen, &count);

  dataSize += buflen;

  return dataSize;
}

int
rsvcNetData::streamOut (char** buffer, size_t* len)
{
  size_t datasize = streamSize ();
  char*  buf = new char[datasize];
  int    i = 0;

  if (!buf) {
    fprintf (stderr, "Cannot allocate buffer to rsvcNetData streamout\n");
    exit (1);
  }
  
  *buffer = buf;
  *len = datasize;
  return streamOut (buf, *len, datasize);
}

int
rsvcNetData::streamOut (char* buffer, size_t buflen, size_t size)
{
  int st = RSVC_SUCCESS;
  int i = 0;

  if (size > buflen) {
    fprintf (stderr, "Fatal: rsvcNetData streamout buffer overflow %d > %d\n",
	     size , buflen);
    return RSVC_ERROR;
  }
  
  // write magic number first
  long tmp = htonl ((long)_RSVC_MAGIC_NUM);
  memcpy (&(buffer[i]), &tmp, rsvcStreamSize (_RSVC_MAGIC_NUM));
  i += rsvcStreamSize (_RSVC_MAGIC_NUM);

  // write data size without header information
  size_t real_size = size - rsvcStreamSize (_RSVC_MAGIC_NUM)
    - rsvcStreamSize (size);
    
  tmp = htonl (real_size);
  memcpy (&(buffer[i]), &tmp, rsvcStreamSize (size));
  i += rsvcStreamSize (real_size);

  // write cbk data
  long cbksize = cbk_.streamSize ();
  if (cbk_.streamOut (&(buffer[i]), buflen - i) != RSVC_SUCCESS)
    return RSVC_ERROR;
  i += (int)cbksize;

  // write data itself
  size_t databuflen, datacount;
  data_.streamSize (&databuflen, &datacount);

  if (data_.streamOut (&(buffer[i]), buflen - i, datacount) != RSVC_SUCCESS)
    return RSVC_ERROR;

  i += databuflen;

  if (i != size) {
    fprintf (stderr, "Fatal: Overflow rsvcNetData the stream out buffer\n");
    return RSVC_ERROR;
  }
  return RSVC_SUCCESS;
}

int
rsvcNetData::streamOut (char* buffer, size_t len)
{
  size_t datasize = streamSize ();

  if (datasize > len) {
    fprintf (stderr, "Fatal: rsvcNetData streamout buffer overflow %d > %d\n",
	     datasize, len);
    return RSVC_ERROR;
  }
  return streamOut (buffer, len, datasize);
}

int
rsvcNetData::streamIn (char* buffer, size_t len)
{
  int st = RSVC_SUCCESS;
  int i = 0;

  if ((st = cbk_.streamIn (&(buffer[i]), len)) != RSVC_SUCCESS)
    return st;

  i += cbk_.streamSize ();

  if ((st = data_.streamIn (&(buffer[i]), len - i)) != RSVC_SUCCESS)
    return st;

  return st;
}

int
rsvcNetData::readHeader (char* buffer, size_t len, size_t* datasize)
{
  long   magicnum;
  size_t size = 0;

  if (len < rsvcStreamSize (_RSVC_MAGIC_NUM) + rsvcStreamSize (size)) {
    fprintf (stderr, "Fatal: reading rsvcNetData Header error: overflow\n");
    return RSVC_ERROR;
  }

  int i = 0;
  long tmp;

  // get magic number
  memcpy (&tmp, &(buffer[i]), rsvcStreamSize (_RSVC_MAGIC_NUM));
  magicnum = ntohl (tmp);
  if (magicnum != _RSVC_MAGIC_NUM) {
    fprintf (stderr, "Fatal: reading rsvcNetData header error: magic number mismatch\n");
    return RSVC_ERROR;
  }
  i += rsvcStreamSize (_RSVC_MAGIC_NUM);

  // get data size
  memcpy (&tmp, &(buffer[i]), rsvcStreamSize (size));
  size = (unsigned int)ntohl (tmp);
  i += rsvcStreamSize (size);

  *datasize = size;

  return RSVC_SUCCESS;
}

size_t
rsvcNetData::headerLen (void)
{
  return rsvcStreamSize (_RSVC_MAGIC_NUM) + rsvcStreamSize ((size_t)1);
}


  
 
