Skip to content

Commit 6259eeb

Browse files
committed
Refactor topology class
1 parent 1fda305 commit 6259eeb

File tree

3 files changed

+146
-64
lines changed

3 files changed

+146
-64
lines changed

Protest/Front/mono/switch.svg

Lines changed: 2 additions & 2 deletions
Loading

Protest/Front/topology.js

Lines changed: 117 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class Topology extends Window {
5050
this.sideBar.textContent = "";
5151

5252
if (this.selected) {
53-
this.selected.element.rect.classList.remove("topology-selected");
53+
this.selected.element.highlight.classList.remove("topology-selected");
5454
this.selected = null;
5555
}
5656
};
@@ -171,6 +171,18 @@ class Topology extends Window {
171171
firewallImage.setAttribute("href", "mono/firewall.svg?light");
172172
firewallMask.appendChild(firewallImage);
173173

174+
const l2switchMask = document.createElementNS("http://www.w3.org/2000/svg", "mask");
175+
l2switchMask.setAttribute("id", "l2switchMask");
176+
l2switchMask.setAttribute("mask-type", "alpha");
177+
this.svg.appendChild(l2switchMask);
178+
const l2switchImage = document.createElementNS("http://www.w3.org/2000/svg", "image");
179+
l2switchImage.setAttribute("x", 2);
180+
l2switchImage.setAttribute("y", 2);
181+
l2switchImage.setAttribute("width", 44);
182+
l2switchImage.setAttribute("height", 44);
183+
l2switchImage.setAttribute("href", "mono/switch.svg?light");
184+
l2switchMask.appendChild(l2switchImage);
185+
174186
this.linksGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
175187
this.linksGroup.setAttribute("stroke", "#c0c0c0");
176188
this.linksGroup.setAttribute("stroke-width", 3);
@@ -319,7 +331,7 @@ class Topology extends Window {
319331
if (json.initial) {
320332
let count = 0;
321333
for (let i=0; i<json.initial.length; i++) {
322-
const element = this.CreateDevice({
334+
const element = this.CreateDeviceElement({
323335
file: json.initial[i].file,
324336
type: json.initial[i].type,
325337
name: json.initial[i].hostname,
@@ -377,15 +389,15 @@ class Topology extends Window {
377389
this.stopButton.disabled = true;
378390
}
379391

380-
CreateDevice(options) {
392+
CreateDeviceElement(options) {
381393
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
382394
g.style.transform = `translate(${options.x}px,${options.y}px)`;
383395
g.setAttribute("file", options.file);
384396
this.svg.appendChild(g);
385397

386398
const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
387-
rect.setAttribute("rx", 8);
388-
rect.setAttribute("ry", 8);
399+
rect.setAttribute("rx", 16);
400+
rect.setAttribute("ry", 16);
389401
rect.setAttribute("width", 96);
390402
rect.setAttribute("height", 96);
391403
rect.setAttribute("fill", "transparent");
@@ -429,26 +441,97 @@ class Topology extends Window {
429441

430442
return {
431443
root: g,
432-
rect: rect,
444+
highlight: rect,
433445
icon: icon,
434446
label: label,
435447
x: options.x,
436448
y: options.y
437449
};
438450
}
439451

452+
CreateUnmanagedSwitchElement(options) {
453+
const uuid = UI.GenerateUuid();
454+
455+
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
456+
g.style.transform = `translate(${options.x}px,${options.y}px)`;
457+
g.setAttribute("file", uuid);
458+
this.svg.appendChild(g);
459+
460+
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
461+
circle.setAttribute("cx", 24);
462+
circle.setAttribute("cy", 24);
463+
circle.setAttribute("r", 24);
464+
circle.setAttribute("fill", "transparent");
465+
g.appendChild(circle);
466+
467+
const icon = document.createElementNS("http://www.w3.org/2000/svg", "rect");
468+
icon.setAttribute("x", 4);
469+
icon.setAttribute("y", 4);
470+
icon.setAttribute("width", 40);
471+
icon.setAttribute("height", 40);
472+
icon.setAttribute("rx", 20);
473+
icon.setAttribute("ry", 20);
474+
icon.setAttribute("fill", "#c0c0c0");
475+
icon.setAttribute("mask", "url(#l2switchMask)");
476+
icon.style.transition = "fill .8s";
477+
g.appendChild(icon);
478+
479+
g.addEventListener("mousedown", event=> {
480+
event.stopPropagation();
481+
const element = this.devices[uuid].element;
482+
483+
this.offsetX = element.x;
484+
this.offsetY = element.y;
485+
this.x0 = event.clientX;
486+
this.y0 = event.clientY;
487+
488+
this.svg.appendChild(g);
489+
this.SelectDevice(uuid);
490+
});
491+
492+
this.AdjustSvgSize();
493+
494+
const element = {
495+
root: g,
496+
highlight: circle,
497+
icon: icon,
498+
x: options.x,
499+
y: options.y
500+
};
501+
502+
this.devices[uuid] = {
503+
element: element,
504+
initial: {type: "switch", unmanaged: true}
505+
};
506+
507+
return element;
508+
}
509+
440510
ComputeLinks(device) {
441511
if (!device.lldp) return;
442512

443513
device.links = {};
444514

515+
console.log(device.initial.hostname);
516+
445517
for (const key in device.lldp.remoteChassisIdSubtype) {
446518

447-
if (device.lldp.remoteChassisIdSubtype.length === 1) {
448-
device.links[key] = {};
519+
if (device.lldp.remoteChassisIdSubtype[key].length === 1) {
520+
console.log(
521+
key,
522+
device.lldp.remoteSystemName[key][0],
523+
device.lldp.remotePortIdSubtype[key][0],
524+
device.lldp.remotePortId[key][0],
525+
device.lldp.remoteChassisIdSubtype[key][0],
526+
device.lldp.remoteChassisId[key][0]);
527+
528+
const remoteDevice = null;
529+
//TODO:
530+
device.links[key] = {device:remoteDevice, port:null};
449531
}
450-
else if (device.lldp.remoteChassisIdSubtype.length > 1) {
451-
device.links[key] = {};
532+
else if (device.lldp.remoteChassisIdSubtype[key].length > 1) {
533+
const unmanagedDevice = this.CreateUnmanagedSwitchElement({x: 100, y: 100});
534+
device.links[key] = {device:unmanagedDevice, port:null};
452535
}
453536

454537
for (let i=0; i<device.lldp.remoteChassisIdSubtype[key].length; i++) {
@@ -465,13 +548,13 @@ class Topology extends Window {
465548

466549
for (let i=0; i<device.lldp.remotePortIdSubtype[key].length; i++) {
467550
switch (device.lldp.remotePortIdSubtype[key][i]) {
468-
case 1: //interface alias
469-
case 2: //port component
470-
case 3: //mac address
471-
case 4: //network name
472-
case 5: //int name
473-
case 6: //agent circuit ID
474-
case 7: //local
551+
case 1: //interface alias
552+
case 2: //port component
553+
case 3: //mac address
554+
case 4: //network name
555+
case 5: //int name
556+
case 6: //agent circuit ID
557+
case 7: //local
475558
}
476559
}
477560

@@ -480,17 +563,19 @@ class Topology extends Window {
480563

481564
SelectDevice(file) {
482565
if (this.selected) {
483-
this.selected.element.rect.classList.remove("topology-selected");
566+
this.selected.element.highlight.classList.remove("topology-selected");
484567
}
485568

486-
this.devices[file].element.rect.classList.add("topology-selected");
569+
const device = this.devices[file];
570+
571+
device.element.highlight.classList.add("topology-selected");
487572

488-
this.selected = this.devices[file];
489-
this.dragging = this.devices[file];
573+
this.selected = device;
574+
this.dragging = device;
490575

491576
this.sideBar.textContent = "";
492577

493-
const initial = this.devices[file].initial;
578+
const initial = device.initial;
494579

495580
const grid = document.createElement("div");
496581
grid.className = "topology-sidebar-grid";
@@ -507,24 +592,24 @@ class Topology extends Window {
507592
const hostnameLabel = document.createElement("div");
508593
hostnameLabel.style.gridArea = "2 / 2";
509594
hostnameLabel.style.fontWeight = "bold";
510-
hostnameLabel.textContent = initial.hostname;
595+
hostnameLabel.textContent = device.initial.unmanaged ? "unmanaged" : initial.hostname;
511596
grid.appendChild(hostnameLabel);
512597

513598
const ipLabel = document.createElement("div");
514599
ipLabel.style.gridArea = "3 / 2";
515600
ipLabel.textContent = initial.ip;
516601
grid.appendChild(ipLabel);
517602

518-
if (file in this.devices && this.devices[file].lldp) {
519-
const id = this.devices[file].lldp.localChassisId;
603+
if (file in this.devices && device.lldp) {
604+
const id = device.lldp.localChassisId;
520605
const idLabel = document.createElement("div");
521606
if (id && initial.hostname != id && initial.ip != id) {
522607
idLabel.style.gridArea = "4 / 2";
523608
idLabel.textContent = id;
524609
grid.appendChild(idLabel);
525610
}
526611

527-
const systemName = this.devices[file].lldp.localHostname;
612+
const systemName = device.lldp.localHostname;
528613
if (systemName) {
529614
hostnameLabel.textContent = systemName;
530615
hostnameLabel.style.gridArea = "1 / 2";
@@ -536,27 +621,23 @@ class Topology extends Window {
536621
intList.className = "topology-interface-list";
537622
this.sideBar.appendChild(intList);
538623

539-
for (let i=0; i<this.devices[file].lldp.localPortName.length; i++) {
624+
625+
626+
for (let i=0; i<device.lldp.localPortName.length; i++) {
540627
const interfaceBox = document.createElement("div");
541628
const localPort = document.createElement("div");
542629
const remotePort = document.createElement("div");
543630

544-
let localPortName = this.devices[file].lldp.localPortName[i];
631+
let localPortName = device.lldp.localPortName[i];
545632
if (!localPortName || localPortName.length === 0) {
546633
localPortName = `(${i+1})`;
547634
localPort.style.color = "#404040";
548635
localPort.style.fontStyle = "italic";
549636
}
550637

551638
let remotePortName = "";
552-
if (i in this.devices[file].lldp.remoteSystemName) {
553-
const remoteName = this.devices[file].lldp.remoteSystemName[i];
554-
if (remoteName.length === 1) {
555-
remotePortName = remoteName[0];
556-
}
557-
else {
558-
remotePortName = "[...]";
559-
}
639+
if (i in device.links && device.links[i].device) {
640+
remotePortName = device.links[i].device.initial.hostname;
560641
}
561642

562643
intList.appendChild(interfaceBox);

Protest/Tools/Topology.cs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,12 @@ private static byte[] ComputeSnmpResponse(string file, IList<Variable> rawLocal,
221221
lldp = new {
222222
file = file,
223223

224-
localChassisId = GetChassisId(localChassisIdSubtype.Data.ToString(), localChassisId.Data),
225-
localHostname = localHostname.Data.ToString(),
226-
//localDescription = localDescription.Data.ToString(),
224+
localChassisIdSubtype = int.TryParse(localChassisIdSubtype.Data.ToString(), out int localChassisIdSubtypeInt) ? localChassisIdSubtypeInt : -1,
225+
localChassisId = GetChassisId(localChassisIdSubtype.Data.ToString(), localChassisId.Data),
226+
localHostname = localHostname.Data.ToString(),
227+
//localDescription = localDescription.Data.ToString(),
227228

228-
localPortIdSubtype = localPortIdSubtype.Select(o=>o.Item2),
229+
localPortIdSubtype = localPortIdSubtype.Select(o=>int.TryParse(o.Item2, out int localPortIdSubtypeInt) ? localPortIdSubtypeInt : -1),
229230
localPortId = localPortId.Select(o=>o.Item2),
230231
localPortName = localPortName.Select(o=>o.Item2),
231232

@@ -251,19 +252,19 @@ private static string GetChassisId(string subtype, ISnmpData value) {
251252
return value.ToString();
252253

253254
case "5": //network address
254-
if (bytes.Length - 2 == 4) {
255-
return $"{bytes[2]}.{bytes[3]}.{bytes[4]}.{bytes[5]}";
255+
if (bytes.Length - 3 == 4) {
256+
return $"{bytes[3]}.{bytes[4]}.{bytes[5]}.{bytes[6]}";
256257
}
257-
else if (bytes.Length - 2 == 16) {
258+
else if (bytes.Length - 3 == 16) {
258259
return $"""
259-
{bytes[2].ToString("x2")}){bytes[3].ToString("x2")}:
260-
{bytes[4].ToString("x2")}){bytes[5].ToString("x2")}:
261-
{bytes[6].ToString("x2")}){bytes[7].ToString("x2")}:
262-
{bytes[8].ToString("x2")}){bytes[9].ToString("x2")}:
263-
{bytes[10].ToString("x2")}){bytes[11].ToString("x2")}:
264-
{bytes[12].ToString("x2")}){bytes[13].ToString("x2")}:
265-
{bytes[14].ToString("x2")}){bytes[15].ToString("x2")}:
266-
{bytes[16].ToString("x2")}){bytes[17].ToString("x2")}
260+
{bytes[3].ToString("x2")}){bytes[4].ToString("x2")}:
261+
{bytes[5].ToString("x2")}){bytes[6].ToString("x2")}:
262+
{bytes[7].ToString("x2")}){bytes[8].ToString("x2")}:
263+
{bytes[9].ToString("x2")}){bytes[10].ToString("x2")}:
264+
{bytes[11].ToString("x2")}){bytes[12].ToString("x2")}:
265+
{bytes[13].ToString("x2")}){bytes[14].ToString("x2")}:
266+
{bytes[15].ToString("x2")}){bytes[16].ToString("x2")}:
267+
{bytes[17].ToString("x2")}){bytes[18].ToString("x2")}
267268
""";
268269
}
269270
return value.ToString();
@@ -283,19 +284,19 @@ private static string GetPortId(string subtype, ISnmpData value) {
283284
return value.ToString();
284285

285286
case "4": //network address
286-
if (bytes.Length - 2 == 4) {
287-
return $"{bytes[2]}.{bytes[3]}.{bytes[4]}.{bytes[5]}";
287+
if (bytes.Length - 3 == 4) {
288+
return $"{bytes[3]}.{bytes[4]}.{bytes[5]}.{bytes[6]}";
288289
}
289-
else if (bytes.Length - 2 == 16) {
290+
else if (bytes.Length - 3 == 16) {
290291
return $"""
291-
{bytes[2].ToString("x2")}){bytes[3].ToString("x2")}:
292-
{bytes[4].ToString("x2")}){bytes[5].ToString("x2")}:
293-
{bytes[6].ToString("x2")}){bytes[7].ToString("x2")}:
294-
{bytes[8].ToString("x2")}){bytes[9].ToString("x2")}:
295-
{bytes[10].ToString("x2")}){bytes[11].ToString("x2")}:
296-
{bytes[12].ToString("x2")}){bytes[13].ToString("x2")}:
297-
{bytes[14].ToString("x2")}){bytes[15].ToString("x2")}:
298-
{bytes[16].ToString("x2")}){bytes[17].ToString("x2")}
292+
{bytes[3].ToString("x2")}){bytes[4].ToString("x2")}:
293+
{bytes[5].ToString("x2")}){bytes[6].ToString("x2")}:
294+
{bytes[7].ToString("x2")}){bytes[8].ToString("x2")}:
295+
{bytes[9].ToString("x2")}){bytes[10].ToString("x2")}:
296+
{bytes[11].ToString("x2")}){bytes[12].ToString("x2")}:
297+
{bytes[13].ToString("x2")}){bytes[14].ToString("x2")}:
298+
{bytes[15].ToString("x2")}){bytes[16].ToString("x2")}:
299+
{bytes[17].ToString("x2")}){bytes[18].ToString("x2")}
299300
""";
300301
}
301302
return value.ToString();

0 commit comments

Comments
 (0)