--- /dev/null
+=head1 NAME
+
+B<check_realserver> - spong-client module to check the local RealServer
+
+=head1 DESCRIPTION
+
+This is a plugin module for the Spong L<spong-client> program. The
+B<check_realserver> module checks the status of the locally running
+RealServer process using the rssm command. It is known to work with
+version 4 of the software, it may work with others (the latest is v9).
+
+It not only alerts you to a problem if it can't connect, but it also
+checks to make sure that certain specified encoders are running
+(useful if you're doing live streaming) and returns all the players
+currently connected.
+
+The number of players listening to each live stream can be
+graphed using L<spong-rrd>.
+
+This module should really be for L<spong-network> but I don't have the
+rssm program for the version of Linux I'm running, nor do I know the
+protocol which rssm uses. Someday I may try and find out the protocol,
+but not yet. If someone can supply me with a rssm that runs in Debian
+GNU/Linux Woody then I'll modify it to work as a spong-network module.
+
+=cut
+
+
+# Register this routine with the plugin reqistry
+$CHECKFUNCS{'realserver'} = \&check_realserver;
+
+# This routine checks RealServer process running locally using rssm.
+
+use Expect;
+
+sub check_realserver {
+ my ($color) = 'green';
+ my ($message) = '';
+ my ($summary) = '';
+ my ($password) = $REALSERVER_PASSWORD;
+
+ if (! defined $password || $password eq '') {
+ $color = 'red';
+ $summary = 'failed - no password';
+ $message = "Please supply me with a password.\n";
+ } else {
+
+ my ($exp);
+ if ($exp = new Expect ("$REALSERVER_RSSM -i localhost")) {
+ $exp->log_stdout(0);
+
+ my ($state) = 'start';
+ my (@list);
+
+ $exp->expect(10, [
+ qr'password:',
+ sub {
+ $spawn_ok = 1;
+ my $fh = shift;
+ $fh->send("$password\n");
+ $state = 'password';
+ exp_continue;
+ }
+ ],
+ [
+ 'Command:',
+ sub {
+ my ($fh) = shift;
+ if ($state eq 'password') {
+ $fh->send("l\n");
+ $state = 'list';
+ exp_continue;
+ } elsif ($state eq 'list') {
+ @list = sort split(/^/m, $exp->before());
+ $fh->send("x\n");
+ $state = 'exit';
+ exp_continue;
+ }
+ }
+ ],
+ [
+ 'rssm: cannot connect to',
+ sub {
+ $state = 'login failed';
+ exp_continue;
+ }
+ ]);
+
+ if ($state eq 'login failed') {
+ $color = 'red';
+ $summary = 'failed';
+ $message = "Connection to RealServer failed. Do you have the correct password?\n";
+ } else {
+ shift(@list);
+
+ my ($encoder_count) = 0;
+ my ($player_count) = 0;
+ my (%encoders_present);
+
+ foreach my $line (@list) {
+ $line =~ s/\r\n//;
+
+ if ($line =~ /^\s*(\w+)\s+([.0-9]+)(\s+(\w+))?/) {
+ my ($type) = $1;
+ my ($ip) = $2;
+ my ($stream) = $4 || undef;
+
+ if ($type eq 'Encoder') {
+ $encoder_count++;
+ $encoders_present{$ip} = 1;
+ $line = $line . "$REALSERVER_ENCODERS_CRIT{$ip}[1] ($REALSERVER_ENCODERS_CRIT{$ip}[0])"
+ if defined $REALSERVER_ENCODERS_CRIT{$ip};
+ $line = $line . "$REALSERVER_ENCODERS_WARN{$ip}[1] ($REALSERVER_ENCODERS_WARN{$ip}[0])"
+ if defined $REALSERVER_ENCODERS_WARN{$ip};
+ } elsif ($type eq 'Player') {
+ $player_count++;
+ }
+ }
+ }
+
+ my $expected_encoder_count = $#{ [ keys %REALSERVER_ENCODERS_CRIT ] }+1
+ + $#{ [ keys %REALSERVER_ENCODERS_WARN ] }+1;
+
+ if ($expected_encoder_count != $encoder_count) {
+ $color = 'yellow';
+ $summary = "$encoder_count encoders, expected $expected_encoder_count";
+ $message = "Missing encoder";
+ $message .= 's' if $expected_encoder_count - $encoder_count > 1;
+ $message .= "\n";
+
+ foreach my $encoder (keys %REALSERVER_ENCODERS_WARN) {
+ $message .= "\t$encoder\t$REALSERVER_ENCODERS_WARN{$encoder}[1]\n"
+ unless defined $encoders_present{$encoder};
+ }
+ foreach my $encoder (keys %REALSERVER_ENCODERS_CRIT) {
+ if (! defined $encoders_present{$encoder}) {
+ $color = 'red';
+ $message
+ .= "\t$encoder\t$REALSERVER_ENCODERS_CRIT{$encoder}[1]\n";
+ }
+ }
+ $message .= "\n";
+ } else {
+ $summary = "ok - players: $player_count";
+ }
+
+ $message .= "Players connected: $player_count\n\n";
+
+ $message .= join("\n", @list) . "\n";
+ }
+ } else {
+ $color = 'red';
+ $summary = 'failed';
+ $message = "Failed to execute rssm: $!\n";
+ }
+ }
+
+# print "c: $color\n";
+# print "s: $summary\n";
+# print "m: $message\n";
+
+ &debug( "realserver - $color, $summary" );
+ &status( $SPONGSERVER, $HOST, "realserver", $color, $summary, $message );
+}
+
+=head2 Output Returned
+
+=over 4
+
+=item Status
+
+If the RealServer process is contactable and any specified encoders are
+running then a 'green' status is returned.
+
+Otherwise, 'yellow' is return if any of the encoders are not running.
+
+'red' is returned if no password is supplied, the server is not accessible
+or rssm fails to execute.
+
+=item Summary Field
+
+If there are no problems then 'ok' and the numbner of players currently
+connected is returned.
+
+If there are problems then a short summary is presented. If there are
+encoders not running then the number of encoders not present and the
+number expected is returned.
+
+=item Detail Message Field
+
+Are full list of all players and encoders currently connected is returned.
+Along with a count of the number of players connected.
+
+If any encoders which are expected aren't found then they are listed.
+
+=back
+
+=head2 Configuration
+
+It is necessary to add the following to L<spong.conf>:
+
+ $REALSERVER_PASSWORD = 'password';
+ %REALSERVER_ENCODERS_WARN = (
+ '10.1.1.1' => [ 'streamfile1', 'Stream pretty name 1' ],
+ );
+ %REALSERVER_ENCODERS_CRIT = (
+ '10.1.1.2' => [ 'streamfile2', 'Stream pretty name 2' ]
+ );
+ $REALSERVER_RSSM = "/local/pnserver/bin/rssm";
+
+Configure C<$REALSERVER_RSSM> to be where rssm is installed on your system.
+
+In C<%REALSERVER_ENCODERS_WARN> and
+C<%REALSERVER_ENCODERS_CRIT> the IP address is the IP address of the encoder.
+In the array, 'streamfile1' is the name that clients request (the filename
+the encoder encodes to). 'Stream pretty name1' is more human readable
+form. It is inserted in the list of encoders that is returned to
+L<spong-server> and is used for the L<spong-rrd> graphs.
+
+=back
+
+=head1 SEE ALSO
+
+L<spong-client>,
+L<spong-client Modules Template|spong-client-mod-template>,
+L<Spong Developer's Guide|developer-guide>
+
+=head1 RESTRICTIONS
+
+B<check_realserver> uses rssm, and the Perl Expect module. Run:
+
+=over 4
+
+ perl -MCPAN -e shell
+ i Expect
+
+=back 4
+
+=head1 AUTHOR
+
+Andrew Ruthven <andrew@etc.gen.nz> - 2002/06/20
+