mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	reorganize and add more to the admin
This commit is contained in:
		
							parent
							
								
									fe8a78f966
								
							
						
					
					
						commit
						2dd8152a0c
					
				
					 1 changed files with 264 additions and 156 deletions
				
			
		| 
						 | 
					@ -5,6 +5,7 @@ import "os"
 | 
				
			||||||
import "bytes"
 | 
					import "bytes"
 | 
				
			||||||
import "fmt"
 | 
					import "fmt"
 | 
				
			||||||
import "sort"
 | 
					import "sort"
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO? Make all of this JSON
 | 
					// TODO? Make all of this JSON
 | 
				
			||||||
// TODO: Add authentication
 | 
					// TODO: Add authentication
 | 
				
			||||||
| 
						 | 
					@ -12,11 +13,45 @@ import "sort"
 | 
				
			||||||
type admin struct {
 | 
					type admin struct {
 | 
				
			||||||
	core       *Core
 | 
						core       *Core
 | 
				
			||||||
	listenaddr string
 | 
						listenaddr string
 | 
				
			||||||
 | 
						handlers   []admin_handlerInfo
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type admin_handlerInfo struct {
 | 
				
			||||||
 | 
						name    string                   // Checked against the first word of the api call
 | 
				
			||||||
 | 
						args    []string                 // List of human-readable argument names
 | 
				
			||||||
 | 
						handler func(*[]byte, ...string) // First arg is pointer to the out slice, rest is args
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *admin) addHandler(name string, args []string, handler func(*[]byte, ...string)) {
 | 
				
			||||||
 | 
						a.handlers = append(a.handlers, admin_handlerInfo{name, args, handler})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *admin) init(c *Core, listenaddr string) {
 | 
					func (a *admin) init(c *Core, listenaddr string) {
 | 
				
			||||||
	a.core = c
 | 
						a.core = c
 | 
				
			||||||
	a.listenaddr = listenaddr
 | 
						a.listenaddr = listenaddr
 | 
				
			||||||
 | 
						a.addHandler("help", nil, func(out *[]byte, _ ...string) {
 | 
				
			||||||
 | 
							for _, handler := range a.handlers {
 | 
				
			||||||
 | 
								tmp := append([]string{handler.name}, handler.args...)
 | 
				
			||||||
 | 
								*out = append(*out, []byte(strings.Join(tmp, " "))...)
 | 
				
			||||||
 | 
								*out = append(*out, "\n"...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						// TODO? have other parts of the program call to add their own handlers
 | 
				
			||||||
 | 
						a.addHandler("dot", nil, func(out *[]byte, _ ...string) {
 | 
				
			||||||
 | 
							*out = a.getResponse_dot()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						a.addHandler("getSelf", nil, func(out *[]byte, _ ...string) {
 | 
				
			||||||
 | 
							*out = []byte(a.printInfos(a.getData_getPeers()))
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						a.addHandler("getPeers", nil, func(out *[]byte, _ ...string) {
 | 
				
			||||||
 | 
							*out = []byte(a.printInfos(a.getData_getPeers()))
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						a.addHandler("getDHT", nil, func(out *[]byte, _ ...string) {
 | 
				
			||||||
 | 
							*out = []byte(a.printInfos(a.getData_getDHT()))
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						a.addHandler("getSessions", nil, func(out *[]byte, _ ...string) {
 | 
				
			||||||
 | 
							*out = []byte(a.printInfos(a.getData_getSessions()))
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	go a.listen()
 | 
						go a.listen()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,80 +79,164 @@ func (a *admin) handleRequest(conn net.Conn) {
 | 
				
			||||||
		conn.Close()
 | 
							conn.Close()
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						var out []byte
 | 
				
			||||||
	buf = bytes.Trim(buf, "\x00\r\n\t")
 | 
						buf = bytes.Trim(buf, "\x00\r\n\t")
 | 
				
			||||||
	switch string(buf) {
 | 
						call := strings.Split(string(buf), " ")
 | 
				
			||||||
	case "dot":
 | 
						var cmd string
 | 
				
			||||||
		const mDepth = 1024
 | 
						var args []string
 | 
				
			||||||
		m := make(map[[mDepth]switchPort]string)
 | 
						if len(call) > 0 {
 | 
				
			||||||
		table := a.core.switchTable.table.Load().(lookupTable)
 | 
							cmd = call[0]
 | 
				
			||||||
		peers := a.core.peers.ports.Load().(map[switchPort]*peer)
 | 
							args = call[1:]
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Add my own entry
 | 
					 | 
				
			||||||
		peerID := address_addrForNodeID(getNodeID(&peers[0].box))
 | 
					 | 
				
			||||||
		myAddr := net.IP(peerID[:]).String()
 | 
					 | 
				
			||||||
		var index [mDepth]switchPort
 | 
					 | 
				
			||||||
		copy(index[:mDepth], table.self.coords[:])
 | 
					 | 
				
			||||||
		m[index] = myAddr
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Connect switch table entries to peer entries
 | 
					 | 
				
			||||||
		for _, tableentry := range table.elems {
 | 
					 | 
				
			||||||
			for _, peerentry := range peers {
 | 
					 | 
				
			||||||
				if peerentry.port == tableentry.port {
 | 
					 | 
				
			||||||
					peerID := address_addrForNodeID(getNodeID(&peerentry.box))
 | 
					 | 
				
			||||||
					addr := net.IP(peerID[:]).String()
 | 
					 | 
				
			||||||
					var index [mDepth]switchPort
 | 
					 | 
				
			||||||
					copy(index[:], tableentry.locator.coords)
 | 
					 | 
				
			||||||
					m[index] = addr
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
			}
 | 
						done := false
 | 
				
			||||||
		}
 | 
						for _, handler := range a.handlers {
 | 
				
			||||||
 | 
							if cmd == handler.name {
 | 
				
			||||||
		getPorts := func(coords []byte) []switchPort {
 | 
								handler.handler(&out, args...)
 | 
				
			||||||
			var ports []switchPort
 | 
								done = true
 | 
				
			||||||
			for offset := 0; ; {
 | 
					 | 
				
			||||||
				coord, length := wire_decode_uint64(coords[offset:])
 | 
					 | 
				
			||||||
				if length == 0 {
 | 
					 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
				ports = append(ports, switchPort(coord))
 | 
					 | 
				
			||||||
				offset += length
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
			return ports
 | 
						if !done {
 | 
				
			||||||
 | 
							out = []byte("I didn't understand that!\n")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = conn.Write(out)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							a.core.log.Printf("Admin socket error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn.Close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Look up everything we know from DHT
 | 
					// Maps things like "IP", "port", "bucket", or "coords" onto strings
 | 
				
			||||||
 | 
					type admin_pair struct {
 | 
				
			||||||
 | 
						key string
 | 
				
			||||||
 | 
						val string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type admin_nodeInfo []admin_pair
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (n *admin_nodeInfo) asMap() map[string]string {
 | 
				
			||||||
 | 
						m := make(map[string]string, len(*n))
 | 
				
			||||||
 | 
						for _, p := range *n {
 | 
				
			||||||
 | 
							m[p.key] = p.val
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return m
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (n *admin_nodeInfo) toString() string {
 | 
				
			||||||
 | 
						// TODO return something nicer looking than this
 | 
				
			||||||
 | 
						var out []string
 | 
				
			||||||
 | 
						for _, p := range *n {
 | 
				
			||||||
 | 
							out = append(out, fmt.Sprintf("%v: %v", p.key, p.val))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strings.Join(out, ", ")
 | 
				
			||||||
 | 
						return fmt.Sprint(*n)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *admin) printInfos(infos []admin_nodeInfo) string {
 | 
				
			||||||
 | 
						var out []string
 | 
				
			||||||
 | 
						for _, info := range infos {
 | 
				
			||||||
 | 
							out = append(out, info.toString())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out = append(out, "") // To add a trailing "\n" in the join
 | 
				
			||||||
 | 
						return strings.Join(out, "\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *admin) getData_getSelf() *admin_nodeInfo {
 | 
				
			||||||
 | 
						table := a.core.switchTable.table.Load().(lookupTable)
 | 
				
			||||||
 | 
						addr := a.core.router.addr
 | 
				
			||||||
 | 
						coords := table.self.getCoords()
 | 
				
			||||||
 | 
						self := admin_nodeInfo{
 | 
				
			||||||
 | 
							{"IP", net.IP(addr[:]).String()},
 | 
				
			||||||
 | 
							{"coords", fmt.Sprint(coords)},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &self
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *admin) getData_getPeers() []admin_nodeInfo {
 | 
				
			||||||
 | 
						var peerInfos []admin_nodeInfo
 | 
				
			||||||
 | 
						table := a.core.switchTable.table.Load().(lookupTable)
 | 
				
			||||||
 | 
						peers := a.core.peers.ports.Load().(map[switchPort]*peer)
 | 
				
			||||||
 | 
						for _, elem := range table.elems {
 | 
				
			||||||
 | 
							peer, isIn := peers[elem.port]
 | 
				
			||||||
 | 
							if !isIn {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							addr := *address_addrForNodeID(getNodeID(&peer.box))
 | 
				
			||||||
 | 
							coords := elem.locator.getCoords()
 | 
				
			||||||
 | 
							info := admin_nodeInfo{
 | 
				
			||||||
 | 
								{"IP", net.IP(addr[:]).String()},
 | 
				
			||||||
 | 
								{"coords", fmt.Sprint(coords)},
 | 
				
			||||||
 | 
								{"port", fmt.Sprint(elem.port)},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							peerInfos = append(peerInfos, info)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return peerInfos
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *admin) getData_getDHT() []admin_nodeInfo {
 | 
				
			||||||
 | 
						var infos []admin_nodeInfo
 | 
				
			||||||
	getDHT := func() {
 | 
						getDHT := func() {
 | 
				
			||||||
		for i := 0; i < a.core.dht.nBuckets(); i++ {
 | 
							for i := 0; i < a.core.dht.nBuckets(); i++ {
 | 
				
			||||||
			b := a.core.dht.getBucket(i)
 | 
								b := a.core.dht.getBucket(i)
 | 
				
			||||||
			for _, v := range b.infos {
 | 
								for _, v := range b.infos {
 | 
				
			||||||
					destPorts := getPorts(v.coords)
 | 
									addr := *address_addrForNodeID(v.getNodeID())
 | 
				
			||||||
					addr := net.IP(address_addrForNodeID(v.nodeID_hidden)[:]).String()
 | 
									info := admin_nodeInfo{
 | 
				
			||||||
					var index [mDepth]switchPort
 | 
										{"IP", net.IP(addr[:]).String()},
 | 
				
			||||||
					copy(index[:], destPorts)
 | 
										{"coords", fmt.Sprint(v.coords)},
 | 
				
			||||||
					m[index] = addr
 | 
										{"bucket", fmt.Sprint(i)},
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									infos = append(infos, info)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	a.core.router.doAdmin(getDHT)
 | 
						a.core.router.doAdmin(getDHT)
 | 
				
			||||||
 | 
						return infos
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Look up everything we know from active sessions
 | 
					func (a *admin) getData_getSessions() []admin_nodeInfo {
 | 
				
			||||||
 | 
						var infos []admin_nodeInfo
 | 
				
			||||||
	getSessions := func() {
 | 
						getSessions := func() {
 | 
				
			||||||
		for _, sinfo := range a.core.sessions.sinfos {
 | 
							for _, sinfo := range a.core.sessions.sinfos {
 | 
				
			||||||
				destPorts := getPorts(sinfo.coords)
 | 
								// TODO? skipped known but timed out sessions?
 | 
				
			||||||
				var index [mDepth]switchPort
 | 
								info := admin_nodeInfo{
 | 
				
			||||||
				copy(index[:], destPorts)
 | 
									{"IP", net.IP(sinfo.theirAddr[:]).String()},
 | 
				
			||||||
				m[index] = net.IP(sinfo.theirAddr[:]).String()
 | 
									{"coords", fmt.Sprint(sinfo.coords)},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								infos = append(infos, info)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	a.core.router.doAdmin(getSessions)
 | 
						a.core.router.doAdmin(getSessions)
 | 
				
			||||||
 | 
						return infos
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *admin) getResponse_dot() []byte {
 | 
				
			||||||
 | 
						self := a.getData_getSelf().asMap()
 | 
				
			||||||
 | 
						myAddr := self["IP"]
 | 
				
			||||||
 | 
						peers := a.getData_getPeers()
 | 
				
			||||||
 | 
						dht := a.getData_getDHT()
 | 
				
			||||||
 | 
						sessions := a.getData_getSessions()
 | 
				
			||||||
 | 
						// Map of coords onto IP
 | 
				
			||||||
 | 
						m := make(map[string]string)
 | 
				
			||||||
 | 
						m[self["coords"]] = self["IP"]
 | 
				
			||||||
 | 
						for _, peer := range peers {
 | 
				
			||||||
 | 
							p := peer.asMap()
 | 
				
			||||||
 | 
							m[p["coords"]] = p["IP"]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, node := range dht {
 | 
				
			||||||
 | 
							n := node.asMap()
 | 
				
			||||||
 | 
							m[n["coords"]] = n["IP"]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, node := range sessions {
 | 
				
			||||||
 | 
							n := node.asMap()
 | 
				
			||||||
 | 
							m[n["coords"]] = n["IP"]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Start building a tree from all known nodes
 | 
						// Start building a tree from all known nodes
 | 
				
			||||||
	type nodeInfo struct {
 | 
						type nodeInfo struct {
 | 
				
			||||||
		name   string
 | 
							name   string
 | 
				
			||||||
			key    [mDepth]switchPort
 | 
							key    string
 | 
				
			||||||
			parent [mDepth]switchPort
 | 
							parent string
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		infos := make(map[[mDepth]switchPort]nodeInfo)
 | 
						infos := make(map[string]nodeInfo)
 | 
				
			||||||
	// First fill the tree with all known nodes, no parents
 | 
						// First fill the tree with all known nodes, no parents
 | 
				
			||||||
	for k, n := range m {
 | 
						for k, n := range m {
 | 
				
			||||||
		infos[k] = nodeInfo{
 | 
							infos[k] = nodeInfo{
 | 
				
			||||||
| 
						 | 
					@ -125,14 +244,18 @@ func (a *admin) handleRequest(conn net.Conn) {
 | 
				
			||||||
			key:  k,
 | 
								key:  k,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// Get coords as a slice of strings, FIXME? this looks very fragile
 | 
				
			||||||
 | 
						coordSlice := func(coords string) []string {
 | 
				
			||||||
 | 
							tmp := strings.Replace(coords, "[", "", -1)
 | 
				
			||||||
 | 
							tmp = strings.Replace(tmp, "]", "", -1)
 | 
				
			||||||
 | 
							return strings.Split(tmp, " ")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	// Now go through and create placeholders for any missing nodes
 | 
						// Now go through and create placeholders for any missing nodes
 | 
				
			||||||
	for _, info := range infos {
 | 
						for _, info := range infos {
 | 
				
			||||||
			for idx, port := range info.key {
 | 
							// This is ugly string manipulation
 | 
				
			||||||
				if port == 0 {
 | 
							coordsSplit := coordSlice(info.key)
 | 
				
			||||||
					break
 | 
							for idx := range coordsSplit {
 | 
				
			||||||
				}
 | 
								key := fmt.Sprintf("[%v]", strings.Join(coordsSplit[:idx], " "))
 | 
				
			||||||
				var key [mDepth]switchPort
 | 
					 | 
				
			||||||
				copy(key[:idx], info.key[:])
 | 
					 | 
				
			||||||
			newInfo, isIn := infos[key]
 | 
								newInfo, isIn := infos[key]
 | 
				
			||||||
			if isIn {
 | 
								if isIn {
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
| 
						 | 
					@ -144,41 +267,36 @@ func (a *admin) handleRequest(conn net.Conn) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Now go through and attach parents
 | 
						// Now go through and attach parents
 | 
				
			||||||
	for _, info := range infos {
 | 
						for _, info := range infos {
 | 
				
			||||||
			info.parent = info.key
 | 
							pSplit := coordSlice(info.key)
 | 
				
			||||||
			for idx := len(info.parent) - 1; idx >= 0; idx-- {
 | 
							if len(pSplit) > 0 {
 | 
				
			||||||
				if info.parent[idx] != 0 {
 | 
								pSplit = pSplit[:len(pSplit)-1]
 | 
				
			||||||
					info.parent[idx] = 0
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							info.parent = fmt.Sprintf("[%v]", strings.Join(pSplit, " "))
 | 
				
			||||||
		infos[info.key] = info
 | 
							infos[info.key] = info
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Finally, get a sorted list of keys, which we use to organize the output
 | 
						// Finally, get a sorted list of keys, which we use to organize the output
 | 
				
			||||||
		var keys [][mDepth]switchPort
 | 
						var keys []string
 | 
				
			||||||
	for _, info := range infos {
 | 
						for _, info := range infos {
 | 
				
			||||||
		keys = append(keys, info.key)
 | 
							keys = append(keys, info.key)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// TODO sort
 | 
				
			||||||
	less := func(i, j int) bool {
 | 
						less := func(i, j int) bool {
 | 
				
			||||||
			for idx := range keys[i] {
 | 
							return keys[i] < keys[j]
 | 
				
			||||||
				if keys[i][idx] < keys[j][idx] {
 | 
					 | 
				
			||||||
					return true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if keys[i][idx] > keys[j][idx] {
 | 
					 | 
				
			||||||
					return false
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sort.Slice(keys, less)
 | 
						sort.Slice(keys, less)
 | 
				
			||||||
	// Now print it all out
 | 
						// Now print it all out
 | 
				
			||||||
		conn.Write([]byte(fmt.Sprintf("digraph {\n")))
 | 
						var out []byte
 | 
				
			||||||
 | 
						put := func(s string) {
 | 
				
			||||||
 | 
							out = append(out, []byte(s)...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						put("digraph {\n")
 | 
				
			||||||
	// First set the labels
 | 
						// First set the labels
 | 
				
			||||||
	for _, key := range keys {
 | 
						for _, key := range keys {
 | 
				
			||||||
		info := infos[key]
 | 
							info := infos[key]
 | 
				
			||||||
		if info.name == myAddr {
 | 
							if info.name == myAddr {
 | 
				
			||||||
				conn.Write([]byte(fmt.Sprintf("\"%v\" [ style = \"filled\", label = \"%v\" ];\n", info.key, info.name)))
 | 
								put(fmt.Sprintf("\"%v\" [ style = \"filled\", label = \"%v\" ];\n", info.key, info.name))
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
				conn.Write([]byte(fmt.Sprintf("\"%v\" [ label = \"%v\" ];\n", info.key, info.name)))
 | 
								put(fmt.Sprintf("\"%v\" [ label = \"%v\" ];\n", info.key, info.name))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Then print the tree structure
 | 
						// Then print the tree structure
 | 
				
			||||||
| 
						 | 
					@ -187,23 +305,13 @@ func (a *admin) handleRequest(conn net.Conn) {
 | 
				
			||||||
		if info.key == info.parent {
 | 
							if info.key == info.parent {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		} // happens for the root, skip it
 | 
							} // happens for the root, skip it
 | 
				
			||||||
			for idx := len(info.key) - 1; idx >= 0; idx-- {
 | 
							coordsSplit := coordSlice(key)
 | 
				
			||||||
				port := info.key[idx]
 | 
							if len(coordsSplit) == 0 {
 | 
				
			||||||
				if port == 0 {
 | 
					 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
				conn.Write([]byte(fmt.Sprintf("  \"%+v\" -> \"%+v\" [ label = \"%v\" ];\n", info.parent, info.key, port)))
 | 
							port := coordsSplit[len(coordsSplit)-1]
 | 
				
			||||||
				break
 | 
							put(fmt.Sprintf("  \"%+v\" -> \"%+v\" [ label = \"%v\" ];\n", info.parent, info.key, port))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		}
 | 
						put("}\n")
 | 
				
			||||||
		conn.Write([]byte(fmt.Sprintf("}\n")))
 | 
						return out
 | 
				
			||||||
		break
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		conn.Write([]byte("I didn't understand that!\n"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		a.core.log.Printf("Admin socket error: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	conn.Close()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue