#!/usr/bin/env python
import socket
import sys
import os
import signal
import re


# Skuste: 
# telnet 127.0.0.1 2222
# ukoncite CTRL-] a potom quit
# alebo prikazom Dovi

# Protokol:
# 
# Cislo n -> OK
# Suma -> Suma je ... 
# Dovi -> Dovi 

# Vytvorime TCP socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# Naviazeme ho na port 2222 pre vsetky lokalne adresy
s.bind(('',2222))
# Najviac 5 spojeni bude cakat vo fronte
s.listen(5)

# Toto je kvoli tomu, aby nam nezostavali zombie 
# procesy a neprerusoval nas signal SIGCHLD
signal.signal(signal.SIGCHLD,signal.SIG_IGN)

try:
    while True:
        connected_socket,address=s.accept()
        print 'Connected by',address
        # Po pripojeni klienta sa forkneme.
        # Child proces obsluzi klienta a zavola sys.exit()
        # Parent proces ocakava
        # dalsieho klienta.
        pid_chld=os.fork()
        if pid_chld<0:
            print "fork vratil chybu"
            sys.exit(1)
        if pid_chld==0:
            # Toto robi child proces.
            # Vytvorime si file object z pripojeneho
            # socketu
            f=connected_socket.makefile()
            sum=0
            for line in f:
                # Precitame, co klient chce
                # a dame mu odpoved
                m=re.match(r'Cislo (\d*)\s*',line)
                if m:
                    sum=sum+int(m.groups()[0])
                    f.write('OK\n')
                elif re.match(r'Suma\s*',line):
                    f.write('Suma je %d\n' % sum)
                    sum=0
                elif re.match(r'Dovi\s*',line):
                    f.write('Dovi\n')
                    f.flush()
                    break
                else:
                    f.write('Error: %s' % line)
                # Toto zabezpeci, ze sa odpoved 
                # posle ihned klientovi - inak to ide do buffra
                f.flush()
            # f je duplikovany connected_socket, preto
            # ho musime zavriet osobitne.
            f.close()
            # Takymto sposobom sa spravne zatvara
            # socket, v prikladoch v dokumentacii to
            # je zle.
            connected_socket.shutdown(socket.SHUT_RDWR)
            connected_socket.close()
            print address,'disconnected'
            sys.exit(0)
except KeyboardInterrupt:
    pass
s.close()

