#include "cdevSocket.h"

void cdevSocket::setHandle ( int fd )
	{
	handle = fd;
	}


int cdevSocket::getHandle ( void ) const
	{
	return handle;
	}


int cdevSocket::open (int type, int protocol_family, int protocol)
	{
	setHandle(::socket(protocol_family, type, protocol));
	return getHandle();
	}
	

int cdevSocket::close (void)
	{
	int result = ::close(getHandle());
	setHandle(INVALID_HANDLE);
	return result;
	}


int cdevSocket::unsetFlags ( int flags )
	{
	int retval = -1;
	int fd = getHandle();
	
	if(fd!=cdevSocket::INVALID_HANDLE)
		{
		#ifdef WIN32
			if(flags==O_NONBLOCK)
				{
				unsigned long val = 0;
				retval = ::ioctlsocket(fd, FIONBIO, &val);
				}
		#else
			int val;
			if((val=::fcntl(fd, F_GETFL, 0)) != -1)
				{
				val &= ~flags;
				retval  = (::fcntl(fd, F_SETFL, val)!=-1)?0:1;
				}
		#endif
		}

	return retval;
	}


int cdevSocket::setFlags ( int flags )
	{
	int retval = -1;
	int fd = getHandle();
	
	if(fd!=cdevSocket::INVALID_HANDLE)
		{
		#ifdef WIN32
			if(flags==O_NONBLOCK)
				{
				unsigned long val = 1;
				retval = ::ioctlsocket(fd, FIONBIO, &val);
				}
		#else
			int val;
			if ((val=::fcntl(fd, F_GETFL, 0)) != -1) 
				{
				val |= flags;
				if(::fcntl(fd, F_SETFL, val) != -1) retval = 0;
				}
		#endif
		}

	return retval;
	}

	
int cdevSocket::getFlags ( void )
	{
	int retval = -1;
	int fd = getHandle();
	
	#ifdef WIN32
		retval = 0;
	#else
		if(fd!=cdevSocket::INVALID_HANDLE)
			{
			retval=::fcntl(fd, F_GETFL, 0);
			}
	#endif

	return retval;
	}

int cdevSocket::setOption (int level, int option, void *optval, int optlen) const
	{
	return ::setsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM)optlen);
	}


int cdevSocket::getOption (int level, int option, void *optval, int *optlen) const
	{
	return ::getsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM *)optlen);
	}


int cdevSocket::getLocalAddress  (cdevAddr & addr)
	{
	int retval;
	int len=addr.getSize();

	if(::getsockname(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE)
		{
		retval = INVALID_HANDLE;
		}
	else	{
		addr.setSize(len);
		retval = 0;
		}
	return retval;
	}


int cdevSocket::getRemoteAddress (cdevAddr & addr)
	{
	int retval;
	int len = addr.getSize();
	if(::getpeername(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE)
		{
		retval = INVALID_HANDLE;
		}
	else	{
		addr.setSize(len);
		retval = 0;
		}
	return retval;
	}


cdevSocket::cdevSocket ( void )
	: handle(INVALID_HANDLE)
	{
	}
	

cdevSocket::cdevSocket(int type, int protocol_family, int protocol)
	: handle(INVALID_HANDLE)
	{
	setHandle(open(type, protocol_family, protocol));
	}

