75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
dmnet "git.clan.lol/clan/data-mesher/pkg/net"
|
|
)
|
|
|
|
// HTTP represents the configuration for an HTTP server, including port and interfaces.
|
|
type HTTP struct {
|
|
Port uint16 `mapstructure:"port"`
|
|
Interfaces []string `mapstructure:"interfaces"`
|
|
|
|
// generated after looking at the interfaces
|
|
ListenAddresses []string `mapstructure:"-"`
|
|
|
|
// Resolver is used to resolve interface names to IP addresses. If nil, uses the default system resolver.
|
|
Resolver dmnet.InterfaceResolver `mapstructure:"-"`
|
|
}
|
|
|
|
// Validate checks the HTTP configuration to ensure required fields are set and derives the listen addresses.
|
|
// Returns an error if the configuration is invalid.
|
|
func (h *HTTP) Validate() error {
|
|
defer func() {
|
|
slog.Debug(
|
|
"http config",
|
|
"listen_addresses", h.ListenAddresses,
|
|
"port", h.Port,
|
|
"interfaces", h.Interfaces,
|
|
)
|
|
}()
|
|
|
|
if h.Port == 0 {
|
|
return fmt.Errorf("%w: http port must be between 1 and 65535", ErrInvalidConfig)
|
|
}
|
|
|
|
if len(h.Interfaces) == 0 {
|
|
return fmt.Errorf("%w: at least one http interface is required", ErrInvalidConfig)
|
|
}
|
|
|
|
// determine network resolver
|
|
resolver := h.Resolver
|
|
if resolver == nil {
|
|
// if no resolver is specified we fall back to the system resolver
|
|
resolver = dmnet.DefaultResolver{}
|
|
}
|
|
|
|
// bind to all addresses found for the interfaces
|
|
for _, iface := range h.Interfaces {
|
|
addrs, err := resolver.InterfaceAddresses(iface)
|
|
if err != nil {
|
|
return fmt.Errorf("%w: failed to resolve ip addresses for interface %q: %w", ErrInvalidConfig, iface, err)
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
// we don't want multicast or link-local addresses
|
|
if addr.IP.IsMulticast() || addr.IP.IsLinkLocalMulticast() || addr.IP.IsLinkLocalUnicast() {
|
|
continue
|
|
}
|
|
|
|
h.ListenAddresses = append(h.ListenAddresses, dmnet.ConnectString(addr.IP, h.Port))
|
|
}
|
|
}
|
|
|
|
if len(h.ListenAddresses) == 0 {
|
|
return fmt.Errorf(
|
|
"%w: failed to resolve any ip addresses for interfaces %q",
|
|
ErrInvalidConfig, h.Interfaces,
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|