summaryrefslogtreecommitdiffstats
path: root/socket-multiplexer.pl
blob: 2290fd260d216cecc4b0b1299df4acc8fcaea24b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/perl -T
use strict;
use warnings;

use AnyEvent;
use AnyEvent::Socket;
use AnyEvent::Handle;
use Fcntl qw(:flock);
use File::Basename;

if ($#ARGV != 0) {
	print STDERR "usage: ".basename($0)." <socket path>\n";
	print STDERR "\n";
	print STDERR "muliplex incoming messages on the socket to all clients\n";

	exit 1;
}

our $sock_path = $ARGV[0];
($sock_path) = ($sock_path =~ /^(.+)$/);

sub signal_handler {
	my ($signal) = @_;
	print STDERR "Got signal: $signal\n";

	for my $xid (keys %main::conns) {
		$main::conns{$xid}->destroy;
	}
	$main::sock->destroy if $main::sock;

	if ($main::lock) {
		unlink $main::sock_path or warn "Failed to remove socket: $!\n";
		flock($main::lock, LOCK_UN) or warn "Failed to release lock: $!\n";
		close $main::lock or warn "Failed to close lock file: $!\n";
		unlink "$main::sock_path.lock" or warn "Failed to remove lock file: $!\n";
	}
	exit(1);
}

use sigtrap 'handler', \&signal_handler, 'normal-signals';
$SIG{PIPE} = 'IGNORE';

open (our $lock, ">", "$sock_path.lock") or die "Can't open lock file: $!\n";
flock($lock, LOCK_EX ^ LOCK_NB) or die "Failed to aquire lock: $!\n";

my %conns;
my $i = 0;

our $sock_guard = tcp_server "unix/", $sock_path, sub {
	my ($fh) = @_;
	 my $hdl = AnyEvent::Handle->new(
		 fh => $fh,
	 );

	 my $id = $i++;
	 $conns{$id} = $hdl;

	 $hdl->on_error(sub {
		 delete $conns{$id};
	 });

	 my @reader; @reader = (line => sub {
		 my $line = $_[1];

		 # send to everyone else
		 for my $xid (grep {$_ ne $id} keys %conns) {
			 $conns{$xid}->push_write("$line\n");
		 }
		 $hdl->push_read(@reader);
	 });
	 $hdl->push_read(@reader);
};

AnyEvent->condvar->recv;