1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC. If not, see <http://www.gnu.org/licenses/>.
17
18 #if defined(__GNUG__) && !defined(__APPLE__)
19 #pragma implementation "BOINCDialupManager.h"
20 #endif
21
22 #include "stdwx.h"
23 #include "network.h"
24 #include "diagnostics.h"
25 #include "util.h"
26 #include "mfile.h"
27 #include "miofile.h"
28 #include "parse.h"
29 #include "error_numbers.h"
30 #include "BOINCGUIApp.h"
31 #include "SkinManager.h"
32 #include "MainDocument.h"
33 #include "BOINCTaskBar.h"
34 #include "BOINCBaseFrame.h"
35 #include "BOINCDialupManager.h"
36 #include "DlgOptions.h"
37
38
CBOINCDialUpManager()39 CBOINCDialUpManager::CBOINCDialUpManager() {
40 wxLogTrace(wxT("Function Start/End"), wxT("CBOINCDialUpManager::CBOINCDialUpManager - Function Begin"));
41
42 #ifdef __WXMSW__
43 m_pDialupManager = wxDialUpManager::Create();
44 wxASSERT(m_pDialupManager->IsOk());
45 #endif
46 ResetReminderTimers();
47 m_bSetConnectionTimer = false;
48 m_bNotifyConnectionAvailable = false;
49 m_bConnectedSuccessfully = false;
50 m_bResetTimers = false;
51 m_bWasDialing = false;
52 m_iNetworkStatus = 0;
53 m_iConnectAttemptRetVal = 0;
54
55
56 // Construct the default dialog title for dial-up messages
57 //
58 // %s is the application name
59 // i.e. 'BOINC Manager', 'GridRepublic Manager'
60 m_strDialogTitle.Printf(
61 _("%s - Network Status"),
62 wxGetApp().GetSkinManager()->GetAdvanced()->GetApplicationName().c_str()
63 );
64
65 wxLogTrace(wxT("Function Start/End"), wxT("CBOINCDialUpManager::CBOINCDialUpManager - Function End"));
66 }
67
68
~CBOINCDialUpManager()69 CBOINCDialUpManager::~CBOINCDialUpManager() {
70 wxLogTrace(wxT("Function Start/End"), wxT("CBOINCDialUpManager::~CBOINCDialUpManager - Function Begin"));
71
72 #ifdef __WXMSW__
73 delete m_pDialupManager;
74 #endif
75 wxLogTrace(wxT("Function Start/End"), wxT("CBOINCDialUpManager::~CBOINCDialUpManager - Function End"));
76 }
77
78
IsOk()79 bool CBOINCDialUpManager::IsOk() {
80 #ifdef __WXMSW__
81 return m_pDialupManager->IsOk();
82 #else
83 return true;
84 #endif
85 }
86
87
GetISPNames(wxArrayString & names)88 size_t CBOINCDialUpManager::GetISPNames(wxArrayString& names) {
89 return m_pDialupManager->GetISPNames(names);
90 }
91
92
OnPoll()93 void CBOINCDialUpManager::OnPoll() {
94 CMainDocument* pDoc = wxGetApp().GetDocument();
95 CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
96 static bool bAlreadyRunningLoop = false;
97 bool bIsOnline = false;
98 bool bWantConnection = false;
99 bool bWantDisconnect = false;
100 CC_STATUS cc_status;
101
102
103 // We are ready to rock and roll.
104 if (!bAlreadyRunningLoop && pDoc && pFrame) {
105 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
106 wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame));
107
108 bAlreadyRunningLoop = true;
109
110 // cache the various states
111
112 // The dialup manager tells us if we are still dialing or if we have
113 // successfully connected. IsNetworkAlive/IsOnline both report the
114 // success or failure of the dialup device to establish a connection
115 // to the outside world.
116 pDoc->GetCoreClientStatus(cc_status);
117
118 bIsOnline = (cc_status.network_status == NETWORK_STATUS_ONLINE);
119 bWantConnection = (cc_status.network_status == NETWORK_STATUS_WANT_CONNECTION);
120 bWantDisconnect = (cc_status.network_status == NETWORK_STATUS_WANT_DISCONNECT);
121
122 // The timers are used to keep from spamming the user with the same
123 // messages over each iteration of the poll loop. we only need to
124 // reset them during a connect event in case we randomly loose
125 // a connection.
126 if (m_bResetTimers) {
127 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - Resetting dial-up notification timers"));
128
129 m_bResetTimers = false;
130 m_bSetConnectionTimer = false;
131 ResetReminderTimers();
132 }
133
134 // Log out the trace information for debugging purposes.
135 /*
136 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - Dialup Flags"));
137 wxLogTrace(wxT("Function Status"),
138 wxT("CBOINCDialUpManager::poll - -- bIsOnline = '%d', bIsDialing = '%d', m_bWasDialing = '%d', iNetworkStatus = '%d', bWantConnection = '%d'"),
139 bIsOnline, bIsDialing, m_bWasDialing, iNetworkStatus, bWantConnection
140 );
141 wxLogTrace(wxT("Function Status"),
142 wxT("CBOINCDialUpManager::poll - -- m_bResetTimers = '%d', m_bNotifyConnectionAvailable = '%d', m_bConnectedSuccessfully = '%d'"),
143 m_bResetTimers, m_bNotifyConnectionAvailable, m_bConnectedSuccessfully
144 );
145 wxLogTrace(wxT("Function Status"),
146 wxT("CBOINCDialUpManager::poll - -- confirm_before_connecting = '%d', hangup_if_dialed = '%d'"),
147 pDoc->state.global_prefs.confirm_before_connecting, pDoc->state.global_prefs.hangup_if_dialed
148 );
149 */
150 #ifdef __WXMSW__
151 bool bIsDialing = m_pDialupManager->IsDialing();
152 if (!bIsOnline && !bIsDialing && !m_bWasDialing && bWantConnection) {
153 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - !bIsOnline && !bIsDialing && !m_bWasDialing && bWantConnection"));
154 if (pFrame->IsShown()) {
155 // BOINC Manager is visable and can process user input.
156 m_bSetConnectionTimer = true;
157 Connect();
158 }
159 } else if (!bIsDialing && !m_bWasDialing) {
160 // We are not doing anything now, were we up to something before?
161 if (bIsOnline && m_bConnectedSuccessfully && m_bNotifyConnectionAvailable) {
162 // Ah ha, we are online and we initiated the connection, so we need to
163 // notify the CC that the network is available.
164 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - bIsOnline && m_bConnectedSuccessfully && m_bNotifyConnectionAvailable"));
165 NetworkAvailable();
166 } else if (bWantDisconnect && m_bConnectedSuccessfully) {
167 // We are online, and the CC says it is safe to disconnect. Since we
168 // initiated the connection we need to disconnect now.
169 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - bWantDisconnect && m_bConnectedSuccessfully"));
170 Disconnect();
171 }
172 } else if (!bIsDialing && m_bWasDialing) {
173 // We initiated a connection attempt and now we are either online or failed to
174 // connect because of a modem error or a users credentials were wrong.
175 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - !bIsDialing && m_bWasDialing"));
176
177 if (m_bSetConnectionTimer) {
178 m_bSetConnectionTimer = false;
179 m_dtDialupConnectionTimeout = wxDateTime::Now();
180 m_iConnectAttemptRetVal = ERR_NO_NETWORK_CONNECTION;
181 }
182
183 wxTimeSpan tsTimeout = wxDateTime::Now() - m_dtDialupConnectionTimeout;
184 if (30 > tsTimeout.GetSeconds()) {
185 if(m_iConnectAttemptRetVal != BOINC_SUCCESS) {
186 return;
187 }
188 }
189
190 m_bWasDialing = false;
191 m_bResetTimers = true;
192 if (!m_iConnectAttemptRetVal) {
193 ConnectionSucceeded();
194 } else {
195 ConnectionFailed();
196 }
197 } else if (bIsDialing && !m_bWasDialing) {
198 // Setup the state machine so that it knows when we have finished the connection
199 // attempt.
200 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::poll - bIsDialing && !m_bWasDialing"));
201 m_bWasDialing = true;
202 }
203 #endif
204 bAlreadyRunningLoop = false;
205 }
206 }
207
208
Connect()209 int CBOINCDialUpManager::Connect() {
210 CMainDocument* pDoc = wxGetApp().GetDocument();
211 CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
212 CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
213 wxTimeSpan tsLastDialupRequest;
214 int iAnswer;
215 wxString strDialogMessage = wxEmptyString;
216 GLOBAL_PREFS_MASK mask;
217
218
219 wxASSERT(pDoc);
220 wxASSERT(pFrame);
221 wxASSERT(pSkinAdvanced);
222 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
223 wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame));
224 wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
225
226
227 tsLastDialupRequest = wxDateTime::Now() - m_dtLastDialupRequest;
228 if ((tsLastDialupRequest.GetMinutes() >= (pFrame->GetReminderFrequency() * 60)) && (pFrame->GetReminderFrequency() != 0)) {
229 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::Connect - Begin connection process"));
230 m_dtLastDialupRequest = wxDateTime::Now();
231
232 if(pFrame->GetDialupConnectionName().size()) {
233 // We have a valid connection name that we can dial.
234 // Update current working preferences (including any overrides) from client
235 pDoc->rpc.get_global_prefs_working_struct(pDoc->state.global_prefs, mask);
236 if(pDoc->state.global_prefs.confirm_before_connecting) {
237 // %s is the project name
238 // i.e. 'BOINC', 'GridRepublic'
239 strDialogMessage.Printf(
240 _("%s needs to connect to the Internet.\nMay it do so now?"),
241 pSkinAdvanced->GetApplicationShortName().c_str()
242 );
243 iAnswer = wxGetApp().SafeMessageBox(
244 strDialogMessage,
245 m_strDialogTitle,
246 wxYES_NO | wxICON_QUESTION,
247 pFrame
248 );
249 } else {
250 // %s is the project name
251 // i.e. 'BOINC', 'GridRepublic'
252 strDialogMessage.Printf(
253 _("%s is connecting to the Internet."),
254 pSkinAdvanced->GetApplicationShortName().c_str()
255 );
256 pFrame->ShowAlert(
257 m_strDialogTitle,
258 strDialogMessage,
259 wxOK | wxICON_INFORMATION,
260 true
261 );
262 iAnswer = wxYES;
263 }
264
265 // Are we allow to connect?
266 if (wxYES == iAnswer) {
267 m_bNotifyConnectionAvailable = true;
268 m_bConnectedSuccessfully = false;
269 m_pDialupManager->Dial(
270 pFrame->GetDialupConnectionName(),
271 wxEmptyString,
272 wxEmptyString,
273 true
274 );
275 }
276 } else {
277 // The user hasn't given us a valid connection to dial. Inform them
278 // that we need a connection and that they may need to set a default
279 // connection.
280 }
281 }
282
283 return 0;
284 }
285
286
ConnectionSucceeded()287 int CBOINCDialUpManager::ConnectionSucceeded() {
288 CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
289 CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
290 wxString strDialogMessage = wxEmptyString;
291
292
293 wxASSERT(pFrame);
294 wxASSERT(pSkinAdvanced);
295 wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame));
296 wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
297
298
299 // %s is the project name
300 // i.e. 'BOINC', 'GridRepublic'
301 strDialogMessage.Printf(
302 _("%s has successfully connected to the Internet."),
303 pSkinAdvanced->GetApplicationShortName().c_str()
304 );
305 pFrame->ShowAlert(
306 m_strDialogTitle,
307 strDialogMessage,
308 wxOK | wxICON_INFORMATION,
309 true
310 );
311 m_bConnectedSuccessfully = true;
312
313 return 0;
314 }
315
316
ConnectionFailed()317 int CBOINCDialUpManager::ConnectionFailed() {
318 CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
319 CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
320 wxString strDialogMessage = wxEmptyString;
321
322 wxASSERT(pFrame);
323 wxASSERT(pSkinAdvanced);
324 wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame));
325 wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
326
327 // %s is the project name
328 // i.e. 'BOINC', 'GridRepublic'
329 strDialogMessage.Printf(
330 _("%s failed to connect to the Internet."),
331 pSkinAdvanced->GetApplicationShortName().c_str()
332 );
333 pFrame->ShowAlert(
334 m_strDialogTitle,
335 strDialogMessage,
336 wxOK | wxICON_ERROR,
337 true
338 );
339 m_bConnectedSuccessfully = false;
340
341 return 0;
342 }
343
344
NetworkAvailable()345 int CBOINCDialUpManager::NetworkAvailable() {
346 CMainDocument* pDoc = wxGetApp().GetDocument();
347 CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
348 CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
349 wxString strDialogMessage = wxEmptyString;
350
351
352 wxASSERT(pDoc);
353 wxASSERT(pFrame);
354 wxASSERT(pSkinAdvanced);
355 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
356 wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame));
357 wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
358
359
360 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::NetworkAvailable - Connection Detected, notifing user of update to all projects"));
361
362 m_bNotifyConnectionAvailable = false;
363
364 // We are already online but BOINC for some reason is in a state
365 // where it belives it has some pending work to do, so give it
366 // a nudge
367
368 // %s is the project name
369 // i.e. 'BOINC', 'GridRepublic'
370 strDialogMessage.Printf(
371 _("%s has detected it is now connected to the Internet.\nUpdating all projects and retrying all transfers."),
372 pSkinAdvanced->GetApplicationShortName().c_str()
373 );
374
375 pFrame->ShowAlert(
376 m_strDialogTitle,
377 strDialogMessage,
378 wxOK | wxICON_INFORMATION,
379 true
380 );
381
382 // Signal BOINC to update all projects and transfers.
383 pDoc->rpc.network_available();
384
385 return 0;
386 }
387
388
Disconnect()389 int CBOINCDialUpManager::Disconnect() {
390 CMainDocument* pDoc = wxGetApp().GetDocument();
391 CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
392 CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
393 wxString strDialogMessage = wxEmptyString;
394 GLOBAL_PREFS_MASK mask;
395
396
397 wxASSERT(pDoc);
398 wxASSERT(pFrame);
399 wxASSERT(pSkinAdvanced);
400 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
401 wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame));
402 wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
403
404
405 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::Disconnect - Connection Detected, disconnect requested via the CC."));
406
407 // Update current working preferences (including any overrides) from client
408 pDoc->rpc.get_global_prefs_working_struct(pDoc->state.global_prefs, mask);
409 if (pDoc->state.global_prefs.hangup_if_dialed) {
410 wxLogTrace(wxT("Function Status"), wxT("CBOINCDialUpManager::Disconnect - Connection Detected, Don't need the network, Hanging up."));
411 if (m_pDialupManager->HangUp()) {
412
413 // %s is the project name
414 // i.e. 'BOINC', 'GridRepublic'
415 strDialogMessage.Printf(
416 _("%s has successfully disconnected from the Internet."),
417 pSkinAdvanced->GetApplicationShortName().c_str()
418 );
419 pFrame->ShowAlert(
420 m_strDialogTitle,
421 strDialogMessage,
422 wxOK | wxICON_INFORMATION,
423 true
424 );
425 m_bConnectedSuccessfully = false;
426
427 } else {
428
429 // %s is the project name
430 // i.e. 'BOINC', 'GridRepublic'
431 strDialogMessage.Printf(
432 _("%s failed to disconnected from the Internet."),
433 pSkinAdvanced->GetApplicationShortName().c_str()
434 );
435 pFrame->ShowAlert(
436 m_strDialogTitle,
437 strDialogMessage,
438 wxOK | wxICON_ERROR
439 );
440 }
441 }
442
443 return 0;
444 }
445
446
ResetReminderTimers()447 void CBOINCDialUpManager::ResetReminderTimers() {
448 m_dtLastDialupRequest = wxDateTime((time_t)0);
449 m_dtDialupConnectionTimeout = wxDateTime((time_t)0);
450 }
451
452