1 | use warnings; |
---|
2 | use strict; |
---|
3 | |
---|
4 | =head1 NAME |
---|
5 | |
---|
6 | BarnOwl::Module::Jabber::ConnectionManager |
---|
7 | |
---|
8 | =head1 DESCRIPTION |
---|
9 | |
---|
10 | A class to keep track of all the active connection in the barnowl |
---|
11 | jabber module |
---|
12 | |
---|
13 | =cut |
---|
14 | |
---|
15 | package BarnOwl::Module::Jabber::ConnectionManager; |
---|
16 | |
---|
17 | sub new { |
---|
18 | my $class = shift; |
---|
19 | return bless { }, $class; |
---|
20 | } |
---|
21 | |
---|
22 | sub addConnection { |
---|
23 | my $self = shift; |
---|
24 | my $jidStr = shift; |
---|
25 | |
---|
26 | my $client = BarnOwl::Module::Jabber::Connection->new; |
---|
27 | |
---|
28 | $self->{$jidStr}->{Client} = $client; |
---|
29 | $self->{$jidStr}->{Roster} = $client->Roster(); |
---|
30 | $self->{$jidStr}->{Status} = "available"; |
---|
31 | return $client; |
---|
32 | } |
---|
33 | |
---|
34 | sub removeConnection { |
---|
35 | my $self = shift; |
---|
36 | my $jidStr = shift; |
---|
37 | return 0 unless exists $self->{$jidStr}; |
---|
38 | |
---|
39 | BarnOwl::remove_io_dispatch($self->{$jidStr}->{Client}->{fileno}) if $self->{$jidStr}->{Client}->{fileno}; |
---|
40 | $self->{$jidStr}->{Client}->Disconnect() |
---|
41 | if $self->{$jidStr}->{Client}; |
---|
42 | delete $self->{$jidStr}; |
---|
43 | |
---|
44 | return 1; |
---|
45 | } |
---|
46 | |
---|
47 | sub scheduleReconnect { |
---|
48 | my $self = shift; |
---|
49 | my $jidStr = shift; |
---|
50 | return 0 unless exists $self->{$jidStr}; |
---|
51 | BarnOwl::admin_message(Jabber => "Disconnected from jabber account $jidStr"); |
---|
52 | |
---|
53 | unless (BarnOwl::getvar('jabber:reconnect') eq 'on') { |
---|
54 | return $self->removeConnection($jidStr); |
---|
55 | } |
---|
56 | |
---|
57 | BarnOwl::remove_io_dispatch($self->{$jidStr}->{Client}->{fileno}) if $self->{$jidStr}->{Client}->{fileno}; |
---|
58 | $self->{$jidStr}->{Client}->Disconnect() |
---|
59 | if $self->{$jidStr}->{Client}; |
---|
60 | |
---|
61 | $self->{$jidStr}->{Status} = "reconnecting"; |
---|
62 | $self->{$jidStr}->{ReconnectBackoff} = 5; |
---|
63 | $self->{$jidStr}->{ReconnectAt} = time + $self->{$jidStr}->{ReconnectBackoff}; |
---|
64 | return 1; |
---|
65 | } |
---|
66 | |
---|
67 | sub setAuth { |
---|
68 | my $self = shift; |
---|
69 | my $jidStr = shift; |
---|
70 | $self->{$jidStr}->{Auth} = shift; |
---|
71 | } |
---|
72 | |
---|
73 | sub tryReconnect { |
---|
74 | my $self = shift; |
---|
75 | my $jidStr = shift; |
---|
76 | my $force = shift; |
---|
77 | |
---|
78 | return 0 unless exists $self->{$jidStr}; |
---|
79 | return 0 unless $self->{$jidStr}{Status} eq "reconnecting"; |
---|
80 | return 0 unless $force or (time > $self->{$jidStr}{ReconnectAt}); |
---|
81 | |
---|
82 | $self->{$jidStr}->{ReconnectBackoff} *= 2; |
---|
83 | $self->{$jidStr}->{ReconnectBackoff} = 60*5 |
---|
84 | if $self->{$jidStr}->{ReconnectBackoff} > 60*5; |
---|
85 | $self->{$jidStr}->{ReconnectAt} = time + $self->{$jidStr}->{ReconnectBackoff}; |
---|
86 | |
---|
87 | my $status = $self->{$jidStr}->{Client}->Connect; |
---|
88 | return 0 unless $status; |
---|
89 | |
---|
90 | my @result = $self->{$jidStr}->{Client}->AuthSend( %{ $self->{$jidStr}->{Auth} } ); |
---|
91 | if ( !@result || $result[0] ne 'ok' ) { |
---|
92 | $self->removeConnection($jidStr); |
---|
93 | BarnOwl::error( "Error in jabber reconnect: " . join( " ", @result ) ); |
---|
94 | return 0; |
---|
95 | } |
---|
96 | |
---|
97 | BarnOwl::admin_message(Jabber => "Reconnected to jabber as $jidStr"); |
---|
98 | $self->{$jidStr}{Status} = "available"; |
---|
99 | |
---|
100 | foreach my $muc ($self->{$jidStr}->{Client}->MUCs()) { |
---|
101 | $muc->Join($muc->{ARGS}); |
---|
102 | } |
---|
103 | |
---|
104 | return 1; |
---|
105 | } |
---|
106 | |
---|
107 | sub renameConnection { |
---|
108 | my $self = shift; |
---|
109 | my $oldJidStr = shift; |
---|
110 | my $newJidStr = shift; |
---|
111 | return 0 unless exists $self->{$oldJidStr}; |
---|
112 | return 0 if $oldJidStr eq $newJidStr; |
---|
113 | |
---|
114 | $self->{$newJidStr} = $self->{$oldJidStr}; |
---|
115 | delete $self->{$oldJidStr}; |
---|
116 | return 1; |
---|
117 | } |
---|
118 | |
---|
119 | sub connected { |
---|
120 | my $self = shift; |
---|
121 | return scalar keys %{ $self }; |
---|
122 | } |
---|
123 | |
---|
124 | sub getJIDs { |
---|
125 | my $self = shift; |
---|
126 | return keys %{ $self }; |
---|
127 | } |
---|
128 | |
---|
129 | sub jidExists { |
---|
130 | my $self = shift; |
---|
131 | my $jidStr = shift; |
---|
132 | return exists $self->{$jidStr}; |
---|
133 | } |
---|
134 | |
---|
135 | sub baseJIDExists { |
---|
136 | my $self = shift; |
---|
137 | my $jidStr = shift; |
---|
138 | my $jid = new Net::Jabber::JID; |
---|
139 | $jid->SetJID($jidStr); |
---|
140 | my $baseJID = $jid->GetJID('base'); |
---|
141 | |
---|
142 | foreach my $cjidStr ( keys %{ $self } ) { |
---|
143 | my $cJID = new Net::Jabber::JID; |
---|
144 | $cJID->SetJID($cjidStr); |
---|
145 | return $cjidStr if ($cJID->GetJID('base') eq $baseJID); |
---|
146 | } |
---|
147 | return 0; |
---|
148 | } |
---|
149 | |
---|
150 | sub jidActive { |
---|
151 | my $self = shift; |
---|
152 | my $jidStr = shift; |
---|
153 | return(exists $self->{$jidStr} and $self->{$jidStr}{Status} eq "available"); |
---|
154 | } |
---|
155 | |
---|
156 | sub sidExists { |
---|
157 | my $self = shift; |
---|
158 | my $sid = shift || ""; |
---|
159 | foreach my $c ( values %{ $self } ) { |
---|
160 | return 1 if ($c->{Client}->{SESSION}->{id} eq $sid); |
---|
161 | } |
---|
162 | return 0; |
---|
163 | } |
---|
164 | |
---|
165 | sub getConnectionFromSid { |
---|
166 | my $self = shift; |
---|
167 | my $sid = shift; |
---|
168 | foreach my $c (values %{ $self }) { |
---|
169 | return $c->{Client} if $c->{Client}->{SESSION}->{id} eq $sid; |
---|
170 | } |
---|
171 | return undef; |
---|
172 | } |
---|
173 | |
---|
174 | sub getConnectionFromJID { |
---|
175 | my $self = shift; |
---|
176 | my $jid = shift; |
---|
177 | $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID'); |
---|
178 | return $self->{$jid}->{Client} if $self->jidActive($jid); |
---|
179 | } |
---|
180 | |
---|
181 | sub getRosterFromSid { |
---|
182 | my $self = shift; |
---|
183 | my $sid = shift; |
---|
184 | foreach my $c (values %{ $self }) { |
---|
185 | return $c->{Roster} |
---|
186 | if $c->{Client}->{SESSION}->{id} eq $sid; |
---|
187 | } |
---|
188 | return undef; |
---|
189 | } |
---|
190 | |
---|
191 | sub getRosterFromJID { |
---|
192 | my $self = shift; |
---|
193 | my $jid = shift; |
---|
194 | $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID'); |
---|
195 | return $self->{$jid}->{Roster} if $self->jidExists($jid); |
---|
196 | } |
---|
197 | |
---|
198 | |
---|
199 | 1; |
---|