diff --git a/router/json.go b/router/json.go new file mode 100644 index 00000000..e3091b24 --- /dev/null +++ b/router/json.go @@ -0,0 +1,82 @@ +package router + +import ( + "encoding/json" + "fmt" + "time" +) + +func (router *Router) GenerateStatusJSON(version, encryption string) ([]byte, error) { + return json.Marshal(struct { + Version string + Encryption string + Name, Interface string + Macs *MacCache + Peers *Peers + Routes *Routes + }{version, encryption, router.Ourself.Name.String(), fmt.Sprintf("%v", router.Iface), router.Macs, router.Peers, router.Routes}) + // leaving out ConectionMaker due to async complexities +} + +func (cache *MacCache) MarshalJSON() ([]byte, error) { + type cacheEntry struct { + Mac string + PeerName PeerName + LastSeen time.Time + } + entries := make([]*cacheEntry, 0) + for key, entry := range cache.table { + entries = append(entries, &cacheEntry{intmac(key).String(), entry.peer.Name, entry.lastSeen}) + } + return json.Marshal(entries) +} + +func (peers *Peers) MarshalJSON() ([]byte, error) { + ps := make([]*Peer, 0) + peers.ForEach(func(_ PeerName, peer *Peer) { ps = append(ps, peer) }) + return json.Marshal(ps) +} + +func (routes *Routes) MarshalJSON() ([]byte, error) { + routes.RLock() + defer routes.RUnlock() + type uni struct { + Dest, Via PeerName + } + type broad struct { + Source PeerName + Via []PeerName + } + var r struct { + Unicast []*uni + Broadcast []*broad + } + for name, hop := range routes.unicast { + r.Unicast = append(r.Unicast, &uni{name, hop}) + } + for name, hops := range routes.broadcast { + r.Broadcast = append(r.Broadcast, &broad{name, hops}) + } + return json.Marshal(r) +} + +func (peer *Peer) MarshalJSON() ([]byte, error) { + conns := make([]Connection, 0) + peer.ForEachConnection(func(remoteName PeerName, conn Connection) { + conns = append(conns, conn) + }) + return json.Marshal(struct { + Name string + UID uint64 + Version uint64 + Connections []Connection + }{peer.Name.String(), peer.UID, peer.version, conns}) +} + +func (conn *RemoteConnection) MarshalJSON() ([]byte, error) { + return json.Marshal(struct{ RemoteName, TcpAddr string }{conn.Remote().Name.String(), conn.RemoteTCPAddr()}) +} + +func (name PeerName) MarshalJSON() ([]byte, error) { + return json.Marshal(name.String()) +} diff --git a/weaver/main.go b/weaver/main.go index de62f30b..7d3aae93 100644 --- a/weaver/main.go +++ b/weaver/main.go @@ -145,6 +145,10 @@ func handleHttp(router *weave.Router) { io.WriteString(w, fmt.Sprintln("Encryption", encryption)) io.WriteString(w, router.Status()) }) + http.HandleFunc("/status-json", func(w http.ResponseWriter, r *http.Request) { + json, _ := router.GenerateStatusJSON(version, encryption) + w.Write(json) + }) http.HandleFunc("/connect", func(w http.ResponseWriter, r *http.Request) { peer := r.FormValue("peer") if addr, err := net.ResolveTCPAddr("tcp4", weave.NormalisePeerAddr(peer)); err == nil {