| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- package discovery
- import (
- "context"
- "encoding/json"
- "fmt"
- "net"
- "strings"
- "networktool/internal/config"
- "networktool/internal/deviceinfo"
- "networktool/internal/logger"
- "networktool/internal/model"
- )
- type Server struct {
- cfg config.Config
- log *logger.Logger
- deviceSvc *deviceinfo.Service
- }
- func New(cfg config.Config, log *logger.Logger, deviceSvc *deviceinfo.Service) *Server {
- return &Server{cfg: cfg, log: log, deviceSvc: deviceSvc}
- }
- func (s *Server) Run(ctx context.Context) error {
- addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", s.cfg.UDPHost, s.cfg.UDPPort))
- if err != nil {
- return err
- }
- conn, err := net.ListenUDP("udp4", addr)
- if err != nil {
- return err
- }
- defer conn.Close()
- go func() {
- <-ctx.Done()
- _ = conn.Close()
- }()
- s.log.Info("udp discovery listening", "addr", conn.LocalAddr().String())
- buf := make([]byte, 2048)
- for {
- n, remote, err := conn.ReadFromUDP(buf)
- if err != nil {
- if ctx.Err() != nil {
- return nil
- }
- return err
- }
- var req model.DiscoverRequest
- if err := json.Unmarshal(buf[:n], &req); err != nil || req.MessageType != "discover" {
- continue
- }
- device := s.deviceSvc.Get()
- resp := model.DiscoverResponse{
- ProtocolVersion: 1,
- MessageType: "discover_response",
- RequestID: req.RequestID,
- DeviceID: device.DeviceID,
- Hostname: device.Hostname,
- ServerVersion: device.ServerVersion,
- MAC: findMACByIP(s.cfg.MaintenanceIP),
- LAN2IP: s.cfg.MaintenanceIP,
- AuthRequired: true,
- }
- payload, _ := json.Marshal(resp)
- _, _ = conn.WriteToUDP(payload, remote)
- }
- }
- func findMACByIP(ip string) string {
- ifaces, err := net.Interfaces()
- if err != nil {
- return ""
- }
- var fallback string
- for _, iface := range ifaces {
- if iface.Flags&net.FlagLoopback != 0 || len(iface.HardwareAddr) == 0 {
- continue
- }
- addrs, err := iface.Addrs()
- if err != nil {
- continue
- }
- for _, addr := range addrs {
- var current net.IP
- switch value := addr.(type) {
- case *net.IPNet:
- current = value.IP
- case *net.IPAddr:
- current = value.IP
- }
- current = current.To4()
- if current == nil {
- continue
- }
- if current.String() == ip {
- return iface.HardwareAddr.String()
- }
- if fallback == "" && strings.HasPrefix(current.String(), "169.254.") {
- fallback = iface.HardwareAddr.String()
- }
- }
- }
- return fallback
- }
|