package DJabberd::Connection::ServerIn;
use strict;
use base 'DJabberd::Connection';
use fields
('announced_dialback',
'verified_remote_domain', # once we know it
);
use DJabberd::Stanza::DialbackResult;
sub set_vhost {
my ($self, $vhost) = @_;
return 0 unless $vhost->{s2s};
return $self->SUPER::set_vhost($vhost);
}
sub peer_domain_is_verified {
my ($self, $domain) = @_;
return $self->{verified_remote_domain}->{$domain};
}
sub on_stream_start {
my ($self, $ss) = @_;
$self->{in_stream} = 1;
### namespace mismatch is a streamerror
unless( $ss->xmlns eq $self->namespace ) {
$self->stream_error(
sprintf "namespace mismatch: client->%s server->%s",
$ss->xmlns, $self->namespace
);
$self->close;
}
if ($ss->announced_dialback) {
$self->{announced_dialback} = 1;
$self->start_stream_back($ss,
extra_attr => "xmlns:db='jabber:server:dialback'",
namespace => 'jabber:server');
} else {
$self->start_stream_back($ss,
namespace => 'jabber:server');
}
}
sub on_stanza_received {
my ($self, $node) = @_;
if ($self->xmllog->is_info) {
$self->log_incoming_data($node);
}
my %class = (
"{jabber:server:dialback}result" => "DJabberd::Stanza::DialbackResult",
"{jabber:server:dialback}verify" => "DJabberd::Stanza::DialbackVerify",
"{jabber:server}iq" => 'DJabberd::IQ',
"{jabber:server}message" => 'DJabberd::Message',
"{jabber:server}presence" => 'DJabberd::Presence',
"{http://etherx.jabber.org/streams}features" => 'DJabberd::Stanza::StreamFeatures',
);
my $class = $class{$node->element} or
return $self->stream_error("unsupported-stanza-type", $node->element);
$DJabberd::Stats::counter{"ServerIn:$class"}++;
# same variable as $node, but down(specific)-classed.
my $stanza = $class->downbless($node, $self);
$self->run_hook_chain(phase => "filter_incoming_server",
deprecated => 1, # yes, we know this is deprecated, but we don't have a vhost always during dialback.
args => [ $stanza ],
methods => {
reject => sub { }, # just stops the chain
},
fallback => sub {
$self->filter_incoming_server_builtin($stanza);
});
}
sub filter_incoming_server_builtin {
my ($self, $stanza) = @_;
unless ($stanza->acceptable_from_server($self)) {
# FIXME: who knows. send something else.
$self->log->error("Stansa of type '$stanza' not acceptable");
$self->stream_error;
return 0;
}
$self->run_hook_chain(phase => "switch_incoming_server",
deprecated => 1, # yes, we know this is deprecated, but we don't have a vhost always during dialback.
args => [ $stanza ],
methods => {
process => sub { $stanza->process($self) },
deliver => sub { $stanza->deliver($self) },
},
fallback => sub {
$stanza->on_recv_from_server($self);
});
}
sub is_server { 1 }
sub namespace {
return "jabber:server";
}
sub dialback_verify_valid {
my $self = shift;
my %opts = @_;
# according to page 45 of the spec we have to send the ID back
my $res = qq{};
$self->log->debug("Dialback verify valid for connection $self->{id}. from=$opts{recv_server}, to=$opts{orig_server}: $res\n");
$self->write($res);
}
sub dialback_verify_invalid {
my $self = shift;
my %opts = @_;
$self->log->warn("Dialback verify invalid for $self, from $opts{orig_server} to $opts{recv_server}, reason: $opts{reason}");
$self->close_stream;
}
sub dialback_result_valid {
my $self = shift;
my %opts = @_;
my $res = qq{};
$self->{verified_remote_domain}->{$opts{orig_server}} = $opts{orig_server};
$self->log->debug("Dialback result valid for connection $self->{id}. from=$opts{recv_server}, to=$opts{orig_server}: $res\n");
$self->write($res);
}
sub dialback_result_invalid {
my $self = shift;
my %opts = @_;
$self->log->warn("Dialback result invalid for $self, from $opts{orig_server} to $opts{recv_server}, reason: $opts{reason}");
$self->close_stream;
}
1;