//============================================================================
/// Summary  : Simple Socket
/// Filename : simpleSocket.cc
/// Author   : reed@bluefinrobotics.com
/// Project  : Simple Socket Library
/// Revision : 0.0
/// Created  : 2002.02.26
/// Modified : 2002.02.26
//============================================================================
#pragma comment(lib, “ws2_32.lib”)

#include "stdafx.h"
#include "SimpleSocket.h"

//#define DEBUG_SS 0

SimpleSocket::SimpleSocket(int datagramBufferSize)
{
#ifdef DEBUG_SS
    dwrite(3)("SS: Executing constructor...");
#endif

    networkAddress.connected = false;
    networkAddress.optionsSet = false;
    networkAddress.addressSet = false;
    networkAddress.exists = false;
    networkAddress.type = SS_STREAM;
    networkAddress.domain = SS_UNSPEC;
    networkAddress.protocol = SS_UNSPEC;

    networkAddress.descriptor = -1;
    networkAddress.addressLength = sizeof(networkAddress.address);

#ifdef DEBUG_SS
    dwrite(3)("SS: descriptor   = %d", networkAddress.descriptor);
    dwrite(3)("SS: addressLen   = %d", networkAddress.addressLength);
#endif

    // Apparently the SIGPIPE signal might be killing QNX during sends!!!
  //  signal(SIGPIPE, SIG_IGN);
}

SimpleSocket::~SimpleSocket()
{
#ifdef DEBUG_SS
    dwrite(3)("SS: Executing destructor...");
#endif
    SimpleSocket::destroy();
}


/// Create a TCP/UDP socket.
SOCKET SimpleSocket::create(Type type, Domain domain, int protocol)
{
#ifdef DEBUG_SS
    dwrite(3)("SS::create: create socket...");
    dwrite(3)("SS::create: Type = %d, Domain = %d, Protocol = %d", 
	      type, domain, protocol);
#endif

    networkAddress.type = type;
    networkAddress.domain = domain;
    networkAddress.protocol = protocol;

    // Create socket.
    errno = 0;
    networkAddress.descriptor = socket(domain, type, protocol);
    if ( networkAddress.descriptor < 0 ) 
    {
	networkAddress.exists = false;
//	dwrite(2)("SS: Error, create socket failed (errno=%d).",errno);
    }
    else
    {
	networkAddress.exists = true;
    }

    return(networkAddress.descriptor);
}


/// Create UDP Socket for Datagrams.
SOCKET SimpleSocket::createInternetDatagram()
{
#ifdef DEBUG_SS
    dwrite(3)("SS:createInetDgram: create socket Internet Datagram...");
#endif
    return(SimpleSocket::create(SS_DATAGRAM, SS_INTERNET, IPPROTO_UDP));
}


/// Create TCP Socket for Stream.
SOCKET SimpleSocket::createInternetStream()
{
#ifdef DEBUG_SS
    dwrite(3)("SS:createInternetStream: create socket Internet Stream...");
#endif
    return(SimpleSocket::create(SS_STREAM));
}


/// Close (Destroy) Socket using Socket Descriptor.
int SimpleSocket::destroy()
{
    int returnVal = 0;
#ifdef DEBUG_SS
    dwrite(3)("SS:destroy: destroy (close) socket %d...", networkAddress.descriptor);
#endif
    networkAddress.connected = false;
    networkAddress.optionsSet = false;
    networkAddress.addressSet = false;
    networkAddress.exists = false;
    networkAddress.type = SS_STREAM;
    networkAddress.domain = SS_UNSPEC;
    networkAddress.protocol = SS_UNSPEC;

    // Close (destroy) socket.
    if(networkAddress.descriptor > 0)
    {
	returnVal = closesocket(networkAddress.descriptor);
	networkAddress.descriptor = -1;
	return(returnVal);
    }
    else
    {
	// Error, a socket doesn't exist.
//	dwrite(3)("SS: Attempt to close non-existing socket, no action taken!");
	return (-1);
    }
}


