Pull request 2083: AG-27492-client-runtime
Squashed commit of the following: commit e4c2abd37f5885a12da5c68179e3dba18534c3be Merge: 7411b40b2dae304fc3
Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Dec 13 13:15:40 2023 +0300 Merge branch 'master' into AG-27492-client-runtime commit 7411b40b234a438df4c84823fcb19efecf5eb64d Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Tue Dec 12 17:51:51 2023 +0300 all: imp code commit d5edd0258779c6dfba56da1e4d79e0380b137385 Merge: 371f5b23cc908eec5d
Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Tue Dec 12 13:45:33 2023 +0300 Merge branch 'master' into AG-27492-client-runtime commit 371f5b23c9507fb6e8e8f8ec1f644ca8e67ea412 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Tue Dec 12 13:44:38 2023 +0300 client: imp code commit 9aefb1443082a342270a7e5e77a07d5d1518e327 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Fri Dec 8 17:08:07 2023 +0300 all: imp code commit 3aa51d10aadfd124f36238a31f3d623706e3c870 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Tue Dec 5 19:20:41 2023 +0300 all: imp docs commit 71d7187e0c14e143865b055e9b01ff61a2e30083 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Fri Dec 1 17:17:06 2023 +0300 all: imp code commit e09f8a0bd90f295b5a580e24b2696cc78993713a Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Thu Nov 30 14:46:53 2023 +0300 all: imp log msg commit ce0a9454df9a173694395b4dd8b05347a2e56fdc Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Tue Nov 28 16:21:01 2023 +0300 all: imp code commit e84f176aaba6953b22e13a5fa84079a832d30a24 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Nov 22 17:40:18 2023 +0300 all: add client runtime
This commit is contained in:
parent
dae304fc3c
commit
9241393ed2
|
@ -7,6 +7,8 @@ package client
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Source represents the source from which the information about the client has
|
// Source represents the source from which the information about the client has
|
||||||
|
@ -15,8 +17,7 @@ type Source uint8
|
||||||
|
|
||||||
// Clients information sources. The order determines the priority.
|
// Clients information sources. The order determines the priority.
|
||||||
const (
|
const (
|
||||||
SourceNone Source = iota
|
SourceWHOIS Source = iota + 1
|
||||||
SourceWHOIS
|
|
||||||
SourceARP
|
SourceARP
|
||||||
SourceRDNS
|
SourceRDNS
|
||||||
SourceDHCP
|
SourceDHCP
|
||||||
|
@ -52,3 +53,107 @@ var _ encoding.TextMarshaler = Source(0)
|
||||||
func (cs Source) MarshalText() (text []byte, err error) {
|
func (cs Source) MarshalText() (text []byte, err error) {
|
||||||
return []byte(cs.String()), nil
|
return []byte(cs.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Runtime is a client information from different sources.
|
||||||
|
type Runtime struct {
|
||||||
|
// whois is the filtered WHOIS information of a client.
|
||||||
|
whois *whois.Info
|
||||||
|
|
||||||
|
// arp is the ARP information of a client. nil indicates that there is no
|
||||||
|
// information from the source. Empty non-nil slice indicates that the data
|
||||||
|
// from the source is present, but empty.
|
||||||
|
arp []string
|
||||||
|
|
||||||
|
// rdns is the RDNS information of a client. nil indicates that there is no
|
||||||
|
// information from the source. Empty non-nil slice indicates that the data
|
||||||
|
// from the source is present, but empty.
|
||||||
|
rdns []string
|
||||||
|
|
||||||
|
// dhcp is the DHCP information of a client. nil indicates that there is no
|
||||||
|
// information from the source. Empty non-nil slice indicates that the data
|
||||||
|
// from the source is present, but empty.
|
||||||
|
dhcp []string
|
||||||
|
|
||||||
|
// hostsFile is the information from the hosts file. nil indicates that
|
||||||
|
// there is no information from the source. Empty non-nil slice indicates
|
||||||
|
// that the data from the source is present, but empty.
|
||||||
|
hostsFile []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info returns a client information from the highest-priority source.
|
||||||
|
func (r *Runtime) Info() (cs Source, host string) {
|
||||||
|
info := []string{}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case r.hostsFile != nil:
|
||||||
|
cs, info = SourceHostsFile, r.hostsFile
|
||||||
|
case r.dhcp != nil:
|
||||||
|
cs, info = SourceDHCP, r.dhcp
|
||||||
|
case r.rdns != nil:
|
||||||
|
cs, info = SourceRDNS, r.rdns
|
||||||
|
case r.arp != nil:
|
||||||
|
cs, info = SourceARP, r.arp
|
||||||
|
case r.whois != nil:
|
||||||
|
cs = SourceWHOIS
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(info) == 0 {
|
||||||
|
return cs, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(s.chzhen): Return the full information.
|
||||||
|
return cs, info[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInfo sets a host as a client information from the cs.
|
||||||
|
func (r *Runtime) SetInfo(cs Source, hosts []string) {
|
||||||
|
if len(hosts) == 1 && hosts[0] == "" {
|
||||||
|
hosts = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch cs {
|
||||||
|
case SourceARP:
|
||||||
|
r.arp = hosts
|
||||||
|
case SourceRDNS:
|
||||||
|
r.rdns = hosts
|
||||||
|
case SourceDHCP:
|
||||||
|
r.dhcp = hosts
|
||||||
|
case SourceHostsFile:
|
||||||
|
r.hostsFile = hosts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WHOIS returns a WHOIS client information.
|
||||||
|
func (r *Runtime) WHOIS() (info *whois.Info) {
|
||||||
|
return r.whois
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWHOIS sets a WHOIS client information. info must be non-nil.
|
||||||
|
func (r *Runtime) SetWHOIS(info *whois.Info) {
|
||||||
|
r.whois = info
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset clears a cs information.
|
||||||
|
func (r *Runtime) Unset(cs Source) {
|
||||||
|
switch cs {
|
||||||
|
case SourceWHOIS:
|
||||||
|
r.whois = nil
|
||||||
|
case SourceARP:
|
||||||
|
r.arp = nil
|
||||||
|
case SourceRDNS:
|
||||||
|
r.rdns = nil
|
||||||
|
case SourceDHCP:
|
||||||
|
r.dhcp = nil
|
||||||
|
case SourceHostsFile:
|
||||||
|
r.hostsFile = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns true if there is no information from any source.
|
||||||
|
func (r *Runtime) IsEmpty() (ok bool) {
|
||||||
|
return r.whois == nil &&
|
||||||
|
r.arp == nil &&
|
||||||
|
r.rdns == nil &&
|
||||||
|
r.dhcp == nil &&
|
||||||
|
r.hostsFile == nil
|
||||||
|
}
|
||||||
|
|
|
@ -4,10 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
|
||||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
"github.com/AdguardTeam/golibs/stringutil"
|
||||||
)
|
)
|
||||||
|
@ -85,17 +83,3 @@ func (c *Client) setSafeSearch(
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeClient is a client information about which has been obtained using the
|
|
||||||
// source described in the Source field.
|
|
||||||
type RuntimeClient struct {
|
|
||||||
// WHOIS is the filtered WHOIS data of a client.
|
|
||||||
WHOIS *whois.Info
|
|
||||||
|
|
||||||
// Host is the host name of a client.
|
|
||||||
Host string
|
|
||||||
|
|
||||||
// Source is the source from which the information about the client has
|
|
||||||
// been obtained.
|
|
||||||
Source client.Source
|
|
||||||
}
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ type clientsContainer struct {
|
||||||
list map[string]*Client // name -> client
|
list map[string]*Client // name -> client
|
||||||
idIndex map[string]*Client // ID -> client
|
idIndex map[string]*Client // ID -> client
|
||||||
|
|
||||||
// ipToRC is the IP address to *RuntimeClient map.
|
// ipToRC maps IP addresses to runtime client information.
|
||||||
ipToRC map[netip.Addr]*RuntimeClient
|
ipToRC map[netip.Addr]*client.Runtime
|
||||||
|
|
||||||
allTags *stringutil.Set
|
allTags *stringutil.Set
|
||||||
|
|
||||||
|
@ -103,9 +103,9 @@ func (clients *clientsContainer) Init(
|
||||||
log.Fatal("clients.list != nil")
|
log.Fatal("clients.list != nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
clients.list = make(map[string]*Client)
|
clients.list = map[string]*Client{}
|
||||||
clients.idIndex = make(map[string]*Client)
|
clients.idIndex = map[string]*Client{}
|
||||||
clients.ipToRC = map[netip.Addr]*RuntimeClient{}
|
clients.ipToRC = map[netip.Addr]*client.Runtime{}
|
||||||
|
|
||||||
clients.allTags = stringutil.NewSet(clientTags...)
|
clients.allTags = stringutil.NewSet(clientTags...)
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ func (clients *clientsContainer) clientSource(ip netip.Addr) (src client.Source)
|
||||||
|
|
||||||
rc, ok := clients.ipToRC[ip]
|
rc, ok := clients.ipToRC[ip]
|
||||||
if ok {
|
if ok {
|
||||||
src = rc.Source
|
src, _ = rc.Info()
|
||||||
}
|
}
|
||||||
|
|
||||||
if src < client.SourceDHCP && clients.dhcp.HostByIP(ip) != "" {
|
if src < client.SourceDHCP && clients.dhcp.HostByIP(ip) != "" {
|
||||||
|
@ -389,20 +389,22 @@ func (clients *clientsContainer) clientOrArtificial(
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
client, ok := clients.Find(id)
|
cli, ok := clients.Find(id)
|
||||||
if ok {
|
if ok {
|
||||||
return &querylog.Client{
|
return &querylog.Client{
|
||||||
Name: client.Name,
|
Name: cli.Name,
|
||||||
IgnoreQueryLog: client.IgnoreQueryLog,
|
IgnoreQueryLog: cli.IgnoreQueryLog,
|
||||||
}, false
|
}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
var rc *RuntimeClient
|
var rc *client.Runtime
|
||||||
rc, ok = clients.findRuntimeClient(ip)
|
rc, ok = clients.findRuntimeClient(ip)
|
||||||
if ok {
|
if ok {
|
||||||
|
_, host := rc.Info()
|
||||||
|
|
||||||
return &querylog.Client{
|
return &querylog.Client{
|
||||||
Name: rc.Host,
|
Name: host,
|
||||||
WHOIS: rc.WHOIS,
|
WHOIS: rc.WHOIS(),
|
||||||
}, false
|
}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +551,7 @@ func (clients *clientsContainer) findDHCP(ip netip.Addr) (c *Client, ok bool) {
|
||||||
|
|
||||||
// runtimeClient returns a runtime client from internal index. Note that it
|
// runtimeClient returns a runtime client from internal index. Note that it
|
||||||
// doesn't include DHCP clients.
|
// doesn't include DHCP clients.
|
||||||
func (clients *clientsContainer) runtimeClient(ip netip.Addr) (rc *RuntimeClient, ok bool) {
|
func (clients *clientsContainer) runtimeClient(ip netip.Addr) (rc *client.Runtime, ok bool) {
|
||||||
if ip == (netip.Addr{}) {
|
if ip == (netip.Addr{}) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
@ -563,21 +565,21 @@ func (clients *clientsContainer) runtimeClient(ip netip.Addr) (rc *RuntimeClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// findRuntimeClient finds a runtime client by their IP.
|
// findRuntimeClient finds a runtime client by their IP.
|
||||||
func (clients *clientsContainer) findRuntimeClient(ip netip.Addr) (rc *RuntimeClient, ok bool) {
|
func (clients *clientsContainer) findRuntimeClient(ip netip.Addr) (rc *client.Runtime, ok bool) {
|
||||||
if rc, ok = clients.runtimeClient(ip); ok && rc.Source > client.SourceDHCP {
|
rc, ok = clients.runtimeClient(ip)
|
||||||
return rc, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
host := clients.dhcp.HostByIP(ip)
|
host := clients.dhcp.HostByIP(ip)
|
||||||
if host == "" {
|
|
||||||
return rc, ok
|
if host != "" {
|
||||||
|
if !ok {
|
||||||
|
rc = &client.Runtime{}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc.SetInfo(client.SourceDHCP, []string{host})
|
||||||
|
|
||||||
|
return rc, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return &RuntimeClient{
|
return rc, ok
|
||||||
Host: host,
|
|
||||||
Source: client.SourceDHCP,
|
|
||||||
WHOIS: &whois.Info{},
|
|
||||||
}, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check validates the client.
|
// check validates the client.
|
||||||
|
@ -768,23 +770,20 @@ func (clients *clientsContainer) setWHOISInfo(ip netip.Addr, wi *whois.Info) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(e.burkov): Consider storing WHOIS information separately and
|
|
||||||
// potentially get rid of [RuntimeClient].
|
|
||||||
rc, ok := clients.ipToRC[ip]
|
rc, ok := clients.ipToRC[ip]
|
||||||
if !ok {
|
if !ok {
|
||||||
// Create a RuntimeClient implicitly so that we don't do this check
|
// Create a RuntimeClient implicitly so that we don't do this check
|
||||||
// again.
|
// again.
|
||||||
rc = &RuntimeClient{
|
rc = &client.Runtime{}
|
||||||
Source: client.SourceWHOIS,
|
|
||||||
}
|
|
||||||
clients.ipToRC[ip] = rc
|
clients.ipToRC[ip] = rc
|
||||||
|
|
||||||
log.Debug("clients: set whois info for runtime client with ip %s: %+v", ip, wi)
|
log.Debug("clients: set whois info for runtime client with ip %s: %+v", ip, wi)
|
||||||
} else {
|
} else {
|
||||||
log.Debug("clients: set whois info for runtime client %s: %+v", rc.Host, wi)
|
host, _ := rc.Info()
|
||||||
|
log.Debug("clients: set whois info for runtime client %s: %+v", host, wi)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc.WHOIS = wi
|
rc.SetWHOIS(wi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addHost adds a new IP-hostname pairing. The priorities of the sources are
|
// addHost adds a new IP-hostname pairing. The priorities of the sources are
|
||||||
|
@ -843,18 +842,13 @@ func (clients *clientsContainer) addHostLocked(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = &RuntimeClient{
|
rc = &client.Runtime{}
|
||||||
WHOIS: &whois.Info{},
|
|
||||||
}
|
|
||||||
clients.ipToRC[ip] = rc
|
clients.ipToRC[ip] = rc
|
||||||
} else if src < rc.Source {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc.Host = host
|
rc.SetInfo(src, []string{host})
|
||||||
rc.Source = src
|
|
||||||
|
|
||||||
log.Debug("clients: added %s -> %q [%d]", ip, host, len(clients.ipToRC))
|
log.Debug("clients: adding client info %s -> %q %q [%d]", ip, src, host, len(clients.ipToRC))
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -863,7 +857,8 @@ func (clients *clientsContainer) addHostLocked(
|
||||||
func (clients *clientsContainer) rmHostsBySrc(src client.Source) {
|
func (clients *clientsContainer) rmHostsBySrc(src client.Source) {
|
||||||
n := 0
|
n := 0
|
||||||
for ip, rc := range clients.ipToRC {
|
for ip, rc := range clients.ipToRC {
|
||||||
if rc.Source == src {
|
rc.Unset(src)
|
||||||
|
if rc.IsEmpty() {
|
||||||
delete(clients.ipToRC, ip)
|
delete(clients.ipToRC, ip)
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,9 +60,8 @@ func TestClients(t *testing.T) {
|
||||||
cli1 = "1.1.1.1"
|
cli1 = "1.1.1.1"
|
||||||
cli2 = "2.2.2.2"
|
cli2 = "2.2.2.2"
|
||||||
|
|
||||||
cliNoneIP = netip.MustParseAddr(cliNone)
|
cli1IP = netip.MustParseAddr(cli1)
|
||||||
cli1IP = netip.MustParseAddr(cli1)
|
cli2IP = netip.MustParseAddr(cli2)
|
||||||
cli2IP = netip.MustParseAddr(cli2)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
c := &Client{
|
c := &Client{
|
||||||
|
@ -100,7 +99,9 @@ func TestClients(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, "client2", c.Name)
|
assert.Equal(t, "client2", c.Name)
|
||||||
|
|
||||||
assert.Equal(t, clients.clientSource(cliNoneIP), client.SourceNone)
|
_, ok = clients.Find(cliNone)
|
||||||
|
assert.False(t, ok)
|
||||||
|
|
||||||
assert.Equal(t, clients.clientSource(cli1IP), client.SourcePersistent)
|
assert.Equal(t, clients.clientSource(cli1IP), client.SourcePersistent)
|
||||||
assert.Equal(t, clients.clientSource(cli2IP), client.SourcePersistent)
|
assert.Equal(t, clients.clientSource(cli2IP), client.SourcePersistent)
|
||||||
})
|
})
|
||||||
|
@ -136,7 +137,6 @@ func TestClients(t *testing.T) {
|
||||||
cliOld = "1.1.1.1"
|
cliOld = "1.1.1.1"
|
||||||
cliNew = "1.1.1.2"
|
cliNew = "1.1.1.2"
|
||||||
|
|
||||||
cliOldIP = netip.MustParseAddr(cliOld)
|
|
||||||
cliNewIP = netip.MustParseAddr(cliNew)
|
cliNewIP = netip.MustParseAddr(cliNew)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -149,7 +149,9 @@ func TestClients(t *testing.T) {
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, clients.clientSource(cliOldIP), client.SourceNone)
|
_, ok = clients.Find(cliOld)
|
||||||
|
assert.False(t, ok)
|
||||||
|
|
||||||
assert.Equal(t, clients.clientSource(cliNewIP), client.SourcePersistent)
|
assert.Equal(t, clients.clientSource(cliNewIP), client.SourcePersistent)
|
||||||
|
|
||||||
prev, ok = clients.list["client1"]
|
prev, ok = clients.list["client1"]
|
||||||
|
@ -182,7 +184,8 @@ func TestClients(t *testing.T) {
|
||||||
ok := clients.Del("client1-renamed")
|
ok := clients.Del("client1-renamed")
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
assert.Equal(t, clients.clientSource(netip.MustParseAddr("1.1.1.2")), client.SourceNone)
|
_, ok = clients.Find("1.1.1.2")
|
||||||
|
assert.False(t, ok)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("del_fail", func(t *testing.T) {
|
t.Run("del_fail", func(t *testing.T) {
|
||||||
|
@ -215,10 +218,12 @@ func TestClients(t *testing.T) {
|
||||||
assert.Equal(t, clients.clientSource(ip), client.SourceDHCP)
|
assert.Equal(t, clients.clientSource(ip), client.SourceDHCP)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("addhost_fail", func(t *testing.T) {
|
t.Run("addhost_priority", func(t *testing.T) {
|
||||||
ip := netip.MustParseAddr("1.1.1.1")
|
ip := netip.MustParseAddr("1.1.1.1")
|
||||||
ok := clients.addHost(ip, "host1", client.SourceRDNS)
|
ok := clients.addHost(ip, "host1", client.SourceRDNS)
|
||||||
assert.False(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
assert.Equal(t, client.SourceHostsFile, clients.clientSource(ip))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +240,7 @@ func TestClientsWHOIS(t *testing.T) {
|
||||||
rc := clients.ipToRC[ip]
|
rc := clients.ipToRC[ip]
|
||||||
require.NotNil(t, rc)
|
require.NotNil(t, rc)
|
||||||
|
|
||||||
assert.Equal(t, rc.WHOIS, whois)
|
assert.Equal(t, whois, rc.WHOIS())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("existing_auto-client", func(t *testing.T) {
|
t.Run("existing_auto-client", func(t *testing.T) {
|
||||||
|
@ -247,7 +252,7 @@ func TestClientsWHOIS(t *testing.T) {
|
||||||
rc := clients.ipToRC[ip]
|
rc := clients.ipToRC[ip]
|
||||||
require.NotNil(t, rc)
|
require.NotNil(t, rc)
|
||||||
|
|
||||||
assert.Equal(t, rc.WHOIS, whois)
|
assert.Equal(t, whois, rc.WHOIS())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("can't_set_manually-added", func(t *testing.T) {
|
t.Run("can't_set_manually-added", func(t *testing.T) {
|
||||||
|
|
|
@ -75,6 +75,17 @@ type clientListJSON struct {
|
||||||
Tags []string `json:"supported_tags"`
|
Tags []string `json:"supported_tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// whoisOrEmpty returns a WHOIS client information or a pointer to an empty
|
||||||
|
// struct. Frontend expects a non-nil value.
|
||||||
|
func whoisOrEmpty(r *client.Runtime) (info *whois.Info) {
|
||||||
|
info = r.WHOIS()
|
||||||
|
if info != nil {
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
return &whois.Info{}
|
||||||
|
}
|
||||||
|
|
||||||
// handleGetClients is the handler for GET /control/clients HTTP API.
|
// handleGetClients is the handler for GET /control/clients HTTP API.
|
||||||
func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http.Request) {
|
func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http.Request) {
|
||||||
data := clientListJSON{}
|
data := clientListJSON{}
|
||||||
|
@ -88,11 +99,11 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||||
}
|
}
|
||||||
|
|
||||||
for ip, rc := range clients.ipToRC {
|
for ip, rc := range clients.ipToRC {
|
||||||
|
src, host := rc.Info()
|
||||||
cj := runtimeClientJSON{
|
cj := runtimeClientJSON{
|
||||||
WHOIS: rc.WHOIS,
|
WHOIS: whoisOrEmpty(rc),
|
||||||
|
Name: host,
|
||||||
Name: rc.Host,
|
Source: src,
|
||||||
Source: rc.Source,
|
|
||||||
IP: ip,
|
IP: ip,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,10 +448,11 @@ func (clients *clientsContainer) findRuntime(ip netip.Addr, idStr string) (cj *c
|
||||||
return cj
|
return cj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, host := rc.Info()
|
||||||
cj = &clientJSON{
|
cj = &clientJSON{
|
||||||
Name: rc.Host,
|
Name: host,
|
||||||
IDs: []string{idStr},
|
IDs: []string{idStr},
|
||||||
WHOIS: rc.WHOIS,
|
WHOIS: whoisOrEmpty(rc),
|
||||||
}
|
}
|
||||||
|
|
||||||
disallowed, rule := clients.dnsServer.IsBlockedClient(ip, idStr)
|
disallowed, rule := clients.dnsServer.IsBlockedClient(ip, idStr)
|
||||||
|
|
Loading…
Reference in New Issue