mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-03 05:24:56 +01:00
c590518e0c
Support exit node on Android. With the protect socket function, we mark every connection that should be used out of VPN.
190 lines
5.4 KiB
Go
190 lines
5.4 KiB
Go
//go:build android
|
|
|
|
package android
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/netbirdio/netbird/client/internal"
|
|
"github.com/netbirdio/netbird/client/internal/dns"
|
|
"github.com/netbirdio/netbird/client/internal/listener"
|
|
"github.com/netbirdio/netbird/client/internal/peer"
|
|
"github.com/netbirdio/netbird/client/internal/stdnet"
|
|
"github.com/netbirdio/netbird/client/system"
|
|
"github.com/netbirdio/netbird/formatter"
|
|
"github.com/netbirdio/netbird/iface"
|
|
"github.com/netbirdio/netbird/util/net"
|
|
)
|
|
|
|
// ConnectionListener export internal Listener for mobile
|
|
type ConnectionListener interface {
|
|
peer.Listener
|
|
}
|
|
|
|
// TunAdapter export internal TunAdapter for mobile
|
|
type TunAdapter interface {
|
|
iface.TunAdapter
|
|
}
|
|
|
|
// IFaceDiscover export internal IFaceDiscover for mobile
|
|
type IFaceDiscover interface {
|
|
stdnet.ExternalIFaceDiscover
|
|
}
|
|
|
|
// NetworkChangeListener export internal NetworkChangeListener for mobile
|
|
type NetworkChangeListener interface {
|
|
listener.NetworkChangeListener
|
|
}
|
|
|
|
// DnsReadyListener export internal dns ReadyListener for mobile
|
|
type DnsReadyListener interface {
|
|
dns.ReadyListener
|
|
}
|
|
|
|
func init() {
|
|
formatter.SetLogcatFormatter(log.StandardLogger())
|
|
}
|
|
|
|
// Client struct manage the life circle of background service
|
|
type Client struct {
|
|
cfgFile string
|
|
tunAdapter iface.TunAdapter
|
|
iFaceDiscover IFaceDiscover
|
|
recorder *peer.Status
|
|
ctxCancel context.CancelFunc
|
|
ctxCancelLock *sync.Mutex
|
|
deviceName string
|
|
networkChangeListener listener.NetworkChangeListener
|
|
}
|
|
|
|
// NewClient instantiate a new Client
|
|
func NewClient(cfgFile, deviceName string, tunAdapter TunAdapter, iFaceDiscover IFaceDiscover, networkChangeListener NetworkChangeListener) *Client {
|
|
net.SetAndroidProtectSocketFn(tunAdapter.ProtectSocket)
|
|
return &Client{
|
|
cfgFile: cfgFile,
|
|
deviceName: deviceName,
|
|
tunAdapter: tunAdapter,
|
|
iFaceDiscover: iFaceDiscover,
|
|
recorder: peer.NewRecorder(""),
|
|
ctxCancelLock: &sync.Mutex{},
|
|
networkChangeListener: networkChangeListener,
|
|
}
|
|
}
|
|
|
|
// Run start the internal client. It is a blocker function
|
|
func (c *Client) Run(urlOpener URLOpener, dns *DNSList, dnsReadyListener DnsReadyListener) error {
|
|
cfg, err := internal.UpdateOrCreateConfig(internal.ConfigInput{
|
|
ConfigPath: c.cfgFile,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.recorder.UpdateManagementAddress(cfg.ManagementURL.String())
|
|
c.recorder.UpdateRosenpass(cfg.RosenpassEnabled, cfg.RosenpassPermissive)
|
|
|
|
var ctx context.Context
|
|
//nolint
|
|
ctxWithValues := context.WithValue(context.Background(), system.DeviceNameCtxKey, c.deviceName)
|
|
c.ctxCancelLock.Lock()
|
|
ctx, c.ctxCancel = context.WithCancel(ctxWithValues)
|
|
defer c.ctxCancel()
|
|
c.ctxCancelLock.Unlock()
|
|
|
|
auth := NewAuthWithConfig(ctx, cfg)
|
|
err = auth.login(urlOpener)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// todo do not throw error in case of cancelled context
|
|
ctx = internal.CtxInitState(ctx)
|
|
return internal.RunClientMobile(ctx, cfg, c.recorder, c.tunAdapter, c.iFaceDiscover, c.networkChangeListener, dns.items, dnsReadyListener)
|
|
}
|
|
|
|
// RunWithoutLogin we apply this type of run function when the backed has been started without UI (i.e. after reboot).
|
|
// In this case make no sense handle registration steps.
|
|
func (c *Client) RunWithoutLogin(dns *DNSList, dnsReadyListener DnsReadyListener) error {
|
|
cfg, err := internal.UpdateOrCreateConfig(internal.ConfigInput{
|
|
ConfigPath: c.cfgFile,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.recorder.UpdateManagementAddress(cfg.ManagementURL.String())
|
|
c.recorder.UpdateRosenpass(cfg.RosenpassEnabled, cfg.RosenpassPermissive)
|
|
|
|
var ctx context.Context
|
|
//nolint
|
|
ctxWithValues := context.WithValue(context.Background(), system.DeviceNameCtxKey, c.deviceName)
|
|
c.ctxCancelLock.Lock()
|
|
ctx, c.ctxCancel = context.WithCancel(ctxWithValues)
|
|
defer c.ctxCancel()
|
|
c.ctxCancelLock.Unlock()
|
|
|
|
// todo do not throw error in case of cancelled context
|
|
ctx = internal.CtxInitState(ctx)
|
|
return internal.RunClientMobile(ctx, cfg, c.recorder, c.tunAdapter, c.iFaceDiscover, c.networkChangeListener, dns.items, dnsReadyListener)
|
|
}
|
|
|
|
// Stop the internal client and free the resources
|
|
func (c *Client) Stop() {
|
|
c.ctxCancelLock.Lock()
|
|
defer c.ctxCancelLock.Unlock()
|
|
if c.ctxCancel == nil {
|
|
return
|
|
}
|
|
|
|
c.ctxCancel()
|
|
}
|
|
|
|
// SetTraceLogLevel configure the logger to trace level
|
|
func (c *Client) SetTraceLogLevel() {
|
|
log.SetLevel(log.TraceLevel)
|
|
}
|
|
|
|
// SetInfoLogLevel configure the logger to info level
|
|
func (c *Client) SetInfoLogLevel() {
|
|
log.SetLevel(log.InfoLevel)
|
|
}
|
|
|
|
// PeersList return with the list of the PeerInfos
|
|
func (c *Client) PeersList() *PeerInfoArray {
|
|
|
|
fullStatus := c.recorder.GetFullStatus()
|
|
|
|
peerInfos := make([]PeerInfo, len(fullStatus.Peers))
|
|
for n, p := range fullStatus.Peers {
|
|
pi := PeerInfo{
|
|
p.IP,
|
|
p.FQDN,
|
|
p.ConnStatus.String(),
|
|
}
|
|
peerInfos[n] = pi
|
|
}
|
|
return &PeerInfoArray{items: peerInfos}
|
|
}
|
|
|
|
// OnUpdatedHostDNS update the DNS servers addresses for root zones
|
|
func (c *Client) OnUpdatedHostDNS(list *DNSList) error {
|
|
dnsServer, err := dns.GetServerDns()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
dnsServer.OnUpdatedHostDNSServer(list.items)
|
|
return nil
|
|
}
|
|
|
|
// SetConnectionListener set the network connection listener
|
|
func (c *Client) SetConnectionListener(listener ConnectionListener) {
|
|
c.recorder.SetConnectionListener(listener)
|
|
}
|
|
|
|
// RemoveConnectionListener remove connection listener
|
|
func (c *Client) RemoveConnectionListener() {
|
|
c.recorder.RemoveConnectionListener()
|
|
}
|