//-----------------------------------------------------------------------------
// 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 rsvcAcceptor Class
//
// Author:  Jie Chen
//
// Revision History:
//   rsvcAcceptor.cc,v
// Revision 1.3  1998/02/26  19:08:20  chen
// add list lock to prevent rsvcIO from deleting itself twice
//
// Revision 1.2  1998/02/25  19:52:41  chen
// minor change
//
// Revision 1.1  1998/01/22  17:07:57  akers
// Addition of new NameServer
//
//
//
#include <errno.h>
#include "rsvcAcceptor.h"
#include "rsvcIO.h"

rsvcAcceptor::rsvcAcceptor (cdevReactor & r, rsvcDataStoreTable& st)
:cdevEventHandler (), listener_ (), reactor_ (r),
 connectionList_ (), storeTable_ (st), listLock_ (0)
{
#ifdef _TRACE_OBJECTS
  printf ("    Create rsvcAcceptor Class Object\n");
#endif
}

rsvcAcceptor::~rsvcAcceptor (void)
{
#ifdef _TRACE_OBJECTS
  printf ("    Delete rsvcAcceptor Class Object\n");
#endif
  listLock_ = 1;
  // delete all clients
  deleteAllConnections ();

  listLock_ = 0;

  // close sockets
  handleClose ();
}

int
rsvcAcceptor::handleClose ( void )
{
  return listener_.close ();
}

int
rsvcAcceptor::getHandle (void) const
{
  return listener_.getHandle ();
}


int
rsvcAcceptor::handleInput ( void )
{
  cdevInetAddr rem_addr;

  rsvcIO* client = new rsvcIO (reactor_, this, storeTable_);

  if (listener_.accept (*client, &rem_addr) != -1) {
    printf ("Receivied client connection from host %s at port %d\n",
	    rem_addr.getHostName (), client->getHandle ());

    // remember client address
    client->peerAddr (rem_addr);

    // set socket options to KEEP_ALIVE
    int alive = 1;
    client->setSockOption (SOL_SOCKET, SO_KEEPALIVE,
			   (void *)&alive, sizeof (alive));


/*    int sendsize = 4096;
    client->setSockOption (SOL_SOCKET, SO_SNDBUF, (void *)&sendsize,
			   sizeof (sendsize));
*/			   

    // register client to reactor
    int event_mask = cdevEventHandler::READ_MASK;

    if (reactor_.registerHandler (client, event_mask) == -1) {
      printf ("Unable to register rsvcIO handler\n");
      return -1;
    }
    connectionList_.add ((void *)client);

    // enable non block io
    client->enable (O_NONBLOCK);
  }
  else {
    printf ("rsvcAcceptor accepting client connection failed\n");
    return -1;
  }
  return 0;
}
  


int
rsvcAcceptor::open (unsigned short port)
{
  printf ("RSVC: Create TCP listening port at %d\n", port);
  cdevInetAddr addr (port);

  // reuse address option
  if (listener_.open (addr, 1) == -1) 
    return -1;
  else if (listener_.setFlags (O_NONBLOCK) == -1)
    return -1;
  else
    return 0;
}

unsigned short
rsvcAcceptor::port_number (void)
{
  cdevInetAddr addr;

  listener_.getLocalAddress (addr);

  // port number is in the host byte order
  return addr.getPortNum ();
}

int
rsvcAcceptor::numberConnections (void)
{
  return connectionList_.count ();
}

int
rsvcAcceptor::remove (rsvcIO* client)
{
  return connectionList_.remove ((void *)client);
}

int
rsvcAcceptor::includes (rsvcIO* client)
{
  return connectionList_.includes ((void *)client);
}

int
rsvcAcceptor::sendToAllConnections (rsvcNetData* data)
{
  rsvcSlistIterator ite (connectionList_);
  rsvcIO* io = 0;
  int     status = RSVC_SUCCESS;

  for (ite.init (); !ite; ++ite) {
    io = (rsvcIO *) ite ();
    if (io->sendToPeer (data) != RSVC_SUCCESS)
      status = RSVC_ERROR;
  }
  return status;
}

void
rsvcAcceptor::deleteAllConnections (void)
{
  rsvcSlistIterator ite (connectionList_);
  rsvcIO* io = 0;
  int     status = RSVC_SUCCESS;

  for (ite.init (); !ite; ++ite) {
    io = (rsvcIO *) ite ();
    delete io;
  }
}

rsvcSlist&
rsvcAcceptor::connectionList (void)
{
  return connectionList_;
}


  
    