/// Set Socket Options
int SimpleSocket::setOptions(int level,
			     int options,
			     const void *optionValue,
			     int optionValueLength)
{
#ifdef DEBUG_SS
    dwrite(3)("SS:setOptions: level       = 0x%X...",level);
    dwrite(3)("SS:setOptions: options     = 0x%X...",options);
    dwrite(3)("SS:setOptions: optionValue = 0x%X...",optionValue);
    dwrite(3)("SS:setOptions: optionLen   = %d...",optionValueLength);
#endif
    int returnVal=0;


    if(networkAddress.exists)
    {
	errno = 0;
	returnVal = setsockopt(networkAddress.descriptor,
			       level,
			       options,
			       (const char *)optionValue,
			       optionValueLength);
	if(returnVal < 0)
	{
//	    dwrite(2)("SS: Error setting socket option 0x%X (errno=%d)!", options, errno);
		int errorCode  = WSAGetLastError();
	    SimpleSocket::destroy();
	    networkAddress.optionsSet = false;
	}
	else
	{
	    networkAddress.optionsSet = true;
	}
	return(returnVal);
    }
    else
    {
//	dwrite(3)("Unable to set socket options on a non-existing socket...");
	networkAddress.optionsSet = false;
	return(-1);
    }
}


/// Set Socket Broadcast
int SimpleSocket::setOptionsDatagramBroadcast()
{
    int optionValue = 1;
#ifdef DEBUG_SS
    dwrite(3)("SS:setOptionsDatagramBroadcast: ...");
#endif

    // set socket options to broadcast
    return(setOptions(SS_SOCKET, 
		      SS_BROADCAST,
		      &optionValue,
		      sizeof(optionValue)));
}


// /// Set Socket Timeout
 int SimpleSocket::setOptionsTimeout(MessageDirection messageDirection, int seconds, int useconds)
 {
 #ifdef DEBUG_SS
     dwrite(3)("SS:setOptionsTimeout(%ds %dus)...", seconds, useconds);
 #endif
     int returnVal = 0;
     struct timeval timeout;
     int optionVal = 0;

     timeout.tv_sec = seconds;
     timeout.tv_usec = useconds;

     switch(messageDirection)
     {
     case SS_SEND:
 #ifdef DEBUG_SS
 	dwrite(3)("SS:setOptionsTimeout() Message Direction Send...");
 	dwrite(3)("SS:setOptionsTimeout: descriptor  = 0x%X...",
 		      networkAddress.descriptor);
 	dwrite(3)("SS:setOptionsTimeout: level       = 0x%X...",
 		      SS_SOCKET);
 	dwrite(3)("SS:setOptionsTimeout: options     = 0x%X...",
 		      SS_SENDTIMEOUT);
 #endif
 	// set socket options send timeout
 	return(setOptions(SS_SOCKET,
 			  SS_SENDTIMEOUT,
 			  &timeout,
 			  sizeof(timeout)));
 	break;
     case SS_RECEIVE:
 #ifdef DEBUG_SS
 	dwrite(3)("SS:setOptionsTimeout() Message Direction Receive...");
 	dwrite(3)("SS:setOptionsTimeout: descriptor  = 0x%X...",
 		      networkAddress.descriptor);
 	dwrite(3)("SS:setOptionsTimeout: level       = 0x%X...",
 		      SS_SOCKET);
 	dwrite(3)("SS:setOptionsTimeout: options     = 0x%X...",
 		      SS_RECEIVETIMEOUT);
 #endif
 	// set socket options receive timeout
 	return(setOptions(SS_SOCKET,
 			  SS_RECEIVETIMEOUT,
 			  &timeout,
 			  sizeof(timeout)));
 	break;
     default:
 	return(-1);
 	break;
     }
 }


