1
0
mirror of https://github.com/gryf/wicd.git synced 2025-12-20 04:48:00 +01:00

Added support for monitoring connection status without the need for iwconfig, ifconfig, and ethtool/miitool.

Added a "Disconnect" button to each network entry, which will be visible instead of the "Connect" button for the active network.
Fixed a bug where cancelling a connection while validating authentication would leave the GUI in the connecting state forever.
This commit is contained in:
imdano
2008-03-31 14:21:43 +00:00
parent 45b7f78bd9
commit ed2d53839e
7 changed files with 418 additions and 144 deletions

View File

@@ -195,11 +195,9 @@ class ConnectionWizard(dbus.service.Object):
@dbus.service.method('org.wicd.daemon') @dbus.service.method('org.wicd.daemon')
def SetWiredInterface(self, interface): def SetWiredInterface(self, interface):
""" Sets the wired interface for the daemon to use. """ """ Sets the wired interface for the daemon to use. """
print "setting wired interface", str(interface) print "setting wired interface %s" % (str(interface))
self.wired.wired_interface = interface self.wired.wired_interface = interface
self.wired.SetLiface(interface)
self.wifi.wired_interface = interface self.wifi.wired_interface = interface
self.wifi.SetLiface(interface)
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
config.read(self.app_conf) config.read(self.app_conf)
config.set("Settings","wired_interface", interface) config.set("Settings","wired_interface", interface)
@@ -208,11 +206,9 @@ class ConnectionWizard(dbus.service.Object):
@dbus.service.method('org.wicd.daemon') @dbus.service.method('org.wicd.daemon')
def SetWirelessInterface(self, interface): def SetWirelessInterface(self, interface):
""" Sets the wireless interface the daemon will use. """ """ Sets the wireless interface the daemon will use. """
print "setting wireless interface" , str(interface) print "setting wireless interface %s" % (str(interface))
self.wifi.wireless_interface = interface self.wifi.wireless_interface = interface
self.wifi.SetWiface(interface)
self.wired.wireless_interface = interface self.wired.wireless_interface = interface
self.wired.SetWiface(interface)
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
config.read(self.app_conf) config.read(self.app_conf)
config.set("Settings","wireless_interface", interface) config.set("Settings","wireless_interface", interface)
@@ -363,7 +359,7 @@ class ConnectionWizard(dbus.service.Object):
if fresh: if fresh:
self.Scan() self.Scan()
#self.AutoConnectScan() # Also scans for hidden networks #self.AutoConnectScan() # Also scans for hidden networks
if self.CheckPluggedIn(): if self.CheckPluggedIn(True):
self._wired_autoconnect() self._wired_autoconnect()
else: else:
self._wireless_autoconnect() self._wireless_autoconnect()
@@ -692,6 +688,10 @@ class ConnectionWizard(dbus.service.Object):
""" Returns number of networks. """ """ Returns number of networks. """
return len(self.LastScan) return len(self.LastScan)
@dbus.service.method('org.wicd.daemon.wireless')
def GetApBssid(self):
return self.wifi.GetBSSID()
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def CreateAdHocNetwork(self, essid, channel, ip, enctype, key, encused, def CreateAdHocNetwork(self, essid, channel, ip, enctype, key, encused,
ics): ics):
@@ -736,13 +736,19 @@ class ConnectionWizard(dbus.service.Object):
print "Couldn't detect a wireless interface." print "Couldn't detect a wireless interface."
return str(iface) return str(iface)
@dbus.service.method('org.wicd.daemon.wireless')
def DisconnectWireless(self):
""" Disconnects the wireless network. """
self.SetForcedDisconnect(True)
self.wifi.Disconnect()
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def IsWirelessUp(self): def IsWirelessUp(self):
""" Returns a boolean specifying if wireless is up or down. """ """ Returns a boolean specifying if wireless is up or down. """
return self.wifi.IsUp() return self.wifi.IsUp()
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def GetPrintableSignalStrength(self, iwconfig=None): def GetPrintableSignalStrength(self, iwconfig=None, fast=False):
""" Assigns a signal strength appropriate for display """ Assigns a signal strength appropriate for display
This is used separately from the raw signal strength retrieving This is used separately from the raw signal strength retrieving
@@ -752,38 +758,38 @@ class ConnectionWizard(dbus.service.Object):
""" """
if self.GetSignalDisplayType() == 0: if self.GetSignalDisplayType() == 0:
return self.GetCurrentSignalStrength(iwconfig) return self.GetCurrentSignalStrength(iwconfig, fast)
else: else:
return self.GetCurrentDBMStrength(iwconfig) return self.GetCurrentDBMStrength(iwconfig, fast)
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def GetCurrentSignalStrength(self, iwconfig=None): def GetCurrentSignalStrength(self, iwconfig=None, fast=False):
""" Returns the current signal strength. """ """ Returns the current signal strength. """
try: try:
strength = int(self.wifi.GetSignalStrength(iwconfig)) strength = int(self.wifi.GetSignalStrength(iwconfig, fast))
except: except:
strength = 0 strength = 0
return strength return strength
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def GetCurrentDBMStrength(self, iwconfig=None): def GetCurrentDBMStrength(self, iwconfig=None, fast=False):
""" Returns the current dbm signal strength. """ """ Returns the current dbm signal strength. """
try: try:
dbm_strength = int(self.wifi.GetDBMStrength(iwconfig)) dbm_strength = int(self.wifi.GetDBMStrength(iwconfig, fast))
except: except:
dbm_strength = 0 dbm_strength = 0
return dbm_strength return dbm_strength
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def GetCurrentNetwork(self, iwconfig=None): def GetCurrentNetwork(self, iwconfig=None, fast=False):
""" Returns the current network. """ """ Returns the current network. """
current_network = str(self.wifi.GetCurrentNetwork(iwconfig)) current_network = str(self.wifi.GetCurrentNetwork(iwconfig, fast))
return current_network return current_network
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def GetCurrentNetworkID(self, iwconfig=None): def GetCurrentNetworkID(self, iwconfig=None, fast=False):
""" Returns the id of the current network, or -1 if its not found. """ """ Returns the id of the current network, or -1 if its not found. """
currentESSID = self.GetCurrentNetwork(iwconfig) currentESSID = self.GetCurrentNetwork(iwconfig, fast)
for x in xrange(0, len(self.LastScan)): for x in xrange(0, len(self.LastScan)):
if self.LastScan[x]['essid'] == currentESSID: if self.LastScan[x]['essid'] == currentESSID:
return x return x
@@ -820,18 +826,15 @@ class ConnectionWizard(dbus.service.Object):
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def CheckIfWirelessConnecting(self): def CheckIfWirelessConnecting(self):
"""Returns True if wireless interface is connecting, otherwise False.""" """Returns True if wireless interface is connecting, otherwise False."""
if self.wifi.connecting_thread is not None: if self.wifi.connecting_thread:
# If connecting_thread exists, then check for it's return self.wifi.connecting_thread.is_connecting
# status, if it doesn't, we aren't connecting.
status = self.wifi.connecting_thread.is_connecting
return status
else: else:
return False return False
@dbus.service.method('org.wicd.daemon.wireless') @dbus.service.method('org.wicd.daemon.wireless')
def GetWirelessIP(self): def GetWirelessIP(self, fast=False):
""" Returns the IP associated with the wireless interface. """ """ Returns the IP associated with the wireless interface. """
ip = self.wifi.GetIP() ip = self.wifi.GetIP(fast)
#if self.debug_mode == 1: #if self.debug_mode == 1:
#print 'returning wireless ip', ip #print 'returning wireless ip', ip
return ip return ip
@@ -849,9 +852,9 @@ class ConnectionWizard(dbus.service.Object):
################################# #################################
@dbus.service.method('org.wicd.daemon.wired') @dbus.service.method('org.wicd.daemon.wired')
def GetWiredIP(self): def GetWiredIP(self, fast=False):
""" Returns the wired interface's ip address. """ """ Returns the wired interface's ip address. """
ip = self.wired.GetIP() ip = self.wired.GetIP(True)
return ip return ip
@dbus.service.method('org.wicd.daemon.wired') @dbus.service.method('org.wicd.daemon.wired')
@@ -918,6 +921,12 @@ class ConnectionWizard(dbus.service.Object):
else: else:
return False return False
@dbus.service.method('org.wicd.daemon.wired')
def DisconnectWired(self):
""" Disconnects the wired network. """
self.SetForcedDisconnect(True)
self.wired.Disconnect()
@dbus.service.method('org.wicd.daemon.wired') @dbus.service.method('org.wicd.daemon.wired')
def SetAlwaysShowWiredInterface(self, value): def SetAlwaysShowWiredInterface(self, value):
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
@@ -932,9 +941,9 @@ class ConnectionWizard(dbus.service.Object):
return bool(self.always_show_wired_interface) return bool(self.always_show_wired_interface)
@dbus.service.method('org.wicd.daemon.wired') @dbus.service.method('org.wicd.daemon.wired')
def CheckPluggedIn(self): def CheckPluggedIn(self, fast=False):
if self.wired.wired_interface and self.wired.wired_interface != "None": if self.wired.wired_interface and self.wired.wired_interface != "None":
return self.wired.CheckPluggedIn() return self.wired.CheckPluggedIn(fast)
else: else:
return None return None

