* Add log tab * Merge control mesg & duty log * Fix ping (calc loss) * Add current connection in ping tab. Able to copy by double clicking item * Log font has moved to config * Add debug enable on config + save * Display ping failed reason (debug enable) * Handled copy exception * New content list in duty tab * Show loss rate option in ping tab * Rename Chinese packet info file (No data) * Bigger UI font
425 lines
8.9 KiB
C#
425 lines
8.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.IO;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net;
|
|
|
|
namespace DutyContent.Tab
|
|
{
|
|
public partial class PingForm : Form, Interface.ISuppLocale, Interface.ISuppActPlugin
|
|
{
|
|
private static PingForm _self;
|
|
public static PingForm Self => _self;
|
|
|
|
//
|
|
private System.Timers.Timer _timer;
|
|
private long _last_ping;
|
|
|
|
private Color _color = Color.Transparent;
|
|
|
|
private Libre.PingGrapher _grpr;
|
|
private List<int> _kepts = new List<int> { 0, 0 };
|
|
|
|
//
|
|
private const int PingInterval = 5000;
|
|
private const int PingAmount = 5;
|
|
private const int PingTimeout = PingInterval / (PingAmount + 1);
|
|
|
|
//
|
|
public PingForm()
|
|
{
|
|
_self = this;
|
|
|
|
InitializeComponent();
|
|
|
|
_grpr = new Libre.PingGrapher(pbxPingGraph);
|
|
}
|
|
|
|
public void PluginInitialize()
|
|
{
|
|
chkUsePing.Checked = DcConfig.Duty.UsePing;
|
|
btnPingColor1.BackColor = DcConfig.Duty.PingColors[0];
|
|
btnPingColor2.BackColor = DcConfig.Duty.PingColors[1];
|
|
btnPingColor3.BackColor = DcConfig.Duty.PingColors[2];
|
|
btnPingColor4.BackColor = DcConfig.Duty.PingColors[3];
|
|
chkPingShowLoss.Checked = DcConfig.Duty.PingShowLoss;
|
|
chkPingGraph.Checked = DcConfig.Duty.PingGraph;
|
|
cboPingGraphType.SelectedIndex = DcConfig.Duty.PingGraphType;
|
|
|
|
//
|
|
try
|
|
{
|
|
var svl = File.ReadAllLines(Path.Combine(DcConfig.DataPath, "ServerList.txt"));
|
|
int ssv = -1;
|
|
|
|
for (var i = 0; i < svl.Length; i++)
|
|
{
|
|
cboPingDefAddr.Items.Add(svl[i]);
|
|
|
|
if (svl[i].StartsWith(DcConfig.Duty.PingDefAddr))
|
|
ssv = i;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(DcConfig.Duty.PingDefAddr))
|
|
ssv = -1;
|
|
|
|
cboPingDefAddr.SelectedIndex = ssv > 0 ? ssv : 0;
|
|
}
|
|
catch
|
|
{
|
|
cboPingDefAddr.Items.Clear();
|
|
cboPingDefAddr.Items.Add(Locale.Text(27));
|
|
cboPingDefAddr.SelectedIndex = 0;
|
|
}
|
|
|
|
//
|
|
_timer = new System.Timers.Timer() { Interval = PingInterval };
|
|
_timer.Elapsed += (sender, e) => PingOnce();
|
|
|
|
if (DcConfig.Duty.UsePing)
|
|
{
|
|
PingOnce(false);
|
|
_timer.Start();
|
|
}
|
|
|
|
}
|
|
|
|
public void PluginDeinitialize()
|
|
{
|
|
_timer?.Stop();
|
|
}
|
|
|
|
public void RefreshLocale()
|
|
{
|
|
|
|
}
|
|
|
|
public void UpdateUiLocale()
|
|
{
|
|
chkUsePing.Text = Locale.Text(401);
|
|
lblPingColors.Text = Locale.Text(402);
|
|
lblPingStat1.Text = Locale.Text(403);
|
|
lblPingStat2.Text = Locale.Text(404);
|
|
lblPingStat3.Text = Locale.Text(405);
|
|
lblPingStat4.Text = Locale.Text(406);
|
|
chkPingGraph.Text = Locale.Text(407);
|
|
lblPingDefAddr.Text = Locale.Text(408);
|
|
lblPingAddress.Text = Locale.Text(409);
|
|
lblPingGraphType.Text = Locale.Text(410);
|
|
chkPingShowLoss.Text = Locale.Text(413);
|
|
}
|
|
|
|
private void SaveConfig(int interval = 5000)
|
|
{
|
|
DcControl.Self.RefreshSaveConfig(interval);
|
|
}
|
|
|
|
private void ChkUsePing_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (!DcConfig.PluginEnable)
|
|
return;
|
|
|
|
DcConfig.Duty.UsePing = chkUsePing.Checked;
|
|
|
|
SaveConfig();
|
|
|
|
if (chkUsePing.Checked)
|
|
{
|
|
PingOnce();
|
|
_timer.Start();
|
|
}
|
|
else
|
|
{
|
|
_timer.Stop();
|
|
Overlay.DutyOvForm.Self?.ResetStat();
|
|
}
|
|
}
|
|
|
|
private void PingColorWorker(int index, Button button)
|
|
{
|
|
Color color = (Color)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() =>
|
|
{
|
|
var dg = new ColorDialog()
|
|
{
|
|
AnyColor = true,
|
|
Color = DcConfig.Duty.PingColors[index],
|
|
};
|
|
|
|
return dg.ShowDialog() == DialogResult.OK ? dg.Color : DcConfig.Duty.PingColors[index];
|
|
}));
|
|
|
|
if (DcConfig.Duty.PingColors[index] != color)
|
|
{
|
|
button.BackColor = color;
|
|
DcConfig.Duty.PingColors[index] = color;
|
|
SaveConfig();
|
|
}
|
|
}
|
|
|
|
private void BtnPingColor1_Click(object sender, EventArgs e)
|
|
{
|
|
PingColorWorker(0, btnPingColor1);
|
|
}
|
|
|
|
private void BtnPingColor2_Click(object sender, EventArgs e)
|
|
{
|
|
PingColorWorker(1, btnPingColor2);
|
|
}
|
|
|
|
private void BtnPingColor3_Click(object sender, EventArgs e)
|
|
{
|
|
PingColorWorker(2, btnPingColor3);
|
|
}
|
|
|
|
private void BtnPingColor4_Click(object sender, EventArgs e)
|
|
{
|
|
PingColorWorker(3, btnPingColor4);
|
|
}
|
|
|
|
private void ChkPingShowLoss_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (!DcConfig.PluginEnable)
|
|
return;
|
|
|
|
DcConfig.Duty.PingShowLoss = chkPingShowLoss.Checked;
|
|
|
|
SaveConfig();
|
|
}
|
|
|
|
private void ChkPingGraph_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (!DcConfig.PluginEnable)
|
|
return;
|
|
|
|
DcConfig.Duty.PingGraph = chkPingGraph.Checked;
|
|
|
|
SaveConfig();
|
|
}
|
|
|
|
private void CboPingDefAddr_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (!DcConfig.PluginEnable)
|
|
return;
|
|
|
|
var val = cboPingDefAddr.SelectedItem as string;
|
|
|
|
if (!string.IsNullOrEmpty(val))
|
|
{
|
|
var ss = val.Split(' ');
|
|
if (ss.Length > 0)
|
|
{
|
|
DcConfig.Duty.PingDefAddr = ss[0].Trim();
|
|
|
|
SaveConfig();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
DcConfig.Duty.PingDefAddr = string.Empty;
|
|
|
|
SaveConfig();
|
|
}
|
|
|
|
private void CboPingGraphType_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (!DcConfig.PluginEnable)
|
|
return;
|
|
|
|
if (cboPingGraphType.SelectedIndex>=0)
|
|
{
|
|
DcConfig.Duty.PingGraphType = cboPingGraphType.SelectedIndex;
|
|
SaveConfig();
|
|
}
|
|
}
|
|
|
|
private void LstPingAddress_MouseDoubleClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (lstPingAddress.SelectedIndices.Count != 1)
|
|
return;
|
|
|
|
try
|
|
{
|
|
var s = lstPingAddress.SelectedItem as string;
|
|
Clipboard.SetText(s);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Ex(ex, 35);
|
|
}
|
|
}
|
|
|
|
//
|
|
private void PingOnce(bool check_plugin_enable = true)
|
|
{
|
|
if (!DcConfig.Duty.UsePing)
|
|
return;
|
|
|
|
if (check_plugin_enable && !DcConfig.PluginEnable)
|
|
return;
|
|
|
|
var conns = DcConfig.Connections.CopyConnection();
|
|
long rtt = 0;
|
|
double loss = 0;
|
|
|
|
List<string> addrs = new List<string>();
|
|
|
|
if (conns.Length > 0)
|
|
{
|
|
foreach (var row in conns)
|
|
{
|
|
addrs.Add(row.RemoteAddress.ToString());
|
|
|
|
var (r, l) = CalcPing(row.RemoteAddress, PingTimeout, PingAmount);
|
|
|
|
if (rtt < r)
|
|
rtt = r;
|
|
|
|
if (loss < l)
|
|
loss = l;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrEmpty(DcConfig.Duty.PingDefAddr))
|
|
{
|
|
Overlay.DutyOvForm.Self?.ResetStat();
|
|
return;
|
|
}
|
|
|
|
addrs.Add(DcConfig.Duty.PingDefAddr);
|
|
|
|
var defip = ThirdParty.Converter.ToIPAddressFromIPV4(DcConfig.Duty.PingDefAddr);
|
|
|
|
if (defip == IPAddress.None || defip == IPAddress.IPv6None)
|
|
{
|
|
Overlay.DutyOvForm.Self?.ResetStat();
|
|
return;
|
|
}
|
|
|
|
var (r, l) = CalcPing(defip, PingTimeout, PingAmount);
|
|
|
|
if (rtt < r)
|
|
rtt = r;
|
|
|
|
if (loss < l)
|
|
loss = l;
|
|
}
|
|
|
|
//MesgLog.L("Ping: {0}, {1}%", rtt, loss);
|
|
|
|
Color color;
|
|
if (rtt > 150)
|
|
color = DcConfig.Duty.PingColors[3];
|
|
else if (rtt > 100)
|
|
color = DcConfig.Duty.PingColors[2];
|
|
else if (rtt > 50)
|
|
color = DcConfig.Duty.PingColors[1];
|
|
else
|
|
color = DcConfig.Duty.PingColors[0];
|
|
|
|
if (!DcConfig.Duty.PingShowLoss)
|
|
loss = 0.0;
|
|
|
|
if (_last_ping != rtt || loss > 0.0 || _color != color)
|
|
{
|
|
_last_ping = rtt;
|
|
_color = color;
|
|
|
|
Overlay.DutyOvForm.Self?.SetStatPing(color, rtt, loss);
|
|
}
|
|
|
|
//
|
|
if (DcConfig.Duty.PingGraph)
|
|
{
|
|
_kepts.Add((int)rtt);
|
|
if (_kepts.Count > 120)
|
|
_kepts.RemoveAt(0);
|
|
|
|
_grpr.Enter();
|
|
_grpr.DrawValues(_kepts, (Libre.PingGrapher.DrawType)DcConfig.Duty.PingGraphType);
|
|
WorkerAct.Invoker(() => _grpr.Leave());
|
|
}
|
|
|
|
//
|
|
if (addrs.Count == 0)
|
|
{
|
|
if (lstPingAddress.Items.Count != 0)
|
|
lstPingAddress.Items.Clear();
|
|
}
|
|
else
|
|
{
|
|
bool have_to_update_addrs = false;
|
|
|
|
if (lstPingAddress.Items.Count == 0)
|
|
have_to_update_addrs = true;
|
|
else
|
|
{
|
|
var i = lstPingAddress.Items[0] as string;
|
|
have_to_update_addrs = !addrs.Contains(i);
|
|
}
|
|
|
|
if (have_to_update_addrs)
|
|
{
|
|
WorkerAct.Invoker(() =>
|
|
{
|
|
lstPingAddress.BeginUpdate();
|
|
lstPingAddress.Items.Clear();
|
|
foreach (var i in addrs)
|
|
lstPingAddress.Items.Add(i);
|
|
lstPingAddress.EndUpdate();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// http://forum.codecall.net/topic/37643-c-packet-lossping-program/
|
|
|
|
private static readonly PingOptions _ping_options = new PingOptions { DontFragment = true };
|
|
private static readonly byte[] _ping_buffers = Encoding.ASCII.GetBytes("01234567890123456789012345678901");
|
|
|
|
//
|
|
private (long Rtt, double Loss) CalcPing(IPAddress host, int timeout, int amount)
|
|
{
|
|
var ps = new Ping();
|
|
|
|
int failed = 0;
|
|
long rtt = 0;
|
|
|
|
for (var i = 0; i < amount; i++)
|
|
{
|
|
try
|
|
{
|
|
PingReply pr = ps.Send(host, timeout, _ping_buffers, _ping_options);
|
|
|
|
if (pr.Status != IPStatus.Success)
|
|
{
|
|
failed++;
|
|
|
|
if (DcConfig.DebugEnable)
|
|
{
|
|
Logger.WriteCategory(Color.Red, "Ping", "failed. status: {0} / duration: {1} / at: {2}/{3}", pr.Status, timeout, i + 1, amount);
|
|
}
|
|
}
|
|
|
|
if (rtt < pr.RoundtripTime)
|
|
rtt = pr.RoundtripTime;
|
|
}
|
|
catch
|
|
{
|
|
failed++;
|
|
}
|
|
|
|
System.Threading.Thread.Sleep(1);
|
|
}
|
|
|
|
double loss = failed == 0 ? 0 : (double)failed / amount * 100.0;
|
|
|
|
return (rtt, loss);
|
|
}
|
|
}
|
|
}
|