/// Set Socket Address
int SimpleSocket::setAddress( unsigned short port,
			      unsigned long address,
			      unsigned short family)
{
#ifdef DEBUG_SS
    dwrite(3)("SS:setAddress: port      = %04d...", port);
    dwrite(3)("SS:setAddress: ipAddress = 0x%08x...", address);
    dwrite(3)("SS:setAddress: family    = %02d...", family);
#endif
    networkAddress.address.sin_family = family;
    networkAddress.address.sin_addr.s_addr = htonl(address);
    networkAddress.address.sin_port = htons(port);
#ifdef DEBUG_SS
    dwrite(3)("SS:setAddress: address family = 0x%X...",
	      networkAddress.address.sin_family);
    dwrite(3)("SS:setAddress: address s_addr = 0x%08X...",
	      networkAddress.address.sin_addr.s_addr);
    dwrite(3)("SS:setAddress: address port   = 0x%04X...",
	      networkAddress.address.sin_port);
#endif

    // Network address has been set.
    networkAddress.addressSet = true;

    return(0);
}


/// Set Socket Address
int SimpleSocket::setAddress( unsigned short port,
			      const char *ipAddressString,
			      unsigned short family)
{
    int returnVal = 0;    if(returnVal < 0)
    {
//	dwrite(3)("Unable to create Internet Datagram Socket!");
	return (returnVal);
    }
    else
    {
	// Received socket descriptor on createInetDgram success.
	networkAddress.descriptor = returnVal;
    }

    unsigned long hexIpAddress = 0;

    hexIpAddress = SimpleSocket::string2hexIpAddress(ipAddressString);

#ifdef DEBUG_SS
    dwrite(3)("SS:setAddress: port            = %4d.", port);
    dwrite(3)("SS:setAddress: ipAddressString = %s." , ipAddressString);
    dwrite(3)("SS:setAddress: ipAddressLong   = 0x%08X.", hexIpAddress);
    dwrite(3)("SS:setAddress: family          = %2d.", family);
#endif
    returnVal = SimpleSocket::setAddress(port, hexIpAddress, family);

    return(returnVal);
}


/// Attach (connect) to an IP address and port
int SimpleSocket::attach(const unsigned short attachFlag)
{
    int returnVal = 0;
#ifdef DEBUG_SS
    dwrite(3)("SS::attach: attaching to IP address and port...\n");
#endif

    if(!networkAddress.exists)
    {
//	dwrite(3)("Unable to attach (connect) to non-existing socket!\n");
	returnVal = -1;
    }
    if(!networkAddress.addressSet)
    {
//	dwrite(3)("Unable to attach (connect), no socket address!\n");
	returnVal = -2;
    }
    if(returnVal < 0)
	return(returnVal);

    // Attach to host
    errno = 0;
    switch(attachFlag)
    {
    case AS_CLIENT:
	returnVal = connect(networkAddress.descriptor, 
			    (struct sockaddr *)&networkAddress.address, 
			    sizeof(networkAddress.address));
	break;
    case AS_HOST:
	returnVal = bind(networkAddress.descriptor, 
			 (struct sockaddr *)&networkAddress.address, 
			 sizeof(networkAddress.address));
	break;
 //   default:
//	dwrite(2)("SS: Error, invalid attach method %d!\n",attachFlag);
	}
    if( returnVal < 0)
    {
	int errorNumber = WSAGetLastError();
	printf("SS: Error, attach to IP address and port failed (errno=%d).\n",errno);
	returnVal = destroy();
	returnVal = -3;
    }
    else
    {
	networkAddress.connected = true;
    }

    return(returnVal);
}

/// bindTo (bind) a name to a socket
int SimpleSocket::bindTo( SOCKET descriptor,
			  struct sockaddr_in *socketAddress,
			  int sizeSocketAddress)
{
    int returnVal = 0;
    errno = 0;
    if(socketAddress == NULL)
	socketAddress = &networkAddress.address;

    returnVal = bind(descriptor,
		     (struct sockaddr *)socketAddress,
		     sizeof(struct sockaddr_in));
    if(returnVal != 0)
    {
	printf("SS: Error, bind to socket failed (errno=%d).\n",errno);
	returnVal = destroy();
	returnVal = -1;
    }
    else
    {
	networkAddress.connected = true;
    }
    return(returnVal);
} 

