3 # freeside-selfservice-clientd
5 # This is run REMOTELY over ssh by freeside-selfservice-server
8 use subs qw(spawn logmsg);
11 use Storable qw(nstore_fd fd_retrieve);
16 use LockFile::Simple qw(lock unlock);
18 use vars qw( $Debug );
21 my $socket = "/usr/local/freeside/selfservice_socket";
22 my $pid_file = "$socket.pid";
23 my $lock_file = "$socket.lock";
30 #read data to be cached or something
31 #warn "$me Reading init data\n" if $Debug;
34 warn "[client] Creating $socket\n" if $Debug;
35 my $uaddr = sockaddr_un($socket);
36 my $proto = getprotobyname('tcp');
37 socket(Server,PF_UNIX,SOCK_STREAM,0) or die "socket: $!";
39 bind(Server, $uaddr) or die "bind: $!";
40 listen(Server,SOMAXCONN) or die "listen: $!";
43 open(PIDFILE,"<$pid_file");
44 #chomp( my $old_pid = <PIDFILE> );
45 my $old_pid = <PIDFILE>;
47 $old_pid =~ /^(\d+)$/;
50 open(PIDFILE,">$pid_file");
55 #sub REAPER { $waitedpid = wait; $SIG{CHLD} = \&REAPER; }
56 #$SIG{CHLD} = \&REAPER;
58 warn "[client] entering main loop\n" if $Debug;
67 #my $s = new IO::Select;
71 #for ( $waitedpid = 0;
72 # accept(Client,Server) || $waitedpid;
73 # $waitedpid = 0, close Client)
77 #$SIG{PIPE} = sub { warn "SIGPIPE received" };
78 #$SIG{CHLD} = sub { warn "SIGCHLD received" };
80 sub REAPER { warn "SIGCHLD received"; my $pid = wait; $SIG{CHLD} = \&REAPER; }
81 #sub REAPER { my $pid = wait; delete $kids{$pid}; $SIG{CHLD} = \&REAPER; }
82 $SIG{CHLD} = \&REAPER;
84 warn "[client] creating IO::Select\n" if $Debug;
85 my $s = new IO::Select;
91 warn "[client] waiting for connection or token\n" if $Debug;
92 while ( my @handles = $s->can_read ) {
94 foreach my $handle ( @handles ) {
96 if ( $handle == \*STDIN ) {
101 my $packet = fd_retrieve(\*STDIN);
102 my $token = $packet->{'_token'};
103 warn "[client] received packet with token $token\n".
104 join('', map { " $_=>$packet->{$_}\n" } keys %$packet )
106 if ( exists($kids{$token}) ) {
107 warn "[client] sending return packet to $token via $kids{$token}\n"
109 nstore_fd($packet, $kids{$token});
110 warn "[client] flushing $kids{$token}\n" if $Debug;
111 $kids{$token}->flush;
112 #eval { $kids{$token}->flush; };
113 #die "error flushing?!?!? $@\n" if $@ ne '';
114 #warn "[client] closing $kids{$token}\n";
115 #close $kids{$token};
116 #warn "[client] deleting $kids{$token}\n";
117 #delete $kids{$token};
118 warn "[client] done with $token\n" if $Debug;
120 warn "[client] WARNING: unknown token $token, discarding message";
121 #die "[client] FATAL: unknown token $token, discarding message";
124 } elsif ( $handle == \*Server ) {
126 warn "[client] received local connection; forking\n" if $Debug;
128 accept(Client, Server);
131 warn "[client-$$] reading packet from local client" if $Debug > 1;
132 my $packet = fd_retrieve(\*Client);
133 warn "[client-$$] packet received:\n".
134 join('', map { " $_=>$packet->{$_}\n" } keys %$packet )
136 my $command = $packet->{'command'};
137 #handle some commands weirdly?
138 $packet->{_token}=$$; #??
140 warn "[client-$$] sending packet to remote server" if $Debug > 1;
141 flock(STDOUT, LOCK_EX); #acquire write lock
143 nstore_fd($packet, \*STDOUT);
146 flock(STDOUT, LOCK_UN); #release write lock
148 warn "[client-$$] waiting for response from parent" if $Debug > 1;
150 #block until parent has a message
151 my $w = new IO::Select;
153 my @wait = $w->can_read;
154 my $rv = fd_retrieve(\*STDIN);
158 warn "[client-$$] sending response to local client" if $Debug > 1;
160 #send message to local client
161 nstore_fd($rv, \*Client);
166 warn "[client-$$] child exiting" if $Debug > 1;
168 #while (1) { sleep 5 };
174 #close Client; #in parent, right?
182 warn "[client] done handling messages; returning to wait-state" if $Debug;;
186 #die "[client] died unexpectedly: $!\n";
187 warn "[client] fell-through unexpectedly: $!\n" if $Debug;
194 unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
196 confess "usage: spawn CODEREF";
200 #if (!defined($pid = fork)) {
201 my $kid = new IO::Handle;
202 if (!defined($pid = open($kid, '|-'))) {
203 logmsg "WARNING: cannot fork: $!";
206 logmsg "begat $pid" if $Debug;
208 #$kids{$pid}->autoflush;
209 return; # I'm the parent
211 # else I'm the child -- go spawn
213 # open(STDIN, "<&Client") || die "can't dup client to stdin";
214 # open(STDOUT, ">&Client") || die "can't dup client to stdout";
215 ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
219 #sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
221 sub logmsg { warn "[client] $0 $$: @_ at ", scalar localtime, "\n" }