92 lines
1.5 KiB
Go
92 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/hoisie/redis"
|
|
)
|
|
|
|
type Hosts struct {
|
|
providers []HostProvider
|
|
refreshInterval time.Duration
|
|
}
|
|
|
|
type HostProvider interface {
|
|
Get(domain string) ([]string, bool)
|
|
Refresh()
|
|
}
|
|
|
|
func NewHosts(hs HostsSettings, rs RedisSettings) Hosts {
|
|
providers := []HostProvider{
|
|
NewFileProvider(hs.HostsFile),
|
|
}
|
|
|
|
if hs.RedisEnable {
|
|
logger.Info("Redis is enabled: %s", rs.Addr())
|
|
|
|
rc := &redis.Client{Addr: rs.Addr(), Db: rs.DB, Password: rs.Password}
|
|
|
|
providers = append(providers, NewRedisProvider(rc, hs.RedisKey))
|
|
}
|
|
|
|
h := Hosts{providers, time.Second * time.Duration(hs.RefreshInterval)}
|
|
|
|
h.refresh()
|
|
|
|
return h
|
|
}
|
|
|
|
func (h *Hosts) refresh() {
|
|
ticker := time.NewTicker(h.refreshInterval)
|
|
|
|
go func() {
|
|
for {
|
|
// Force a refresh every refreshInterval
|
|
for _, provider := range h.providers {
|
|
provider.Refresh()
|
|
}
|
|
|
|
<-ticker.C
|
|
}
|
|
}()
|
|
}
|
|
|
|
/*
|
|
Match local /etc/hosts file first, remote redis records second
|
|
*/
|
|
func (h *Hosts) Get(domain string, family int) ([]net.IP, bool) {
|
|
var sips []string
|
|
var ok bool
|
|
var ip net.IP
|
|
var ips []net.IP
|
|
|
|
for _, provider := range h.providers {
|
|
sips, ok = provider.Get(domain)
|
|
|
|
if ok {
|
|
break
|
|
}
|
|
}
|
|
|
|
if sips == nil {
|
|
return nil, false
|
|
}
|
|
|
|
for _, sip := range sips {
|
|
switch family {
|
|
case _IP4Query:
|
|
ip = net.ParseIP(sip).To4()
|
|
case _IP6Query:
|
|
ip = net.ParseIP(sip).To16()
|
|
default:
|
|
continue
|
|
}
|
|
if ip != nil {
|
|
ips = append(ips, ip)
|
|
}
|
|
}
|
|
|
|
return ips, ips != nil
|
|
}
|