/*
 * Opens requred sockets
 * $Header: inet.c,v 2.1 93/04/13 21:46:08 jraja Exp $
 * $Log:	inet.c,v $
 * Revision 2.1  93/04/13  21:46:08  21:46:08  jraja (Jarno Tapio Rajahalme)
 * Made this compile with the newest API.
 * 
 * Revision 2.0  93/03/20  17:31:39  17:31:39  ppessi (Pekka Pessi)
 * initial netlib version..
 * 
 * Revision 1.4  93/03/16  19:13:57  19:13:57  too (Tomi Ollila)
 * code fixes
 * 
 * Revision 1.3  93/03/16  10:43:25  10:43:25  puhuri (Markus Peuhkuri)
 * Added AMITCP stuff.
 * 
 */

#ifdef AMIGA
#include <exec/types.h>
#include <sys/types.h>
#if __SASC
#include <proto/socket.h>
#elif __GNUC__
#include <inline/socket.h>
#else
#include <clib/socket_protos.h>
#endif
#endif /* AMIGA */

#ifdef __STDC__
#include <stdlib.h>
#endif

#include <stdio.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>

#include <netinet/in.h>

#include <netdb.h>

#include "qwriter.h"
#include <string.h>

#include <arpa/inet.h>

/*
 * hostname pointer to our host name or NULL
 * port in a port number to listen
 * type is SOCK_STREAM (TCP) or SOCK_DGRAM (UDP)
 * 
 * returns a file descriptor to open socket
 */

char *MyHost;

int Fail(int s, int error)
{
  if (s >= 0)
    CloseSocket(s);
  return error;
}

int open_server(char *hostname, UWORD port, int type)
{ 
#ifndef NODB
  struct hostent *hp;
#endif
  struct sockaddr_in soc_in_s, soc_in_c;
  int soc_len = sizeof(struct sockaddr);
  int sid_s, sid_c;

  printf("'%s' port=%ld type=%ld\n", hostname, port, type);
#ifndef NODB
  if(hostname == NULL){
    hostname = (char *)malloc(80);
    gethostname(hostname,80);
  }
				/* Get our address */
  if ((hp = gethostbyname(hostname)) == NULL){
    fprintf(stderr,"Couldn't get information for host '%s'",hostname);
    return(FAIL);
  }
#endif
				/* Get socket */
  if ((sid_s = socket(AF_INET, type, 0)) < 0) {
    perror("socket() failed");
    return(FAIL);
  }
				/* Create address corresponding our service */

  bzero((caddr_t)&soc_in_s, sizeof(soc_in_s));
  bzero((caddr_t)&soc_in_c, sizeof(soc_in_c));

#ifdef AMITCP
  soc_in_s.sin_len = sizeof(struct sockaddr_in);
#endif
  soc_in_s.sin_family = AF_INET;
  soc_in_s.sin_port = htons(port);
#ifndef NODB
  bcopy(hp->h_addr, (caddr_t)&soc_in_s.sin_addr, hp->h_length);
  printf("addr: %s\n", inet_ntoa(soc_in_s.sin_addr));
#else
  soc_in_s.sin_addr.s_addr = inet_addr(MyHost);
#endif

				/* Bind it to our socket */
  if(bind(sid_s, (struct sockaddr *)&soc_in_s, sizeof(soc_in_s)) < 0 ) {
    perror("bind() failed");
    return (Fail(sid_s, FAIL));
  }
				/* An UDP-socket can't be
				   listen'd or accept'd */
  if(type == SOCK_DGRAM)
    return (sid_s);
				/* Listen socket.. */
  if(listen(sid_s, 1) < 0) {
    perror("listen() failed\n");
    return (Fail(sid_s, FAIL));
  }
				/* Accept connection */
  if ((sid_c = accept(sid_s, 
		      (struct sockaddr *)&soc_in_c, 
		      (long *)&soc_len)) 
      < 0){
    perror("accept() failed\n");
    return (Fail(sid_s, FAIL));
  }

  CloseSocket(sid_s);

  return (sid_c);
}

/*
 * as above, but does not accept null as hostname
 */
int open_client(char *hostname,UWORD port,int type)
{
#ifndef NODB
  struct hostent *hp;
#endif
  struct sockaddr_in soc_in_s, soc_in_c;
  int sid_s;

printf("'%s' port=%ld type=%ld\n",hostname,port,type);
				/* Get server address */
#ifndef NODB
  if((hp = gethostbyname(hostname)) == NULL){
    fprintf(stderr,"Couldn't get information for host '%s'",hostname);
    perror("");
    return(FAIL);
  }
#endif
				/* Get socket */
  if((sid_s = socket(AF_INET, type, 0)) < 0) {
    perror("socket() failed");
    return(FAIL);
  }

  bzero((caddr_t)&soc_in_s, sizeof(soc_in_s));
  bzero((caddr_t)&soc_in_c, sizeof(soc_in_c));

#ifdef AMITCP
  soc_in_s.sin_len = sizeof(struct sockaddr_in);
#endif
  soc_in_s.sin_family = AF_INET;
  soc_in_s.sin_port = htons(port);
#ifndef NODB
  bcopy(hp->h_addr, (caddr_t)&soc_in_s.sin_addr, hp->h_length);
#else
  soc_in_s.sin_addr.s_addr = inet_addr(MyHost);
#endif

				/* Connect to server.. */
  if (connect(sid_s, (struct sockaddr *)&soc_in_s, sizeof(soc_in_s)) < 0){
    perror("connect() failed");
    CloseSocket(sid_s);
    return(FAIL);
  }
  return(sid_s);
}
