mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-01-18 03:28:19 +01:00
network enhanecment / refactor (#361)
* chore(network): improve connectivity check * refactor(network): rewrite network and timesync component * feat(display): show cloud connection status * chore: change logging verbosity * chore(websecure): update log message * fix(ota): validate root certificate when downloading update * feat(ui): add network settings tab * fix(display): cloud connecting animation * fix: golintci issues * feat: add network settings tab * feat(timesync): query servers in parallel * refactor(network): move to internal/network package * feat(timesync): add metrics * refactor(log): move log to internal/logging package * refactor(mdms): move mdns to internal/mdns package * feat(developer): add pprof endpoint * feat(logging): add a simple logging streaming endpoint * fix(mdns): do not start mdns until network is up * feat(network): allow users to update network settings from ui * fix(network): handle errors when net.IPAddr is nil * fix(mdns): scopedLogger SIGSEGV * fix(dhcp): watch directory instead of file to catch fsnotify.Create event * refactor(nbd): move platform-specific code to different files * refactor(native): move platform-specific code to different files * chore: fix linter issues * chore(dev_deploy): allow to override PION_LOG_TRACE
This commit is contained in:
191
internal/udhcpc/udhcpc.go
Normal file
191
internal/udhcpc/udhcpc.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package udhcpc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const (
|
||||
DHCPLeaseFile = "/run/udhcpc.%s.info"
|
||||
DHCPPidFile = "/run/udhcpc.%s.pid"
|
||||
)
|
||||
|
||||
type DHCPClient struct {
|
||||
InterfaceName string
|
||||
leaseFile string
|
||||
pidFile string
|
||||
lease *Lease
|
||||
logger *zerolog.Logger
|
||||
process *os.Process
|
||||
onLeaseChange func(lease *Lease)
|
||||
}
|
||||
|
||||
type DHCPClientOptions struct {
|
||||
InterfaceName string
|
||||
PidFile string
|
||||
Logger *zerolog.Logger
|
||||
OnLeaseChange func(lease *Lease)
|
||||
}
|
||||
|
||||
var defaultLogger = zerolog.New(os.Stdout).Level(zerolog.InfoLevel)
|
||||
|
||||
func NewDHCPClient(options *DHCPClientOptions) *DHCPClient {
|
||||
if options.Logger == nil {
|
||||
options.Logger = &defaultLogger
|
||||
}
|
||||
|
||||
l := options.Logger.With().Str("interface", options.InterfaceName).Logger()
|
||||
return &DHCPClient{
|
||||
InterfaceName: options.InterfaceName,
|
||||
logger: &l,
|
||||
leaseFile: fmt.Sprintf(DHCPLeaseFile, options.InterfaceName),
|
||||
pidFile: options.PidFile,
|
||||
onLeaseChange: options.OnLeaseChange,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DHCPClient) getWatchPaths() []string {
|
||||
watchPaths := make(map[string]interface{})
|
||||
watchPaths[filepath.Dir(c.leaseFile)] = nil
|
||||
|
||||
if c.pidFile != "" {
|
||||
watchPaths[filepath.Dir(c.pidFile)] = nil
|
||||
}
|
||||
|
||||
paths := make([]string, 0)
|
||||
for path := range watchPaths {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
// Run starts the DHCP client and watches the lease file for changes.
|
||||
// this isn't a blocking call, and the lease file is reloaded when a change is detected.
|
||||
func (c *DHCPClient) Run() error {
|
||||
err := c.loadLeaseFile()
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if !event.Has(fsnotify.Write) && !event.Has(fsnotify.Create) {
|
||||
continue
|
||||
}
|
||||
|
||||
if event.Name == c.leaseFile {
|
||||
c.logger.Debug().
|
||||
Str("event", event.Op.String()).
|
||||
Str("path", event.Name).
|
||||
Msg("udhcpc lease file updated, reloading lease")
|
||||
_ = c.loadLeaseFile()
|
||||
}
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
c.logger.Error().Err(err).Msg("error watching lease file")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for _, path := range c.getWatchPaths() {
|
||||
err = watcher.Add(path)
|
||||
if err != nil {
|
||||
c.logger.Error().
|
||||
Err(err).
|
||||
Str("path", path).
|
||||
Msg("failed to watch directory")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: update udhcpc pid file
|
||||
// we'll comment this out for now because the pid might change
|
||||
// process := c.GetProcess()
|
||||
// if process == nil {
|
||||
// c.logger.Error().Msg("udhcpc process not found")
|
||||
// }
|
||||
|
||||
// block the goroutine until the lease file is updated
|
||||
<-make(chan struct{})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DHCPClient) loadLeaseFile() error {
|
||||
file, err := os.ReadFile(c.leaseFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := string(file)
|
||||
if data == "" {
|
||||
c.logger.Debug().Msg("udhcpc lease file is empty")
|
||||
return nil
|
||||
}
|
||||
|
||||
lease := &Lease{}
|
||||
err = UnmarshalDHCPCLease(lease, string(file))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isFirstLoad := c.lease == nil
|
||||
c.lease = lease
|
||||
|
||||
if lease.IPAddress == nil {
|
||||
c.logger.Info().
|
||||
Interface("lease", lease).
|
||||
Str("data", string(file)).
|
||||
Msg("udhcpc lease cleared")
|
||||
return nil
|
||||
}
|
||||
|
||||
msg := "udhcpc lease updated"
|
||||
if isFirstLoad {
|
||||
msg = "udhcpc lease loaded"
|
||||
}
|
||||
|
||||
leaseExpiry, err := lease.SetLeaseExpiry()
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("failed to get dhcp lease expiry")
|
||||
} else {
|
||||
expiresIn := time.Until(leaseExpiry)
|
||||
c.logger.Info().
|
||||
Interface("expiry", leaseExpiry).
|
||||
Str("expiresIn", expiresIn.String()).
|
||||
Msg("current dhcp lease expiry time calculated")
|
||||
}
|
||||
|
||||
c.onLeaseChange(lease)
|
||||
|
||||
c.logger.Info().
|
||||
Str("ip", lease.IPAddress.String()).
|
||||
Str("leaseTime", lease.LeaseTime.String()).
|
||||
Interface("data", lease).
|
||||
Msg(msg)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DHCPClient) GetLease() *Lease {
|
||||
return c.lease
|
||||
}
|
||||
Reference in New Issue
Block a user