#include "cdevSocketAcceptor.h"

// *****************************************************************************
// * cdevSocketAcceptor::cdevSocketAcceptor :
// *	Do nothing routine for constructor.
// *****************************************************************************
cdevSocketAcceptor::cdevSocketAcceptor(void)
	{
	}

// *****************************************************************************
// * cdevSocketAcceptor::open :
// *	General purpose routine for performing server cdevSocket creation. 
// *****************************************************************************
int cdevSocketAcceptor::open
	(
	const cdevAddr &addr, 
	int         reuse_addr, 
	int         protocol_family, 
	int         backlog, 
	int         protocol,
	int         reopen)
	{
	int one = 1;	
	int retval;

	if(reopen) cdevSocket::open(SOCK_STREAM, protocol_family, protocol);
	
	if(this->getHandle() == cdevSocket::INVALID_HANDLE)
		{
		retval = cdevSocket::INVALID_HANDLE;
		close();
		}
	else	{
		if(reuse_addr && setOption(SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == cdevSocket::INVALID_HANDLE)
			{
			close();
			}
		else if(::bind(getHandle(), (sockaddr *)addr.getAddress(), 
			addr.getSize()) == cdevSocket::INVALID_HANDLE || 
			::listen(getHandle(), backlog) == cdevSocket::INVALID_HANDLE)
			{
			close();
			}
		retval = getHandle();
		}
	return retval;
	}

// *****************************************************************************
// * cdevSocketAcceptor::cdevSocketAcceptor :
// *	General purpose routine for performing server cdevSocket creation. 
// *****************************************************************************
cdevSocketAcceptor::cdevSocketAcceptor (
	const cdevAddr &addr, 
	int             reuse_addr, 
	int             protocol_family, 
	int             backlog, 
	int             protocol)
	: cdevSocket(SOCK_STREAM, protocol_family, protocol)
	{
	open(addr, reuse_addr, protocol_family, backlog, protocol, 0);
	}

// *****************************************************************************
// * cdevSocketAcceptor::accept :
// *	General purpose routine for accepting new connections.
// *****************************************************************************
int cdevSocketAcceptor::accept(cdevSocketStream &new_stream, cdevAddr *addr) const
	{
	sockaddr *sock_addr=0;
	int      *len_ptr=0;
	int       len;
	int       new_handle;
	
	if(addr != 0)
		{
		len=addr->getSize();
		len_ptr= &len;
		sock_addr=(sockaddr *) addr->getAddress();
		}

	do	{
		new_handle=::accept(this->getHandle(), sock_addr, (SOCKOPT_SIZE_PARM *)len_ptr);
		} while(new_handle==cdevSocket::INVALID_HANDLE && errno==EINTR); 

	if(addr != 0) addr->setSize(*len_ptr);
	
	new_stream.setHandle(new_handle);
	new_stream.configureHandle();

	return new_handle;
	}
