diff --git a/.gitignore b/.gitignore index 30521a8..f8b4426 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.coverprofile *exportable-fuzz.zip go-i2p +*.exe \ No newline at end of file diff --git a/lib/router/router.go b/lib/router/router.go index 965076c..a91c77b 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -1,14 +1,17 @@ package router import ( + log "github.com/Sirupsen/logrus" "github.com/hkparker/go-i2p/lib/config" "github.com/hkparker/go-i2p/lib/netdb" + "time" ) // i2p router type type Router struct { - cfg *config.RouterConfig - ndb netdb.StdNetDB + cfg *config.RouterConfig + ndb netdb.StdNetDB + closeChnl chan bool } // create router with default configuration @@ -22,9 +25,22 @@ func CreateRouter() (r *Router, err error) { func FromConfig(c *config.RouterConfig) (r *Router, err error) { r = new(Router) r.cfg = c + r.closeChnl = make(chan bool) return } +func (r *Router) Wait() { + <-r.closeChnl +} + +func (r *Router) Stop() { + r.closeChnl <- true +} + +func (r *Router) Close() error { + return nil +} + // run i2p router mainloop func (r *Router) Run() { r.ndb = netdb.StdNetDB(r.cfg.NetDb.Path) @@ -32,5 +48,17 @@ func (r *Router) Run() { err := r.ndb.Ensure() if err == nil { // netdb ready + log.WithFields(log.Fields{ + "at": "(Router) Run", + }).Info("Router ready") + for err == nil { + time.Sleep(time.Second) + } + } else { + // netdb failed + log.WithFields(log.Fields{ + "at": "(Router) Run", + "reason": err.Error(), + }).Error("Netdb Startup failed") } } diff --git a/lib/util/closeables.go b/lib/util/closeables.go new file mode 100644 index 0000000..d98ac0e --- /dev/null +++ b/lib/util/closeables.go @@ -0,0 +1,16 @@ +package util + +import "io" + +var closeOnExit []io.Closer + +func RegisterCloser(c io.Closer) { + closeOnExit = append(closeOnExit, c) +} + +func CloseAll() { + for idx := range closeOnExit { + closeOnExit[idx].Close() + } + closeOnExit = nil +} diff --git a/lib/util/signals/signals.go b/lib/util/signals/signals.go new file mode 100644 index 0000000..2012b96 --- /dev/null +++ b/lib/util/signals/signals.go @@ -0,0 +1,33 @@ +package signals + +import ( + "os" +) + +var sigChan = make(chan os.Signal) + +type Handler func() + +var reloaders []Handler + +func RegisterReloadHandler(f Handler) { + reloaders = append(reloaders, f) +} + +func handleReload() { + for idx := range reloaders { + reloaders[idx]() + } +} + +var interrupters []Handler + +func RegisterInterruptHandler(f Handler) { + interrupters = append(interrupters, f) +} + +func handleInterrupted() { + for idx := range interrupters { + interrupters[idx]() + } +} diff --git a/lib/util/signals/unix.go b/lib/util/signals/unix.go new file mode 100644 index 0000000..fb06054 --- /dev/null +++ b/lib/util/signals/unix.go @@ -0,0 +1,30 @@ +// +build !windows + +package signals + +import ( + "os/signal" + "syscall" +) + +func init() { + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) +} + +func Handle() { + for { + sig, ok := <-sigChan + if !ok { + // closed channel + return + } + if sig == syscall.SIGHUP { + handleReload() + } else if sig == syscall.SIGINT || sig == syscall.SIGTERM { + handleInterrupted() + } else { + // wtf? + } + } + +} diff --git a/lib/util/signals/windows.go b/lib/util/signals/windows.go new file mode 100644 index 0000000..3b75d1a --- /dev/null +++ b/lib/util/signals/windows.go @@ -0,0 +1,28 @@ +// +build windows + +package signals + +import ( + "os" + "os/signal" +) + +func init() { + signal.Notify(sigChan, os.Interrupt) +} + +func Handle() { + for { + sig, ok := <-sigChan + if !ok { + // closed channel + return + } + if sig == os.Interrupt { + handleInterrupted() + } else { + // wtf? + } + } + +} diff --git a/main.go b/main.go index 7d188f6..532392d 100644 --- a/main.go +++ b/main.go @@ -3,16 +3,26 @@ package main import ( log "github.com/Sirupsen/logrus" "github.com/hkparker/go-i2p/lib/router" + "github.com/hkparker/go-i2p/lib/util/signals" ) func main() { - + go signals.Handle() log.Info("parsing i2p router configuration") log.Info("starting up i2p router") r, err := router.CreateRouter() if err == nil { - r.Run() + signals.RegisterReloadHandler(func() { + // TODO: reload config + }) + signals.RegisterInterruptHandler(func() { + // TODO: graceful shutdown + r.Stop() + }) + go r.Run() + defer r.Close() + r.Wait() } else { log.Errorf("failed to create i2p router: %s", err) }