+ my $thing = shift;
+ my $dxchan = shift;
+ my $class;
+ my $sub;
+
+ if (@_) {
+ $class = shift;
+ } elsif ($dxchan->isa('DXChannel')) {
+ $class = ref $dxchan;
+ }
+
+ # BEWARE!!!!!
+ no strict 'refs';
+
+ # do output filtering
+ if ($thing->can('out_filter')) {
+ return unless $thing->out_filter($dxchan);
+ }
+
+ # before send (and line generation) things
+ # function must return true to make the send happen
+ $sub = "before_send_$class";
+ if ($thing->can($sub)) {
+ return unless $thing->$sub($dxchan);
+ }
+
+ # generate the protocol line which may (or not) be cached
+ my $ref;
+ unless ($ref = $thing->{class}) {
+ $sub = "gen_$class";
+ $ref = $thing->$sub($dxchan) if $thing->can($sub);
+ }
+ $dxchan->send(ref $ref ? @$ref : $ref) if $ref;
+
+ # after send
+ if ($thing->can('after_send_all')) {
+ $thing->after_send_all($dxchan);
+ } else {
+ $sub = "after_send_$class";
+ $thing->$sub($dxchan) if $thing->can($sub);
+ }
+}
+
+#
+# This is the main routing engine for the new protocol. Broadcast is a slight
+# misnomer, because if it thinks it can route it down one or interfaces, it will.
+#
+# It handles anything it recognises as a callsign, sees if it can find it in a
+# routing table, and if it does, then routes the message.
+#
+# If it can't then it will broadcast it.
+#
+sub broadcast
+{
+ my $thing = shift;
+ dbg("Thingy::broadcast: " . $thing->ascii) if isdbg('thing');
+
+ my @dxchan;
+ my $to ||= $thing->{route};
+ $to ||= $thing->{touser};
+ $to ||= $thing->{group};
+ if ($to && is_callsign($to) && (my $ref = Route::get($to))) {
+ dbg("Thingy::broadcast: routing for $to") if isdbg('thing');
+ @dxchan = $ref->alldxchan;
+ } else {
+ @dxchan = DXChannel::get_all();
+ }
+
+ dbg("Thingy::broadcast: offered " . join(',', map {$_->call} @dxchan)) if isdbg('thing');
+
+ foreach my $dxchan (@dxchan) {
+ next if $dxchan == $main::me;
+ next if grep $dxchan == $_, @_;
+ next if $dxchan->{call} eq $thing->{origin};
+ next if $thing->{user} && !$dxchan->is_user && $dxchan->{call} eq $thing->{user};
+
+ dbg("Thingy::broadcast: sending to $dxchan->{call}") if isdbg('thing');
+ $thing->send($dxchan);
+ }