summaryrefslogtreecommitdiffabout
path: root/BigBrotherDoc.cpp
Unidiff
Diffstat (limited to 'BigBrotherDoc.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--BigBrotherDoc.cpp1039
1 files changed, 1039 insertions, 0 deletions
diff --git a/BigBrotherDoc.cpp b/BigBrotherDoc.cpp
new file mode 100644
index 0000000..4a5328e
--- a/dev/null
+++ b/BigBrotherDoc.cpp
@@ -0,0 +1,1039 @@
1// BigBrotherDoc.cpp : implementation of the CBigBrotherDoc class
2//
3
4#include "stdafx.h"
5#include "BigBrother.h"
6
7#include "BigBrotherDoc.h"
8#include "BigBrotherView.h"
9#include "ActivityView.h"
10#include "HostPropertyPages.h"
11#include "MainFrm.h"
12#include "Preferences.h"
13
14#ifdef _DEBUG
15#define new DEBUG_NEW
16#undef THIS_FILE
17static char THIS_FILE[] = __FILE__;
18#endif
19
20/////////////////////////////////////////////////////////////////////////////
21// CBigBrotherDoc
22
23IMPLEMENT_SERIAL(CBigBrotherDoc, CDocument, VERSIONABLE_SCHEMA | 3 )
24IMPLEMENT_SERIAL(CBrother, CObject, VERSIONABLE_SCHEMA | 2 )
25IMPLEMENT_SERIAL(CAction, CObject, VERSIONABLE_SCHEMA | 1 )
26IMPLEMENT_SERIAL(CLogEntry, CObject, VERSIONABLE_SCHEMA | 2 )
27
28BEGIN_MESSAGE_MAP(CBigBrotherDoc, CDocument)
29 //{{AFX_MSG_MAP(CBigBrotherDoc)
30 ON_COMMAND(ID_BROTHERS_NEW, OnBrothersNew)
31 ON_UPDATE_COMMAND_UI(ID_BROTHERS_ADDBROTHER, OnUpdateBrothersAddbrother)
32 ON_COMMAND(ID_BROTHERS_ADDBROTHER, OnBrothersAddbrother)
33 ON_UPDATE_COMMAND_UI(ID_BROTHERS_DELETE, OnUpdateBrothersDelete)
34 ON_COMMAND(ID_BROTHERS_DELETE, OnBrothersDelete)
35 ON_COMMAND(ID_FILE_PREFERENCES, OnFilePreferences)
36 ON_UPDATE_COMMAND_UI(ID_FILE_PAUSE, OnUpdateFilePause)
37 ON_COMMAND(ID_FILE_PAUSE, OnFilePause)
38 ON_UPDATE_COMMAND_UI(ID_VIEW_HOSTPROPERTIES, OnUpdateViewHostproperties)
39 ON_COMMAND(ID_VIEW_HOSTPROPERTIES, OnViewHostproperties)
40 //}}AFX_MSG_MAP
41END_MESSAGE_MAP()
42
43/////////////////////////////////////////////////////////////////////////////
44// CBigBrotherDoc construction/destruction
45
46CBigBrotherDoc::CBigBrotherDoc()
47 : m_MaxLogTime(0,1,0,0), m_Threads(0), m_MaxThreads(10), m_PingSize(32), m_RootBrother(NULL),
48 m_bSaveOnShutdown(TRUE), m_AutoSave(0,0,30,0), m_bStoreLastActivity(FALSE)
49{
50 m_BBView = NULL;
51 m_AView = NULL;
52}
53
54CBigBrotherDoc::~CBigBrotherDoc()
55{
56 CleanUp();
57}
58
59BOOL CBigBrotherDoc::OnNewDocument()
60{
61 if (!CDocument::OnNewDocument())
62 return FALSE;
63
64 CleanUp();
65 m_RootBrother=new CBrother();
66
67 return TRUE;
68}
69
70/////////////////////////////////////////////////////////////////////////////
71// CBigBrotherDoc serialization
72
73void CBigBrotherDoc::Serialize(CArchive& ar)
74{
75 ASSERT_VALID(this);
76
77 CDocument::Serialize(ar);
78
79 ar.MapObject(this);
80 ar.SerializeClass(RUNTIME_CLASS(CBigBrotherDoc));
81
82 if (ar.IsStoring())
83 {
84 // Store to archive
85 ar << m_PingSize;
86 ar << m_MaxThreads;
87 ar << m_MaxLogTime;
88 ar << m_bSaveOnShutdown;
89 ar << m_AutoSave;
90 ar << m_LogFile;
91 ar << m_bStoreLastActivity;
92 ar << m_RootBrother;
93 m_Brotherhood.Serialize(ar);
94 }
95 else
96 {
97 UINTschema = ar.GetObjectSchema();
98 #ifndefNDEBUG
99 {
100 CString tmp;
101 tmp.Format("Doc-OSchema: %u\n",schema);
102 TRACE0(tmp);
103 }
104#endif
105 CleanUp();
106 m_ThisMap.RemoveAll();
107 // Read from archive
108 ar >> m_PingSize;
109 ar >> m_MaxThreads;
110 ar >> m_MaxLogTime;
111 if(schema>=2){
112 ar >> m_bSaveOnShutdown;
113 ar >> m_AutoSave;
114 }
115 ar >> m_LogFile;
116 if(schema>=3)
117 ar >> m_bStoreLastActivity;
118 ar >> m_RootBrother;
119 m_Brotherhood.Serialize(ar);
120 // Read from archive
121 m_ThisMap.RemoveAll();
122 // Log loading
123 CString logLine;
124 logLine.Format(IDS_LOG_LOADFILE,(LPCTSTR)GetTitle());
125 logLine=CTime::GetCurrentTime().Format(IDS_LOG_DATEFORMAT)+" "+logLine;
126 LogLine(logLine);
127 }
128}
129
130/////////////////////////////////////////////////////////////////////////////
131// CBigBrotherDoc diagnostics
132
133#ifdef _DEBUG
134void CBigBrotherDoc::AssertValid() const
135{
136 CDocument::AssertValid();
137}
138
139void CBigBrotherDoc::Dump(CDumpContext& dc) const
140{
141 CDocument::Dump(dc);
142}
143#endif //_DEBUG
144
145/////////////////////////////////////////////////////////////////////////////
146// CBigBrotherDoc commands
147
148CBrother::CBrother(CBrother *daddy)
149{
150 CleanUp();
151 m_Daddy=daddy;
152 ParentalAdjust(TRUE);
153}
154
155void CBrother::CleanUp()
156{
157 m_Item=NULL;
158 flags=0;
159 m_bLog=TRUE;
160 m_Daddy=NULL;
161 m_Desc.Empty();
162 m_Down.CleanUp();
163 m_Host.Empty();
164 m_IntervalBad=30;
165 m_IntervalGood=30;
166 m_Retries=3;
167 m_TimeOut=5000;
168 m_Up.CleanUp();
169 m_bPinged=FALSE;
170 m_bPending=FALSE;
171 m_bIsUp=TRUE;
172 m_bPinging=FALSE;
173 m_bUp=TRUE;
174 m_bToKill=FALSE;
175 m_Doc=NULL;
176}
177
178CAction::CAction()
179{
180 CleanUp();
181}
182
183void CAction::CleanUp()
184{
185 flags=0;
186 m_Custom.Empty();
187 m_Sound.Empty();
188}
189
190CAction& CAction::operator=(CAction& src)
191{
192 flags=src.flags;
193 m_Custom=src.m_Custom;
194 m_Sound=src.m_Sound;
195 return *this;
196}
197
198void CBrother::ParentalAdjust(BOOL cleanUp)
199{
200 if(!m_Daddy){
201 flags|=flagsOverrideIntervals|flagsOverrideTimeout|flagsOverrideRetries|flagsOverrideActions|flagsOverrideLogging;
202 if(cleanUp){
203 m_Desc.LoadString(IDS_ROOTNODENAME);
204 m_IntervalBad=30, m_IntervalGood=30;
205 m_TimeOut=5000;
206 m_Retries=3;
207 {
208 m_Up.CleanUp();
209 m_Down.CleanUp();
210 m_Up.flags=m_Down.flags=CAction::flagsPlayASound;
211 m_Up.m_Sound.LoadString(IDS_ACTION_HOST_UP);
212 m_Down.m_Sound.LoadString(IDS_ACTION_HOST_DOWN);
213 }
214 m_bLog=TRUE;
215 }
216 }else{
217 if(!(flags&flagsOverrideIntervals)){
218 CBrother *parent = m_Daddy;
219 while(!(parent->flags&flagsOverrideIntervals)){
220 ASSERT(parent->m_Daddy);
221 parent=parent->m_Daddy;
222 }
223 m_IntervalBad=parent->m_IntervalBad;
224 m_IntervalGood=parent->m_IntervalGood;
225 }
226 if(!(flags&flagsOverrideTimeout)){
227 CBrother *parent = m_Daddy;
228 while(!(parent->flags&flagsOverrideTimeout)){
229 ASSERT(parent->m_Daddy);
230 parent=parent->m_Daddy;
231 }
232 m_TimeOut=parent->m_TimeOut;
233 }
234 if(!(flags&flagsOverrideRetries)){
235 CBrother *parent = m_Daddy;
236 while(!(parent->flags&flagsOverrideRetries)){
237 ASSERT(parent->m_Daddy);
238 parent=parent->m_Daddy;
239 }
240 m_Retries=parent->m_Retries;
241 }
242 if(!(flags&flagsOverrideActions)){
243 CBrother *parent = m_Daddy;
244 while(!(parent->flags&flagsOverrideActions)){
245 ASSERT(parent->m_Daddy);
246 parent=parent->m_Daddy;
247 }
248 m_Up=parent->m_Up;
249 m_Down=parent->m_Down;
250 }
251 if(!(flags&flagsOverrideLogging)){
252 CBrother *parent = m_Daddy;
253 while(!(parent->flags&flagsOverrideLogging)){
254 ASSERT(parent->m_Daddy);
255 parent=parent->m_Daddy;
256 }
257 m_bLog=parent->m_bLog;
258 }
259 }
260}
261
262void CBigBrotherDoc::OnChangedViewList()
263{
264 m_BBView=NULL;
265 m_AView=NULL;
266POSITION p = GetFirstViewPosition();
267 while(p){
268 CView* v = GetNextView(p);
269 if(v->IsKindOf(RUNTIME_CLASS(CBigBrotherView))){
270 ASSERT(!m_BBView);
271 m_BBView=(CBigBrotherView*)v;
272 }else if(v->IsKindOf(RUNTIME_CLASS(CActivityView))){
273 ASSERT(!m_AView);
274 m_AView=(CActivityView*)v;
275 }
276 }
277
278 CDocument::OnChangedViewList();
279}
280
281void CBigBrotherDoc::OnBrothersNew()
282{
283 ASSERT(m_BBView);
284CBrother *bro = m_BBView->GetCurrentBrother();
285 ASSERT(bro);
286CBrother *lb = new CBrother(bro);
287 m_Brotherhood.AddTail(lb);
288 SetModifiedFlag();
289 m_BBView->AddBrother(lb);
290 m_BBView->GotoBrother(lb);
291}
292
293void CBigBrotherDoc::CheckPendingQueue()
294{
295 if(flags&flagsSuspended)
296 return;
297CTime currentTime = CTime::GetCurrentTime();
298CTime nearestCheck;
299BOOL nearested = CheckPendingBrother(m_RootBrother,currentTime,nearestCheck,FALSE);
300POSITION p = m_Brotherhood.GetHeadPosition();
301 while(p){
302 CBrother *b = (CBrother*)m_Brotherhood.GetNext(p);
303 ASSERT(b);
304 nearested|=CheckPendingBrother(b,currentTime,nearestCheck,nearested);
305 }
306 if(m_AutoSave.GetTotalMinutes()){
307 CTime nc = m_AutoSaved+m_AutoSave;
308 if(nc<=currentTime){
309 if(IsModified())
310 DoFileSave();
311 m_AutoSaved=currentTime;
312 while(nc<=currentTime)
313 nc=nc+m_AutoSave;
314 }
315 if((!nearested) || nc<nearestCheck){
316 nearestCheck=nc;
317 nearested=TRUE;
318 }
319 }
320 if(!nearested)
321 return;
322 currentTime = CTime::GetCurrentTime();
323CTimeSpan nextto = nearestCheck-currentTime;
324 UINTtimer = 60000;
325 if(nextto.GetTotalSeconds()<60)
326 timer=nextto.GetTotalSeconds()*1000;
327 if(m_BBView)// In case we're destroying..
328 m_BBView->SetTimer(TM_CHECK,timer,NULL);
329}
330
331BOOL CBigBrotherDoc::CheckPendingBrother(CBrother* b,CTime& currentTime,CTime& nearestCheck,BOOL nearested)
332{
333 if(!b)
334 return FALSE;
335 if(b->m_Host.IsEmpty() || b->m_bPinging){
336 b->m_bPending=FALSE;
337 return FALSE;
338 }
339 if(b->m_bPending){
340 TryBrother(b);
341 return FALSE;
342 }
343CTime nextCheck = b->m_Pinged+CTimeSpan(b->m_bIsUp?b->m_IntervalGood:b->m_IntervalBad);
344 if(nextCheck<=currentTime){
345 TryBrother(b);
346 return FALSE;
347 }
348 if((!nearested) || nextCheck<nearestCheck){
349 nearestCheck=nextCheck;
350 return TRUE;
351 }
352 return FALSE;
353}
354
355void CBigBrotherDoc::TryBrother(CBrother *b)
356{
357 ASSERT(!b->m_Host.IsEmpty());
358 if(!(m_Threads<m_MaxThreads)){
359 b->m_bPending=TRUE;
360 return;
361 }
362 if(!m_BBView)
363 return;// In case we're dying
364 m_BBView->SendMessage(WM_ACTIVITYCOUNT,1,0);
365 b->m_Doc=this;
366 b->m_bPinging=TRUE;
367 VERIFY(AfxBeginThread(CBrother::DoCheck,(LPVOID)b));
368}
369
370UINT CBrother::DoCheck(LPVOID pParam)
371{
372CBrother *b = (CBrother*)pParam;
373 ASSERT(b);
374 return b->Check();
375}
376
377UINT CBrother::Check()
378{
379CBigBrotherDoc *m_Doc = (CBigBrotherDoc*)CBrother::m_Doc;
380
381 if(!m_bToKill){
382 ASSERT(m_Doc);
383 ASSERT(m_Doc->IsKindOf(RUNTIME_CLASS(CBigBrotherDoc)));
384 ASSERT(m_Doc->m_BBView);
385 m_Doc->m_BBView->PostMessage(WM_UPDATETREEBROTHER,0,(LPARAM)this);
386 }
387
388CICMP *pICMP = NULL;
389UINT dataSize = m_bToKill?32:m_Doc->m_PingSize;
390in_addr ip;
391 ip.s_addr = inet_addr(m_Host);
392CLogEntry le;
393 if(ip.s_addr==INADDR_NONE){
394 hostent *he = gethostbyname(m_Host);
395 if(!he){
396 le.m_Status.LoadString(IDS_PS_FAILEDTORESOLVE);
397 goto goBye;
398 }
399 memmove(&ip.s_addr,he->h_addr,sizeof(ip.s_addr));
400 }
401 pICMP = CICMP::CreateICMP();
402 if(!(pICMP && pICMP->Initialize())) {
403 le.m_Status.LoadString(IDS_PS_UNABLETOICMP);
404 goto goBye;
405 }
406 INT status;
407 LONG rtt;
408 rtt=pICMP->Ping(ip,dataSize,m_TimeOut,&status);
409 switch(status){
410 case CICMP::ipSuccess:
411 le.m_bReached=TRUE;
412 le.m_RTT=rtt;
413 le.m_Status.Empty();
414 break;
415 case CICMP::ipBuffTooSmall:
416 le.m_Status.LoadString(IDS_PS_INTERNALERROR);
417 break;
418 case CICMP::ipDestNetUnreachable:
419 le.m_Status.LoadString(IDS_PS_NETUNREACHABLE);
420 break;
421 case CICMP::ipDestHostUnreachable:
422 le.m_Status.LoadString(IDS_PS_HOSTUNREACHABLE);
423 break;
424 case CICMP::ipDestProtUnreachable:
425 le.m_Status.LoadString(IDS_PS_PROTUNREACHABLE);
426 break;
427 case CICMP::ipDestPortUnreachable:
428 le.m_Status.LoadString(IDS_PS_PORTUNREACHABLE);
429 case CICMP::ipNoResources:
430 le.m_Status.LoadString(IDS_PS_NORESOURCES);
431 break;
432 case CICMP::ipBadOption:
433 le.m_Status.LoadString(IDS_PS_INTERNALERROR);
434 break;
435 case CICMP::ipHWError:
436 le.m_Status.LoadString(IDS_PS_HWERROR);
437 break;
438 case CICMP::ipPacketTooBig:
439 le.m_Status.LoadString(IDS_PS_BIGPACKET);
440 break;
441 case CICMP::ipTimeOut:
442 le.m_Status.LoadString(IDS_PS_TIMEOUT);
443 break;
444 case CICMP::ipBadRequest:
445 le.m_Status.LoadString(IDS_PS_INTERNALERROR);
446 break;
447 case CICMP::ipBadRoute:
448 le.m_Status.LoadString(IDS_PS_BADROUTE);
449 break;
450 case CICMP::ipTTLExpiredInTransit:
451 le.m_Status.LoadString(IDS_PS_TTLEXPTRANSIT);
452 break;
453 case CICMP::ipTTLExpiredInReasm:
454 le.m_Status.LoadString(IDS_PS_TTLEXPREASM);
455 break;
456 case CICMP::ipParamProblem:
457 le.m_Status.LoadString(IDS_PS_IPARAMP);
458 break;
459 case CICMP::ipSourceQuench:
460 le.m_Status.LoadString(IDS_PS_SOURCEQUENCH);
461 break;
462 case CICMP::ipOptionTooBig:
463 le.m_Status.LoadString(IDS_PS_BIGOPTION);
464 break;
465 case CICMP::ipBadDest:
466 le.m_Status.LoadString(IDS_PS_BADDEST);
467 break;
468 default:
469 le.m_Status.Format(IDS_PS_UNKNOWNERROR,status);
470 break;
471 }
472goBye:
473 if(pICMP) {
474 pICMP->Deinitialize();
475 delete pICMP;
476 }
477 if(le.m_bReached)
478 m_bIsUp=TRUE;
479 else{
480 if(m_bIsUp)
481 m_HowDown=0;
482 m_bIsUp=FALSE;
483 m_HowDown++;
484 }
485
486 le.m_Time=CTime::GetCurrentTime();
487
488CLogEntry *newLE = NULL;
489 if(!m_Log.IsEmpty()){
490 CLogEntry *head = m_Log.GetHead();
491 while(head && (m_bToKill?FALSE:(m_Doc->m_MaxLogTime<(le.m_Time-head->m_Time)))){
492 m_Log.RemoveHead();
493 if(newLE)
494 delete head;
495 else
496 newLE=head;
497 if(m_Log.IsEmpty())
498 head=NULL;
499 else
500 head = m_Log.GetHead();
501 }
502 }
503 if(newLE)
504 (*newLE)=le;
505 else
506 newLE=new CLogEntry(le);
507 m_Log.AddTail(newLE);
508
509 if(m_bToKill)
510 delete this;
511 else{
512 m_bPinged=TRUE;
513 m_Pinged = CTime::GetCurrentTime();
514 if(m_Doc)
515 m_Doc->m_BBView->SendMessage(WM_ACTIVITYCOUNT,(WPARAM)-1,0);
516 if(m_Doc)
517 m_Doc->SetModifiedFlag();
518 if(m_Doc)
519 m_Doc->m_BBView->SendMessage(WM_UPDATETREEBROTHER,TRUE,(LPARAM)this);
520 }
521 return 0;
522}
523
524CLogEntry::CLogEntry()
525{
526 flags=0;
527 m_bReached=FALSE;
528 m_Status.Empty();
529 m_Time=CTime::GetCurrentTime();
530}
531
532CBrother::~CBrother()
533{
534POSITION p = m_Log.GetHeadPosition();
535 while(p){
536 CLogEntry *le = m_Log.GetNext(p);
537 delete le;
538 }
539 m_Log.RemoveAll();
540}
541
542void CBigBrotherDoc::CleanUp()
543{
544 if(m_BBView && m_BBView->m_Pages){
545 m_BBView->m_Pages->SetBrother(NULL);
546 }
547 if(m_RootBrother){
548 while(!m_Brotherhood.IsEmpty()){
549 CBrother *b = m_Brotherhood.GetHead();
550 ASSERT(b);
551 b->m_Doc=this;
552 b->Suicide();
553 }
554 m_RootBrother->m_Doc=this;
555 m_RootBrother->Suicide();
556 m_RootBrother=NULL;
557 }
558 m_MaxLogTime = CTimeSpan(0,1,0,0);
559 m_MaxThreads = 5;
560 m_PingSize = 32;
561 m_bSaveOnShutdown = TRUE;
562 m_AutoSave = CTimeSpan(0,0,30,0);
563 m_AutoSaved = CTime::GetCurrentTime();
564 flags=0;
565}
566
567CBrother* CBigBrotherDoc::GetCurrentBrother()
568{
569 if(m_BBView);
570 return m_BBView->GetCurrentBrother();
571 return NULL;
572}
573
574BOOL CBrother::IsValuable()
575{
576 return !m_Host.IsEmpty();
577}
578
579void CBigBrotherDoc::GetFamily(CBrother *b,CBrotherList *bh)
580{
581 ASSERT(b);
582 ASSERT(bh);
583 ASSERT(m_BBView);
584 m_BBView->GetFamily(b,bh);
585}
586
587void CBigBrotherDoc::OnUpdateBrothersAddbrother(CCmdUI* pCmdUI)
588{
589 ASSERT(m_BBView);
590CBrother *bro = m_BBView->GetCurrentBrother();
591 if(bro)
592 pCmdUI->Enable(bro->m_Daddy!=NULL);
593 else
594 pCmdUI->Enable(FALSE);
595}
596
597void CBigBrotherDoc::OnBrothersAddbrother()
598{
599 ASSERT(m_BBView);
600CBrother *bro = m_BBView->GetCurrentBrother();
601 ASSERT(bro);
602 bro = bro->m_Daddy;
603 ASSERT(bro);
604CBrother *lb = new CBrother(bro);
605 m_Brotherhood.AddTail(lb);
606 SetModifiedFlag();
607 m_BBView->AddBrother(lb);
608 m_BBView->GotoBrother(lb);
609}
610
611BOOL CAction::PlayASound(LPCTSTR sound)
612{
613CString str;
614 str.LoadString(IDS_ACTION_HOST_UP);
615 if(!str.CompareNoCase(sound))
616 return ::PlaySound((LPCTSTR)IDW_HOST_UP,AfxGetApp()->m_hInstance,SND_ASYNC|SND_NODEFAULT|SND_NOSTOP|SND_NOWAIT|SND_RESOURCE);
617 str.LoadString(IDS_ACTION_HOST_DOWN);
618 if(!str.CompareNoCase(sound))
619 return ::PlaySound((LPCTSTR)IDW_HOST_DOWN,AfxGetApp()->m_hInstance,SND_ASYNC|SND_NODEFAULT|SND_NOSTOP|SND_NOWAIT|SND_RESOURCE);
620 str.LoadString(IDS_ACTION_SYSTEM_OK);
621 if(!str.CompareNoCase(sound))
622 return MessageBeep(MB_ICONASTERISK);
623 str.LoadString(IDS_ACTION_SYSTEM_CRITICAL);
624 if(!str.CompareNoCase(sound))
625 return MessageBeep(MB_ICONHAND);
626 return ::PlaySound(sound,AfxGetApp()->m_hInstance,SND_ASYNC|SND_NODEFAULT|SND_NOSTOP|SND_NOWAIT|SND_FILENAME);
627}
628
629CLogEntry& CLogEntry::operator=(CLogEntry& src)
630{
631 m_bReached=src.m_bReached;
632 m_RTT=src.m_RTT;
633 m_Status=src.m_Status;
634 m_Time=src.m_Time;
635 flags=src.flags;
636 return *this;
637}
638
639CLogEntry::CLogEntry(CLogEntry& src)
640{
641 (*this)=src;
642}
643
644void CAction::PerformAction(CBrother *b)
645{
646 if(flags&flagsPlayASound)
647 PlayASound(m_Sound);
648 if(flags&flagsRunCustom){
649 CString cmd = FormatLine(m_Custom,b);
650 system(cmd);
651 }
652}
653
654void CBrother::Serialize(CArchive& ar)
655{
656 ASSERT_VALID(this);
657
658 CObject::Serialize(ar);
659
660CBigBrotherDoc *pDoc = (CBigBrotherDoc*)ar.m_pDocument;
661 ASSERT(pDoc);
662 ASSERT(pDoc->IsKindOf(RUNTIME_CLASS(CBigBrotherDoc)));
663
664 if (ar.IsStoring())
665 {
666 if(pDoc->m_BBView && (pDoc->m_BBView->GetTreeCtrl().GetItemState(m_Item,TVIS_EXPANDED)&TVIS_EXPANDED))
667 flags|=flagsExpandedTree;
668 else
669 flags&=~flagsExpandedTree;
670 if(pDoc->GetCurrentBrother()==this)
671 flags|=flagsCurrentBrother;
672 else
673 flags&=~flagsCurrentBrother;
674 // Store to archive
675 ar << (DWORD)this;
676 ar << (DWORD)m_Daddy;
677 ar << flags;
678 ar << m_bLog;
679 ar << m_Host;
680 ar << m_Desc;
681 ar << m_IntervalGood;
682 ar << m_IntervalBad;
683 ar << m_TimeOut;
684 ar << m_Retries;
685 ar << &m_Up;
686 ar << &m_Down;
687 if(pDoc->m_bStoreLastActivity)
688 m_Log.Serialize(ar);
689 else{
690 CLogList tmp;
691 tmp.Serialize(ar);
692 }
693 }else{
694 #ifndefNDEBUG
695 {
696 CString tmp;
697 tmp.Format("Bro-OSchema: %u\n",ar.GetObjectSchema());
698 TRACE0(tmp);
699 }
700#endif
701 // Read from archive
702 DWORD dw;
703 ar >> dw;
704 pDoc->m_ThisMap[dw]=this;
705 ar >> dw;
706 if(dw){
707 VERIFY(pDoc->m_ThisMap.Lookup(dw,m_Daddy));
708 }else
709 m_Daddy=NULL;
710 ar >> flags;
711 ar >> m_bLog;
712 ar >> m_Host;
713 ar >> m_Desc;
714 ar >> m_IntervalGood;
715 ar >> m_IntervalBad;
716 ar >> m_TimeOut;
717 ar >> m_Retries;
718 CAction *act = NULL;
719 ar >> act;
720 m_Up = *act;
721 delete act;
722 act = NULL;
723 ar >> act;
724 m_Down = *act;
725 delete act;
726 m_Log.Serialize(ar);
727 ParentalAdjust();
728 }
729}
730
731void CAction::Serialize(CArchive& ar)
732{
733 ASSERT_VALID(this);
734
735 CObject::Serialize(ar);
736
737 if (ar.IsStoring())
738 {
739 // Store to archive
740 ar << flags;
741 ar << m_Sound;
742 ar << m_Custom;
743 }else{
744 #ifndefNDEBUG
745 {
746 CString tmp;
747 tmp.Format("Act-OSchema: %u\n",ar.GetObjectSchema());
748 TRACE0(tmp);
749 }
750#endif
751 // Read from archive
752 ar >> flags;
753 ar >> m_Sound;
754 ar >> m_Custom;
755 }
756}
757
758void CLogEntry::Serialize(CArchive& ar)
759{
760 ASSERT_VALID(this);
761
762 CObject::Serialize(ar);
763
764 if (ar.IsStoring())
765 {
766 // Store to archive
767 ar << flags;
768 ar << m_Time;
769 ar << m_bReached;
770 ar << m_RTT;
771 ar << m_Status;
772 }else{
773 UINT schema = ar.GetObjectSchema();
774 /*
775 #ifndefNDEBUG
776 {
777 CString tmp;
778 tmp.Format("Log-OSchema: %u\n",schema);
779 TRACE0(tmp);
780 }
781#endif
782 */
783 // Read from archive
784 if(schema>=2){
785 ar >> flags;
786 }
787 ar >> m_Time;
788 ar >> m_bReached;
789 ar >> m_RTT;
790 ar >> m_Status;
791 }
792}
793
794CBrother::CBrother()
795{
796 CleanUp();
797 ParentalAdjust(TRUE);
798}
799
800void CBigBrotherDoc::OnUpdateBrothersDelete(CCmdUI* pCmdUI)
801{
802 pCmdUI->Enable(GetCurrentBrother()!=NULL);
803}
804
805void CBigBrotherDoc::OnBrothersDelete()
806{
807 ASSERT(m_BBView);
808CBrother *b = GetCurrentBrother();
809 ASSERT(b);
810 m_BBView->KillBrother(b);
811 SetModifiedFlag();
812}
813
814void CBrother::Suicide()
815{
816 ASSERT(m_Doc);
817 ASSERT(m_Doc->IsKindOf(RUNTIME_CLASS(CBigBrotherDoc)));
818CBigBrotherDoc *pDoc = (CBigBrotherDoc*)m_Doc;
819 if(pDoc->m_BBView && pDoc->m_BBView->m_Pages->m_Brother==this)
820 pDoc->m_BBView->m_Pages->m_Brother=NULL;
821POSITION p = pDoc->m_Brotherhood.Find(this);
822 if(p)
823 pDoc->m_Brotherhood.RemoveAt(p);
824 #ifndefNDEBUG
825 else{
826 ASSERT(!m_Daddy);
827 }
828#endif
829 m_Item=NULL;
830 if(m_bPinging){
831 m_bToKill=TRUE;
832 m_Daddy=NULL;
833 m_Doc=NULL;
834 }else
835 delete this;
836}
837
838BOOL CBrother::operator==(CBrother& b)
839{
840 if(flags!=b.flags)
841 return FALSE;
842 if(m_bLog!=b.m_bLog)
843 return FALSE;
844 if(m_Desc.Compare(b.m_Desc))
845 return FALSE;
846 if(m_Down!=b.m_Down)
847 return FALSE;
848 if(m_Host.Compare(b.m_Host))
849 return FALSE;
850 if(m_IntervalGood!=b.m_IntervalGood || m_IntervalBad!=b.m_IntervalBad)
851 return FALSE;
852 if(m_Retries!=b.m_Retries)
853 return FALSE;
854 if(m_TimeOut!=b.m_TimeOut)
855 return FALSE;
856 if(m_Up!=b.m_Up)
857 return FALSE;
858 return TRUE;
859}
860
861BOOL CBrother::operator!=(CBrother& b)
862{
863 return !((*this)==b);
864}
865
866BOOL CAction::operator==(CAction& a)
867{
868 if(flags!=a.flags)
869 return FALSE;
870 if(m_Custom.Compare(a.m_Custom))
871 return FALSE;
872 if(m_Sound.Compare(a.m_Sound))
873 return FALSE;
874 return TRUE;
875}
876
877BOOL CAction::operator!=(CAction& a)
878{
879 return !((*this)==a);
880}
881
882CBrother& CBrother::operator=(CBrother& b)
883{
884 flags=b.flags;
885 m_bLog=b.m_bLog;
886 m_Desc=b.m_Desc;
887 m_Down=b.m_Down;
888 m_Host=b.m_Host;
889 m_IntervalGood=b.m_IntervalGood;
890 m_IntervalBad=b.m_IntervalBad;
891 m_Retries=b.m_Retries;
892 m_TimeOut=b.m_TimeOut;
893 m_Up=b.m_Up;
894 return *this;
895}
896
897BOOL CBigBrotherDoc::SaveModified()
898{
899 if(((CMainFrame*)(AfxGetApp()->m_pMainWnd))->m_bShuttingDown && m_bSaveOnShutdown){
900 DoFileSave();
901 ((CMainFrame*)(AfxGetApp()->m_pMainWnd))->m_bShuttingDown = FALSE;
902 return TRUE;
903 }
904 return CDocument::SaveModified();
905}
906
907void CBrother::AppendSeparator()
908{
909CLogEntry *le = new CLogEntry();
910 le->flags=CLogEntry::flagsSeparator;
911 m_Log.AddTail(le);
912}
913
914void CBigBrotherDoc::OnFilePreferences()
915{
916CPreferences prefs(AfxGetApp()->m_pMainWnd);
917 prefs.m_AutosaveMinutes=m_AutoSave.GetTotalMinutes();
918 prefs.m_LogFile=m_LogFile;
919 prefs.m_MaxThreads=m_MaxThreads;
920 prefs.m_PingSize=m_PingSize;
921 prefs.m_SaveOnShutdown=m_bSaveOnShutdown;
922 prefs.m_LogMins=m_MaxLogTime.GetTotalMinutes();
923 prefs.m_bStoreLastActivity=m_bStoreLastActivity;
924 if(prefs.DoModal()==IDOK){
925 m_AutoSave = CTimeSpan(0,prefs.m_AutosaveMinutes/60,prefs.m_AutosaveMinutes%60,0);
926 m_LogFile=prefs.m_LogFile;
927 m_MaxThreads=prefs.m_MaxThreads;
928 m_PingSize=prefs.m_PingSize;
929 m_bSaveOnShutdown=prefs.m_SaveOnShutdown;
930 m_MaxLogTime = CTimeSpan(0,prefs.m_LogMins/60,prefs.m_LogMins%60,0);
931 m_bStoreLastActivity=prefs.m_bStoreLastActivity;
932 }
933}
934
935void CBigBrotherDoc::LogLine(LPCTSTR str)
936{
937 if(!m_LogFile.IsEmpty()){
938 TRY{
939 CFile file(m_LogFile,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite|CFile::shareDenyWrite|CFile::typeBinary);
940 file.SeekToEnd();
941 file.Write(str,strlen(str));
942 file.Write("\r\n",2);
943 file.Close();
944 }CATCH(CFileException, e){
945 #ifndefNDEBUG
946 afxDump << "Logging error: " << e->m_cause << "\n";
947#endif
948 }END_CATCH
949 }
950}
951
952CString CAction::FormatLine(LPCTSTR fmt,CBrother *b)
953{
954 ASSERT(b);
955CString str = fmt;
956CString rv;
957 while(!str.IsEmpty()){
958 int pe = str.Find('%');
959 if(pe<0){
960 rv+=str;
961 str.Empty();
962 }else{
963 rv+=str.Left(pe);
964 str = str.Mid(pe+1);
965 if(!str.IsEmpty()){
966 switch(str[0]){
967 case'%':
968 rv+="%";
969 break;
970 case'h':
971 case'H':
972 rv+=b->m_Host;
973 break;
974 case'd':
975 case'D':
976 rv+=b->m_Desc;
977 break;
978 }
979 str=str.Mid(1);
980 }else{
981 rv+="%"+str;
982 str.Empty();
983 }
984 }
985 }
986 return rv;
987}
988
989void CBigBrotherDoc::OnUpdateFilePause(CCmdUI* pCmdUI)
990{
991 pCmdUI->SetCheck((flags&flagsSuspended)?1:0);
992}
993
994void CBigBrotherDoc::OnFilePause()
995{
996 flags^=flagsSuspended;
997 if(!(flags&flagsSuspended)){
998 ASSERT(m_RootBrother);
999 m_RootBrother->AppendSeparator();
1000 POSITION p = m_Brotherhood.GetHeadPosition();
1001 while(p){
1002 CBrother *b = m_Brotherhood.GetNext(p);
1003 ASSERT(b);
1004 b->AppendSeparator();
1005 }
1006 CheckPendingQueue();
1007 }else{
1008 ASSERT(m_BBView);
1009 m_BBView->KillTimer(TM_CHECK);
1010 }
1011}
1012
1013void CBigBrotherDoc::DeleteContents()
1014{
1015 CleanUp();
1016 CDocument::DeleteContents();
1017}
1018
1019void CBigBrotherDoc::OnCloseDocument()
1020{
1021 CleanUp();
1022 CDocument::OnCloseDocument();
1023}
1024
1025void CBigBrotherDoc::OnUpdateViewHostproperties(CCmdUI* pCmdUI)
1026{
1027 pCmdUI->SetCheck((flags&flagsShowProps)?1:0);
1028}
1029
1030void CBigBrotherDoc::OnViewHostproperties()
1031{
1032 ASSERT(m_BBView);
1033 ASSERT(m_BBView->m_Pages);
1034 flags^=flagsShowProps;
1035 if(flags&flagsShowProps)
1036 m_BBView->m_Pages->ShowWindow(SW_SHOW);
1037 else
1038 m_BBView->m_Pages->ShowWindow(SW_HIDE);
1039}