/*
** bof-server.c for bof-server
** 
** Made by Raffaello Pelagalli
** 
** Started on  Mon Jan 21 14:13:07 2008 Raffaello Pelagalli
** Last update Wed Jan 23 00:08:18 2008 Raffaello Pelagalli
** 
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
** 
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
** 
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
** 02111-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <winsock.h>

#define BACKLOG 5
#define VERSION_STR "bof-server v0.01"

void    usage(char * name)
{
  printf("usage: %s <port>\n", name);
  exit (-1);
}

void    bserv_error(char *s, int n, char *msg)
{
  fprintf(stderr, "%s at line %i: %s, %s\n", s, n, msg, strerror(errno));
  exit(-1);
}

int     getl(int fd, char *s)
{
  int   n;
  int   ret;

  s[0] = 0;
  for (n = 0; (ret = recv(fd, s + n, 1, 0)) == 1 && 
         s[n] && s[n] != '\n'; n++)
    ;
  if (ret == -1 || ret == 0)
    return (-1);
  while (n && (s[n] == '\n' || s[n] == '\r' || s[n] == ' '))
    {
      s[n] = 0;
      n--;
    }
  return (n);
}

void    manage_client(int s)
{
  char buffer[512];
  int cont = 1;

  while (cont)
    {
      send(s, "\r\n> ", 4, 0);
      if (getl(s, buffer) == -1)
        return ;
      if (!strcmp(buffer, "version"))
        send(s, VERSION_STR, strlen(VERSION_STR), 0);
      if (!strcmp(buffer, "quit"))
        cont = 0;
    }
}

int     main(int ac, char **av)
{
  int                   p;
  int                   s;
  int                   i;
  int                   pid;
  int                   cli_s;
  struct sockaddr_in    sin;
  struct sockaddr_in    cli_sin;

  if (ac != 2 || atoi(av[1]) > 65555)
    usage(av[0]);
  p = atoi(av[1]);

  WSADATA wsaData;

  if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
    fprintf(stderr, "WSAStartup failed.\n");
    exit(1);
  }

  if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    bserv_error(__FILE__, __LINE__, "socket");
  sin.sin_family = AF_INET;
  sin.sin_port = htons(p);
  sin.sin_addr.s_addr = INADDR_ANY;
  if (bind(s, (struct sockaddr*)&sin, sizeof(sin)) == -1)
    bserv_error(__FILE__, __LINE__, "Can't bind");
  if (listen(s, 42) == -1)
    bserv_error(__FILE__, __LINE__, "Can't listen");
  i = sizeof(cli_sin);
  while ((cli_s = accept(s, (struct sockaddr*)&cli_sin, &i)) != -1)
    {
      printf("[%i] %s connected\n", cli_s, inet_ntoa(cli_sin.sin_addr));
      manage_client(cli_s);
      printf("[%i] %s disconnected\n", cli_s, inet_ntoa(cli_sin.sin_addr));
      closesocket(cli_s);
    }
  perror("accept");
  closesocket(s);
  return (0);
}