98
gui.py
View File

@@ -179,8 +179,6 @@ language['setting_broadcast_address'] = _('Setting broadcast address...')
language['setting_static_dns'] = _('Setting static DNS servers...') language['setting_static_dns'] = _('Setting static DNS servers...')
language['setting_static_ip'] = _('Setting static IP addresses...') language['setting_static_ip'] = _('Setting static IP addresses...')
language['running_dhcp'] = _('Obtaining IP address...') language['running_dhcp'] = _('Obtaining IP address...')
language['no_dhcp_offers'] = _('Connection Failed: No DHCP offers received. \
Couldn\'t get an IP Address.')
language['dhcp_failed'] = _('Connection Failed: Unable to Get IP Address') language['dhcp_failed'] = _('Connection Failed: Unable to Get IP Address')
language['aborted'] = _('Connection Cancelled') language['aborted'] = _('Connection Cancelled')
language['bad_pass'] = _('Connection Failed: Bad password') language['bad_pass'] = _('Connection Failed: Bad password')
@@ -647,6 +645,10 @@ class NetworkEntry(gtk.HBox):
self.connect_hbox.pack_start(self.connect_button, False, False) self.connect_hbox.pack_start(self.connect_button, False, False)
self.connect_hbox.show() self.connect_hbox.show()
# Set up the Disconnect button
self.disconnect_button = gtk.Button(stock=gtk.STOCK_DISCONNECT)
self.connect_hbox.pack_start(self.disconnect_button, False, False)
# Set up the VBox that goes in the gtk.Expander # Set up the VBox that goes in the gtk.Expander
self.expander_vbox = gtk.VBox(False, 1) self.expander_vbox = gtk.VBox(False, 1)
self.expander_vbox.show() self.expander_vbox.show()
@@ -790,6 +792,7 @@ class WiredNetworkEntry(NetworkEntry):
self.expander.set_expanded(True) self.expander.set_expanded(True)
self.profile_help.show() self.profile_help.show()
self.check_enable() self.check_enable()
self.update_connect_button()
self.wireddis = self.connect("destroy", self.destroy_called) self.wireddis = self.connect("destroy", self.destroy_called)
def destroy_called(self, *args): def destroy_called(self, *args):
@@ -828,6 +831,16 @@ class WiredNetworkEntry(NetworkEntry):
self.advanced_button.set_sensitive(False) self.advanced_button.set_sensitive(False)
self.script_button.set_sensitive(False) self.script_button.set_sensitive(False)
def update_connect_button(self, apbssid=None):
""" Update the connection/disconnect button for this entry. """
state, x = daemon.GetConnectionStatus()
if state == misc.WIRED:
self.disconnect_button.show()
self.connect_button.hide()
else:
self.disconnect_button.hide()
self.connect_button.show()
def add_profile(self, widget): def add_profile(self, widget):
""" Add a profile to the profile list. """ """ Add a profile to the profile list. """
print "adding profile" print "adding profile"
@@ -871,12 +884,10 @@ class WiredNetworkEntry(NetworkEntry):
def toggle_default_profile(self, widget): def toggle_default_profile(self, widget):
""" Change the default profile. """ """ Change the default profile. """
if self.chkbox_default_profile.get_active(): if self.chkbox_default_profile.get_active():
print 'unsetting previous default profile...'
# Make sure there is only one default profile at a time # Make sure there is only one default profile at a time
config.UnsetWiredDefault() config.UnsetWiredDefault()
wired.SetWiredProperty("default", wired.SetWiredProperty("default",
self.chkbox_default_profile.get_active()) self.chkbox_default_profile.get_active())
print 'toggle defualt prof'
config.SaveWiredNetworkProfile(self.combo_profile_names.get_active_text()) config.SaveWiredNetworkProfile(self.combo_profile_names.get_active_text())
def change_profile(self, widget): def change_profile(self, widget):
@@ -967,6 +978,7 @@ class WirelessNetworkEntry(NetworkEntry):
# Show everything # Show everything
self.show_all() self.show_all()
self.advanced_dialog = WirelessSettingsDialog(networkID) self.advanced_dialog = WirelessSettingsDialog(networkID)
self.update_connect_button(wireless.GetApBssid())
self.wifides = self.connect("destroy", self.destroy_called) self.wifides = self.connect("destroy", self.destroy_called)
def destroy_called(self, *args): def destroy_called(self, *args):
@@ -1033,6 +1045,17 @@ class WirelessNetworkEntry(NetworkEntry):
self.image.set_from_file(wpath.images + signal_img) self.image.set_from_file(wpath.images + signal_img)
self.lbl_strength.set_label(disp_strength + ending) self.lbl_strength.set_label(disp_strength + ending)
def update_connect_button(self, apbssid):
""" Update the connection/disconnect button for this entry. """
state, x = daemon.GetConnectionStatus()
if state == misc.WIRELESS and apbssid == \
wireless.GetWirelessProperty(self.networkID, "bssid"):
self.disconnect_button.show()
self.connect_button.hide()
else:
self.disconnect_button.hide()
self.connect_button.show()
def set_mac_address(self, address): def set_mac_address(self, address):
""" Set the MAC address for the WirelessNetworkEntry. """ """ Set the MAC address for the WirelessNetworkEntry. """
self.lbl_mac.set_label(str(address)) self.lbl_mac.set_label(str(address))
@@ -1133,7 +1156,7 @@ class appGui:
dic = { "refresh_clicked" : self.refresh_networks, dic = { "refresh_clicked" : self.refresh_networks,
"quit_clicked" : self.exit, "quit_clicked" : self.exit,
"disconnect_clicked" : self.disconnect, "disconnect_clicked" : self.disconnect_all,
"main_exit" : self.exit, "main_exit" : self.exit,
"cancel_clicked" : self.cancel_connect, "cancel_clicked" : self.cancel_connect,
"connect_clicked" : self.connect_hidden, "connect_clicked" : self.connect_hidden,
@@ -1157,7 +1180,6 @@ class appGui:
self.network_list = self.wTree.get_widget("network_list_vbox") self.network_list = self.wTree.get_widget("network_list_vbox")
self.status_area = self.wTree.get_widget("connecting_hbox") self.status_area = self.wTree.get_widget("connecting_hbox")
self.status_bar = self.wTree.get_widget("statusbar") self.status_bar = self.wTree.get_widget("statusbar")
self.refresh_networks(fresh=False)
self.status_area.hide_all() self.status_area.hide_all()
@@ -1168,6 +1190,8 @@ class appGui:
self.pulse_active = False self.pulse_active = False
self.standalone = standalone self.standalone = standalone
self.wpadrivercombo = None self.wpadrivercombo = None
self.fast = True # Use ioctl instead of external program calls
self.refresh_networks(fresh=False)
self.window.connect('delete_event', self.exit) self.window.connect('delete_event', self.exit)
@@ -1186,7 +1210,7 @@ class appGui:
if width > -1 and height > -1: if width > -1 and height > -1:
self.window.resize(int(width), int(height)) self.window.resize(int(width), int(height))
gobject.timeout_add(700, self.update_statusbar) gobject.timeout_add(400, self.update_statusbar)
def create_adhoc_network(self, widget=None): def create_adhoc_network(self, widget=None):
""" Shows a dialog that creates a new adhoc network. """ """ Shows a dialog that creates a new adhoc network. """
@@ -1238,9 +1262,10 @@ class appGui:
""" Toggles the encryption key entry box for the ad-hoc dialog. """ """ Toggles the encryption key entry box for the ad-hoc dialog. """
self.key_entry.set_sensitive(self.chkbox_use_encryption.get_active()) self.key_entry.set_sensitive(self.chkbox_use_encryption.get_active())
def disconnect(self, widget=None): def disconnect_all(self, widget=None):
""" Disconnects from any active network. """ """ Disconnects from any active network. """
daemon.Disconnect() daemon.Disconnect()
self.update_connect_buttons()
def about_dialog(self, widget, event=None): def about_dialog(self, widget, event=None):
""" Displays an about dialog. """ """ Displays an about dialog. """
@@ -1550,45 +1575,59 @@ class appGui:
if not self.is_visible: if not self.is_visible:
return True return True
fast = self.fast
wiredConnecting = wired.CheckIfWiredConnecting() wiredConnecting = wired.CheckIfWiredConnecting()
wirelessConnecting = wireless.CheckIfWirelessConnecting() wirelessConnecting = wireless.CheckIfWirelessConnecting()
connecting = wiredConnecting or wirelessConnecting
if wirelessConnecting or wiredConnecting: if connecting and not self.pulse_active:
if not self.pulse_active:
self.pulse_active = True self.pulse_active = True
gobject.timeout_add(100, self.pulse_progress_bar) gobject.timeout_add(100, self.pulse_progress_bar)
self.network_list.set_sensitive(False) self.network_list.set_sensitive(False)
self.status_area.show_all() self.status_area.show_all()
if self.statusID: if self.statusID:
self.status_bar.remove(1, self.statusID) self.status_bar.remove(1, self.statusID)
if wirelessConnecting: if wirelessConnecting:
if not fast:
iwconfig = wireless.GetIwconfig() iwconfig = wireless.GetIwconfig()
self.set_status(wireless.GetCurrentNetwork(iwconfig) + ': ' + else:
iwconfig = ''
self.set_status(wireless.GetCurrentNetwork(iwconfig, fast) + ': ' +
language[str(wireless.CheckWirelessConnectingMessage())]) language[str(wireless.CheckWirelessConnectingMessage())])
if wiredConnecting: if wiredConnecting:
self.set_status(language['wired_network'] + ': ' + self.set_status(language['wired_network'] + ': ' +
language[str(wired.CheckWiredConnectingMessage())]) language[str(wired.CheckWiredConnectingMessage())])
else: elif self.pulse_active and not connecting:
self.network_list.set_sensitive(True)
self.pulse_active = False self.pulse_active = False
self.update_connect_buttons()
self.network_list.set_sensitive(True)
self.status_area.hide_all() self.status_area.hide_all()
if self.statusID: if self.statusID:
self.status_bar.remove(1, self.statusID) self.status_bar.remove(1, self.statusID)
# Determine connection status. # Determine connection status.
if self.check_for_wired(wired.GetWiredIP()): if self.check_for_wired(wired.GetWiredIP(fast)):
return True return True
if not fast:
if self.check_for_wireless(wireless.GetIwconfig(), iwconfig = wireless.GetIwconfig()
wireless.GetWirelessIP()): else:
iwconfig = ''
if self.check_for_wireless(iwconfig,
wireless.GetWirelessIP(fast)):
return True return True
self.set_status(language['not_connected']) self.set_status(language['not_connected'])
return True return True
def update_connect_buttons(self):
""" Updates the connect/disconnect buttons for each network entry. """
apbssid = wireless.GetApBssid()
for entry in self.network_list:
if hasattr(entry, "update_connect_button"):
entry.update_connect_button(apbssid)
def check_for_wired(self, wired_ip): def check_for_wired(self, wired_ip):
""" Determine if wired is active, and if yes, set the status. """ """ Determine if wired is active, and if yes, set the status. """
if wired_ip and wired.CheckPluggedIn(): if wired_ip and wired.CheckPluggedIn(self.fast):
self.set_status(language['connected_to_wired'].replace('$A', self.set_status(language['connected_to_wired'].replace('$A',
wired_ip)) wired_ip))
return True return True
@@ -1600,15 +1639,15 @@ class appGui:
if not wireless_ip: if not wireless_ip:
return False return False
network = wireless.GetCurrentNetwork(iwconfig) network = wireless.GetCurrentNetwork(iwconfig, self.fast)
if not network: if not network:
return False return False
network = str(network) network = str(network)
if daemon.GetSignalDisplayType() == 0: if daemon.GetSignalDisplayType() == 0:
strength = wireless.GetCurrentSignalStrength(iwconfig) strength = wireless.GetCurrentSignalStrength(iwconfig, self.fast)
else: else:
strength = wireless.GetCurrentDBMStrength(iwconfig) strength = wireless.GetCurrentDBMStrength(iwconfig, self.fast)
if strength is None: if strength is None:
return False return False
@@ -1644,12 +1683,14 @@ class appGui:
z.destroy() z.destroy()
del z del z
if wired.CheckPluggedIn() or wired.GetAlwaysShowWiredInterface(): if wired.CheckPluggedIn(self.fast) or wired.GetAlwaysShowWiredInterface():
printLine = True # In this case we print a separator. printLine = True # In this case we print a separator.
wirednet = WiredNetworkEntry() wirednet = WiredNetworkEntry()
self.network_list.pack_start(wirednet, False, False) self.network_list.pack_start(wirednet, False, False)
wirednet.connect_button.connect("button-press-event", self.connect, wirednet.connect_button.connect("button-press-event", self.connect,
"wired", 0, wirednet) "wired", 0, wirednet)
wirednet.disconnect_button.connect("button-press-event", self.disconnect,
"wired", 0, wirednet)
wirednet.advanced_button.connect("button-press-event", wirednet.advanced_button.connect("button-press-event",
self.edit_advanced, "wired", 0, self.edit_advanced, "wired", 0,
wirednet) wirednet)
@@ -1673,11 +1714,13 @@ class appGui:
else: else:
printLine = True printLine = True
tempnet = WirelessNetworkEntry(x) tempnet = WirelessNetworkEntry(x)
tempnet.show_all()
self.network_list.pack_start(tempnet, False, False) self.network_list.pack_start(tempnet, False, False)
tempnet.connect_button.connect("button-press-event", tempnet.connect_button.connect("button-press-event",
self.connect, "wireless", x, self.connect, "wireless", x,
tempnet) tempnet)
tempnet.disconnect_button.connect("button-press-event",
self.disconnect, "wireless",
x, tempnet)
tempnet.advanced_button.connect("button-press-event", tempnet.advanced_button.connect("button-press-event",
self.edit_advanced, "wireless", self.edit_advanced, "wireless",
x, tempnet) x, tempnet)
@@ -1889,6 +1932,13 @@ class appGui:
wired.ConnectWired() wired.ConnectWired()
self.update_statusbar() self.update_statusbar()
def disconnect(self, widget, event, nettype, networkid, networkentry):
if nettype == "wired":
wired.DisconnectWired()
else:
wireless.DisconnectWireless()
self.update_connect_buttons()
def wait_for_events(self, amt=0): def wait_for_events(self, amt=0):
""" Wait for any pending gtk events to finish before moving on. """ Wait for any pending gtk events to finish before moving on.

View File

@@ -278,3 +278,4 @@ def error(parent, message):
dialog.set_markup(message) dialog.set_markup(message)
dialog.run() dialog.run()
dialog.destroy() dialog.destroy()

View File

@@ -67,6 +67,9 @@ class ConnectionStatus():
self.reconnect_tries = 0 self.reconnect_tries = 0
self.last_reconnect_time = time.time() self.last_reconnect_time = time.time()
self.signal_changed = False self.signal_changed = False
# This determines if we use ioctl or external programs
self.fast = True
self.iwconfig = ''
def check_for_wired_connection(self, wired_ip): def check_for_wired_connection(self, wired_ip):
""" Checks for an active wired connection. """ Checks for an active wired connection.
@@ -76,7 +79,7 @@ class ConnectionStatus():
""" """
if wired_ip and wired.CheckPluggedIn(): if wired_ip and wired.CheckPluggedIn(self.fast):
# Only change the interface if it's not already set for wired # Only change the interface if it's not already set for wired
if not self.still_wired: if not self.still_wired:
daemon.SetCurrentInterface(daemon.GetWiredInterface()) daemon.SetCurrentInterface(daemon.GetWiredInterface())
@@ -99,6 +102,10 @@ class ConnectionStatus():
if wireless_ip is None: if wireless_ip is None:
return False return False
if self.fast:
self.iwconfig = ''
else:
self.iwconfig = wireless.GetIwconfig()
# Reset this, just in case. # Reset this, just in case.
self.tried_reconnect = False self.tried_reconnect = False
@@ -106,9 +113,11 @@ class ConnectionStatus():
# if something goes wrong. # if something goes wrong.
try: try:
if daemon.GetSignalDisplayType() == 0: if daemon.GetSignalDisplayType() == 0:
wifi_signal = int(wireless.GetCurrentSignalStrength(self.iwconfig)) wifi_signal = int(wireless.GetCurrentSignalStrength(self.iwconfig,
self.fast))
else: else:
wifi_signal = int(wireless.GetCurrentDBMStrength(self.iwconfig)) wifi_signal = int(wireless.GetCurrentDBMStrength(self.iwconfig,
self.fast))
except: except:
wifi_signal = 0 wifi_signal = 0
@@ -127,7 +136,7 @@ class ConnectionStatus():
# Only update if the signal strength has changed because doing I/O # Only update if the signal strength has changed because doing I/O
# calls is expensive, and the icon flickers. # calls is expensive, and the icon flickers.
if (wifi_signal != self.last_strength or if (wifi_signal != self.last_strength or
self.network != wireless.GetCurrentNetwork(self.iwconfig)): self.network != wireless.GetCurrentNetwork(self.iwconfig, self.fast)):
self.last_strength = wifi_signal self.last_strength = wifi_signal
self.signal_changed = True self.signal_changed = True
daemon.SetCurrentInterface(daemon.GetWirelessInterface()) daemon.SetCurrentInterface(daemon.GetWirelessInterface())
@@ -153,15 +162,15 @@ class ConnectionStatus():
# Determine what our current state is. # Determine what our current state is.
# Check for wired. # Check for wired.
wired_ip = wired.GetWiredIP() wired_ip = wired.GetWiredIP(self.fast)
wired_found = self.check_for_wired_connection(wired_ip) wired_found = self.check_for_wired_connection(wired_ip)
if wired_found: if wired_found:
self.update_state(misc.WIRED, wired_ip=wired_ip) self.update_state(misc.WIRED, wired_ip=wired_ip)
return True return True
# Check for wireless # Check for wireless
wifi_ip = wireless.GetWirelessIP() wifi_ip = wireless.GetWirelessIP(self.fast)
self.iwconfig = wireless.GetIwconfig() #self.iwconfig = wireless.GetIwconfig()
self.signal_changed = False self.signal_changed = False
wireless_found = self.check_for_wireless_connection(wifi_ip) wireless_found = self.check_for_wireless_connection(wifi_ip)
if wireless_found: if wireless_found:
@@ -184,6 +193,8 @@ class ConnectionStatus():
def update_state(self, state, wired_ip=None, wifi_ip=None): def update_state(self, state, wired_ip=None, wifi_ip=None):
""" Set the current connection state. """ """ Set the current connection state. """
# Set our connection state/info. # Set our connection state/info.
iwconfig = self.iwconfig
fast = self.fast
if state == misc.NOT_CONNECTED: if state == misc.NOT_CONNECTED:
info = [""] info = [""]
elif state == misc.SUSPENDED: elif state == misc.SUSPENDED:
@@ -192,12 +203,12 @@ class ConnectionStatus():
if wired.CheckIfWiredConnecting(): if wired.CheckIfWiredConnecting():
info = ["wired"] info = ["wired"]
else: else:
info = ["wireless", wireless.GetCurrentNetwork(self.iwconfig)] info = ["wireless", wireless.GetCurrentNetwork(iwconfig, fast)]
elif state == misc.WIRELESS: elif state == misc.WIRELESS:
self.reconnect_tries = 0 self.reconnect_tries = 0
info = [wifi_ip, wireless.GetCurrentNetwork(self.iwconfig), info = [wifi_ip, wireless.GetCurrentNetwork(iwconfig, fast),
str(wireless.GetPrintableSignalStrength(self.iwconfig)), str(wireless.GetPrintableSignalStrength(iwconfig, fast)),
str(wireless.GetCurrentNetworkID(self.iwconfig))] str(wireless.GetCurrentNetworkID(iwconfig, fast))]
elif state == misc.WIRED: elif state == misc.WIRED:
self.reconnect_tries = 0 self.reconnect_tries = 0
info = [wired_ip] info = [wired_ip]
@@ -240,7 +251,7 @@ class ConnectionStatus():
# If we just lost a wireless connection, try to connect to that # If we just lost a wireless connection, try to connect to that
# network again. Otherwise just call Autoconnect. # network again. Otherwise just call Autoconnect.
cur_net_id = wireless.GetCurrentNetworkID(self.iwconfig) cur_net_id = wireless.GetCurrentNetworkID(self.iwconfig, self.fast)
if from_wireless and cur_net_id > -1: if from_wireless and cur_net_id > -1:
print 'Trying to reconnect to last used wireless ' + \ print 'Trying to reconnect to last used wireless ' + \
'network' 'network'
@@ -262,7 +273,7 @@ def err_handle(error):
def main(): def main():
""" Start the connection monitor and set the updater to run every 2 sec. """ """ Start the connection monitor and set the updater to run every 2 sec. """
monitor = ConnectionStatus() monitor = ConnectionStatus()
gobject.timeout_add(3000, monitor.update_connection_status) gobject.timeout_add(2000, monitor.update_connection_status)
mainloop = gobject.MainLoop() mainloop = gobject.MainLoop()
mainloop.run() mainloop.run()

View File

@@ -53,7 +53,6 @@ if __name__ == '__main__':
wpath.chdir(__file__) wpath.chdir(__file__)
class Controller(object): class Controller(object):
""" Parent class for the different interface types. """ """ Parent class for the different interface types. """
def __init__(self): def __init__(self):
@@ -126,16 +125,6 @@ class Controller(object):
flush_tool = property(get_flush_tool, set_flush_tool) flush_tool = property(get_flush_tool, set_flush_tool)
dhcp_client = property(get_dhcp_client, set_dhcp_client) dhcp_client = property(get_dhcp_client, set_dhcp_client)
def SetWiface(self, iface):
""" Sets the wireless interface for the associated wnettools class. """
if self.wiface:
self.wiface.SetInterface(iface)
def SetLiface(self, iface):
""" Sets the wired interface for the associated wnettools class. """
if self.liface:
self.liface.SetInterface(iface)
class ConnectThread(threading.Thread): class ConnectThread(threading.Thread):
""" A class to perform network connections in a multi-threaded way. """ A class to perform network connections in a multi-threaded way.
@@ -178,6 +167,7 @@ class ConnectThread(threading.Thread):
self.after_script = after_script self.after_script = after_script
self.disconnect_script = disconnect_script self.disconnect_script = disconnect_script
self.should_die = False self.should_die = False
self.abort_reason = ""
self.global_dns_1 = gdns1 self.global_dns_1 = gdns1
self.global_dns_2 = gdns2 self.global_dns_2 = gdns2
@@ -279,7 +269,7 @@ class ConnectThread(threading.Thread):
print "Running DHCP" print "Running DHCP"
dhcp_status = iface.StartDHCP() dhcp_status = iface.StartDHCP()
if dhcp_status in ['no_dhcp_offers', 'dhcp_failed']: if dhcp_status in ['no_dhcp_offers', 'dhcp_failed']:
self.connect_aborted(dhcp_status) self.abort_connection(dhcp_status)
return return
def set_dns_addresses(self): def set_dns_addresses(self):
@@ -306,12 +296,19 @@ class ConnectThread(threading.Thread):
a few seconds to make sure the message is readable a few seconds to make sure the message is readable
""" """
if self.abort_reason:
reason = self.abort_reason
self.SetStatus(reason) self.SetStatus(reason)
self.is_aborted = True self.is_aborted = True
self.abort_msg = reason self.abort_msg = reason
self.is_connecting = False self.is_connecting = False
print 'exiting connection thread' print 'exiting connection thread'
def abort_connection(self, reason):
""" Schedule a connection abortion for the given reason. """
self.abort_reason = reason
self.should_die = True
def stop_dhcp_clients(self, iface): def stop_dhcp_clients(self, iface):
""" Stop and running DHCP clients, as well as wpa_supplicant. """ """ Stop and running DHCP clients, as well as wpa_supplicant. """
print 'Stopping wpa_supplicant, and any dhcp clients' print 'Stopping wpa_supplicant, and any dhcp clients'
@@ -399,41 +396,51 @@ class Wireless(Controller):
self.connecting_thread.start() self.connecting_thread.start()
return True return True
def GetSignalStrength(self, iwconfig=None): def GetSignalStrength(self, iwconfig=None, fast=False):
""" Get signal strength of the current network. """ Get signal strength of the current network.
Returns: Returns:
The current signal strength. The current signal strength.
""" """
return self.wiface.GetSignalStrength(iwconfig) return self.wiface.GetSignalStrength(iwconfig, fast)
def GetDBMStrength(self, iwconfig=None): def GetDBMStrength(self, iwconfig=None, fast=False):
""" Get the dBm signal strength of the current network. """ Get the dBm signal strength of the current network.
Returns: Returns:
The current dBm signal strength. The current dBm signal strength.
""" """
return self.wiface.GetDBMStrength(iwconfig) return self.wiface.GetDBMStrength(iwconfig, fast)
def GetCurrentNetwork(self, iwconfig=None): def GetCurrentNetwork(self, iwconfig=None, fast=False):
""" Get current network name. """ Get current network name.
Returns: Returns:
The name of the currently connected network. The name of the currently connected network.
""" """
return self.wiface.GetCurrentNetwork(iwconfig) return self.wiface.GetCurrentNetwork(iwconfig, fast)
def GetIP(self): def GetIP(self, fast=False):
""" Get the IP of the interface. """ Get the IP of the interface.
Returns: Returns:
The IP address of the interface in dotted notation. The IP address of the interface in dotted notation.
""" """
return self.wiface.GetIP() return self.wiface.GetIP(fast)
def GetBSSID(self, fast=True):
""" Get the BSSID of the current access point.
Returns:
The MAC Adress of the active access point as a string, or
None the BSSID can't be found.
"""
return self.wiface.GetBSSID(fast)
def GetIwconfig(self): def GetIwconfig(self):
""" Get the out of iwconfig. """ """ Get the out of iwconfig. """
@@ -641,8 +648,8 @@ class WirelessConnectThread(ConnectThread):
if self.network.get('enctype'): if self.network.get('enctype'):
self.SetStatus('validating_authentication') self.SetStatus('validating_authentication')
if not wiface.ValidateAuthentication(time.time()): if not wiface.ValidateAuthentication(time.time()):
self.connect_aborted('bad_pass') self.abort_connection('bad_pass')
return self.abort_if_needed()
# Set up gateway, IP address, and DNS servers. # Set up gateway, IP address, and DNS servers.
self.set_broadcast_address(wiface) self.set_broadcast_address(wiface)
@@ -657,7 +664,7 @@ class WirelessConnectThread(ConnectThread):
self.SetStatus('done') self.SetStatus('done')
print 'Connecting thread exiting.' print 'Connecting thread exiting.'
if self.debug: if self.debug:
print "IP Address is: " + wiface.GetIP() print "IP Address is: " + wiface.GetIP(fast=True)
self.is_connecting = False self.is_connecting = False
def generate_psk_and_authenticate(self, wiface): def generate_psk_and_authenticate(self, wiface):
@@ -709,14 +716,14 @@ class Wired(Controller):
""" Load the wnettools controls for the wired/wireless interfaces. """ """ Load the wnettools controls for the wired/wireless interfaces. """
self.liface = wnettools.WiredInterface(self.wired_interface, self.debug) self.liface = wnettools.WiredInterface(self.wired_interface, self.debug)
def CheckPluggedIn(self): def CheckPluggedIn(self, fast=False):
""" Check whether the wired connection is plugged in. """ Check whether the wired connection is plugged in.
Returns: Returns:
The status of the physical connection link. The status of the physical connection link.
""" """
return self.liface.GetPluggedIn() return self.liface.GetPluggedIn(fast)
def Connect(self, network, debug=False): def Connect(self, network, debug=False):
""" Spawn a connection thread to connect to the network. """ Spawn a connection thread to connect to the network.
@@ -734,14 +741,14 @@ class Wired(Controller):
self.connecting_thread.start() self.connecting_thread.start()
return True return True
def GetIP(self): def GetIP(self, fast=False):
""" Get the IP of the interface. """ Get the IP of the interface.
Returns: Returns:
The IP address of the interface in dotted notation. The IP address of the interface in dotted notation.
""" """
return self.liface.GetIP() return self.liface.GetIP(fast)
def Disconnect(self): def Disconnect(self):
""" Disconnect from the network. """ """ Disconnect from the network. """
@@ -858,5 +865,5 @@ class WiredConnectThread(ConnectThread):
self.SetStatus('done') self.SetStatus('done')
print 'Connecting thread exiting.' print 'Connecting thread exiting.'
if self.debug: if self.debug:
print "IP Address is: " + liface.GetIP() print "IP Address is: " + liface.GetIP(fast=True)
self.is_connecting = False self.is_connecting = False

View File

@@ -170,7 +170,7 @@ class TrayIcon:
.replace('$A', self.network) .replace('$A', self.network)
.replace('$B', sig_string) .replace('$B', sig_string)
.replace('$C', str(wireless_ip))) .replace('$C', str(wireless_ip)))
self.set_signal_image(strength, lock) self.set_signal_image(int(strength), lock)
def set_connecting_state(self, info): def set_connecting_state(self, info):
""" Sets the icon info for a connecting state. """ """ Sets the icon info for a connecting state. """

