package host import ( "fmt" "net" "os" "strconv" "strings" "git.giaever.org/joachimmg/go-log.git/log" "git.giaever.org/joachimmg/m-dns/errors" ) type HostString string type HostIP net.IP type HostIPs []HostIP type HostIPvType int type HostPort int const ( IPv4 HostIPvType = iota << 1 IPv6 HostIPvType = iota << 1 NoIP HostIPvType = iota << 1 ) type Host struct { service HostString domain HostString hostname HostString ips HostIPs port HostPort } func New() *Host { return new(Host) } func (h *Host) SetService(s string) error { if err := HostString(s).validService(); err != nil { return err } h.service = HostString(s) return nil } func (h *Host) SetDomain(d string) error { if len(d) == 0 { d = "local." } if err := HostString(d).validDomain(); err != nil { return err } h.domain = HostString(d) return nil } func (h *Host) SetHostname(hn string) error { if len(hn) == 0 { var err error hn, err = os.Hostname() if err != nil { log.Warningln(h, hn, err) return errors.HostHostnameCouldNotDetermine } hn = fmt.Sprintf("%s.", hn) } if err := HostString(hn).validHostname(); err != nil { return err } h.hostname = HostString(hn) return nil } func (h *Host) SetIPs(i []net.IP) error { if len(i) == 0 { var err error i, err = net.LookupIP(fmt.Sprintf("%s%s", h.GetHostname(), h.GetDomain())) if err != nil { log.Warningln(h, err) return errors.HostIPCouldNotDetermine } } var ips HostIPs for _, ip := range i { ips = append(ips, HostIP(ip)) } if err := ips.validIPs(); err != nil { log.Warningln(err) return err } h.ips = ips return nil } func (h *Host) SetPort(p int) error { if err := HostPort(p).validPort(); err != nil { return err } h.port = HostPort(p) return nil } func (h *Host) GetService() HostString { if err := h.service.validService(); err != nil { log.Panicln(err) } return h.service } func (h *Host) GetDomain() HostString { if err := h.domain.validDomain(); err != nil { log.Panicln(err) } return h.domain } func (h *Host) GetHostname() HostString { if err := h.hostname.validHostname(); err != nil { log.Panicln(err) } return h.hostname } func (h *Host) GetIPs() HostIPs { if err := h.ips.validIPs(); err != nil { log.Panicln(err) } return h.ips } func (h *Host) GetPort() HostPort { if err := h.port.validPort(); err != nil { log.Panicln(err) } return h.port } func (h *Host) String() string { return fmt.Sprintf("Service: %s\nDomain: %s\nHostname: %s\nIPs: %s\nPort: %s\n", h.GetService(), h.GetDomain(), h.GetHostname(), strings.Join(h.GetIPs().String(), ", "), h.GetPort(), ) } func (h HostString) ValidFQDM() bool { if len(h) == 0 { log.Warningln("Cannot be blank", h) return false } if h[len(h)-1] != '.' { log.Warningf("Missing trailing '.' in <%s>", h) return false } return true } func (h HostString) validService() error { if len(h) == 0 { log.Warningln("Service is empty", h) return errors.HostServiceIsEmpty } return nil } func (h HostString) validHostname() error { if !h.ValidFQDM() { return errors.HostHostnameNotFQDM } return nil } func (h HostString) validDomain() error { if !h.ValidFQDM() { return errors.HostDomainNotFQDM } return nil } func (h HostString) TrimDot() string { return strings.Trim(h.String(), ".") } func (h HostString) String() string { return string(h) } func (h HostIPs) validIPs() error { for _, ip := range h { if t := ip.Type(); t == NoIP { return errors.HostIPAddressIsInvalid } } return nil } func (h HostIPs) String() []string { s := []string{} for _, ip := range h { s = append(s, ip.String()) } return s } func (h HostIP) Type() HostIPvType { if h.AsIP().To4() != nil { return IPv4 } if h.AsIP().To16() != nil { return IPv6 } return NoIP } func (h HostIP) AsIP() net.IP { return net.IP(h) } func (h HostIP) String() string { return h.AsIP().String() } func (h HostPort) validPort() error { if h <= 0 { log.Warningf("Port <%d> is invalid.", h) return errors.HostPortInvalid } return nil } func (h HostPort) Uint16() uint16 { return uint16(h) } func (h HostPort) String() string { return strconv.Itoa(int(h)) }