You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

129 lines
5.0 KiB

using ISPChk.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ISPChk
{
public class NetworkTest : INetworkTest
{
private ISPChkContext _context;
public NetworkTest() {
_context = CreateDbContext();
}
public async void LoadHostsFromDatabase()
{
List<Host> hosts = await _context.Hosts.Include(host => host.PingItems).ToListAsync();
foreach (Host host in hosts)
{
AddHost(host);
}
}
private ISPChkContext CreateDbContext()
{
var optionsBuilder = new DbContextOptionsBuilder<ISPChkContext>();
optionsBuilder.UseSqlite("Data Source=ispchk.db");
var ctx = new ISPChkContext(optionsBuilder.Options);
System.Diagnostics.Debug.WriteLine("NetworkTest instantiated.");
ctx.Database.EnsureCreated();
return ctx;
}
private void StartPing(Host host)
{
var t = Task.Run(async () => {
// Do not use the outer context, not threadsafe?
var ctx = CreateDbContext();
var h = await ctx.Hosts.FindAsync(host.HostId);
ctx.Entry(h).Collection(hst => hst.PingItems).Load();
Ping pingSender = new Ping();
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
// Wait 10 seconds for a reply.
int timeout = 3000;
// Set options for transmission:
// The data can go through 64 gateways or routers
// before it is destroyed, and the data packet
// cannot be fragmented.
PingOptions options = new PingOptions(64, true);
System.Diagnostics.Debug.WriteLine("Pinging " + host.Name);
while (true)
{
int numPings = 5;
long min = timeout + 1;
long max = 0;
long avg = 0;
int successes = 0;
int failures = 0;
for (var i = 0; i < numPings; ++i)
{
// Send the request.
PingReply reply = pingSender.Send(host.HostName, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
successes++;
//System.Diagnostics.Debug.WriteLine("Reply from " + reply.Address.ToString() +
// ": bytes=" + reply.Buffer.Length +
// " time=" + reply.RoundtripTime + "ms");
avg += reply.RoundtripTime;
if (reply.RoundtripTime < min)
{
min = reply.RoundtripTime;
}
if (reply.RoundtripTime > max)
{
max = reply.RoundtripTime;
}
//System.Diagnostics.Debug.WriteLine("Time to live: {0}", reply.Options.Ttl);
//System.Diagnostics.Debug.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
}
else
{
System.Diagnostics.Debug.WriteLine(reply.Status);
failures++;
}
Thread.Sleep(500);
}
if(successes > 0)
avg = avg / successes;
// FIXME: This is dirty but I don't want the graph to explode
if (min > timeout)
min = 0;
System.Diagnostics.Debug.WriteLine(h.HostName+": "+"min:" + min + " max:" + max + " avg:" + avg);
PingItem pi = new PingItem { Date = DateTimeOffset.UtcNow, Min = min, Max = max, Avg = avg, Failures = failures };
h.PingItems.Add(pi);
ctx.SaveChanges();
// Throttle if everything is ok
if(successes == numPings)
Thread.Sleep(5000);
}
});
}
public void AddHost(Host host)
{
System.Diagnostics.Debug.WriteLine("Host added!");
if (host.PingItems == null)
host = _context.Hosts.Include(host => host.PingItems).Where(h => h.HostId == host.HostId).Single();
if(host.Ping)
StartPing(host);
}
}
}