#include "tcpserver.h"

tcpserver::tcpserver()
{
  ready = 0;
}

tcpserver::~tcpserver()
{
  closesocket();
}

int tcpserver::init( std::string myip, int p )
{
  ip = myip;
  port = p;
  sock = socket(AF_INET, SOCK_STREAM, 0);

  if(sock < 0)
    {
      std::cout << "socket creation error\n";
      return -1;
    }
  address.sin_family = AF_INET;
  address.sin_port = htons(port);
  address.sin_addr.s_addr
    = inet_addr(ip.c_str());
  if(bind(sock,
          (struct sockaddr *) &address,
          sizeof(address)) < 0)
    {
      std::cout << "socket bind error\n";
      return -1;
    }
  listen(sock,10);
  std::cout << "server socket ready\n";
  ready = 1;
  int opts;
  opts = fcntl(sock,F_GETFL);
  if (opts < 0) 
    {
      perror("fcntl(F_GETFL)");
      exit(0);
    }
  opts = (opts | O_NONBLOCK);
  if (fcntl(sock,F_SETFL,opts) < 0) 
    {
      perror("fcntl(F_SETFL)");
      exit(0);
    }
  return 0;
}

int tcpserver::closesocket()
{
  if(ready == 1)
    {
      close(sock);
      ready = 0;
    }
  return 0;
}

int tcpserver::wait( tcpconnection &tc )
{
  if( ready != 1 )
    return -2;
  tc.closesocket();
  FD_ZERO(&fdset);
  FD_SET( sock, &fdset );

#ifdef __DEBUG_TCP__
  std::cout << "waiting for connection\n";
#endif

  struct sockaddr_in cli_addr;
  int clilen = sizeof(cli_addr);  

  struct timeval tv;
  tv.tv_sec = 5;
  tv.tv_usec = 0;
  int retval;
  retval = select(sock+1, &fdset, NULL, NULL, &tv);
  if( retval == 0 )
    {
#ifdef __DEBUG_TCP__
      std::cout << "wait period over\n";
#endif
      return -1;
    }
  int cli = accept(sock,
                   (struct sockaddr *) &cli_addr,
                   (socklen_t*) &clilen);
#ifdef __DEBUG_TCP__
  std::cout << "socket accepted\n";
#endif
  if (cli < 0 )
    return -1;
  tc.init( cli, cli_addr );
  return 0;
}

