From fb8b43dbce8bc310718614384297aeaabb9a3cbb Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Mon, 05 Jul 2004 01:53:09 +0000 Subject: initial commit into svn repository git-svn-id: http://svn.klever.net/kin/bigbrother/trunk@1 fe716a7a-6dde-0310-88d9-d003556173a8 --- (limited to 'BigBrotherDoc.cpp') 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 @@ +// BigBrotherDoc.cpp : implementation of the CBigBrotherDoc class +// + +#include "stdafx.h" +#include "BigBrother.h" + +#include "BigBrotherDoc.h" +#include "BigBrotherView.h" +#include "ActivityView.h" +#include "HostPropertyPages.h" +#include "MainFrm.h" +#include "Preferences.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBigBrotherDoc + +IMPLEMENT_SERIAL(CBigBrotherDoc, CDocument, VERSIONABLE_SCHEMA | 3 ) +IMPLEMENT_SERIAL(CBrother, CObject, VERSIONABLE_SCHEMA | 2 ) +IMPLEMENT_SERIAL(CAction, CObject, VERSIONABLE_SCHEMA | 1 ) +IMPLEMENT_SERIAL(CLogEntry, CObject, VERSIONABLE_SCHEMA | 2 ) + +BEGIN_MESSAGE_MAP(CBigBrotherDoc, CDocument) + //{{AFX_MSG_MAP(CBigBrotherDoc) + ON_COMMAND(ID_BROTHERS_NEW, OnBrothersNew) + ON_UPDATE_COMMAND_UI(ID_BROTHERS_ADDBROTHER, OnUpdateBrothersAddbrother) + ON_COMMAND(ID_BROTHERS_ADDBROTHER, OnBrothersAddbrother) + ON_UPDATE_COMMAND_UI(ID_BROTHERS_DELETE, OnUpdateBrothersDelete) + ON_COMMAND(ID_BROTHERS_DELETE, OnBrothersDelete) + ON_COMMAND(ID_FILE_PREFERENCES, OnFilePreferences) + ON_UPDATE_COMMAND_UI(ID_FILE_PAUSE, OnUpdateFilePause) + ON_COMMAND(ID_FILE_PAUSE, OnFilePause) + ON_UPDATE_COMMAND_UI(ID_VIEW_HOSTPROPERTIES, OnUpdateViewHostproperties) + ON_COMMAND(ID_VIEW_HOSTPROPERTIES, OnViewHostproperties) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBigBrotherDoc construction/destruction + +CBigBrotherDoc::CBigBrotherDoc() + : m_MaxLogTime(0,1,0,0), m_Threads(0), m_MaxThreads(10), m_PingSize(32), m_RootBrother(NULL), + m_bSaveOnShutdown(TRUE), m_AutoSave(0,0,30,0), m_bStoreLastActivity(FALSE) +{ + m_BBView = NULL; + m_AView = NULL; +} + +CBigBrotherDoc::~CBigBrotherDoc() +{ + CleanUp(); +} + +BOOL CBigBrotherDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + CleanUp(); + m_RootBrother=new CBrother(); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CBigBrotherDoc serialization + +void CBigBrotherDoc::Serialize(CArchive& ar) +{ + ASSERT_VALID(this); + + CDocument::Serialize(ar); + + ar.MapObject(this); + ar.SerializeClass(RUNTIME_CLASS(CBigBrotherDoc)); + + if (ar.IsStoring()) + { + // Store to archive + ar << m_PingSize; + ar << m_MaxThreads; + ar << m_MaxLogTime; + ar << m_bSaveOnShutdown; + ar << m_AutoSave; + ar << m_LogFile; + ar << m_bStoreLastActivity; + ar << m_RootBrother; + m_Brotherhood.Serialize(ar); + } + else + { + UINT schema = ar.GetObjectSchema(); +#ifndef NDEBUG + { + CString tmp; + tmp.Format("Doc-OSchema: %u\n",schema); + TRACE0(tmp); + } +#endif + CleanUp(); + m_ThisMap.RemoveAll(); + // Read from archive + ar >> m_PingSize; + ar >> m_MaxThreads; + ar >> m_MaxLogTime; + if(schema>=2){ + ar >> m_bSaveOnShutdown; + ar >> m_AutoSave; + } + ar >> m_LogFile; + if(schema>=3) + ar >> m_bStoreLastActivity; + ar >> m_RootBrother; + m_Brotherhood.Serialize(ar); + // Read from archive + m_ThisMap.RemoveAll(); + // Log loading + CString logLine; + logLine.Format(IDS_LOG_LOADFILE,(LPCTSTR)GetTitle()); + logLine=CTime::GetCurrentTime().Format(IDS_LOG_DATEFORMAT)+" "+logLine; + LogLine(logLine); + } +} + +///////////////////////////////////////////////////////////////////////////// +// CBigBrotherDoc diagnostics + +#ifdef _DEBUG +void CBigBrotherDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CBigBrotherDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CBigBrotherDoc commands + +CBrother::CBrother(CBrother *daddy) +{ + CleanUp(); + m_Daddy=daddy; + ParentalAdjust(TRUE); +} + +void CBrother::CleanUp() +{ + m_Item=NULL; + flags=0; + m_bLog=TRUE; + m_Daddy=NULL; + m_Desc.Empty(); + m_Down.CleanUp(); + m_Host.Empty(); + m_IntervalBad=30; + m_IntervalGood=30; + m_Retries=3; + m_TimeOut=5000; + m_Up.CleanUp(); + m_bPinged=FALSE; + m_bPending=FALSE; + m_bIsUp=TRUE; + m_bPinging=FALSE; + m_bUp=TRUE; + m_bToKill=FALSE; + m_Doc=NULL; +} + +CAction::CAction() +{ + CleanUp(); +} + +void CAction::CleanUp() +{ + flags=0; + m_Custom.Empty(); + m_Sound.Empty(); +} + +CAction& CAction::operator=(CAction& src) +{ + flags=src.flags; + m_Custom=src.m_Custom; + m_Sound=src.m_Sound; + return *this; +} + +void CBrother::ParentalAdjust(BOOL cleanUp) +{ + if(!m_Daddy){ + flags|=flagsOverrideIntervals|flagsOverrideTimeout|flagsOverrideRetries|flagsOverrideActions|flagsOverrideLogging; + if(cleanUp){ + m_Desc.LoadString(IDS_ROOTNODENAME); + m_IntervalBad=30, m_IntervalGood=30; + m_TimeOut=5000; + m_Retries=3; + { + m_Up.CleanUp(); + m_Down.CleanUp(); + m_Up.flags=m_Down.flags=CAction::flagsPlayASound; + m_Up.m_Sound.LoadString(IDS_ACTION_HOST_UP); + m_Down.m_Sound.LoadString(IDS_ACTION_HOST_DOWN); + } + m_bLog=TRUE; + } + }else{ + if(!(flags&flagsOverrideIntervals)){ + CBrother *parent = m_Daddy; + while(!(parent->flags&flagsOverrideIntervals)){ + ASSERT(parent->m_Daddy); + parent=parent->m_Daddy; + } + m_IntervalBad=parent->m_IntervalBad; + m_IntervalGood=parent->m_IntervalGood; + } + if(!(flags&flagsOverrideTimeout)){ + CBrother *parent = m_Daddy; + while(!(parent->flags&flagsOverrideTimeout)){ + ASSERT(parent->m_Daddy); + parent=parent->m_Daddy; + } + m_TimeOut=parent->m_TimeOut; + } + if(!(flags&flagsOverrideRetries)){ + CBrother *parent = m_Daddy; + while(!(parent->flags&flagsOverrideRetries)){ + ASSERT(parent->m_Daddy); + parent=parent->m_Daddy; + } + m_Retries=parent->m_Retries; + } + if(!(flags&flagsOverrideActions)){ + CBrother *parent = m_Daddy; + while(!(parent->flags&flagsOverrideActions)){ + ASSERT(parent->m_Daddy); + parent=parent->m_Daddy; + } + m_Up=parent->m_Up; + m_Down=parent->m_Down; + } + if(!(flags&flagsOverrideLogging)){ + CBrother *parent = m_Daddy; + while(!(parent->flags&flagsOverrideLogging)){ + ASSERT(parent->m_Daddy); + parent=parent->m_Daddy; + } + m_bLog=parent->m_bLog; + } + } +} + +void CBigBrotherDoc::OnChangedViewList() +{ + m_BBView=NULL; + m_AView=NULL; +POSITION p = GetFirstViewPosition(); + while(p){ + CView* v = GetNextView(p); + if(v->IsKindOf(RUNTIME_CLASS(CBigBrotherView))){ + ASSERT(!m_BBView); + m_BBView=(CBigBrotherView*)v; + }else if(v->IsKindOf(RUNTIME_CLASS(CActivityView))){ + ASSERT(!m_AView); + m_AView=(CActivityView*)v; + } + } + + CDocument::OnChangedViewList(); +} + +void CBigBrotherDoc::OnBrothersNew() +{ + ASSERT(m_BBView); +CBrother *bro = m_BBView->GetCurrentBrother(); + ASSERT(bro); +CBrother *lb = new CBrother(bro); + m_Brotherhood.AddTail(lb); + SetModifiedFlag(); + m_BBView->AddBrother(lb); + m_BBView->GotoBrother(lb); +} + +void CBigBrotherDoc::CheckPendingQueue() +{ + if(flags&flagsSuspended) + return; +CTime currentTime = CTime::GetCurrentTime(); +CTime nearestCheck; +BOOL nearested = CheckPendingBrother(m_RootBrother,currentTime,nearestCheck,FALSE); +POSITION p = m_Brotherhood.GetHeadPosition(); + while(p){ + CBrother *b = (CBrother*)m_Brotherhood.GetNext(p); + ASSERT(b); + nearested|=CheckPendingBrother(b,currentTime,nearestCheck,nearested); + } + if(m_AutoSave.GetTotalMinutes()){ + CTime nc = m_AutoSaved+m_AutoSave; + if(nc<=currentTime){ + if(IsModified()) + DoFileSave(); + m_AutoSaved=currentTime; + while(nc<=currentTime) + nc=nc+m_AutoSave; + } + if((!nearested) || ncSetTimer(TM_CHECK,timer,NULL); +} + +BOOL CBigBrotherDoc::CheckPendingBrother(CBrother* b,CTime& currentTime,CTime& nearestCheck,BOOL nearested) +{ + if(!b) + return FALSE; + if(b->m_Host.IsEmpty() || b->m_bPinging){ + b->m_bPending=FALSE; + return FALSE; + } + if(b->m_bPending){ + TryBrother(b); + return FALSE; + } +CTime nextCheck = b->m_Pinged+CTimeSpan(b->m_bIsUp?b->m_IntervalGood:b->m_IntervalBad); + if(nextCheck<=currentTime){ + TryBrother(b); + return FALSE; + } + if((!nearested) || nextCheckm_Host.IsEmpty()); + if(!(m_Threadsm_bPending=TRUE; + return; + } + if(!m_BBView) + return; // In case we're dying + m_BBView->SendMessage(WM_ACTIVITYCOUNT,1,0); + b->m_Doc=this; + b->m_bPinging=TRUE; + VERIFY(AfxBeginThread(CBrother::DoCheck,(LPVOID)b)); +} + +UINT CBrother::DoCheck(LPVOID pParam) +{ +CBrother *b = (CBrother*)pParam; + ASSERT(b); + return b->Check(); +} + +UINT CBrother::Check() +{ +CBigBrotherDoc *m_Doc = (CBigBrotherDoc*)CBrother::m_Doc; + + if(!m_bToKill){ + ASSERT(m_Doc); + ASSERT(m_Doc->IsKindOf(RUNTIME_CLASS(CBigBrotherDoc))); + ASSERT(m_Doc->m_BBView); + m_Doc->m_BBView->PostMessage(WM_UPDATETREEBROTHER,0,(LPARAM)this); + } + +CICMP *pICMP = NULL; +UINT dataSize = m_bToKill?32:m_Doc->m_PingSize; +in_addr ip; + ip.s_addr = inet_addr(m_Host); +CLogEntry le; + if(ip.s_addr==INADDR_NONE){ + hostent *he = gethostbyname(m_Host); + if(!he){ + le.m_Status.LoadString(IDS_PS_FAILEDTORESOLVE); + goto goBye; + } + memmove(&ip.s_addr,he->h_addr,sizeof(ip.s_addr)); + } + pICMP = CICMP::CreateICMP(); + if(!(pICMP && pICMP->Initialize())) { + le.m_Status.LoadString(IDS_PS_UNABLETOICMP); + goto goBye; + } + INT status; + LONG rtt; + rtt=pICMP->Ping(ip,dataSize,m_TimeOut,&status); + switch(status){ + case CICMP::ipSuccess: + le.m_bReached=TRUE; + le.m_RTT=rtt; + le.m_Status.Empty(); + break; + case CICMP::ipBuffTooSmall: + le.m_Status.LoadString(IDS_PS_INTERNALERROR); + break; + case CICMP::ipDestNetUnreachable: + le.m_Status.LoadString(IDS_PS_NETUNREACHABLE); + break; + case CICMP::ipDestHostUnreachable: + le.m_Status.LoadString(IDS_PS_HOSTUNREACHABLE); + break; + case CICMP::ipDestProtUnreachable: + le.m_Status.LoadString(IDS_PS_PROTUNREACHABLE); + break; + case CICMP::ipDestPortUnreachable: + le.m_Status.LoadString(IDS_PS_PORTUNREACHABLE); + case CICMP::ipNoResources: + le.m_Status.LoadString(IDS_PS_NORESOURCES); + break; + case CICMP::ipBadOption: + le.m_Status.LoadString(IDS_PS_INTERNALERROR); + break; + case CICMP::ipHWError: + le.m_Status.LoadString(IDS_PS_HWERROR); + break; + case CICMP::ipPacketTooBig: + le.m_Status.LoadString(IDS_PS_BIGPACKET); + break; + case CICMP::ipTimeOut: + le.m_Status.LoadString(IDS_PS_TIMEOUT); + break; + case CICMP::ipBadRequest: + le.m_Status.LoadString(IDS_PS_INTERNALERROR); + break; + case CICMP::ipBadRoute: + le.m_Status.LoadString(IDS_PS_BADROUTE); + break; + case CICMP::ipTTLExpiredInTransit: + le.m_Status.LoadString(IDS_PS_TTLEXPTRANSIT); + break; + case CICMP::ipTTLExpiredInReasm: + le.m_Status.LoadString(IDS_PS_TTLEXPREASM); + break; + case CICMP::ipParamProblem: + le.m_Status.LoadString(IDS_PS_IPARAMP); + break; + case CICMP::ipSourceQuench: + le.m_Status.LoadString(IDS_PS_SOURCEQUENCH); + break; + case CICMP::ipOptionTooBig: + le.m_Status.LoadString(IDS_PS_BIGOPTION); + break; + case CICMP::ipBadDest: + le.m_Status.LoadString(IDS_PS_BADDEST); + break; + default: + le.m_Status.Format(IDS_PS_UNKNOWNERROR,status); + break; + } +goBye: + if(pICMP) { + pICMP->Deinitialize(); + delete pICMP; + } + if(le.m_bReached) + m_bIsUp=TRUE; + else{ + if(m_bIsUp) + m_HowDown=0; + m_bIsUp=FALSE; + m_HowDown++; + } + + le.m_Time=CTime::GetCurrentTime(); + +CLogEntry *newLE = NULL; + if(!m_Log.IsEmpty()){ + CLogEntry *head = m_Log.GetHead(); + while(head && (m_bToKill?FALSE:(m_Doc->m_MaxLogTime<(le.m_Time-head->m_Time)))){ + m_Log.RemoveHead(); + if(newLE) + delete head; + else + newLE=head; + if(m_Log.IsEmpty()) + head=NULL; + else + head = m_Log.GetHead(); + } + } + if(newLE) + (*newLE)=le; + else + newLE=new CLogEntry(le); + m_Log.AddTail(newLE); + + if(m_bToKill) + delete this; + else{ + m_bPinged=TRUE; + m_Pinged = CTime::GetCurrentTime(); + if(m_Doc) + m_Doc->m_BBView->SendMessage(WM_ACTIVITYCOUNT,(WPARAM)-1,0); + if(m_Doc) + m_Doc->SetModifiedFlag(); + if(m_Doc) + m_Doc->m_BBView->SendMessage(WM_UPDATETREEBROTHER,TRUE,(LPARAM)this); + } + return 0; +} + +CLogEntry::CLogEntry() +{ + flags=0; + m_bReached=FALSE; + m_Status.Empty(); + m_Time=CTime::GetCurrentTime(); +} + +CBrother::~CBrother() +{ +POSITION p = m_Log.GetHeadPosition(); + while(p){ + CLogEntry *le = m_Log.GetNext(p); + delete le; + } + m_Log.RemoveAll(); +} + +void CBigBrotherDoc::CleanUp() +{ + if(m_BBView && m_BBView->m_Pages){ + m_BBView->m_Pages->SetBrother(NULL); + } + if(m_RootBrother){ + while(!m_Brotherhood.IsEmpty()){ + CBrother *b = m_Brotherhood.GetHead(); + ASSERT(b); + b->m_Doc=this; + b->Suicide(); + } + m_RootBrother->m_Doc=this; + m_RootBrother->Suicide(); + m_RootBrother=NULL; + } + m_MaxLogTime = CTimeSpan(0,1,0,0); + m_MaxThreads = 5; + m_PingSize = 32; + m_bSaveOnShutdown = TRUE; + m_AutoSave = CTimeSpan(0,0,30,0); + m_AutoSaved = CTime::GetCurrentTime(); + flags=0; +} + +CBrother* CBigBrotherDoc::GetCurrentBrother() +{ + if(m_BBView); + return m_BBView->GetCurrentBrother(); + return NULL; +} + +BOOL CBrother::IsValuable() +{ + return !m_Host.IsEmpty(); +} + +void CBigBrotherDoc::GetFamily(CBrother *b,CBrotherList *bh) +{ + ASSERT(b); + ASSERT(bh); + ASSERT(m_BBView); + m_BBView->GetFamily(b,bh); +} + +void CBigBrotherDoc::OnUpdateBrothersAddbrother(CCmdUI* pCmdUI) +{ + ASSERT(m_BBView); +CBrother *bro = m_BBView->GetCurrentBrother(); + if(bro) + pCmdUI->Enable(bro->m_Daddy!=NULL); + else + pCmdUI->Enable(FALSE); +} + +void CBigBrotherDoc::OnBrothersAddbrother() +{ + ASSERT(m_BBView); +CBrother *bro = m_BBView->GetCurrentBrother(); + ASSERT(bro); + bro = bro->m_Daddy; + ASSERT(bro); +CBrother *lb = new CBrother(bro); + m_Brotherhood.AddTail(lb); + SetModifiedFlag(); + m_BBView->AddBrother(lb); + m_BBView->GotoBrother(lb); +} + +BOOL CAction::PlayASound(LPCTSTR sound) +{ +CString str; + str.LoadString(IDS_ACTION_HOST_UP); + if(!str.CompareNoCase(sound)) + return ::PlaySound((LPCTSTR)IDW_HOST_UP,AfxGetApp()->m_hInstance,SND_ASYNC|SND_NODEFAULT|SND_NOSTOP|SND_NOWAIT|SND_RESOURCE); + str.LoadString(IDS_ACTION_HOST_DOWN); + if(!str.CompareNoCase(sound)) + return ::PlaySound((LPCTSTR)IDW_HOST_DOWN,AfxGetApp()->m_hInstance,SND_ASYNC|SND_NODEFAULT|SND_NOSTOP|SND_NOWAIT|SND_RESOURCE); + str.LoadString(IDS_ACTION_SYSTEM_OK); + if(!str.CompareNoCase(sound)) + return MessageBeep(MB_ICONASTERISK); + str.LoadString(IDS_ACTION_SYSTEM_CRITICAL); + if(!str.CompareNoCase(sound)) + return MessageBeep(MB_ICONHAND); + return ::PlaySound(sound,AfxGetApp()->m_hInstance,SND_ASYNC|SND_NODEFAULT|SND_NOSTOP|SND_NOWAIT|SND_FILENAME); +} + +CLogEntry& CLogEntry::operator=(CLogEntry& src) +{ + m_bReached=src.m_bReached; + m_RTT=src.m_RTT; + m_Status=src.m_Status; + m_Time=src.m_Time; + flags=src.flags; + return *this; +} + +CLogEntry::CLogEntry(CLogEntry& src) +{ + (*this)=src; +} + +void CAction::PerformAction(CBrother *b) +{ + if(flags&flagsPlayASound) + PlayASound(m_Sound); + if(flags&flagsRunCustom){ + CString cmd = FormatLine(m_Custom,b); + system(cmd); + } +} + +void CBrother::Serialize(CArchive& ar) +{ + ASSERT_VALID(this); + + CObject::Serialize(ar); + +CBigBrotherDoc *pDoc = (CBigBrotherDoc*)ar.m_pDocument; + ASSERT(pDoc); + ASSERT(pDoc->IsKindOf(RUNTIME_CLASS(CBigBrotherDoc))); + + if (ar.IsStoring()) + { + if(pDoc->m_BBView && (pDoc->m_BBView->GetTreeCtrl().GetItemState(m_Item,TVIS_EXPANDED)&TVIS_EXPANDED)) + flags|=flagsExpandedTree; + else + flags&=~flagsExpandedTree; + if(pDoc->GetCurrentBrother()==this) + flags|=flagsCurrentBrother; + else + flags&=~flagsCurrentBrother; + // Store to archive + ar << (DWORD)this; + ar << (DWORD)m_Daddy; + ar << flags; + ar << m_bLog; + ar << m_Host; + ar << m_Desc; + ar << m_IntervalGood; + ar << m_IntervalBad; + ar << m_TimeOut; + ar << m_Retries; + ar << &m_Up; + ar << &m_Down; + if(pDoc->m_bStoreLastActivity) + m_Log.Serialize(ar); + else{ + CLogList tmp; + tmp.Serialize(ar); + } + }else{ +#ifndef NDEBUG + { + CString tmp; + tmp.Format("Bro-OSchema: %u\n",ar.GetObjectSchema()); + TRACE0(tmp); + } +#endif + // Read from archive + DWORD dw; + ar >> dw; + pDoc->m_ThisMap[dw]=this; + ar >> dw; + if(dw){ + VERIFY(pDoc->m_ThisMap.Lookup(dw,m_Daddy)); + }else + m_Daddy=NULL; + ar >> flags; + ar >> m_bLog; + ar >> m_Host; + ar >> m_Desc; + ar >> m_IntervalGood; + ar >> m_IntervalBad; + ar >> m_TimeOut; + ar >> m_Retries; + CAction *act = NULL; + ar >> act; + m_Up = *act; + delete act; + act = NULL; + ar >> act; + m_Down = *act; + delete act; + m_Log.Serialize(ar); + ParentalAdjust(); + } +} + +void CAction::Serialize(CArchive& ar) +{ + ASSERT_VALID(this); + + CObject::Serialize(ar); + + if (ar.IsStoring()) + { + // Store to archive + ar << flags; + ar << m_Sound; + ar << m_Custom; + }else{ +#ifndef NDEBUG + { + CString tmp; + tmp.Format("Act-OSchema: %u\n",ar.GetObjectSchema()); + TRACE0(tmp); + } +#endif + // Read from archive + ar >> flags; + ar >> m_Sound; + ar >> m_Custom; + } +} + +void CLogEntry::Serialize(CArchive& ar) +{ + ASSERT_VALID(this); + + CObject::Serialize(ar); + + if (ar.IsStoring()) + { + // Store to archive + ar << flags; + ar << m_Time; + ar << m_bReached; + ar << m_RTT; + ar << m_Status; + }else{ + UINT schema = ar.GetObjectSchema(); + /* +#ifndef NDEBUG + { + CString tmp; + tmp.Format("Log-OSchema: %u\n",schema); + TRACE0(tmp); + } +#endif + */ + // Read from archive + if(schema>=2){ + ar >> flags; + } + ar >> m_Time; + ar >> m_bReached; + ar >> m_RTT; + ar >> m_Status; + } +} + +CBrother::CBrother() +{ + CleanUp(); + ParentalAdjust(TRUE); +} + +void CBigBrotherDoc::OnUpdateBrothersDelete(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(GetCurrentBrother()!=NULL); +} + +void CBigBrotherDoc::OnBrothersDelete() +{ + ASSERT(m_BBView); +CBrother *b = GetCurrentBrother(); + ASSERT(b); + m_BBView->KillBrother(b); + SetModifiedFlag(); +} + +void CBrother::Suicide() +{ + ASSERT(m_Doc); + ASSERT(m_Doc->IsKindOf(RUNTIME_CLASS(CBigBrotherDoc))); +CBigBrotherDoc *pDoc = (CBigBrotherDoc*)m_Doc; + if(pDoc->m_BBView && pDoc->m_BBView->m_Pages->m_Brother==this) + pDoc->m_BBView->m_Pages->m_Brother=NULL; +POSITION p = pDoc->m_Brotherhood.Find(this); + if(p) + pDoc->m_Brotherhood.RemoveAt(p); +#ifndef NDEBUG + else{ + ASSERT(!m_Daddy); + } +#endif + m_Item=NULL; + if(m_bPinging){ + m_bToKill=TRUE; + m_Daddy=NULL; + m_Doc=NULL; + }else + delete this; +} + +BOOL CBrother::operator==(CBrother& b) +{ + if(flags!=b.flags) + return FALSE; + if(m_bLog!=b.m_bLog) + return FALSE; + if(m_Desc.Compare(b.m_Desc)) + return FALSE; + if(m_Down!=b.m_Down) + return FALSE; + if(m_Host.Compare(b.m_Host)) + return FALSE; + if(m_IntervalGood!=b.m_IntervalGood || m_IntervalBad!=b.m_IntervalBad) + return FALSE; + if(m_Retries!=b.m_Retries) + return FALSE; + if(m_TimeOut!=b.m_TimeOut) + return FALSE; + if(m_Up!=b.m_Up) + return FALSE; + return TRUE; +} + +BOOL CBrother::operator!=(CBrother& b) +{ + return !((*this)==b); +} + +BOOL CAction::operator==(CAction& a) +{ + if(flags!=a.flags) + return FALSE; + if(m_Custom.Compare(a.m_Custom)) + return FALSE; + if(m_Sound.Compare(a.m_Sound)) + return FALSE; + return TRUE; +} + +BOOL CAction::operator!=(CAction& a) +{ + return !((*this)==a); +} + +CBrother& CBrother::operator=(CBrother& b) +{ + flags=b.flags; + m_bLog=b.m_bLog; + m_Desc=b.m_Desc; + m_Down=b.m_Down; + m_Host=b.m_Host; + m_IntervalGood=b.m_IntervalGood; + m_IntervalBad=b.m_IntervalBad; + m_Retries=b.m_Retries; + m_TimeOut=b.m_TimeOut; + m_Up=b.m_Up; + return *this; +} + +BOOL CBigBrotherDoc::SaveModified() +{ + if(((CMainFrame*)(AfxGetApp()->m_pMainWnd))->m_bShuttingDown && m_bSaveOnShutdown){ + DoFileSave(); + ((CMainFrame*)(AfxGetApp()->m_pMainWnd))->m_bShuttingDown = FALSE; + return TRUE; + } + return CDocument::SaveModified(); +} + +void CBrother::AppendSeparator() +{ +CLogEntry *le = new CLogEntry(); + le->flags=CLogEntry::flagsSeparator; + m_Log.AddTail(le); +} + +void CBigBrotherDoc::OnFilePreferences() +{ +CPreferences prefs(AfxGetApp()->m_pMainWnd); + prefs.m_AutosaveMinutes=m_AutoSave.GetTotalMinutes(); + prefs.m_LogFile=m_LogFile; + prefs.m_MaxThreads=m_MaxThreads; + prefs.m_PingSize=m_PingSize; + prefs.m_SaveOnShutdown=m_bSaveOnShutdown; + prefs.m_LogMins=m_MaxLogTime.GetTotalMinutes(); + prefs.m_bStoreLastActivity=m_bStoreLastActivity; + if(prefs.DoModal()==IDOK){ + m_AutoSave = CTimeSpan(0,prefs.m_AutosaveMinutes/60,prefs.m_AutosaveMinutes%60,0); + m_LogFile=prefs.m_LogFile; + m_MaxThreads=prefs.m_MaxThreads; + m_PingSize=prefs.m_PingSize; + m_bSaveOnShutdown=prefs.m_SaveOnShutdown; + m_MaxLogTime = CTimeSpan(0,prefs.m_LogMins/60,prefs.m_LogMins%60,0); + m_bStoreLastActivity=prefs.m_bStoreLastActivity; + } +} + +void CBigBrotherDoc::LogLine(LPCTSTR str) +{ + if(!m_LogFile.IsEmpty()){ + TRY{ + CFile file(m_LogFile,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite|CFile::shareDenyWrite|CFile::typeBinary); + file.SeekToEnd(); + file.Write(str,strlen(str)); + file.Write("\r\n",2); + file.Close(); + }CATCH(CFileException, e){ +#ifndef NDEBUG + afxDump << "Logging error: " << e->m_cause << "\n"; +#endif + }END_CATCH + } +} + +CString CAction::FormatLine(LPCTSTR fmt,CBrother *b) +{ + ASSERT(b); +CString str = fmt; +CString rv; + while(!str.IsEmpty()){ + int pe = str.Find('%'); + if(pe<0){ + rv+=str; + str.Empty(); + }else{ + rv+=str.Left(pe); + str = str.Mid(pe+1); + if(!str.IsEmpty()){ + switch(str[0]){ + case '%': + rv+="%"; + break; + case 'h': + case 'H': + rv+=b->m_Host; + break; + case 'd': + case 'D': + rv+=b->m_Desc; + break; + } + str=str.Mid(1); + }else{ + rv+="%"+str; + str.Empty(); + } + } + } + return rv; +} + +void CBigBrotherDoc::OnUpdateFilePause(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck((flags&flagsSuspended)?1:0); +} + +void CBigBrotherDoc::OnFilePause() +{ + flags^=flagsSuspended; + if(!(flags&flagsSuspended)){ + ASSERT(m_RootBrother); + m_RootBrother->AppendSeparator(); + POSITION p = m_Brotherhood.GetHeadPosition(); + while(p){ + CBrother *b = m_Brotherhood.GetNext(p); + ASSERT(b); + b->AppendSeparator(); + } + CheckPendingQueue(); + }else{ + ASSERT(m_BBView); + m_BBView->KillTimer(TM_CHECK); + } +} + +void CBigBrotherDoc::DeleteContents() +{ + CleanUp(); + CDocument::DeleteContents(); +} + +void CBigBrotherDoc::OnCloseDocument() +{ + CleanUp(); + CDocument::OnCloseDocument(); +} + +void CBigBrotherDoc::OnUpdateViewHostproperties(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck((flags&flagsShowProps)?1:0); +} + +void CBigBrotherDoc::OnViewHostproperties() +{ + ASSERT(m_BBView); + ASSERT(m_BBView->m_Pages); + flags^=flagsShowProps; + if(flags&flagsShowProps) + m_BBView->m_Pages->ShowWindow(SW_SHOW); + else + m_BBView->m_Pages->ShowWindow(SW_HIDE); +} -- cgit v0.9.0.2