DJabberd
view release on metacpan or search on metacpan
lib/DJabberd.pm view on Meta::CPAN
use DJabberd::Connection::OldSSLClientIn;
use DJabberd::Connection::Admin;
use DJabberd::Stanza::StartTLS;
use DJabberd::Stanza::SASL;
use DJabberd::Stanza::StreamFeatures;
use DJabberd::Stanza::DialbackVerify;
use DJabberd::Stanza::DialbackResult;
use DJabberd::JID;
use DJabberd::IQ;
use DJabberd::Message;
use DJabberd::Presence;
use DJabberd::StreamVersion;
use DJabberd::Log;
use DJabberd::Delivery::Local;
use DJabberd::Delivery::S2S;
use DJabberd::PresenceChecker::Local;
use DJabberd::Stats;
package DJabberd;
use strict;
use Socket qw(IPPROTO_TCP TCP_NODELAY SOL_SOCKET SOCK_STREAM);
use Carp qw(croak);
use DJabberd::Util qw(tsub as_bool as_num as_abs_path as_bind_addr);
our $VERSION = '0.85';
our $logger = DJabberd::Log->get_logger();
our $hook_logger = DJabberd::Log->get_logger("DJabberd::Hook");
our %server;
$SIG{USR2} = sub { Carp::cluck("USR2") };
sub new {
my ($class, %opts) = @_;
my $self = {
'daemonize' => delete $opts{daemonize},
's2s_port' => delete $opts{s2s_port},
'c2s_port' => delete($opts{c2s_port}) || 5222, # {=clientportnumber}
'old_ssl' => delete $opts{old_ssl},
'vhosts' => {},
'fake_peers' => {}, # for s2s testing. $hostname => "ip:port"
'share_parsers' => 1,
'monitor_host' => {},
};
# if they set s2s_port to explicitly 0, it's disabled for all vhosts
# but not setting it means 5269 still listens, if vhosts are configured
# for s2s.
# {=serverportnumber}
$self->{s2s_port} = 5269 unless defined $self->{s2s_port};
croak("Unknown server parameters: " . join(", ", keys %opts)) if %opts;
bless $self, $class;
$server{$self} = $self;
Scalar::Util::weaken($server{$self});
return $self;
}
sub DESTROY {
delete $server{$_[0]};
}
# class method
sub foreach_vhost {
my (undef, $cb) = @_;
foreach my $server (values %DJabberd::server) {
foreach my $vhost (values %{$server->{vhosts}}) {
$cb->($vhost);
}
}
}
sub share_parsers { $_[0]{share_parsers} };
sub set_config_shareparsers {
my ($self, $val) = @_;
$self->{share_parsers} = as_bool($val);
}
sub set_config_declaremonitor {
my ($self, $val) = @_;
$self->{monitor_host}{$val} = 1;
}
# mimicing Apache's SSLCertificateKeyFile config
sub set_config_sslcertificatekeyfile {
my ($self, $val) = @_;
$self->{ssl_private_key_file} = as_abs_path($val);
}
# mimicing Apache's SSLCertificateFile
sub set_config_sslcertificatefile {
my ($self, $val) = @_;
$self->{ssl_cert_file} = as_abs_path($val);
}
# mimicing Apache's SSLCertificateChainFile
sub set_config_sslcertificatechainfile {
my ($self, $val) = @_;
$self->{ssl_cert_chain_file} = as_abs_path($val);
}
sub ssl_private_key_file { return $_[0]{ssl_private_key_file} }
sub ssl_cert_file { return $_[0]{ssl_cert_file} }
sub ssl_cert_chain_file { return $_[0]{ssl_cert_chain_file} }
sub set_config_oldssl {
my ($self, $val) = @_;
$self->{old_ssl} = as_bool($val);
}
sub set_config_unixdomainsocket {
my ($self, $val) = @_;
$self->{unixdomainsocket} = $val;
lib/DJabberd.pm view on Meta::CPAN
$fake_peers{$host} = $ipendpt;
}
sub fake_s2s_peer {
my ($self, $host) = @_;
return $fake_peers{$host};
}
sub set_config_casesensitive {
my ($self, $val) = @_;
$DJabberd::JID::CASE_SENSITIVE = as_bool($val);
}
sub add_vhost {
my ($self, $vhost) = @_;
my $sname = lc $vhost->name;
if (my $existing = $self->{vhosts}{$sname}) {
croak("Can't set vhost with name '$sname'. Already exists in this server.")
if $existing != $vhost;
}
if ($vhost->server && $vhost->server != $self) {
croak("Vhost already has a server.");
}
$vhost->setup_default_plugins;
$self->{vhosts}{$sname} = $vhost;
$vhost->set_server($self);
}
# works as Server method or class method.
sub lookup_vhost {
my ($self, $hostname) = @_;
# look at all server objects in process
unless (ref $self) {
foreach my $server (values %DJabberd::server) {
my $vh = $server->lookup_vhost($hostname);
return $vh if $vh;
}
return 0;
}
# method on server object
foreach my $vhost (values %{$self->{vhosts}}) {
return $vhost
if ($vhost->handles_domain($hostname));
}
return 0;
}
# return the version of the spec we implement
sub spec_version {
my $self = shift;
return $self->{_spec_version} ||= DJabberd::StreamVersion->new("1.0");
}
my %obj_source; # refaddr -> file/linenumber
my %obj_living; # file/linenumber -> ct
use Scalar::Util qw(refaddr weaken);
use Data::Dumper;
sub dump_obj_stats {
print Dumper(\%obj_living);
my %class_ct;
foreach (values %obj_source) {
$class_ct{ref($_->[1])}++;
}
print Dumper(\%class_ct);
}
sub track_new_obj {
return unless $ENV{TRACKOBJ};
my ($class, $obj) = @_;
my $i = 0;
my $fileline;
while (!$fileline) {
$i++;
my ($pkg, $filename, $line, $subname) = caller($i);
next if $subname eq "new";
$fileline = "$filename/$line";
}
my $addr = refaddr($obj);
warn "New object $obj -- $fileline\n" if $ENV{TRACKOBJ};
$obj_source{$addr} = [$fileline, $obj];
weaken($obj_source{$addr}[1]);
$obj_living{$fileline}++;
dump_obj_stats() if $ENV{TRACKOBJ};
}
sub track_destroyed_obj {
return unless $ENV{TRACKOBJ};
my ($class, $obj) = @_;
my $addr = refaddr($obj);
my $fileline = $obj_source{$addr}->[0] or die "Where did $obj come from?";
delete $obj_source{$addr};
warn "Destroyed object $obj -- $fileline\n" if $ENV{TRACKOBJ};
$obj_living{$fileline}--;
dump_obj_stats() if $ENV{TRACKOBJ};
}
sub debug {
my $self = shift;
return unless $self->{debug};
printf STDERR @_;
}
sub run {
my $self = shift;
daemonize() if $self->{daemonize};
local $SIG{'PIPE'} = "IGNORE"; # handled manually
if ($self->{pid_file}) {
$logger->debug("Logging PID to file $self->{pid_file}");
open(PIDFILE,'>',$self->{pid_file}) or $logger->logdie("Can't open pidfile $self->{pid_file} for writing");
print PIDFILE "$$\n";
close(PIDFILE);
}
$self->start_c2s_server();
# {=s2soptional}
$self->start_s2s_server() if $self->{s2s_port};
$self->start_cluster_server() if $self->{cluster_listen};
$self->_start_server($self->{admin_port}, "DJabberd::Connection::Admin") if $self->{admin_port};
DJabberd::Connection::Admin->on_startup;
Danga::Socket->EventLoop();
unlink($self->{pid_file}) if (-f $self->{pid_file});
}
sub _start_server {
my ($self, $localaddr, $class) = @_;
# establish SERVER socket, bind and listen.
my $server;
my $not_tcp = 0;
if ($localaddr =~ m!^/!) {
$not_tcp = 1;
$server = IO::Socket::UNIX->new(Type => SOCK_STREAM,
Local => $localaddr,
Listen => 10)
or $logger->logdie("Error creating unix domain socket: $@\n");
} else {
( run in 1.946 second using v1.01-cache-2.11-cpan-99c4e6809bf )