# $Id: Announcer.pm 1354 2006-06-14 00:27:26Z rvosa $ # Subversion: $Rev: 117 $ # Copyright (c) 1997 Lunatech Research / Bart Schuller # See the file "Artistic" in the distribution for licensing and # (lack of) warranties. use Log::Log4perl; use COPE::CORBA::ORB; Log::Log4perl::init( COPE::CORBA::ORB->LOGPERLCONF ); package COPE::Announcer; use strict; use IO::Handle; use Socket; use COPE::CORBA::ORB; my $logger = Log::Log4perl::get_logger('COPE.Announcer'); # Subs sub announce { $logger->info("Announcing service"); my ( $name, $value ) = @_; my ( $msg, $index ) = ( 'ADD ', 4 ); CORBA::ORB::_marshal_string( \$msg, \$index, 0, $name ); CORBA::ORB::_marshal_string( \$msg, \$index, 0, $value ); my $broadcaster = new COPE::Announcer; $broadcaster->shout(); return $broadcaster->send_and_get_message($msg); } sub resolve { $logger->info("Resolving service"); my ($name) = @_; my ( $msg, $index ) = ( 'GET ', 4 ); CORBA::ORB::_marshal_string( \$msg, \$index, 0, $name ); my $broadcaster = new COPE::Announcer; $broadcaster->shout(); $msg = $broadcaster->send_and_get_message($msg); return undef if !defined $msg; $index = 0; my $value = CORBA::ORB::_unmarshal_string( \$msg, \$index, 0 ); return $value; } sub daemon { $logger->info("Starting daemon"); my %db; my $listener = new COPE::Announcer; $listener->listen(); while (1) { my $msg = $listener->get_message(undef); next if !$msg; my $cmd = substr( $msg, 0, 4 ); my $index = 4; if ( $cmd eq 'ADD ' ) { my $name = CORBA::ORB::_unmarshal_string( \$msg, \$index, 0 ); my $value = CORBA::ORB::_unmarshal_string( \$msg, \$index, 0 ); $db{$name} = $value; $listener->send_message('ADDED'); next; } if ( $cmd eq 'GET ' ) { my $name = CORBA::ORB::_unmarshal_string( \$msg, \$index, 0 ); $msg = ''; $index = 0; CORBA::ORB::_marshal_string( \$msg, \$index, 0, $db{$name} ); $listener->send_message($msg); next; } } } # Class methods sub new { $logger->info("Creating new announcer"); my ($class) = @_; my $self = { sock => new IO::Handle }; socket( $self->{sock}, PF_INET, SOCK_DGRAM, getprotobyname('udp') ) or ( $logger->fatal($!) && die "socket: $!" ); return bless $self, $class; } # Object methods sub listen { $logger->info("Listening"); my ($self) = @_; bind( $self->{sock}, scalar sockaddr_in( 3228, INADDR_ANY ) ) or ( $logger->fatal($!) && die "bind: $!" ); } sub shout { $logger->info("Shouting"); my ($self) = @_; $self->{'peer'} = sockaddr_in( 3228, INADDR_BROADCAST ); setsockopt( $self->{'sock'}, SOL_SOCKET, SO_BROADCAST, 1 ) or ( $logger->fatal($!) && die "setsockopt: $!" ); } sub get_message { $logger->info("Getting message"); my ( $self, $timeout ) = @_; my ( $msg, $rout ); my $rin = ''; vec( $rin, fileno( $self->{'sock'} ), 1 ) = 1; select( $rout = $rin, undef, undef, $timeout ); if ( vec( $rout, fileno( $self->{'sock'} ), 1 ) ) { $self->{'peer'} = recv $self->{'sock'}, $msg, 4096, 0; return $msg; } else { return undef; } } sub send_message { $logger->info("Sending message"); my ( $self, $msg ) = @_; send( $self->{sock}, $msg, 0, $self->{peer} ) or ( $logger->fatal($!) && die "send: $!\n" ); } sub send_and_get_message { $logger->info("Sending and getting message"); my ( $self, $in ) = @_; my $out; for ( my $i = 0 ; $i < 10 ; $i++ ) { $self->send_message($in); last if defined( $out = $self->get_message(1) ); } return $out; } 1; __END__ =head1 NAME COPE::Announcer A class to ... =head1 SYNOPSIS use COPE::Announcer; =head1 DESCRIPTION The COPE::Announcer class implements ... =head1 OPTIONS -D - show debugging information -h - show help -v - show version Other options ... =head1 SUBROUTINES =head2 announce Parameters: name value Insert description of subroutine here... =head2 resolve Parameters: name Insert description of subroutine here... =head2 daemon Parameters: none Insert description of subroutine here... =head2 new (constructor) Parameters: class Insert description of constructor here... =head2 listen (method) Parameters: none Insert description of method here... =head2 shout (method) Parameters: none Insert description of method here... =head2 get_message (method) Parameters: timeout Insert description of method here... =head2 send_message (method) Parameters: msg Insert description of method here... =head2 send_and_get_message (method) Parameters: in Insert description of method here... =head1 FILES Files used by the COPE::Announcer class ... =head1 SEE ALSO Related information ... =head1 WARNINGS ... =head1 NOTES ... =head1 BUGS What? =cut =head2 announce Parameters: name value Insert description of subroutine here... =head2 resolve Parameters: name Insert description of subroutine here... =head2 daemon Parameters: none Insert description of subroutine here... =head2 new (constructor) Parameters: class Insert description of constructor here... =head2 listen (method) Parameters: none Insert description of method here... =head2 shout (method) Parameters: none Insert description of method here... =head2 get_message (method) Parameters: timeout Insert description of method here... =head2 send_message (method) Parameters: msg Insert description of method here... =head2 send_and_get_message (method) Parameters: in Insert description of method here...