//============================================================================
/// 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
//============================================================================

#include "SimpleSocket.h"


SimpleSocket::SimpleSocket(debug_t debugLevel,
			   int datagramBufferSize)
{
    debug = debugLevel;

#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.
int SimpleSocket::create(Type type, Domain domain, Protocol 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.
int SimpleSocket::createInternetDatagram()
{
#ifdef DEBUG_SS
    dwrite(3)("SS:createInetDgram: create socket Internet Datagram...");
#endif
    return(SimpleSocket::create(SS_DATAGRAM));
}


/// Create TCP Socket for Stream.
int 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 = close(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,
			       optionValue,
			       optionValueLength);
	if(returnVal < 0)
	{
	    dwrite(2)("SS: Error setting socket option 0x%X (errno=%d)!", options, errno);
	    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 = 0;
#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;
#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 = -1;
    }
    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)
    {
	dwrite(2)("SS: Error, attach to IP address and port failed (errno=%d).\n",errno);
	returnVal = destroy();
	returnVal = -1;
    }
    else
    {
	networkAddress.connected = true;
    }

    return(returnVal);
}

/// bindTo (bind) a name to a socket
int SimpleSocket::bindTo( int descriptor,
			  struct sockaddr_in *socketAddress,
			  int sizeSocketAddress)
{
    int returnVal = 0;
    errno = 0;
    if(socketAddress == NULL)
	socketAddress = &networkAddress.address;

    returnVal = bind(descriptor,
		     (struct sockaddr *)&socketAddress,
		     sizeSocketAddress);
    if(returnVal != 0)
    {
	dwrite(2)("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
int 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
    int returnVal=0;

    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.
int 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
    returnVal = 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);
    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,
			message,
			messageLength,
			flags,
			(const struct sockaddr *)&networkAddress.address,
			networkAddress.addressLength);
    if(bytesSent < 0)
    {
	dwrite(2)("SS: Error, broadcast send failed (errno=%d).\n", errno);
    }
    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;
    int 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);
    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,
		      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;
    int 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);
    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);
    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;
	bytesReceived = recv( recvDescriptor,
			      (void *)buffer,
			      ((sizeOfBuffer >= bytesToReceive) ? sizeOfBuffer : bytesToReceive),
			      0);
	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.
int SimpleSocket::createConnectedStreamClient(unsigned short port,
					      unsigned long ipAddress,
					      unsigned short family)
{
    int returnVal = 0;

    // Create an internet stream socket.
    returnVal = createInternetStream();
    if(returnVal < 0)
    {
	dwrite(3)("SS: Creating connected client stream failed!\n");
	return(returnVal);
    }
    // Set host address.
    returnVal = setAddress(port, ipAddress, family);
    if(returnVal < 0)
    {
	dwrite(3)("SS: Setting address for connected client stream failed!\n");
	return(returnVal);
    }
    // Attach to host.
    returnVal = attach(AS_CLIENT);
    if(returnVal < 0)
    {
	dwrite(3)("SS: Attach failed to client stream!\n");
    }
    return(returnVal);
}
/// Create a connected internet stream to a host computer.
int 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.
int SimpleSocket::createConnectedStreamHost(unsigned short port,
					    unsigned long address,
					    unsigned short family)
{
    int returnVal = 0;

    // Create an internet stream socket.
    returnVal = createInternetStream();
    if(returnVal < 0)
    {
	dwrite(3)("SS: Creating connected host stream failed!\n");
	return(returnVal);
    }
    // Set host address.
    returnVal = setAddress(port, address, family);
    if(returnVal < 0)
    {
	dwrite(3)("SS: Setting address for connected host stream failed!\n");
	return(returnVal);
    }
    // Attach to host.
    returnVal = attach(AS_HOST);
    if(returnVal < 0)
    {
	dwrite(3)("SS: Attach failed to host stream!\n");
    }
    return(returnVal);
}

// /// 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.
int SimpleSocket::accepting(IoControl ioControl)
{
    int returnVal;

    // 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);
    returnVal = accept(networkAddress.descriptor,
		       (struct sockaddr *)&networkAddress.address, 
		       &addressSize);
    if(returnVal < 0)
    {
	dwrite(2)("SS: accepting failed (errno=%d).\n",errno);
    }

    return(returnVal);
}

int SimpleSocket::createBroadcastDatagramReceive(unsigned short port)
{
    int returnVal = 0;

    returnVal = createInternetDatagram();
    if(returnVal < 0)
    {
	dwrite(3)("SS: Unable to create Internet Datagram Socket!\n");
	return (returnVal);
    }
    else
    {
	// Received socket descriptor on createInetDgram success.
	networkAddress.descriptor = returnVal;
    }

    // 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;
    }

    return(returnVal);
}

// Returns number of bytes read.
int SimpleSocket::receiveFrom(void *datagramBuffer,
			      unsigned int bufferLength,
			      int *receivedLength,
			      int flags,
			      int 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,
			 datagramBuffer,
			 bufferLength,
			 flags,
			 (struct sockaddr*)receivedSocketAddress,
			 receivedLength);
    dwrite(3)("SS: datagram size = %d, received length = %d.",
	      returnVal,receivedLength);
    if(returnVal < 0)
    {
	dwrite(2)("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 = receiveFrom(dataBuffer,
			    bufferLength,
			    &receivedLength);
    dwrite(3)("SS: datagram size = %d, received length = %d.",
	      returnVal,receivedLength);
    if(returnVal < 0)
    {
	dwrite(2)("SS: Error receiving datagram!");
	returnVal = -1;
    }
    return(returnVal);
}
