#!/usr/bin/perl -w
# CGI Rendez-vous server for slide-show control
# (c)2011 Felix Hauri - http://realtime.f-hauri.ch - realtime@f-hauri.ch
# GNU Lesser General Public License
# All this work is published under terms of LGPL V3 http://www.gnu.org/licenses/lgpl.html
# This tool open a UNIX Socket in listenning for real time exchanges,
# serve a NPH as multidoc mime flow for pushing control commands to javascript listen clients

my $delay=50;
use strict;
use CGI qw(-nph :push :standard);
use IO::Socket;
use POSIX qw(:signal_h);
my $sigset=POSIX::SigSet->new(SIGALRM);
$sigset->addset(SIGINT);
$sigset->addset(SIGHUP);
$sigset->addset(SIGPIPE);
$sigset->addset(SIGSTOP);
$sigset->addset(SIGABRT);
$sigset->addset(SIGKILL);
$sigset->addset(SIGQUIT);
sigprocmask(SIG_UNBLOCK,$sigset);

$|=1;
my $q=new CGI;

my $sockname="/tmp/cgi-rendezvous-serveur-".$1 if
	$q->param('handler') && $q->param('handler') =~
	/([a-z0-9]+)/;

unless (defined $sockname) {
	print header(-status=>'404 Not Found').start_html("404 Not Found").
	    h1("Not Found").p("The requested URL ".$q->script_name.
				" was not found on this server.").
	    hr.address($q->server_software." at ".$q->server_name);
	exit 0;
};

my $sk;
$SIG{'QUIT'}=$SIG{'KILL'}=$SIG{'STOP'}=$SIG{'HUP'}=$SIG{__DIE__}=
    $SIG{'INT'}=$SIG{'ABRT'}=$SIG{'PIPE'}=sub {
	close $sk;unlink $sockname;exit;};

$SIG{ALRM} =sub {
    print "event: null\ndata: {}\n\n";
    alarm $delay;
    sigprocmask(SIG_UNBLOCK,$sigset);
};
alarm $delay;

print header(-type=>'text/event-stream',-charset=>'utf-8');

if (-S $sockname) {
    die unless $sk=IO::Socket::UNIX->new($sockname);
    print $sk "listenning\n";
    while (<$sk>) {
	printf "event: command\ndata: { 'command' : '%s'}\n\n", $1
	    if /^(Next|Prev|\d+)$/;
    };
} else {
    $sk=IO::Socket::UNIX->new(-Listen=>1,Local=>$sockname) or die;
    $sk->bind($sockname); $sk->listen();
    my @clientlist;
    while (1==1) {
	if (accept(my $newsock,$sk)) {
		my $request=<$newsock>;
		if ($request =~ /^listenning$/) {
			push @clientlist,$newsock;
		} elsif ($request =~ /^(Next|Prev|\d+)$/) {
			my $command=$1;
#			printf STDERR "Send: %s \n",$command;
			printf "event: command\ndata: { 'command': '%s' }\n\n",
			    $command;
		        close $newsock;
			map {
			    syswrite( $_, sprintf("%s\n",$command))
			} @clientlist;
		};
	};
    };
};

