1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
package dns
import (
"net"
"path/filepath"
"sync"
"github.com/areYouLazy/libhosty"
"github.com/fsnotify/fsnotify"
log "github.com/sirupsen/logrus"
)
type HostsFile struct {
hostsReadLock sync.RWMutex
hostsFilePath string
hostsFile *libhosty.HostsFile
}
// NewHostsFile Creates new HostsFile instance
// Pass ""(empty string) if you want to use default hosts file
func NewHostsFile(hostsPath string) (*HostsFile, error) {
hostsFile, err := readHostsFile(hostsPath)
if err != nil {
return nil, err
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
h := &HostsFile{
hostsFile: hostsFile,
hostsFilePath: hostsFile.Config.FilePath,
}
go func() {
h.startWatch(watcher)
}()
return h, nil
}
func (h *HostsFile) startWatch(w *fsnotify.Watcher) {
err := w.Add(filepath.Dir(h.hostsFilePath))
if err != nil {
log.Errorf("Hosts file adding watcher error:%s", err)
return
}
for {
select {
case err, ok := <-w.Errors:
if !ok {
return
}
log.Errorf("Hosts file watcher error:%s", err)
case event, ok := <-w.Events:
if !ok {
return
}
if event.Name == h.hostsFilePath && event.Op&fsnotify.Write == fsnotify.Write {
err := h.updateHostsFile()
if err != nil {
log.Errorf("Hosts file read error:%s", err)
return
}
}
}
}
}
func (h *HostsFile) LookupByHostname(name string) (net.IP, error) {
h.hostsReadLock.RLock()
defer h.hostsReadLock.RUnlock()
_, ip, err := h.hostsFile.LookupByHostname(name)
return ip, err
}
func (h *HostsFile) updateHostsFile() error {
newHosts, err := readHostsFile(h.hostsFilePath)
if err != nil {
return err
}
h.hostsReadLock.Lock()
defer h.hostsReadLock.Unlock()
h.hostsFile = newHosts
return nil
}
func readHostsFile(hostsFilePath string) (*libhosty.HostsFile, error) {
config, err := libhosty.NewHostsFileConfig(hostsFilePath)
if err != nil {
return nil, err
}
return libhosty.InitWithConfig(config)
}
|