/// Create Broadcast Datagram Socket
/// returns on success : socket descriptor
/// returns on failure : -1
SOCKET SimpleSocket::createBroadcastDatagramSend( unsigned short port, 
					       unsigned long address, 
					       unsigned short family)
{
#ifdef DEBUG_SS
    dwrite(3)("SS:createBroadcastDatagramSend: port = %4d...,\n", port);
    dwrite(3)("SS:createBroadcastDatagramSend: ipAddress = 0x%08x...\n", address);
#endif
    SOCKET returnVal;
     
    returnVal = SimpleSocket::createInternetDatagram();
    if(returnVal < 0)
    {
//	dwrite(3)("Unable to create Internet Datagram Socket!\n");
	return (returnVal);
    }
    else
    {
	// Received socket descriptor on createInetDgram success.
	networkAddress.descriptor = returnVal;
    }

    // setup the socket for broadcasting
    returnVal = SimpleSocket::setOptionsDatagramBroadcast();
    if(returnVal < 0)
    {
	// close the socket on failure to setup socket
	returnVal = SimpleSocket::destroy();
	return(-1);
    }

    /// Note that socket connection exists.
    if (networkAddress.descriptor > 0)
    { 
#ifdef DEBUG_SS
	dwrite(3)("SS:createBroadcastDatagramSend: port      = %4d.\n", port);
	dwrite(3)("SS:createBroadcastDatagramSend: address = 0x%0x.\n", address);
	dwrite(3)("SS:createBroadcastDatagramSend: family    = %2d.\n", family);
#endif
	/// set socket address
	returnVal = SimpleSocket::setAddress( port,
					      address,
					      family);
    }

    return(returnVal);
}


// Create a DataGram Broadcast port using IP address string.
SOCKET SimpleSocket::createBroadcastDatagramSend( unsigned short port,
					       const char *ipAddressString,
					       unsigned short family)
{
 //   int returnVal = 0;
    unsigned long hexIpAddress = 0;

    hexIpAddress = SimpleSocket::string2hexIpAddress(ipAddressString);
#ifdef DEBUG_SS
    dwrite(3)("SS:createBroadcastDatagramSend: port            = %04d.\n", port);
    dwrite(3)("SS:createBroadcastDatagramSend: ipAddressString = %s.\n", ipAddressString);
    dwrite(3)("SS:createBroadcastDatagramSend: hexIpAddress    = 0x%08x.\n", hexIpAddress);
#endif
    return SimpleSocket::createBroadcastDatagramSend(port, hexIpAddress, family);

    //return(returnVal);
}


/// send to socket explicit
int SimpleSocket::broadcast(const void *message,
			    unsigned int messageLength,
			    IoControl ioControl,
			    int flags)
{
    int bytesSent = 0;
    int returnVal = 0;
    unsigned int enable;

#ifdef DEBUG_SS
    //dwrite(3)("SS:broadcast: message = %s.",message);
    dwrite(3)("SS:broadcast: messageLength = %d.\n", messageLength);
    dwrite(3)("SS:broadcast: flags = %d.", flags);
    dwrite(3)("SS:broadcast: networkAddress.descriptor              = %d.\n",
		  networkAddress.descriptor);
    dwrite(3)("SS:broadcast: networkAddress.address.sin_family      = %d (0x%X).\n",
		  networkAddress.address.sin_family,
		  networkAddress.address.sin_family);
    dwrite(3)("SS:broadcast: networkAddress.address.sin_addr.s_addr = %d (0x%X).\n",
		  networkAddress.address.sin_addr.s_addr,
		  networkAddress.address.sin_addr.s_addr);
    dwrite(3)("SS:broadcast: networkAddress.address.sin_port        = %d (0x%X).\n",
		  networkAddress.address.sin_port,
		  networkAddress.address.sin_port);
    dwrite(3)("SS:broadcast: networkAddress.addressLength           = %d.\n",
		  networkAddress.addressLength);
#endif

    if( !ready())
    {
//	dwrite(3)("SS:broadcast: socket not ready, unable to broadcast!\n");
	return(-1);
    }

    // Set blocking type.
    enable = ioControl;
    errno = 0;
//    returnVal = ioctl( networkAddress.descriptor, FIONBIO, &enable);
	returnVal = 1;
    if(returnVal < 0)
    {
//	dwrite(2)("SS:broadcast:  IO control failed (non-block)(errno=%d).\n", errno);
	return(-1);
    }
    // Broadcast data.
    errno = 0;
    bytesSent = sendto( networkAddress.descriptor,
			(const char *)message,
			messageLength,
			flags,
			(const struct sockaddr *)&networkAddress.address,
			networkAddress.addressLength);
    if(bytesSent < 0)
    {
//	dwrite(2)("SS: Error, broadcast send failed (errno=%d).\n", errno);
	perror("SS:");
    }
    return(bytesSent);
}


