Revamp Connection.ID

Add Connection.Type and Connection.External
Deprecate Connection.Scope
This commit is contained in:
Daniel
2021-03-20 22:29:29 +01:00
parent 20383226f8
commit fbf666ee68
6 changed files with 196 additions and 76 deletions

View File

@@ -1,11 +1,10 @@
package network
import (
"fmt"
"strconv"
"strings"
"github.com/safing/portmaster/network/state"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/iterator"
"github.com/safing/portbase/database/query"
@@ -27,37 +26,86 @@ type StorageInterface struct {
storage.InjectBase
}
// Get returns a database record.
func (s *StorageInterface) Get(key string) (record.Record, error) {
// Database prefixes:
// Processes: network:tree/<PID>
// DNS Requests: network:tree/<PID>/dns/<ID>
// IP Connections: network:tree/<PID>/ip/<ID>
splitted := strings.Split(key, "/")
switch splitted[0] { //nolint:gocritic // TODO: implement full key space
case "tree":
switch len(splitted) {
case 2:
pid, err := strconv.Atoi(splitted[1])
if err == nil {
proc, ok := process.GetProcessFromStorage(pid)
if ok {
return proc, nil
}
}
case 3:
if r, ok := dnsConns.get(splitted[1] + "/" + splitted[2]); ok {
return r, nil
}
case 4:
if r, ok := conns.get(splitted[3]); ok {
return r, nil
func makeKey(pid int, scope, id string) string {
if scope == "" {
return "network:tree/" + strconv.Itoa(pid)
}
return fmt.Sprintf("network:tree/%d/%s/%s", pid, scope, id)
}
func parseDBKey(key string) (pid int, scope, id string, ok bool) {
// Split into segments.
segments := strings.Split(key, "/")
// Check for valid prefix.
if !strings.HasPrefix("tree", segments[0]) {
return 0, "", "", false
}
// Keys have 2 or 4 segments.
switch len(segments) {
case 4:
id = segments[3]
fallthrough
case 3:
scope = segments[2]
// Sanity check.
switch scope {
case "dns", "ip", "":
// Parsed id matches possible values.
// The empty string is for matching a trailing slash for in query prefix.
// TODO: For queries, also prefixes of these values are valid.
default:
// Unknown scope.
return 0, "", "", false
}
fallthrough
case 2:
var err error
if segments[1] == "" {
pid = process.UndefinedProcessID
} else {
pid, err = strconv.Atoi(segments[1])
if err != nil {
return 0, "", "", false
}
}
case "system":
if len(splitted) >= 2 {
switch splitted[1] {
case "state":
return state.GetInfo(), nil
default:
}
return pid, scope, id, true
case 1:
// This is a valid query prefix, but not process ID was given.
return process.UndefinedProcessID, "", "", true
default:
return 0, "", "", false
}
}
// Get returns a database record.
func (s *StorageInterface) Get(key string) (record.Record, error) {
// Parse key and check if valid.
pid, scope, id, ok := parseDBKey(strings.TrimPrefix(key, "network:"))
if !ok || pid == process.UndefinedProcessID {
return nil, storage.ErrNotFound
}
switch scope {
case "dns":
if r, ok := dnsConns.get(id); ok {
return r, nil
}
case "ip":
if r, ok := conns.get(id); ok {
return r, nil
}
case "":
if proc, ok := process.GetProcessFromStorage(pid); ok {
return proc, nil
}
}
@@ -74,9 +122,13 @@ func (s *StorageInterface) Query(q *query.Query, local, internal bool) (*iterato
}
func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
slashes := strings.Count(q.DatabaseKeyPrefix(), "/")
pid, scope, _, ok := parseDBKey(q.DatabaseKeyPrefix())
if !ok {
it.Finish(nil)
return
}
if slashes <= 1 {
if pid == process.UndefinedProcessID {
// processes
for _, proc := range process.All() {
proc.Lock()
@@ -87,7 +139,7 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
}
}
if slashes <= 2 {
if scope == "" || scope == "dns" {
// dns scopes only
for _, dnsConn := range dnsConns.clone() {
dnsConn.Lock()
@@ -98,7 +150,7 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
}
}
if slashes <= 3 {
if scope == "" || scope == "ip" {
// connections
for _, conn := range conns.clone() {
conn.Lock()