Skip to content

Commit

Permalink
Monitor back-end
Browse files Browse the repository at this point in the history
  • Loading branch information
veniware committed Feb 22, 2024
1 parent 72278c7 commit b6ef53f
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 31 deletions.
4 changes: 2 additions & 2 deletions Protest/Front/about.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ class About extends Tabs {
link.style.borderRadius = "4px";
link.style.margin = "4px";
link.style.padding = "8px";
link.style.paddingLeft = "32px";
link.style.background = "url(mono/download.svg) 2px center / 24px 24px no-repeat";
link.style.paddingLeft = "36px";
link.style.background = "url(mono/download.svg) 4px center / 24px 24px no-repeat";
link.target = "_blank";
link.href = "https://github.com/openprotest/protest/releases/latest";
link.textContent = `Pro-test ${json.version}`;
Expand Down
1 change: 1 addition & 0 deletions Protest/Front/deviceview.js
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,7 @@ class DeviceView extends View {
for (let i=0; i<data.length; i++) {
if (data[i].t === 0) continue;
let x = 750 - Math.round((today.getTime() - data[i].d) / DeviceView.DAY_TICKS * 50);
let y = (height + 4) - Math.round(height * data[i].v / data[i].t);

d += `L ${x} ${y} `;

Expand Down
2 changes: 1 addition & 1 deletion Protest/Front/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8">
<title>Pro-test</title>
<link rel="icon" id="favicon">
<meta name="theme-color" content="#E87600"/>
<meta name="theme-color" content="#202020"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="description" content="A management base for System Admins"/>

Expand Down
2 changes: 2 additions & 0 deletions Protest/Front/mono/listener.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions Protest/Front/personalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,9 @@ class Personalize extends Tabs {
this.tabsPanel.appendChild(document.createElement("hr"));
this.tabsPanel.appendChild(document.createElement("br"));

this.tabsPanel.appendChild(document.createElement("hr"));
this.tabsPanel.appendChild(document.createElement("br"));

const settingsButton = document.createElement("input");
settingsButton.type = "button";
settingsButton.value = "Prompt agent settings";
Expand All @@ -788,8 +791,8 @@ class Personalize extends Tabs {
link.style.borderRadius = "4px";
link.style.margin = "4px";
link.style.padding = "8px";
link.style.paddingLeft = "32px";
link.style.background = "url(mono/download.svg) 2px center / 24px 24px no-repeat";
link.style.paddingLeft = "36px";
link.style.background = "url(mono/download.svg) 4px center / 24px 24px no-repeat";
link.target = "_blank";
link.href = "https://github.com/openprotest/protest/releases/latest";
link.textContent = `Download agent`;
Expand Down
146 changes: 120 additions & 26 deletions Protest/Tools/Monitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ public struct Query {
public string value;
}

public struct Answer {
public int index;
public Dictionary<string, List<string>> data;
}

private static JsonSerializerOptions actionSerializerOptions;
private static JsonSerializerOptions answerSerializerOptions;

static Monitor() {
actionSerializerOptions = new JsonSerializerOptions();
actionSerializerOptions.Converters.Add(new ActionJsonConverter());

answerSerializerOptions = new JsonSerializerOptions();
answerSerializerOptions.Converters.Add(new AnswerJsonConverter());
}

private static async Task WsWriteText(WebSocket ws, [StringSyntax(StringSyntaxAttribute.Json)] string text) {
Expand Down Expand Up @@ -73,7 +82,7 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {
string target = null!;
bool paused = false;
bool ping = true;
int interval = 500;
int interval = 1000;
ConcurrentDictionary<int, Query> wmi = new ConcurrentDictionary<int, Query>();
ConcurrentDictionary<int, Query> snmp = new ConcurrentDictionary<int, Query>();
byte[] buff = new byte[2048];
Expand Down Expand Up @@ -108,7 +117,7 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {
Logger.Error(ex);
}

Thread icmpThread = new Thread(async () => { //icmp thread
Func<Task> IcmpDelegate = async () => {
while (ws.State == WebSocketState.Open) {
if (paused) {
await Task.Delay(interval);
Expand All @@ -128,9 +137,9 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {
await Task.Delay(calculatedInterval);
}
}
});
};

Thread wmiThread = new Thread(async() => { //wmi thread
Func<Task> WmiDelegate = async () => {
ManagementScope scope = null;
if (!OperatingSystem.IsWindows()) {
await WsWriteText(ws, "{\"loglevel\":\"warning\",\"text\":\"WMI is not supported\"}"u8.ToArray());
Expand Down Expand Up @@ -176,9 +185,9 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {
await Task.Delay(calculatedInterval);
}
}
});
};

Thread smtpThread = new Thread(async () => { //snmp thread
Func<Task> SnmpDelegate = async () => {
while (ws.State == WebSocketState.Open) {
if (paused) {
await Task.Delay(interval);
Expand All @@ -197,12 +206,15 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {
await Task.Delay(calculatedInterval);
}
}
});
};

Thread icmpThread = null;
Thread wmiThread = null;
Thread smtpThread = null;

icmpThread = new Thread(() => IcmpDelegate());
icmpThread.Start();


try {
while (ws.State == WebSocketState.Open) {
WebSocketReceiveResult receiveResult = await ws.ReceiveAsync(new ArraySegment<byte>(buff), CancellationToken.None);
Expand All @@ -223,7 +235,10 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {
switch (query.action) {
case Action.start:
paused = false;
//if (!icmpThread.IsAlive) { icmpThread.Start(); }
if (icmpThread is null) {
icmpThread = new Thread(() => IcmpDelegate());
icmpThread.Start();
}
break;

case Action.pause:
Expand All @@ -236,12 +251,18 @@ public static async void WebSocketHandler(HttpListenerContext ctx) {

case Action.addwmi:
wmi.TryAdd(query.index, query);
if (!wmiThread.IsAlive) { wmiThread.Start(); }
if (wmiThread is null) {
wmiThread = new Thread(() => WmiDelegate());
wmiThread.Start();
}
break;

case Action.addsnmp:
snmp.TryAdd(query.index, query);
if (!smtpThread.IsAlive) { smtpThread.Start(); }
if (smtpThread is null) {
smtpThread = new Thread(() => SnmpDelegate());
smtpThread.Start();
}
break;

case Action.remove:
Expand Down Expand Up @@ -303,42 +324,43 @@ private static long HandlePing(string host, int timeout) {
[SupportedOSPlatform("windows")]
private static async Task HandleWmi(WebSocket ws, ManagementScope scope, ConcurrentDictionary<int, Query> queries) {
foreach (Query query in queries.Values) {
Console.WriteLine(query.value);

try {
await HandleWmiQuery(ws, scope, query.value);
await HandleWmiQuery(ws, scope, query);
}
catch { }
}
}

[SupportedOSPlatform("windows")]
async private static Task HandleWmiQuery(WebSocket ws, ManagementScope scope, string query) {
using ManagementObjectCollection moc = new ManagementObjectSearcher(scope, new SelectQuery(query)).Get();
Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
async private static Task HandleWmiQuery(WebSocket ws, ManagementScope scope, Query query) {
using ManagementObjectCollection moc = new ManagementObjectSearcher(scope, new SelectQuery(query.value)).Get();
Dictionary<string, List<string>> data = new Dictionary<string, List<string>>();

foreach (ManagementObject o in moc.Cast<ManagementObject>()) {
foreach (PropertyData p in o.Properties) {
string name = p.Name.ToString();
string value = Protocols.Wmi.FormatProperty(p);

if (!dic.ContainsKey(name)) {
dic.Add(name, new List<string>());
if (!data.ContainsKey(name)) {
data.Add(name, new List<string>());
}

Console.WriteLine(name + ": " + value);

dic[name].Add(value);
data[name].Add(value);
}
}

string x = JsonSerializer.Serialize<Dictionary<string, List<string>>>(dic);
byte[] bytes = JsonSerializer.SerializeToUtf8Bytes<Dictionary<string, List<string>>>(dic);
Answer answer = new Answer() {
data = data,
index = query.index
};

string x = JsonSerializer.Serialize<Answer>(answer, answerSerializerOptions);
byte[] bytes = JsonSerializer.SerializeToUtf8Bytes<Answer>(answer, answerSerializerOptions);
Console.WriteLine(x);

await WsWriteText(ws, bytes);

dic.Clear();
data.Clear();
}

private static void HandleSnmp(WebSocket ws, ConcurrentDictionary<int, Query> queries) {
Expand All @@ -355,6 +377,78 @@ private static void HandleSnmpQuery(string query) {
}
}

file sealed class AnswerJsonConverter : JsonConverter<Monitor.Answer> {
public override Monitor.Answer Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
Monitor.Answer answer = new Monitor.Answer();

if (reader.TokenType != JsonTokenType.StartObject) {
throw new JsonException("Expected start of object");
}

reader.Read();

while (reader.TokenType == JsonTokenType.PropertyName) {
string propertyName = reader.GetString();

reader.Read();

switch (propertyName) {
case "index":
answer.index = reader.GetInt32();
break;

case "data":
reader.Read();
while (reader.TokenType != JsonTokenType.EndObject) {
string key = reader.GetString();
reader.Read();
List<string> values = new List<string>();
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) {
values.Add(reader.GetString());
}
answer.data[key] = values;

reader.Read();
}
break;

default:
break;
}

reader.Read();
}

if (reader.TokenType != JsonTokenType.EndObject) {
throw new JsonException();
}

return answer;
}

public override void Write(Utf8JsonWriter writer, Monitor.Answer value, JsonSerializerOptions options) {
ReadOnlySpan<char> index = "index".AsSpan();
ReadOnlySpan<char> _data = "data".AsSpan();

writer.WriteStartObject();
writer.WriteNumber(index, value.index);

writer.WritePropertyName(_data);
writer.WriteStartObject();
foreach (KeyValuePair<string, List<string>> pair in value.data) {
writer.WritePropertyName(pair.Key.ToLower());
writer.WriteStartArray();
for (int i = 0; i < pair.Value.Count; i++) {
writer.WriteStringValue(pair.Value[i]);
}
writer.WriteEndArray();
}
writer.WriteEndObject();

writer.WriteEndObject();
}
}

file sealed class ActionJsonConverter : JsonConverter<Monitor.Query> {
public override Monitor.Query Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
Monitor.Query action = new Monitor.Query();
Expand Down Expand Up @@ -390,4 +484,4 @@ public override void Write(Utf8JsonWriter writer, Monitor.Query value, JsonSeria
writer.WriteNumber(_index, value.index);
writer.WriteEndObject();
}
}
}

0 comments on commit b6ef53f

Please sign in to comment.