This commit is contained in:
Matt Drollette
2014-09-13 14:21:33 -05:00
parent c59c1bf00d
commit 88602cac2c
2 changed files with 103 additions and 72 deletions

18
cli.go
View File

@@ -62,13 +62,17 @@ func main() {
}, },
}, },
Action: func(c *cli.Context) { Action: func(c *cli.Context) {
server := NewReseeder() Run(&Config{
server.NetDBDir = c.String("netdb") NetDBDir: c.String("netdb"),
server.RefreshInterval = c.Duration("refresh") RefreshInterval: c.Duration("refresh"),
server.Proxy = c.Bool("proxy") Proxy: c.Bool("proxy"),
server.Verbose = c.Bool("verbose") Verbose: c.Bool("verbose"),
server.RateLimit = c.Int("rateLimit") RateLimit: c.Int("rateLimit"),
server.Start(c.String("addr"), c.String("port"), c.String("cert"), c.String("key")) Addr: c.String("addr"),
Port: c.String("port"),
Cert: c.String("cert"),
Key: c.String("key"),
})
}, },
}, },
{ {

View File

@@ -15,6 +15,7 @@ package main
// https://geti2p.net/en/docs/spec/updates // https://geti2p.net/en/docs/spec/updates
import ( import (
"fmt"
"github.com/PuerkitoBio/throttled" "github.com/PuerkitoBio/throttled"
"github.com/PuerkitoBio/throttled/store" "github.com/PuerkitoBio/throttled/store"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
@@ -29,6 +30,10 @@ import (
"time" "time"
) )
const (
LIST_TEMPLATE = `<html><head><title>NetDB</title></head><body><ul>{{ range . }}<li><a href="{{ . }}">{{ . }}</a></li>{{ end }}</ul></body></html>`
)
func proxiedHandler(h http.Handler) http.Handler { func proxiedHandler(h http.Handler) http.Handler {
return remoteAddrFixup{h} return remoteAddrFixup{h}
} }
@@ -44,77 +49,94 @@ func (h remoteAddrFixup) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.h.ServeHTTP(w, r) h.h.ServeHTTP(w, r)
} }
type Reseeder struct { type Config struct {
NetDBDir string NetDBDir string
nextMap chan []string
RefreshInterval time.Duration RefreshInterval time.Duration
Proxy bool Proxy bool
Verbose bool Verbose bool
RateLimit int RateLimit int
listTemplate *template.Template Addr string
Port string
Cert string
Key string
} }
func (rs *Reseeder) Start(addr, port, cert, key string) { func Run(config *Config) {
var err error legacyReseeder := NewLegacyReseeder(config.NetDBDir)
legacyReseeder.Start(config.RefreshInterval)
go rs.runMap() su3Reseeder := NewSu3Reseeder(config.NetDBDir)
go rs.refresher() su3Reseeder.Start()
// parse the template for routerInfo lists
rs.listTemplate, err = template.New("routerinfos").Parse(`<html><head><title>NetDB</title></head><body><ul>{{ range . }}<li><a href="{{ . }}">{{ . }}</a></li>{{ end }}</ul></body></html>`)
if err != nil {
log.Fatalln("error parsing routerInfo list template", err)
return
}
r := mux.NewRouter() r := mux.NewRouter()
s := r.PathPrefix("/netdb").Subrouter() s := r.PathPrefix("/netdb").Subrouter()
s.HandleFunc("/", rs.listHandler) s.HandleFunc("/", legacyReseeder.ListHandler)
s.HandleFunc("/i2pseeds.su3", rs.su3Handler) s.HandleFunc("/i2pseeds.su3", su3Reseeder.Su3Handler)
s.HandleFunc(`/routerInfo-{hash:[A-Za-z0-9+/\-=~]+}.dat`, rs.routerInfoHandler) s.HandleFunc(`/routerInfo-{hash:[A-Za-z0-9+/\-=~]+}.dat`, legacyReseeder.RouterInfoHandler)
// timeout // timeout
muxWithMiddlewares := http.TimeoutHandler(r, time.Second*5, "Timeout!") muxWithMiddlewares := http.TimeoutHandler(r, time.Second*5, "Timeout!")
th := throttled.RateLimit(throttled.PerMin(rs.RateLimit), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(1000)) th := throttled.RateLimit(throttled.PerMin(config.RateLimit), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(1000))
muxWithMiddlewares = th.Throttle(muxWithMiddlewares) muxWithMiddlewares = th.Throttle(muxWithMiddlewares)
if rs.Proxy { if config.Proxy {
muxWithMiddlewares = proxiedHandler(muxWithMiddlewares) muxWithMiddlewares = proxiedHandler(muxWithMiddlewares)
} }
if rs.Verbose { if config.Verbose {
muxWithMiddlewares = handlers.CombinedLoggingHandler(os.Stdout, muxWithMiddlewares) muxWithMiddlewares = handlers.CombinedLoggingHandler(os.Stdout, muxWithMiddlewares)
} }
listenAddress := fmt.Sprintf("%s:%s", config.Addr, config.Port)
// try to start tls server // try to start tls server
if _, err = os.Stat(cert); err == nil { if config.Cert != "" && config.Key != "" {
if _, err = os.Stat(key); err == nil { log.Println("Starting TLS reseed server on " + listenAddress)
log.Println("Starting TLS reseed server on " + addr + ":" + port) err := http.ListenAndServeTLS(listenAddress, config.Cert, config.Key, muxWithMiddlewares)
err := http.ListenAndServeTLS(addr+":"+port, cert, key, muxWithMiddlewares)
if nil != err { if nil != err {
log.Fatalln(err) log.Fatalln(err)
} }
} else {
return
}
}
// fall back to regular http server // fall back to regular http server
log.Println("Starting reseed server on " + addr + ":" + port) log.Println("Starting reseed server on " + listenAddress)
err = http.ListenAndServe(addr+":"+port, muxWithMiddlewares) err := http.ListenAndServe(listenAddress, muxWithMiddlewares)
if nil != err { if nil != err {
log.Fatalln(err) log.Fatalln(err)
} }
} }
func NewReseeder() *Reseeder {
return &Reseeder{nextMap: make(chan []string)}
} }
func (r *Reseeder) runMap() { func NewLegacyReseeder(netdbDir string) *LegacyReseeder {
return &LegacyReseeder{netdbDir: netdbDir, nextMap: make(chan []string)}
}
func NewSu3Reseeder(netdbDir string) *Su3Reseeder {
return &Su3Reseeder{netdbDir: netdbDir, nextMap: make(chan []string)}
}
type Su3Reseeder struct {
nextMap chan []string
netdbDir string
}
func (r *Su3Reseeder) Start() {
}
func (rs *Su3Reseeder) Su3Handler(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
}
type LegacyReseeder struct {
nextMap chan []string
netdbDir string
listTemplate *template.Template
}
func (r *LegacyReseeder) Start(refreshInterval time.Duration) {
go func() {
var m []string var m []string
for { for {
select { select {
@@ -122,20 +144,29 @@ func (r *Reseeder) runMap() {
case r.nextMap <- m: case r.nextMap <- m:
} }
} }
} }()
func (r *Reseeder) refresher() { go func() {
for { for {
log.Println("Updating routerInfos") log.Println("Updating routerInfos")
r.Refresh() r.Refresh()
time.Sleep(r.RefreshInterval) time.Sleep(refreshInterval)
}
}()
// parse the template for routerInfo lists
var err error
r.listTemplate, err = template.New("ri").Parse(LIST_TEMPLATE)
if err != nil {
log.Fatalln("error parsing routerInfo list template", err)
return
} }
} }
func (r *Reseeder) Refresh() { func (r *LegacyReseeder) Refresh() {
var m []string var m []string
src, err := ioutil.ReadDir(r.NetDBDir) src, err := ioutil.ReadDir(r.netdbDir)
if nil != err { if nil != err {
log.Fatalln("error reading netdb dir", err) log.Fatalln("error reading netdb dir", err)
return return
@@ -162,21 +193,17 @@ func (r *Reseeder) Refresh() {
r.nextMap <- m r.nextMap <- m
} }
func (rs *Reseeder) listHandler(w http.ResponseWriter, r *http.Request) { func (lr *LegacyReseeder) ListHandler(w http.ResponseWriter, r *http.Request) {
err := rs.listTemplate.Execute(w, <-rs.nextMap) err := lr.listTemplate.Execute(w, <-lr.nextMap)
if err != nil { if err != nil {
log.Fatalln("error rending list template", err) log.Fatalln("error rending list template", err)
} }
} }
func (rs *Reseeder) su3Handler(w http.ResponseWriter, r *http.Request) { func (rs *LegacyReseeder) RouterInfoHandler(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
}
func (rs *Reseeder) routerInfoHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
fileName := "routerInfo-" + vars["hash"] + ".dat" fileName := "routerInfo-" + vars["hash"] + ".dat"
f, err := os.Open(rs.NetDBDir + "/" + fileName) f, err := os.Open(rs.netdbDir + "/" + fileName)
if nil != err { if nil != err {
http.NotFound(w, r) http.NotFound(w, r)
log.Println("error sending file", err) log.Println("error sending file", err)