/*
  
  trojan - klasicky UDP server - linux verze 
  2006 (L) cZokL, mr [dot] czokl [at] gmail [dot] com

 
*/

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <netinet/in.h>
 
using namespace std ;

#define BUFSIZE 1024

inline void usage() {

  cout << "Pouziti: udp_server_lin <port> " << endl ;  
  
}


int main(int argc, char *argv[]) {

  /*
  
  prebrani vstupnich parametru
  
  */
  
  if ( argc != 2 ) {
  
    cerr << "chybny pocet argumentu" << endl ;
    usage() ;
    exit(-1) ;
    
  }
   
  
  int port = atoi(argv[1]) ;
  
  if ( port < 1 || port > 65536 ) {
  
    cerr << "port neni v rozsahu 1-65536" << endl ;
    usage() ;
    exit(-1) ;
  
  }  


  /* naplneni struktury SOCKADRR_IN */

  sockaddr_in service ;

  service.sin_family = AF_INET ;
  service.sin_addr.s_addr = INADDR_ANY ;
  service.sin_port = htons(port) ;

  /*Vytvoreni soket deskcriptoru*/

  int sock = socket(AF_INET, SOCK_DGRAM, 0)  ;

  if( sock == -1 ) {
  
    cerr << "Nepodarilo se vytvorit socket deskriptor " << endl ;

    exit(-1) ;

  }

  /*
  
  bind - otevreni portu a asociovani s nasi aplikaci  
   
  */

  if( bind(sock, (sockaddr*) &service, sizeof(service)) == -1 ) {

    cerr << "Chyba pri spousteni bind()" << endl ;

    close(sock) ;
    
    exit(-1) ;

  }

  /* cekani na prijem zpravy */

  socklen_t iSize = sizeof(service) ;
  int size ;
  char data[BUFSIZE] ;  
 
 if( (size = recvfrom(sock, data, BUFSIZE, 0, (sockaddr*) &service, &iSize)) == -1 ) {

    cerr << "Chyba pri prijimani dat!" << endl ;

    close(sock) ;
        
    exit(-1) ;

  }

  /* 
  spustime prikaz ktery pozaduje klient a to tak ze proces forkneme
  abychom nemuseli cekat na vysledek procesu ale klientu odesleme
  zpravu o spusteni a ukoncime rodice, dite at si pak dela co chce  
  
  */

  data[size] = '\0' ;
 
  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 (sendto(sock, result.c_str(), result.size(), 0, (sockaddr*) &service, sizeof(service)) == -1) {

      cout << "Chyba pri odesilani pozadavku" << endl ;

      close(sock) ;
       
      exit(-1) ;

    }
    

    //uzavreni socketu a vycisteni struktury WSAdata
    close(sock) ;
    
    exit (0) ;
  
  }

  execl(data, data, 0) ;


}
