-
Notifications
You must be signed in to change notification settings - Fork 8
/
WOL Agent.cs
154 lines (127 loc) · 5.33 KB
/
WOL Agent.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.ServiceProcess;
using System.Xml;
namespace Agent
{
partial class WOL_Agent : ServiceBase
{
private BackgroundWorker backgroundworker;
private int sendPort, listenPort;
private string sendAddress, listenAddress;
const string app = "WOL_Agent";
public WOL_Agent()
{
InitializeComponent();
string filename = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) +
"\\Aquila Technology\\Agent\\config.xml";
XmlTextReader reader = new XmlTextReader(filename);
reader.WhitespaceHandling = WhitespaceHandling.None;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
reader.Close();
XmlElement agent = xmlDoc["agent"];
XmlNode send = agent.SelectSingleNode("send");
sendPort = int.Parse(send["port"].InnerText);
sendAddress = send["address"].InnerText;
XmlNode listen = agent.SelectSingleNode("listen");
listenPort = int.Parse(listen["port"].InnerText);
listenAddress = listen["address"].InnerText;
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = app;
eventLog.WriteEntry("WOL agent listening on " + listenAddress + ":" + listenPort,
EventLogEntryType.Information, 101);
}
backgroundworker = new BackgroundWorker
{
WorkerSupportsCancellation = true
};
backgroundworker.DoWork += new DoWorkEventHandler(DoWork);
}
protected override void OnStart(string[] args)
{
backgroundworker.RunWorkerAsync();
}
protected override void OnStop()
{
backgroundworker.CancelAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
UdpClient udpSender = new UdpClient();
IPEndPoint listenEP = new IPEndPoint(IPAddress.Parse(listenAddress), listenPort);
UdpClient udpReceiver = new UdpClient(listenEP);
Dictionary<string, DateTime> list = new Dictionary<string, DateTime>();
DateTime lastTime;
string mac;
udpSender.Connect(sendAddress, sendPort);
udpSender.EnableBroadcast = true;
while (worker.CancellationPending == false)
{
try
{
Byte[] receiveBytes = udpReceiver.Receive(ref listenEP);
// verify that WOL packet
if (validPacket(receiveBytes))
{
// we have a valid packet
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = app;
eventLog.WriteEntry("WOL packet received from " + listenEP.Address.ToString(),
EventLogEntryType.Information, 101);
}
mac = BitConverter.ToString(receiveBytes, 6, 6);
if (list.TryGetValue(mac, out lastTime))
{
if ((DateTime.UtcNow - lastTime).TotalSeconds > 2)
{
list.Remove(mac);
list.Add(key: mac, value: DateTime.UtcNow);
udpSender.Send(receiveBytes, receiveBytes.Length);
}
}
else
{
list.Add(key: mac, value: DateTime.UtcNow);
udpSender.Send(receiveBytes, receiveBytes.Length);
}
}
}
catch (Exception ex)
{
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = app;
eventLog.WriteEntry("WOL Agent error: " + ex.ToString(), EventLogEntryType.Error, 201, 1);
}
}
}
e.Cancel = true;
return;
}
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
IStructuralEquatable eqa1 = a1;
return eqa1.Equals(a2, StructuralComparisons.StructuralEqualityComparer);
}
private bool validPacket(byte[] receiveBytes)
{
if (receiveBytes.Length < 102)
return false;
for (int i = 0; i < 5; i++)
if (receiveBytes[i] != 0xff) return false;
for (int i = 1; i < 15; i++)
for (int j = 0; j < 5; j++)
if (receiveBytes[6 + j] != receiveBytes[6 + j + (i * 6)]) return false;
return true;
}
}
}