221 lines
4.8 KiB
Go
221 lines
4.8 KiB
Go
package services
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"lostcavewireplanner/internal/db"
|
|
"lostcavewireplanner/internal/models"
|
|
)
|
|
|
|
type Segment struct {
|
|
DeviceID int64
|
|
DeviceName string
|
|
ModelName string
|
|
PortID int64
|
|
PortName string
|
|
Side string
|
|
}
|
|
|
|
type TraceResult struct {
|
|
FarSegments []Segment
|
|
ConnectionID int64
|
|
ConnectionType string
|
|
Color string
|
|
Label1 string
|
|
Label2 string
|
|
ClickedPortID int64
|
|
ClickedPortName string
|
|
ClickedDeviceID int64
|
|
ClickedDeviceName string
|
|
ClickedModelName string
|
|
ClickedSide string
|
|
NearSegments []Segment
|
|
HasConnection bool
|
|
}
|
|
|
|
func TraceConnection(store *db.Store, clickedPortID int64) (*TraceResult, error) {
|
|
clickedPort, err := store.PortGetByID(clickedPortID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if clickedPort == nil {
|
|
return nil, fmt.Errorf("port not found")
|
|
}
|
|
|
|
clickedDevice, err := store.DeviceGetByID(clickedPort.DeviceID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result := &TraceResult{
|
|
ClickedPortID: clickedPort.ID,
|
|
ClickedPortName: clickedPort.Name,
|
|
ClickedDeviceID: clickedDevice.ID,
|
|
ClickedDeviceName: clickedDevice.Name,
|
|
ClickedSide: clickedPort.Side,
|
|
}
|
|
if clickedDevice.Model != nil {
|
|
result.ClickedModelName = clickedDevice.Model.Name
|
|
}
|
|
|
|
conn, err := store.ConnectionGetByPortID(clickedPortID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if conn == nil {
|
|
return result, nil
|
|
}
|
|
|
|
result.HasConnection = true
|
|
result.ConnectionID = conn.ID
|
|
result.Color = conn.Color
|
|
if conn.Label1 != nil {
|
|
result.Label1 = *conn.Label1
|
|
}
|
|
if conn.Label2 != nil {
|
|
result.Label2 = *conn.Label2
|
|
}
|
|
if conn.ConnectionType != nil {
|
|
result.ConnectionType = conn.ConnectionType.Name
|
|
}
|
|
|
|
var remotePort *models.DevicePort
|
|
if conn.PortID1 != nil && *conn.PortID1 == clickedPortID {
|
|
if conn.PortID2 != nil {
|
|
remotePort, _ = store.PortGetByID(*conn.PortID2)
|
|
}
|
|
} else if conn.PortID2 != nil && *conn.PortID2 == clickedPortID {
|
|
if conn.PortID1 != nil {
|
|
remotePort, _ = store.PortGetByID(*conn.PortID1)
|
|
}
|
|
}
|
|
|
|
if remotePort != nil {
|
|
result.FarSegments = traceAway(store, remotePort.ID, conn.ID)
|
|
}
|
|
|
|
result.NearSegments = traceThrough(store, clickedPortID, conn.ID)
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func traceAway(store *db.Store, portID int64, excludeConnID int64) []Segment {
|
|
var segments []Segment
|
|
visitedPorts := map[int64]bool{}
|
|
currentPortID := portID
|
|
|
|
for {
|
|
if visitedPorts[currentPortID] {
|
|
break
|
|
}
|
|
visitedPorts[currentPortID] = true
|
|
|
|
port, err := store.PortGetByID(currentPortID)
|
|
if err != nil || port == nil {
|
|
break
|
|
}
|
|
|
|
device, err := store.DeviceGetByID(port.DeviceID)
|
|
if err != nil || device == nil {
|
|
break
|
|
}
|
|
|
|
modelName := ""
|
|
if device.Model != nil {
|
|
modelName = device.Model.Name
|
|
}
|
|
|
|
segments = append(segments, Segment{
|
|
DeviceID: device.ID,
|
|
DeviceName: device.Name,
|
|
ModelName: modelName,
|
|
PortID: port.ID,
|
|
PortName: port.Name,
|
|
Side: port.Side,
|
|
})
|
|
|
|
isPatch := device.Model != nil && (device.Model.IsPatchPanel || device.Model.IsWallSocket)
|
|
if !isPatch {
|
|
break
|
|
}
|
|
|
|
pairedSide := "back"
|
|
if port.Side == "back" {
|
|
pairedSide = "front"
|
|
}
|
|
|
|
pairedPort, err := store.PortGetPaired(port.DeviceID, port.Name, pairedSide)
|
|
if err != nil || pairedPort == nil {
|
|
break
|
|
}
|
|
|
|
if visitedPorts[pairedPort.ID] {
|
|
break
|
|
}
|
|
|
|
nextConn, err := store.ConnectionGetByPortIDExcluding(pairedPort.ID, excludeConnID)
|
|
if err != nil || nextConn == nil {
|
|
break
|
|
}
|
|
|
|
var nextPortID int64
|
|
if nextConn.PortID1 != nil && *nextConn.PortID1 != pairedPort.ID {
|
|
nextPortID = *nextConn.PortID1
|
|
} else if nextConn.PortID2 != nil && *nextConn.PortID2 != pairedPort.ID {
|
|
nextPortID = *nextConn.PortID2
|
|
} else {
|
|
break
|
|
}
|
|
|
|
excludeConnID = nextConn.ID
|
|
currentPortID = nextPortID
|
|
}
|
|
|
|
return segments
|
|
}
|
|
|
|
func traceThrough(store *db.Store, portID int64, excludeConnID int64) []Segment {
|
|
var segments []Segment
|
|
|
|
port, err := store.PortGetByID(portID)
|
|
if err != nil || port == nil {
|
|
return segments
|
|
}
|
|
|
|
device, err := store.DeviceGetByID(port.DeviceID)
|
|
if err != nil || device == nil {
|
|
return segments
|
|
}
|
|
|
|
isPatch := device.Model != nil && (device.Model.IsPatchPanel || device.Model.IsWallSocket)
|
|
if !isPatch {
|
|
return segments
|
|
}
|
|
|
|
pairedSide := "back"
|
|
if port.Side == "back" {
|
|
pairedSide = "front"
|
|
}
|
|
|
|
pairedPort, err := store.PortGetPaired(port.DeviceID, port.Name, pairedSide)
|
|
if err != nil || pairedPort == nil {
|
|
return segments
|
|
}
|
|
|
|
nextConn, err := store.ConnectionGetByPortIDExcluding(pairedPort.ID, excludeConnID)
|
|
if err != nil || nextConn == nil {
|
|
return segments
|
|
}
|
|
|
|
var nextPortID int64
|
|
if nextConn.PortID1 != nil && *nextConn.PortID1 != pairedPort.ID {
|
|
nextPortID = *nextConn.PortID1
|
|
} else if nextConn.PortID2 != nil && *nextConn.PortID2 != pairedPort.ID {
|
|
nextPortID = *nextConn.PortID2
|
|
} else {
|
|
return segments
|
|
}
|
|
|
|
return traceAway(store, nextPortID, nextConn.ID)
|
|
}
|