Author: bklaas
Date: Thu Jan  8 12:03:41 2009
New Revision: 3740

URL: http://svn.slimdevices.com?rev=3740&root=Jive&view=rev
Log:
Bug: 10526
Description: refactor Wireless class

jive.net.Wireless becomes jive.net.Networking and the constructor is slightly 
different

               local wirelessInterface = Networking:wirelessInterface()
               local wireless = Networking(jnt, wirelessInterface)


Added:
    
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/jive/net/Networking.lua
Removed:
    7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/jive/net/Wireless.lua
Modified:
    
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SelectPlayer/SelectPlayerApplet.lua
    
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SetupSqueezebox/SetupSqueezeboxApplet.lua
    
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimDiscovery/SlimDiscoveryApplet.lua
    
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SetupWelcome/SetupWelcomeApplet.lua
    
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SqueezeboxJive/SqueezeboxJiveApplet.lua
    
7.4/trunk/squeezeplay/src/squeezeplay_jive/specialProjects/sbcPosSlideshow/SqueezeboxJiveApplet.lua
    
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupWireless/SetupWirelessApplet.lua

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SelectPlayer/SelectPlayerApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SelectPlayer/SelectPlayerApplet.lua?rev=3740&root=Jive&r1=3739&r2=3740&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SelectPlayer/SelectPlayerApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SelectPlayer/SelectPlayerApplet.lua
 Thu Jan  8 12:03:41 2009
@@ -36,7 +36,7 @@
 local Surface            = require("jive.ui.Surface")
 local LocalPlayer        = require("jive.slim.LocalPlayer")
 
-local hasWireless, Wireless  = pcall(require, "jive.net.Wireless")
+local hasNetworking, Networking  = pcall(require, "jive.net.Networking")
 
 local log                = require("jive.utils.log").logger("applets.setup")
 local debug              = require("jive.utils.debug")
@@ -61,8 +61,11 @@
        self.serverItem = {}
        self.scanResults = {}
 
-       if hasWireless then
-               self.wireless = Wireless(jnt, "eth0")
+       if hasNetworking then
+               local wirelessInterface = Networking:wirelessInterface()
+               if wirelessInterface then
+                       self.wireless = Networking(jnt, wirelessInterface)
+               end
        end
 
        jnt:subscribe(self)

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SetupSqueezebox/SetupSqueezeboxApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SetupSqueezebox/SetupSqueezeboxApplet.lua?rev=3740&root=Jive&r1=3739&r2=3740&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SetupSqueezebox/SetupSqueezeboxApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SetupSqueezebox/SetupSqueezeboxApplet.lua
 Thu Jan  8 12:03:41 2009
@@ -27,7 +27,7 @@
 local Player                 = require("jive.slim.Player")
 
 local Udap                   = require("jive.net.Udap")
-local hasWireless, Wireless  = pcall(require, "jive.net.Wireless")
+local hasNetworking, Networking  = pcall(require, "jive.net.Networking")
 
 local log                    = 
require("jive.utils.log").logger("applets.setup")
 
@@ -108,8 +108,11 @@
                error("No player discovery")
        end
 
-       if hasWireless then
-               self.wireless = Wireless(jnt, "eth0")
+       if hasNetworking then
+               local wirelessInterface = Networking:wirelessInterface()
+               if wirelessInterface then
+                       self.wireless = Networking(jnt, wirelessInterface)
+               end
        end
 
        -- socket for udap discovery
@@ -143,7 +146,7 @@
        -- note we keep old entries so this list the window is not empty
        -- during initial setup. if this becomes a problem a "finding
        -- squeezeboxen" screen will need to be added.
-       if hasWireless then
+       if self.wireless then
                self:_scanComplete(self.wireless:scanResults(), keepOldEntries)
        end
 
@@ -203,7 +206,7 @@
 
 
 function _scan(self)
-       if hasWireless then
+       if self.wireless then
                self.wireless:scan(function(scanTable)
                                           _scanComplete(self, scanTable)
                                   end)

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimDiscovery/SlimDiscoveryApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimDiscovery/SlimDiscoveryApplet.lua?rev=3740&root=Jive&r1=3739&r2=3740&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimDiscovery/SlimDiscoveryApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimDiscovery/SlimDiscoveryApplet.lua
 Thu Jan  8 12:03:41 2009
@@ -37,7 +37,7 @@
 local SocketUdp     = require("jive.net.SocketUdp")
 local Udap          = require("jive.net.Udap")
 
-local hasWireless, Wireless  = pcall(require, "jive.net.Wireless")
+local hasNetworking, Networking  = pcall(require, "jive.net.Networking")
 
 local Player        = require("jive.slim.Player")
 local SlimServer    = require("jive.slim.SlimServer")
