00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 #include "stdafx.h"
00037 #include "RealTimeTraceRouteSocket.h"
00038 
00039 #include "ErrorHandlerMacros.h"
00040 #include "ThreadPool.h"
00041 #include "GenericCriticalSection.h"
00042 #include "OSManager.h"
00043 
00044 #include <atlbase.h>
00045 
00046 #ifdef _MEMORY_DEBUG 
00047     #define new    DEBUG_NEW  
00048     #define malloc DEBUG_MALLOC  
00049     static char THIS_FILE[] = __FILE__;  
00050 #endif
00051 
00052 KOMODIA_NAMESPACE_START
00053 
00054 
00055 
00056 #define CRealTimeDNSManager_Class "CRealTimeDNSManager"
00057 
00058 CRealTimeTraceRouteSocket::CRealTimeDNSManager::CRealTimeDNSManager(CRealTimeTraceRouteSocket* pFather,
00059                                                                     const std::string strDNSServer,
00060                                                                     BOOL bTCP) : CDNSManager(strDNSServer,
00061                                                                                              bTCP,
00062                                                                                              TRUE,
00063                                                                                              TRUE),
00064                                                                                  m_pFather(pFather)
00065 {
00066     try
00067     {
00068         
00069         SetName(CRealTimeDNSManager_Class);
00070     }
00071     ERROR_HANDLER("CRealTimeDNSManager")
00072 }
00073 
00074 CRealTimeTraceRouteSocket::CRealTimeDNSManager::~CRealTimeDNSManager()
00075 {
00076 }
00077 
00078 void CRealTimeTraceRouteSocket::CRealTimeDNSManager::OnDNSError(int iErrorCode,
00079                                                                 LPVOID lpLocalIDData)
00080 {
00081     try
00082     {
00083         
00084         m_pFather->AdjustResolvers(-1);
00085 
00086         
00087         m_pFather->DNSDone();
00088     }
00089     ERROR_HANDLER("OnDNSError")
00090 }
00091 
00092 void CRealTimeTraceRouteSocket::CRealTimeDNSManager::OnDNSTimeout(const KomodiaDNS::CDNSQuery& rQuery,
00093                                                                   LPVOID lpLocalIDData)
00094 {
00095     try
00096     {
00097         
00098         m_pFather->AdjustResolvers(-1);
00099 
00100         
00101         m_pFather->DNSDone();
00102     }
00103     ERROR_HANDLER("OnDNSTimeout")
00104 }
00105 
00106 void CRealTimeTraceRouteSocket::CRealTimeDNSManager::OnDNSReceive(KomodiaDNS::CDNSAnswers* pAnswers,
00107                                                                   LPVOID lpLocalIDData)
00108 {
00109     try
00110     {
00111         
00112         std::auto_ptr<KomodiaDNS::CDNSAnswers> pProtection(pAnswers);
00113 
00114         
00115         if (m_pFather->m_bTraceDone)
00116             return;
00117 
00118         
00119         if (lpLocalIDData)
00120         {
00121             
00122             TraceRouteData* pData;
00123             pData=(TraceRouteData*)lpLocalIDData;
00124 
00125             
00126             pData->pDNS=NULL;
00127 
00128             
00129             if (pAnswers->IsResolved())
00130                 
00131                 if (!pAnswers->GetAnswer().empty())
00132                 {
00133                     
00134                     pData->sReverseDNS=pAnswers->GetAnswer();
00135 
00136                     
00137                     pData->bResolved=TRUE;
00138 
00139                     
00140                     if (pData->aReplyingAddress)
00141                     {
00142                         
00143                         m_pFather->TraceDataForModify(pData,
00144                                                       TRUE);
00145 
00146                         
00147                         m_pFather->TraceData(pData,
00148                                              TRUE);
00149                     }
00150                 }
00151                 else
00152                     ReportError("CRealTimeDNSManager","Received empty answer!");
00153         }
00154 
00155         
00156         m_pFather->AdjustResolvers(-1);
00157 
00158         
00159         m_pFather->DNSDone();
00160     }
00161     ERROR_HANDLER("OnDNSReceive")
00162 }
00163 
00164 
00165 
00166 #define CRealTimeTraceRouteSocket_Class "CRealTimeTraceRouteSocket"
00167 
00168 unsigned short CRealTimeTraceRouteSocket::m_sPortStart=0;
00169 
00170 CRealTimeTraceRouteSocket::CRealTimeTraceRouteSocket(std::string sDNSServer,
00171                                                      BOOL bDNSTcp,
00172                                                      BOOL bMultithreaded) : CPingSocket(),
00173                                                                             m_bTraceDone(TRUE),
00174                                                                             m_pManager(NULL),
00175                                                                             m_pCSection(NULL),
00176                                                                             m_bInitialized(FALSE),
00177                                                                             m_bResolveIPs(TRUE),
00178                                                                             m_pCSectionResolve(NULL),
00179                                                                             m_pCSectionGeneral(NULL),
00180                                                                             m_bFinishing(FALSE),
00181                                                                             m_bPartialDone(FALSE)
00182 {
00183     try
00184     {
00185         
00186         SetName(CRealTimeTraceRouteSocket_Class);
00187 
00188         
00189         SetUseSameID(TRUE);
00190 
00191         
00192         m_pManager=new CRealTimeDNSManager(this,
00193                                            sDNSServer,
00194                                            bDNSTcp);
00195 
00196         
00197         m_pCSection=COSManager::CreateCriticalSection();
00198         m_pCSectionResolve=COSManager::CreateCriticalSection();
00199         m_pCSectionGeneral=COSManager::CreateCriticalSection();
00200 
00201         
00202         if (!(m_bInitialized=m_pManager->Initialize()))
00203             
00204             ReportError("CRealTimeTraceRouteSocket","Failed to initialize DNS!");
00205         else 
00206         {
00207             
00208             m_pManager->SetDNSTimeout(15000);
00209             
00210             
00211             m_pManager->SetConnectionTimeout(7500);
00212 
00213             
00214             if (bMultithreaded)
00215                 m_pManager->ParseMultithreaded(10);
00216         }
00217     }
00218     ERROR_HANDLER("CRealTimeTraceRouteSocket")
00219 }
00220 
00221 CRealTimeTraceRouteSocket::~CRealTimeTraceRouteSocket()
00222 {
00223     try
00224     {
00225         
00226         delete m_pCSection;
00227         delete m_pCSectionResolve;
00228         delete m_pCSectionGeneral;
00229 
00230         
00231         delete m_pManager;
00232     }
00233     ERROR_HANDLER("~CRealTimeTraceRouteSocket")
00234 }
00235 
00236 BOOL CRealTimeTraceRouteSocket::IsTraceDone()const
00237 {
00238     return m_bTraceDone;
00239 }
00240 
00241 BOOL CRealTimeTraceRouteSocket::TraceRoute(const std::string& rDestinationAddress,
00242                                            DWORD dwTimeout)
00243 {
00244     try
00245     {
00246         return TraceRoute(StringToLong(rDestinationAddress),
00247                           dwTimeout);
00248     }
00249     ERROR_HANDLER_RETURN("TraceRoute",FALSE)
00250 }
00251 
00252 BOOL CRealTimeTraceRouteSocket::TraceRoute(IP aDestinationAddress,
00253                                            DWORD dwTimeout)
00254 {
00255     try
00256     {
00257         if (!m_bTraceDone ||
00258             !m_bInitialized ||
00259             m_bFinishing ||
00260             m_bPartialDone)
00261             return FALSE;
00262 
00263         
00264         m_bTraceDone=FALSE;
00265         m_bPartialDone=FALSE;
00266         m_bFinishing=FALSE;
00267 
00268         
00269         m_aTracedAddress=aDestinationAddress;
00270 
00271         
00272         for (int iCounter=0;iCounter<=mhMaxHops;++iCounter)
00273         {
00274             
00275             m_aData[iCounter].aReplyingAddress=0;
00276             m_aData[iCounter].ucTTL=0;
00277             m_aData[iCounter].dwElapsedTime=0;
00278             m_aData[iCounter].pDNS=m_pManager;
00279             m_aData[iCounter].bResolved=FALSE;
00280             m_aData[iCounter].bTarget=FALSE;
00281             m_aData[iCounter].bFinal=FALSE;
00282             m_aData[iCounter].lpUserData=NULL;
00283 
00284             
00285             std::auto_ptr<CGenericCriticalSection> pProtection(COSManager::CreateCriticalSection());
00286 
00287             
00288             m_aData[iCounter].pCSection=pProtection;
00289         }
00290 
00291         m_ucMaxHOP=0;
00292         m_ucMinHOP=mhMaxHops;
00293 
00294         
00295         
00296         m_aData[mhMaxHops].bTarget=TRUE;
00297 
00298         
00299         m_ulResolvers=0;
00300 
00301         
00302         m_usPortStart=GetPortStart();
00303 
00304         
00305         for (int iPings=0;iPings<3;++iPings)
00306             for (int iCounter=1;
00307                  iCounter<=mhMaxHops;
00308                  ++iCounter)
00309             {
00310                 
00311                 SetTTL(iCounter);
00312 
00313                 
00314                 SetID(iCounter);
00315 
00316                 
00317                 SetSequence(m_usPortStart);
00318 
00319                 
00320                 if (!Ping(aDestinationAddress,
00321                           0))
00322                 {
00323                     
00324                     m_bTraceDone=TRUE;
00325 
00326                     
00327                     TraceDone(TRUE);
00328 
00329                     
00330                     return FALSE;
00331                 }
00332             }
00333 
00334         
00335         SetTimeout(dwTimeout);
00336 
00337         
00338         if (m_bResolveIPs)
00339         {
00340             
00341             AdjustResolvers(1);
00342 
00343             
00344             ResolveThreadData* pThreadData;
00345             pThreadData=new ResolveThreadData;
00346 
00347             
00348             pThreadData->pClass=this;
00349             pThreadData->pData=&m_aData[mhMaxHops];
00350 
00351             
00352             
00353             m_pManager->GetThreadManager()->SubmitJob(ResolveData,(LPVOID)pThreadData);
00354         }
00355 
00356         
00357         return TRUE;
00358     }
00359     ERROR_HANDLER_RETURN("TraceRoute",FALSE)
00360 }
00361 
00362 void CRealTimeTraceRouteSocket::PingDoneData(IP aReplyingAddress,
00363                                              unsigned char ucTTL,
00364                                              DWORD dwTimeElapsed,
00365                                              int iDataSize,
00366                                              unsigned short usID,
00367                                              BOOL bTTLExpired)
00368 {
00369     try
00370     {
00371         
00372         if (m_bTraceDone ||
00373             m_bPartialDone)
00374             return;
00375 
00376         if (usID>mhMaxHops)
00377             return;
00378 
00379         
00380         if (m_aData[usID].aReplyingAddress)
00381             return;
00382 
00383         if (!bTTLExpired)
00384         {
00385             
00386             if (!m_aData[mhMaxHops].aReplyingAddress)
00387             {
00388                 {
00389                     
00390                     CCriticalAutoRelease aRelease(m_aData[mhMaxHops].pCSection.get(),TRUE);
00391 
00392                     
00393                     m_aData[mhMaxHops].aReplyingAddress=aReplyingAddress;
00394                     m_aData[mhMaxHops].dwElapsedTime=dwTimeElapsed;
00395                     m_aData[mhMaxHops].ucTTL=usID;
00396                 }
00397 
00398                 
00399                 if (m_bResolveIPs)
00400                 {
00401                     
00402                     AdjustResolvers(1);
00403 
00404                     
00405                     ResolveThreadData* pThreadData;
00406                     pThreadData=new ResolveThreadData;
00407 
00408                     
00409                     pThreadData->pClass=this;
00410                     pThreadData->pData=&m_aData[mhMaxHops];
00411 
00412                     
00413                     m_pManager->GetThreadManager()->SubmitJob(ResolveData,(LPVOID)pThreadData);
00414                 }
00415 
00416                 
00417                 TraceDataForModify(&m_aData[mhMaxHops],
00418                                    FALSE);
00419 
00420                 
00421                 TraceData(&m_aData[mhMaxHops],
00422                           FALSE);
00423             }
00424         }
00425         else
00426         {
00427             {
00428                 
00429                 CCriticalAutoRelease aRelease(m_pCSection,TRUE);
00430 
00431                 
00432                 if (usID<m_ucMinHOP)
00433                     m_ucMinHOP=usID;
00434 
00435                 
00436                 if (usID>m_ucMaxHOP)
00437                     m_ucMaxHOP=usID;
00438             }
00439 
00440             {
00441                 
00442                 CCriticalAutoRelease aRelease(m_aData[usID].pCSection.get(),TRUE);
00443 
00444                 
00445                 m_aData[usID].aReplyingAddress=aReplyingAddress;
00446                 m_aData[usID].dwElapsedTime=dwTimeElapsed;
00447                 m_aData[usID].ucTTL=usID;
00448                 m_aData[usID].pDNS=m_pManager;
00449             }
00450 
00451             
00452             if (m_bResolveIPs)
00453             {
00454                 
00455                 AdjustResolvers(1);
00456 
00457                 
00458                 ResolveThreadData* pThreadData;
00459                 pThreadData=new ResolveThreadData;
00460 
00461                 
00462                 pThreadData->pClass=this;
00463                 pThreadData->pData=&m_aData[usID];
00464 
00465                 
00466                 m_pManager->GetThreadManager()->SubmitJob(ResolveData,(LPVOID)pThreadData);
00467             }
00468 
00469             
00470             TraceDataForModify(&m_aData[usID],
00471                                FALSE);
00472 
00473             
00474             TraceData(&m_aData[usID],
00475                       FALSE);
00476         }
00477     }
00478     ERROR_HANDLER("PingDoneData")
00479 }
00480 
00481 BOOL CRealTimeTraceRouteSocket::IsIDOK(unsigned short usID,
00482                                        unsigned short usSequence)const
00483 {
00484     return m_usPortStart==usSequence &&
00485            usID<=mhMaxHops;
00486 }
00487 
00488 void CRealTimeTraceRouteSocket::ResolveData(LPVOID lpData)
00489 {
00490     try
00491     {
00492         
00493         std::auto_ptr<ResolveThreadData> pData((ResolveThreadData*)lpData);
00494 
00495         
00496         unsigned short usID;
00497 
00498         
00499         BOOL bAdjust;
00500 
00501         
00502         TraceRouteData aData;
00503 
00504         {
00505             
00506             CCriticalAutoRelease aRelease(pData->pData->pCSection.get(),TRUE);
00507 
00508             
00509             aData=*pData->pData;
00510         }
00511 
00512         
00513         if (aData.ucTTL>=mhMaxHops)
00514         {
00515             
00516             pData->pClass->AdjustResolvers(-1);
00517 
00518             
00519             pData->pClass->DNSDone();
00520 
00521             
00522             return;
00523         }
00524         else if (!aData.ucTTL)
00525             usID=rand()%60000+mhMaxHops;
00526         else
00527             usID=aData.ucTTL;
00528 
00529         
00530         bAdjust=TRUE;
00531 
00532         
00533         
00534         if (aData.pDNS)
00535             if (aData.pDNS->GetDNSEntry(aData.aReplyingAddress,
00536                                         usID,
00537                                         (LPVOID)pData->pData))
00538                 bAdjust=FALSE;
00539         else
00540             ReportStaticError(CRealTimeTraceRouteSocket_Class,"ResolveData","Missing DNS information!");
00541 
00542         
00543         if (bAdjust)
00544         {
00545             
00546             pData->pClass->AdjustResolvers(-1);
00547 
00548             
00549             pData->pClass->DNSDone();
00550         }
00551     }
00552     ERROR_HANDLER_STATIC(CRealTimeTraceRouteSocket_Class,"ResolveData")
00553 }
00554 
00555 void CRealTimeTraceRouteSocket::TraceData(const TraceRouteData* pData,
00556                                           BOOL bResolved)
00557 {
00558 }
00559 
00560 BOOL CRealTimeTraceRouteSocket::IsInitialized()const
00561 {
00562     return m_bInitialized;
00563 }
00564 
00565 BOOL CRealTimeTraceRouteSocket::OnSocketTimeout()
00566 {
00567     try
00568     {
00569         
00570         KillTimer();
00571 
00572         
00573         if (m_bTraceDone)
00574             return FALSE;
00575 
00576         
00577         if (GetResolvers())
00578         {
00579             
00580             m_bPartialDone=TRUE;
00581 
00582             
00583             return FALSE;
00584         }
00585 
00586         
00587         m_bPartialDone=TRUE;
00588 
00589         
00590         InvokeTraceDone();
00591 
00592         
00593         return FALSE;
00594     }
00595     ERROR_HANDLER_RETURN("OnSocketTimeout",FALSE)
00596 }
00597 
00598 void CRealTimeTraceRouteSocket::TraceDone(BOOL bError)
00599 {
00600 }
00601 
00602 unsigned char CRealTimeTraceRouteSocket::GetMaxHops()const
00603 {
00604     return m_ucMaxHOP;
00605 }
00606 
00607 const CRealTimeTraceRouteSocket::TraceRouteData* CRealTimeTraceRouteSocket::GetData()const
00608 {
00609     return (const TraceRouteData*)&m_aData;
00610 }
00611 
00612 CRealTimeTraceRouteSocket::CRealTimeDNSManager* CRealTimeTraceRouteSocket::GetDNSManager()const
00613 {
00614     return m_pManager;
00615 }
00616 
00617 void CRealTimeTraceRouteSocket::TraceDataForModify(TraceRouteData* pData,
00618                                                    BOOL bResolved)
00619 {
00620 }
00621 
00622 void CRealTimeTraceRouteSocket::SetResolveStatus(BOOL bResolve)
00623 {   
00624     try
00625     {
00626         m_bResolveIPs=bResolve;
00627     }
00628     ERROR_HANDLER("SetResolveStatus")
00629 }
00630 
00631 void CRealTimeTraceRouteSocket::AdjustResolvers(long lAmount)
00632 {
00633     try
00634     {
00635         if (m_bTraceDone)
00636             return;
00637 
00638         
00639         CCriticalAutoRelease aRelease(m_pCSectionResolve,TRUE);
00640 
00641         
00642         m_ulResolvers+=lAmount;
00643     }
00644     ERROR_HANDLER("AdjustResolvers")
00645 }
00646 
00647 unsigned long CRealTimeTraceRouteSocket::GetResolvers()const
00648 {
00649     try
00650     {
00651         
00652         CCriticalAutoRelease aRelease(m_pCSectionResolve,TRUE);
00653 
00654         
00655         return m_ulResolvers;
00656     }
00657     ERROR_HANDLER_RETURN("GetResolvers",0)
00658 }
00659 
00660 void CRealTimeTraceRouteSocket::InvokeTraceDone()
00661 {
00662     try
00663     {
00664         {
00665             
00666             CCriticalAutoRelease aRelease(m_pCSectionGeneral,TRUE);
00667 
00668             
00669             if (m_bFinishing ||
00670                 m_bTraceDone)
00671                 return;
00672             else
00673                 m_bFinishing=TRUE;
00674         }
00675 
00676         
00677         BOOL bTrace;
00678 
00679         {
00680             
00681             CCriticalAutoRelease aRelease(m_aData[mhMaxHops].pCSection.get(),TRUE);
00682 
00683             if (!m_aData[mhMaxHops].aReplyingAddress)
00684             {
00685                 
00686                 
00687                 m_bFinishing=FALSE;
00688 
00689                 
00690                 aRelease.Exit();
00691 
00692                 
00693                 FakeLastRequest();
00694 
00695                 
00696                 return;
00697             }
00698 
00699             
00700             if (m_ucMaxHOP!=mhMaxHops)
00701                 ++m_ucMaxHOP;
00702 
00703             
00704             if (m_ucMaxHOP>mhMaxHops)
00705             {
00706                 
00707                 ReportError("InvokeTraceDone","Too big max hops!");
00708 
00709                 
00710                 m_ucMaxHOP=mhMaxHops;
00711             }
00712 
00713             
00714             m_aData[mhMaxHops].ucTTL=m_ucMaxHOP;
00715             m_aData[mhMaxHops].bFinal=TRUE;
00716 
00717             
00718             if (!m_aData[mhMaxHops].aReplyingAddress)
00719                 m_aData[mhMaxHops].aReplyingAddress=m_aTracedAddress;
00720 
00721             
00722             bTrace=!m_aData[mhMaxHops].sReverseDNS.empty();
00723 
00724             CCriticalAutoRelease aRelease2(m_aData[m_ucMaxHOP].pCSection.get(),TRUE);
00725 
00726             
00727             
00728             m_aData[m_ucMaxHOP]=m_aData[mhMaxHops];
00729         }
00730 
00731         
00732         TraceDataForModify(&m_aData[m_ucMaxHOP],bTrace);
00733         TraceData(&m_aData[m_ucMaxHOP],bTrace);
00734 
00735         
00736         m_bTraceDone=TRUE;
00737         
00738         
00739         m_bFinishing=FALSE;
00740 
00741         
00742         TraceDone(FALSE);
00743     }
00744     ERROR_HANDLER("InvokeTraceDone")
00745 }
00746 
00747 void CRealTimeTraceRouteSocket::DNSDone()
00748 {
00749     try
00750     {
00751         
00752         if (m_bPartialDone &&
00753             !m_bTraceDone &&
00754             !GetResolvers())
00755             
00756             InvokeTraceDone();
00757     }
00758     ERROR_HANDLER("DNSDone")
00759 }
00760 
00761 unsigned short CRealTimeTraceRouteSocket::GetPortStart()
00762 {
00763     try
00764     {
00765         
00766         CCriticalAutoRelease aRelease(CSpoofBase::GetGlobalCriticalSection(),TRUE);
00767 
00768         
00769         unsigned short usPort;
00770         usPort=m_sPortStart;
00771 
00772         
00773         ++m_sPortStart;
00774 
00775         
00776         if (m_sPortStart>=65000)
00777             m_sPortStart=0;
00778 
00779         
00780         return usPort;
00781     }
00782     ERROR_HANDLER_STATIC_RETURN(CRealTimeTraceRouteSocket_Class,"GetPortStart",0)
00783 }
00784 
00785 void CRealTimeTraceRouteSocket::FakeLastRequest()
00786 {
00787     try
00788     {
00789         
00790         if (!m_aData[mhMaxHops].aReplyingAddress)
00791         {
00792             {
00793                 
00794                 CCriticalAutoRelease aRelease(m_aData[mhMaxHops].pCSection.get(),TRUE);
00795 
00796                 
00797                 m_aData[mhMaxHops].aReplyingAddress=m_aTracedAddress;
00798                 m_aData[mhMaxHops].dwElapsedTime=0;
00799                 m_aData[mhMaxHops].ucTTL=m_ucMaxHOP;
00800                 m_aData[mhMaxHops].pDNS=m_pManager;
00801             }
00802 
00803             
00804             if (m_bResolveIPs)
00805             {
00806                 
00807                 AdjustResolvers(1);
00808 
00809                 
00810                 ResolveThreadData* pThreadData;
00811                 pThreadData=new ResolveThreadData;
00812 
00813                 
00814                 pThreadData->pClass=this;
00815                 pThreadData->pData=&m_aData[mhMaxHops];
00816 
00817                 
00818                 m_pManager->GetThreadManager()->SubmitJob(ResolveData,(LPVOID)pThreadData);
00819             }
00820 
00821             
00822             TraceDataForModify(&m_aData[mhMaxHops],
00823                                FALSE);
00824 
00825             
00826             TraceData(&m_aData[mhMaxHops],
00827                       FALSE);
00828         }
00829     }
00830     ERROR_HANDLER("FakeLastRequest")
00831 }
00832 
00833 KOMODIA_NAMESPACE_END