From d828648644ee3f4bec0ba5d559848c4858c33700 Mon Sep 17 00:00:00 2001 From: mertz Date: Thu, 21 Dec 2000 16:39:25 +0000 Subject: * 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! --- Ivy.pm | 153 +++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file 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 # Stéphane Chatty # Hervé Damiano +# Christophe Mertz # # 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 '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 'your message when ready'> @@ -1746,18 +1772,27 @@ before running. =item B<-statusFunc =E 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 , Herve Damiano +Alexandre Bustico , Herve Damiano , +Stephane Chtatty , Christophe Mertz =head1 COPYRIGHT -- cgit v1.1