/// send to socket simple
int SimpleSocket::broadcastDatagram(const void *message,
				    unsigned int messageLength,
				    IoControl ioControl)
{
#ifdef DEBUG_SS
    dwrite(3)("SS:broadcastDatagram: messageLength = %d.\n",messageLength);
#endif

    int bytesSent=0;

    return(broadcast( message,
		      messageLength,
		      ioControl,
		      0)); // flags
};


/// Convert string IP address to a hex address, i.e. "255.255.255.255" --> 0xFFFFFFFF.
unsigned long SimpleSocket::string2hexIpAddress(const char *ipAddressString)
{
    int returnVal = 0;
    unsigned int network1 = 0, network2 = 0, subnet = 0, host = 0;
    unsigned long hexIpAddress = 0;

    // Get a copy of the ip address string.
    strncpy(&networkAddress.ipAddressString[0], ipAddressString, MaxIpAddressStringSize);
    // Scan in the IP Address Components.
    returnVal=sscanf(ipAddressString,"%d.%d.%d.%d", &network1, &network2, &subnet, &host);
    // Generate the hex IP Address.
    hexIpAddress=network1;
    hexIpAddress<<=8;
    hexIpAddress+=network2;
    hexIpAddress<<=8;
    hexIpAddress+=subnet;
    hexIpAddress<<=8;
    hexIpAddress+=host;

#ifdef DEBUG_SS
    dwrite(3)("SS:string2hexIpAddress(%s) = 0x%8X.\n", ipAddressString, hexIpAddress);
#endif

    return(hexIpAddress);
}


/// send to connected socket explicit
int SimpleSocket::sending(const void *message,
			  unsigned int messageLength,
			  int descriptor,
			  IoControl ioControl,
			  int flags)
{
    int bytesSent = 0;
    int returnVal = 0;
    SOCKET sendDescriptor;
    //unsigned int enable;

    // Make sure connection is ready before attempting to send.
    if(!ready())
    {
//	dwrite(3)("SS: Socket not ready, unable to send data...\n");
	return(-1);
    }

#ifdef DEBUG_SS
    //dwrite(3)("SS:sending: message = %s.",message);
    dwrite(3)("SS:sending: messageLength = %d.\n", messageLength);
    dwrite(3)("SS:sending: flags = %d.\n", flags);
    dwrite(3)("SS:sending: networkAddress.descriptor              = %d.\n", 
	   networkAddress.descriptor);
    dwrite(3)("SS:sending: networkAddress.address.sin_family      = %d (0x%X).\n",
	   networkAddress.address.sin_family, 
	   networkAddress.address.sin_family);
    dwrite(3)("SS:sending: networkAddress.address.sin_addr.s_addr = %d (0x%X).\n",
	   networkAddress.address.sin_addr.s_addr, 
	   networkAddress.address.sin_addr.s_addr);
    dwrite(3)("SS:sending: networkAddress.address.sin_port        = %d (0x%X).\n",
	   networkAddress.address.sin_port, 
	   networkAddress.address.sin_port);
    dwrite(3)("SS:sending: networkAddress.addressLength           = %d.\n", 
	   networkAddress.addressLength);
#endif

    // Enable blocking type.
    //enable = ioControl;
    if(descriptor < 0)
    {
	sendDescriptor = networkAddress.descriptor;
    }
    else
    {
	sendDescriptor = descriptor;
    }

    errno = 0;
    //returnVal = ioctl( sendDescriptor, FIONBIO, &ioControl);
	returnVal = 1;
    if(returnVal < 0)
    {
//	dwrite(2)("SS: sending, IO control failed (non-block/block)(errno=%d).\n", errno);
	return(-1);
    }

    // send message
    errno = 0;
    bytesSent = send( sendDescriptor,
		      (const char *)message,
		      messageLength,
		      flags);
    if(bytesSent < 0)
    {
//	dwrite(2)("SS: sending, failed (errno=%d).\n", errno);
	// Free up connection so another connection can be made.
	returnVal = destroy();
	return(-1);
    }
    return(bytesSent);
}


