diff --git a/wicd/gui.py b/wicd/gui.py index 9ecb8f6..d1d5203 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -295,17 +295,22 @@ class appGui(object): 'org.wicd.daemon.wireless') bus.add_signal_receiver(self.update_connect_buttons, 'StatusChanged', 'org.wicd.daemon') - if standalone: - bus.add_signal_receiver(handle_no_dbus, "DaemonClosing", - "org.wicd.daemon") - bus.add_signal_receiver(lambda: setup_dbus(force=False), - "DaemonStarting", "org.wicd.daemon") + bus.add_signal_receiver(self.handle_connection_results, + 'ConnectResultsSent', 'org.wicd.daemon') + bus.add_signal_receiver(handle_no_dbus, "DaemonClosing", + "org.wicd.daemon") + bus.add_signal_receiver(lambda: setup_dbus(force=False), + "DaemonStarting", "org.wicd.daemon") try: gobject.timeout_add_seconds(1, self.update_statusbar) except: gobject.timeout_add(1000, self.update_statusbar) self.refresh_clicked() + + def handle_connection_results(self, results): + if results != "Success" and self.is_visible: + error(self.window, results, block=False) def create_adhoc_network(self, widget=None): """ Shows a dialog that creates a new adhoc network. """ diff --git a/wicd/monitor.py b/wicd/monitor.py index b875b10..27b2f1a 100755 --- a/wicd/monitor.py +++ b/wicd/monitor.py @@ -146,6 +146,8 @@ class ConnectionStatus(object): state = misc.CONNECTING self.update_state(state) return True + + daemon.SendConnectResultsIfAvail() # Check for wired. wired_ip = wired.GetWiredIP("") diff --git a/wicd/networking.py b/wicd/networking.py index b20be29..813f2a9 100644 --- a/wicd/networking.py +++ b/wicd/networking.py @@ -57,6 +57,22 @@ if __name__ == '__main__': BACKEND = None BACKEND_MGR = BackendManager() +def abortable(func): + """ Mark a method in a ConnectionThread as abortable. + + This decorator runs a check that will abort the connection thread + if necessary before running a given method. + + """ + def wrapper(self, *__args, **__kargs): + self.abort_if_needed() + return func(self, *__args, **__kargs) + + wrapper.__name__ = func.__name__ + wrapper.__dict__ = func.__dict__ + wrapper.__doc__ = func.__doc__ + return wrapper + def get_backend_list(): if BACKEND_MGR: return BACKEND_MGR.get_available_backends() @@ -96,6 +112,7 @@ class Controller(object): self.driver = None self.wiface = None self.liface = None + self.iface = None self.backend_manager = BackendManager() def set_wireless_iface(self, value): @@ -155,6 +172,9 @@ class Controller(object): return self._backend.NeedsExternalCalls() else: return True + + def StopDHCP(self): + return self.iface.StopDHCP() class ConnectThread(threading.Thread): @@ -194,12 +214,13 @@ class ConnectThread(threading.Thread): self.wired_interface = wired self.is_connecting = False self.is_aborted = False - self.abort_msg = None + self.connect_result = None self.before_script = before_script self.after_script = after_script self.disconnect_script = disconnect_script self._should_die = False self.abort_reason = "" + self.connect_result = "" self.global_dns_1 = gdns1 self.global_dns_2 = gdns2 @@ -251,6 +272,7 @@ class ConnectThread(threading.Thread): self.lock.release() return message + @abortable def reset_ip_addresses(self, wiface, liface): """ Resets the IP addresses for both wired/wireless interfaces. @@ -262,13 +284,15 @@ class ConnectThread(threading.Thread): self.SetStatus('resetting_ip_address') wiface.SetAddress('0.0.0.0') liface.SetAddress('0.0.0.0') - + + @abortable def put_iface_down(self, iface): """ Puts the given interface down. """ print 'Putting interface down' self.SetStatus('interface_down') iface.Down() + @abortable def run_script_if_needed(self, script, msg): """ Execute a given script if needed. @@ -280,21 +304,24 @@ class ConnectThread(threading.Thread): if script: print 'Executing %s script' % (msg) misc.ExecuteScript(script) - + + @abortable def flush_routes(self, wiface, liface): """ Flush the routes for both wired/wireless interfaces. """ self.SetStatus('flushing_routing_table') print 'Flushing the routing table...' wiface.FlushRoutes() liface.FlushRoutes() - + + @abortable def set_broadcast_address(self, iface): """ Set the broadcast address for the given interface. """ if not self.network.get('broadcast') == None: self.SetStatus('setting_broadcast_address') print 'Setting the broadcast address...' + self.network['broadcast'] iface.SetAddress(broadcast=self.network['broadcast']) - + + @abortable def set_ip_address(self, iface): """ Set the IP address for the given interface. @@ -315,7 +342,8 @@ class ConnectThread(threading.Thread): if dhcp_status in ['no_dhcp_offers', 'dhcp_failed']: self.abort_connection(dhcp_status) return - + + @abortable def set_dns_addresses(self): """ Set the DNS address(es). @@ -336,6 +364,20 @@ class ConnectThread(threading.Thread): self.network.get('dns3'), self.network.get('search_domain')) + @abortable + def release_dhcp_clients(self, wiface, liface): + """ Release all running dhcp clients. """ + print "Releasing DHCP leases..." + wiface.ReleaseDHCP() + liface.ReleaseDHCP() + + @abortable + def stop_dhcp_clients(self, iface): + """ Stop and running DHCP clients, as well as wpa_supplicant. """ + print 'Stopping wpa_supplicant and any DHCP clients' + iface.StopWPA() + BACKEND.StopDHCP() + def connect_aborted(self, reason): """ Sets the thread status to aborted in a thread-safe way. @@ -347,7 +389,7 @@ class ConnectThread(threading.Thread): reason = self.abort_reason self.connecting_message = reason self.is_aborted = True - self.abort_msg = reason + self.connect_result = reason self.is_connecting = False print 'exiting connection thread' @@ -356,18 +398,6 @@ class ConnectThread(threading.Thread): self.abort_reason = reason self.should_die = True - def release_dhcp_clients(self, wiface, liface): - """ Release all running dhcp clients. """ - print "Releasing DHCP leases..." - wiface.ReleaseDHCP() - liface.ReleaseDHCP() - - def stop_dhcp_clients(self, iface): - """ Stop and running DHCP clients, as well as wpa_supplicant. """ - print 'Stopping wpa_supplicant and any DHCP clients' - iface.StopWPA() - BACKEND.StopDHCP() - def abort_if_needed(self): """ Abort the thread is it has been requested. """ self.lock.acquire() @@ -377,7 +407,8 @@ class ConnectThread(threading.Thread): thread.exit() finally: self.lock.release() - + + @abortable def put_iface_up(self, iface): """ Bring up given interface. """ print 'Putting interface up...' @@ -397,11 +428,15 @@ class Wireless(Controller): self._wpa_driver = value if self.wiface: self.SetWPADriver(value) - def get_wpa_driver(self): return self._wpa_driver - wpa_driver = property(get_wpa_driver, set_wpa_driver) + def set_iface(self, value): + self.wiface = value + def get_iface(self): + return self.wiface + iface = property(get_iface, set_iface) + def LoadBackend(self, backend): """ Load a given backend. @@ -541,6 +576,9 @@ class Wireless(Controller): """ return self.wiface.IsUp() + + def StopWPA(self): + return self.wiface.StopWPA() def CreateAdHocNetwork(self, essid, channel, ip, enctype, key, enc_used, ics): @@ -632,6 +670,7 @@ class Wireless(Controller): misc.ExecuteScript(self.disconnect_script) wiface.ReleaseDHCP() + wiface.StopWPA() wiface.SetAddress('0.0.0.0') wiface.Down() wiface.Up() @@ -699,17 +738,13 @@ class WirelessConnectThread(ConnectThread): self.is_connecting = True # Run pre-connection script. - self.abort_if_needed() self.run_script_if_needed(self.before_script, 'pre-connection') - self.abort_if_needed() # Take down interface and clean up previous connections. self.put_iface_down(wiface) - self.abort_if_needed() self.release_dhcp_clients(wiface, liface) self.reset_ip_addresses(wiface, liface) self.stop_dhcp_clients(wiface) - self.abort_if_needed() self.flush_routes(wiface, liface) # Generate PSK and authenticate if needed. @@ -717,10 +752,8 @@ class WirelessConnectThread(ConnectThread): self.generate_psk_and_authenticate(wiface) # Put interface up. - self.abort_if_needed() self.SetStatus('configuring_interface') self.put_iface_up(wiface) - self.abort_if_needed() # Associate. wiface.SetMode(self.network['mode']) @@ -737,24 +770,23 @@ class WirelessConnectThread(ConnectThread): self.SetStatus('validating_authentication') if not wiface.ValidateAuthentication(time.time()): self.abort_connection('bad_pass') - self.abort_if_needed() # Set up gateway, IP address, and DNS servers. self.set_broadcast_address(wiface) - self.abort_if_needed() self.set_ip_address(wiface) self.set_dns_addresses() # Run post-connection script. - self.abort_if_needed() self.run_script_if_needed(self.after_script, 'post-connection') self.SetStatus('done') print 'Connecting thread exiting.' if self.debug: print "IP Address is: " + str(wiface.GetIP()) + self.connect_result = "Success" self.is_connecting = False - + + @abortable def generate_psk_and_authenticate(self, wiface): """ Generates a PSK and authenticates if necessary. @@ -799,6 +831,12 @@ class Wired(Controller): def get_link_detect(self): return self._link_detect link_detect = property(get_link_detect, set_link_detect) + def set_iface(self, value): + self.liface = value + def get_iface(self): + return self.liface + iface = property(get_iface, set_iface) + def LoadBackend(self, backend): """ Load the backend up. """ Controller.LoadBackend(self, backend) @@ -831,7 +869,7 @@ class Wired(Controller): self.wiface, self.liface, debug) self.connecting_thread.setDaemon(True) self.connecting_thread.start() - return True + return self.connecting_thread def DetectWiredInterface(self): """ Attempts to automatically detect a wired interface. """ @@ -937,28 +975,22 @@ class WiredConnectThread(ConnectThread): self.is_connecting = True # Run pre-connection script. - self.abort_if_needed() self.run_script_if_needed(self.before_script, 'pre-connection') - self.abort_if_needed() # Take down interface and clean up previous connections. self.put_iface_down(liface) self.release_dhcp_clients(wiface, liface) self.reset_ip_addresses(wiface, liface) self.stop_dhcp_clients(wiface) - self.abort_if_needed() self.flush_routes(wiface, liface) # Bring up interface. self.put_iface_up(liface) - self.abort_if_needed() # Set gateway, IP adresses, and DNS servers. self.set_broadcast_address(liface) - self.abort_if_needed() self.set_ip_address(liface) self.set_dns_addresses() - self.abort_if_needed() # Run post-connection script. self.run_script_if_needed(self.after_script, 'post-connection') @@ -967,4 +999,6 @@ class WiredConnectThread(ConnectThread): print 'Connecting thread exiting.' if self.debug: print "IP Address is: " + str(liface.GetIP()) + + self.connect_result = "Success" self.is_connecting = False diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index 150d81e..7d7a047 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -83,8 +83,9 @@ class WicdDaemon(dbus.service.Object): self.wired = networking.Wired() self.config = ConfigManager(os.path.join(wpath.etc, "manager-settings.conf")) - self.wired_bus= WiredDaemon(bus_name, wired=self.wired, wifi=self.wifi) - self.wireless_bus = WirelessDaemon(bus_name, wired=self.wired, + self.wired_bus= WiredDaemon(bus_name, self, wired=self.wired, + wifi=self.wifi) + self.wireless_bus = WirelessDaemon(bus_name, self, wired=self.wired, wifi=self.wifi) self.forced_disconnect = False self.need_profile_chooser = False @@ -321,8 +322,6 @@ class WicdDaemon(dbus.service.Object): def GetAutoReconnect(self): """ Returns the value of self.auto_reconnect. See SetAutoReconnect. """ do = bool(self.auto_reconnect) - return self.__printReturn('returning automatically reconnect when ' \ - + 'connection drops', do) @dbus.service.method('org.wicd.daemon') def SetAutoReconnect(self, value): @@ -358,9 +357,12 @@ class WicdDaemon(dbus.service.Object): print 'canceling connection attempt' if self.wifi.connecting_thread: self.wifi.connecting_thread.should_die = True + self.wifi.StopDHCP() + self.wifi.StopWPA() if self.wired.connecting_thread: self.wired.connecting_thread.should_die = True - misc.Run("killall dhclient dhclient3 wpa_supplicant") + self.wired.StopDHCP() + #misc.Run("killall dhclient pump dhcpcd-bin dhclient3 wpa_supplicant") @dbus.service.method('org.wicd.daemon') def GetCurrentInterface(self): @@ -699,7 +701,33 @@ class WicdDaemon(dbus.service.Object): return False self.auto_connecting = False return False + + @dbus.service.method("org.wicd.daemon") + def ConnectResultsAvailable(self): + if ((self.wired.connecting_thread and self.wired.connecting_thread.connect_result) or + (self.wifi.connecting_thread and self.wifi.connecting_thread.connect_result)): + return True + else: + return False + + @dbus.service.method("org.wicd.daemon") + def SendConnectResultsIfAvail(self): + if self.ConnectResultsAvailable(): + self.SendConnectResult() + @dbus.service.method("org.wicd.daemon") + def SendConnectResult(self): + if self.wired.connecting_thread and self.wired.connecting_thread.connect_result: + self.ConnectResultsSent(self.wired.connecting_thread.connect_result) + self.wired.connecting_thread.connect_result = "" + elif self.wifi.connecting_thread and self.wifi.connecting_thread.connect_result: + self.ConnectResultsSent(self.wifi.connecting_thread.connect_result) + self.wifi.connecting_thread.connect_result = "" + + @dbus.service.signal(dbus_interface="org.wicd.daemon",signature='s') + def ConnectResultsSent(self, result): + print "Sending connectiong attempt result %s" % result + @dbus.service.signal(dbus_interface='org.wicd.daemon', signature='') def LaunchChooser(self): """ Emits the wired profile chooser dbus signal. """ @@ -731,12 +759,6 @@ class WicdDaemon(dbus.service.Object): """ pass - def __printReturn(self, text, value): - """ Prints the specified text and value, then returns the value. """ - if self.debug_mode: - print ''.join([text, " ", str(value)]) - return value - def ReadConfig(self): """ Reads the manager-settings.conf file. @@ -823,11 +845,12 @@ class WicdDaemon(dbus.service.Object): class WirelessDaemon(dbus.service.Object): """ DBus interface for wireless connection operations. """ - def __init__(self, bus_name, wired=None, wifi=None, debug=False): + def __init__(self, bus_name, daemon, wired=None, wifi=None, debug=False): """ Intitialize the wireless DBus interface. """ dbus.service.Object.__init__(self, bus_name=bus_name, object_path='/org/wicd/daemon/wireless') self.hidden_essid = None + self.daemon = daemon self.wired = wired self.wifi = wifi self.debug_mode = debug @@ -1012,7 +1035,7 @@ class WirelessDaemon(dbus.service.Object): self.wifi.disconnect_script = self.GetWirelessProperty(id, 'disconnectscript') print 'Connecting to wireless network ' + self.LastScan[id]['essid'] - return self.wifi.Connect(self.LastScan[id], debug=self.debug_mode) + conthread = self.wifi.Connect(self.LastScan[id], debug=self.debug_mode) @dbus.service.method('org.wicd.daemon.wireless') def CheckIfWirelessConnecting(self): @@ -1174,10 +1197,11 @@ class WirelessDaemon(dbus.service.Object): class WiredDaemon(dbus.service.Object): """ DBus interface for wired connection operations. """ - def __init__(self, bus_name, wired=None, wifi=None, debug=False): + def __init__(self, bus_name, daemon, wired=None, wifi=None, debug=False): """ Intitialize the wireless DBus interface. """ dbus.service.Object.__init__(self, bus_name=bus_name, object_path="/org/wicd/daemon/wired") + self.daemon = daemon self.wired = wired self.wifi = wifi self.debug_mode = debug @@ -1587,4 +1611,5 @@ if __name__ == '__main__': print ("Root privileges are required for the daemon to run properly." + " Exiting.") sys.exit(1) + gobject.threads_init() main(sys.argv)