From: Dirk Koopman <djk@tobit.co.uk>
Date: Thu, 26 Jun 2008 19:25:21 +0000 (+0100)
Subject: send talks to every node a user is logged in to
X-Git-Tag: 1.56~73
X-Git-Url: http://dxspider.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=ba799b8ac9feef688cff478a4006399b6dfc183f;p=spider.git

send talks to every node a user is logged in to

If a user is on more than one node, a talk will be sent to each of those
nodes. Before it would only go to the first node in the routing table.
---

diff --git a/perl/DXProtHandle.pm b/perl/DXProtHandle.pm
index 166d5643..e19688bb 100644
--- a/perl/DXProtHandle.pm
+++ b/perl/DXProtHandle.pm
@@ -1836,6 +1836,42 @@ sub handle_92
 	$self->broadcast_route_pc9x($pcall, undef, $line, 0);
 }
 
+# get all the routes for a thing, bearing in mind that the thing (e.g. a user)
+# might be on two or more nodes at the same time or that there may be more than
+# one equal distance neighbour to a node.
+#
+# What this means that if sh/route g1tlh shows that he is on (say) two nodes, then
+# a Route::findroutes is done on each of those two nodes, the best route(s) taken from
+# each and then combined to give a set of dxchans to send the PC9x record down
+#
+sub find_pc9x_routes
+{
+	my $to = shift;
+	my $ref = Route::get($to);
+	my @parent;
+	my %cand;
+
+	if ($ref->isa('Route::User')) {
+		my $dxchan = DXChannel::get($to);
+		push @parent, $to if $dxchan;
+		push @parent, @{$ref->parent};
+	} else {
+		@parent = $to;
+	}
+	foreach my $p (@parent) {
+		my $lasthops;
+		my @routes = Route::findroutes($p);
+		foreach my $r (@routes) {
+			$lasthops = $r->[0] unless defined $lasthops;
+			if ($r->[0] == $lasthops) {
+				$cand{$r->[1]->call} = $r->[1];
+			} else {
+				last;
+			}
+		}
+	}
+	return values %cand;
+}
 
 sub handle_93
 {
@@ -1896,45 +1932,26 @@ sub handle_93
 	# if it is routeable then then treat it like a talk
 	my $ref = Route::get($to);
 	if ($ref) {
-		# local talks
 		my $dxchan;
-		$dxchan = DXChannel::get($main::myalias) if $to eq $main::mycall;
-		$dxchan = DXChannel::get($to) unless $dxchan;
-		# check it...
-		if ($dxchan) {
-			if (ref $dxchan && $dxchan->isa('DXChannel')) {
-				if ($dxchan->is_user) {
-					$dxchan->talk($from, $to, $via, $text, $onode);
-					return;
-				}
-			} else {
-				dbg("ERROR: $to -> $dxchan is not a DXChannel! (local talk)");
-			}
-		}
 
-		# convert to PC10 talks where appropriate
+		# convert to PC10 or local talks where appropriate
 		# PC93 capable nodes of the same hop count all get a copy
 		# if there is a PC10 node then it will get a copy and that
 		# will be it. Hopefully such a node will not figure highly
 		# in the route list, unless it is local, 'cos it don't issue PC92s!
-		my @routes = Route::findroutes($to);
+		# note that both local and PC93s at the same time are possible if the
+		# user on more than one node.
+		my @routes = find_pc9x_routes($to);
 		my $lasthops;
-		foreach my $r (@routes) {
-			$lasthops = $r->[0] unless defined $lasthops;
-			if ($r->[0] == $lasthops) {
-				$dxchan = $r->[1];
-				if (ref $dxchan && $dxchan->isa('DXChannel')) {
-					if ($dxchan->{do_pc9x}) {
-						$dxchan->send($line);
-					} else {
-						$dxchan->talk($from, $to, $via, $text, $onode);
-						last;
-					}
+		foreach $dxchan (@routes) {
+			if (ref $dxchan && $dxchan->isa('DXChannel')) {
+				if ($dxchan->{do_pc9x}) {
+					$dxchan->send($line);
 				} else {
-					dbg("ERROR: $to -> $dxchan is not a DXChannel! (convert to pc10)");
+					$dxchan->talk($from, $to, $via, $text, $onode);
 				}
 			} else {
-				last;
+				dbg("ERROR: $to -> $dxchan is not a DXChannel! (convert to pc10)");
 			}
 		}
 		return;
diff --git a/perl/Route.pm b/perl/Route.pm
index 3c1c453e..eb83af11 100644
--- a/perl/Route.pm
+++ b/perl/Route.pm
@@ -289,29 +289,33 @@ sub get
 sub findroutes
 {
 	my $call = shift;
+	my %cand;
 	my @out;
 
 	dbg("ROUTE: findroutes $call") if isdbg('findroutes');
 
-	# return immediately if we are directly connected
+	my $nref = Route::get($call);
+	return () unless $nref;
+
+	# we are directly connected, force "best possible" priority, but
+	# carry on in case user is connected on other nodes.
 	my $dxchan = DXChannel::get($call);
 	if ($dxchan) {
 		dbg("ROUTE: findroutes $call -> directly connected") if isdbg('findroutes');
-		return [99, $dxchan];
+		$cand{$call} = 99;
 	}
 
-	my $nref = Route::get($call);
-	return () unless $nref;
-
 	# obtain the dxchannels that have seen this thingy
 	my @parent = $nref->isa('Route::User') ? @{$nref->{parent}} : $call;
-	my %cand;
 	foreach my $p (@parent) {
-		# return immediately if we are directly connected or a user's parent node is
+		next if $p eq $main::mycall; # this is dealt with above
+
+		# deal with directly connected nodes, again "best priority"
 		$dxchan = DXChannel::get($p);
 		if ($dxchan) {
 			dbg("ROUTE: findroutes $call -> connected direct via parent $p") if isdbg('findroutes');
-			return [99, $dxchan];
+			$cand{$p} = 99;
+			next;
 		}
 
 		my $r = Route::Node::get($p);
diff --git a/perl/Version.pm b/perl/Version.pm
index 2a1927aa..96e37485 100644
--- a/perl/Version.pm
+++ b/perl/Version.pm
@@ -11,6 +11,6 @@ use vars qw($version $subversion $build);
 
 $version = '1.55';
 $subversion = '0';
-$build = '22';
+$build = '23';
 
 1;