mirror of https://github.com/jetkvm/kvm.git
155 lines
2.9 KiB
Go
155 lines
2.9 KiB
Go
package mdns
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"reflect"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/jetkvm/kvm/internal/logging"
|
|
pion_mdns "github.com/pion/mdns/v2"
|
|
"github.com/rs/zerolog"
|
|
"golang.org/x/net/ipv4"
|
|
"golang.org/x/net/ipv6"
|
|
)
|
|
|
|
type MDNS struct {
|
|
conn *pion_mdns.Conn
|
|
lock sync.Mutex
|
|
l *zerolog.Logger
|
|
|
|
localNames []string
|
|
listenOptions *MDNSListenOptions
|
|
}
|
|
|
|
type MDNSListenOptions struct {
|
|
IPv4 bool
|
|
IPv6 bool
|
|
}
|
|
|
|
type MDNSOptions struct {
|
|
Logger *zerolog.Logger
|
|
LocalNames []string
|
|
ListenOptions *MDNSListenOptions
|
|
}
|
|
|
|
const (
|
|
DefaultAddressIPv4 = pion_mdns.DefaultAddressIPv4
|
|
DefaultAddressIPv6 = pion_mdns.DefaultAddressIPv6
|
|
)
|
|
|
|
func NewMDNS(opts *MDNSOptions) (*MDNS, error) {
|
|
if opts.Logger == nil {
|
|
opts.Logger = logging.GetDefaultLogger()
|
|
}
|
|
|
|
return &MDNS{
|
|
l: opts.Logger,
|
|
lock: sync.Mutex{},
|
|
localNames: opts.LocalNames,
|
|
listenOptions: opts.ListenOptions,
|
|
}, nil
|
|
}
|
|
|
|
func (m *MDNS) start(allowRestart bool) error {
|
|
m.lock.Lock()
|
|
defer m.lock.Unlock()
|
|
|
|
if m.conn != nil {
|
|
if !allowRestart {
|
|
return fmt.Errorf("mDNS server already running")
|
|
}
|
|
|
|
m.conn.Close()
|
|
}
|
|
|
|
addr4, err := net.ResolveUDPAddr("udp4", DefaultAddressIPv4)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
addr6, err := net.ResolveUDPAddr("udp6", DefaultAddressIPv6)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
l4, err := net.ListenUDP("udp4", addr4)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
l6, err := net.ListenUDP("udp6", addr6)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
scopeLogger := m.l.With().Interface("local_names", m.localNames).Logger()
|
|
|
|
newLocalNames := make([]string, len(m.localNames))
|
|
for i, name := range m.localNames {
|
|
newLocalNames[i] = strings.TrimRight(strings.ToLower(name), ".")
|
|
if !strings.HasSuffix(newLocalNames[i], ".local") {
|
|
newLocalNames[i] = newLocalNames[i] + ".local"
|
|
}
|
|
}
|
|
|
|
mDNSConn, err := pion_mdns.Server(ipv4.NewPacketConn(l4), ipv6.NewPacketConn(l6), &pion_mdns.Config{
|
|
LocalNames: newLocalNames,
|
|
LoggerFactory: logging.GetPionDefaultLoggerFactory(),
|
|
})
|
|
|
|
if err != nil {
|
|
scopeLogger.Warn().Err(err).Msg("failed to start mDNS server")
|
|
return err
|
|
}
|
|
|
|
m.conn = mDNSConn
|
|
scopeLogger.Info().Msg("mDNS server started")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MDNS) Start() error {
|
|
return m.start(false)
|
|
}
|
|
|
|
func (m *MDNS) Restart() error {
|
|
return m.start(true)
|
|
}
|
|
|
|
func (m *MDNS) Stop() error {
|
|
m.lock.Lock()
|
|
defer m.lock.Unlock()
|
|
|
|
if m.conn == nil {
|
|
return nil
|
|
}
|
|
|
|
return m.conn.Close()
|
|
}
|
|
|
|
func (m *MDNS) SetLocalNames(localNames []string, always bool) error {
|
|
if reflect.DeepEqual(m.localNames, localNames) && !always {
|
|
return nil
|
|
}
|
|
|
|
m.localNames = localNames
|
|
m.Restart()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MDNS) SetListenOptions(listenOptions *MDNSListenOptions) error {
|
|
if m.listenOptions != nil &&
|
|
m.listenOptions.IPv4 == listenOptions.IPv4 &&
|
|
m.listenOptions.IPv6 == listenOptions.IPv6 {
|
|
return nil
|
|
}
|
|
|
|
m.listenOptions = listenOptions
|
|
m.Restart()
|
|
|
|
return nil
|
|
}
|