// Berkeley Open Infrastructure for Network Computing // http://boinc.berkeley.edu // Copyright (C) 2005 University of California // // This is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any later version. // // This software is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // To view the GNU Lesser General Public License visit // http://www.gnu.org/copyleft/lesser.html // or write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #if defined(__GNUG__) && !defined(__APPLE__) #pragma implementation "BOINCDialUpManager.h" #endif #include "stdwx.h" #include "network.h" #include "BOINCGUIApp.h" #include "diagnostics.h" #include "error_numbers.h" #include "BOINCDialUpManager.h" #include "DlgOptions.h" #include "DlgDialupCredentials.h" CBOINCDialUpManager::CBOINCDialUpManager() { m_pDialupManager = wxDialUpManager::Create(); wxASSERT(m_pDialupManager->IsOk()); ResetReminderTimers(); m_bSetConnectionTimer = false; m_bNotifyConnectionAvailable = false; m_bConnectedSuccessfully = false; m_bResetTimers = false; m_bWasDialing = false; m_iNetworkStatus = 0; m_iConnectAttemptRetVal = 0; // Construct the default dialog title for dial-up messages // // %s is the application name // i.e. 'BOINC Manager', 'GridRepublic Manager' m_strDialogTitle.Printf( _("%s - Network Status"), wxGetApp().GetBrand()->GetApplicationName().c_str() ); } CBOINCDialUpManager::~CBOINCDialUpManager() { delete m_pDialupManager; } bool CBOINCDialUpManager::IsOk() { return m_pDialupManager->IsOk(); } size_t CBOINCDialUpManager::GetISPNames(wxArrayString& names) { return m_pDialupManager->GetISPNames(names); } void CBOINCDialUpManager::poll() { CMainDocument* pDoc = wxGetApp().GetDocument(); CMainFrame* pFrame = wxGetApp().GetFrame(); bool bIsDialing = false; bool bIsOnline = false; bool bWantConnection = false; bool bWantDisconnect = false; int iNetworkStatus = 0; wxString strDialogMessage = wxEmptyString; // We are ready to rock and roll. if (pDoc) { wxASSERT(wxDynamicCast(pDoc, CMainDocument)); wxASSERT(wxDynamicCast(pFrame, CMainFrame)); // cache the various states // The dialup manager tells us if we are still dialing or if we have // successfully connected. IsNetworkAlive/IsOnline both report the // success or failure of the dialup device to establish a connection // to the outside world. pDoc->rpc.network_status(iNetworkStatus); bIsDialing = m_pDialupManager->IsDialing(); bIsOnline = iNetworkStatus == 0 ? true : false; bWantConnection = iNetworkStatus == 1 ? true : false; bWantDisconnect = iNetworkStatus == 2 ? true : false; // The timers are used to keep from spamming the user with the same // messages over each iteration of the poll loop. we only need to // reset them during a connect event in case we randomly loose // a connection. if (m_bResetTimers) { wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - Resetting dial-up notification timers")); m_bResetTimers = false; m_bSetConnectionTimer = false; ResetReminderTimers(); } // Log out the trace information for debugging purposes. /* wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - Dialup Flags")); wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - -- bIsOnline = '%d', bIsDialing = '%d', m_bWasDialing = '%d', iNetworkStatus = '%d', bWantConnection = '%d'"), bIsOnline, bIsDialing, m_bWasDialing, iNetworkStatus, bWantConnection ); wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - -- m_bResetTimers = '%d', m_bNotifyConnectionAvailable = '%d', m_bConnectedSuccessfully = '%d'"), m_bResetTimers, m_bNotifyConnectionAvailable, m_bConnectedSuccessfully ); wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - -- confirm_before_connecting = '%d', hangup_if_dialed = '%d'"), pDoc->state.global_prefs.confirm_before_connecting, pDoc->state.global_prefs.hangup_if_dialed ); */ if (!bIsOnline && !bIsDialing && !m_bWasDialing && bWantConnection) { wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - !bIsOnline && !bIsDialing && !m_bWasDialing && bWantConnection")); if (!pFrame->IsShown()) { // BOINC Manager is hidden and displaying a dialog might interupt what they // are doing. NotifyUserNeedConnection(); } else { // BOINC Manager is visable and can process user input. m_bSetConnectionTimer = true; Connect(); } } else if (!bIsDialing && !m_bWasDialing) { // We are not doing anything now, were we up to something before? if (bIsOnline && m_bConnectedSuccessfully && m_bNotifyConnectionAvailable) { // Ah ha, we are online and we initiated the connection, so we need to // notify the CC that the network is available. wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - bIsOnline && m_bConnectedSuccessfully && m_bNotifyConnectionAvailable")); NetworkAvailable(); } else if (bWantDisconnect && m_bConnectedSuccessfully) { // We are online, and the CC says it is safe to disconnect. Since we // initiated the connection we need to disconnect now. wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - bWantDisconnect && m_bConnectedSuccessfully")); Disconnect(); } } else if (!bIsDialing && m_bWasDialing) { // We initiated a connection attempt and now we are either online or failed to // connect because of a modem error or a users credentials were wrong. wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - !bIsDialing && m_bWasDialing")); if (m_bSetConnectionTimer) { m_bSetConnectionTimer = false; m_dtDialupConnectionTimeout = wxDateTime::Now(); m_iConnectAttemptRetVal = ERR_NO_NETWORK_CONNECTION; } wxTimeSpan tsTimeout = wxDateTime::Now() - m_dtDialupConnectionTimeout; if (30 > tsTimeout.GetSeconds()) { if(m_iConnectAttemptRetVal != BOINC_SUCCESS) { if (m_iConnectAttemptRetVal != ERR_IN_PROGRESS) { // Attempt to successfully download the Google homepage pDoc->rpc.lookup_website(LOOKUP_GOOGLE); } m_iConnectAttemptRetVal = pDoc->rpc.lookup_website_poll(); return; } } m_bWasDialing = false; m_bResetTimers = true; if (!m_iConnectAttemptRetVal) { ConnectionSucceeded(); } else { ConnectionFailed(); } } else if (bIsDialing && !m_bWasDialing) { // Setup the state machine so that it knows when we have finished the connection // attempt. wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - bIsDialing && !m_bWasDialing")); m_bWasDialing = true; } } } int CBOINCDialUpManager::NotifyUserNeedConnection() { CMainFrame* pFrame = wxGetApp().GetFrame(); wxTimeSpan tsLastDialupAlertSent; wxString strDialogMessage = wxEmptyString; wxASSERT(pFrame); wxASSERT(wxDynamicCast(pFrame, CMainFrame)); tsLastDialupAlertSent = wxDateTime::Now() - m_dtLastDialupAlertSent; if (tsLastDialupAlertSent.GetSeconds() >= (pFrame->GetReminderFrequency() * 60)) { wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::NotifyUserNeedConnection - Manager not shown, notify instead")); m_dtLastDialupAlertSent = wxDateTime::Now(); // 1st %s is the project name // i.e. 'BOINC', 'GridRepublic' // 2st %s is the application name // i.e. 'BOINC Manager', 'GridRepublic Manager' strDialogMessage.Printf( _("%s needs a connection to the Internet to perform some " "maintenance, open the %s to connect up and " "perform the needed work."), wxGetApp().GetBrand()->GetProjectName().c_str(), wxGetApp().GetBrand()->GetApplicationName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_INFORMATION, true ); } return 0; } int CBOINCDialUpManager::Connect() { CMainDocument* pDoc = wxGetApp().GetDocument(); CMainFrame* pFrame = wxGetApp().GetFrame(); wxTimeSpan tsLastDialupRequest; int iAnswer; wxString strDialogMessage = wxEmptyString; wxASSERT(pDoc); wxASSERT(pFrame); wxASSERT(wxDynamicCast(pDoc, CMainDocument)); wxASSERT(wxDynamicCast(pFrame, CMainFrame)); tsLastDialupRequest = wxDateTime::Now() - m_dtLastDialupRequest; if (tsLastDialupRequest.GetSeconds() >= (pFrame->GetReminderFrequency() * 60)) { wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::Connect - Begin connection process")); m_dtLastDialupRequest = wxDateTime::Now(); if(pFrame->GetDialupConnectionName().size()) { // We have a valid connection name that we can dial. if(pDoc->state.global_prefs.confirm_before_connecting) { // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s needs to connect to the Internet.\nMay it do so now?"), wxGetApp().GetBrand()->GetProjectName().c_str() ); iAnswer = ::wxMessageBox( strDialogMessage, m_strDialogTitle, wxYES_NO | wxICON_QUESTION, pFrame ); } else { // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s is connecting to the Internet."), wxGetApp().GetBrand()->GetProjectName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_INFORMATION, true ); iAnswer = wxYES; } // Are we allow to connect? if (wxYES == iAnswer) { m_bNotifyConnectionAvailable = true; m_bConnectedSuccessfully = false; m_pDialupManager->Dial( pFrame->GetDialupConnectionName(), wxEmptyString, wxEmptyString, true ); } } else { // The user hasn't given us a valid connection to dial. Inform them // that we need a connection and that they may need to set a default // connection. // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s is unable to communicate with a project and no default connection is specified.\n" "Please connect up to the Internet or specify a default connection via the connections\n" "tab in the Options dialog off of the advanced menu."), wxGetApp().GetBrand()->GetProjectName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_INFORMATION, false ); } } return 0; } int CBOINCDialUpManager::ConnectionSucceeded() { CMainFrame* pFrame = wxGetApp().GetFrame(); wxString strDialogMessage = wxEmptyString; wxASSERT(pFrame); wxASSERT(wxDynamicCast(pFrame, CMainFrame)); // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s has successfully connected to the Internet."), wxGetApp().GetBrand()->GetProjectName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_INFORMATION, true ); m_bConnectedSuccessfully = true; return 0; } int CBOINCDialUpManager::ConnectionFailed() { CMainFrame* pFrame = wxGetApp().GetFrame(); wxString strDialogMessage = wxEmptyString; wxASSERT(pFrame); wxASSERT(wxDynamicCast(pFrame, CMainFrame)); // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s failed to connect to the Internet."), wxGetApp().GetBrand()->GetProjectName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_ERROR, true ); m_bConnectedSuccessfully = false; return 0; } int CBOINCDialUpManager::NetworkAvailable() { CMainDocument* pDoc = wxGetApp().GetDocument(); CMainFrame* pFrame = wxGetApp().GetFrame(); wxString strDialogMessage = wxEmptyString; wxASSERT(pDoc); wxASSERT(wxDynamicCast(pDoc, CMainDocument)); wxASSERT(pFrame); wxASSERT(wxDynamicCast(pFrame, CMainFrame)); wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::NetworkAvailable - Connection Detected, notifing user of update to all projects")); m_bNotifyConnectionAvailable = false; // We are already online but BOINC for some reason is in a state // where it belives it has some pending work to do, so give it // a nudge // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s has detected it is now connected to the Internet. " "Updating all projects and retrying all transfers."), wxGetApp().GetBrand()->GetProjectName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_INFORMATION, true ); // Signal BOINC to update all projects and transfers. pDoc->rpc.network_available(); return 0; } int CBOINCDialUpManager::Disconnect() { CMainDocument* pDoc = wxGetApp().GetDocument(); CMainFrame* pFrame = wxGetApp().GetFrame(); wxString strDialogMessage = wxEmptyString; wxASSERT(pDoc); wxASSERT(wxDynamicCast(pDoc, CMainDocument)); wxASSERT(pFrame); wxASSERT(wxDynamicCast(pFrame, CMainFrame)); wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::Disconnect - Connection Detected, disconnect requested via the CC.")); if (pDoc->state.global_prefs.hangup_if_dialed) { wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::Disconnect - Connection Detected, Don't need the network, Hanging up.")); if (m_pDialupManager->HangUp()) { // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s has successfully disconnected from the Internet."), wxGetApp().GetBrand()->GetProjectName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_INFORMATION, true ); m_bConnectedSuccessfully = false; } else { // %s is the project name // i.e. 'BOINC', 'GridRepublic' strDialogMessage.Printf( _("%s failed to disconnected from the Internet."), wxGetApp().GetBrand()->GetProjectName().c_str() ); pFrame->ShowAlert( m_strDialogTitle, strDialogMessage, wxICON_ERROR ); } } return 0; } void CBOINCDialUpManager::ResetReminderTimers() { m_dtLastDialupAlertSent = wxDateTime((time_t)0); m_dtLastDialupRequest = wxDateTime((time_t)0); m_dtDialupConnectionTimeout = wxDateTime((time_t)0); }