#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h>
#include <signal.h>
#include <string.h>
#include <memory.h>
extern int errno;
/******************************************************************************/
int createListeningSocketOnPort(port) unsigned short port; {
  /* create a socket on which I can listen and accept connections */
  struct protoent *p; 
  struct sockaddr_in sin;
  int s;
  char host[100];

  p = getprotobyname("tcp");
  if((s = socket(AF_INET,SOCK_STREAM,p->p_proto))==-1) {
    perror("createListeningSocket: socket"); 
    return 0; 
  }
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_ANY;  
  sin.sin_port = htons(port);
  /* need a unique inet identifier for the socket */
  if (bind(s,(struct sockaddr *)&sin,sizeof(sin))==-1) {
    perror("createListeningSocketOnPort: bind"); 
    return 0; 
  }
  if (listen(s,5)) {
    perror("acceptConnect: listen");
    return 0; 
  }
  return s;
}
/******************************************************************************/
int acceptConnect(s) int s;
{
  /* returns a new socket no. from listening to socket s if successful, 0 otherwise */
  int status,ns,len;
  struct sockaddr saddr;

  while (1) {
    len = sizeof(saddr);
    ns = accept(s,&saddr,&len);
    if (ns >= 0) break;
    if (errno != EINTR) {
      perror("acceptConnect: accept");
      return 0;
    } 
  }
  return ns;
}
/*************************************************************************************/
int makeConnect(hostname,port_no) /* returns socket if successful, 0 otherwise       */
char *hostname;                   /* name of host to which I desire to connect       */
unsigned short port_no;           /* port no. of process to which I desire to connect*/
{
  struct protoent *p; 
  struct hostent  *h;
  int s; 
  struct sockaddr_in sin;
  int i;

  while (1) {
    p = getprotobyname("tcp");
    if((s = socket(AF_INET,SOCK_STREAM,p->p_proto))==-1) {
      perror("makeConnect - socket"); 
      close(s);
      return 0; 
    }
    if (!(h = gethostbyname(hostname))) { 
      int inetaddr = inet_addr(hostname);
      close(s);
      if (inetaddr != -1) {
	return makeInetConnect(inetaddr,port_no);
      }
      else {
	fprintf(stderr, "makeConnect: %s: unknown host\n",hostname);
	return 0; 
      }
    }
    memcpy(&sin.sin_addr,h->h_addr,h->h_length);
        
    sin.sin_port = htons(port_no);
    sin.sin_family = h->h_addrtype;
    if (connect(s,(struct sockaddr *)&sin,sizeof(sin))==0) {
      return s;
    } else if (errno == ECONNREFUSED || errno == EINTR) {
      close(s);
    } else {
      perror("failed makeConnect - connect"); 
      close(s);
      return 0;
    }
  }
}

/*******************************************************************************/
int makeInetConnect(inetaddr,port_no) /* returns socket if successful, 0 otherwise       */
unsigned int inetaddr;                /* 32 bit inet address                             */
unsigned short port_no;               /* port no. of process to which I desire to connect*/
{
  struct protoent *p; 
  struct hostent  *h;
  int s; 
  struct sockaddr_in sin;
  int i;
 
  while (1) {
    p = getprotobyname("tcp");
    if((s = socket(AF_INET,SOCK_STREAM,p->p_proto))==-1) {
      perror("makeInetConnect: socket"); 
      close(s);
      return 0; 
    }
    memcpy(&sin.sin_addr,&inetaddr,sizeof(inetaddr));
    sin.sin_port = htons(port_no);
    sin.sin_family = AF_INET;
    if (connect(s,(struct sockaddr *)&sin,sizeof(sin))==0) {
      return s;
    } else if (errno == ECONNREFUSED) {
      perror("try again makeInetConnect: connect");
      close(s);
    } else {
      perror("failed makeInetConnect: connect"); 
      close(s);
      return 0;
    }
  }
}

