| 
					
				 | 
			
			
				@@ -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)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |