|
@@ -0,0 +1,253 @@
|
|
|
+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))
|
|
|
+}
|