~awn-extras/awn-extras/network-detection

« back to all changes in this revision

Viewing changes to shared/python/network/nm.py

  • Committer: Mark Lee
  • Date: 2010-04-18 22:25:35 UTC
  • Revision ID: bzr@lazymalevolence.com-20100418222535-ppgcuwmvak2xpb77
Add modular Python library that detects whether the computer is connected to a network. Currently only implemented for NetworkManager.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
#
 
3
# Network detection library for Python (NetworkManager implementation).
 
4
# Copyright (C) 2009, 2010  Mark Lee <avant-wn@lazymalevolence.com>
 
5
#
 
6
# This library is free software; you can redistribute it and/or
 
7
# modify it under the terms of the GNU Lesser General Public
 
8
# License as published by the Free Software Foundation; either
 
9
# version 2.1 of the License, or (at your option) any later version.
 
10
#
 
11
# This library is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
# Lesser General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU Lesser General Public
 
17
# License along with this library; if not, write to the Free Software
 
18
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 
 
20
import dbus
 
21
from dbus.mainloop.glib import DBusGMainLoop
 
22
import gobject
 
23
 
 
24
DBusGMainLoop(set_as_default=True)
 
25
 
 
26
HAS_WATCH_NAME_OWNER = (dbus.version >= (0, 81, 0))
 
27
 
 
28
if not HAS_WATCH_NAME_OWNER:
 
29
 
 
30
    def timeout_add_seconds(interval, callback):
 
31
        if hasattr(gobject, 'timeout_add_seconds'):
 
32
            gobject.timeout_add_seconds(interval, callback)
 
33
        else:
 
34
            gobject.timeout_add(interval * 1000, callback)
 
35
 
 
36
    def watch_name_owner(bus, bus_name, callback):
 
37
        def check_for_name():
 
38
            if bus.name_has_owner(bus_name):
 
39
                callback(bus_name)
 
40
                return False
 
41
            else:
 
42
                callback('')
 
43
                return True
 
44
        timeout_add_seconds(1, check_for_name)
 
45
    dbus.SystemBus.watch_name_owner = watch_name_owner
 
46
 
 
47
NM_BUS_NAME = 'org.freedesktop.NetworkManager'
 
48
NM_OBJECT_PATH = '/org/freedesktop/NetworkManager'
 
49
DBUS_PROPS_IFACE_NAME = 'org.freedesktop.DBus.Properties'
 
50
NM_IFACE_NAME = 'org.freedesktop.NetworkManager'
 
51
NM_ACTIVE_CONNECTION_IFACE_NAME = \
 
52
    'org.freedesktop.NetworkManager.Connection.Active'
 
53
 
 
54
NM_STATE_UNKNOWN = 0
 
55
NM_STATE_ASLEEP = 1
 
56
NM_STATE_CONNECTING = 2
 
57
NM_STATE_CONNECTED = 3
 
58
NM_STATE_DISCONNECTED = 4
 
59
 
 
60
NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0
 
61
NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1
 
62
NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2
 
63
 
 
64
 
 
65
class DObject(object):
 
66
    '''Wrapper for DBus object proxies.'''
 
67
 
 
68
    def initialize(self, bus_name, object_path, iface_name):
 
69
        self.proxy = self.bus.get_object(bus_name, object_path)
 
70
        self.iface_name = iface_name
 
71
        self.iface = dbus.Interface(self.proxy, dbus_interface=iface_name)
 
72
        self.dbus_iface = dbus.Interface(self.proxy,
 
73
                                         dbus_interface=DBUS_PROPS_IFACE_NAME)
 
74
 
 
75
    def __getattr__(self, name):
 
76
        return self.dbus_iface.Get(self.iface_name, name)
 
77
 
 
78
 
 
79
class ActiveConnection(DObject):
 
80
    '''Wraps an active connection proxy object.'''
 
81
 
 
82
    def __init__(self, bus, object_path):
 
83
        self.bus = bus
 
84
        self.initialize(NM_BUS_NAME, object_path,
 
85
                        NM_ACTIVE_CONNECTION_IFACE_NAME)
 
86
 
 
87
 
 
88
class Detector(DObject, gobject.GObject):
 
89
    '''Detects that a network connection exists, according to NetworkManager.
 
90
    '''
 
91
 
 
92
    __gsignals__ = {
 
93
        'connected': (gobject.SIGNAL_RUN_FIRST, None, ()),
 
94
        'disconnected': (gobject.SIGNAL_RUN_FIRST, None, ()),
 
95
        'state_changed': (gobject.SIGNAL_RUN_FIRST, None, (int,)),
 
96
        }
 
97
 
 
98
    def __init__(self):
 
99
        super(Detector, self).__init__()
 
100
        self.__connection_state = None
 
101
        self.bus = dbus.SystemBus()
 
102
        if self.bus.name_has_owner(NM_BUS_NAME):
 
103
            self.initialize()
 
104
        else:
 
105
            # requires dbus-python >= 0.81.0
 
106
 
 
107
            def on_watch(conn):
 
108
                if conn != '':
 
109
                    self.initialize()
 
110
            self.bus.watch_name_owner(NM_BUS_NAME, on_watch)
 
111
 
 
112
    def initialize(self):
 
113
        super(Detector, self).initialize(NM_BUS_NAME, NM_OBJECT_PATH,
 
114
                                         NM_IFACE_NAME)
 
115
        self.iface.connect_to_signal('StateChanged', self.__on_state_changed)
 
116
        self.__on_state_changed(self.State)
 
117
 
 
118
    def __getattr__(self, name):
 
119
        value = super(Detector, self).__getattr__(name)
 
120
        if name == 'ActiveConnections':
 
121
            value = [ActiveConnection(self.bus, path) for path in value]
 
122
        return value
 
123
 
 
124
    def __on_state_changed(self, state):
 
125
        '''Determines the state of each "active" connection to determine if
 
126
        the computer is connected to a network, as the state property is too
 
127
        unreliable.
 
128
        '''
 
129
        active_connections = self.ActiveConnections
 
130
        real_conns = len([x for x in active_connections
 
131
                          if x.State == NM_ACTIVE_CONNECTION_STATE_ACTIVATED])
 
132
        connected = real_conns > 0
 
133
        if connected != self.__connection_state:
 
134
            self.__connection_state = connected
 
135
            if connected:
 
136
                self.emit('connected')
 
137
            else:
 
138
                self.emit('disconnected')
 
139
        self.emit('state_changed', state)
 
140
 
 
141
    @property
 
142
    def connected(self):
 
143
        '''The way to determine whether the computer is connected to a
 
144
        network, without having to deal with signals.
 
145
        '''
 
146
        return self.__connection_state