#include "include/ircd.h"
#include "include/socket.h"

int StartSS(Conf cf) {
  int s,one=1;
  struct sockaddr_in local;
  struct linger li;
  memset(&local,0,sizeof(local));
  local.sin_family = AF_INET;
  local.sin_addr.s_addr = inet_addr(cf->ip);
  local.sin_port = htons(cf->port);
  li.l_onoff = 1;
  li.l_linger = 30;
  if ((s=socket(AF_INET,SOCK_STREAM,0)) == -1) {
    perror("socket");
  }
  if (setsockopt(s,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger)) < 0) {
    perror("setsockopt");
    }
  if (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0) {
    perror("setsockopt");
    }
  if (bind(s,(struct sockaddr *)&local,sizeof(local)) == -1) {
    perror("bind");
    }
  if (listen(s,5) == -1) {
    perror("listen");
    }
  return(s);
  }

int GetConnection(int s,Conf cf) {
  int size,one=0,y=0;
  struct sockaddr_in remote;
  int     bufnum;
  fd_set  fds;
  struct  timeval  wait;
  bufnum = 0;
  size = sizeof(struct sockaddr_in);
  if (s==-1) {
    return(-1);
    }
  wait.tv_sec  = 0L;
  wait.tv_usec = 2500L;
  FD_ZERO(&fds);
  FD_SET(s, &fds);
  if (select(s+1, &fds, NULL, 0, &wait) > 0) {
    if ((y = accept (s, (struct sockaddr *)&remote, &size))== -1) {
      perror ("accept");
      }
    if (setsockopt(y, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,sizeof(int)) < 0) {
      perror("setsockopt");
      }
    }
  return(y);
  }

int SendSock(int s,const char *fmt, ...) {
  int len;
  char *string = malloc(sizeof(char));
  va_list args;
  va_start(args, fmt);
  vsprintf(string,fmt,args);
  va_end(args);
  if (string) {
    send(s, string, strlen(string), 0);
    len = strlen(string);
    }
  else {
    len = 0;
    }
  free(string);
  return(len);
  }

int ReadSock(Sock socket) {
    char    inc;
  int     bufnum, n;
  u_long  brx = 0;
  fd_set  fds;
  struct  timeval  wait;
  bufnum = 0;
  if (socket->socket==-1) {
    return(-1);
    }
  wait.tv_sec  = 0L;
  wait.tv_usec = 2500L;
  FD_ZERO(&fds);
  FD_SET(socket->socket, &fds);
  socket->b = 0;
  if (select(socket->socket+1, &fds, NULL, 0, &wait) > 0) {
    do {
      n = recv(socket->socket, &inc, 1,0);
      if (n == 0) {
        socket->socket = -1;
        return -1;
        }
      if ((bufnum == 0) && (inc == ':')) {
        socket->b = 1;
        }
      else {
        if (bufnum < BUFFER_SIZE - 1 ) {
          if ((inc != 13) & (inc != '\n')) {
            socket->data[bufnum++] = inc;
            }
          }
        if (bufnum >= 1024) {
          SendSock(socket->socket,"Reached Max Input\n");
          close(socket->socket);
          socket->socket=-1;
          return(0);
          }
        }
      }
      while (inc != '\n');
      {
         socket->data[bufnum] = '\0';
      }
      brx += bufnum;
      return bufnum;
     }
  return 0;
  }
  
void AddSock(int val,struct slist *tmp) {
  struct slist head;
  Sock node;
  head = *tmp;
  if ((node=(Sock)calloc(1,sizeof(SocketNode)))!=NULL) {
    node->socket=val;
    node->b=1;
    node->id = head.lid++;
    node->next=head.sockets;
    head.sockets = node;   
    }
  else {
    printf("Val: %i not inserted - not enough mem!\n",val);
    }
  *tmp = head;
  }

void DeleteSock(Sock *head,int val) {
  Sock temp,previous,current;
  if (val==(*head)->id) {
    temp=*head;
    *head=(*head)->next; 
    free(temp);
    return;
    }
  else {
    previous=*head;
    current=(*head)->next;
    while((current!=NULL)&(current->id!=val)) {
      previous=current;
      current=current->next;
      }
    if (current!=NULL) {   
      temp=current;  
      previous->next=current->next;
      free(temp);
      return;
      }
    }
  return;
  }

int GetHost(char *host, char *ip) {
	struct in_addr		a;
	struct hostent		*h;


	if (inet_aton(ip, &a) == 0) {
		perror(ip);
		return(1);
	}

	if ((h = gethostbyaddr((char *)&a, sizeof(a), AF_INET)) == NULL) {
		herror(ip);
		return(1);
	}
  sprintf(host,"%s",h->h_name);
	return 0;
	}