@@ -217,8 +217,11 @@
                end)
 
        -- wireless discovery
-       if hasWireless then
-               obj.wireless = Wireless(jnt, "eth0")
+       if hasNetworking then
+               local wirelessInterface = Networking:wirelessInterface()
+               if wirelessInterface then
+                       obj.wireless = Networking(jnt, wirelessInterface)
+               end
        end
 
        -- discovery timer
@@ -253,7 +256,7 @@
        self.udap:send(function() return packet end, "255.255.255.255")
 
        -- Wireless discovery, only in probing state
-       if self.state == 'probing' and hasWireless then
+       if self.state == 'probing' and self.wireless then
                self.wireless:scan(
                        function(scanTable)
                                _scanComplete(self, scanTable)

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SetupWelcome/SetupWelcomeApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SetupWelcome/SetupWelcomeApplet.lua?rev=3740&root=Jive&r1=3739&r2=3740&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SetupWelcome/SetupWelcomeApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SetupWelcome/SetupWelcomeApplet.lua
 Thu Jan  8 12:03:41 2009
@@ -32,7 +32,7 @@
 local Textarea         = require("jive.ui.Textarea")
 local Window           = require("jive.ui.Window")
 
-local Wireless         = require("jive.net.Wireless")
+local Networking       = require("jive.net.Networking")
 
 local log              = require("jive.utils.log").logger("applets.setup")
 local locale           = require("jive.utils.locale")
@@ -141,7 +141,7 @@
        log:info("step5")
 
        -- wireless connection, using squeezebox?
-       local scanResults = Wireless.scanResults()
+       local scanResults = Networking.scanResults()
 
        for ssid,_ in pairs(scanResults) do
                log:warn("checking ssid ", ssid)
@@ -174,7 +174,7 @@
        log:info("step6")
 
        -- wireless connection, using squeezebox?
-       local scanResults = Wireless.scanResults()
+       local scanResults = Networking.scanResults()
 
        for ssid,_ in pairs(scanResults) do
                log:warn("checking ssid ", ssid)

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SqueezeboxJive/SqueezeboxJiveApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SqueezeboxJive/SqueezeboxJiveApplet.lua?rev=3740&root=Jive&r1=3739&r2=3740&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SqueezeboxJive/SqueezeboxJiveApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_jive/share/applets/SqueezeboxJive/SqueezeboxJiveApplet.lua
 Thu Jan  8 12:03:41 2009
@@ -10,7 +10,7 @@
 
 local jiveBSP                = require("jiveBSP")
 local Watchdog               = require("jiveWatchdog")
-local Wireless               = require("jive.net.Wireless")
+local Networking             = require("jive.net.Networking")
 local LocalPlayer            = require("jive.slim.LocalPlayer")
 
 local Applet                 = require("jive.Applet")
@@ -146,7 +146,8 @@
                                 end)
 
        -- wireless
-       self.wireless = Wireless(jnt, "eth0")
+       local wireless = Networking:wirelessInterface()
+       self.wireless = Networking(jnt, wireless)
 
        -- register network active function
        jnt:registerNetworkActive(function(active)

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay_jive/specialProjects/sbcPosSlideshow/SqueezeboxJiveApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_jive/specialProjects/sbcPosSlideshow/SqueezeboxJiveApplet.lua?rev=3740&root=Jive&r1=3739&r2=3740&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_jive/specialProjects/sbcPosSlideshow/SqueezeboxJiveApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_jive/specialProjects/sbcPosSlideshow/SqueezeboxJiveApplet.lua
 Thu Jan  8 12:03:41 2009
@@ -10,7 +10,7 @@
 
 local jiveBSP                = require("jiveBSP")
 local Watchdog               = require("jiveWatchdog")
-local Wireless               = require("jive.net.Wireless")
+local Networking             = require("jive.net.Networking")
 
 local Applet                 = require("jive.Applet")
 local Audio                  = require("jive.ui.Audio")
@@ -143,7 +143,8 @@
                                 end)
 
        -- wireless