/// receive from a connected socket
/// returns number of bytes read or -1 on error.
int SimpleSocket::receiving(const void *buffer,
			    unsigned int sizeOfBuffer,
			    int descriptor,
			    IoControl ioControl,
			    int flags)
{
    int bytesReceived = 0;
    int returnVal = 0;
    unsigned int bytesToReceive = 0;
    SOCKET recvDescriptor;

    // Make sure connection is ready before attempting to send.
    if(!ready())
    {
//	dwrite(3)("SS: Socket not ready, data not being received...\n");
	return(-1);
    }

    if(descriptor < 0)
    {
	recvDescriptor = networkAddress.descriptor;
    }
    else
    {
	recvDescriptor = descriptor;
    }

#ifdef DEBUG_SS
    //dwrite(3)("SS:receiving: message = %s.",message);
    dwrite(3)("SS:receiving: sizeOfBuffer = %d.\n", sizeOfBuffer);
    dwrite(3)("SS:receiving: ioControl = %s.\n",(ioControl ? "NONBLOCKING" : "BLOCKING"));
    dwrite(3)("SS:receiving: flags = %d.\n", flags);
    dwrite(3)("SS:receiving: networkAddress.descriptor              = %d.\n", 
		  networkAddress.descriptor);
    dwrite(3)("SS:receiving: networkAddress.address.sin_family      = %d (0x%X).\n",
		  networkAddress.address.sin_family, 
		  networkAddress.address.sin_family);
    dwrite(3)("SS:receiving: networkAddress.address.sin_addr.s_addr = %d (0x%X).\n",
		  networkAddress.address.sin_addr.s_addr, 
		  networkAddress.address.sin_addr.s_addr);
    dwrite(3)("SS:receiving: networkAddress.address.sin_port        = %d (0x%X).\n",
		  networkAddress.address.sin_port, 
		  networkAddress.address.sin_port);
    dwrite(3)("SS:receiving: networkAddress.addressLength           = %d.\n", 
		  networkAddress.addressLength);
#endif

    // Enable blocking type.
    errno = 0;
//    returnVal = ioctl(recvDescriptor,
//		      FIONBIO,
//		      &ioControl);
	returnVal = 1;
    if(returnVal < 0)
    {
//	dwrite(2)("SS:receiving: IO blocking control failed (errno=%d).\n", errno);
	return(-1);
    }

    // See if there is anything to read, then read up to size of buffer.
    errno = 0;
    //returnVal = ioctl(recvDescriptor,
		  //    FIONREAD,
		  //    &bytesToReceive);
	returnVal = 1;
    if(returnVal < 0)
    {
//	dwrite(2)("SS:receiving: IO bytes received failed (errno=%d).\n", errno);
	return(-1);
    }

    if(bytesToReceive > 0)
    {
	// Read was has been received upto size of buffer.
	errno = 0;
//	dwrite(2)("SS:calling recv for %d bytes\n", sizeOfBuffer);
	bytesReceived = recv( recvDescriptor,
			      (char *)buffer,
			      ((sizeOfBuffer >= bytesToReceive) ? bytesToReceive:sizeOfBuffer),
			      0);
//	dwrite(2)("SS:Returnd from recv with %d bytes\n", bytesReceived);
	if(bytesReceived < 0)
	{
//	    dwrite(2)("SS:receiving message failed (recv)(errno=%d).\n", errno);
	}
	return(bytesReceived);
    }
    else
    {
	// Nothing to receive.
	return(0);
    }
}


