mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-12 20:31:17 +08:00
chore: code cleanup
This commit is contained in:
parent
16c95fca87
commit
f5834dd5e2
@ -51,3 +51,23 @@ func UnMasked(p netip.Prefix) netip.Addr {
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PrefixCompare returns an integer comparing two prefixes.
|
||||
// The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
|
||||
// modify from https://github.com/golang/go/issues/61642#issuecomment-1848587909
|
||||
func PrefixCompare(p, p2 netip.Prefix) int {
|
||||
// compare by validity, address family and prefix base address
|
||||
if c := p.Masked().Addr().Compare(p2.Masked().Addr()); c != 0 {
|
||||
return c
|
||||
}
|
||||
// compare by prefix length
|
||||
f1, f2 := p.Bits(), p2.Bits()
|
||||
if f1 < f2 {
|
||||
return -1
|
||||
}
|
||||
if f1 > f2 {
|
||||
return 1
|
||||
}
|
||||
// compare by prefix address
|
||||
return p.Addr().Compare(p2.Addr())
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ func ApplyConfig(cfg *config.Config, force bool) {
|
||||
}
|
||||
}
|
||||
|
||||
updateExperimental(cfg)
|
||||
updateUsers(cfg.Users)
|
||||
updateProxies(cfg.Proxies, cfg.Providers)
|
||||
updateRules(cfg.Rules, cfg.SubRules, cfg.RuleProviders)
|
||||
@ -100,8 +101,6 @@ func ApplyConfig(cfg *config.Config, force bool) {
|
||||
updateDNS(cfg.DNS, cfg.General.IPv6)
|
||||
updateListeners(cfg.General, cfg.Listeners, force)
|
||||
updateIPTables(cfg)
|
||||
updateTun(cfg.General)
|
||||
updateExperimental(cfg)
|
||||
updateTunnels(cfg.Tunnels)
|
||||
|
||||
tunnel.OnInnerLoading()
|
||||
@ -186,6 +185,7 @@ func updateListeners(general *config.General, listeners map[string]C.InboundList
|
||||
listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel)
|
||||
listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel)
|
||||
listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel)
|
||||
listener.ReCreateTun(general.Tun, tunnel.Tunnel)
|
||||
}
|
||||
|
||||
func updateExperimental(c *config.Config) {
|
||||
@ -343,12 +343,6 @@ func hcCompatibleProvider(proxyProviders map[string]provider.ProxyProvider) {
|
||||
}
|
||||
|
||||
}
|
||||
func updateTun(general *config.General) {
|
||||
if general == nil {
|
||||
return
|
||||
}
|
||||
listener.ReCreateTun(general.Tun, tunnel.Tunnel)
|
||||
}
|
||||
|
||||
func updateSniffer(sniffer *config.Sniffer) {
|
||||
if sniffer.Enable {
|
||||
|
@ -62,7 +62,6 @@ type tunSchema struct {
|
||||
DNSHijack *[]string `yaml:"dns-hijack" json:"dns-hijack"`
|
||||
AutoRoute *bool `yaml:"auto-route" json:"auto-route"`
|
||||
AutoDetectInterface *bool `yaml:"auto-detect-interface" json:"auto-detect-interface"`
|
||||
//RedirectToTun []string `yaml:"-" json:"-"`
|
||||
|
||||
MTU *uint32 `yaml:"mtu" json:"mtu,omitempty"`
|
||||
GSO *bool `yaml:"gso" json:"gso,omitempty"`
|
||||
@ -118,21 +117,13 @@ func getConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
render.JSON(w, r, general)
|
||||
}
|
||||
|
||||
func pointerOrDefault(p *int, def int) int {
|
||||
func pointerOrDefault[T any](p *T, def T) T {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func pointerOrDefaultString(p *string, def string) string {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
|
||||
return def
|
||||
}
|
||||
|
||||
func pointerOrDefaultTun(p *tunSchema, def LC.Tun) LC.Tun {
|
||||
if p != nil {
|
||||
def.Enable = p.Enable
|
||||
@ -336,8 +327,8 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
P.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tunnel.Tunnel)
|
||||
P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tunnel.Tunnel)
|
||||
P.ReCreateTun(pointerOrDefaultTun(general.Tun, P.LastTunConf), tunnel.Tunnel)
|
||||
P.ReCreateShadowSocks(pointerOrDefaultString(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel)
|
||||
P.ReCreateVmess(pointerOrDefaultString(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel)
|
||||
P.ReCreateShadowSocks(pointerOrDefault(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel)
|
||||
P.ReCreateVmess(pointerOrDefault(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel)
|
||||
P.ReCreateTuic(pointerOrDefaultTuicServer(general.TuicServer, P.LastTuicConf), tunnel.Tunnel)
|
||||
|
||||
if general.Mode != nil {
|
||||
|
@ -3,7 +3,10 @@ package config
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/metacubex/mihomo/common/nnip"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
func StringSliceToNetipPrefixSlice(ss []string) ([]netip.Prefix, error) {
|
||||
@ -25,7 +28,6 @@ type Tun struct {
|
||||
DNSHijack []string `yaml:"dns-hijack" json:"dns-hijack"`
|
||||
AutoRoute bool `yaml:"auto-route" json:"auto-route"`
|
||||
AutoDetectInterface bool `yaml:"auto-detect-interface" json:"auto-detect-interface"`
|
||||
RedirectToTun []string `yaml:"-" json:"-"`
|
||||
|
||||
MTU uint32 `yaml:"mtu" json:"mtu,omitempty"`
|
||||
GSO bool `yaml:"gso" json:"gso,omitempty"`
|
||||
@ -60,3 +62,146 @@ type Tun struct {
|
||||
Inet4RouteExcludeAddress []netip.Prefix `yaml:"inet4-route-exclude-address" json:"inet4-route-exclude-address,omitempty"`
|
||||
Inet6RouteExcludeAddress []netip.Prefix `yaml:"inet6-route-exclude-address" json:"inet6-route-exclude-address,omitempty"`
|
||||
}
|
||||
|
||||
func (t *Tun) Sort() {
|
||||
slices.Sort(t.DNSHijack)
|
||||
|
||||
slices.SortFunc(t.Inet4Address, nnip.PrefixCompare)
|
||||
slices.SortFunc(t.Inet6Address, nnip.PrefixCompare)
|
||||
slices.SortFunc(t.RouteAddress, nnip.PrefixCompare)
|
||||
slices.Sort(t.RouteAddressSet)
|
||||
slices.SortFunc(t.RouteExcludeAddress, nnip.PrefixCompare)
|
||||
slices.Sort(t.RouteExcludeAddressSet)
|
||||
slices.Sort(t.IncludeInterface)
|
||||
slices.Sort(t.ExcludeInterface)
|
||||
slices.Sort(t.IncludeUID)
|
||||
slices.Sort(t.IncludeUIDRange)
|
||||
slices.Sort(t.ExcludeUID)
|
||||
slices.Sort(t.ExcludeUIDRange)
|
||||
slices.Sort(t.IncludeAndroidUser)
|
||||
slices.Sort(t.IncludePackage)
|
||||
slices.Sort(t.ExcludePackage)
|
||||
|
||||
slices.SortFunc(t.Inet4RouteAddress, nnip.PrefixCompare)
|
||||
slices.SortFunc(t.Inet6RouteAddress, nnip.PrefixCompare)
|
||||
slices.SortFunc(t.Inet4RouteExcludeAddress, nnip.PrefixCompare)
|
||||
slices.SortFunc(t.Inet6RouteExcludeAddress, nnip.PrefixCompare)
|
||||
}
|
||||
|
||||
func (t *Tun) Equal(other Tun) bool {
|
||||
if t.Enable != other.Enable {
|
||||
return false
|
||||
}
|
||||
if t.Device != other.Device {
|
||||
return false
|
||||
}
|
||||
if t.Stack != other.Stack {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.DNSHijack, other.DNSHijack) {
|
||||
return false
|
||||
}
|
||||
if t.AutoRoute != other.AutoRoute {
|
||||
return false
|
||||
}
|
||||
if t.AutoDetectInterface != other.AutoDetectInterface {
|
||||
return false
|
||||
}
|
||||
|
||||
if t.MTU != other.MTU {
|
||||
return false
|
||||
}
|
||||
if t.GSO != other.GSO {
|
||||
return false
|
||||
}
|
||||
if t.GSOMaxSize != other.GSOMaxSize {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.Inet4Address, other.Inet4Address) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.Inet6Address, other.Inet6Address) {
|
||||
return false
|
||||
}
|
||||
if t.IPRoute2TableIndex != other.IPRoute2TableIndex {
|
||||
return false
|
||||
}
|
||||
if t.IPRoute2RuleIndex != other.IPRoute2RuleIndex {
|
||||
return false
|
||||
}
|
||||
if t.AutoRedirect != other.AutoRedirect {
|
||||
return false
|
||||
}
|
||||
if t.AutoRedirectInputMark != other.AutoRedirectInputMark {
|
||||
return false
|
||||
}
|
||||
if t.AutoRedirectOutputMark != other.AutoRedirectOutputMark {
|
||||
return false
|
||||
}
|
||||
if t.StrictRoute != other.StrictRoute {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.RouteAddress, other.RouteAddress) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.RouteAddressSet, other.RouteAddressSet) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.RouteExcludeAddress, other.RouteExcludeAddress) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.RouteExcludeAddressSet, other.RouteExcludeAddressSet) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.IncludeInterface, other.IncludeInterface) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.ExcludeInterface, other.ExcludeInterface) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.IncludeUID, other.IncludeUID) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.IncludeUIDRange, other.IncludeUIDRange) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.ExcludeUID, other.ExcludeUID) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.ExcludeUIDRange, other.ExcludeUIDRange) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.IncludeAndroidUser, other.IncludeAndroidUser) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.IncludePackage, other.IncludePackage) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.ExcludePackage, other.ExcludePackage) {
|
||||
return false
|
||||
}
|
||||
if t.EndpointIndependentNat != other.EndpointIndependentNat {
|
||||
return false
|
||||
}
|
||||
if t.UDPTimeout != other.UDPTimeout {
|
||||
return false
|
||||
}
|
||||
if t.FileDescriptor != other.FileDescriptor {
|
||||
return false
|
||||
}
|
||||
|
||||
if !slices.Equal(t.Inet4RouteAddress, other.Inet4RouteAddress) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.Inet6RouteAddress, other.Inet6RouteAddress) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.Inet4RouteExcludeAddress, other.Inet4RouteExcludeAddress) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(t.Inet6RouteExcludeAddress, other.Inet6RouteExcludeAddress) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -2,9 +2,7 @@ package listener
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/exp/slices"
|
||||
"net"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -49,19 +47,17 @@ var (
|
||||
tuicListener *tuic.Listener
|
||||
|
||||
// lock for recreate function
|
||||
socksMux sync.Mutex
|
||||
httpMux sync.Mutex
|
||||
redirMux sync.Mutex
|
||||
tproxyMux sync.Mutex
|
||||
mixedMux sync.Mutex
|
||||
tunnelMux sync.Mutex
|
||||
inboundMux sync.Mutex
|
||||
tunMux sync.Mutex
|
||||
ssMux sync.Mutex
|
||||
vmessMux sync.Mutex
|
||||
tuicMux sync.Mutex
|
||||
autoRedirMux sync.Mutex
|
||||
tcMux sync.Mutex
|
||||
socksMux sync.Mutex
|
||||
httpMux sync.Mutex
|
||||
redirMux sync.Mutex
|
||||
tproxyMux sync.Mutex
|
||||
mixedMux sync.Mutex
|
||||
tunnelMux sync.Mutex
|
||||
inboundMux sync.Mutex
|
||||
tunMux sync.Mutex
|
||||
ssMux sync.Mutex
|
||||
vmessMux sync.Mutex
|
||||
tuicMux sync.Mutex
|
||||
|
||||
LastTunConf LC.Tun
|
||||
LastTuicConf LC.TuicServer
|
||||
@ -499,6 +495,8 @@ func ReCreateMixed(port int, tunnel C.Tunnel) {
|
||||
}
|
||||
|
||||
func ReCreateTun(tunConf LC.Tun, tunnel C.Tunnel) {
|
||||
tunConf.Sort()
|
||||
|
||||
tunMux.Lock()
|
||||
defer func() {
|
||||
LastTunConf = tunConf
|
||||
@ -513,7 +511,7 @@ func ReCreateTun(tunConf LC.Tun, tunnel C.Tunnel) {
|
||||
}
|
||||
}()
|
||||
|
||||
if !hasTunConfigChange(&tunConf) {
|
||||
if tunConf.Equal(LastTunConf) {
|
||||
if tunLister != nil {
|
||||
tunLister.FlushDefaultInterface()
|
||||
}
|
||||
@ -717,137 +715,6 @@ func genAddr(host string, port int, allowLan bool) string {
|
||||
return fmt.Sprintf("127.0.0.1:%d", port)
|
||||
}
|
||||
|
||||
func hasTunConfigChange(tunConf *LC.Tun) bool {
|
||||
if LastTunConf.Enable != tunConf.Enable ||
|
||||
LastTunConf.Device != tunConf.Device ||
|
||||
LastTunConf.Stack != tunConf.Stack ||
|
||||
LastTunConf.AutoRoute != tunConf.AutoRoute ||
|
||||
LastTunConf.AutoDetectInterface != tunConf.AutoDetectInterface ||
|
||||
LastTunConf.MTU != tunConf.MTU ||
|
||||
LastTunConf.GSO != tunConf.GSO ||
|
||||
LastTunConf.GSOMaxSize != tunConf.GSOMaxSize ||
|
||||
LastTunConf.IPRoute2TableIndex != tunConf.IPRoute2TableIndex ||
|
||||
LastTunConf.IPRoute2RuleIndex != tunConf.IPRoute2RuleIndex ||
|
||||
LastTunConf.AutoRedirect != tunConf.AutoRedirect ||
|
||||
LastTunConf.AutoRedirectInputMark != tunConf.AutoRedirectInputMark ||
|
||||
LastTunConf.AutoRedirectOutputMark != tunConf.AutoRedirectOutputMark ||
|
||||
LastTunConf.StrictRoute != tunConf.StrictRoute ||
|
||||
LastTunConf.EndpointIndependentNat != tunConf.EndpointIndependentNat ||
|
||||
LastTunConf.UDPTimeout != tunConf.UDPTimeout ||
|
||||
LastTunConf.FileDescriptor != tunConf.FileDescriptor {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(LastTunConf.DNSHijack) != len(tunConf.DNSHijack) {
|
||||
return true
|
||||
}
|
||||
|
||||
sort.Slice(tunConf.DNSHijack, func(i, j int) bool {
|
||||
return tunConf.DNSHijack[i] < tunConf.DNSHijack[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.RouteAddress, func(i, j int) bool {
|
||||
return tunConf.RouteAddress[i].String() < tunConf.RouteAddress[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.RouteAddressSet, func(i, j int) bool {
|
||||
return tunConf.RouteAddressSet[i] < tunConf.RouteAddressSet[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.RouteExcludeAddress, func(i, j int) bool {
|
||||
return tunConf.RouteExcludeAddress[i].String() < tunConf.RouteExcludeAddress[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.RouteExcludeAddressSet, func(i, j int) bool {
|
||||
return tunConf.RouteExcludeAddressSet[i] < tunConf.RouteExcludeAddressSet[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.Inet4Address, func(i, j int) bool {
|
||||
return tunConf.Inet4Address[i].String() < tunConf.Inet4Address[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.Inet6Address, func(i, j int) bool {
|
||||
return tunConf.Inet6Address[i].String() < tunConf.Inet6Address[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.Inet4RouteAddress, func(i, j int) bool {
|
||||
return tunConf.Inet4RouteAddress[i].String() < tunConf.Inet4RouteAddress[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.Inet6RouteAddress, func(i, j int) bool {
|
||||
return tunConf.Inet6RouteAddress[i].String() < tunConf.Inet6RouteAddress[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.Inet4RouteExcludeAddress, func(i, j int) bool {
|
||||
return tunConf.Inet4RouteExcludeAddress[i].String() < tunConf.Inet4RouteExcludeAddress[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.Inet6RouteExcludeAddress, func(i, j int) bool {
|
||||
return tunConf.Inet6RouteExcludeAddress[i].String() < tunConf.Inet6RouteExcludeAddress[j].String()
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.IncludeInterface, func(i, j int) bool {
|
||||
return tunConf.IncludeInterface[i] < tunConf.IncludeInterface[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.ExcludeInterface, func(i, j int) bool {
|
||||
return tunConf.ExcludeInterface[i] < tunConf.ExcludeInterface[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.IncludeUID, func(i, j int) bool {
|
||||
return tunConf.IncludeUID[i] < tunConf.IncludeUID[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.IncludeUIDRange, func(i, j int) bool {
|
||||
return tunConf.IncludeUIDRange[i] < tunConf.IncludeUIDRange[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.ExcludeUID, func(i, j int) bool {
|
||||
return tunConf.ExcludeUID[i] < tunConf.ExcludeUID[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.ExcludeUIDRange, func(i, j int) bool {
|
||||
return tunConf.ExcludeUIDRange[i] < tunConf.ExcludeUIDRange[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.IncludeAndroidUser, func(i, j int) bool {
|
||||
return tunConf.IncludeAndroidUser[i] < tunConf.IncludeAndroidUser[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.IncludePackage, func(i, j int) bool {
|
||||
return tunConf.IncludePackage[i] < tunConf.IncludePackage[j]
|
||||
})
|
||||
|
||||
sort.Slice(tunConf.ExcludePackage, func(i, j int) bool {
|
||||
return tunConf.ExcludePackage[i] < tunConf.ExcludePackage[j]
|
||||
})
|
||||
|
||||
if !slices.Equal(tunConf.DNSHijack, LastTunConf.DNSHijack) ||
|
||||
!slices.Equal(tunConf.RouteAddress, LastTunConf.RouteAddress) ||
|
||||
!slices.Equal(tunConf.RouteAddressSet, LastTunConf.RouteAddressSet) ||
|
||||
!slices.Equal(tunConf.RouteExcludeAddress, LastTunConf.RouteExcludeAddress) ||
|
||||
!slices.Equal(tunConf.RouteExcludeAddressSet, LastTunConf.RouteExcludeAddressSet) ||
|
||||
!slices.Equal(tunConf.Inet4Address, LastTunConf.Inet4Address) ||
|
||||
!slices.Equal(tunConf.Inet6Address, LastTunConf.Inet6Address) ||
|
||||
!slices.Equal(tunConf.Inet4RouteAddress, LastTunConf.Inet4RouteAddress) ||
|
||||
!slices.Equal(tunConf.Inet6RouteAddress, LastTunConf.Inet6RouteAddress) ||
|
||||
!slices.Equal(tunConf.Inet4RouteExcludeAddress, LastTunConf.Inet4RouteExcludeAddress) ||
|
||||
!slices.Equal(tunConf.Inet6RouteExcludeAddress, LastTunConf.Inet6RouteExcludeAddress) ||
|
||||
!slices.Equal(tunConf.IncludeInterface, LastTunConf.IncludeInterface) ||
|
||||
!slices.Equal(tunConf.ExcludeInterface, LastTunConf.ExcludeInterface) ||
|
||||
!slices.Equal(tunConf.IncludeUID, LastTunConf.IncludeUID) ||
|
||||
!slices.Equal(tunConf.IncludeUIDRange, LastTunConf.IncludeUIDRange) ||
|
||||
!slices.Equal(tunConf.ExcludeUID, LastTunConf.ExcludeUID) ||
|
||||
!slices.Equal(tunConf.ExcludeUIDRange, LastTunConf.ExcludeUIDRange) ||
|
||||
!slices.Equal(tunConf.IncludeAndroidUser, LastTunConf.IncludeAndroidUser) ||
|
||||
!slices.Equal(tunConf.IncludePackage, LastTunConf.IncludePackage) ||
|
||||
!slices.Equal(tunConf.ExcludePackage, LastTunConf.ExcludePackage) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func closeTunListener() {
|
||||
if tunLister != nil {
|
||||
tunLister.Close()
|
||||
|
Loading…
Reference in New Issue
Block a user