/*
  Funciones para la creación y tratamiento de sockets.
  Utilización de TCP y UDP.
  
  IMPLEMENTACIÓN
  Por Miguel Masmano Tello
*/


//#include "red.h"
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int connectsock(char *host,char *service,char *protocol);
int passivesock(char *service,char *protocol,int qlen);

int passiveTCP(char *service,int qlen)
{
  return passivesock(service,"tcp",qlen);
}

int passiveUDP(char *service,int qlen)
{
  return passivesock(service,"udp",qlen);
}

int connectTCP(char *host,char *service)
{
  return connectsock(host,service,"tcp");
}

int connectUDP(char *host,char *service)
{
  return connectsock(host,service,"udp");
}

int connectsock(char *host,char *service,char *protocol)
{
  struct hostent *phe;
  struct servent *pse;
  struct protoent *ppe;
  struct sockaddr_in sin;
  int s,type;

  memset((char*)&sin,0,sizeof(sin));
  sin.sin_family=AF_INET;

  if(pse=getservbyname(service,protocol)) 
    sin.sin_port=pse->s_port;
  else
    if((sin.sin_port=htons((u_short)atoi(service)))==0)
      perror("Servicio inexistente: %s",service);

  if(phe=gethostbyname(host))
    memcpy(phe->h_addr,(char*)&sin.sin_addr,phe->h_length);
  else 
    if(((sin.sin_addr.s_addr=inet_addr(host))==INADDR_NONE))
       perror("Host inexistente: %s",host);

  if((ppe=getprotobyname(protocol))==0)
     perror("Protocolo inexistente: %s",protocol);

  if(strcmp(protocol,"udp")==0)
    type=SOCK_DGRAM;
  else 
    type=SOCK_STREAM;

  s=socket(AF_INET,type,ppe->p_proto);

  if(s<0) perror("No se puede crear el socket");

  if(connect(s,(struct sockaddr *)&sin,sizeof(sin))<0)
      perror("No se puede conectar con %s",host);

  return s;
}

int passivesock(char *service,char *protocol,int qlen)
{
  struct servent *pse;
  struct protoent *ppe;
  struct sockaddr_in sin;
  int s,type;

  memset((char*)&sin,0,sizeof(sin));
  sin.sin_family=AF_INET;
  sin.sin_addr.s_addr=INADDR_ANY;

  if(pse=getservbyname(service,protocol)) 
    sin.sin_port=pse->s_port;
  else
    if((sin.sin_port=htons((u_short)atoi(service)))==0){
      perror("Servicio inexistente: %s",service);
      return -1;
    }
  
  if((ppe=getprotobyname(protocol))==0){
    perror("Protocolo inexistente: %s",protocol);
    return -1;
  }

  if(strcmp(protocol,"udp")==0)
    type=SOCK_DGRAM;
  else 
    type=SOCK_STREAM;

  s=socket(AF_INET,type,ppe->p_proto);

  if(s<0){
    perror("No se puede crear el socket");
    return -1;
  }
  if(bind(s,(struct sockaddr *)&sin,sizeof(sin))<0){
    perror("No puedo asociar el socket");
    return -1;
  }
  if(type==SOCK_STREAM && listen(s,qlen)<0){
    perror("No puedo hacer listen");
    return -1;
  }
  
  return s;
}