/// Create a connected internet stream to a host computer.
SOCKET SimpleSocket::createConnectedStreamClient(unsigned short port,
					      unsigned long ipAddress,
					      unsigned short family)
{
int returnVal = 0;
SOCKET returnSock;
u_long iMode=1;


    // Create an internet stream socket.
    returnSock = createInternetStream();
  /*  if(returnVal < 0)
    {
      printf("SS: Creating connected client stream failed!\n");
	return(returnVal);
    }*/

	// Set host address.
    returnVal = setAddress(port, ipAddress, family);
    if(returnVal < 0)
    {
	printf("SS: Setting address for connected client stream failed!\n");
	return(returnVal);
    }
    // Attach to host.
    returnVal = attach(AS_CLIENT);
    if(returnVal < 0)
    {
	printf("SS: Attach failed to client stream!\n");
    }

	// Set Non-blocking
	ioctlsocket(returnSock,FIONBIO,&iMode);

    return(returnSock);
}
/// Create a connected internet stream to a host computer.
SOCKET SimpleSocket::createConnectedStreamClient(unsigned short port, 
					      const char *ipAddressString,
					      unsigned short family)
{
    return(createConnectedStreamClient(port,string2hexIpAddress(ipAddressString), family));
}

/// Create a connected internet stream to a host computer.
SOCKET SimpleSocket::createConnectedStreamHost(unsigned short port,
					    unsigned long address,
					    unsigned short family)
{
    int returnVal = 0;
    SOCKET returnSock;

    // Create an internet stream socket.
    returnSock = createInternetStream();
   /* if(returnVal < 0)
    {
	printf("SS: Creating connected host stream failed!\n");
	return(returnVal);
    }*/
    // Set host address.
    returnVal = setAddress(port, address, family);
    if(returnVal < 0)
    {
	printf("SS: Setting address for connected host stream failed!\n");
	return(returnVal);
    }
    // Attach to host.
    returnVal = attach(AS_HOST);
    if(returnVal < 0)
    {
	printf("SS: Attach failed to host stream!\n");
    }
    return(returnSock);
}

// /// Create a connected internet stream to a host computer.
// int SimpleSocket::createConnectedStreamHost(unsigned short port, 
// 					    const char *ipAddressString)
// {
//     return(createConnectedStreamHost(port,string2hexIpAddress(ipAddressString)));
// }


/// Listening for a connection to socket.
int SimpleSocket::listening(const int backlog, SimpleSocket::IoControl ioControl)
{
    int returnVal;

    // Make sure there is something to listen too!
    if(!ready())
    {
//	dwrite(3)("SS: Socket not ready, unable to listen...\n");
	return(-1);
    }

//    errno = 0;
//    returnVal = ioctl( networkAddress.descriptor, FIONBIO, &ioControl);
//    if(returnVal < 0)
//    {
////	dwrite(2)("SS:listening: IO control failed (non-block/block)(errno=%d).\n", errno);
//	return(-1);
//    }

    errno = 0;
    returnVal = listen(networkAddress.descriptor, backlog);
    if(returnVal < 0)
    {
//	dwrite(2)("SS:listening failed (errno=%d).\n",errno);
    }

    return(returnVal);
}


