Changeset a957e9285b443c0e7c978318a7e67324b6085139

Show
Ignore:
Timestamp:
10/18/09 15:59:29 (5 weeks ago)
Author:
Alex Vandiver <alexmv@mit.edu>
git-author:
Alex Vandiver <alexmv@mit.edu> / 2009-03-22T02:06:46Z-0400
Parents:
99cc3dceec1bb97699f4e130556ce22975e39b6f
Children:
f3678c324b8086ca07cd0baaa425a0aa99a75524
git-committer:
Alex Vandiver <alexmv@mit.edu> / 2009-10-18T15:59:29Z-0400
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 modified

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