DJabberd

 view release on metacpan or  search on metacpan

lib/DJabberd/Delivery/ComponentConnection.pm  view on Meta::CPAN


    $self->_prepare_connection();
}

sub deliver {
    my ($self, $vhost, $cb, $stanza) = @_;

    if ($self->_can_deliver_stanza($stanza)) {
        if (my $conn = $self->connection) {
            $conn->write_stanza($stanza);
        }
        else {
            # If we've currently got no connection at all,
            # let's throw a wobbly.
            # FIXME: Could this get into an infinite loop in some cases? Probably.
            $stanza->make_error_response('503', 'cancel', 'service-unavailable')->deliver($vhost);
        }
        return $cb->delivered;
    }
    else {
        return $cb->decline;
    }

}

sub _i_am_the_component {
    return $_[0]->{i_am_the_component};
}

sub _can_deliver_stanza {
    my ($self, $stanza) = @_;
    
    # If we're the component, we want to offload anything with a domain
    # other than our own. If we aren't the component, the reverse is true.
    my $same_host = ($stanza->to_jid->domain eq $self->vhost->server_name);
    
    return $self->_i_am_the_component ? ! $same_host : $same_host;
}

sub connection {
    return $_[0]->{connection};
}

sub _prepare_connection {
    my ($self) = @_;
    
    if ($self->_i_am_the_component) {
        $self->_start_connection($self);
    }
    else {
        $self->_start_listener($self);
    }
}

sub _start_connection {
    my ($self) = @_;
    
    my $vhost = $self->vhost;
    
    my $connection = DJabberd::Connection::ComponentOut->new(
        endpoint => DJabberd::IPEndPoint->new($self->{remoteaddr}, $self->{remoteport}),
        vhost => $vhost,
        secret => $self->{secret},
    );
    $connection->watch_read(1);
    $connection->add_connect_handler(sub {
        $logger->debug("Connection established and channel open.");
        $self->{connection} = $connection;
    });
    $connection->add_disconnect_handler(sub {
        # FIXME: Maybe this delay should get exponentially longer each retry?
        # We're probably only connecting to localhost anyway, so I shant bother for now.
        $logger->debug("Outgoing connection was lost. Will attempt to re-establish it in 30 seconds.");

        Danga::Socket->AddTimer(30, sub {
            $self->{connection} = undef;
            $self->_prepare_connection();
        });
    });

}

sub _start_listener {
    my ($self) = @_;
    my $vhost = $self->vhost;
    
    my $bindaddr = $self->{listenaddr};

    # FIXME: Maybe shouldn't duplicate all of this code out of DJabberd.pm.
    
    my $server;
    my $not_tcp = 0;
    if ($bindaddr =~ m!^/!) {
        $not_tcp = 1;
        $server = IO::Socket::UNIX->new(
            Type   => SOCK_STREAM,
            Local  => $bindaddr,
            Listen => 10
        );
        $logger->logdie("Error creating UNIX domain socket $bindaddr: $@") unless $server;
        $logger->info("Started listener for component ".$self->domain." on UNIX domain socket $bindaddr");
    } else {
        $server = IO::Socket::INET->new(
            LocalAddr => $bindaddr,
            Type      => SOCK_STREAM,
            Proto     => IPPROTO_TCP,
            Blocking  => 0,
            Reuse     => 1,
            Listen    => 10
        );
        $logger->logdie("Error creating listen socket for <$bindaddr>: $@") unless $server;
        $logger->info("Started listener for component ".$self->domain." on TCP socket <$bindaddr>");
    }

    # Brad thinks this is necessary under Perl 5.6, and who am I to argue?
    IO::Handle::blocking($server, 0);
    
    $self->{listener} = $server;

    my $accept_handler = sub {
        my $csock = $server->accept;



( run in 1.048 second using v1.01-cache-2.11-cpan-ceb78f64989 )