#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#ifdef _AIX
#include <sys/select.h>
#endif

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif

#ifndef NULL
#define NULL (char *)0
#endif

#include "port.h"
#include "connect.h"
#include "memStuffForPipSqueeks.h"

PortDescriptor *NetClientConnect(serverAddress,serverTCPPort)
char *serverAddress;
int serverTCPPort;
/* create an internet client socket connection to the server address 
 * return PortDescriptor
 * return 0 on can't connect */
{
int sockfd;
struct sockaddr_in serv_addr;
unsigned long inaddr;
struct hostent  *hp;
PortDescriptor *s;


	bzero((char *) &serv_addr, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port	= htons(serverTCPPort);

        /*
         * First try to convert the host name as a dotted-decimal number.
         * Only if that fails do we call gethostbyname().
         */

        if ((inaddr = inet_addr(serverAddress)) != INADDR_NONE) {
                                        /* it's dotted-decimal */
                bcopy((char *) &inaddr, (char *) &serv_addr.sin_addr,
                                sizeof(inaddr));
                }
	else { /* it's a dotted alphanum name */
		if ((hp = gethostbyname(serverAddress)) == 0) {
#ifdef DEBUG
			printf("Can't get IP from hostname %s\n",serverAddress);
#endif
			return(0);
			}
		else {	
			bcopy(hp->h_addr, (char *) &serv_addr.sin_addr,
					hp->h_length);
			}
		}

	
	if (( sockfd = socket(AF_INET, SOCK_STREAM, 0 )) < 0) {
#ifdef DEBUG
		printf("NetClientConnect():Couldn't create socket\n");
#endif
		return(0);
		}
	if (connect(sockfd, (struct sockaddr *) &serv_addr,
			sizeof(serv_addr)) < 0) {
#ifdef DEBUG
		printf("NetClientConnect():Couldn't connect\n");
#endif
		return(0);
		}
#ifdef DEBUG
		printf("NetClientConnect():Connection established\n");
#endif
	if (!(s = (PortDescriptor *) MALLOC(sizeof(PortDescriptor)))) {
		return(0);
		}

	s->socketFD = sockfd;
	if (!(s->serverAddress = (char *) STRDUP(serverAddress))) {
		return(0); /* out of memory */
		}
	s->serverTCPPort = serverTCPPort;
	s->connected = 1;
	s->numInBuffer = 0;

	return(s);
}

void NetCloseConnection(s)
/* Close connection and free up PortDescriptor */
PortDescriptor *s;
{
	if (!s) 
		return;

	close(s->socketFD);
	s->connected = 0;
/*
	FREE(s->serverAddress);
	FREE(s);
*/
}



int NetWrite(s,message,length)
PortDescriptor *s;
char *message;
int length;
/* return number of bytes written */
/* return -1 on error */
{
int wlength;

	if ((!s) || (!s->connected)) {
		return(-1);
		}

	wlength = write(s->socketFD, message, length);

	if (wlength != length) {
		/* error */
		NetCloseConnection(s);
		}

	return(wlength);
}

int NetIsThereInput(s)
/* Do a non block check on socket for input and return 1 for yes, 0 for no */
PortDescriptor *s;
{
static struct  timeval timeout = { 0L , 0L };
int val;
fd_set readfds;

	if ((!s) || (!s->connected)) {
		return(-1);
		}

	FD_ZERO(&readfds);
	FD_SET(s->socketFD,&readfds);
	if (0 < select(32, &readfds, 0, 0, &timeout)){
		return(1);
		}
	else {
		return(0);
		}
	
}

int NetRead(s,buffer,bufferSize)
PortDescriptor *s;
char *buffer;
int bufferSize;
/* return number of characters read */
/* if 0 is returned after select returned true, then connection has been
 * 	terminated on remote side */
/* return -1 on error */
{
int length;

	if ((!s) || (!s->connected)) {
		return(-1);
		}

	length = read(s->socketFD, buffer, bufferSize);

	if (length == -1) {
		/* error */
		NetCloseConnection(s);
		}

	return(length);
}




char *NetReturnAddress(s)
PortDescriptor *s;
/* return address of this port */
{
static char address[80];

	if (!s || (!s->connected)) {
		return((char *) 0);
		}

	sprintf(address,"%s:%d",s->serverAddress,s->serverTCPPort);
	return(address);
}


int NetGetSocketDescriptor(s)
/* extract socket file descriptor from the Port structure */
PortDescriptor *s;
{
	if (!s) {
		return(-1);
		}
	return(s->socketFD);
}

int NetIsConnected(s)
/* if connected, return 1, else 0 */
PortDescriptor *s;
{
	if (!s)
		return(0);
	return(s->connected);
}
