+sub max
+{
+ return $max;
+}
+
+#
+# this routine handles the possible adding of an entry in the routing
+# table. It will only add an entry if it is new. It may have all sorts of
+# other side effects which may include fixing up other links.
+#
+# It will return a node object if (and only if) it is a completely new
+# object with that callsign. The upper layers are expected to do something
+# sensible with this!
+#
+# called as $parent->add(call, dxchan, version, flags)
+#
+
+sub add
+{
+ my $parent = shift;
+ my $call = uc shift;
+ confess "Route::add trying to add $call to myself" if $call eq $parent->{call};
+ my $self = get($call);
+ if ($self) {
+ $self->_addparent($parent->{call});
+ $parent->_addnode($call);
+ return undef;
+ }
+ $parent->_addnode($call);
+ $self = $parent->new($call, @_);
+ return $self;
+}
+
+#
+# this routine is the opposite of 'add' above.
+#
+# It will return an object if (and only if) this 'del' will remove
+# this object completely
+#
+
+sub del
+{
+ my $self = shift;
+ my $pref = shift;
+
+ # delete parent from this call's parent list
+ my $pcall = $pref->{call};
+ my $ref = $self->_delparent($pcall);
+ my @nodes;
+
+ # is this the last connection?
+ $self->_del_users;
+ unless (@$ref) {
+ push @nodes, $self->del_nodes;
+ delete $list{$self->{call}};
+ push @nodes, $self;
+ }
+ return @nodes;
+}
+
+
+sub _del_users
+{
+ my $self = shift;
+ for (@{$self->{users}}) {
+ my $ref = Route::User::get($_);
+ $ref->del($self) if $ref;
+ }
+ $self->{users} = [];
+}
+
+# remove all sub nodes from this parent
+sub del_nodes
+{
+ my $self = shift;
+ my @nodes;
+
+ for (@{$self->{nodes}}) {
+ next if $self->{call} eq $_;
+ push @nodes, $self->del_node($_);
+ }
+ return @nodes;
+}
+
+# delete a node from this node (ie I am a parent)
+sub del_node
+{
+ my $self = shift;
+ my $ncall = shift;
+ my @out;
+ $self->_delnode($ncall);
+ if (my $ref = get($ncall)) {
+ foreach my $rcall (@{$ref->{nodes}}) {
+ next if $rcall eq $ncall || $rcall eq $self->{call};
+ push @out, $ref->del_node($rcall);
+ }
+ push @out, $ref->del($self);
+ }
+ return @out;
+}
+
+# add a user to this node
+sub add_user
+{
+ my $self = shift;
+ my $ucall = shift;
+ $self->_adduser($ucall);
+
+ $self->{usercount} = scalar @{$self->{users}};
+ my $uref = Route::User::get($ucall);
+ my @out = (Route::User->new($ucall, $self->{call}, @_)) unless $uref;
+ return @out;
+}
+
+# delete a user from this node
+sub del_user
+{
+ my $self = shift;
+ my $ucall = shift;
+ my $ref = Route::User::get($ucall);
+ $self->_deluser($ucall);
+ my @out = $ref->del($self) if $ref;
+ return @out;
+}
+
+sub usercount
+{
+ my $self = shift;
+ if (@_ && @{$self->{users}} == 0) {
+ $self->{usercount} = shift;
+ }
+ return $self->{usercount};
+}
+
+sub users
+{
+ my $self = shift;
+ return @{$self->{users}};
+}
+
+sub nodes
+{
+ my $self = shift;
+ return @{$self->{nodes}};
+}
+
+sub rnodes
+{
+ my $self = shift;
+ my @out;
+ foreach my $call (@{$self->{nodes}}) {
+ next if grep $call eq $_, @_;
+ push @out, $call;
+ my $r = get($call);
+ push @out, $r->rnodes(@_, @out) if $r;
+ }
+ return @out;
+}
+
+