Ignore:
Timestamp:
Oct 18, 2009, 3:59:29 PM (15 years ago)
Author:
Alex Vandiver <alexmv@mit.edu>
Branches:
master, release-1.10, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
f3678c3
Parents:
99cc3dc
git-author:
Alex Vandiver <alexmv@mit.edu> (03/22/09 02:06:46)
git-committer:
Alex Vandiver <alexmv@mit.edu> (10/18/09 15:59:29)
Message:
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.
Location:
perl/modules/Jabber/lib/BarnOwl/Module
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm

    rf798d02 ra957e92  
    132132
    133133    foreach my $jid ( $conn->getJIDs() ) {
     134
     135        next unless $conn->jidActive($jid) or $conn->tryReconnect($jid);
     136
    134137        my $client = $conn->getConnectionFromJID($jid);
    135 
    136138        unless($client) {
    137139            $conn->removeConnection($jid);
     
    140142        my $status = $client->Process(0); # keep-alive
    141143        if ( !defined($status) ) {
    142             BarnOwl::error("Jabber account $jid disconnected!");
    143             do_logout($jid);
    144             next;
     144            $conn->scheduleReconnect($jid);
    145145        }
    146146        if ($::shutdown) {
     
    383383    }
    384384
    385     if ( $conn->jidExists($jidStr) ) {
     385    if ( $conn->jidActive($jidStr) ) {
    386386        BarnOwl::error("Already logged in as $jidStr.");
    387387        return;
     388    } elsif ($conn->jidExists($jidStr)) {
     389        return $conn->tryReconnect($jidStr, 1);
    388390    }
    389391
     
    453455                BarnOwl::error( "Error in connect: " . join( " ", @result ) );
    454456            } else {
     457                $conn->setAuth(
     458                    $jidStr,
     459                    {   %{ $vars{jlogin_authhash} },
     460                        password => $vars{jlogin_password}
     461                    }
     462                );
    455463                my $roster = $conn->getRosterFromJID($jidStr);
    456464                $roster->fetch();
     
    463471                $client->{fileno} = $client->getSocket()->fileno();
    464472                #queue_admin_msg("Connected to jabber as $fullJid ($client->{fileno})");
    465                 BarnOwl::add_dispatch($client->{fileno}, sub { $client->OwlProcess() });
     473                BarnOwl::add_dispatch($client->{fileno}, sub { $client->OwlProcess($fullJid) });
    466474
    467475                # populate completion from roster.
  • perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm

    r5f3168a ra957e92  
    142142sub OwlProcess {
    143143    my $self = shift;
     144    my $jid = shift || $self->{SESSION}->{FULLJID};
    144145    my $status = $self->Process(0);
    145146    if ( !defined($status) ) {
    146         my $jid = $self->{SESSION}->{FULLJID};
    147         BarnOwl::error("Jabber account $jid disconnected!");
    148         BarnOwl::Module::Jabber::do_logout($jid);
     147        $BarnOwl::Module::Jabber::conn->scheduleReconnect($jid);
    149148    }
     149}
     150
     151=head2 Disconnect
     152
     153Work around a bug in Net::Jabber::Client where Process' return status
     154is not cleared on disconnect.
     155
     156=cut
     157
     158sub Disconnect {
     159    my $self = shift;
     160    delete $self->{PROCESSERROR};
     161    return $self->SUPER::Disconnect(@_);
    150162}
    151163
  • perl/modules/Jabber/lib/BarnOwl/Module/Jabber/ConnectionManager.pm

    r8ff511d ra957e92  
    4141      if $self->{$jidStr}->{Client};
    4242    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";
    4395
    4496    return 1;
     
    88140}
    89141
     142sub jidActive {
     143    my $self = shift;
     144    my $jidStr = shift;
     145    return(exists $self->{$jidStr} and $self->{$jidStr}{Status} eq "available");
     146}
     147
    90148sub sidExists {
    91149    my $self = shift;
     
    110168    my $jid = shift;
    111169    $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID');
    112     return $self->{$jid}->{Client} if exists $self->{$jid};
     170    return $self->{$jid}->{Client} if $self->jidActive($jid);
    113171}
    114172
     
    127185    my $jid = shift;
    128186    $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID');
    129     return $self->{$jid}->{Roster} if exists $self->{$jid};
     187    return $self->{$jid}->{Roster} if $self->jidExists($jid);
    130188}
    131189
Note: See TracChangeset for help on using the changeset viewer.