Ticket #90: reconnect.patch

File reconnect.patch, 13.7 kB (added by valerio, 4 months ago)

Implemented automatic reconnection

  • src/network/msnsocketbase.h

     
    5656    , ERROR_DROP                   /// The connection was dropped 
    5757    , ERROR_DATA                   /// An error within the data was received 
    5858    , ERROR_CONNECTION_TIME_LIMIT  /// The connection was not successful within the time limit 
     59    , ERROR_CONNECTION_OTHER       /// The current account has connected from elsewhere, disconnecting us 
    5960    , ERROR_AUTH_TIME_LIMIT        /// The authentication/login was not successful within the time limit 
     61    , ERROR_AUTH_LOGIN             /// The authentication/login failed due to wrong username or password 
    6062    /// The next are server-reported errors 
    6163    , ERROR_USER                   /// An error caused by the user 
    6264    , ERROR_SERVER                 /// Server error 
  • src/network/msnsockettcp.cpp

     
    2222#include <QHostAddress> 
    2323 
    2424#include <KLocale> 
    25 #include <KMessageBox> 
    2625 
    2726#include "../currentaccount.h" 
    2827#include "../kmessdebug.h" 
     
    384383  // Assume the connection was lost when 3 pings are missed. 
    385384  if ( missedPings_ == 3 ) 
    386385  { 
    387     KMessageBox::error( 0, i18n("The connection to the server was lost.") ); 
    388     disconnectFromServer( false ); 
     386    // Bounce back to the unified error handler to disconnect and give the user a message 
     387    emit error( i18n( "The connection to the server was lost" ), MsnSocketBase::ERROR_DROP ); 
    389388  } 
    390389 
    391390  writeData( "PNG\r\n" ); 
  • src/network/msnnotificationconnection.cpp

     
    13081308 
    13091309 
    13101310 
    1311 // Received notice of disconnetion from the server 
     1311// Received notice of disconnection from the server 
    13121312void MsnNotificationConnection::gotOut(const QStringList& command) 
    13131313{ 
    1314   // If the first word is "OTH", it means that this user connected from elsewhere. 
    1315   if ( command[1] == "OTH" ) 
     1314  // If the first command parameter is "OTH", it means that this account has connected from elsewhere. 
     1315  if( command[1] == "OTH" ) 
    13161316  { 
    1317     KMessageBox::error( 0, i18n("<p>You have been disconnected!</p><p>You connected with this account from another Messenger client, or from another location.</p>") ); 
     1317    slotError( i18n( "<p>You have been disconnected!</p>" 
     1318                     "<p>You connected with this account from another Messenger client," 
     1319                     "or from another location.</p>" ), 
     1320               MsnSocketBase::ERROR_CONNECTION_OTHER ); 
     1321 
     1322    // Don't try reconnecting when connected from elsewhere. 
    13181323  } 
     1324  else 
     1325  { 
     1326    closeConnection(); 
    13191327 
    1320   closeConnection(); 
     1328    // Try connecting again 
     1329    emit reconnect( currentAccount_->getHandle() ); 
     1330  } 
    13211331} 
    13221332 
    13231333 
     
    18901900  // NOTE: a similar thing also happens in soapRequestFailed(), 
    18911901  // but for fatal SOAP errors. 
    18921902 
    1893   // Show a message to the user, before deleting the object! 
    1894   KMessageBox::error( 0, i18n("Authentication failed, please verify your account name and password.") ); 
    1895  
    1896   // Close the connection attempt. 
    1897   closeConnection(); 
     1903  slotError( i18n("<p>Authentication has failed, please verify your account name and password.</p>"), MsnSocketBase::ERROR_AUTH_LOGIN ); 
    18981904} 
    18991905 
    19001906 
     
    32103216  kWarning() << "KMess Error ( type" << type << "):" << error << "!"; 
    32113217 
    32123218  int result; 
     3219  bool tryReconnecting = true; 
    32133220  QString additionalInfo; 
    32143221  QString dialogTitle = i18nc( "Error dialog box title", "MSN error" ); 
    32153222 
     
    32323239  // Then decide what kind of message to show 
    32333240  switch( type ) 
    32343241  { 
     3242      // Notify that connecting has failed due to a wrong handle or password 
     3243    case MsnSocketBase::ERROR_CONNECTION_OTHER: 
     3244    case MsnSocketBase::ERROR_AUTH_LOGIN: 
     3245      KMessageBox::error( 0, i18nc( "Connection error dialog box", "%1", error ), dialogTitle ); 
     3246      // Do not attempt to reconnect 
     3247      tryReconnecting = false; 
     3248      break; 
     3249 
    32353250    case MsnSocketBase::ERROR_CONNECTION_TIME_LIMIT: 
    32363251    case MsnSocketBase::ERROR_CONNECTING: 
    32373252      // Continue as for authentication errors if the switch to HTTP had failed 
     
    32663281    case MsnSocketBase::ERROR_DATA: 
    32673282    case MsnSocketBase::ERROR_UNKNOWN: 
    32683283    default: 
    3269       KMessageBox::error(0, i18nc( "Connection error message, with more details for developer versions", 
    3270                                    "<p>Connection to the MSN server has been lost.%1</p>", additionalInfo ), dialogTitle ); 
     3284      KMessageBox::error( 0, i18nc( "Connection error message, with more details for developer versions", 
     3285                                    "<p>Connection to the MSN server has been lost.%1</p>", additionalInfo ), dialogTitle ); 
    32713286      break; 
    32723287  } 
     3288 
     3289  // Try connecting again 
     3290  if( tryReconnecting ) 
     3291  { 
     3292    emit reconnect( currentAccount_->getHandle() ); 
     3293  } 
    32733294} 
    32743295 
    32753296 
  • src/network/msnnotificationconnection.h

     
    329329    void                 contactAddedUser(const Contact *contact); 
    330330    // Signal that a new email has been received 
    331331    void                 newEmail(QString sender, QString subject, bool inInbox, QString command, QString folder, QString url); 
     332    // Signal that the connection should be established again after a disconnection 
     333    void                 reconnect( QString handle ); 
    332334    // A new switchboard with a contact has been opened 
    333335    void                 startSwitchboard( const ChatInformation &chatInfo ); 
    334336 
  • src/kmess.cpp

     
    16951695  connect( initialView_, SIGNAL(                                  disconnectClicked() ), 
    16961696           this,         SLOT  (                                  disconnectClicked() ) ); 
    16971697 
    1698   connect( msnNotificationConnection_, SIGNAL( statusMessage(QString,bool) ), 
    1699            initialView_,               SLOT  ( statusMessage(QString)      ) ); 
     1698  connect( msnNotificationConnection_, SIGNAL(            reconnect(QString)      ), 
     1699           initialView_,               SLOT  ( scheduleReconnection(QString)      ) ); 
     1700  connect( msnNotificationConnection_, SIGNAL(        statusMessage(QString,bool) ), 
     1701           initialView_,               SLOT  (        statusMessage(QString)      ) ); 
    17001702 
    17011703 
    17021704  // Set it as the window's main widget 
  • src/initialview.cpp

     
    2929#include <KLocale> 
    3030#include <KStandardDirs> 
    3131 
     32/** 
     33 * Reconnection timeout 
     34 * 
     35 * This number is the time, expressed in seconds, after which a connection is attempted again 
     36 */ 
     37#ifndef RECONNECTION_TIME 
     38  #define RECONNECTION_TIME        30 
     39#endif 
    3240 
    3341 
     42 
    3443// The constructor 
    3544InitialView::InitialView( QWidget *parent ) 
    3645 : QWidget( parent ) 
    3746 , Ui::InitialView() 
     47 , hasNetworkConnection_() 
    3848 , isConnecting_( false ) 
    3949{ 
    4050  // Set up the UI first 
     
    110120  connect( AccountsManager::instance(), SIGNAL( passwordsReady() ), 
    111121           this,                        SLOT  (     updateView() ) ); 
    112122 
     123  // When the reconnection timer fires, update the timer in the UI or connect if it's time to 
     124  connect( &reconnectTimer_,            SIGNAL(   timeout() ), 
     125           this,                        SLOT  ( reconnect() ) ); 
     126 
    113127  // The status is needed only later 
    114128  statusLabel_->hide(); 
    115129 
     
    195209 
    196210 
    197211/** 
     212 * @brief Connect again after being disconnected 
     213 * 
     214 * This method updates the timer in the UI and connects if the time has passed 
     215 */ 
     216void InitialView::reconnect() 
     217{ 
     218  int elapsedTime = ( reconnectElapsedTime_.elapsed() / 1000 ); 
     219 
     220  if( elapsedTime <= RECONNECTION_TIME ) 
     221  { 
     222    statusMessage( i18n( "Reconnecting in %1 seconds...", ( RECONNECTION_TIME - elapsedTime ) ) ); 
     223    return; 
     224  } 
     225 
     226#ifdef KMESSDEBUG_INITIALVIEW 
     227  kDebug() << "Starting reconnection."; 
     228#endif 
     229 
     230  // The time has passed, try connecting again 
     231  reconnectTimer_.stop(); 
     232 
     233  // This is needed to force the Connect button to behave like a Connect button 
     234  isConnecting_ = false; 
     235 
     236  // Connect to the selected account 
     237  slotConnectClicked(); 
     238} 
     239 
     240 
     241 
     242/** 
     243 * @brief Automatically reconnect with a specified account 
     244 * 
     245 * This method schedules a timed reconnection to an account 
     246 * 
     247 * @param handle  The email address of the account to reconnect 
     248 */ 
     249void InitialView::scheduleReconnection( QString handle ) 
     250{ 
     251#ifdef KMESSDEBUG_INITIALVIEW 
     252  kDebug() << "Scheduling reconnection for account" << handle; 
     253#endif 
     254 
     255  Account *account = accounts_[ handle ]; 
     256  if( account == 0 ) 
     257  { 
     258#ifdef KMESSDEBUG_INITIALVIEW 
     259    kDebug() << "Account not found, aborting."; 
     260#endif 
     261    return; 
     262  } 
     263 
     264  // If the network connection goes down, reconnect after it comes back up 
     265  doReconnectWithAccount_ = handle; 
     266  if( isConnecting_ || ! hasNetworkConnection_ ) 
     267  { 
     268#ifdef KMESSDEBUG_INITIALVIEW 
     269    kDebug() << "Cannot schedule a reconnection now, postponing the action." 
     270                "(is connecting:" << isConnecting_ << ",has network:" << hasNetworkConnection_ << ")"; 
     271#endif 
     272    return; 
     273  } 
     274 
     275  // Change the UI to the connecting mode 
     276  startedConnecting( handle ); 
     277 
     278  // Start the timed reconnection mechanism 
     279  reconnectElapsedTime_.start(); 
     280  reconnectTimer_.start(); 
     281 
     282  // Change the text of the Connect button 
     283  connectButton_->setText( i18n( "&Cancel" ) ); 
     284} 
     285 
     286 
     287 
     288/** 
    198289 * @brief Update the view when the network connection status changes 
    199290 * 
    200291 * This method receives KDE's Solid network connection status changes, and updates the view's widgets 
     
    205296void InitialView::slotConnectionStatusChanged( Solid::Networking::Status newStatus ) 
    206297{ 
    207298  // If Solid is unable to retrieve the status, assume we're connected 
    208   bool isConnected = ( newStatus == Solid::Networking::Connected || newStatus == Solid::Networking::Unknown ); 
     299  hasNetworkConnection_ = ( newStatus == Solid::Networking::Connected || newStatus == Solid::Networking::Unknown ); 
    209300 
    210   connectButton_->setEnabled( isConnected ); 
     301#ifdef KMESSDEBUG_INITIALVIEW 
     302  if( newStatus == Solid::Networking::Unknown ) 
     303  { 
     304    kDebug() << "Cannot determine network status from Solid, assuming we're connected."; 
     305  } 
     306  else 
     307  { 
     308    kDebug() << "The network connection is now" << (hasNetworkConnection_?"active":"disabled") << "."; 
     309  } 
     310#endif 
    211311 
    212   if( isConnected && ! isConnecting_ ) 
     312  connectButton_->setEnabled( hasNetworkConnection_ ); 
     313 
     314  if( hasNetworkConnection_ ) 
    213315  { 
    214     statusLabel_->setVisible( false ); 
    215     statusMessage( QString() ); 
     316    if( ! isConnecting_ ) 
     317    { 
     318#ifdef KMESSDEBUG_INITIALVIEW 
     319      kDebug() << "Was not connecting, enabling back the UI."; 
     320#endif 
     321      setEnabled( true ); 
     322 
     323      if( ! doReconnectWithAccount_.isEmpty() ) 
     324      { 
     325#ifdef KMESSDEBUG_INITIALVIEW 
     326        kDebug() << "Reconnection was needed."; 
     327#endif 
     328        scheduleReconnection( doReconnectWithAccount_ ); 
     329      } 
     330    } 
    216331  } 
    217332  else 
    218333  { 
    219334    if( isConnecting_ ) 
    220335    { 
     336#ifdef KMESSDEBUG_INITIALVIEW 
     337      kDebug() << "Was trying to connect, stopping."; 
     338#endif 
    221339      // Force a disconnection 
    222340      connectButton_->click(); 
    223341    } 
    224342 
     343    // Avoid the reconnection timer to try connecting even if no connection is available 
     344    reconnectTimer_.stop(); 
     345 
     346    setEnabled( false ); 
    225347    statusLabel_->setVisible( true ); 
    226348    statusMessage( i18n("Internet connection not available.") ); 
    227349  } 
  • src/initialview.h

     
    2222#include "contact/msnstatus.h" 
    2323 
    2424#include <QHash> 
     25#include <QTime> 
     26#include <QTimer> 
    2527 
    2628#include <Solid/Networking> 
    2729 
     
    6264  public slots: // Public slots 
    6365    // A profile was selected from the drop-down list, or written manually. 
    6466    void                 updateView(); 
     67    // Automatically reconnect with a specified account 
     68    void                 scheduleReconnection( QString handle ); 
    6569    // Change the connection status text 
    6670    void                 statusMessage( QString text ); 
    6771 
     
    7074    QString              getSelectedHandle() const; 
    7175    // The "remember account" checkbox change its state 
    7276    void                 rememberAccountStateChanged( int state ); 
     77    // Connect again after being disconnected 
     78    void                 reconnect(); 
    7379    // Enable or disable the widgets when we're connecting or waiting 
    7480    void                 setEnabled( bool isEnabled ); 
    7581    // The connect/disconnect button has been clicked 
     
    8692    KConfigGroup         config_; 
    8793    // The default handle to display 
    8894    QString              defaultHandle_; 
     95    // Whether a reconnection should be scheduled after a network connection comes back up 
     96    QString              doReconnectWithAccount_; 
     97    // Whether there is an active network connection or not 
     98    bool                 hasNetworkConnection_; 
    8999    // Whether the UI is set up for connection or waiting for the login data 
    90100    bool                 isConnecting_; 
    91101    // Loader for icons 
    92102    KIconLoader         *loader_; 
     103    // Time elapsed after the reconnection schedulation 
     104    QTime                reconnectElapsedTime_; 
     105    // Timer for reconnection 
     106    QTimer               reconnectTimer_; 
    93107 
    94108  signals: // Public signals 
    95109    // Connect with the given account