/*******************************************************************************
 * Copyright (c) 2005, 2009 Intel Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Hoang M Nguyen, Intel - Initial API and Implementation
 *
 * $Id: TransportOSCalls_solaris.c,v 1.1 2009/04/14 20:33:34 jwest Exp $
 *
 *******************************************************************************/

#ifdef _SOLARIS  // Linux-specific

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "tptp/TransportSupport.h"



/**
 *********************************************************
 *
 * @brief
 *    required initialization before using socket library.
 *    This also checks for socket DLL version.
 *
 * @note
 *    For linux, we don't have to initialize. No-op.
 *
 * @return
 *    0 - Success
 *    nonzero - Error.
 *********************************************************/
int initForSocketCalls()
{
	return ( 0 );
}


/**
 *********************************************************
 *
 * @brief
 *    set a given handle for child process inheritance
 *
 * @note
 *    for linux, this is not needed. No-op.
 *
 * @return
 *    0 - Error
 *    nonzero - Success
 *********************************************************/
int setHandleInherited(HANDLE handle)
{
	return ( 1 ) ;
}


/**
 *********************************************************
 *
 * @brief
 *    return indicator whether a given socket is valid or not
 *
 * @return
 *    nonzero - Valid
 *    zero - Invalid
 *********************************************************/
int isSocketValid(SOCKET sock)
{
	return (sock >= 0) ;
}


/**
 *********************************************************
 *
 * @brief
 *    print out info about a given socket request
 *
 * @return
 *    0 - always
 * IPV4-ONLY
 *********************************************************/
int printSocketRequest(SOCKET sock, struct sockaddr_in *pRequester)
{
    printf("Incoming connection request on socket %d from 0x%x \n",
				sock,
				(pRequester->sin_addr.s_addr)) ;
	return 0 ;

}



/**
 *********************************************************
 *
 * @brief
 *    Read from a given sock and place the incoming data
 *    into the given buffer
 *
 * @return
 *    negative - Error in receiving
 *    zero - Socket has been closed
 *    positive - Successfully read. The number of bytes received.
 *********************************************************/
int  readFromSocket(SOCKET sock,
					char *buffer,
					int bufferLength,
					int *pBytesRead)
{
	int	   result = 0 ;
	BOOL   tryAgain = FALSE ;
	int i = 0;
	do
	{
		result = read(sock, buffer, bufferLength);

		if (result >= 0)
		{
			*pBytesRead = result ;
			/* terminate with a NULL byte for printf purpose */
			*(buffer+result) = '\0' ;
		}
		else if (errno == EINTR)
		{
			/* if we were interrupted by a signal, try again */
			tryAgain = TRUE ;
		}
	} while (tryAgain == TRUE) ;

	return ( result ) ;
}


/**
 *********************************************************
 *
 * @brief
 *    close the given socket connection
 *
 * @return
 *    0 - Success
 *    nonzero - Error.
 *********************************************************/
int closeThisSocket(SOCKET sock)
{
	int rc = 0 ;

	shutdown(sock, 2);
	rc = close(sock);

	return ( rc ) ;
}

/**
 *********************************************************
 *
 * @brief
 *    convert the given IP address string from "II.JJ.KK.LL"
 *    format to a four byte data array containting
 *    [II][JJ][KK][LL] as unsigned characters
 *
 * @return
 *    0          success
 *    non-zero   failure
 *********************************************************/
int convertIPAddressStringToArrayIPv4M( char *addrStr, unsigned char* addrArray )
{
	struct in_addr addr;
	int            rc;
	unsigned long tmpAddr;


	rc = inet_aton( addrStr, &addr );
	if ( rc == 0 )
	{
		/* The string wasn't recognized as a valid IP address */
		return -1;
	}
	tmpAddr = htonl(addr.s_addr); /* Translate the address to network byte order */

	addrArray[0]=(unsigned char)(tmpAddr>>24 & 0x000000ff);
	addrArray[1]=(unsigned char)(tmpAddr>>16 & 0x000000ff);
	addrArray[2]=(unsigned char)(tmpAddr>>8  & 0x000000ff);
	addrArray[3]=(unsigned char)(tmpAddr);

	return 0;
}

/**
 *********************************************************
 *
 * @brief
 *    convert the given IP address unsigned long value
 *    to "II.JJ.KK.LL" format.  The string returned will
 *    have been allocated using tptp_malloc and should
 *    be freed by the caller using tptp_free
 *
 * @return
 *    0          success
 *    non-zero   failure
 *********************************************************/
int convertIPAddressUlongToStringIPv4M( unsigned long addr, char **addrStr )
{
	char* tempAddrStr;
	struct in_addr  saddr;

	saddr.s_addr = ntohl( addr );
	tempAddrStr = inet_ntoa( saddr );
	if ( tempAddrStr == NULL )
	{
		/* addr wasn't recognized as a valid IP address */
		return -1;
	}

	/* The size here (16) is three digits for each element, plus three dots, plus a NULL */
	*addrStr = tptp_malloc( 16 );
	if ( *addrStr == NULL )
	{
		return TPTP_SYS_NO_MEM;
	}

	strcpy( *addrStr, tempAddrStr );

	return 0;
}

/** IPV4-ONLY */
void extractAddressFromSockAddr(struct sockaddr_in *connection, unsigned char *address)
{
	unsigned long tmpAddr;

	tmpAddr = htonl(connection->sin_addr.s_addr); /* Translate the address to network byte order */

	address[0]=(unsigned char)(tmpAddr>>24 & 0x000000ff);
	address[1]=(unsigned char)(tmpAddr>>16 & 0x000000ff);
	address[2]=(unsigned char)(tmpAddr>>8  & 0x000000ff);
	address[3]=(unsigned char)(tmpAddr);
}


#endif   // end-of-Linux-specific
