diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b132854..de4ba0b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +* Implement and use golang endpoint for getting IPs of the device, also fixes duplicate IP reporting in the JS implementation [Praneeth] * Refactor bootstrapping to run in background [Pablo] * Run preloaded app images [Pablo] * Add API endpoints for device reboot and shutdown [Pablo] diff --git a/gosuper/gosuper/api.go b/gosuper/gosuper/api.go index 12624794..5691fb04 100644 --- a/gosuper/gosuper/api.go +++ b/gosuper/gosuper/api.go @@ -4,9 +4,11 @@ import ( "encoding/json" "fmt" "log" + "net" "net/http" "os" "strconv" + "strings" "time" "resin-supervisor/gosuper/systemd" @@ -112,3 +114,56 @@ func ShutdownHandler(writer http.ResponseWriter, request *http.Request) { sendResponse("OK", "", http.StatusAccepted) go inASecond(func() { systemd.Logind.PowerOff(false) }) } + +// This function returns all active IPs of the interfaces that arent docker/rce and loopback +func ipAddress() ([]string, error) { + ipAddr := []string{} + ifaces, err := net.Interfaces() + if err != nil { + return ipAddr, err + } + for _, iface := range ifaces { + if (iface.Flags&net.FlagUp == 0) || (iface.Flags&net.FlagLoopback != 0) || strings.Contains(iface.Name, "docker") || strings.Contains(iface.Name, "rce") { + continue // Interface down or Interface is loopback or Interface is a docker IP + } + addrs, err := iface.Addrs() + if err != nil { + return ipAddr, err + } + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + if ip == nil { + continue + } else { + ip = ip.To4() + if ip == nil { + continue // This isnt an IPv4 Addresss + } else { + ipAddr = append(ipAddr, ip.String()) + } + } + } + } + return ipAddr, nil +} + +//IPAddressHandler is used to reply back with an array of the IPaddress used by the system. +func IPAddressHandler(writer http.ResponseWriter, request *http.Request) { + // log.Println("Fetching IP Address'") - Not logging this as this is called every 30 seconds. + sendResponse := responseSender(writer) + sendError := func(err string) { + sendResponse("Error", err, http.StatusInternalServerError) + } + + if ipAddr, err := ipAddress(); err != nil { + sendError("Invalid request") + } else { + sendResponse(strings.Join(ipAddr, " "), "", http.StatusOK) + } +} diff --git a/gosuper/gosuper/main.go b/gosuper/gosuper/main.go index 807bbd73..005892cb 100644 --- a/gosuper/gosuper/main.go +++ b/gosuper/gosuper/main.go @@ -18,6 +18,7 @@ func setupApi(router *mux.Router) { }) apiv1 := router.PathPrefix("/v1").Subrouter() + apiv1.HandleFunc("/ipaddr", IPAddressHandler).Methods("GET") apiv1.HandleFunc("/purge", PurgeHandler).Methods("POST") apiv1.HandleFunc("/reboot", RebootHandler).Methods("POST") apiv1.HandleFunc("/shutdown", ShutdownHandler).Methods("POST") diff --git a/src/app.coffee b/src/app.coffee index 3bbc4d2b..45a04e3e 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -6,6 +6,7 @@ knex = require './db' utils = require './utils' bootstrap = require './bootstrap' config = require './config' +request = require 'request' knex.init.then -> utils.mixpanelTrack('Supervisor start') @@ -54,10 +55,14 @@ knex.init.then -> application.update() updateIpAddr = -> - utils.findIpAddrs().then (ipAddrs) -> - device.updateState( - ip_address: ipAddrs.join(' ') - ) + callback = (error, response, body ) -> + if !error && response.statusCode == 200 + api_response = JSON.parse(body) + device.updateState( + ip_address: api_response.Status + ) + request.get(config.gosuperAddress + '/v1/ipaddr', callback ) + console.log('Starting periodic check for IP addresses..') setInterval(updateIpAddr, 30 * 1000) # Every 30s updateIpAddr() diff --git a/src/utils.coffee b/src/utils.coffee index c6066264..1394d358 100644 --- a/src/utils.coffee +++ b/src/utils.coffee @@ -35,31 +35,6 @@ exports.mixpanelTrack = (event, properties = {}) -> mixpanelClient.track(event, properties) -# Returns an array of the host's ip address(es) by parsing the host /proc/net/fib_trie -exports.findIpAddrs = -> - fs.readFileAsync('/mnt/fib_trie', 'utf8') - .then (fibtrie) -> - prevLine = '' - fibtrie.split('\n') - .map (line) -> - line = line.trim() - - # We only care about LOCAL routes (not UNICAST or BROADCAST) - if line.match(/LOCAL$/) - # Then we make sure the previous line was an ending branch (and hence contains an IP - 127.0.0.0 has - # BROADCAST and LOCAL entries) - if prevLine.match(/^\|--/) - # Then we remove the ending branch bit - maybeAddr = prevLine.replace(/^\|--/, '').trim() - # And ignore loopback/docker interfaces. - # TODO: Docker interface can technically be on another address range if 172.17 - if !maybeAddr.match(/^(127.0.0.1|172.17.)/) - ipAddr = maybeAddr - - prevLine = line - return ipAddr - .filter(Boolean) - networkPattern = blinks: 4 pause: 1000