-       self.wireless = Wireless(jnt, "eth0")
+       local wireless = Networking:wirelessInterface()
+       self.wireless = Networking(jnt, wireless)
 
        -- register network active function
        jnt:registerNetworkActive(function(active)
@@ -1012,6 +1013,7 @@
 
 
 function _wlanPowerSave(self, active)
+
        if active ~= nil then
                -- update the network active state
                self.networkActive = active

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupWireless/SetupWirelessApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupWireless/SetupWirelessApplet.lua?rev=3740&root=Jive&r1=3739&r2=3740&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupWireless/SetupWirelessApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupWireless/SetupWirelessApplet.lua
 Thu Jan  8 12:03:41 2009
@@ -32,7 +32,7 @@
 local Window                 = require("jive.ui.Window")
 local Popup                  = require("jive.ui.Popup")
 
-local Wireless               = require("jive.net.Wireless")
+local Networking             = require("jive.net.Networking")
 
 local log                    = 
require("jive.utils.log").logger("applets.setup")
 
@@ -59,7 +59,10 @@
 
 
 function init(self)
-       self.t_ctrl = Wireless(jnt, "eth0")
+
+       local wirelessInterface = Networking:wirelessInterface()
+       self.t_ctrl = Networking(jnt, wirelessInterface)
+
 end
 
 
@@ -702,7 +705,7 @@
 
 
 -- FIXME this function and associated attach/detach functions should
--- be refactored into Wireless.lua with callbacks on approriate events.
+-- be refactored into Networking.lua with callbacks on approriate events.
 function _eventSink(self, chunk)
        log:warn("wpa-cli event: ", chunk)
 

Added: 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/jive/net/Networking.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/jive/net/Networking.lua?rev=3740&root=Jive&view=auto
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/jive/net/Networking.lua 
(added)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/jive/net/Networking.lua 
Thu Jan  8 12:03:41 2009
@@ -1,0 +1,1095 @@
+--[[
+=head1 NAME
+
+jive.net.Networking 
+
+=head1 DESCRIPTION
+
+This class implements methods for administering network interfaces.
+
+Much of the methods in this class need to be done through Task. These methods 
are by convention prefixed with t_
+
+=head1 SYNOPSIS
+
+pull in networking object to manipulate wireless interface
+
+       local wirelessInterface = Networking:wirelessInterface()
+       local wireless = Networking(jnt, wirelessInterface)
+
+=head1 FUNCTIONS
+
+=cut
+--]]
+
+local assert, ipairs, pairs, pcall, tonumber, tostring, type = assert, ipairs, 
pairs, pcall, tonumber, tostring, type
+
+local oo          = require("loop.simple")
+
+local io          = require("io")
+local os          = require("os")
+local string      = require("string")
+local table       = require("jive.utils.table")
+local ltn12       = require("ltn12")
+
+local debug       = require("jive.utils.debug")
+local log         = require("jive.utils.log").logger("net.socket")
+
+local Framework   = require("jive.ui.Framework")
+local Socket      = require("jive.net.Socket")
+local Task        = require("jive.ui.Task")
+local wireless    = require("jiveWireless")
+
+
+module("jive.net.Networking")
+oo.class(_M, Socket)
+
+
+local SSID_TIMEOUT = 20000
+
+-- wpa scan results signal level -> quality
+-- FIXME tune with production boards
+local WIRELESS_LEVEL = {
+       0,
+       175,
+       180,
+       190,
+}
+
+-- iwpriv snr -> quality
+-- FIXME tune with production boards
+local WIRELESS_SNR = {
+       0,
+       10,
+       18,
+       25,
+}
+
+-- FIXME check this region mapping is correct for Marvell and Atheros
+local REGION_CODE_MAPPING = {
+       -- name, marvell code, atheros code
+       [ "US" ] = { 0x10, 4  }, -- ch 1-11
+       [ "CA" ] = { 0x20, 6  }, -- ch 1-11
+       [ "EU" ] = { 0x30, 14 }, -- ch 1-13
+       [ "FR" ] = { 0x30, 13 }, -- ch 1-13
+       [ "CH" ] = { 0x30, 23 }, -- ch 1-13
+       [ "TW" ] = { 0x30, 21 }, -- ch 1-13
+       [ "AU" ] = { 0x10, 7  }, -- ch 1-11
+       [ "JP" ] = { 0x41, 16 }, -- ch 1-13
+}
+
+
+-- global for storing data on available network interfaces
+local interfaceTable = {}
+
+-- global wireless network scan results
+local _scanResults = {}
+
+-- singleton wireless instance per interface
+local _instance = {}
+
+--[[
+
+=head2 jive.net.Networking(jnt, interface, name)
+
+Constructs an object for administration of a network interface
+
+=cut
+--]]
+
+function __init(self, jnt, interface, name)
+
+       if _instance[interface] then
+               return _instance[interface]
+       end
+
+       local obj = oo.rawnew(self, Socket(jnt, name))
+
+       obj.interface     = interface
+       obj.isWireless    = ( interfaceTable[interface] and 
interfaceTable[interface].isWireless ) 
+                               or obj:isWireless(interface)
+       log:debug('Interface : ', obj.interface)
+       log:debug('isWireless: ', obj.isWireless)
+       obj.responseQueue = {}
+
+       obj:open()
+
+       _instance[interface] = obj
+       return obj
+end
+
+--[[
+
+=head2 jive.net.Networking:interfaces()
+
+returns a table of existing interfaces on a device
+
+=cut
+--]]
+
+
+function interfaces(self)
+
+       log:debug('scanning /proc/net/dev for interfaces...')
+
+       for i, v in ipairs(interfaceTable) do
+               if i then
+                       return interfaceTable
+               end
+       end
+
+        local interfaces = {}
+
+        local f = io.popen("cat /proc/net/dev")
+        if f == nil then
+                return interfaces
+        end
+
+       while true do
+               local line = f:read("*l")
+               if line == nil then
+                       break
+               end
+               local interface = string.match(line, "^%s*(%w+):")
+               if interface ~= nil and interface ~= 'lo' then
+                       table.insert(interfaces, interface)
+               end
+       end
+
+       for _, interface in ipairs(interfaces) do
+               if not interfaceTable[interface] then
+                       interfaceTable[interface] = {}
+               end
+               self:isWireless(interface)
+       end
+
+        f:close()
+        return interfaces
+
+end
+
+--[[
+
+=head2 jive.net.Networking:wirelessInterface()
+
+returns the first interface (if any) from the interface table capable of 
wireless
+
+=cut
+--]]
+
+
+function wirelessInterface(self)
+
+        self:interfaces()
+
+       for _, v in ipairs(interfaceTable) do
+               if self:isWireless(v) then
+                       log:debug('Wireless interface found: ', v)
+                       return v
+               end
+       end
+
+       log:error('Error: interfaceTable shows no wireless interface. returning 
eth0, the default wireless on SBC')
+       return 'eth0'
+
+end
+
+
+--[[
+
+=head2 jive.net.Networking:wiredInterface()
+
+returns the first available interface (if any) from the interface table that 
does not do wireless
+
+=cut
+--]]
+
+
+function wiredInterface(self)
+
+        self:interfaces()
+
+       for _, v in ipairs(interfaceTable) do
+               if not self:isWireless(v) then
+                       return v
+               end
+       end
+       return false
+end
+
+--[[
+
+=head2 jive.net.Networking:isWireless(interface)
+
+returns true if the named I<interface> is wireless
+
+=cut
+--]]
+
+function isWireless(self, interface)
+
+       if not interface then
+               return false
+       end
+
+       -- look to see if we've cached this already
+       if interfaceTable[interface] and interfaceTable[interface].isWireless 
then
+               return true
+       end
+
+       local f = io.popen("/sbin/iwconfig " .. interface .. " 2>/dev/null")
+        if f == nil then
+                return false
+        end
+
+       while true do
+               local line = f:read("*l")
+               if line == nil then
+                       break
+               end
+               local doesWireless = string.match(line, "^(%w+)%s+")
+               if interface == doesWireless then
+                       interfaceTable[interface]['isWireless'] = true
+                       f:close()
+                       return true
+               end
+       end
+
+        f:close()
+
+       return false
+       
+end
+
+--[[
+
+=head2 jive.net.Networking:getRegionNames()
+
+returns the available wireless region names
+
+=cut
+--]]
+
+function getRegionNames(self)
+       return pairs(REGION_CODE_MAPPING)
+end
+
+--[[
+
+=head2 jive.net.Networking:getRegion()
+
+returns the current region
+
+=cut
+--]]
+
+
+function getRegion(self)
+       -- check config file
+       local fh = io.open("/etc/network/config")
+       if fh then
+               local file = fh:read("*a")
+               fh:close()
+
+               local region = string.match(file, "REGION=([^%s]+)")
+               if  region then
+                       return region
+               end
+       end
+       
+       -- check marvell region
+       local fh = assert(io.popen("/sbin/iwpriv " .. self.interface .. " 
getregioncode"))
+       local line = fh:read("*a")
+       fh:close()
+
+       local code = tonumber(string.match(line, "getregioncode:(%d+)"))
+
+       for name,mapping in pairs(REGION_CODE_MAPPING) do
+               log:info("code=", code, " mapping[1]=", mapping[1])
+               if mapping[1] == code then
+                       log:info("returning=", name)
+                       return name
+               end
+       end
+       return nil
+end
+
+--[[
+
+=head2 jive.net.Networking:setRegion(region)
+
+sets the current region
+
+=cut
+--]]
+
+function setRegion(self, region)
+       if type(self.interface) ~= "string" then
+               return
+       end
+       local mapping = REGION_CODE_MAPPING[region]
+       if not mapping then
+               return
+       end
+
+       -- save config file
+       local fh = assert(io.open("/etc/network/config", "w"))
+       fh:write("REGION=" .. region .. "\n")
+       fh:write("REGIONCODE=" .. mapping[1] .. "\n")
+       fh:close()
+
+       -- set new region
+       local cmd = "/sbin/iwpriv " .. self.interface .. " setregioncode " .. 
mapping[1]
+       log:info("setRegion: ", cmd)
+       os.execute(cmd)
+end
+
+
+--[[
+
+=head2 jive.net.Networking:getMarvellRegionCode()
+
+returns the region code for Marvell on Jive
+
+=cut
+--]]
+
+function getMarvellRegionCode(self)
+       local mapping = REGION_CODE_MAPPING[region or self:getRegion()]
+       return mapping and mapping[1] or 0
+end
+
+--[[
+
+=head2 jive.net.Networking:getAtherosRegionCode()
+
+returns the region code for Atheros on Squeezebox
+
+=cut
+--]]
+
+
+function getAtherosRegionCode(self)
+       local mapping = REGION_CODE_MAPPING[region or self:getRegion()]
+       return mapping and mapping[2] or 0
+end
+
+--[[
+
+=head2 jive.net.Networking:scan(callback)
+
+start a wireless network scan in a new task
+
+=cut
+--]]
+
+function scan(self, callback)
+       Task("networkScan", self,
+            function()
+                    t_scan(self, callback)
+            end):addTask()
+end
+
+--[[
+
+=head2 jive.net.Networking:scanResults()
+
+returns wireless scan results, or nil if a network scan has not been performed.
+
+=cut
+--]]
+
+function scanResults(self)
+       return _scanResults
+end
+
+--[[
+
+=head2 jive.net.Networking:t_scan(callback)
+
+network scanning. this can take a little time so we do this in 
+the network thread so the ui is not blocked.
+
+=cut
+--]]
+
+
+function t_scan(self, callback)
+       assert(Task:running(), "Networking:scan must be called in a Task")
+
+       local status, err = self:request("SCAN")
+       if err then
+               return
+       end
+
+       local status, err = self:request("STATUS")
+       if err then
+               return
+       end
+
+       local associated = string.match(status, "\nssid=([^\n]+)")
+
+       local scanResults, err = self:request("SCAN_RESULTS")
+       if err then
+               return
+       end
+
+       _scanResults = _scanResults or {}
+
+       local now = Framework:getTicks()
+
+       for bssid, level, flags, ssid in string.gmatch(scanResults, 
"([%x:]+)\t%d+\t(%d+)\t(%S*)\t([^\n]+)\n") do
+
+               local quality = 1
+               level = tonumber(level)
+               for i, l in ipairs(WIRELESS_LEVEL) do
+                       if level < l then
+                               break
+                       end
+                       quality = i
+               end
+
+               _scanResults[ssid] = {
+                       bssid = string.lower(bssid),
+                       flags = flags,
+                       level = level,
+                       quality = quality,
+                       associated = (ssid == associated),
+                       lastScan = now
+               }
+       end
+
+       for ssid, entry in pairs(_scanResults) do
+               if now - entry.lastScan > SSID_TIMEOUT then
+                       _scanResults[ssid] = nil
+               end
+       end
+
+       -- Bug #5227 if we are associated use the same quality indicator
+       -- as the icon bar
+       if associated and _scanResults[associated] then
+               _scanResults[associated].quality = self:getLinkQuality()
+       end
+
+       if callback then
+               callback(_scanResults)
+       end
+
+       self.scanTask = nil
+end
+
+--[[
+
+=head2 jive.net.Networking:t_wpaStatus()
+
+parse and return wpa status
+
+=cut
+--]]
+
+function t_wpaStatus(self)
+       assert(Task:running(), "Networking:wpaStatus must be called in a Task")
+
+       local statusStr = self:request("STATUS")
+
+       local status = {}
+       for k,v in string.gmatch(statusStr, "([^=]+)=([^\n]+)\n") do
+               status[k] = v
+       end
+
+       return status
+end
+
+--[[
+
+=head2 jive.net.Networking:t_addNetwork(ssid, option)
+
+adds a network to the list of discovered networks
+
+=cut
+--]]
+
+
+function t_addNetwork(self, ssid, option)
+       assert(Task:running(), "Networking:addNetwork must be called in a Task")
+
+       local request, response
+
+       -- make sure this ssid is not in any configuration
+       self:t_removeNetwork(ssid)
+
+       log:info("Connect to ", ssid)
+       local flags = (_scanResults[ssid] and _scanResults[ssid].flags) or ""
+
+       -- Set to use dhcp by default
+       self:_editNetworkInterfaces(ssid, "dhcp", "script 
/etc/network/udhcpc_action")
+
+       response = self:request("ADD_NETWORK")
+       local id = string.match(response, "%d+")
+       assert(id, "wpa_cli failed: to add network")
+
+       request = 'SET_NETWORK ' .. id .. ' ssid "' .. ssid .. '"'
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+
+       if string.find(flags, "IBSS") or option.ibss then
+               request = 'SET_NETWORK ' .. id .. ' mode 1 '
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+       end
+
+       if option.encryption == "wpa" then
+               log:info("encryption WPA")
+
+               request = 'SET_NETWORK ' .. id .. ' key_mgmt WPA-PSK'
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+
+               request = 'SET_NETWORK ' .. id .. ' proto WPA'
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+
+               -- Setting the PSK can timeout
+               pcall(function()
+                             request = 'SET_NETWORK ' .. id .. ' psk "' .. 
option.psk .. '"'
+                             assert(self:request(request) == "OK\n", "wpa_cli 
failed:" .. request)
+                     end)
+       elseif option.encryption == "wpa2" then
+               log:info("encryption WPA2")
+
+               request = 'SET_NETWORK ' .. id .. ' key_mgmt WPA-PSK'
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+
+               request = 'SET_NETWORK ' .. id .. ' proto WPA2'
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+
+               -- Setting the PSK can timeout
+               pcall(function()
+                             request = 'SET_NETWORK ' .. id .. ' psk "' .. 
option.psk .. '"'
+                             assert(self:request(request) == "OK\n", "wpa_cli 
failed:" .. request)
+                     end)
+       else
+               request = 'SET_NETWORK ' .. id .. ' key_mgmt NONE'
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+       end
+
+       if option.encryption == "wep40" or option.encryption == "wep104" then
+               log:info("encryption WEP")
+
+               request = 'SET_NETWORK ' .. id .. ' wep_key0 ' .. option.key
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+       end
+
+       -- If we have not scanned the ssid then enable scanning with ssid 
+       -- specific probe requests. This allows us to find APs with hidden
+       -- SSIDS
+       if not _scanResults[ssid] then
+               request = 'SET_NETWORK ' .. id .. ' scan_ssid 1'
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+       end
+
+       -- Disconnect from existing network
+       self:t_disconnectNetwork()
+
+       -- Use select network to disable all other networks
+       request = 'SELECT_NETWORK ' .. id
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+
+       -- Allow association
+       request = 'REASSOCIATE'
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+
+       -- Save config, it will be removed later if it fails
+       request = 'SAVE_CONFIG'
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+
+       return id
+end
+
+--[[
+
+=head2 jive.net.Networking:t_removeNetwork(ssid)
+
+forgets a previously discovered network 
+
+=cut
+--]]
+
+function t_removeNetwork(self, ssid)
+       assert(Task:running(), "Networking:removeNetwork must be called in a 
Task")
+
+       local networkResults = self:request("LIST_NETWORKS")
+
+       local id = false
+       for nid, nssid in string.gmatch(networkResults, 
"([%d]+)\t([^\t]*).-\n") do
+               if nssid == ssid then
+                       id = nid
+                       break
+               end
+       end
+
+       -- Remove ssid from wpa supplicant
+       if id then
+               local request = 'REMOVE_NETWORK ' .. id
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+
+               request = 'SAVE_CONFIG'
+               assert(self:request(request) == "OK\n", "wpa_cli failed:" .. 
request)
+       end
+
+       -- Remove dhcp/static ip configuration for network
+       self:_editNetworkInterfaces(ssid)
+end
+
+--[[
+
+=head2 jive.net.Networking:t_disconnectNetwork()
+
+brings down a network interface. If wireless, then force the wireless 
disconnect as well
+
+=cut
+--]]
+
+function t_disconnectNetwork(self)
+
+       assert(type(self.interface) == 'string')
+       assert(Task:running(), "Networking:disconnectNetwork must be called in 
a Task")
+
+       -- Force disconnect from existing network
+       local request = 'DISCONNECT'
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+
+       -- Force the interface down
+       local ifDown = "/sbin/ifdown -f " .. self.interface
+       os.execute(ifDown)
+end
+
+--[[
+
+=head2 jive.net.Networking:t_selectNetwork(ssid)
+
+selects a network to connect to. wireless only
+
+=cut
+--]]
+
+
+function t_selectNetwork(self, ssid)
+
+       assert(Task:running(), "Networking:selectNetwork must be called in a 
Task")
+
+       local networkResults = self:request("LIST_NETWORKS")
+       log:info("list results ", networkResults)
+
+       local id = false
+       for nid, nssid in string.gmatch(networkResults, 
"([%d]+)\t([^\t]*).-\n") do
+               log:info("id=", nid, " ssid=", nssid)
+               if nssid == ssid then
+                       id = nid
+                       break
+               end
+       end
+
+       -- Select network
+       if not id then
+               log:warn("can't find network ", ssid)
+               return
+       end
+
+       -- Disconnect from existing network
+       self:t_disconnectNetwork()
+
+       local request = 'SELECT_NETWORK ' .. id
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+
+       -- Allow association
+       request = 'REASSOCIATE'
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+
+       -- Save configuration
+       request = 'SAVE_CONFIG'
+       assert(self:request(request) == "OK\n", "wpa_cli failed:" .. request)
+end
+
+
+--[[
+
+=head2 jive.net.Networking:t_setStaticIp(ssid, ipAddress, ipSubnet, ipGateway, 
ipDNS)
+
+apply IP address and associated configuration parameters to a network interface
+
+=cut
+--]]
+
+
+function t_setStaticIP(self, ssid, ipAddress, ipSubnet, ipGateway, ipDNS)
+       assert(type(self.interface) == 'string')
+       -- Reset the network
+       local killCommand   = "kill -TERM `cat /var/run/udhcpc." .. 
self.interface .. "pid`"
+       local configCommand = "/sbin/ifconfig " .. self.interface .. " 0.0.0.0"
+
+       os.execute(killCommand)
+       os.execute(configCommand)
+
+       -- Set static ip configuration for network
+       self:_editNetworkInterfaces(ssid, "static",
+                                   "address " .. ipAddress,
+                                   "netmask " .. ipSubnet,
+                                   "gateway " .. ipGateway,
+                                   "dns " .. ipDNS,
+                                   "up echo 'nameserver " .. ipDNS .. "' > 
/etc/resolv.conf"
+                           )
+
+       -- Bring up the network
+       local ifUp = "/sbin/ifup " .. interface
+       local status = os.execute(ifUp)
+       log:info("ifup status=", status)
+end
+
+
+function _editNetworkInterfaces(self, ssid, method, ...)
+       -- the interfaces file uses " \t" as word breaks so munge the ssid
+       -- FIXME ssid's with \n are not supported
+       assert(ssid, debug.traceback())
+       ssid = string.gsub(ssid, "[ \t]", "_")
+       log:info("munged ssid=", ssid)
+
+       local fi = assert(io.open("/etc/network/interfaces", "r+"))
+       local fo = assert(io.open("/etc/network/interfaces.tmp", "w"))
+
+       local network = ""
+       for line in fi:lines() do
+               if string.match(line, "^mapping%s") or string.match(line, 
"^auto%s") then
+                       network = ""
+               elseif string.match(line, "^iface%s") then
+                       network = string.match(line, "^iface%s([^%s]+)%s")
+               end
+
+               if network ~= ssid then
+                       fo:write(line .. "\n")
+               end
+       end
+
+       if method then
+               fo:write("iface " .. ssid .. " inet " .. method .. "\n")
+               for _,v in ipairs{...} do
+                       fo:write("\t" .. v .. "\n")
+               end
+       end
+
+       fi:close()
+       fo:close()
+
+       os.execute("/bin/mv /etc/network/interfaces.tmp 
/etc/network/interfaces")
+end
+
+--[[
+
+=head2 jive.net.Networking:getLinkQuality()
+
+returns "quality" of wireless interface
+used for dividing SNR values into categorical levels of signal quality
+
+       quality of 1 indicates SNR of 0
+       quality of 2 indicates SNR <= 10
+       quality of 3 indicates SNR <= 18
+       quality of 4 indicates SNR <= 25
+
+=cut
+--]]
+
+function getLinkQuality(self)
+
+       local snr = self:getSNR()
+
+       if snr == nil or snr == 0 then
+               return nil
+       end
+
+       local quality = 1
+       for i, l in ipairs(WIRELESS_SNR) do
+               if snr <= l then
+                       break
+               end
+               quality = i
+       end
+
+       return quality
+end
+
+--[[
+
+=head2 jive.net.Networking:getSNR()
+
+returns signal to noise ratio of wireless link
+
+=cut
+--]]
+
+
+function getSNR(self)
+       if type(self.interface) ~= 'string' then
+               return 0
+       end
+       local f = io.popen("/sbin/iwpriv " .. self.interface .. " getSNR 1")
+       if f == nil then
+               return 0
+       end
+
+       local t = f:read("*all")
+       f:close()
+
+       return tonumber(string.match(t, ":(%d+)"))
+end
+
+--[[
+
+=head2 jive.net.Networking:getRSSI()
+
+returns Received Signal Strength Indication (signal power) of a wireless 
interface
+=cut
+--]]
+
+function getRSSI(self)
+       if type(self.interface) ~= 'string' then
+               return 0
+       end
+       local f = io.popen("/sbin/iwpriv " .. self.interface .. " getRSSI 1")
+       if f == nil then
+               return 0
+       end
+
+       local t = f:read("*all")
+       f:close()
+
+       return tonumber(string.match(t, ":(%-?%d+)"))
+end
+
+--[[
+
+=head2 jive.net.Networking:getNF()
+
+returns NF (?) of a wireless interface
+
+=cut
+--]]
+
+
+function getNF(self)
+       if type(self.interface) ~= 'string' then
+               return 0
+       end
+       local f = io.popen("/sbin/iwpriv " .. self.interface .. " getNF 1")
+       if f == nil then
+               return 0
+       end
+
+       local t = f:read("*all")
+       f:close()
+
+       return tonumber(string.match(t, ":(%-?%d+)"))
+end
+
+--[[
+
+=head2 jive.net.Networking:getTxBitRate()
+
+returns bitrate of a wireless interface
+
+=cut
+--]]
+
+function getTxBitRate(self)
+       if type(self.interface) ~= 'string' then
+               return "0"
+       end
+       local f = io.popen("/sbin/iwconfig " .. self.interface)
+       if f == nil then
+               return "0"
+       end
+
+       local t = f:read("*all")
+       f:close()
+
+       return string.match(t, "Bit Rate:(%d+%s[^%s]+)")
+end
+
+--[[
+
+=head2 jive.net.Networking:powerSave(enable)
+
+sets wireless power save state
+
+=cut
+--]]
+
+
+function powerSave(self, enable)
+       if self._powerSaveState == enable then
+               return
+       end
+
+       if not self.t_sock then
+               return
+       end
+
+       self._powerSaveState = enable
+       if enable then
+               log:info("iwconfig power on")
+               self.t_sock:setPower(true)
+       else
+               log:info("iwconfig power off")
+               self.t_sock:setPower(false)
+       end
+end
+
+--[[
+
+=head2 jive.net.Networking:open()
+
+opens a socket to pick up network events
+
+=cut
+--]]
+
+
+
+function open(self)
+       if self.t_sock then
+               log:error("Socket already open")
+               return
+       end
+
+       local err
+
+       if self.isWireless then
+               log:debug('Open wireless socket')
+               self.t_sock, err = wireless:open(self.interface)
+               if err then
+                       log:warn(err)
+       
+                       self:close()
+                       return false
+               end
+
+               local source = function()
+                                      return self.t_sock:receive()
+                              end
+       
+               local sink = function(chunk, err)
+                                    if chunk and string.sub(chunk, 1, 1) == 
"<" then
+                                            -- wpa event message
+                                            if self.eventSink  then
+                                                    Task("wirelessEvent", nil,
+                                                         function()
+                                                                 
self.eventSink(chunk, err)
+                                                         end):addTask()
+                                            end
+                                    else
+                                            -- request response
+                                            local task = 
table.remove(self.responseQueue, 1)
+                                            if task then
+                                                    task:addTask(chunk, err)
+                                            end
+                                    end
+                            end
+       
+               self:t_addRead(function()
+                                      -- XXXX handle timeout
+                                      local status, err = 
ltn12.pump.step(source, sink)
+                                      if err then
+                                              log:warn(err)
+                                              self:close()
+                                      end
+                              end,
+              0) -- no timeout
+       end
+
+       return true
+end
+
+--[[
+
+=head2 jive.net.Networking:close()
+
+closes existing socket
+
+=cut
+--]]
+
+
+function close(self)
+       -- cancel queued requests
+       for i, task in ipairs(self.responseQueue) do
+               task:addTask(nil, "closed")
+       end
+       self.responseQueue = {}
+
+       Socket.close(self)
+end
+
+--[[
+
+=head2 jive.net.Networking:request()
+
+pushes request to open socket
+
+=cut
+--]]
+
+
+function request(self, ...)
+       local task = Task:running()
+       assert(task, "Networking:request must be called in a Task")
+
+       log:info("REQUEST: ", ...)
+
+       -- open the socket if it is closed
+       if not self.t_sock and not self:open() then
+               -- XXXX callers expect a string
+               return "", "closed"
+       end
+
+       local status, err = self.t_sock:request(...)
+
+       if err then
+               log:warn(err)
+               self:close()
+
+               -- XXXX callers expect a string
+               return "", err
+       end
+
+       -- yield task
+       table.insert(self.responseQueue, task)
+       local _, reply, err = Task:yield(false)
+
+       if not reply or err then
+               log:warn(err)
+               self:close()
+
+               -- XXXX callers expect a string
+               return "", err
+       end
+
+       log:info("REPLY:", reply)
+       return reply
+end
+
+
+function attach(self, sink)
+       -- XXXX allow multiple sinks
+       self.eventSink = sink
+end
+
+
+function detach(self)
+       self.eventSink = nil
+end
+
+
+--[[
+
+=head1 LICENSE
+
+Copyright 2009 Logitech. All Rights Reserved.
+
+This file is subject to the Logitech Public Source License Version 1.0. Please 
see the LICENCE file for details.
+
+=cut
+--]]

_______________________________________________
Jive-checkins mailing list
[email protected]
http://lists.slimdevices.com/cgi-bin/mailman/listinfo/jive-checkins

Reply via email to