--- projects/cms/source/host/winhost/nettest.frm 2001/02/28 08:19:00 1.25 +++ projects/cms/source/host/winhost/nettest.frm 2001/03/22 09:27:04 1.39 @@ -4,69 +4,94 @@ Object = "{33155A3D-0CE0-11D1-A6B4-444553540000}#1.0#0 Begin VB.Form Form1 BorderStyle = 3 'Fixed Dialog Caption = "i-scream Winhost" - ClientHeight = 1275 + ClientHeight = 1380 ClientLeft = 45 ClientTop = 330 - ClientWidth = 4710 + ClientWidth = 4635 Icon = "nettest.frx":0000 LinkTopic = "Form1" MaxButton = 0 'False MinButton = 0 'False - ScaleHeight = 1275 - ScaleWidth = 4710 + ScaleHeight = 1380 + ScaleWidth = 4635 ShowInTaskbar = 0 'False StartUpPosition = 2 'CenterScreen Visible = 0 'False + Begin VB.CommandButton Command1 + Caption = "more" + Height = 255 + Left = 3885 + TabIndex = 8 + Top = 1035 + Width = 615 + End + Begin VB.TextBox Text1 + Height = 2055 + Left = 120 + Locked = -1 'True + MultiLine = -1 'True + ScrollBars = 2 'Vertical + TabIndex = 7 + Top = 1440 + Width = 4395 + End Begin VB.CommandButton Hide - Caption = "Hide Window" - Height = 375 - Left = 3120 + Caption = "hide" + Height = 255 + Left = 3225 TabIndex = 6 - Top = 480 - Width = 1455 + Top = 1035 + Width = 615 End Begin SysTray.SystemTray SystemTray - Left = 2160 - Top = 1800 + Left = 2520 + Top = 4200 _ExtentX = 847 _ExtentY = 847 SysTrayText = "i-scream Winhost" IconFile = 0 End Begin VB.Timer Timer1 - Left = 2760 - Top = 1800 + Left = 3120 + Top = 4200 End Begin VB.CommandButton Reconfigure Caption = "Reconfigure with FilterManager" Height = 375 - Left = 120 + Left = 840 TabIndex = 0 - Top = 480 + Top = 3555 Width = 2895 End Begin MSWinsockLib.Winsock TCPSock - Left = 3720 - Top = 1800 + Left = 4080 + Top = 4200 _ExtentX = 741 _ExtentY = 741 _Version = 393216 End Begin MSWinsockLib.Winsock UDPSock - Left = 3240 - Top = 1800 + Left = 3600 + Top = 4200 _ExtentX = 741 _ExtentY = 741 _Version = 393216 Protocol = 1 End + Begin VB.Image Image1 + Height = 900 + Left = 2400 + Picture = "nettest.frx":08CA + Top = 90 + Width = 2100 + End Begin VB.Label Label2 Alignment = 1 'Right Justify Caption = "Next heartbeat:" Height = 255 - Left = 2400 + Left = 120 TabIndex = 5 - Top = 120 + Top = 645 Width = 1455 End Begin VB.Label Label1 @@ -75,16 +100,16 @@ Begin VB.Form Form1 Height = 255 Left = 120 TabIndex = 4 - Top = 120 + Top = 165 Width = 1455 End Begin VB.Label Label4 BorderStyle = 1 'Fixed Single Caption = "0" Height = 255 - Left = 3960 + Left = 1680 TabIndex = 3 - Top = 120 + Top = 645 Width = 615 End Begin VB.Label Label3 @@ -93,7 +118,7 @@ Begin VB.Form Form1 Height = 255 Left = 1680 TabIndex = 2 - Top = 120 + Top = 165 Width = 615 End Begin VB.Label Status @@ -102,8 +127,8 @@ Begin VB.Form Form1 Height = 255 Left = 0 TabIndex = 1 - Top = 960 - Width = 4695 + Top = 1035 + Width = 3180 End End Attribute VB_Name = "Form1" @@ -111,35 +136,66 @@ Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False -' For the system tray bits +' For the system tray methods Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long Private Declare Function GetPrivateProfileInt Lib "kernel32" Alias "GetPrivateProfileIntA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal nDefault As Long, ByVal lpFileName As String) As Long +' Address of the filter manager Dim filterManagerHostname As String Dim filterManagerTCPPort As Long +' Sequence number and machine name are sent in each UDP packet. Dim seqNo As Long Dim machineName As String +' DEPRICATED. The number of seconds that the program has been running. +Dim secondsRunning As Long + +' Address of the filter to use. Dim filterHostname As String Dim filterTCPPort As Integer Dim filterUDPPort As Integer + +' Server configuration details. Dim fileList As String Dim lastModified As String +' Time intervals between UDP packets and heartbeats. Dim UDPUpdateTime As Integer Dim TCPUpdateTime As Integer +' The protocol version used by the winhost. Dim protocolVersion As String + +' Action flags. Dim connected As Boolean +Dim heartBeating As Boolean +Dim windowBig As Boolean +' Define classes to be used to obtain uptime and number of users. Dim CUpTime As New CUpTime Dim wksta As New CNetWksta +' Keep track of the line number in TCP communications. Dim responseNumber As Integer + +' Toggle visibility of the debug output. +Private Sub Command1_Click() + If windowBig Then + Form1.Height = 1755 + windowBig = False + Else + Form1.Height = 4380 + windowBig = True + End If +End Sub + + +' Main method (or its Visual Basic equivalent!). Private Sub Form_Load() + ' Do not let any user run the program twice on one machine. If App.PrevInstance Then x = MsgBox("There is already an i-scream Winhost running on this machine.", 48, "i-scream host already running") End @@ -152,80 +208,105 @@ Private Sub Form_Load() CUpTime.Init + ' Some class functions only work on NT-based systems, and Win9x boxes + ' are rarely used as servers, anyway. If CUpTime.isWin9x Then x = MsgBox("Sorry, the i-scream host can only be used to monitor servers (i.e. not Win9x)", 48, "Not a server") End End If - ''''TEMP - 'filterManagerHostname = "killigrew.ukc.ac.uk" - 'filterManagerTCPPort = 4567 - ''''' END TEMP + ' Start the program with the small window size. + windowBig = False - 'GoTo skip + ' Catch errors while reading the configuration from the ini file. On Error GoTo iniError + Dim buf As String * 256 Dim length As Long - length = GetPrivateProfileString("i-scream Winhost", "FilterManager", "", buf, Len(buf), App.Path & "/winhost.ini") + length = GetPrivateProfileString("i-scream Winhost", "FilterManager", "", buf, Len(buf), App.Path & "/winhost.ini") filterManagerHostname = Left$(buf, length) length = GetPrivateProfileInt("i-scream Winhost", "FilterManagerPort", 0, App.Path & "/winhost.ini") filterManagerTCPPort = length + If filterManagerHostname = "" Then GoTo iniError End If + + ' Resume normal error handling. On Error GoTo 0 -skip: + ' We have the configuration. Now connect. Status.Caption = "Connecting to Filter Manager " & filterManagerHostname & ":" & filterManagerTCPPort Reconfigure_Click + ' Install the icon in the system tray. SystemTray.Icon = Val(Form1.Icon) SystemTray.Action = 0 Exit Sub +' Error handler iniError: x = MsgBox("The i-scream Winhost could not read the correct settings from the winhost.ini file. Please correct these and try again. " & Err.Description, 48, "Configuration not found") End End Sub + +' Unload event. Also fires when the machine is shutting down. Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) + + ' Prevent users from unwittingly shutting down thet winhost. x = MsgBox("Are you sure you want to shut down the Winhost? This will stop your computer sending information to the i-scream Central Monitoring System.", vbYesNo, "i-scream Winhost") If x = 7 Then Cancel = True Else + ' Remove the icon from the system tray. SystemTray.Action = 2 End If End Sub + +' Make the form disappear and update the icon in the system tray. Private Sub Hide_Click() Form1.Visible = False SystemTray.Icon = Val(Form1.Icon) End Sub + +' Reconfigure the host with the filter manager. Private Sub Reconfigure_Click() - ' establish a TCP connection to a filtermanager - connected = False - TCPSock.Close - TCPSock.Connect filterManagerHostname, filterManagerTCPPort + ' establish a TCP connection to a filtermanager, provided another TCP + ' communication is not already taking place. + If Not heartBeating Then + connected = False + TCPSock.Close + TCPSock.Connect filterManagerHostname, filterManagerTCPPort + Else + Status.Caption = "Cannot reconfigure while heartbeating" + End If End Sub - +' Do this when the user double-clicks on the system tray icon. Private Sub SystemTray_MouseDblClk(ByVal Button As Integer) - + ' After double-clicking on the system tray icon, we make the + ' form visible and give it active focus. Form1.Visible = True Form1.SetFocus End Sub + +' Establish a connection with the filter manager. +' Thereafter, use the filter instead. Private Sub TCPSock_Connect() + ' Start from the first line of the response. responseNumber = 0 - + ' Send something as soon as we connect to the server. If connected = False Then ' contact the FilterManager @@ -237,8 +318,11 @@ Private Sub TCPSock_Connect() End Sub + +' Deal with TCP traffic coming from the filter or filter manager. Private Sub TCPSock_DataArrival(ByVal bytesTotal As Long) + ' Move to the next line of the response. responseNumber = responseNumber + 1 ' Get the line from the server. @@ -247,7 +331,6 @@ Private Sub TCPSock_DataArrival(ByVal bytesTotal As Lo ' Remove linefeeds and returns from the line. response = Replace(response, Chr(13), "") response = Replace(response, Chr(10), "") - 'Text4.Text = Text4.Text & vbCrLf & response If connected = False Then ' Perform TCP configuration (1.1) @@ -256,45 +339,59 @@ Private Sub TCPSock_DataArrival(ByVal bytesTotal As Lo Case 1: If Not response = "OK" Then GoTo configError TCPSock.SendData "LASTMODIFIED" & vbCrLf + Text1.Text = "Requesting configuration from FilterManager:- " & vbCrLf + Text1.Text = Text1.Text & response & vbCrLf Case 2: If response = "ERROR" Then GoTo configError lastModified = response + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData "FILELIST" & vbCrLf Case 3: If response = "ERROR" Then GoTo configError fileList = response - TCPSock.SendData "UDPUpdateTime" & vbCrLf + Text1.Text = Text1.Text & response & vbCrLf + TCPSock.SendData "FQDN" & vbCrLf Case 4: If response = "ERROR" Then GoTo configError + Text1.Text = Text1.Text & response & vbCrLf + machineName = response + TCPSock.SendData "UDPUpdateTime" & vbCrLf + Case 5: + If response = "ERROR" Then GoTo configError UDPUpdateTime = response + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData "TCPUpdateTime" & vbCrLf - Case 5: + Case 6: If response = "ERROR" Then GoTo configError TCPUpdateTime = response + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData "ENDCONFIG" & vbCrLf - Case 6: + Case 7: If Not response = "OK" Then GoTo configError + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData "FILTER" & vbCrLf - Case 7: - 'we got a filter list here. + Case 8: + Text1.Text = Text1.Text & response & vbCrLf + ' We got a filter list here. readTo = 0 - ' get hostname + ' Get hostname readTo = InStr(1, response, ";", vbBinaryCompare) filterHostname = Mid(response, 1, readTo - 1) response = Mid(response, readTo + 1, Len(response)) - ' get UDP Port number + ' Get UDP Port number readTo = InStr(1, response, ";") filterUDPPort = Mid(response, 1, readTo - 1) response = Mid(response, readTo + 1, Len(response)) - ' get TCP Port number + ' Get TCP Port number filterTCPPort = response TCPSock.SendData "END" & vbCrLf - Case 8: + Case 9: If Not response = "OK" Then GoTo configError connected = True responseNumber = 0 + ' We've finished with the socket now. TCPSock.Close - 'Text4.Text = Text4.Text & vbCrLf & " " + Text1.Text = Text1.Text & response & vbCrLf Status.Caption = "Configuration successful" Label3.Caption = UDPUpdateTime Label4.Caption = TCPUpdateTime @@ -302,24 +399,37 @@ Private Sub TCPSock_DataArrival(ByVal bytesTotal As Lo End Select Else ' Perform a heartbeat (1.1) + heartBeating = True On Error GoTo heartbeatError Select Case responseNumber Case 1: If Not response = "OK" Then GoTo heartbeatError + Text1.Text = "Performing heartbeat: -" & vbCrLf + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData "CONFIG" & vbCrLf Case 2: If Not response = "OK" Then GoTo heartbeatError + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData fileList & vbCrLf Case 3: If Not response = "OK" Then GoTo heartbeatError + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData lastModified & vbCrLf Case 4: - If Not response = "OK" Then GoTo heartbeatError + ' Reconfigure if the server configuration for the + ' host has been altered. + If Not response = "OK" Then + heartBeating = False + Reconfigure_Click + End If + Text1.Text = Text1.Text & response & vbCrLf TCPSock.SendData "ENDHEARTBEAT" & vbCrLf Case 5: If Not response = "OK" Then GoTo heartbeatError + Text1.Text = Text1.Text & response & vbCrLf TCPSock.Close Status.Caption = "Heartbeat sent successfully." + heartBeating = False End Select End If @@ -328,13 +438,17 @@ Private Sub TCPSock_DataArrival(ByVal bytesTotal As Lo Exit Sub configError: - Status.Caption = "FAILED to get configuration" + heartBeating = False + Status.Caption = "FAILED to get configuration from the server" Exit Sub heartbeatError: + heartBeating = False Status.Caption = "Heatbeat FAILED" Exit Sub End Sub + +' Deal with the construction and sending of UDP packets. Private Sub Timer1_Timer() Label3.Caption = Label3.Caption - 1 @@ -346,24 +460,34 @@ Private Sub Timer1_Timer() ' prepare the contents of the XML packet. seqNo = seqNo + 1 - machineName = TCPSock.LocalHostName + + ' Windows machines can provide their NetBIOS name to assist + ' in identifying the machine. + netbiosName = TCPSock.LocalHostName + + ' The I.P. address of the host machine. LocalIP = TCPSock.LocalIP + + ' The date according to the host machine (formatted as the + ' number of seconds since the epoch). packetDate = Date2Num() - + ' Attempt to return Windows version information with the API. Dim verinfo As OSVERSIONINFO verinfo.dwOSVersionInfoSize = Len(verinfo) ret% = GetVersionEx(verinfo) If ret% = 0 Then - MsgBox "Error getting Windows version Information" + Text1.Text = Text1.Text & vbCrLf & "Error getting Windows version Information" End End If + ' Now get all of the version information. osName = GetVersion() osVersionMajor = verinfo.dwMajorVersion osVersionMinor = verinfo.dwMinorVersion osBuild = verinfo.dwBuildNumber + ' Find out what type of processor the host is using. Dim sysinfo As SYSTEM_INFO GetSystemInfo sysinfo Select Case sysinfo.dwProcessorType @@ -381,40 +505,54 @@ Private Sub Timer1_Timer() processorType = "(unknown)" End Select + ' Find the amount of swap memory and physical memory + ' (both free and total) Dim memsts As MEMORYSTATUS Dim memory& GlobalMemoryStatus memsts memory& = memsts.dwTotalPhys - memTotal = memory& \ 1024 + memTotal = memory& \ 1048576 memory& = memsts.dwAvailPhys - memFree = memory& \ 1024 + memFree = memory& \ 1048576 memory& = memsts.dwTotalVirtual - swapTotal = memory& \ 1024 + swapTotal = memory& \ 1048576 memory& = memsts.dwAvailVirtual - swapFree = memory& \ 1024 + swapFree = memory& \ 1048576 - uptime = CUpTime.MilliSecs \ 1000 - + ' Cause the CUpTime class to capture its data. CUpTime.Capture + + ' Get the processor occupancy percentages. cpu_time = CUpTime.CPUTime percent_idle = CUpTime.PercentIdle + ' Get the uptime for the host. DO NOT use integer division here, + ' as this will cause the result to overflow if the machine has + ' been up for more than ~47 days. + uptime = CUpTime.MilliSecs / 1000# + + ' Use the CNetWksta class to find out how many users are logged + ' on to the system. + userCount = wksta.LoggedOnUsers + ' build the contents of the XML packet xml = "" & _ "" & _ + "" & netbiosName & "" & _ "" & osName & "" & _ - "" & osVersionMajor & "" & _ + "" & osVersionMajor & "." & osVersionMinor & "" & _ "" & osBuild & "" & _ - "" & osName & "" & _ - "" & osVersionMinor & "" & _ - "" & processorType & "" & _ + "" & processorType & "" & _ "" & uptime & "" & _ "" & _ + "" & userCount & "" & _ "" & percent_idle & "" & cpu_time & "" & _ "" & memTotal & "" & memFree & "" & _ "" & swapTotal & "" & swapFree & "" & _ "" - 'Text4.Text = Text4.Text + xml + + ' Show the interested user what we are sending. + Text1.Text = "Last packet contained: -" & vbCrLf & xml ' Use the first winsock control to send a UDP packet. UDPSock.RemoteHost = filterHostname @@ -433,6 +571,9 @@ Private Sub Timer1_Timer() End Sub + +' Format the current date and time as a long integer representing +' the number of seconds since the epoch. Function Date2Num() As Long Dim x As Long x = DateDiff("s", "1-1-1970", Now)