View File

@@ -33,8 +33,13 @@ class WirelessInterface() -- Control a wireless network interface.
import misc import misc
import re import re
import os
import wpath import wpath
import time import time
import socket
import fcntl
import struct
import array
# Compile the regex patterns that will be used to search the output of iwlist # Compile the regex patterns that will be used to search the output of iwlist
# scan for info these are well tested, should work on most cards # scan for info these are well tested, should work on most cards
@@ -60,6 +65,15 @@ wpa2_pattern = re.compile('(WPA2)', re.I | re.M | re.S)
auth_pattern = re.compile('.*wpa_state=(.*?)\n', re.I | re.M | re.S) auth_pattern = re.compile('.*wpa_state=(.*?)\n', re.I | re.M | re.S)
RALINK_DRIVER = 'ralink legacy' RALINK_DRIVER = 'ralink legacy'
SIOCGIWESSID = 0x8B1B
SIOCGIFADDR = 0x8915
SIOCGIWSTATS = 0x8B0F
SIOCGIFHWADDR = 0x8927
SIOCGMIIPHY = 0x8947
SIOCGETHTOOL = 0x8946
SIOCGIFFLAGS = 0x8913
SIOCGIWRANGE = 0x8B0B
SIOCGIWAP = 0x8B15
def SetDNS(dns1=None, dns2=None, dns3=None): def SetDNS(dns1=None, dns2=None, dns3=None):
""" Set the DNS of the system to the specified DNS servers. """ Set the DNS of the system to the specified DNS servers.
@@ -123,7 +137,10 @@ def _fast_get_wifi_interfaces():
device = re.compile('[a-z]{3,4}[0-9]') device = re.compile('[a-z]{3,4}[0-9]')
ifnames = [] ifnames = []
try:
f = open('/proc/net/wireless', 'r') f = open('/proc/net/wireless', 'r')
except IOError:
return None
data = f.readlines() data = f.readlines()
f.close() f.close()
for line in data: for line in data:
@@ -137,6 +154,20 @@ def _fast_get_wifi_interfaces():
else: else:
return None return None
def get_iw_ioctl_result(iface, call):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
buff = array.array('c', '\0' * 32)
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
data = (iface + '\0' * 16)[:16] + arg
try:
result = fcntl.ioctl(s.fileno(), call, data)
except IOError:
return None
except OSError:
return None
return buff.tostring()
class Interface(object): class Interface(object):
""" Control a network interface. """ """ Control a network interface. """
def __init__(self, iface, verbose=False): def __init__(self, iface, verbose=False):
@@ -157,6 +188,7 @@ class Interface(object):
self.IP_FOUND = False self.IP_FOUND = False
self.flush_tool = None self.flush_tool = None
self.link_detect = None self.link_detect = None
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.Check() self.Check()
def SetDebugMode(self, value): def SetDebugMode(self, value):
@@ -172,7 +204,18 @@ class Interface(object):
""" """
self.iface = str(iface) self.iface = str(iface)
def _find_client_path(self, client):
paths = ['/sbin/', '/usr/sbin/', '/bin/', '/usr/bin/',
'/usr/local/sbin/', '/usr/local/bin/']
for path in paths:
if os.access("%s%s" % (path, client), os.F_OK):
return "%s%s" % (path, client)
if self.verbose:
"WARNING: No path found for %s" % (client)
return None
def _client_found(self, client): def _client_found(self, client):
# TODO: Don't use which anymore. Just search path manually.
output = misc.Run("which " + client) output = misc.Run("which " + client)
if output and not ("no " + client) in output: if output and not ("no " + client) in output:
return True return True
@@ -188,46 +231,57 @@ class Interface(object):
""" """
if self.DHCP_CLIENT: if self.DHCP_CLIENT:
DHCP_CLIENT = self.DHCP_CLIENT dhcp_client = self.DHCP_CLIENT
else: else:
DHCP_CLIENT = None dhcp_client = None
dhcp_path = None
dhcpclients = ["dhclient", "dhcpcd", "pump"] dhcpclients = ["dhclient", "dhcpcd", "pump"]
for client in dhcpclients: for client in dhcpclients:
if self._client_found(client): dhcp_path = self._find_client_path(client)
DHCP_CLIENT = client if dhcp_path:
dhcp_client = client
break break
if not DHCP_CLIENT: if not dhcp_client:
print "WARNING: NO DHCP CLIENT DETECTED! Make sure there is one \ print "WARNING: No supported DHCP Client could be found!"
set in your path."
return return
elif DHCP_CLIENT in [misc.DHCLIENT, "dhclient"]: elif dhcp_client in [misc.DHCLIENT, "dhclient"]:
DHCP_CLIENT = misc.DHCLIENT dhcp_client = misc.DHCLIENT
DHCP_CMD = "dhclient" dhcp_cmd = dhcp_path
DHCP_RELEASE = "dhclient -r" dhcp_release = dhcp_cmd + " -r"
elif DHCP_CLIENT in [misc.PUMP, "pump"]: elif dhcp_client in [misc.PUMP, "pump"]:
DHCP_CLIENT = misc.PUMP dhcp_client = misc.PUMP
DHCP_CMD = "pump -i" dhcp_cmd = dhcp_path + " -i"
DHCP_RELEASE = "pump -r -i" dhcp_release = dhcp_cmd + " -r -i"
elif DHCP_CLIENT in [misc.DHCPCD, "dhcpcd"]: elif dhcp_client in [misc.DHCPCD, "dhcpcd"]:
DHCP_CLIENT = misc.DHCPCD dhcp_client = misc.DHCPCD
DHCP_CMD = "dhcpcd" dhcp_cmd = dhcp_path
DHCP_RELEASE = "dhcpcd -r" dhcp_release = dhcp_cmd + " -r"
else:
dhcp_client = None
dhcp_cmd = None
dhcp_release = None
self.DHCP_CMD = DHCP_CMD self.DHCP_CMD = dhcp_cmd
self.DHCP_RELEASE = DHCP_RELEASE self.DHCP_RELEASE = dhcp_release
self.DHCP_CLIENT = DHCP_CLIENT self.DHCP_CLIENT = dhcp_client
def CheckWiredTools(self): def CheckWiredTools(self):
""" Check for the existence of ethtool and mii-tool. """ """ Check for the existence of ethtool and mii-tool. """
if self._client_found("mii-tool"): miitool_path = self._find_client_path("mii-tool")
if miitool_path:
self.miitool_cmd = miitool_path
self.MIITOOL_FOUND = True self.MIITOOL_FOUND = True
else: else:
self.miitool_cmd = None
self.MIITOOL_FOUND = False self.MIITOOL_FOUND = False
if self._client_found("ethtool"): ethtool_path = self._find_client_path("ethtool")
if ethtool_path:
self.ethtool_cmd = ethtool_path
self.ETHTOOL_FOUND = True self.ETHTOOL_FOUND = True
else: else:
self.ethtool_cmd = None
self.ETHTOOL_FOUND = False self.ETHTOOL_FOUND = False
def Check(self): def Check(self):
@@ -236,9 +290,12 @@ class Interface(object):
self.CheckDHCP() self.CheckDHCP()
self.CheckWiredTools() self.CheckWiredTools()
if self._client_found("ip"): ip_path = self._find_client_path("ip")
if ip_path:
self.ip_cmd = ip_path
self.IP_FOUND = True self.IP_FOUND = True
else: else:
self.ip_cmd = None
self.IP_FOUND = False self.IP_FOUND = False
def Up(self): def Up(self):
@@ -427,25 +484,48 @@ class Interface(object):
if self.verbose: print cmd if self.verbose: print cmd
misc.Run(cmd) misc.Run(cmd)
def GetIP(self): def GetIP(self, fast=False):
""" Get the IP address of the interface. """ Get the IP address of the interface.
Returns: Returns:
The IP address of the interface in dotted quad form. The IP address of the interface in dotted quad form.
""" """
if fast:
return self._fast_get_ip()
cmd = 'ifconfig ' + self.iface cmd = 'ifconfig ' + self.iface
if self.verbose: print cmd if self.verbose: print cmd
output = misc.Run(cmd) output = misc.Run(cmd)
return misc.RunRegex(ip_pattern, output) return misc.RunRegex(ip_pattern, output)
def IsUp(self): def _fast_get_ip(self):
""" Gets the IP Address of the interface using ioctl.
Using ioctl calls to get the IP Address info is MUCH faster
than calling ifconfig and paring it's output. It's less
portable though, so there may be problems with it on some
systems.
"""
ifstruct = struct.pack('256s', self.iface)
try:
raw_ip = fcntl.ioctl(self.sock.fileno(), SIOCGIFADDR, ifstruct)
except IOError:
return None
except OSError:
return None
return socket.inet_ntoa(raw_ip[20:24])
def IsUp(self, fast=True):
""" Determines if the interface is up. """ Determines if the interface is up.
Returns: Returns:
True if the interface is up, False otherwise. True if the interface is up, False otherwise.
""" """
if fast:
return self._fast_is_up()
cmd = "ifconfig " + self.iface cmd = "ifconfig " + self.iface
output = misc.Run(cmd) output = misc.Run(cmd)
lines = output.split('\n') lines = output.split('\n')
@@ -458,6 +538,19 @@ class Interface(object):
return False return False
def _fast_is_up(self):
data = (self.iface + '\0' * 16)[:18]
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGIFFLAGS, data)
except IOError, e:
if self.verbose:
print "SIOCGIFFLAGS failed: " + str(e)
return False
flags, = struct.unpack('H', result[16:18])
return bool(flags & 1)
class WiredInterface(Interface): class WiredInterface(Interface):
""" Control a wired network interface. """ """ Control a wired network interface. """
@@ -471,7 +564,7 @@ class WiredInterface(Interface):
""" """
Interface.__init__(self, iface, verbose) Interface.__init__(self, iface, verbose)
def GetPluggedIn(self): def GetPluggedIn(self, fast=False):
""" Get the current physical connection state. """ Get the current physical connection state.
The method will first attempt to use ethtool do determine The method will first attempt to use ethtool do determine
@@ -485,21 +578,23 @@ class WiredInterface(Interface):
if not self.iface: if not self.iface:
return False return False
if self.ETHTOOL_FOUND and self.link_detect != misc.MIITOOL: if self.ETHTOOL_FOUND and self.link_detect != misc.MIITOOL:
return self._eth_get_plugged_in() return self._eth_get_plugged_in(fast)
elif self.MIITOOL_FOUND: elif self.MIITOOL_FOUND:
return self._mii_get_plugged_in() return self._mii_get_plugged_in(fast)
else: else:
print 'Error: No way of checking for a wired connection. Make \ print 'Error: No way of checking for a wired connection. Make \
sure that either mii-tool or ethtool is installed.' sure that either mii-tool or ethtool is installed.'
return False return False
def _eth_get_plugged_in(self): def _eth_get_plugged_in(self, fast):
""" Use ethtool to determine the physical connection state. """ Use ethtool to determine the physical connection state.
Returns: Returns:
True if a link is detected, False otherwise. True if a link is detected, False otherwise.
""" """
if fast:
self._fast_eth_get_plugged_in()
link_tool = 'ethtool' link_tool = 'ethtool'
if not self.IsUp(): if not self.IsUp():
print 'Wired Interface is down, putting it up' print 'Wired Interface is down, putting it up'
@@ -512,13 +607,32 @@ class WiredInterface(Interface):
else: else:
return False return False
def _mii_get_plugged_in(self): def _fast_eth_get_plugged_in(self):
if not self.IsUp():
self.Up()
time.sleep(1)
buff = array.array('i', [0x0000000a, 0x00000000])
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
data = (self.iface + '\0' * 16)[:16] + arg
try:
fcntl.ioctl(self.sock.fileno(), SIOCGETHTOOL, data)
except IOError, e:
if self.verbose:
print 'SIOCGETHTOOL failed: ' + str(e)
return False
return bool(buff.tolist()[1])
def _mii_get_plugged_in(self, fast):
""" Use mii-tool to determine the physical connection state. """ Use mii-tool to determine the physical connection state.
Returns: Returns:
True if a link is detected, False otherwise. True if a link is detected, False otherwise.
""" """
if fast:
return self._fast_mii_get_plugged_in()
link_tool = 'mii-tool' link_tool = 'mii-tool'
tool_data = misc.Run(link_tool + ' ' + self.iface, True) tool_data = misc.Run(link_tool + ' ' + self.iface, True)
if misc.RunRegex(re.compile('(Invalid argument)', re.I | re.M | re.S), if misc.RunRegex(re.compile('(Invalid argument)', re.I | re.M | re.S),
@@ -534,6 +648,21 @@ class WiredInterface(Interface):
else: else:
return False return False
def _fast_mii_get_plugged_in(self):
""" Get link status usingthe SIOCGMIIPHY ioctl. """
if not self.IsUp():
self.Up()
time.sleep(1)
buff = struct.pack('16shhhh', (self.iface + '\0' * 16)[:16], 0, 1,
0x0004, 0)
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGMIIPHY, buff)
except IOError, e:
if self.verbose:
print 'SIOCGMIIPHY failed: ' + str(e)
return False
reg = struct.unpack('16shhhh', result)[-1]
return bool(reg & 0x0004)
class WirelessInterface(Interface): class WirelessInterface(Interface):
""" Control a wireless network interface. """ """ Control a wireless network interface. """
@@ -975,26 +1104,43 @@ class WirelessInterface(Interface):
if self.verbose: print cmd if self.verbose: print cmd
misc.Run(cmd) misc.Run(cmd)
def GetBSSID(self, fast=True):
""" Get the MAC address for the interface. """
if fast:
return self._fast_get_bssid()
else:
return ""
def GetSignalStrength(self, iwconfig=None): def _fast_get_bssid(self):
""" Gets the MAC address for the connected AP using ioctl calls. """
data = (self.iface + '\0' * 32)[:32]
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGIWAP, data)[16:]
except IOError, e:
if self.verbose:
print "SIOCGIWAP failed: " + str(e)
return ""
raw_addr = struct.unpack("xxBBBBBB", result[:8])
return "%02X:%02X:%02X:%02X:%02X:%02X" % raw_addr
def GetSignalStrength(self, iwconfig=None, fast=False):
""" Get the signal strength of the current network. """ Get the signal strength of the current network.
Returns: Returns:
The signal strength. The signal strength.
""" """
if fast:
return self._get_signal_strength_fast()
if not iwconfig: if not iwconfig:
cmd = 'iwconfig ' + self.iface cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd if self.verbose: print cmd
output = misc.Run(cmd) output = misc.Run(cmd)
else: else:
output = iwconfig output = iwconfig
# implemented the patch provided in
# https://bugs.launchpad.net/wicd/+bug/175104
# it was for the stable version, so I've improvised here
# should work though
#strength = misc.RunRegex(strength_pattern,output)
[(strength, max_strength)] = strength_pattern.findall(output) [(strength, max_strength)] = strength_pattern.findall(output)
if max_strength and strength: if max_strength and strength:
@@ -1005,13 +1151,44 @@ class WirelessInterface(Interface):
return strength return strength
def GetDBMStrength(self, iwconfig=None): def _get_signal_strength_fast(self):
""" Get the link quality using ioctl calls. """
buff = get_iw_ioctl_result(self.iface, SIOCGIWSTATS)
strength = ord(buff[2])
max_strength = self._get_max_strength_fast()
if strength and max_strength:
return 100 * int(strength) // int(max_strength)
return strength
def _get_max_strength_fast(self):
""" Gets the maximum possible strength from the wireless driver. """
buff = array.array('c', '\0' * 700)
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
iwfreq = (self.iface + '\0' * 16)[:16] + arg
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGIWRANGE, iwfreq)
except IOError, e:
if self.verbose:
print "SIOCGIWRANGE failed: " + str(e)
return None
fmt = "iiihb6ii4B4Bi32i2i2i2i2i3h8h2b2bhi8i2b3h2i2ihB17x" + 32*"ihbb"
size = struct.calcsize(fmt)
data = buff.tostring()
data = data[0:size]
values = struct.unpack(fmt, data)
return values[12]
def GetDBMStrength(self, iwconfig=None, fast=False):
""" Get the dBm signal strength of the current network. """ Get the dBm signal strength of the current network.
Returns: Returns:
The dBm signal strength. The dBm signal strength.
""" """
if fast:
return self._get_dbm_strength_fast()
if iwconfig: if iwconfig:
cmd = 'iwconfig ' + self.iface cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd if self.verbose: print cmd
@@ -1021,14 +1198,24 @@ class WirelessInterface(Interface):
dbm_strength = misc.RunRegex(signaldbm_pattern, output) dbm_strength = misc.RunRegex(signaldbm_pattern, output)
return dbm_strength return dbm_strength
def _get_dbm_strength_fast(self):
buff = misc.get_irwange_ioctl_result(self.iface, SIOCGIWSTATS)
if not buff:
return None
def GetCurrentNetwork(self, iwconfig=None): return str((ord(buff[3]) - 256))
def GetCurrentNetwork(self, iwconfig=None, fast=False):
""" Get the essid of the current network. """ Get the essid of the current network.
Returns: Returns:
The current network essid. The current network essid.
""" """
if fast:
return self._get_essid_fast()
if not iwconfig: if not iwconfig:
cmd = 'iwconfig ' + self.iface cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd if self.verbose: print cmd
@@ -1040,3 +1227,12 @@ class WirelessInterface(Interface):
if network: if network:
network = misc.to_unicode(network) network = misc.to_unicode(network)
return network return network
def _get_essid_fast(self):
""" Get the current essid using ioctl. """
buff = get_iw_ioctl_result(self.iface, SIOCGIWESSID)
if not buff:
return None
return buff.strip('\x00')