//-----------------------------------------------------------------------------
// 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:
//      RSVC UDP Client
//
// Author:  Jie Chen
//
// Revision History:
//   rsvcUdpClient.cc,v
// Revision 1.2  1998/02/20  19:37:28  chen
// reset errno after using it (hpux) sometimes not resetting it
//
// Revision 1.1  1998/01/22  17:08:25  akers
// Addition of new NameServer
//
//
//
#include "rsvcUdpClient.h"
#include <errno.h>

rsvcUdpClient::rsvcUdpClient (void)
:fd_ (-1)
{
#ifdef _TRACE_OBJECTS
  printf ("Create rsvcUdpClient Class Object\n");
#endif
}


rsvcUdpClient::~rsvcUdpClient (void)
{
#ifdef _TRACE_OBJECTS
  printf ("Delete rsvcUdpClient Class Object\n");
#endif
  if (fd_ != -1)
    close (fd_);
}

int
rsvcUdpClient::connect (char* host, unsigned short port)
{
  if ((openUdpPort (host, port)) == -1)
    return RSVC_ERROR;

  return RSVC_SUCCESS;
}

int
rsvcUdpClient::disconnect (void)
{
  if (fd_ != -1)
    close (fd_);
  return RSVC_SUCCESS;
}

int
rsvcUdpClient::update (rsvcData& data)
{
  if (fd_ == -1)
    return RSVC_ERROR;
      
  int nbytes;
  int nw;
  int status = RSVC_SUCCESS;

  rsvcCbk      cbkid (RSVC_SET, (long)0,
		      (long)5678, (long)fd_);
  // create netdata
  rsvcNetData   netdata (data, cbkid);
    
  if ((nbytes = streamData (netdata)) <= 0)
    status = RSVC_ERROR;
  else {
    // block write
    if ((nw = ::sendto (fd_, obuffer_, nbytes, 0, (sockaddr *)&udp_addr_, 
			sizeof (udp_addr_))) != nbytes) {
#ifdef _RSVC_DEBUG
      printf ("rsvcUdpClient: wrote %d nbytes and expect to write %d bytes\n",
	      nw, nbytes);
      printf ("rsvcUdpClient: errno is %d\n", errno);
      perror ("client sendto error ");
      // reset errno
      errno = 0;
#endif
      status = RSVC_ERROR;
    }
  }
  return status;
}

int
rsvcUdpClient::streamData (rsvcNetData& data)
{
  size_t datasize = data.streamSize ();

  if (datasize > sizeof (obuffer_)) {
#ifdef _RSVC_DEBUG
    printf ("rsvcUdpClient: Streamed data size %d is exceeding %d, resize\n",
	    datasize, sizeof(obuffer_));
#endif
    return -1;
  }

  if (data.streamOut (obuffer_, datasize) != RSVC_SUCCESS) {
#ifdef _RSVC_DEBUG
    printf ("rsvcUdpClient: rsvcNetData stream out error\n");
#endif
    return -1;
  }
  return datasize;
}

int
rsvcUdpClient::openUdpPort (char* host, unsigned short port)
{
  struct sockaddr_in my_addr;
  struct hostent*    hp = 0;

  // initialize the server inet address structure
  ::memset (&udp_addr_, 0, sizeof (udp_addr_));
  udp_addr_.sin_family = AF_INET;
  udp_addr_.sin_port = htons (port);

  hp = gethostbyname (host);

  if (hp == 0) {
    fprintf (stderr, "rsvcUdpClient: Cannot find ip address of host %s\n",
	     host);
    return -1;
  }
  ::memcpy (&udp_addr_.sin_addr, hp->h_addr, hp->h_length);

  // open a socket
  if ((fd_ = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
    fprintf (stderr, "udp_open: cannot create socket\n");
    fd_ = -1;
    return -1;
  }
  // bind local address for us
  ::memset (&my_addr, 0, sizeof (my_addr));
  my_addr.sin_family = AF_INET;
  my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  my_addr.sin_port = htons (0);

  if (bind (fd_, (struct sockaddr *)&my_addr, sizeof (my_addr)) < 0) {
    fprintf (stderr, "rsvcUdpClient : bind error\n");
    close (fd_);
    fd_ = -1;
    return -1;
  }
  return 0;
}
  






  
