source: perl/modules/Jabber/lib/BarnOwl/Module/Jabber/ConnectionManager.pm @ a957e92

release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since a957e92 was a957e92, checked in by Alex Vandiver <alexmv@mit.edu>, 12 years ago
Make Jabber try to reconnect when disconnected, at exponential intervals Make the ConnectionManager store auth information on connect, and use that auth information to try to reconnect and re-auth. Use some simple exponential backoff, capped at 5 minutes, as intervals for reconnecting.
  • Property mode set to 100644
File size: 4.6 KB
Line 
1use warnings;
2use strict;
3
4=head1 NAME
5
6BarnOwl::Module::Jabber::ConnectionManager
7
8=head1 DESCRIPTION
9
10A class to keep track of all the active connection in the barnowl
11jabber module
12
13=cut
14
15package BarnOwl::Module::Jabber::ConnectionManager;
16
17sub new {
18    my $class = shift;
19    return bless { }, $class;
20}
21
22sub 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
34sub removeConnection {
35    my $self = shift;
36    my $jidStr = shift;
37    return 0 unless exists $self->{$jidStr};
38
39    BarnOwl::remove_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
47sub 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    BarnOwl::remove_dispatch($self->{$jidStr}->{Client}->{fileno}) if $self->{$jidStr}->{Client}->{fileno};
54    $self->{$jidStr}->{Client}->Disconnect()
55      if $self->{$jidStr}->{Client};
56
57    $self->{$jidStr}->{Status} = "reconnecting";
58    $self->{$jidStr}->{ReconnectBackoff} = 5;
59    $self->{$jidStr}->{ReconnectAt} = time + $self->{$jidStr}->{ReconnectBackoff};
60    return 1;
61}
62
63sub setAuth {
64    my $self = shift;
65    my $jidStr = shift;
66    $self->{$jidStr}->{Auth} = shift;
67}
68
69sub tryReconnect {
70    my $self = shift;
71    my $jidStr = shift;
72    my $force = shift;
73
74    return 0 unless exists $self->{$jidStr};
75    return 0 unless $self->{$jidStr}{Status} eq "reconnecting";
76    return 0 unless $force or (time > $self->{$jidStr}{ReconnectAt});
77
78    $self->{$jidStr}->{ReconnectBackoff} *= 2;
79    $self->{$jidStr}->{ReconnectBackoff} = 60*5
80        if $self->{$jidStr}->{ReconnectBackoff} > 60*5;
81    $self->{$jidStr}->{ReconnectAt} = time + $self->{$jidStr}->{ReconnectBackoff};
82
83    my $status = $self->{$jidStr}->{Client}->Connect;
84    return 0 unless $status;
85
86    my @result = $self->{$jidStr}->{Client}->AuthSend( %{ $self->{$jidStr}->{Auth} } );
87    if ( !@result || $result[0] ne 'ok' ) {
88        $self->removeConnection($jidStr);
89        BarnOwl::error( "Error in jabber reconnect: " . join( " ", @result ) );
90        return 0;
91    }
92
93    BarnOwl::admin_message(Jabber => "Reconnected to jabber as $jidStr");
94    $self->{$jidStr}{Status} = "available";
95
96    return 1;
97}
98
99sub renameConnection {
100    my $self = shift;
101    my $oldJidStr = shift;
102    my $newJidStr = shift;
103    return 0 unless exists $self->{$oldJidStr};
104    return 0 if $oldJidStr eq $newJidStr;
105
106    $self->{$newJidStr} = $self->{$oldJidStr};
107    delete $self->{$oldJidStr};
108    return 1;
109}
110
111sub connected {
112    my $self = shift;
113    return scalar keys %{ $self };
114}
115
116sub getJIDs {
117    my $self = shift;
118    return keys %{ $self };
119}
120
121sub jidExists {
122    my $self = shift;
123    my $jidStr = shift;
124    return exists $self->{$jidStr};
125}
126
127sub baseJIDExists {
128    my $self = shift;
129    my $jidStr = shift;
130    my $jid = new Net::Jabber::JID;
131    $jid->SetJID($jidStr);
132    my $baseJID = $jid->GetJID('base');
133
134    foreach my $cjidStr ( keys %{ $self } ) {
135        my $cJID = new Net::Jabber::JID;
136        $cJID->SetJID($cjidStr);
137        return $cjidStr if ($cJID->GetJID('base') eq $baseJID);
138    }
139    return 0;
140}
141
142sub jidActive {
143    my $self = shift;
144    my $jidStr = shift;
145    return(exists $self->{$jidStr} and $self->{$jidStr}{Status} eq "available");
146}
147
148sub sidExists {
149    my $self = shift;
150    my $sid = shift || "";
151    foreach my $c ( values %{ $self } ) {
152        return 1 if ($c->{Client}->{SESSION}->{id} eq $sid);
153    }
154    return 0;
155}
156
157sub getConnectionFromSid {
158    my $self = shift;
159    my $sid = shift;
160    foreach my $c (values %{ $self }) {
161        return $c->{Client} if $c->{Client}->{SESSION}->{id} eq $sid;
162    }
163    return undef;
164}
165
166sub getConnectionFromJID {
167    my $self = shift;
168    my $jid = shift;
169    $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID');
170    return $self->{$jid}->{Client} if $self->jidActive($jid);
171}
172
173sub getRosterFromSid {
174    my $self = shift;
175    my $sid = shift;
176    foreach my $c (values %{ $self }) {
177        return $c->{Roster}
178          if $c->{Client}->{SESSION}->{id} eq $sid;
179    }
180    return undef;
181}
182
183sub getRosterFromJID {
184    my $self = shift;
185    my $jid = shift;
186    $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID');
187    return $self->{$jid}->{Roster} if $self->jidExists($jid);
188}
189
190
1911;
Note: See TracBrowser for help on using the repository browser.