mirror of
https://github.com/bettercap/bettercap
synced 2025-08-14 02:36:57 -07:00
misc: several improvements to the graph module
This commit is contained in:
parent
5b8cb9a82c
commit
71634058a7
6 changed files with 468 additions and 263 deletions
158
modules/graph/edges.go
Normal file
158
modules/graph/edges.go
Normal file
|
@ -0,0 +1,158 @@
|
|||
package graph
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/evilsocket/islazy/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const edgesIndexName = "edges.json"
|
||||
|
||||
type EdgesTo map[string][]Edge
|
||||
|
||||
type EdgesCallback func(string, []Edge, string) error
|
||||
|
||||
type Edges struct {
|
||||
sync.RWMutex
|
||||
timestamp time.Time
|
||||
fileName string
|
||||
size int
|
||||
from map[string]EdgesTo
|
||||
}
|
||||
|
||||
type edgesJSON struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Size int `json:"size"`
|
||||
Edges map[string]EdgesTo `json:"edges"`
|
||||
}
|
||||
|
||||
func LoadEdges(basePath string) (*Edges, error) {
|
||||
edges := Edges{
|
||||
fileName: path.Join(basePath, edgesIndexName),
|
||||
from: make(map[string]EdgesTo),
|
||||
}
|
||||
|
||||
if fs.Exists(edges.fileName) {
|
||||
var js edgesJSON
|
||||
|
||||
if raw, err := ioutil.ReadFile(edges.fileName); err != nil {
|
||||
return nil, err
|
||||
} else if err = json.Unmarshal(raw, &js); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
edges.timestamp = js.Timestamp
|
||||
edges.from = js.Edges
|
||||
edges.size = js.Size
|
||||
}
|
||||
|
||||
return &edges, nil
|
||||
}
|
||||
|
||||
func (e *Edges) flush() error {
|
||||
e.timestamp = time.Now()
|
||||
js := edgesJSON{
|
||||
Timestamp: e.timestamp,
|
||||
Size: e.size,
|
||||
Edges: e.from,
|
||||
}
|
||||
|
||||
if raw, err := json.Marshal(js); err != nil {
|
||||
return err
|
||||
} else if err = ioutil.WriteFile(e.fileName, raw, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Edges) Flush() error {
|
||||
e.RLock()
|
||||
defer e.RUnlock()
|
||||
return e.flush()
|
||||
}
|
||||
|
||||
func (e *Edges) ForEachEdge(cb EdgesCallback) error {
|
||||
e.RLock()
|
||||
defer e.RUnlock()
|
||||
|
||||
for from, edgesTo := range e.from {
|
||||
for to, edges := range edgesTo {
|
||||
if err := cb(from, edges, to); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Edges) ForEachEdgeFrom(nodeID string, cb EdgesCallback) error {
|
||||
e.RLock()
|
||||
defer e.RUnlock()
|
||||
|
||||
if edgesTo, found := e.from[nodeID]; found {
|
||||
for to, edges := range edgesTo {
|
||||
if err := cb(nodeID, edges, to); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Edges) IsConnected(nodeID string) bool {
|
||||
e.RLock()
|
||||
defer e.RUnlock()
|
||||
|
||||
if edgesTo, found := e.from[nodeID]; found {
|
||||
return len(edgesTo) > 0
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Edges) FindEdges(fromID, toID string, doSort bool) []Edge {
|
||||
e.RLock()
|
||||
defer e.RUnlock()
|
||||
|
||||
if edgesTo, foundFrom := e.from[fromID]; foundFrom {
|
||||
if edges, foundTo := edgesTo[toID]; foundTo {
|
||||
if doSort {
|
||||
// sort edges from oldest to newer
|
||||
sort.Slice(edges, func(i, j int) bool {
|
||||
return edges[i].CreatedAt.Before(edges[j].CreatedAt)
|
||||
})
|
||||
}
|
||||
return edges
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Edges) Connect(fromID, toID string, edge Edge) error {
|
||||
e.Lock()
|
||||
defer e.Unlock()
|
||||
|
||||
if edgesTo, foundFrom := e.from[fromID]; foundFrom {
|
||||
edges := edgesTo[toID]
|
||||
edges = append(edges, edge)
|
||||
e.from[fromID][toID] = edges
|
||||
} else {
|
||||
// create the entire path
|
||||
e.from[fromID] = EdgesTo{
|
||||
toID: {edge},
|
||||
}
|
||||
}
|
||||
|
||||
e.size++
|
||||
|
||||
return e.flush()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue