ifupdown/ifaces.go

108 lines
2.2 KiB
Go
Raw Normal View History

2023-12-02 04:26:14 +00:00
package iface
import (
"bufio"
2023-12-02 07:24:28 +00:00
"fmt"
2023-12-02 04:26:14 +00:00
"strings"
2023-12-02 07:24:28 +00:00
"sync"
2023-12-02 04:26:14 +00:00
"git.tcp.direct/kayos/common/pool"
)
type poolGroup struct {
Buffers pool.BufferFactory
Strs pool.StringFactory
}
var pools = poolGroup{Buffers: pool.NewBufferFactory(), Strs: pool.NewStringFactory()}
type MultiParser struct {
Interfaces map[string]*NetworkInterface
Errs []error
buf []byte
}
func NewMultiParser() *MultiParser {
return &MultiParser{
Interfaces: make(map[string]*NetworkInterface),
Errs: make([]error, 0),
buf: make([]byte, 0),
}
}
func (p *MultiParser) Write(data []byte) (int, error) {
p.buf = append(p.buf, data...)
return len(data), nil
}
func (p *MultiParser) Parse() error {
scanner := bufio.NewScanner(strings.NewReader(string(p.buf)))
index := 0
currentIfaceName := ""
buf := pools.Buffers.Get()
defer pools.Buffers.MustPut(buf)
flush := func(name string) (*NetworkInterface, bool) {
if len(buf.Bytes()) == 0 {
return nil, false
}
defer buf.MustReset()
newIface := NewNetworkInterface(name)
if _, err := buf.WriteTo(newIface); err != nil {
p.Errs = append(p.Errs, err)
return nil, false
}
p.Interfaces[newIface.Name] = newIface
return newIface, true
}
w := func(s string) {
_, _ = buf.WriteString(s)
_ = buf.WriteByte('\n')
}
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
upForChange := currentIfaceName == "" ||
(currentIfaceName != "" && !strings.Contains(line, currentIfaceName)) ||
index == 0
startDetected := len(strings.Fields(line)) > 1 &&
(strings.HasPrefix(line, "auto") ||
strings.HasPrefix(line, "allow-") ||
strings.HasPrefix(line, "iface"))
switch {
case line == "", strings.HasPrefix(line, "#"):
continue
case upForChange && startDetected:
newName := strings.Fields(line)[1]
if ifa, ok := flush(newName); ok {
currentIfaceName = ifa.Name
index++
}
w(line)
continue
default:
w(line)
}
}
if len(buf.Bytes()) > 0 {
flush("unknown")
}
2023-12-02 07:24:28 +00:00
var multiErr error
2023-12-02 04:26:14 +00:00
for _, err := range p.Errs {
2023-12-02 07:24:28 +00:00
switch {
case err == nil:
continue
case multiErr == nil:
multiErr = err
default:
multiErr = fmt.Errorf("%w, %w", multiErr, err)
2023-12-02 04:26:14 +00:00
}
}
2023-12-02 07:24:28 +00:00
return p.Interfaces, multiErr
2023-12-02 04:26:14 +00:00
}