summaryrefslogtreecommitdiff
path: root/Ivy.pm
diff options
context:
space:
mode:
authormertz2000-12-21 16:39:25 +0000
committermertz2000-12-21 16:39:25 +0000
commitd828648644ee3f4bec0ba5d559848c4858c33700 (patch)
tree16299c1771ffd7100f15591ac6bb239fb4a85197 /Ivy.pm
parent803b22c9ab3a282c10ae8cda996921b00c26c56d (diff)
downloadivy-perl-d828648644ee3f4bec0ba5d559848c4858c33700.zip
ivy-perl-d828648644ee3f4bec0ba5d559848c4858c33700.tar.gz
ivy-perl-d828648644ee3f4bec0ba5d559848c4858c33700.tar.bz2
ivy-perl-d828648644ee3f4bec0ba5d559848c4858c33700.tar.xz
* This version is compatible again with version 3 of Ivy.
Thats means it can be used again without ivy object. This has been documented in the man pages. However it is preferable to create Ivy objects. * \s and ^\s in regexp are now correctly expanded as tab and blank characters * regular expressions are now case-insensitive (the same as ivy-c!) Of course, case of parameters transmitted on the bus are preserved! * an implementation of ivyprobe is given as an example and as a test tool /usr/bin/ivyprobe.pl -h for more infos. * when :port is used as a domain/port ivy-perl now really do connect to the 127:port bus. * man pages have been enhanced. Some features not yet documented are now (mainly sendDirect / bindDirect / fileEvent). * the stop method works now also with applications written with the C version of ivy. However the hack may not be the good solution!
Diffstat (limited to 'Ivy.pm')
-rw-r--r--Ivy.pm153
1 files changed, 117 insertions, 36 deletions
diff --git a/Ivy.pm b/Ivy.pm
index 13bfe9f..31e7872 100644
--- a/Ivy.pm
+++ b/Ivy.pm
@@ -7,6 +7,7 @@
# Authors: Alexandre Bustico <bustico@cena.fr>
# Stéphane Chatty <chatty@cena.fr>
# Hervé Damiano <damiano@cena.fr>
+# Christophe Mertz <mertz@cena.fr>
#
# All functions
#
@@ -37,7 +38,7 @@ use Time::Gettimeofday;
use vars qw($VERSION);
-$VERSION = '4.5';
+$VERSION = '4.6';
#############################################################################
#### PROTOTYPES #####
@@ -125,7 +126,7 @@ sub _pong ($$); # (fd)
sub _tkFileEvent ($$); # associe un fd a un callback pour la mainloop tk
sub _scanAfter () ; # parse si il faut appeler un callback associe a un after
sub _myCanRead (); # interface au select
-sub _scanConnStatus ($); # verifie les connections effectuees et
+sub _scanConnStatus ($$$$); # verifie les connections effectuees et
# appelle la fonction $statusFunc
sub _inetAdrByName ($$); # transforme une adresse inet native en chaine
# $host:$port
@@ -136,7 +137,7 @@ sub _parseIvyBusParam ($); # prends une adresse de bus de la forme
# un numero de port et une ref sur une
# liste d'adresses addr_inet
-sub _substituteEscapedChar ($$); #permet de transormer une regexp etendue
+sub _substituteEscapedChar ($$); #permet de transformer une regexp etendue
# 'perl' en regexp de base
#############################################################################
@@ -169,8 +170,8 @@ use constant MAX_TIMOUT => 1000;
# ne pas mettre un \n dans une chaine entre "" car l'\n sera interprete.
use constant REG_PERLISSISME => ('w' => '[a-zA-Z0-9_]',
'W' => '[^a-zA-Z0-9_]',
- 's' => '[ ]',
- 'S' => '[^ ]',
+ 's' => '[\t ]',
+ 'S' => '[^\t ]',
'd' => '[0-9]',
'D' => '[^0-9]',
'n' => '', # Il ne faut pas mettre d'\n :
@@ -264,7 +265,6 @@ use constant statusFunc => $constantIndexer++;
use constant supSock => $constantIndexer++;
use constant connSock => $constantIndexer++;
use constant sockList => $constantIndexer++;
-use constant queueList => $constantIndexer++;
use constant threadList => $constantIndexer++;
use constant appliList => $constantIndexer++;
use constant sendRegList => $constantIndexer++;
@@ -393,12 +393,12 @@ sub new ($%)
# liste des applis necessaires a l'appli locale
$self->[neededApp] = [];
- # callback prenant en param 2 refs sur des listes :
- # [applis presentes, appli absentes]
+ # callback prenant en param 3 refs sur des listes :
+ # [applis presentes, appli absentes, hash_applis_present]
# cette fonction est appelee :
# - tout les pollingTime tant que toutes les applis
# ne sont pas presentes
- # - des que toutes les applis sont presentes
+ # - des qu'une appli se connecte
# - lorsqu'une appli se deconnecte
$self->[statusFunc] = '';
@@ -543,11 +543,14 @@ sub DESTROY ($)
# pour toutes les connections
foreach my $fd (values %{$self->[sockList]}) {
- next unless exists ($self->[queueList]->{$fd});
-
foreach my $fd (values %{$self->[sockList]}) {
- send ($fd, sprintf (MSG_FMT, BYE, 0, ""), 0)
- or $self->_removeFileDescriptor ($fd);
+# send ($fd, sprintf (MSG_FMT, BYE, 0, ""), 0)
+# or $self->_removeFileDescriptor ($fd);
+ # the 2 previous lines seems to works with other ivy-perl applis
+ # but DONOT work with ivy-c api.
+ # the 2 next lines works. This has to been validated! CM 21/12/2000
+ send ($fd, sprintf (MSG_FMT, BYE, 0, ""), 0);
+ $self->_removeFileDescriptor ($fd);
}
}
@@ -616,7 +619,7 @@ sub start
Proto => 'udp',
Type => SOCK_DGRAM,
Reuse => 1);
-
+
$self->[supSock]->sockopt (SO_BROADCAST, 1);
@@ -942,7 +945,7 @@ sub fileEvent ($$;$)
} else {
# deleting the handler
delete $localBindByHandle{$fd};
- # print ("DBG: Ivy::fileEvent : removing fd from the select\n");
+# print ("DBG: Ivy::fileEvent : removing fd from the select\n");
$localLoopSel->remove ($fd);
}
}
@@ -1163,7 +1166,7 @@ sub _getMessages ($$)
$self->[sendRegList]{$appSock}->[$id] = eval <<'_EOL_';
sub {
use strict;
- if (my @args = ${$_[0]} =~ /($valeurs)/o) {
+ if (my @args = ${$_[0]} =~ /($valeurs)/io) {
shift @args;
$args[$#args] .= "\003" if @args;
send ($appSock, sprintf (MSG_FMT,
@@ -1206,7 +1209,8 @@ _EOL_
push @{$self->[appliList]{$senderName}}, $appSock;
}
- $self->_scanConnStatus ();
+ my $host = (gethostbyaddr ($addr, AF_INET))[0] ;
+ $self->_scanConnStatus ($senderName, "new", "$host");
}
elsif ($type == APP_NAME) {
# etat Connecte
@@ -1377,12 +1381,15 @@ sub _removeFileDescriptor ($$)
}
#printf "DBG> _removeFileDescriptor : deconnection de %s ($diedAppName)\n", _inetAdrByName ($diedAppName);
-
+
delete $self->[cnnxion]{$addrInet};
# on vire l'entree correspondant a ce canal dans la liste des
# regexps par canal
- $self->_scanConnStatus () ;
+
+ my $addr = substr ($addrInet,0,4);
+ my $host = (gethostbyaddr ($addr, AF_INET))[0] ;
+ $self->_scanConnStatus ($diedAppName, "died", $host) ;
}
@@ -1473,9 +1480,9 @@ sub _scanAfter ()
############### METHODE SCAN CONN STATUS
-sub _scanConnStatus ($)
+sub _scanConnStatus ($$$$)
{
- my $self = shift;
+ my ($self, $appname, $status, $addr) = @_;
my (%readyApp, @nonReadyApp);
@@ -1495,7 +1502,7 @@ sub _scanConnStatus ($)
# applis presentes, comme valeur le nombre d'applis ayant ce nom,
# de facon a detecter plus facilement quand il y a trop d'applis
# de meme nom sur le meme bus.
- &{$self->[statusFunc]} ([keys %readyApp], \@nonReadyApp, \%readyApp);
+ &{$self->[statusFunc]} ([keys %readyApp], \@nonReadyApp, \%readyApp, $appname, $status, $addr);
}
@@ -1546,6 +1553,7 @@ sub _parseIvyBusParam ($)
my @broadcastAddrs = split (',', $ivyNetworks);
foreach my $netAddr (@broadcastAddrs) {
+ print "netAddr=$netAddr\n";
$netAddr = BROADCAST_ADDRS if
(($netAddr eq '') || ($netAddr =~ /^127/) ||
($netAddr =~ /^loopback/));
@@ -1584,6 +1592,19 @@ sub _parseIvyBusParam ($)
push (@ivyAddrInet, pack_sockaddr_in ($ivyPort, $netAddrInet));
}
+
+ unless (scalar @ivyAddrInet) {
+ push (@ivyAddrInet, pack_sockaddr_in ($ivyPort, inet_aton(BROADCAST_ADDRS)));
+ }
+
+ foreach my $ivyAddr (@ivyAddrInet) {
+ my ($port, $iaddr) = unpack_sockaddr_in($ivyAddr);
+ my $iaddrH = unpack ("H8",$iaddr);
+ my $iaddrInt = join (".", unpack ("C4", $iaddr));
+
+ print "Broadcasting on network $iaddrInt ($iaddrH) on port $ivyPort\n";
+ }
+
return ($ivyPort, \@ivyAddrInet);
}
@@ -1629,6 +1650,8 @@ When you quit your application don't forget to call 'exit' class methods.
=head2 Ivy->init(...)
+Ivy::init(...)
+
Allows one to define global parameters which may be used as default ones
at object creation time.
@@ -1647,8 +1670,11 @@ Name of your application used to identify on ivy bus.
=item B<-ivyBus =E<gt> 'domain 1,...,domain n:port number'>
-A list of domains, followed by port number where to broadcast messages.
-Default is 127:2010
+A list of domains (may be empty), followed by a port number where to broadcast messages.
+If the domain list is empty (i.e. parameter is ':port number'), broadcast will be done
+on localhost (i.e. '127:port number'). Default is the value of the environment variable
+IVYBUS and if it is not defined the default is 127:2010.
+
=item B<-messWhenReady =E<gt> 'your message when ready'>
@@ -1746,18 +1772,27 @@ before running.
=item B<-statusFunc =E<gt> sub {}>
-A callback which will be called until every needed app is present on the bus.
+A callback which will be called every time an appli is connected or deconnected on the bus.
Your callback could be:
sub MyCallback {
- my ($present, $absent, %present) = @_;
-
+ my ($present, $absent, %present, $appname, $status, $host) = @_;
+ # $status is either new or died
+
foreach my $remoteapp (keys %present) {
if ($present{$remoteapp} > 1) {
print "n apps $remoteapp are presents on bus\n";
}
}
+ if ($status eq "new") {
+ print "$appname connected from $host\n";
+ }
+ elsif ($status eq "died") {
+ print "$appname disconnected from $host\n";
+ }
+ }
+
Example:
@@ -1774,15 +1809,21 @@ Local main events loop. Use it if you don't use the Tk library.
=head2 $ivyobj->stop;
+Ivy::stop;
+
=head1 OBJECT METHODS
=head2 $ivyobj->start;
+Ivy::start;
+
You must call this after you are ready to communicate through an Ivy bus
and before you really communicate.
=head2 $ivyobj->sendMsgs(@messages);
+Ivy::sendMsgs(@messages);
+
Send a list of messages
Example :
@@ -1791,6 +1832,8 @@ Example :
=head2 $ivyobj->sendAppNameMsgs(@messages);
+Ivy::sendAppNameMsgs(@messages);
+
Send a list of messages preceded by your application's name.
Example :
@@ -1800,19 +1843,24 @@ Example :
=head2 $ivyobject->bindRegexp($regexp, [\&callback, @cb_parameters]);
+Ivy::bindRegexp($regexp, [\&callback, @cb_parameters]);
+
=head2 $ivyobject->bindRegexp($regexp, [$an_obj, \&method, @cb_parameters]);
+Ivy::bindRegexp($regexp, [$an_obj, \&method, @cb_parameters]);
+
This allows you to bind a regular expression to a
callback or method. The callback or method will be called for every
-message that matches the regexp. See perlre(1) to find how to write regexps.
+message that matches the regexp (case insensitive).
+See perlre(1) to find how to write regexps.
Use the bracketing construct ( ... ) so that your callback is
called with the captured bits of text as parameters.
Example :
$ivyobject->bindRegexp("\w+ (\d+)", [\&callback, @cb_parameters]);
- # You callback will be called with one more parameter which will be
- # a number precedeed by a word, because of bracketed regexp.
+ # Your callback will be called with one more parameter which will be
+ # the name of appli who send the message
Your callback and method must be like:
@@ -1830,51 +1878,84 @@ Your callback and method must be like:
=head2 $ivyobj->sendDirectMsgs($to, $id, @msgs);
-Send a message but Ask Alex to find what are $to and $id
+Ivy::sendDirectMsgs($to, $id, @msgs);
+
+Send a message a message to appli $to. This appli must have done a bindDirect before to accept this message. regexp matching is not used with direct Messages
=head2 $ivyobj->bindDirect($regexp, $id, [\&callback, @cb_parameters]);
-=head2 $ivyobj->bindDirect($regexp, $id, [$an_obj, \&method, @cb_parameters]);
+Ivy::bindDirect($id, [\&callback, @cb_parameters]);
+
+The callback will be called with both the @msgs and the @cb_parameters.
+
+Example :
+
+ $ivyobject->bindDirectMessage("id1", [\&callback, @cb_parameters]);
+
+Your callback and method must be like:
+
+ sub cb {
+ my (@cb_parameters, @msgs) = @_;
+ ...
+ }
-Same as bindRegexp method but Ask Alex to find what is $id.
+ sub method {
+ my ($self, @cb_parameters, @msgs) = @_;
+ ...
+ }
=head2 $ivyobj->sendDieTo($to)
+Ivy::sendDieTo($to)
+
Send a suicide to the application named $to.
=head2 $ivyobj->ping($to, $timeout);
+Ivy::ping($to, $timeout);
+
Send a ping message and wait until timeout to receive a pong.
=head2 $after_id = $ivyobj->after($timeAfter, \@callbacks_list);
+$after_id = Ivy::after($timeAfter, \@callbacks_list);
+
Call a list of callbacks after $timeAfter milliseconds.
=head2 $repeat_id = $ivyobj->repeat($timeAfter, \@callbacks_list);
+$repeat_id = Ivy:repeat($timeAfter, \@callbacks_list);
+
Have a list of callbacks repeatedly called every $timeAfter milliseconds.
=head2 $ivyobj->afterCancel($after_or_repeat_id);
+Ivy::afterCancel($after_or_repeat_id);
+
Cancel an after callback call.
=head2 $ivyobj->fileEvent($fd, $cb);
-Ask Alex
+Ivy::fileEvent($fd, $cb);
+
+Add a fileEvent handler (or remove any handler associated to $fd if $cb paramter is omitted).
+The callback $cb will get the filehandle $fd as parameter.
=head2 $ivyobj->DESTROY;
=head1 BUGS
+The stop method does not work!
No know bugs at this time. Report them to author.
=head1 SEE ALSO
-perl(1), perlre(1)
+perl(1), perlre(1), ivyprobe.pl(1)
=head1 AUTHORS
-Alexandre Bustico <bustico@cena.fr>, Herve Damiano <damiano@cena.fr>
+Alexandre Bustico <bustico@cena.fr>, Herve Damiano <damiano@cena.fr>,
+Stephane Chtatty <chatty@cena.fr>, Christophe Mertz <mertz@@cena.fr>
=head1 COPYRIGHT