/*
 * tail.c
 * (C) Peter Salanki 2002
 * This program is copyright, and covered by the Gnu Public License.
 * The Natasha bot.
 * sorcer@linux.se
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <dlfcn.h>
#include "../../settings.h"
#include "../../globals.h"
#include "../../bottypes.h"
#include "networking.h"

int tailfd = 0;
int listenfd = 0;
BOOL destroylistener = 0;

void *listener(void* ptr) {
  int cliLen;
  struct sockaddr_in cliAddr, servAddr;
  char line[MAX_NETDATA];


  /* create the socket */
  listenfd = socket(AF_INET, SOCK_STREAM, 0);
  if(listenfd<0) {
    perror("Error: listener cannot open socket ");
    return NULL;
  }

  /* bind our socket to server port */
  servAddr.sin_family = AF_INET;
  servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servAddr.sin_port = htons(TAIL_PORT);

  if(bind(listenfd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) {
    perror("Error: listener cannot bind port ");
    return NULL;
  }

  listen(listenfd, 5);

  printf("Tail is waiting for connections on %u\n", TAIL_PORT);

  while(1) {
 
    cliLen = sizeof(cliAddr);
    tailfd = accept(listenfd, (struct sockaddr *) &cliAddr, &cliLen);
    if(checksip(&cliAddr)) {

      if(tailfd < 0) { /* an error occured */
	perror("Error: listener cannot accept connection ");
	return NULL;
      }

      /* init line */
      memset(line,0x0,MAX_NETDATA);

      /* receive segments */
      while(read_line(line)!=1) {

#ifdef DEBUG
	printf("Received: %s\n", line);
#endif

	netparse(line, 1); /* Parse the data */ 

	memset(line,0x0,MAX_NETDATA);	/* init line */
      
      }
    } else {
      putsocket("You are not allowed to connect from this host.\n", tailfd);
      close(tailfd);
      sprintf(line, "%c4Warning:%c Unauthorized connection from: %c%s%c", COLORS, COLORS, BOLD, inet_ntoa(cliAddr.sin_addr), BOLD);
      privmsg(HOMECHAN, line);
    }
    if(destroylistener) return NULL;
  }

}

int read_line(char *line_to_return) {

  static int rcv_ptr=0;
  static char rcv_msg[MAX_NETDATA];
  static int n;
  int offset;

 offset=0;

 while(1) {
  if(rcv_ptr==0) {
   /* read data from socket */
   memset(rcv_msg,0x0,MAX_NETDATA); /* init buffer */
   n = recv(tailfd, rcv_msg, MAX_NETDATA, 0); /* wait for data */
   if (n<0) {     /* error! */
    perror(" cannot receive data ");
    return 1;
   } else if (n==0) { /* the connection was closed */
    printf(" connection closed by client\n");
    close(tailfd);
    return 1;
   }
  }

  /* if new data read on socket */
  /* OR */
  /* if another line is still in buffer */

  /* copy line into 'line_to_return' */
  while(*(rcv_msg+rcv_ptr)!=END_LINE && rcv_ptr<n) {
   memcpy(line_to_return+offset,rcv_msg+rcv_ptr,1);
   offset++;
   rcv_ptr++;
  }

  /* end of line + end of buffer => return line */
  if(rcv_ptr==n-1) {
   /* set last byte to END_LINE */
   *(line_to_return+offset)=END_LINE;
   rcv_ptr=0;
   return ++offset;
  }

  /* end of line but still some data in buffer => return line */
  if(rcv_ptr <n-1) {
   /* set last byte to END_LINE */
   *(line_to_return+offset)=END_LINE;
   rcv_ptr++;
   return ++offset;
  }

  /* end of buffer but line is not ended => */
  /*  wait for more data to arrive on socket */
  if(rcv_ptr == n) {
   rcv_ptr = 0;
  }

 } /* end while */
}

int checksip(struct sockaddr_in *cliAddr) {
  return 1;
}

