diff --git a/README.md b/README.md index b8a8d8d..6af5ee9 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,10 @@ this should improve performance and reduces network load*
- `[ ]` + host history: pressing del key or right mouse will remove selected entry
- `[ ]` * new icon
-~~~~ +### About me / why I decided to create this fork +There isn't that much to say actually, I've been using IPv6 for a few years now thanks to [**SixXS**](http://sixxs.net/) and it always annoyed me that WinMTR couldn't handle IPv6... finally my ISP got some sort of IPv6 beta test. And that's what I wanted to compare, native vs SixXS with long-term trace routes such as those WinMTR provides. +Since there wasn't any WinMTR build with IPv6, I decided to do it myself ;) The result can be seen here :P + +**If you're looking for an alternative** *(not meant for long-term traces)* there's [**vTrace**](vtrace.pl). +It's some really interesting piece of Software ;) *(with more then just trace routes)* +~~~~ \ No newline at end of file diff --git a/src/WinMTR.rc b/src/WinMTR.rc index 20399b0..b3cc862 100644 --- a/src/WinMTR.rc +++ b/src/WinMTR.rc @@ -70,24 +70,25 @@ IDR_MAINFRAME ICON "WinMTR.ico" // Dialog // -IDD_WINMTR_DIALOG DIALOGEX 0, 0, 390, 193 +IDD_WINMTR_DIALOG DIALOGEX 0, 0, 420, 220 STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_APPWINDOW FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - DEFPUSHBUTTON "&Start",ID_RESTART,203,12,50,14,BS_FLAT - PUSHBUTTON "&Options",ID_OPTIONS,270,12,51,14,BS_FLAT - PUSHBUTTON "E&xit",IDCANCEL,328,12,49,14,BS_FLAT - PUSHBUTTON "&Copy Text to clipboard",ID_CTTC,14,39,89,14,BS_FLAT - PUSHBUTTON "Co&py HTML to clipboard",ID_CHTC,113,39,89,14,BS_FLAT - PUSHBUTTON "Export &TEXT",ID_EXPT,270,39,51,14,BS_FLAT - PUSHBUTTON "Export &HTML",ID_EXPH,328,39,49,14,BS_FLAT - CONTROL "List1",IDC_LIST_MTR,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,60,376,126 - LTEXT "Host:",IDC_STATIC,13,12,20,13,SS_CENTERIMAGE - GROUPBOX "",IDC_STATIC,7,3,251,29,BS_FLAT - GROUPBOX "",IDC_STATICS,263,3,120,29,BS_FLAT - GROUPBOX "",IDC_STATICJ,7,31,376,26,BS_FLAT - COMBOBOX IDC_COMBO_HOST,35,12,164,73,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "&Start",ID_RESTART,235,10,50,14,BS_FLAT + PUSHBUTTON "&Options",ID_OPTIONS,333,10,41,14,BS_FLAT + PUSHBUTTON "E&xit",IDCANCEL,379,10,30,14,BS_FLAT + PUSHBUTTON "&Copy Text to clipboard",ID_CTTC,12,37,89,14,BS_FLAT + PUSHBUTTON "Co&py HTML to clipboard",ID_CHTC,111,37,89,14,BS_FLAT + PUSHBUTTON "Export &TEXT",ID_EXPT,301,37,51,14,BS_FLAT + PUSHBUTTON "Export &HTML",ID_EXPH,359,37,49,14,BS_FLAT + CONTROL "List1",IDC_LIST_MTR,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,58,409,157 + LTEXT "Host:",IDC_STATIC,11,10,20,13,SS_LEFT | SS_CENTERIMAGE + GROUPBOX "",IDC_STATIC,5,0,287,30,BS_FLAT + GROUPBOX "",IDC_STATICS,295,0,120,30,BS_FLAT + GROUPBOX "",IDC_STATICJ,5,29,409,26,BS_FLAT + COMBOBOX IDC_COMBO_HOST,33,10,198,73,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + AUTO3STATE "IPv6",IDC_CHECK_IPV6,301,14,31,8 END IDD_DIALOG_OPTIONS DIALOGEX 0, 0, 251, 164 @@ -106,11 +107,11 @@ BEGIN CONTROL "Resolve names",IDC_CHECK_DNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,167,119,63,8 GROUPBOX "",IDC_STATIC,7,7,237,82,BS_FLAT CTEXT "Get Fully Managed Dedicated and Cloud hosting in Europe and USA at killer prices.",IDC_STATIC,31,35,201,17 - CTEXT "WinMTR v0.92 is offered under GPL V2 by Appnor MSP",IDC_STATIC,42,14,194,17 + CTEXT "WinMTR (Redux) v1.00 is offered under GPLv2",IDC_STATIC,42,14,194,17 PUSHBUTTON "&License and Credits",ID_LICENSE,81,67,94,14,BS_FLAT LTEXT "Max. hosts in LRU list:",IDC_STATIC,15,119,74,10,NOT WS_GROUP EDITTEXT IDC_EDIT_MAX_LRU,90,116,34,13,ES_AUTOHSCROLL - CONTROL "www.appnor.com",IDC_MFCLINK1,"MfcLink",WS_TABSTOP,102,51,60,11 + LTEXT "www.appnor.com",IDC_STATIC,102,51,60,11,NOT WS_GROUP END IDD_DIALOG_LICENSE DIALOGEX 0, 0, 175, 70 @@ -118,40 +119,41 @@ STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "License & Credits" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN - DEFPUSHBUTTON "OK",IDOK,59,43,50,14 - LTEXT "Read more on",IDC_STATIC,36,27,46,8 - CONTROL "www.winmtr.net",IDC_MFCLINK1,"MfcLink",WS_TABSTOP,83,26,60,14 - LTEXT "WinMTR is licensed under GPL V2.",IDC_STATIC,33,14,113,8 + DEFPUSHBUTTON "OK",IDOK,62,36,50,14 + LTEXT "Read more on",IDC_STATIC,36,21,46,8 + LTEXT "www.winmtr.net",IDC_STATIC,85,21,60,8 + CTEXT "WinMTR (Redux) is licensed under GPLv2.",IDC_STATIC,2,9,171,8,SS_CENTER + CTEXT "https://github.com/White-Tiger/WinMTR",IDC_STATIC,7,57,161,8,SS_CENTER END -IDD_DIALOG_PROPERTIES DIALOG 0, 0, 201, 159 +IDD_DIALOG_PROPERTIES DIALOG 0, 0, 282, 160 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Host properties" FONT 8, "MS Sans Serif" BEGIN - DEFPUSHBUTTON "OK",IDOK,71,138,50,14,BS_FLAT + DEFPUSHBUTTON "OK",IDOK,116,140,50,14,BS_FLAT LTEXT "Name:",IDC_STATIC,15,18,24,8 - EDITTEXT IDC_EDIT_PHOST,48,16,136,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT_PHOST,48,16,219,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY LTEXT "IP Address:",IDC_STATIC,14,32,40,9 - EDITTEXT IDC_EDIT_PIP,58,31,126,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY - GROUPBOX "Packets",IDC_STATIC,7,74,89,60,BS_FLAT - GROUPBOX "Ping time",IDC_STATIC,108,74,86,60,BS_FLAT - GROUPBOX "Host",IDC_STATIC,7,7,187,62,BS_FLAT - LTEXT "Loss (%):",IDC_STATIC,13,117,31,9 - LTEXT "Received:",IDC_STATIC,13,101,36,9 - LTEXT "Sent:",IDC_STATIC,13,85,21,9 - LTEXT "Last:",IDC_STATIC,114,84,18,9 - LTEXT "Best:",IDC_STATIC,114,96,20,8 - LTEXT "Average:",IDC_STATIC,114,107,32,8 - LTEXT "Worst:",IDC_STATIC,114,118,23,8 - EDITTEXT IDC_EDIT_PSENT,53,82,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER - EDITTEXT IDC_EDIT_PRECV,53,99,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER - EDITTEXT IDC_EDIT_PLOSS,53,116,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER - EDITTEXT IDC_EDIT_PLAST,150,81,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_EDIT_PBEST,150,94,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_EDIT_PAVRG,150,106,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_EDIT_PWORST,150,118,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_EDIT_PCOMMENT,14,50,170,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT_PIP,58,31,209,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY + GROUPBOX "Packets",IDC_STATIC,46,74,89,60,BS_FLAT + GROUPBOX "Ping time",IDC_STATIC,147,74,86,60,BS_FLAT + GROUPBOX "Host",IDC_STATIC,7,7,267,62,BS_FLAT + LTEXT "Loss (%):",IDC_STATIC,52,117,31,9 + LTEXT "Received:",IDC_STATIC,52,101,36,9 + LTEXT "Sent:",IDC_STATIC,52,85,21,9 + LTEXT "Last:",IDC_STATIC,153,84,18,9 + LTEXT "Best:",IDC_STATIC,153,96,20,8 + LTEXT "Average:",IDC_STATIC,153,107,32,8 + LTEXT "Worst:",IDC_STATIC,153,118,23,8 + EDITTEXT IDC_EDIT_PSENT,92,82,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER + EDITTEXT IDC_EDIT_PRECV,92,99,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER + EDITTEXT IDC_EDIT_PLOSS,92,116,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER + EDITTEXT IDC_EDIT_PLAST,189,81,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT_PBEST,189,94,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT_PAVRG,189,106,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT_PWORST,189,118,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT_PCOMMENT,14,50,253,12,ES_AUTOHSCROLL | ES_READONLY END IDD_DIALOG_HELP DIALOGEX 0, 0, 256, 122 @@ -160,8 +162,8 @@ CAPTION "WinMTR" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,144,101,50,14 - CONTROL "www.appnor.com",IDC_MFCLINK1,"MfcLink",WS_TABSTOP,187,8,60,11 - LTEXT "WinMTR v0.92 is offered under GPL V2 by Appnor MSP",IDC_STATIC,7,9,176,10 + LTEXT "www.appnor.com",IDC_STATIC,187,9,60,11 + LTEXT "WinMTR (Redux) v1.00 is offered under GPLv2",IDC_STATIC,7,9,176,10 LTEXT "Usage: WinMTR [options] target_host_name",IDC_STATIC,7,29,144,8 LTEXT "Options:",IDC_STATIC,7,39,28,8 LTEXT " --interval, -i VALUE. Set ping interval.",IDC_STATIC,26,47,131,8 @@ -178,8 +180,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,0,2 - PRODUCTVERSION 0,9,0,2 + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -194,13 +196,13 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "FileDescription", "WinMTR by Appnor MSP - www.winmtr.net" - VALUE "FileVersion", "0.9.0.2" + VALUE "FileDescription", "WinMTR Redux (original by Appnor MSP - www.winmtr.net)" + VALUE "FileVersion", "1.0.0.0" VALUE "InternalName", "WinMTR" VALUE "LegalCopyright", "WinMTR 0.9 (c) 2010-2011 Appnor MSP - Fully Managed Hosting & Cloud Provider www.appnor.com" - VALUE "OriginalFilename", "WinMTR.EXE" + VALUE "OriginalFilename", "WinMTR.exe" VALUE "ProductName", "WinMTR Application" - VALUE "ProductVersion", "0.9.0.2" + VALUE "ProductVersion", "1.0.0.0" END END BLOCK "VarFileInfo" @@ -268,67 +270,6 @@ END #endif // APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Dialog Info -// - -IDD_DIALOG_HELP DLGINIT -BEGIN - IDC_MFCLINK1, 0x37c, 238, 0 -0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x683e, 0x7474, 0x3a70, -0x2f2f, 0x7777, 0x2e77, 0x7061, 0x6e70, 0x726f, 0x632e, 0x6d6f, 0x3f2f, -0x7475, 0x5f6d, 0x6f73, 0x7275, 0x6563, 0x773d, 0x6e69, 0x746d, 0x2672, -0x7475, 0x5f6d, 0x656d, 0x6964, 0x6d75, 0x643d, 0x7365, 0x746b, 0x706f, -0x7526, 0x6d74, 0x635f, 0x6d61, 0x6170, 0x6769, 0x3d6e, 0x6f73, 0x7466, -0x6177, 0x6572, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x7255, 0x3e6c, -0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x7250, 0x6665, 0x7869, -0x3c3e, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x7250, 0x6665, -0x7869, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x6f54, 0x6c6f, 0x6974, -0x3e70, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x6f54, 0x6c6f, 0x6974, -0x3e70, 0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x465f, 0x6c75, 0x546c, 0x7865, -0x5474, 0x6f6f, 0x746c, 0x7069, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, -0x4c43, 0x6e69, 0x5f6b, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, -0x6974, 0x3e70, - 0 -END - -IDD_DIALOG_OPTIONS DLGINIT -BEGIN - IDC_MFCLINK1, 0x37c, 238, 0 -0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x683e, 0x7474, 0x3a70, -0x2f2f, 0x7777, 0x2e77, 0x7061, 0x6e70, 0x726f, 0x632e, 0x6d6f, 0x3f2f, -0x7475, 0x5f6d, 0x6f73, 0x7275, 0x6563, 0x773d, 0x6e69, 0x746d, 0x2672, -0x7475, 0x5f6d, 0x656d, 0x6964, 0x6d75, 0x643d, 0x7365, 0x746b, 0x706f, -0x7526, 0x6d74, 0x635f, 0x6d61, 0x6170, 0x6769, 0x3d6e, 0x6f73, 0x7466, -0x6177, 0x6572, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x7255, 0x3e6c, -0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x7250, 0x6665, 0x7869, -0x3c3e, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x7250, 0x6665, -0x7869, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x6f54, 0x6c6f, 0x6974, -0x3e70, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x6f54, 0x6c6f, 0x6974, -0x3e70, 0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x465f, 0x6c75, 0x546c, 0x7865, -0x5474, 0x6f6f, 0x746c, 0x7069, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, -0x4c43, 0x6e69, 0x5f6b, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, -0x6974, 0x3e70, - 0 -END - -IDD_DIALOG_LICENSE DLGINIT -BEGIN - IDC_MFCLINK1, 0x37c, 157, 0 -0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x3c3e, 0x4d2f, 0x4346, -0x694c, 0x6b6e, 0x555f, 0x6c72, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, -0x7255, 0x506c, 0x6572, 0x6966, 0x3e78, 0x2f3c, 0x464d, 0x4c43, 0x6e69, -0x5f6b, 0x7255, 0x506c, 0x6572, 0x6966, 0x3e78, 0x4d3c, 0x4346, 0x694c, -0x6b6e, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x4d2f, 0x4346, 0x694c, -0x6b6e, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 0x4c43, 0x6e69, -0x5f6b, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x6974, 0x3e70, -0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x465f, 0x6c75, -0x546c, 0x7865, 0x5474, 0x6f6f, 0x746c, 0x7069, "\076" - 0 -END - - ///////////////////////////////////////////////////////////////////////////// // // String Table @@ -337,7 +278,7 @@ END STRINGTABLE BEGIN IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." - IDS_STRING_SB_NAME "WinMTR v0.92 GPL V2 by Appnor MSP - Fully Managed Hosting & Cloud Provider" + IDS_STRING_SB_NAME "WinMTR v1.00 GPLv2 (original by Appnor MSP - Fully Managed Hosting & Cloud Provider)" IDS_STRING_SB_PING "0000000" IDS_STRING_CLEAR_HISTORY "Clear History" END @@ -346,25 +287,8 @@ END ///////////////////////////////////////////////////////////////////////////// - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// // -// Generated from the TEXTINCLUDE 3 resource. +// Manifest resources // -#define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE 9, 1 -#pragma code_page(1252) -#endif //_WIN32 -#include "afxres.rc" // Standard components -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +1 RT_MANIFEST ".\\manifest.xml" diff --git a/src/WinMTRDialog.cpp b/src/WinMTRDialog.cpp index 9fcc82e..620c368 100644 --- a/src/WinMTRDialog.cpp +++ b/src/WinMTRDialog.cpp @@ -11,7 +11,6 @@ #include "WinMTRNet.h" #include #include -#include "afxlinkctrl.h" #define TRACE_MSG(msg) \ { \ @@ -76,9 +75,12 @@ WinMTRDialog::WinMTRDialog(CWnd* pParent) hasPingsizeFromCmdLine = false; hasMaxLRUFromCmdLine = false; hasUseDNSFromCmdLine = false; + hasUseIPv6FromCmdLine = false; traceThreadMutex = CreateMutex(NULL, FALSE, NULL); wmtrnet = new WinMTRNet(this); + if(!wmtrnet->hasIPv6) m_checkIPv6.EnableWindow(FALSE); + useIPv6=2; } WinMTRDialog::~WinMTRDialog() @@ -99,6 +101,7 @@ void WinMTRDialog::DoDataExchange(CDataExchange* pDX) DDX_Control(pDX, IDCANCEL, m_buttonExit); DDX_Control(pDX, ID_RESTART, m_buttonStart); DDX_Control(pDX, IDC_COMBO_HOST, m_comboHost); + DDX_Control(pDX, IDC_CHECK_IPV6, m_checkIPv6); DDX_Control(pDX, IDC_LIST_MTR, m_listMTR); DDX_Control(pDX, IDC_STATICS, m_staticS); DDX_Control(pDX, IDC_STATICJ, m_staticJ); @@ -115,11 +118,15 @@ void WinMTRDialog::DoDataExchange(CDataExchange* pDX) BOOL WinMTRDialog::OnInitDialog() { CDialog::OnInitDialog(); + if(!wmtrnet->initialized){ + EndDialog(-1); + return TRUE; + } #ifndef _WIN64 - char caption[] = {"WinMTR v0.92 32 bit by Appnor MSP - www.winmtr.net"}; + char caption[] = {"WinMTR (Redux) v1.00 32bit"}; #else - char caption[] = {"WinMTR v0.92 64 bit by Appnor MSP - www.winmtr.net"}; + char caption[] = {"WinMTR (Redux) v1.00 64bit"}; #endif SetTimer(1, WINMTR_DIALOG_TIMER, NULL); @@ -136,22 +143,14 @@ BOOL WinMTRDialog::OnInitDialog() sbi[0] = IDS_STRING_SB_NAME; statusBar.SetIndicators( sbi,1); statusBar.SetPaneInfo(0, statusBar.GetItemID(0),SBPS_STRETCH, NULL ); - { // Add appnor URL - CMFCLinkCtrl* m_pWndButton = new CMFCLinkCtrl; - if (!m_pWndButton->Create(_T("www.appnor.com"), WS_CHILD|WS_VISIBLE|WS_TABSTOP, CRect(0,0,0,0), &statusBar, 1234)) { - TRACE(_T("Failed to create button control.\n")); - return FALSE; - } - - m_pWndButton->SetURL("http://www.appnor.com/?utm_source=winmtr&utm_medium=desktop&utm_campaign=software"); - - if(!statusBar.AddPane(1234,1)) { - AfxMessageBox(_T("Pane index out of range\nor pane with same ID already exists in the status bar"), MB_ICONERROR); - return FALSE; + + // create Appnor button + if(m_buttonAppnor.Create(_T("www.appnor.com"), WS_CHILD|WS_VISIBLE|WS_TABSTOP, CRect(0,0,0,0), &statusBar, 1234)){ + m_buttonAppnor.SetURL("http://appnor.com/?utm_source=winmtr&utm_medium=desktop&utm_campaign=software"); + if(statusBar.AddPane(1234,1)){ + statusBar.SetPaneWidth(statusBar.CommandToIndex(1234),100); + statusBar.AddPaneControl(m_buttonAppnor,1234,true); } - - statusBar.SetPaneWidth(statusBar.CommandToIndex(1234), 100); - statusBar.AddPaneControl(m_pWndButton, 1234, true); } for(int i = 0; i< MTR_NR_COLS; i++) @@ -215,27 +214,7 @@ BOOL WinMTRDialog::InitRegistry() DWORD res, tmp_dword, value_size; LONG r; - r = RegCreateKeyEx( HKEY_CURRENT_USER, - "Software", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKey, - &res); - if( r != ERROR_SUCCESS) - return FALSE; - - r = RegCreateKeyEx( hKey, - "WinMTR", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKey, - &res); + r = RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\WinMTR",0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&res); if( r != ERROR_SUCCESS) return FALSE; @@ -243,15 +222,7 @@ BOOL WinMTRDialog::InitRegistry() RegSetValueEx(hKey,"License", 0, REG_SZ, (const unsigned char *)WINMTR_LICENSE, sizeof(WINMTR_LICENSE)+1); RegSetValueEx(hKey,"HomePage", 0, REG_SZ, (const unsigned char *)WINMTR_HOMEPAGE, sizeof(WINMTR_HOMEPAGE)+1); - r = RegCreateKeyEx( hKey, - "Config", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKey_v, - &res); + r = RegCreateKeyEx(hKey,"Config",0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey_v,&res); if( r != ERROR_SUCCESS) return FALSE; @@ -259,7 +230,7 @@ BOOL WinMTRDialog::InitRegistry() tmp_dword = pingsize; RegSetValueEx(hKey_v,"PingSize", 0, REG_DWORD, (const unsigned char *)&tmp_dword, sizeof(DWORD)); } else { - if(!hasPingsizeFromCmdLine) pingsize = tmp_dword; + if(!hasPingsizeFromCmdLine) pingsize = (WORD)tmp_dword; } if(RegQueryValueEx(hKey_v, "MaxLRU", 0, NULL, (unsigned char *)&tmp_dword, &value_size) != ERROR_SUCCESS) { @@ -275,6 +246,14 @@ BOOL WinMTRDialog::InitRegistry() } else { if(!hasUseDNSFromCmdLine) useDNS = (BOOL)tmp_dword; } + if(RegQueryValueEx(hKey_v, "UseIPv6", 0, NULL, (unsigned char *)&tmp_dword, &value_size) != ERROR_SUCCESS) { + tmp_dword = useIPv6; + RegSetValueEx(hKey_v,"UseIPv6", 0, REG_DWORD, (const unsigned char *)&tmp_dword, sizeof(DWORD)); + } else { + if(!hasUseIPv6FromCmdLine) useIPv6 = (unsigned char)tmp_dword; + if(useIPv6>2) useIPv6=1; + } + m_checkIPv6.SetCheck(useIPv6); if(RegQueryValueEx(hKey_v, "Interval", 0, NULL, (unsigned char *)&tmp_dword, &value_size) != ERROR_SUCCESS) { tmp_dword = (DWORD)(interval * 1000); @@ -283,15 +262,7 @@ BOOL WinMTRDialog::InitRegistry() if(!hasIntervalFromCmdLine) interval = (float)tmp_dword / 1000.0; } - r = RegCreateKeyEx( hKey, - "LRU", - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hKey_v, - &res); + r = RegCreateKeyEx(hKey,"LRU",0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey_v,&res); if( r != ERROR_SUCCESS) return FALSE; if(RegQueryValueEx(hKey_v, "NrLRU", 0, NULL, (unsigned char *)&tmp_dword, &value_size) != ERROR_SUCCESS) { @@ -329,10 +300,10 @@ void WinMTRDialog::OnSizing(UINT fwSide, LPRECT pRect) int iWidth = (pRect->right)-(pRect->left); int iHeight = (pRect->bottom)-(pRect->top); - if (iWidth < 600) - pRect->right = pRect->left + 600; - if (iHeight <250) - pRect->bottom = pRect->top + 250; + if (iWidth<638) + pRect->right = pRect->left+638; + if (iHeight<388) + pRect->bottom = pRect->top+388; } @@ -341,50 +312,41 @@ void WinMTRDialog::OnSizing(UINT fwSide, LPRECT pRect) // // //***************************************************************************** +/// @todo (White-Tiger#1#): simplify it... use initial positions from "right" to calculate new position (no fix values here) void WinMTRDialog::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); - CRect r; - GetClientRect(&r); - CRect lb; + CRect rct,lb; + if(!IsWindow(m_staticS.m_hWnd)) return; + GetClientRect(&rct); + m_staticS.GetWindowRect(&lb); + ScreenToClient(&lb); + m_staticS.SetWindowPos(NULL, lb.TopLeft().x, lb.TopLeft().y, rct.Width()-lb.TopLeft().x-8, lb.Height() , SWP_NOMOVE | SWP_NOZORDER); + + m_staticJ.GetWindowRect(&lb); + ScreenToClient(&lb); + m_staticJ.SetWindowPos(NULL, lb.TopLeft().x, lb.TopLeft().y, rct.Width() - 16, lb.Height(), SWP_NOMOVE | SWP_NOZORDER); + + m_buttonOptions.GetWindowRect(&lb); + ScreenToClient(&lb); + m_buttonOptions.SetWindowPos(NULL, rct.Width() - lb.Width()-52-16, lb.TopLeft().y, lb.Width(), lb.Height() , SWP_NOSIZE | SWP_NOZORDER); + m_buttonExit.GetWindowRect(&lb); + ScreenToClient(&lb); + m_buttonExit.SetWindowPos(NULL, rct.Width() - lb.Width()-16, lb.TopLeft().y, lb.Width(), lb.Height() , SWP_NOSIZE | SWP_NOZORDER); - if (::IsWindow(m_staticS.m_hWnd)) { - m_staticS.GetWindowRect(&lb); - ScreenToClient(&lb); - m_staticS.SetWindowPos(NULL, lb.TopLeft().x, lb.TopLeft().y, r.Width()-lb.TopLeft().x-10, lb.Height() , SWP_NOMOVE | SWP_NOZORDER); - } - - if (::IsWindow(m_staticJ.m_hWnd)) { - m_staticJ.GetWindowRect(&lb); - ScreenToClient(&lb); - m_staticJ.SetWindowPos(NULL, lb.TopLeft().x, lb.TopLeft().y, r.Width() - 21, lb.Height(), SWP_NOMOVE | SWP_NOZORDER); - } - - if (::IsWindow(m_buttonExit.m_hWnd)) { - m_buttonExit.GetWindowRect(&lb); - ScreenToClient(&lb); - m_buttonExit.SetWindowPos(NULL, r.Width() - lb.Width()-21, lb.TopLeft().y, lb.Width(), lb.Height() , SWP_NOSIZE | SWP_NOZORDER); - } - - if (::IsWindow(m_buttonExpH.m_hWnd)) { - m_buttonExpH.GetWindowRect(&lb); - ScreenToClient(&lb); - m_buttonExpH.SetWindowPos(NULL, r.Width() - lb.Width()-21, lb.TopLeft().y, lb.Width(), lb.Height() , SWP_NOSIZE | SWP_NOZORDER); - } - if (::IsWindow(m_buttonExpT.m_hWnd)) { - m_buttonExpT.GetWindowRect(&lb); - ScreenToClient(&lb); - m_buttonExpT.SetWindowPos(NULL, r.Width() - lb.Width()- 103, lb.TopLeft().y, lb.Width(), lb.Height() , SWP_NOSIZE | SWP_NOZORDER); - } + m_buttonExpH.GetWindowRect(&lb); + ScreenToClient(&lb); + m_buttonExpH.SetWindowPos(NULL, rct.Width() - lb.Width()-16, lb.TopLeft().y, lb.Width(), lb.Height() , SWP_NOSIZE | SWP_NOZORDER); + m_buttonExpT.GetWindowRect(&lb); + ScreenToClient(&lb); + m_buttonExpT.SetWindowPos(NULL, rct.Width() - lb.Width()- 103, lb.TopLeft().y, lb.Width(), lb.Height() , SWP_NOSIZE | SWP_NOZORDER); - if (::IsWindow(m_listMTR.m_hWnd)) { - m_listMTR.GetWindowRect(&lb); - ScreenToClient(&lb); - m_listMTR.SetWindowPos(NULL, lb.TopLeft().x, lb.TopLeft().y, r.Width() - 21, r.Height() - lb.top - 25, SWP_NOMOVE | SWP_NOZORDER); - } + m_listMTR.GetWindowRect(&lb); + ScreenToClient(&lb); + m_listMTR.SetWindowPos(NULL, lb.TopLeft().x, lb.TopLeft().y, rct.Width() - 17, rct.Height() - lb.top - 25, SWP_NOMOVE | SWP_NOZORDER); RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, - 0, reposQuery, r); + 0, reposQuery, rct); RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); @@ -435,47 +397,39 @@ HCURSOR WinMTRDialog::OnQueryDragIcon() // WinMTRDialog::OnDblclkList // //***************************************************************************** -void WinMTRDialog::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) +void WinMTRDialog::OnDblclkList(NMHDR* /*pNMHDR*/, LRESULT* pResult) { - *pResult = 0; - - if(state == TRACING) { + *pResult=0; + if(state==TRACING || state==IDLE || state==STOPPING) { POSITION pos = m_listMTR.GetFirstSelectedItemPosition(); if(pos!=NULL) { int nItem = m_listMTR.GetNextSelectedItem(pos); WinMTRProperties wmtrprop; - - if(wmtrnet->GetAddr(nItem)==0) { + + union{sockaddr* addr;sockaddr_in* addr4;sockaddr_in6* addr6;}; + addr=wmtrnet->GetAddr(nItem); + if(!(addr4->sin_family==AF_INET&&addr4->sin_addr.s_addr) && !(addr6->sin6_family==AF_INET6&&(addr6->sin6_addr.u.Word[0]|addr6->sin6_addr.u.Word[1]|addr6->sin6_addr.u.Word[2]|addr6->sin6_addr.u.Word[3]|addr6->sin6_addr.u.Word[4]|addr6->sin6_addr.u.Word[5]|addr6->sin6_addr.u.Word[6]|addr6->sin6_addr.u.Word[7]))){ strcpy(wmtrprop.host,""); strcpy(wmtrprop.ip,""); wmtrnet->GetName(nItem, wmtrprop.comment); - - wmtrprop.pck_loss = wmtrprop.pck_sent = wmtrprop.pck_recv = 0; - - wmtrprop.ping_avrg = wmtrprop.ping_last = 0.0; - wmtrprop.ping_best = wmtrprop.ping_worst = 0.0; - } else { + }else{ wmtrnet->GetName(nItem, wmtrprop.host); - int addr = wmtrnet->GetAddr(nItem); - sprintf ( wmtrprop.ip , "%d.%d.%d.%d", - (addr >> 24) & 0xff, - (addr >> 16) & 0xff, - (addr >> 8) & 0xff, - addr & 0xff - ); - strcpy(wmtrprop.comment , "Host alive."); - - wmtrprop.ping_avrg = (float)wmtrnet->GetAvg(nItem); - wmtrprop.ping_last = (float)wmtrnet->GetLast(nItem); - wmtrprop.ping_best = (float)wmtrnet->GetBest(nItem); - wmtrprop.ping_worst = (float)wmtrnet->GetWorst(nItem); - - wmtrprop.pck_loss = wmtrnet->GetPercent(nItem); - wmtrprop.pck_recv = wmtrnet->GetReturned(nItem); - wmtrprop.pck_sent = wmtrnet->GetXmit(nItem); + if(getnameinfo(addr,sizeof(sockaddr_in6),wmtrprop.ip,40,NULL,0,NI_NUMERICHOST)){ + *wmtrprop.ip='\0'; + } + strcpy(wmtrprop.comment, "Host alive."); } + wmtrprop.ping_avrg = (float)wmtrnet->GetAvg(nItem); + wmtrprop.ping_last = (float)wmtrnet->GetLast(nItem); + wmtrprop.ping_best = (float)wmtrnet->GetBest(nItem); + wmtrprop.ping_worst = (float)wmtrnet->GetWorst(nItem); + + wmtrprop.pck_loss = wmtrnet->GetPercent(nItem); + wmtrprop.pck_recv = wmtrnet->GetReturned(nItem); + wmtrprop.pck_sent = wmtrnet->GetXmit(nItem); + wmtrprop.DoModal(); } } @@ -497,7 +451,7 @@ void WinMTRDialog::SetHostName(const char *host) // WinMTRDialog::SetPingSize // //***************************************************************************** -void WinMTRDialog::SetPingSize(int ps) +void WinMTRDialog::SetPingSize(WORD ps) { pingsize = ps; } @@ -547,44 +501,35 @@ void WinMTRDialog::OnRestart() } CString sHost; - if(state == IDLE) { m_comboHost.GetWindowText(sHost); - sHost.TrimLeft(); - sHost.TrimLeft(); - + sHost.TrimLeft(); sHost.TrimRight(); if(sHost.IsEmpty()) { AfxMessageBox("No host specified!"); m_comboHost.SetFocus(); return ; } m_listMTR.DeleteAllItems(); - } - - if(state == IDLE) { + HKEY hKey; DWORD tmp_dword; + if(RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\WinMTR\\Config",0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&tmp_dword)==ERROR_SUCCESS){ + tmp_dword=m_checkIPv6.GetCheck(); + useIPv6=(unsigned char)tmp_dword; + RegSetValueEx(hKey,"UseIPv6",0,REG_DWORD,(const unsigned char*)&tmp_dword,sizeof(DWORD)); + RegCloseKey(hKey); + } if(InitMTRNet()) { if(m_comboHost.FindString(-1, sHost) == CB_ERR) { m_comboHost.InsertString(m_comboHost.GetCount() - 1,sHost); - - HKEY hKey; - DWORD tmp_dword; - LONG r; char key_name[20]; - - r = RegOpenKeyEx( HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS,&hKey); - r = RegOpenKeyEx( hKey, "WinMTR", 0, KEY_ALL_ACCESS, &hKey); - r = RegOpenKeyEx( hKey, "LRU", 0, KEY_ALL_ACCESS, &hKey); - - if(nrLRU >= maxLRU) - nrLRU = 0; - - nrLRU++; - sprintf(key_name, "Host%d", nrLRU); - r = RegSetValueEx(hKey,key_name, 0, REG_SZ, (const unsigned char *)(LPCTSTR)sHost, strlen((LPCTSTR)sHost)+1); - tmp_dword = nrLRU; - r = RegSetValueEx(hKey,"NrLRU", 0, REG_DWORD, (const unsigned char *)&tmp_dword, sizeof(DWORD)); - RegCloseKey(hKey); + if(RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\WinMTR\\LRU",0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&tmp_dword)==ERROR_SUCCESS){ + if(++nrLRU>maxLRU) nrLRU=0; + sprintf(key_name, "Host%d", nrLRU); + RegSetValueEx(hKey,key_name, 0, REG_SZ, (const unsigned char*)(LPCTSTR)sHost, (DWORD)strlen((LPCTSTR)sHost)+1); + tmp_dword = nrLRU; + RegSetValueEx(hKey,"NrLRU", 0, REG_DWORD, (const unsigned char*)&tmp_dword, sizeof(DWORD)); + RegCloseKey(hKey); + } } Transit(TRACING); } @@ -610,7 +555,7 @@ void WinMTRDialog::OnOptions() if(IDOK == optDlg.DoModal()) { - pingsize = optDlg.GetPingSize(); + pingsize = (WORD)optDlg.GetPingSize(); interval = optDlg.GetInterval(); maxLRU = optDlg.GetMaxLRU(); useDNS = optDlg.GetUseDNS(); @@ -893,10 +838,10 @@ int WinMTRDialog::DisplayRedraw() int nh = wmtrnet->GetMax(); while( m_listMTR.GetItemCount() > nh ) m_listMTR.DeleteItem(m_listMTR.GetItemCount() - 1); - for(int i=0;i GetName(i, buf); - if( strcmp(buf,"")==0 ) strcpy(buf,"No response from host"); + if(!*buf) strcpy(buf,"No response from host"); sprintf(nr_crt, "%d", i+1); if(m_listMTR.GetItemCount() <= i ) @@ -941,35 +886,33 @@ int WinMTRDialog::DisplayRedraw() //***************************************************************************** int WinMTRDialog::InitMTRNet() { - char strtmp[255]; - char *Hostname = strtmp; + char hostname[255]; char buf[255]; - struct hostent *host; - m_comboHost.GetWindowText(strtmp, 255); - - if (Hostname == NULL) Hostname = "localhost"; - - int isIP=1; - char *t = Hostname; - while(*t) { - if(!isdigit(*t) && *t!='.') { - isIP=0; - break; + m_comboHost.GetWindowText(hostname, 255); + + sprintf(buf, "Resolving host %s...", hostname); + statusBar.SetPaneText(0,buf); + + addrinfo nfofilter={0}; + addrinfo* anfo; + if(wmtrnet->hasIPv6){ + switch(useIPv6){ + case 0: + nfofilter.ai_family=AF_INET;break; + case 1: + nfofilter.ai_family=AF_INET6;break; + default: + nfofilter.ai_family=AF_UNSPEC; } - t++; } - - if(!isIP) { - sprintf(buf, "Resolving host %s...", strtmp); - statusBar.SetPaneText(0,buf); - host = gethostbyname(Hostname); - if(host == NULL) { - statusBar.SetPaneText(0, CString((LPCSTR)IDS_STRING_SB_NAME) ); - AfxMessageBox("Unable to resolve hostname."); - return 0; - } + nfofilter.ai_socktype=SOCK_RAW; + nfofilter.ai_flags=AI_NUMERICSERV|AI_ADDRCONFIG;//|AI_V4MAPPED; + if(getaddrinfo(hostname,NULL,&nfofilter,&anfo)||!anfo){ + statusBar.SetPaneText(0, CString((LPCSTR)IDS_STRING_SB_NAME) ); + AfxMessageBox("Unable to resolve hostname."); + return 0; } - + freeaddrinfo(anfo); return 1; } @@ -984,44 +927,31 @@ void PingThread(void *p) WinMTRDialog *wmtrdlg = (WinMTRDialog *)p; WaitForSingleObject(wmtrdlg->traceThreadMutex, INFINITE); - struct hostent *host, *lhost; - char strtmp[255]; - char *Hostname = strtmp; - int traddr; - int localaddr; - - wmtrdlg->m_comboHost.GetWindowText(strtmp, 255); - - if (Hostname == NULL) Hostname = "localhost"; - - int isIP=1; - char *t = Hostname; - while(*t) { - if(!isdigit(*t) && *t!='.') { - isIP=0; - break; + char hostname[255]; + wmtrdlg->m_comboHost.GetWindowText(hostname, 255); + + addrinfo nfofilter={0}; + addrinfo* anfo; + if(wmtrdlg->wmtrnet->hasIPv6){ + switch(wmtrdlg->useIPv6){ + case 0: + nfofilter.ai_family=AF_INET;break; + case 1: + nfofilter.ai_family=AF_INET6;break; + default: + nfofilter.ai_family=AF_UNSPEC; } - t++; } - - if(!isIP) { - host = gethostbyname(Hostname); - traddr = *(int *)host->h_addr; - } else - traddr = inet_addr(Hostname); - - lhost = gethostbyname("localhost"); - if(lhost == NULL) { - AfxMessageBox("Unable to get local IP address."); - ReleaseMutex(wmtrdlg->traceThreadMutex); - return; + nfofilter.ai_socktype=SOCK_RAW; + nfofilter.ai_flags=AI_NUMERICSERV|AI_ADDRCONFIG;//|AI_V4MAPPED; + if(getaddrinfo(hostname,NULL,&nfofilter,&anfo)||!anfo){//we use first address returned + AfxMessageBox("Unable to resolve hostname. (again)"); + ReleaseMutex(wmtrdlg->traceThreadMutex); + return; } - localaddr = *(int *)lhost->h_addr; - - wmtrdlg->wmtrnet->DoTrace(traddr); - + wmtrdlg->wmtrnet->DoTrace(anfo->ai_addr); + freeaddrinfo(anfo); ReleaseMutex(wmtrdlg->traceThreadMutex); - _endthread(); } @@ -1137,57 +1067,53 @@ void WinMTRDialog::Transit(STATES new_state) // modify controls according to new state switch(transition) { + case IDLE_TO_IDLE: + // nothing to be done + break; case IDLE_TO_TRACING: m_buttonStart.EnableWindow(FALSE); m_buttonStart.SetWindowText("Stop"); m_comboHost.EnableWindow(FALSE); + m_checkIPv6.EnableWindow(FALSE); m_buttonOptions.EnableWindow(FALSE); statusBar.SetPaneText(0, "Double click on host name for more information."); _beginthread(PingThread, 0 , this); m_buttonStart.EnableWindow(TRUE); break; - case IDLE_TO_IDLE: - // nothing to be done + case IDLE_TO_EXIT: + m_buttonStart.EnableWindow(FALSE); + m_comboHost.EnableWindow(FALSE); + m_buttonOptions.EnableWindow(FALSE); break; case STOPPING_TO_IDLE: + DisplayRedraw(); m_buttonStart.EnableWindow(TRUE); statusBar.SetPaneText(0, CString((LPCSTR)IDS_STRING_SB_NAME) ); m_buttonStart.SetWindowText("Start"); m_comboHost.EnableWindow(TRUE); + m_checkIPv6.EnableWindow(TRUE); m_buttonOptions.EnableWindow(TRUE); m_comboHost.SetFocus(); break; case STOPPING_TO_STOPPING: DisplayRedraw(); break; + case STOPPING_TO_EXIT: + break; case TRACING_TO_TRACING: DisplayRedraw(); break; case TRACING_TO_STOPPING: m_buttonStart.EnableWindow(FALSE); - m_comboHost.EnableWindow(FALSE); - m_buttonOptions.EnableWindow(FALSE); wmtrnet->StopTrace(); statusBar.SetPaneText(0, "Waiting for last packets in order to stop trace ..."); DisplayRedraw(); break; - case IDLE_TO_EXIT: - m_buttonStart.EnableWindow(FALSE); - m_comboHost.EnableWindow(FALSE); - m_buttonOptions.EnableWindow(FALSE); - break; case TRACING_TO_EXIT: m_buttonStart.EnableWindow(FALSE); - m_comboHost.EnableWindow(FALSE); - m_buttonOptions.EnableWindow(FALSE); wmtrnet->StopTrace(); statusBar.SetPaneText(0, "Waiting for last packets in order to stop trace ..."); break; - case STOPPING_TO_EXIT: - m_buttonStart.EnableWindow(FALSE); - m_comboHost.EnableWindow(FALSE); - m_buttonOptions.EnableWindow(FALSE); - break; default: TRACE_MSG("Unknown transition " << transition); } @@ -1196,22 +1122,18 @@ void WinMTRDialog::Transit(STATES new_state) void WinMTRDialog::OnTimer(UINT_PTR nIDEvent) { - static unsigned int call_count = 0; - call_count += 1; - + static unsigned int call_count=0; if(state == EXIT && WaitForSingleObject(traceThreadMutex, 0) == WAIT_OBJECT_0) { ReleaseMutex(traceThreadMutex); OnOK(); } - if( WaitForSingleObject(traceThreadMutex, 0) == WAIT_OBJECT_0 ) { ReleaseMutex(traceThreadMutex); Transit(IDLE); - } else if( (call_count % 10 == 0) && (WaitForSingleObject(traceThreadMutex, 0) == WAIT_TIMEOUT) ) { - ReleaseMutex(traceThreadMutex); - if( state == TRACING) Transit(TRACING); - else if( state == STOPPING) Transit(STOPPING); + }else if((++call_count&5)==5){ + if(state==TRACING) Transit(TRACING); + else if(state==STOPPING) Transit(STOPPING); } CDialog::OnTimer(nIDEvent); diff --git a/src/WinMTRDialog.h b/src/WinMTRDialog.h index a214d7b..3ac6534 100644 --- a/src/WinMTRDialog.h +++ b/src/WinMTRDialog.h @@ -17,6 +17,7 @@ #include "WinMTRStatusBar.h" #include "WinMTRNet.h" +#include "afxlinkctrl.h" //***************************************************************************** // CLASS: WinMTRDialog @@ -59,7 +60,9 @@ class WinMTRDialog : public CDialog CButton m_buttonExit; CButton m_buttonStart; CComboBox m_comboHost; - CListCtrl m_listMTR; + CButton m_checkIPv6; + CListCtrl m_listMTR; + CMFCLinkCtrl m_buttonAppnor; CStatic m_staticS; CStatic m_staticJ; @@ -77,18 +80,20 @@ class WinMTRDialog : public CDialog HANDLE traceThreadMutex; double interval; bool hasIntervalFromCmdLine; - int pingsize; + WORD pingsize; bool hasPingsizeFromCmdLine; int maxLRU; bool hasMaxLRUFromCmdLine; int nrLRU; BOOL useDNS; bool hasUseDNSFromCmdLine; + unsigned char useIPv6; + bool hasUseIPv6FromCmdLine; WinMTRNet* wmtrnet; void SetHostName(const char *host); void SetInterval(float i); - void SetPingSize(int ps); + void SetPingSize(WORD ps); void SetMaxLRU(int mlru); void SetUseDNS(BOOL udns); diff --git a/src/WinMTRGlobal.cpp b/src/WinMTRGlobal.cpp index 0f435c8..053fba1 100644 --- a/src/WinMTRGlobal.cpp +++ b/src/WinMTRGlobal.cpp @@ -11,7 +11,7 @@ // // win32 port of unix gettimeofday //***************************************************************************** -int gettimeofday(struct timeval* tv, struct timezone *tz) +int gettimeofday(struct timeval* tv, struct timezone* /*tz*/) { if(!tv) return -1; @@ -19,7 +19,7 @@ int gettimeofday(struct timeval* tv, struct timezone *tz) _ftime(&timebuffer); - tv->tv_sec = timebuffer.time; + tv->tv_sec = (long)timebuffer.time; tv->tv_usec = timebuffer.millitm * 1000 + 500; return 0; } diff --git a/src/WinMTRGlobal.h b/src/WinMTRGlobal.h index 53524ee..3f3102e 100644 --- a/src/WinMTRGlobal.h +++ b/src/WinMTRGlobal.h @@ -28,6 +28,8 @@ #include #endif #include +#include //IP_OPTION_INFORMATION32 +#include //sockaddr_in6 #include #include @@ -46,10 +48,9 @@ #include "resource.h" -#define WINMTR_VERSION "0.9" -#define WINMTR_LICENSE "GPL - GNU Public License" -#define WINMTR_COPYRIGHT "WinMTR 0.9 (c) 2010-2011 Appnor MSP - Fully Managed Hosting & Cloud Provider www.appnor.com" -#define WINMTR_HOMEPAGE "http://WinMTR.sourceforge.net" +#define WINMTR_VERSION "1.0" +#define WINMTR_LICENSE "GPLv2 - GNU General Public License, version 2" +#define WINMTR_HOMEPAGE "https://github.com/White-Tiger/WinMTR" #define DEFAULT_PING_SIZE 64 #define DEFAULT_INTERVAL 1.0 @@ -98,7 +99,7 @@ const char MTR_COLS[ MTR_NR_COLS ][10] = { }; const int MTR_COL_LENGTH[ MTR_NR_COLS ] = { - 190, 30, 50, 40, 40, 50, 50, 50, 50 + 249, 30, 50, 40, 40, 50, 50, 50, 50 }; int gettimeofday(struct timeval* tv, struct timezone *tz); diff --git a/src/WinMTRMain.cpp b/src/WinMTRMain.cpp index 7e740fe..581583f 100644 --- a/src/WinMTRMain.cpp +++ b/src/WinMTRMain.cpp @@ -61,6 +61,8 @@ WinMTRMain::WinMTRMain() //***************************************************************************** BOOL WinMTRMain::InitInstance() { + INITCOMMONCONTROLSEX icex={sizeof(INITCOMMONCONTROLSEX),ICC_STANDARD_CLASSES}; + InitCommonControlsEx(&icex); if (!AfxSocketInit()) { AfxMessageBox(IDP_SOCKETS_INIT_FAILED); @@ -68,10 +70,6 @@ BOOL WinMTRMain::InitInstance() } AfxEnableControlContainer(); - -#ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL -#endif WinMTRDialog mtrDialog; @@ -82,7 +80,7 @@ BOOL WinMTRMain::InitInstance() ParseCommandLineParams(m_lpCmdLine, &mtrDialog); } - int nResponse = mtrDialog.DoModal(); + mtrDialog.DoModal(); return FALSE; @@ -114,17 +112,25 @@ void WinMTRMain::ParseCommandLineParams(LPTSTR cmd, WinMTRDialog *wmtrdlg) wmtrdlg->hasIntervalFromCmdLine = true; } if(GetParamValue(cmd, "size",'s', value)) { - wmtrdlg->SetPingSize(atoi(value)); + wmtrdlg->SetPingSize((WORD)atoi(value)); wmtrdlg->hasPingsizeFromCmdLine = true; } if(GetParamValue(cmd, "maxLRU",'m', value)) { wmtrdlg->SetMaxLRU(atoi(value)); wmtrdlg->hasMaxLRUFromCmdLine = true; } - if(GetParamValue(cmd, "numeric",'n', value)) { + if(GetParamValue(cmd, "numeric",'n', NULL)) { wmtrdlg->SetUseDNS(FALSE); wmtrdlg->hasUseDNSFromCmdLine = true; } + if(GetParamValue(cmd, "ipv6",'6', NULL)) { + wmtrdlg->hasUseIPv6FromCmdLine=true; + wmtrdlg->useIPv6=1; + } + if(GetParamValue(cmd, "ipv4",'4', NULL)) { + wmtrdlg->hasUseIPv6FromCmdLine=true; + wmtrdlg->useIPv6=0; + } } //***************************************************************************** @@ -149,7 +155,7 @@ int WinMTRMain::GetParamValue(LPTSTR cmd, char * param, char sparam, char *value if(p == NULL) return 0; - if(strcmp(param,"numeric")==0) + if(!value) return 1; while(*p && *p!=' ') @@ -172,7 +178,7 @@ int WinMTRMain::GetParamValue(LPTSTR cmd, char * param, char sparam, char *value int WinMTRMain::GetHostNameParamValue(LPTSTR cmd, std::string& host_name) { // WinMTR -h -i 1 -n google.com - int size = strlen(cmd); + size_t size = strlen(cmd); std::string name = ""; while(cmd[--size] == ' '); @@ -200,7 +206,7 @@ int WinMTRMain::GetHostNameParamValue(LPTSTR cmd, std::string& host_name) possible_argument = cmd[size] + possible_argument; } - if(possible_argument.length() && (possible_argument[0] != '-' || possible_argument == "-n" || possible_argument == "--numeric")) { + if(possible_argument.length() && (possible_argument[0] != '-' || possible_argument == "-n" || possible_argument == "--numeric" || possible_argument == "-6" || possible_argument == "--ipv6" || possible_argument == "-4" || possible_argument == "--ipv4")) { host_name = name; return 1; } diff --git a/src/WinMTRNet.cpp b/src/WinMTRNet.cpp index 7c5e8ae..bcc8a6d 100644 --- a/src/WinMTRNet.cpp +++ b/src/WinMTRNet.cpp @@ -19,22 +19,29 @@ #define MAX_HOPS 30 struct trace_thread { - int address; - WinMTRNet *winmtr; + WinMTRNet* winmtr; + in_addr address; int ttl; }; +struct trace_thread6 { + WinMTRNet* winmtr; + sockaddr_in6 address; + int ttl; +}; struct dns_resolver_thread { + WinMTRNet* winmtr; int index; - WinMTRNet *winmtr; }; -void TraceThread(void *p); +unsigned WINAPI TraceThread(void *p); +unsigned WINAPI TraceThread6(void *p); void DnsResolverThread(void *p); WinMTRNet::WinMTRNet(WinMTRDialog *wp) { ghMutex = CreateMutex(NULL, FALSE, NULL); + hasIPv6=true; tracing=false; initialized = false; wmtrdlg = wp; @@ -44,32 +51,61 @@ WinMTRNet::WinMTRNet(WinMTRDialog *wp) { AfxMessageBox("Failed initializing windows sockets library!"); return; } - - hICMP_DLL = LoadLibrary(_T("ICMP.DLL")); - if (hICMP_DLL == 0) { - AfxMessageBox("Failed: Unable to locate ICMP.DLL!"); - return; - } + OSVERSIONINFOEX osvi={0}; + osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX); + if(!GetVersionEx((OSVERSIONINFO*) &osvi)){ + AfxMessageBox("Failed to get Windows version!"); + return; + } + if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0){//w2k + hICMP_DLL=LoadLibrary(_T("ICMP.DLL")); + if(!hICMP_DLL){ + AfxMessageBox("Failed: Unable to locate ICMP.DLL!"); + return; + } + }else{ + hICMP_DLL=LoadLibrary(_T("Iphlpapi.dll")); + if(!hICMP_DLL){ + AfxMessageBox("Failed: Unable to locate Iphlpapi.dll!"); + return; + } + } /* * Get pointers to ICMP.DLL functions */ + //IPv4 lpfnIcmpCreateFile = (LPFNICMPCREATEFILE)GetProcAddress(hICMP_DLL,"IcmpCreateFile"); lpfnIcmpCloseHandle = (LPFNICMPCLOSEHANDLE)GetProcAddress(hICMP_DLL,"IcmpCloseHandle"); - lpfnIcmpSendEcho = (LPFNICMPSENDECHO)GetProcAddress(hICMP_DLL,"IcmpSendEcho"); - if ((!lpfnIcmpCreateFile) || (!lpfnIcmpCloseHandle) || (!lpfnIcmpSendEcho)) { - AfxMessageBox("Wrong ICMP.DLL system library !"); + lpfnIcmpSendEcho2 = (LPFNICMPSENDECHO2)GetProcAddress(hICMP_DLL,"IcmpSendEcho2"); + if (!lpfnIcmpCreateFile || !lpfnIcmpCloseHandle || !lpfnIcmpSendEcho2) { + AfxMessageBox("Wrong ICMP system library !"); return; } + //IPv6 + lpfnIcmp6CreateFile=(LPFNICMP6CREATEFILE)GetProcAddress(hICMP_DLL,"Icmp6CreateFile"); + lpfnIcmp6SendEcho2=(LPFNICMP6SENDECHO2)GetProcAddress(hICMP_DLL,"Icmp6SendEcho2"); + if(!lpfnIcmp6CreateFile || !lpfnIcmp6SendEcho2){ + hasIPv6=false; + AfxMessageBox("IPv6 support not found!"); + return;//@todo : soft fail + } /* * IcmpCreateFile() - Open the ping service */ hICMP = (HANDLE) lpfnIcmpCreateFile(); if (hICMP == INVALID_HANDLE_VALUE) { - AfxMessageBox("Error in ICMP.DLL !"); + AfxMessageBox("Error in ICMP module!"); return; } + if(hasIPv6){ + hICMP6=(HANDLE)lpfnIcmp6CreateFile(); + if(hICMP6==INVALID_HANDLE_VALUE){ + AfxMessageBox("Error in ICMPv6 module!"); + return;//@todo : soft fail + } + } ResetHops(); @@ -83,6 +119,7 @@ WinMTRNet::~WinMTRNet() /* * IcmpCloseHandle - Close the ICMP handle */ + if(hasIPv6) lpfnIcmpCloseHandle(hICMP6); lpfnIcmpCloseHandle(hICMP); // Shut down... @@ -96,37 +133,42 @@ WinMTRNet::~WinMTRNet() void WinMTRNet::ResetHops() { - for(int i = 0; i < MaxHost;i++) { - host[i].addr = 0; - host[i].xmit = 0; - host[i].returned = 0; - host[i].total = 0; - host[i].last = 0; - host[i].best = 0; - host[i].worst = 0; - memset(host[i].name,0,sizeof(host[i].name)); - } + memset(host,0,sizeof(host)); } -void WinMTRNet::DoTrace(int address) +void WinMTRNet::DoTrace(sockaddr* sockaddr) { HANDLE hThreads[MAX_HOPS]; + unsigned char hops=0; tracing = true; - ResetHops(); - - last_remote_addr = address; - - // one thread per TTL value - for(int i = 0; i < MAX_HOPS; i++) { - trace_thread *current = new trace_thread; - current->address = address; - current->winmtr = this; - current->ttl = i + 1; - hThreads[i] = (HANDLE)_beginthread(TraceThread, 0 , current); + if(sockaddr->sa_family==AF_INET6){ + host[0].addr6.sin6_family=AF_INET6; + last_remote_addr6=((sockaddr_in6*)sockaddr)->sin6_addr; + for(; hopsaddress=*(sockaddr_in6*)sockaddr; + current->winmtr=this; + current->ttl=hops+1; + hThreads[hops]=(HANDLE)_beginthreadex(NULL,0,TraceThread6,current,0,NULL); + Sleep(30); + if(++hops>this->GetMax()) break; + } + }else{ + host[0].addr.sin_family=AF_INET; + last_remote_addr=((sockaddr_in*)sockaddr)->sin_addr; + for(; hopsaddress=((sockaddr_in*)sockaddr)->sin_addr; + current->winmtr=this; + current->ttl=hops+1; + hThreads[hops]=(HANDLE)_beginthreadex(NULL,0,TraceThread,current,0,NULL); + Sleep(30); + if(++hops>this->GetMax()) break; + } } - - WaitForMultipleObjects(MAX_HOPS, hThreads, TRUE, INFINITE); + WaitForMultipleObjects(hops, hThreads, TRUE, INFINITE); + for(; hops; ) CloseHandle(hThreads[--hops]); } void WinMTRNet::StopTrace() @@ -134,24 +176,27 @@ void WinMTRNet::StopTrace() tracing = false; } -void TraceThread(void *p) +unsigned WINAPI TraceThread(void *p) { trace_thread* current = (trace_thread*)p; WinMTRNet *wmtrnet = current->winmtr; - TRACE_MSG("Threaad with TTL=" << current->ttl << " started."); + TRACE_MSG("Thread with TTL=" << (int)current->ttl << " started."); IPINFO stIPInfo, *lpstIPInfo; DWORD dwReplyCount; char achReqData[8192]; - int nDataLen = wmtrnet->wmtrdlg->pingsize; - char achRepData[sizeof(ICMPECHO) + 8192]; + WORD nDataLen = wmtrnet->wmtrdlg->pingsize; + union{ + ICMP_ECHO_REPLY icmp_echo_reply; + char achRepData[sizeof(ICMPECHO)+8192]; + }; /* * Init IPInfo structure */ lpstIPInfo = &stIPInfo; - stIPInfo.Ttl = current->ttl; + stIPInfo.Ttl = (UCHAR)current->ttl; stIPInfo.Tos = 0; stIPInfo.Flags = IPFLAG_DONT_FRAGMENT; stIPInfo.OptionsSize = 0; @@ -172,117 +217,107 @@ void TraceThread(void *p) // - as soon as we get a hop, we start pinging directly that hop, with a greater TTL // - a drawback would be that, some servers are configured to reply for TTL transit expire, but not to ping requests, so, // for these servers we'll have 100% loss - dwReplyCount = wmtrnet->lpfnIcmpSendEcho(wmtrnet->hICMP, current->address, achReqData, nDataLen, lpstIPInfo, achRepData, sizeof(achRepData), ECHO_REPLY_TIMEOUT); - - PICMPECHO icmp_echo_reply = (PICMPECHO)achRepData; + dwReplyCount = wmtrnet->lpfnIcmpSendEcho2(wmtrnet->hICMP, 0,NULL,NULL, current->address, achReqData, nDataLen, lpstIPInfo, achRepData, sizeof(achRepData), ECHO_REPLY_TIMEOUT); wmtrnet->AddXmit(current->ttl - 1); - if (dwReplyCount != 0) { - TRACE_MSG("TTL " << current->ttl << " reply TTL " << icmp_echo_reply->Options.Ttl << " Status " << icmp_echo_reply->Status << " Reply count " << dwReplyCount); + if(dwReplyCount){ + TRACE_MSG("TTL " << (int)current->ttl << " reply TTL " << (int)icmp_echo_reply.Options.Ttl << " Status " << icmp_echo_reply.Status << " Reply count " << dwReplyCount); - switch(icmp_echo_reply->Status) { + switch(icmp_echo_reply.Status) { case IP_SUCCESS: case IP_TTL_EXPIRED_TRANSIT: - wmtrnet->SetLast(current->ttl - 1, icmp_echo_reply->RoundTripTime); - wmtrnet->SetBest(current->ttl - 1, icmp_echo_reply->RoundTripTime); - wmtrnet->SetWorst(current->ttl - 1, icmp_echo_reply->RoundTripTime); + wmtrnet->UpdateRTT(current->ttl - 1, icmp_echo_reply.RoundTripTime); wmtrnet->AddReturned(current->ttl - 1); - wmtrnet->SetAddr(current->ttl - 1, icmp_echo_reply->Address); - break; - case IP_BUF_TOO_SMALL: - wmtrnet->SetName(current->ttl - 1, "Reply buffer too small."); - break; - case IP_DEST_NET_UNREACHABLE: - wmtrnet->SetName(current->ttl - 1, "Destination network unreachable."); - break; - case IP_DEST_HOST_UNREACHABLE: - wmtrnet->SetName(current->ttl - 1, "Destination host unreachable."); - break; - case IP_DEST_PROT_UNREACHABLE: - wmtrnet->SetName(current->ttl - 1, "Destination protocol unreachable."); - break; - case IP_DEST_PORT_UNREACHABLE: - wmtrnet->SetName(current->ttl - 1, "Destination port unreachable."); - break; - case IP_NO_RESOURCES: - wmtrnet->SetName(current->ttl - 1, "Insufficient IP resources were available."); - break; - case IP_BAD_OPTION: - wmtrnet->SetName(current->ttl - 1, "Bad IP option was specified."); - break; - case IP_HW_ERROR: - wmtrnet->SetName(current->ttl - 1, "Hardware error occurred."); - break; - case IP_PACKET_TOO_BIG: - wmtrnet->SetName(current->ttl - 1, "Packet was too big."); - break; - case IP_REQ_TIMED_OUT: - wmtrnet->SetName(current->ttl - 1, "Request timed out."); - break; - case IP_BAD_REQ: - wmtrnet->SetName(current->ttl - 1, "Bad request."); - break; - case IP_BAD_ROUTE: - wmtrnet->SetName(current->ttl - 1, "Bad route."); - break; - case IP_TTL_EXPIRED_REASSEM: - wmtrnet->SetName(current->ttl - 1, "The time to live expired during fragment reassembly."); - break; - case IP_PARAM_PROBLEM: - wmtrnet->SetName(current->ttl - 1, "Parameter problem."); - break; - case IP_SOURCE_QUENCH: - wmtrnet->SetName(current->ttl - 1, "Datagrams are arriving too fast to be processed and datagrams may have been discarded."); - break; - case IP_OPTION_TOO_BIG: - wmtrnet->SetName(current->ttl - 1, "An IP option was too big."); - break; - case IP_BAD_DESTINATION: - wmtrnet->SetName(current->ttl - 1, "Bad destination."); - break; - case IP_GENERAL_FAILURE: - wmtrnet->SetName(current->ttl - 1, "General failure."); + wmtrnet->SetAddr(current->ttl - 1, icmp_echo_reply.Address); break; default: - wmtrnet->SetName(current->ttl - 1, "General failure."); + wmtrnet->SetErrorName(current->ttl - 1, icmp_echo_reply.Status); } - if(wmtrnet->wmtrdlg->interval * 1000 > icmp_echo_reply->RoundTripTime) - Sleep(wmtrnet->wmtrdlg->interval * 1000 - icmp_echo_reply->RoundTripTime); + if((DWORD)(wmtrnet->wmtrdlg->interval * 1000) > icmp_echo_reply.RoundTripTime) + Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000) - icmp_echo_reply.RoundTripTime); + }else{ + DWORD err=GetLastError(); + wmtrnet->SetErrorName(current->ttl - 1, err); + switch(err){ + case IP_REQ_TIMED_OUT: break; + default: + Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000)); + } } - } /* end ping loop */ - TRACE_MSG("Thread with TTL=" << current->ttl << " stopped."); + TRACE_MSG("Thread with TTL=" << (int)current->ttl << " stopped."); delete p; - _endthread(); + return 0; } -int WinMTRNet::GetAddr(int at) +unsigned WINAPI TraceThread6(void* p) { - WaitForSingleObject(ghMutex, INFINITE); - int addr = ntohl(host[at].addr); - ReleaseMutex(ghMutex); - return addr; + static sockaddr_in6 sockaddrfrom={AF_INET6,0,0,in6addr_any,0}; + trace_thread6* current = (trace_thread6*)p; + WinMTRNet* wmtrnet = current->winmtr; + TRACE_MSG("Thread with TTL=" << (int)current->ttl << " started."); + + IPINFO stIPInfo, *lpstIPInfo; + DWORD dwReplyCount; + char achReqData[8192]; + WORD nDataLen = wmtrnet->wmtrdlg->pingsize; + union{ + ICMPV6_ECHO_REPLY icmpv6_echo_reply; + char achRepData[sizeof(PICMPV6_ECHO_REPLY) + 8192]; + }; + + lpstIPInfo = &stIPInfo; + stIPInfo.Ttl = (UCHAR)current->ttl; + stIPInfo.Tos = 0; + stIPInfo.Flags = IPFLAG_DONT_FRAGMENT; + stIPInfo.OptionsSize = 0; + stIPInfo.OptionsData = NULL; + for(int i=0; itracing){ + if(current->ttl > wmtrnet->GetMax()) break; + dwReplyCount = wmtrnet->lpfnIcmp6SendEcho2(wmtrnet->hICMP6, 0,NULL,NULL, &sockaddrfrom, ¤t->address, achReqData, nDataLen, lpstIPInfo, achRepData, sizeof(achRepData), ECHO_REPLY_TIMEOUT); + wmtrnet->AddXmit(current->ttl - 1); + if(dwReplyCount) { + TRACE_MSG("TTL " << (int)current->ttl << " Status " << icmpv6_echo_reply.Status << " Reply count " << dwReplyCount); + switch(icmpv6_echo_reply.Status) { + case IP_SUCCESS: + case IP_TTL_EXPIRED_TRANSIT: + wmtrnet->UpdateRTT(current->ttl - 1, icmpv6_echo_reply.RoundTripTime); + wmtrnet->AddReturned(current->ttl - 1); + wmtrnet->SetAddr6(current->ttl - 1, icmpv6_echo_reply.Address); + break; + default: + wmtrnet->SetErrorName(current->ttl - 1, icmpv6_echo_reply.Status); + } + if((DWORD)(wmtrnet->wmtrdlg->interval * 1000) > icmpv6_echo_reply.RoundTripTime) + Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000) - icmpv6_echo_reply.RoundTripTime); + }else{ + DWORD err=GetLastError(); + wmtrnet->SetErrorName(current->ttl - 1, err); + switch(err){ + case IP_REQ_TIMED_OUT: break; + default: + Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000)); + } + } + }//end loop + TRACE_MSG("Thread with TTL=" << (int)current->ttl << " stopped."); + delete p; + return 0; +} + +sockaddr* WinMTRNet::GetAddr(int at) +{ + return (sockaddr*)&host[at].addr; } int WinMTRNet::GetName(int at, char *n) { WaitForSingleObject(ghMutex, INFINITE); - if(!strcmp(host[at].name, "")) { - int addr = GetAddr(at); - sprintf ( n, "%d.%d.%d.%d", - (addr >> 24) & 0xff, - (addr >> 16) & 0xff, - (addr >> 8) & 0xff, - addr & 0xff - ); - if(addr==0) - strcpy(n,""); - } else { - strcpy(n, host[at].name); - } + strcpy(n, host[at].name); ReleaseMutex(ghMutex); return 0; } @@ -344,112 +379,165 @@ int WinMTRNet::GetXmit(int at) } int WinMTRNet::GetMax() -{ +{// @todo : improve this (last hop guess) WaitForSingleObject(ghMutex, INFINITE); - int max = MAX_HOPS; - - // first match: traced address responds on ping requests, and the address is in the hosts list - for(int i = 0; i < MAX_HOPS; i++) { - if(host[i].addr == last_remote_addr) { - max = i + 1; - break; + int max=0;//first try to find target, if not found, find best guess (doesn't work actually :P) + if(host[0].addr6.sin6_family==AF_INET6){ + for(; max1 && !memcmp(&host[max-1].addr6.sin6_addr,&host[max-2].addr6.sin6_addr,sizeof(in6_addr)) && (host[max-1].addr6.sin6_addr.u.Word[0]|host[max-1].addr6.sin6_addr.u.Word[1]|host[max-1].addr6.sin6_addr.u.Word[2]|host[max-1].addr6.sin6_addr.u.Word[3]|host[max-1].addr6.sin6_addr.u.Word[4]|host[max-1].addr6.sin6_addr.u.Word[5]|host[max-1].addr6.sin6_addr.u.Word[6]|host[max-1].addr6.sin6_addr.u.Word[7])) --max; + } + }else{ + for(; max1 && host[max-1].addr.sin_addr.s_addr==host[max-2].addr.sin_addr.s_addr && host[max-1].addr.sin_addr.s_addr) --max; } } - - // second match: traced address doesn't responds on ping requests - if(max == MAX_HOPS) { - while((max > 1) && (host[max - 1].addr == host[max - 2].addr) && (host[max - 1].addr != 0) ) max--; - } - ReleaseMutex(ghMutex); return max; } -void WinMTRNet::SetAddr(int at, __int32 addr) +void WinMTRNet::SetAddr(int at, u_long addr) { WaitForSingleObject(ghMutex, INFINITE); - if(host[at].addr == 0 && addr != 0) { - TRACE_MSG("Start DnsResolverThread for new address " << addr << ". Old addr value was " << host[at].addr); - host[at].addr = addr; - dns_resolver_thread *dnt = new dns_resolver_thread; - dnt->index = at; - dnt->winmtr = this; + if(host[at].addr.sin_addr.s_addr==0){ + TRACE_MSG("Start DnsResolverThread for new address " << addr << ". Old addr value was " << host[at].addr.sin_addr.s_addr); + host[at].addr.sin_family=AF_INET; + host[at].addr.sin_addr.s_addr=addr; + dns_resolver_thread *dnt=new dns_resolver_thread; + dnt->index=at; + dnt->winmtr=this; if(wmtrdlg->useDNS) _beginthread(DnsResolverThread, 0, dnt); + else DnsResolverThread(dnt); } - ReleaseMutex(ghMutex); } -void WinMTRNet::SetName(int at, char *n) +void WinMTRNet::SetAddr6(int at, IPV6_ADDRESS_EX addrex) { WaitForSingleObject(ghMutex, INFINITE); - strcpy(host[at].name, n); + if(!(host[at].addr6.sin6_addr.u.Word[0]|host[at].addr6.sin6_addr.u.Word[1]|host[at].addr6.sin6_addr.u.Word[2]|host[at].addr6.sin6_addr.u.Word[3]|host[at].addr6.sin6_addr.u.Word[4]|host[at].addr6.sin6_addr.u.Word[5]|host[at].addr6.sin6_addr.u.Word[6]|host[at].addr6.sin6_addr.u.Word[7])){ + TRACE_MSG("Start DnsResolverThread for new address " << addrex.sin6_addr[0] << ". Old addr value was " << host[at].addr6.sin6_addr.u.Word[0]); + host[at].addr6.sin6_family=AF_INET6; + host[at].addr6.sin6_addr=*(in6_addr*)&addrex.sin6_addr; + dns_resolver_thread* dnt=new dns_resolver_thread; + dnt->index=at; + dnt->winmtr=this; + if(wmtrdlg->useDNS) _beginthread(DnsResolverThread,0,dnt); + else DnsResolverThread(dnt); + } ReleaseMutex(ghMutex); } -void WinMTRNet::SetBest(int at, int current) +void WinMTRNet::SetName(int at, char *n) { WaitForSingleObject(ghMutex, INFINITE); - if(host[at].best > current || host[at].xmit == 1) { - host[at].best = current; - }; - if(host[at].worst < current) { - host[at].worst = current; - } - + strcpy(host[at].name, n); ReleaseMutex(ghMutex); } -void WinMTRNet::SetWorst(int at, int current) -{ +void WinMTRNet::SetErrorName(int at, DWORD errnum){ + const char* name; + switch(errnum){ + case IP_BUF_TOO_SMALL: + name="Reply buffer too small.";break; + case IP_DEST_NET_UNREACHABLE: + name="Destination network unreachable.";break; + case IP_DEST_HOST_UNREACHABLE: + name="Destination host unreachable.";break; + case IP_DEST_PROT_UNREACHABLE: + name="Destination protocol unreachable.";break; + case IP_DEST_PORT_UNREACHABLE: + name="Destination port unreachable.";break; + case IP_NO_RESOURCES: + name="Insufficient IP resources were available.";break; + case IP_BAD_OPTION: + name="Bad IP option was specified.";break; + case IP_HW_ERROR: + name="Hardware error occurred.";break; + case IP_PACKET_TOO_BIG: + name="Packet was too big.";break; + case IP_REQ_TIMED_OUT: + name="Request timed out.";break; + case IP_BAD_REQ: + name="Bad request.";break; + case IP_BAD_ROUTE: + name="Bad route.";break; + case IP_TTL_EXPIRED_REASSEM: + name="The time to live expired during fragment reassembly.";break; + case IP_PARAM_PROBLEM: + name="Parameter problem.";break; + case IP_SOURCE_QUENCH: + name="Datagrams are arriving too fast to be processed and datagrams may have been discarded.";break; + case IP_OPTION_TOO_BIG: + name="An IP option was too big.";break; + case IP_BAD_DESTINATION: + name="Bad destination.";break; + case IP_GENERAL_FAILURE: + name="General failure.";break; + default: + TRACE_MSG("==UNKNOWN ERROR== " << errnum); + name="Unknown error! (please report)";break; + } WaitForSingleObject(ghMutex, INFINITE); + if(!*host[at].name) + strcpy(host[at].name,name); ReleaseMutex(ghMutex); } -void WinMTRNet::SetLast(int at, int last) +void WinMTRNet::UpdateRTT(int at, int rtt) { WaitForSingleObject(ghMutex, INFINITE); - host[at].last = last; - host[at].total += last; + host[at].last=rtt; + host[at].total+=rtt; + if(host[at].best>rtt || host[at].xmit==1) + host[at].best=rtt; + if(host[at].worstwinmtr; + dns_resolver_thread* dnt=(dns_resolver_thread*)p; + WinMTRNet* wn=dnt->winmtr; + char hostname[NI_MAXHOST]; + if(!getnameinfo(wn->GetAddr(dnt->index),sizeof(sockaddr_in6),hostname,NI_MAXHOST,NULL,0,NI_NUMERICHOST)){ + wn->SetName(dnt->index,hostname); + } + if(wn->wmtrdlg->useDNS){ + TRACE_MSG("DNS resolver thread started."); + if(!getnameinfo(wn->GetAddr(dnt->index),sizeof(sockaddr_in6),hostname,NI_MAXHOST,NULL,0,0)){ + wn->SetName(dnt->index,hostname); + } + TRACE_MSG("DNS resolver thread stopped."); + } + delete p; +} + + + + + + + + + - struct hostent *phent ; - char buf[100]; - int addr = wn->GetAddr(dnt->index); - sprintf (buf, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); - int haddr = htonl(addr); - phent = gethostbyaddr( (const char*)&haddr, sizeof(int), AF_INET); - if(phent) { - wn->SetName(dnt->index, phent->h_name); - } else { - wn->SetName(dnt->index, buf); - } - - delete p; - TRACE_MSG("DNS resolver thread stopped."); - _endthread(); -} diff --git a/src/WinMTRNet.h b/src/WinMTRNet.h index a372a57..d3206d6 100644 --- a/src/WinMTRNet.h +++ b/src/WinMTRNet.h @@ -16,18 +16,20 @@ class WinMTRDialog; -typedef ip_option_information IPINFO, *PIPINFO, FAR *LPIPINFO; - +typedef IP_OPTION_INFORMATION IPINFO, *PIPINFO, FAR *LPIPINFO; #ifdef _WIN64 -typedef icmp_echo_reply32 ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; +typedef ICMP_ECHO_REPLY32 ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; #else -typedef icmp_echo_reply ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; -#endif +typedef ICMP_ECHO_REPLY ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; +#endif // _WIN64 #define ECHO_REPLY_TIMEOUT 5000 struct s_nethost { - __int32 addr; // IP as a decimal, big endian + union{ + sockaddr_in addr; + sockaddr_in6 addr6; + }; int xmit; // number of PING packets sent int returned; // number of ICMP echo replies received unsigned long total; // total time @@ -44,19 +46,25 @@ struct s_nethost { //***************************************************************************** class WinMTRNet { + typedef FARPROC PIO_APC_ROUTINE;//not the best way to do it, but works ;) (we do not use it anyway) + //IPv4 typedef HANDLE (WINAPI *LPFNICMPCREATEFILE)(VOID); typedef BOOL (WINAPI *LPFNICMPCLOSEHANDLE)(HANDLE); - typedef DWORD (WINAPI *LPFNICMPSENDECHO)(HANDLE, u_long, LPVOID, WORD, LPVOID, LPVOID, DWORD, DWORD); + typedef DWORD (WINAPI *LPFNICMPSENDECHO2)(HANDLE IcmpHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,in_addr DestinationAddress,LPVOID RequestData,WORD RequestSize,PIP_OPTION_INFORMATION RequestOptions,LPVOID ReplyBuffer,DWORD ReplySize,DWORD Timeout); + //IPv6 + typedef HANDLE (WINAPI *LPFNICMP6CREATEFILE)(VOID); + typedef BOOL (WINAPI *LPFNICMP6CLOSEHANDLE)(HANDLE); + typedef DWORD (WINAPI *LPFNICMP6SENDECHO2)(HANDLE IcmpHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,sockaddr_in6* SourceAddress,sockaddr_in6* DestinationAddress,LPVOID RequestData,WORD RequestSize,PIP_OPTION_INFORMATION RequestOptions,LPVOID ReplyBuffer,DWORD ReplySize,DWORD Timeout); public: WinMTRNet(WinMTRDialog *wp); ~WinMTRNet(); - void DoTrace(int address); + void DoTrace(sockaddr* sockaddr); void ResetHops(); void StopTrace(); - int GetAddr(int at); + sockaddr* GetAddr(int at); int GetName(int at, char *n); int GetBest(int at); int GetWorst(int at); @@ -67,22 +75,31 @@ class WinMTRNet { int GetXmit(int at); int GetMax(); - void SetAddr(int at, __int32 addr); + void SetAddr(int at, u_long addr); + void SetAddr6(int at, IPV6_ADDRESS_EX addrex); void SetName(int at, char *n); - void SetBest(int at, int current); - void SetWorst(int at, int current); - void SetLast(int at, int last); + void SetErrorName(int at,DWORD errnum); + void UpdateRTT(int at, int rtt); void AddReturned(int at); void AddXmit(int at); WinMTRDialog *wmtrdlg; - __int32 last_remote_addr; + union{ + in_addr last_remote_addr; + in6_addr last_remote_addr6; + }; + bool hasIPv6; bool tracing; bool initialized; - HANDLE hICMP; - LPFNICMPCREATEFILE lpfnIcmpCreateFile; + HANDLE hICMP; + HANDLE hICMP6; + //IPv4 + LPFNICMPCREATEFILE lpfnIcmpCreateFile; LPFNICMPCLOSEHANDLE lpfnIcmpCloseHandle; - LPFNICMPSENDECHO lpfnIcmpSendEcho; + LPFNICMPSENDECHO2 lpfnIcmpSendEcho2; + //IPv6 + LPFNICMP6CREATEFILE lpfnIcmp6CreateFile; + LPFNICMP6SENDECHO2 lpfnIcmp6SendEcho2; private: HINSTANCE hICMP_DLL; diff --git a/src/WinMTRProperties.h b/src/WinMTRProperties.h index 8a7dafc..8eae2d7 100644 --- a/src/WinMTRProperties.h +++ b/src/WinMTRProperties.h @@ -30,7 +30,7 @@ class WinMTRProperties : public CDialog enum { IDD = IDD_DIALOG_PROPERTIES }; char host[255]; - char ip[16]; + char ip[40]; char comment[255]; float ping_last; diff --git a/src/WinMTRStatusBar.cpp b/src/WinMTRStatusBar.cpp index 5d6ba1d..2903079 100644 --- a/src/WinMTRStatusBar.cpp +++ b/src/WinMTRStatusBar.cpp @@ -60,7 +60,7 @@ LRESULT WinMTRStatusBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) void WinMTRStatusBar::RepositionControls() { - HDWP _hDWP = ::BeginDeferWindowPos( m_arrPaneControls.GetSize() ); + HDWP _hDWP = ::BeginDeferWindowPos( (int)m_arrPaneControls.GetSize() ); CRect rcClient; GetClientRect(&rcClient); @@ -170,7 +170,7 @@ BOOL WinMTRStatusBar::AddPane( arrPanesTmp.Add(pNewPane); } - int nPanesCount = arrPanesTmp.GetSize(); + int nPanesCount = (int)arrPanesTmp.GetSize(); UINT* lpIDArray = new UINT[ nPanesCount ]; for (iIndex = 0; iIndex < nPanesCount; iIndex++) { lpIDArray[iIndex] = arrPanesTmp[iIndex]->nID; @@ -232,7 +232,7 @@ BOOL WinMTRStatusBar::RemovePane( } // set the indicators - SetIndicators(lpIDArray, arrPanesTmp.GetSize()); + SetIndicators(lpIDArray, (int)arrPanesTmp.GetSize()); // free memory for (nIndex = 0; nIndex < arrPanesTmp.GetSize(); nIndex++){ _STATUSBAR_PANE_* pPane = arrPanesTmp[nIndex]; diff --git a/src/resource.h b/src/resource.h index 1ca45e3..955b8e3 100644 --- a/src/resource.h +++ b/src/resource.h @@ -39,7 +39,7 @@ #define IDC_STATICJ 1023 #define IDC_COMBO_HOST 1024 #define IDC_EDIT_MAX_LRU 1025 -#define IDC_MFCLINK1 1026 +#define IDC_CHECK_IPV6 1026 // Next default values for new objects //