Add support for V2 source format -- Goodbye, CSV.

This commit is contained in:
Frank Denis 2018-01-25 15:02:18 +01:00
parent 78e8abeebc
commit 79193e6ee3
1 changed files with 63 additions and 3 deletions

View File

@ -9,6 +9,7 @@ import (
"os" "os"
"strings" "strings"
"time" "time"
"unicode"
"github.com/dchest/safefile" "github.com/dchest/safefile"
@ -20,6 +21,7 @@ type SourceFormat int
const ( const (
SourceFormatV1 = iota SourceFormatV1 = iota
SourceFormatV2
) )
const ( const (
@ -101,10 +103,13 @@ type URLToPrefetch struct {
func NewSource(url string, minisignKeyStr string, cacheFile string, formatStr string, refreshDelay time.Duration) (Source, []URLToPrefetch, error) { func NewSource(url string, minisignKeyStr string, cacheFile string, formatStr string, refreshDelay time.Duration) (Source, []URLToPrefetch, error) {
_ = refreshDelay _ = refreshDelay
source := Source{url: url} source := Source{url: url}
if formatStr != "v1" { if formatStr == "v1" {
source.format = SourceFormatV1
} else if formatStr == "v2" {
source.format = SourceFormatV2
} else {
return source, []URLToPrefetch{}, fmt.Errorf("Unsupported source format: [%s]", formatStr) return source, []URLToPrefetch{}, fmt.Errorf("Unsupported source format: [%s]", formatStr)
} }
source.format = SourceFormatV1
minisignKey, err := minisign.NewPublicKey(minisignKeyStr) minisignKey, err := minisign.NewPublicKey(minisignKeyStr)
if err != nil { if err != nil {
return source, []URLToPrefetch{}, err return source, []URLToPrefetch{}, err
@ -121,7 +126,10 @@ func NewSource(url string, minisignKeyStr string, cacheFile string, formatStr st
urlsToPrefetch = append(urlsToPrefetch, URLToPrefetch{url: sigURL, cacheFile: sigCacheFile, when: now.Add(sigDelayTillNextUpdate)}) urlsToPrefetch = append(urlsToPrefetch, URLToPrefetch{url: sigURL, cacheFile: sigCacheFile, when: now.Add(sigDelayTillNextUpdate)})
if err != nil || sigErr != nil { if err != nil || sigErr != nil {
return source, urlsToPrefetch, nil if err == nil {
err = sigErr
}
return source, urlsToPrefetch, err
} }
signature, err := minisign.DecodeSignature(sigStr) signature, err := minisign.DecodeSignature(sigStr)
@ -152,6 +160,16 @@ func NewSource(url string, minisignKeyStr string, cacheFile string, formatStr st
} }
func (source *Source) Parse(prefix string) ([]RegisteredServer, error) { func (source *Source) Parse(prefix string) ([]RegisteredServer, error) {
if source.format == SourceFormatV1 {
return source.parseV1(prefix)
} else if source.format == SourceFormatV2 {
return source.parseV2(prefix)
}
dlog.Fatal("Unexpected source format")
return []RegisteredServer{}, nil
}
func (source *Source) parseV1(prefix string) ([]RegisteredServer, error) {
var registeredServers []RegisteredServer var registeredServers []RegisteredServer
csvReader := csv.NewReader(strings.NewReader(source.in)) csvReader := csv.NewReader(strings.NewReader(source.in))
@ -193,6 +211,48 @@ func (source *Source) Parse(prefix string) ([]RegisteredServer, error) {
return registeredServers, nil return registeredServers, nil
} }
func (source *Source) parseV2(prefix string) ([]RegisteredServer, error) {
var registeredServers []RegisteredServer
in := string(source.in)
parts := strings.Split(in, "## ")
if len(parts) < 2 {
return registeredServers, fmt.Errorf("Invalid format for source at [%s]", source.url)
}
parts = parts[1:]
for _, part := range parts {
part = strings.TrimFunc(part, unicode.IsSpace)
subparts := strings.Split(part, "\n")
if len(subparts) < 2 {
return registeredServers, fmt.Errorf("Invalid format for source at [%s]", source.url)
}
name := strings.TrimFunc(subparts[0], unicode.IsSpace)
if len(name) == 0 {
return registeredServers, fmt.Errorf("Invalid format for source at [%s]", source.url)
}
var stampStr string
for _, subpart := range subparts {
subpart = strings.TrimFunc(subpart, unicode.IsSpace)
if strings.HasPrefix(subpart, "sdns://") {
stampStr = subpart
break
}
}
if len(stampStr) < 8 {
return registeredServers, fmt.Errorf("Missing stamp for server [%s] in source from [%s]", name, source.url)
}
stamp, err := NewServerStampFromString(stampStr)
if err != nil {
return registeredServers, err
}
registeredServer := RegisteredServer{
name: name, stamp: stamp,
}
dlog.Debugf("Registered [%s] with stamp [%s]", name, stamp.String())
registeredServers = append(registeredServers, registeredServer)
}
return registeredServers, nil
}
func PrefetchSourceURL(urlToPrefetch *URLToPrefetch) error { func PrefetchSourceURL(urlToPrefetch *URLToPrefetch) error {
in, _, delayTillNextUpdate, err := fetchWithCache(urlToPrefetch.url, urlToPrefetch.cacheFile) in, _, delayTillNextUpdate, err := fetchWithCache(urlToPrefetch.url, urlToPrefetch.cacheFile)
if err == nil { if err == nil {