/// Listening for a connection to socket.
SOCKET SimpleSocket::accepting(IoControl ioControl)
{
    int returnVal;
    SOCKET returnSock;
    // Make sure there is something to listen too!
    if(!ready())
    {
//	dwrite(3)("Socket not ready, unable to accept...\n");
	return(-1);
    }

//    errno = 0;
//    returnVal = ioctl( networkAddress.descriptor, FIONBIO, &ioControl);
//    if(returnVal < 0)
//    {
////	dwrite(2)("SS:accepting: IO control failed (non-block/block)(errno=%d).\n", errno);
//	return(-1);
//    }

    #ifdef DEBUG_SS
    dwrite(3)("SS:accepting: networkAddress.descriptor              = %d.\n", 
	   networkAddress.descriptor);
    dwrite(3)("SS:accepting: networkAddress.address.sin_family      = %d (0x%X).\n",
	   networkAddress.address.sin_family, 
	   networkAddress.address.sin_family);
    dwrite(3)("SS:accepting: networkAddress.address.sin_addr.s_addr = %d (0x%X).\n",
	   networkAddress.address.sin_addr.s_addr, 
	   networkAddress.address.sin_addr.s_addr);
    dwrite(3)("SS:accepting: networkAddress.address.sin_port        = %d (0x%X).\n",
	   networkAddress.address.sin_port, 
	   networkAddress.address.sin_port);
    dwrite(3)("SS:accepting: networkAddress.addressLength           = %d.\n", 
	   networkAddress.addressLength);
    #endif

    errno = 0;
    int addressSize;
    addressSize = sizeof(networkAddress.address);
    returnSock = accept(networkAddress.descriptor,
		       (struct sockaddr *)&networkAddress.address, 
		       &addressSize);
    if(returnVal < 0)
    {
//	dwrite(2)("SS: accepting failed (errno=%d).\n",errno);
    }

    return(returnSock);
}

SOCKET SimpleSocket::createBroadcastDatagramReceive(unsigned short port)
{
    int returnVal = 0;
    SOCKET returnSock;
    struct sockaddr_in addr;

    returnSock = createInternetDatagram();
   
	networkAddress.descriptor = returnSock;
    setAddress(port, SS_ANY_ADDRESS, SS_INTERNET);
    u_long flags = 1; //1 is non=blocking, 0 is blocking
	ioctlsocket(returnSock, FIONBIO, &flags);
    networkAddress.optionsSet = TRUE;

    // Bind here, this is the do all function.
    returnVal = bindTo(networkAddress.descriptor);
    if(returnVal != 0)
    {
//	dwrite(3)("SS: Unable to bind to socket!");
	returnVal = -1;
    }
    if(returnVal != 0)
    {
//	dwrite(3)("SS: Unable to bind to socket!");
	returnVal = -1;
	}
	return(returnSock);
}

// Returns number of bytes read.
int SimpleSocket::receiveFrom(void *datagramBuffer,
			      unsigned int bufferLength,
			      int *receivedLength,
			      int flags,
			      SOCKET socketDescriptor,
			      struct sockaddr_in *receivedSocketAddress)
{
    int returnVal = 0;
    
    if(socketDescriptor < 0)
    {
	socketDescriptor = networkAddress.descriptor;
    }
    if(receivedSocketAddress == NULL)
    {
	receivedSocketAddress = &networkAddress.address;
    }
    errno = 0;
    returnVal = recvfrom(socketDescriptor,
			 (char *)datagramBuffer,
			 bufferLength,
			 flags,
			 (struct sockaddr*)receivedSocketAddress,
			 receivedLength);
 //   dwrite(3)("SS: datagram size = %d, received length = %d.",
//	      returnVal,receivedLength);
    if(returnVal < 0)
    {
    printf("SS: Error receiving datagram (errno=%d)!",errno);
	returnVal = -1;
    }

    return(returnVal);
}

// Returns number of bytes read.
int SimpleSocket::receiveDatagram(void *dataBuffer,
				  unsigned int bufferLength)
{
    int returnVal = 0;
    int receivedLength;

	returnVal = recvfrom(networkAddress.descriptor,
							(char *)dataBuffer,
							bufferLength,
							NULL, //flags
							NULL, NULL //address
							);

//    returnVal = receiveFrom(dataBuffer,
//			    bufferLength, NULL, 0,
//				networkAddress.descriptor, NULL);
//    dwrite(3)("SS: datagram size = %d, received length = %d.",
//	      returnVal,receivedLength);
    if(returnVal < 0)
    {
//	dwrite(2)("SS: Error receiving datagram!");
	returnVal = -1;
    }
    return(returnVal);
}
