mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-22 04:55:33 +03:00
Pull request: 5035-netip-maps-clients
Updates #5035. Squashed commit of the following: commit c2d38fe75b8aa2f00b19892724984ed3bb843db5 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Oct 24 16:50:14 2022 +0300 home: move clients to netip.Addr
This commit is contained in:
parent
a272b61ed6
commit
cebbb69a4c
5 changed files with 53 additions and 69 deletions
|
@ -706,7 +706,5 @@ func (s *Server) IsBlockedClient(ip net.IP, clientID string) (blocked bool, rule
|
||||||
blocked = true
|
blocked = true
|
||||||
}
|
}
|
||||||
|
|
||||||
rule = aghalg.Coalesce(rule, clientID)
|
return blocked, aghalg.Coalesce(rule, clientID)
|
||||||
|
|
||||||
return blocked, rule
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding"
|
"encoding"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -25,8 +26,6 @@ import (
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
//lint:file-ignore SA1019 TODO(a.garipov): Replace [*netutil.IPMap].
|
|
||||||
|
|
||||||
const clientsUpdatePeriod = 10 * time.Minute
|
const clientsUpdatePeriod = 10 * time.Minute
|
||||||
|
|
||||||
var webHandlersRegistered = false
|
var webHandlersRegistered = false
|
||||||
|
@ -135,9 +134,7 @@ type clientsContainer struct {
|
||||||
idIndex map[string]*Client // ID -> client
|
idIndex map[string]*Client // ID -> client
|
||||||
|
|
||||||
// ipToRC is the IP address to *RuntimeClient map.
|
// ipToRC is the IP address to *RuntimeClient map.
|
||||||
//
|
ipToRC map[netip.Addr]*RuntimeClient
|
||||||
// TODO(e.burkov): Use map[netip.Addr]struct{} instead.
|
|
||||||
ipToRC *netutil.IPMap
|
|
||||||
|
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
|
||||||
|
@ -173,7 +170,7 @@ func (clients *clientsContainer) Init(
|
||||||
}
|
}
|
||||||
clients.list = make(map[string]*Client)
|
clients.list = make(map[string]*Client)
|
||||||
clients.idIndex = make(map[string]*Client)
|
clients.idIndex = make(map[string]*Client)
|
||||||
clients.ipToRC = netutil.NewIPMap(0)
|
clients.ipToRC = map[netip.Addr]*RuntimeClient{}
|
||||||
|
|
||||||
clients.allTags = stringutil.NewSet(clientTags...)
|
clients.allTags = stringutil.NewSet(clientTags...)
|
||||||
|
|
||||||
|
@ -541,20 +538,17 @@ func (clients *clientsContainer) findLocked(id string) (c *Client, ok bool) {
|
||||||
// findRuntimeClientLocked finds a runtime client by their IP address. For
|
// findRuntimeClientLocked finds a runtime client by their IP address. For
|
||||||
// internal use only.
|
// internal use only.
|
||||||
func (clients *clientsContainer) findRuntimeClientLocked(ip net.IP) (rc *RuntimeClient, ok bool) {
|
func (clients *clientsContainer) findRuntimeClientLocked(ip net.IP) (rc *RuntimeClient, ok bool) {
|
||||||
var v any
|
// TODO(a.garipov): Remove once we switch to netip.Addr more fully.
|
||||||
v, ok = clients.ipToRC.Get(ip)
|
ipAddr, err := netutil.IPToAddrNoMapped(ip)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, false
|
log.Error("clients: bad client ip %v: %s", ip, err)
|
||||||
}
|
|
||||||
|
|
||||||
rc, ok = v.(*RuntimeClient)
|
|
||||||
if !ok {
|
|
||||||
log.Error("clients: bad type %T in ipToRC for %s", v, ip)
|
|
||||||
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc, true
|
rc, ok = clients.ipToRC[ipAddr]
|
||||||
|
|
||||||
|
return rc, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindRuntimeClient finds a runtime client by their IP.
|
// FindRuntimeClient finds a runtime client by their IP.
|
||||||
|
@ -782,7 +776,15 @@ func (clients *clientsContainer) SetWHOISInfo(ip net.IP, wi *RuntimeClientWHOISI
|
||||||
|
|
||||||
rc.WHOISInfo = wi
|
rc.WHOISInfo = wi
|
||||||
|
|
||||||
clients.ipToRC.Set(ip, rc)
|
// TODO(a.garipov): Remove once we switch to netip.Addr more fully.
|
||||||
|
ipAddr, err := netutil.IPToAddrNoMapped(ip)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("clients: bad client ip %v: %s", ip, err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
clients.ipToRC[ipAddr] = 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)
|
||||||
}
|
}
|
||||||
|
@ -813,10 +815,18 @@ func (clients *clientsContainer) addHostLocked(ip net.IP, host string, src clien
|
||||||
WHOISInfo: &RuntimeClientWHOISInfo{},
|
WHOISInfo: &RuntimeClientWHOISInfo{},
|
||||||
}
|
}
|
||||||
|
|
||||||
clients.ipToRC.Set(ip, rc)
|
// TODO(a.garipov): Remove once we switch to netip.Addr more fully.
|
||||||
|
ipAddr, err := netutil.IPToAddrNoMapped(ip)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("clients: bad client ip %v: %s", ip, err)
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("clients: added %s -> %q [%d]", ip, host, clients.ipToRC.Len())
|
clients.ipToRC[ipAddr] = rc
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("clients: added %s -> %q [%d]", ip, host, len(clients.ipToRC))
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -824,27 +834,20 @@ func (clients *clientsContainer) addHostLocked(ip net.IP, host string, src clien
|
||||||
// rmHostsBySrc removes all entries that match the specified source.
|
// rmHostsBySrc removes all entries that match the specified source.
|
||||||
func (clients *clientsContainer) rmHostsBySrc(src clientSource) {
|
func (clients *clientsContainer) rmHostsBySrc(src clientSource) {
|
||||||
n := 0
|
n := 0
|
||||||
clients.ipToRC.Range(func(ip net.IP, v any) (cont bool) {
|
for ip, rc := range clients.ipToRC {
|
||||||
rc, ok := v.(*RuntimeClient)
|
|
||||||
if !ok {
|
|
||||||
log.Error("clients: bad type %T in ipToRC for %s", v, ip)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if rc.Source == src {
|
if rc.Source == src {
|
||||||
clients.ipToRC.Del(ip)
|
delete(clients.ipToRC, ip)
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
log.Debug("clients: removed %d client aliases", n)
|
log.Debug("clients: removed %d client aliases", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addFromHostsFile fills the client-hostname pairing index from the system's
|
// addFromHostsFile fills the client-hostname pairing index from the system's
|
||||||
// hosts files.
|
// hosts files.
|
||||||
|
//
|
||||||
|
//lint:ignore SA1019 TODO(a.garipov): Replace [*netutil.IPMap].
|
||||||
func (clients *clientsContainer) addFromHostsFile(hosts *netutil.IPMap) {
|
func (clients *clientsContainer) addFromHostsFile(hosts *netutil.IPMap) {
|
||||||
clients.lock.Lock()
|
clients.lock.Lock()
|
||||||
defer clients.lock.Unlock()
|
defer clients.lock.Unlock()
|
||||||
|
@ -855,7 +858,7 @@ func (clients *clientsContainer) addFromHostsFile(hosts *netutil.IPMap) {
|
||||||
hosts.Range(func(ip net.IP, v any) (cont bool) {
|
hosts.Range(func(ip net.IP, v any) (cont bool) {
|
||||||
rec, ok := v.(*aghnet.HostsRecord)
|
rec, ok := v.(*aghnet.HostsRecord)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("dns: bad type %T in ipToRC for %s", v, ip)
|
log.Error("clients: bad type %T in hosts for %s", v, ip)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,38 +202,30 @@ func TestClientsWHOIS(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("new_client", func(t *testing.T) {
|
t.Run("new_client", func(t *testing.T) {
|
||||||
ip := net.IP{1, 1, 1, 255}
|
ip := netip.MustParseAddr("1.1.1.255")
|
||||||
clients.SetWHOISInfo(ip, whois)
|
clients.SetWHOISInfo(ip.AsSlice(), whois)
|
||||||
v, _ := clients.ipToRC.Get(ip)
|
rc := clients.ipToRC[ip]
|
||||||
require.NotNil(t, v)
|
|
||||||
|
|
||||||
rc, ok := v.(*RuntimeClient)
|
|
||||||
require.True(t, ok)
|
|
||||||
require.NotNil(t, rc)
|
require.NotNil(t, rc)
|
||||||
|
|
||||||
assert.Equal(t, rc.WHOISInfo, whois)
|
assert.Equal(t, rc.WHOISInfo, whois)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("existing_auto-client", func(t *testing.T) {
|
t.Run("existing_auto-client", func(t *testing.T) {
|
||||||
ip := net.IP{1, 1, 1, 1}
|
ip := netip.MustParseAddr("1.1.1.1")
|
||||||
ok, err := clients.AddHost(ip, "host", ClientSourceRDNS)
|
ok, err := clients.AddHost(ip.AsSlice(), "host", ClientSourceRDNS)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
clients.SetWHOISInfo(ip, whois)
|
clients.SetWHOISInfo(ip.AsSlice(), whois)
|
||||||
v, _ := clients.ipToRC.Get(ip)
|
rc := clients.ipToRC[ip]
|
||||||
require.NotNil(t, v)
|
|
||||||
|
|
||||||
rc, ok := v.(*RuntimeClient)
|
|
||||||
require.True(t, ok)
|
|
||||||
require.NotNil(t, rc)
|
require.NotNil(t, rc)
|
||||||
|
|
||||||
assert.Equal(t, rc.WHOISInfo, whois)
|
assert.Equal(t, rc.WHOISInfo, whois)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("can't_set_manually-added", func(t *testing.T) {
|
t.Run("can't_set_manually-added", func(t *testing.T) {
|
||||||
ip := net.IP{1, 1, 1, 2}
|
ip := netip.MustParseAddr("1.1.1.2")
|
||||||
|
|
||||||
ok, err := clients.Add(&Client{
|
ok, err := clients.Add(&Client{
|
||||||
IDs: []string{"1.1.1.2"},
|
IDs: []string{"1.1.1.2"},
|
||||||
|
@ -242,9 +234,9 @@ func TestClientsWHOIS(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
clients.SetWHOISInfo(ip, whois)
|
clients.SetWHOISInfo(ip.AsSlice(), whois)
|
||||||
v, _ := clients.ipToRC.Get(ip)
|
rc := clients.ipToRC[ip]
|
||||||
require.Nil(t, v)
|
require.Nil(t, rc)
|
||||||
|
|
||||||
assert.True(t, clients.Del("client1"))
|
assert.True(t, clients.Del("client1"))
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// clientJSON is a common structure used by several handlers to deal with
|
// clientJSON is a common structure used by several handlers to deal with
|
||||||
|
@ -70,26 +69,17 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||||
data.Clients = append(data.Clients, cj)
|
data.Clients = append(data.Clients, cj)
|
||||||
}
|
}
|
||||||
|
|
||||||
clients.ipToRC.Range(func(ip net.IP, v any) (cont bool) {
|
for ip, rc := range clients.ipToRC {
|
||||||
rc, ok := v.(*RuntimeClient)
|
|
||||||
if !ok {
|
|
||||||
log.Error("dns: bad type %T in ipToRC for %s", v, ip)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
cj := runtimeClientJSON{
|
cj := runtimeClientJSON{
|
||||||
WHOISInfo: rc.WHOISInfo,
|
WHOISInfo: rc.WHOISInfo,
|
||||||
|
|
||||||
Name: rc.Host,
|
Name: rc.Host,
|
||||||
Source: rc.Source,
|
Source: rc.Source,
|
||||||
IP: ip,
|
IP: ip.AsSlice(),
|
||||||
}
|
}
|
||||||
|
|
||||||
data.RuntimeClients = append(data.RuntimeClients, cj)
|
data.RuntimeClients = append(data.RuntimeClients, cj)
|
||||||
|
}
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
data.Tags = clientTags
|
data.Tags = clientTags
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -88,7 +89,7 @@ func TestRDNS_Begin(t *testing.T) {
|
||||||
clients: &clientsContainer{
|
clients: &clientsContainer{
|
||||||
list: map[string]*Client{},
|
list: map[string]*Client{},
|
||||||
idIndex: tc.cliIDIndex,
|
idIndex: tc.cliIDIndex,
|
||||||
ipToRC: netutil.NewIPMap(0),
|
ipToRC: map[netip.Addr]*RuntimeClient{},
|
||||||
allTags: stringutil.NewSet(),
|
allTags: stringutil.NewSet(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -228,7 +229,7 @@ func TestRDNS_WorkerLoop(t *testing.T) {
|
||||||
cc := &clientsContainer{
|
cc := &clientsContainer{
|
||||||
list: map[string]*Client{},
|
list: map[string]*Client{},
|
||||||
idIndex: map[string]*Client{},
|
idIndex: map[string]*Client{},
|
||||||
ipToRC: netutil.NewIPMap(0),
|
ipToRC: map[netip.Addr]*RuntimeClient{},
|
||||||
allTags: stringutil.NewSet(),
|
allTags: stringutil.NewSet(),
|
||||||
}
|
}
|
||||||
ch := make(chan net.IP)
|
ch := make(chan net.IP)
|
||||||
|
|
Loading…
Reference in a new issue