#include "cdevSocketConnector.h"
#include "cdevHandleSet.h"

// *****************************************************************************
// * cdevSocketConnector::connect :
// *	Actively connect and produce a new cdevSocketStream if things go well...
// *****************************************************************************
int cdevSocketConnector::connect ( const cdevAddr & remote_addr ) 
	{
	int retval    = 0;

	if(getHandle() == cdevSocket::INVALID_HANDLE &&
	   cdevSocket::open(SOCK_STREAM, PF_INET, 0) == cdevSocket::INVALID_HANDLE)
		{
		retval = -1;
		}
	else
		{
		double    secondsWaited = 0.0;
		sockaddr *addr=(sockaddr *) remote_addr.getAddress();
		size_t    size=remote_addr.getSize();
		
		if(configureHandle()<0)
			{
			retval = -1;
			}
		else if(::connect(getHandle(), addr, size) == cdevSocket::INVALID_HANDLE)
			{
			int errCode = GetSocketErrno();

			if(getBlockingSemantics()==O_NONBLOCK && errCode==EINPROGRESS)
				{
				errCode=EWOULDBLOCK;
				}
		
			if(errCode == EISCONN)
				{
				retval = 0;
				}
			else if(errCode != EWOULDBLOCK)
				{
				close();
				setHandle(cdevSocket::INVALID_HANDLE);
				retval = -1;
				}
			else	{
				cdevHandleSet  ws;
				cdevHandleSet  es;
				struct timeval tv;
				int            fd = getHandle();
				
				ws.set_bit(fd);
				es.set_bit(fd);
				tv.tv_sec  = 3;
				tv.tv_usec = 0;
				
				if(cdevSelect(fd+1, NULL, ws, es, &tv)>0 && ws.is_set(fd)) retval = 0;
				else retval = -1;
				} 
			}
		}

	return retval;
	}

