discovery.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package discovery
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "strings"
  8. "networktool/internal/config"
  9. "networktool/internal/deviceinfo"
  10. "networktool/internal/logger"
  11. "networktool/internal/model"
  12. )
  13. type Server struct {
  14. cfg config.Config
  15. log *logger.Logger
  16. deviceSvc *deviceinfo.Service
  17. }
  18. func New(cfg config.Config, log *logger.Logger, deviceSvc *deviceinfo.Service) *Server {
  19. return &Server{cfg: cfg, log: log, deviceSvc: deviceSvc}
  20. }
  21. func (s *Server) Run(ctx context.Context) error {
  22. addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", s.cfg.UDPHost, s.cfg.UDPPort))
  23. if err != nil {
  24. return err
  25. }
  26. conn, err := net.ListenUDP("udp4", addr)
  27. if err != nil {
  28. return err
  29. }
  30. defer conn.Close()
  31. go func() {
  32. <-ctx.Done()
  33. _ = conn.Close()
  34. }()
  35. s.log.Info("udp discovery listening", "addr", conn.LocalAddr().String())
  36. buf := make([]byte, 2048)
  37. for {
  38. n, remote, err := conn.ReadFromUDP(buf)
  39. if err != nil {
  40. if ctx.Err() != nil {
  41. return nil
  42. }
  43. return err
  44. }
  45. var req model.DiscoverRequest
  46. if err := json.Unmarshal(buf[:n], &req); err != nil || req.MessageType != "discover" {
  47. continue
  48. }
  49. device := s.deviceSvc.Get()
  50. resp := model.DiscoverResponse{
  51. ProtocolVersion: 1,
  52. MessageType: "discover_response",
  53. RequestID: req.RequestID,
  54. DeviceID: device.DeviceID,
  55. Hostname: device.Hostname,
  56. ServerVersion: device.ServerVersion,
  57. MAC: findMACByIP(s.cfg.MaintenanceIP),
  58. LAN2IP: s.cfg.MaintenanceIP,
  59. AuthRequired: true,
  60. }
  61. payload, _ := json.Marshal(resp)
  62. _, _ = conn.WriteToUDP(payload, remote)
  63. }
  64. }
  65. func findMACByIP(ip string) string {
  66. ifaces, err := net.Interfaces()
  67. if err != nil {
  68. return ""
  69. }
  70. var fallback string
  71. for _, iface := range ifaces {
  72. if iface.Flags&net.FlagLoopback != 0 || len(iface.HardwareAddr) == 0 {
  73. continue
  74. }
  75. addrs, err := iface.Addrs()
  76. if err != nil {
  77. continue
  78. }
  79. for _, addr := range addrs {
  80. var current net.IP
  81. switch value := addr.(type) {
  82. case *net.IPNet:
  83. current = value.IP
  84. case *net.IPAddr:
  85. current = value.IP
  86. }
  87. current = current.To4()
  88. if current == nil {
  89. continue
  90. }
  91. if current.String() == ip {
  92. return iface.HardwareAddr.String()
  93. }
  94. if fallback == "" && strings.HasPrefix(current.String(), "169.254.") {
  95. fallback = iface.HardwareAddr.String()
  96. }
  97. }
  98. }
  99. return fallback
  100. }