示例#1
0
文件: service.py 项目: disco0/public
    def iface(self):
        if hasattr(self, "_iface"):
            iface = self._iface
        else:
            iface_methods = []
            for method_name, (args_xform, returns_xform,
                              fn) in self.methods.items():
                iface_methods.append(
                    Method(
                        method_name,
                        arguments=args_xform.signature(),
                        returns=returns_xform.signature(),
                    ))

            iface_properties = []
            for prop_name, (xform, _, kwargs) in self.properties.items():
                iface_properties.append(
                    Property(prop_name, xform.signature(), **kwargs))

            iface_signals = []
            for signal_name, xform in self.signals.items():
                iface_signals.append(Signal(signal_name, xform.signature()))

            iface = DBusInterface(
                f"{self.service.namespace}.{self.iface_name}",
                *(iface_methods + iface_properties + iface_signals),
            )
            self._iface = iface
        return iface
示例#2
0
class Network(BaseIface):
    """Interface implemented by objects representing configured networks"""

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1.Network'

    iface = DBusInterface(
        INTERFACE_PATH,
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "Network(Path: %s, Properties: %s)" % (self.get_path(),
                                                      self.get_properties())

    #
    # Properties
    #
    def get_properties(self):
        """Properties of the configured network

        Dictionary contains entries from "network" block of  wpa_supplicant.conf.
        All values are string type, e.g., frequency is "2437", not 2437.
        """

        network_properties = self.get('Properties')
        ssid = network_properties.get('ssid', '')
        if ssid:
            quote_chars = {'"', "'"}
            ssid = ssid[1:] if ssid[0] in quote_chars else ssid
            ssid = ssid[:-1] if ssid[-1] in quote_chars else ssid
        network_properties.update({
            'ssid': ssid
        })
        return network_properties

    def get_enabled(self):
        """Determines if the configured network is enabled or not"""

        return self.get('Enabled')
示例#3
0
Note: There are some hardcoded values in this example and should not be expected
to run on every PC but serves as a reference.
"""

from twisted.internet import reactor, defer
from txdbus import client, error
from txdbus.interface import DBusInterface, Method, Signal
import time

dbus_name = 'fi.w1.wpa_supplicant1'
root_iface_str = 'fi.w1.wpa_supplicant1'
root_iface_obj_path = "/" + root_iface_str.replace('.', '/')

interface_iface_str = root_iface_str + ".Interface"
interface_iface = DBusInterface(
    interface_iface_str, Signal('ScanDone', 'b'),
    Method('Scan', arguments='a{sv}'),
    Method('AddNetwork', arguments='a{sv}', returns='o'),
    Method('RemoveNetwork', arguments='o'),
    Method('SelectNetwork', arguments='o'))


@defer.inlineCallbacks
def set_mode_example():
    cli = yield client.connect(reactor, busAddress='system')

    root_obj = yield cli.getRemoteObject(dbus_name, root_iface_obj_path)
    print "Root Object: %s" % root_obj

    wlan0_obj_path = yield root_obj.callRemote('GetInterface', 'wlan1')
    print "WLAN0 Object Path: %s" % wlan0_obj_path
示例#4
0
BUS_NAME = 'org.tagnet.si446x'
OBJECT_PATH = '/org/tagnet/si446x/0/0'  # object name includes device id/port numbers

si446x_dbus_interface = DBusInterface(
    BUS_NAME,
    Method('cca', returns='u'),
    Method('clear_status', returns='s'),
    Method('control', arguments='s', returns='s'),
    Method('dump_radio', arguments='s', returns='s'),
    Method('dump_trace', arguments='sissu', returns='a(dyssay)'),
    Method('send', arguments='ayu', returns='s'),
    Method('spi_send', arguments='ays', returns='s'),
    Method('spi_send_recv', arguments='ayuss', returns='ay'),
    Method('status', returns='s'),
    Signal('new_status', 's'),
    Signal('receive', 'ayu'),
    Signal('send_cmp', 's'),
)


class Si446xDbus(objects.DBusObject):
    """
    provides the interface for accessing the SI446x Radio Chip Driver
    """
    dbusInterfaces = [si446x_dbus_interface]

    def __init__(self, objectPath, trace=None):
        super(Si446xDbus, self).__init__(objectPath)
        self.uuid = binascii.hexlify(os.urandom(16))
        self.status = 'OFF'
示例#5
0
class BSS(BaseIface):
    """Interface implemented by objects representing a scanned BSSs (scan results)"""

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1.BSS'

    iface = DBusInterface(
        INTERFACE_PATH,
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "BSS(Path: %s, SSID: %s, BSSID: %s, Signal: %sdBm)" % (self.get_path(),
                                                                      self.get_ssid(),
                                                                      self.get_bssid(),
                                                                      self.get_signal_dbm())

    def to_dict(self):
        """Dict representation of a BSS object"""

        elements = (
            ('ssid', self.get_ssid),
            ('rsn', self.get_rsn),
            ('channel', self.get_channel),
            ('privacy', self.get_privacy),
            ('wpa', self.get_wpa),
            ('signal_dbm', self.get_signal_dbm),
            ('signal_quality', self.get_signal_quality),
            ('network_type', self.get_network_type),
            ('privacy', self.get_privacy),
        )
        out = {}
        for k, v in elements:
            try:
                out[k] = v()
            except:
                logger.exception('Error while fetching BSS information')
        return out

    #
    # Properties
    #
    def get_channel(self):
        """Wi-Fi channel number (1-14)"""
        freq = self.get_frequency()

        if freq == 2484:  # Handle channel 14
            return 14
        elif freq >= 2412 and freq <= 2472:
            return 1 + (freq - 2412) / 5
        elif freq >= 5180 and freq <= 5905:
            return 36 + (freq - 5180) / 5
        else:
            logger.warn('Unexpected frequency %s', freq)
            raise WpaSupplicantException('Unexpected frequency in WiFi connection.')

    def get_ssid(self):
        """SSID of the BSS in ASCII"""

        return "".join(chr(i) for i in self.get('SSID'))

    def get_bssid(self):
        """BSSID of the BSS as hex bytes delimited by a colon"""

        return ":".join(["{:02X}".format(i) for i in self.get('BSSID')])

    def get_frequency(self):
        """Frequency of the BSS in MHz"""

        return self.get('Frequency')

    def get_wpa(self):
        """WPA information of the BSS, empty dictionary indicates no WPA support

        Dictionaries are::

            {
                "KeyMgmt": <Possible array elements: "wpa-psk", "wpa-eap", "wpa-none">,
                "Pairwise": <Possible array elements: "ccmp", "tkip">,
                "Group": <Possible values are: "ccmp", "tkip", "wep104", "wep40">,
                "MgmtGroup": <Possible values are: "aes128cmac">
            }
        """

        return self.get('WPA')

    def get_rsn(self):
        """RSN/WPA2 information of the BSS, empty dictionary indicates no RSN support

        Dictionaries are::

            {
                "KeyMgmt": <Possible array elements: "wpa-psk", "wpa-eap", "wpa-ft-psk", "wpa-ft-eap", "wpa-psk-sha256", "wpa-eap-sha256">,
                "Pairwise": <Possible array elements: "ccmp", "tkip">,
                "Group": <Possible values are: "ccmp", "tkip", "wep104", "wep40">,
                "MgmtGroup": <Possible values are: "aes128cmac">,
            }
        """

        return self.get('RSN')

    def get_ies(self):
        """All IEs of the BSS as a chain of TLVs"""

        return self.get('IEs')

    def get_privacy(self):
        """Indicates if BSS supports privacy"""

        return self.get('Privacy')

    def get_mode(self):
        """Describes mode of the BSS

            Possible values are: "ad-hoc"
                                 "infrastructure"

        """

        return self.get('Mode')

    def get_rates(self):
        """Descending ordered array of rates supported by the BSS in bits per second"""

        return self.get('Rates')

    def get_signal_dbm(self):
        """Signal strength of the BSS in dBm"""

        return self.get('Signal')

    def get_signal_quality(self):
        """Signal strength of the BSS as a percentage (0-100)"""

        dbm = self.get_signal_dbm()
        if dbm <= -100:
            return 0
        elif dbm >= -50:
            return 100
        else:
            return 2 * (dbm + 100)

    def get_network_type(self):
        """Return the network type as a string

        Possible values are:
                'WPA'
                'WPA2'
                'WEP'
                'OPEN'
        """

        if self.get_privacy():
            rsn_key_mgmt = self.get_rsn().get('KeyMgmt')
            if rsn_key_mgmt:
                return 'WPA2'

            wpa_key_mgmt = self.get_wpa().get('KeyMgmt')
            if wpa_key_mgmt:
                return 'WPA'

            return 'WEP'
        else:
            return 'OPEN'
示例#6
0
class Interface(BaseIface):
    """Interface implemented by objects related to network interface added to wpa_supplicant"""

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1.Interface'

    iface = DBusInterface(
        INTERFACE_PATH,
        Method('Scan', arguments='a{sv}'),
        Method('AddNetwork', arguments='a{sv}', returns='o'),
        Method('RemoveNetwork', arguments='o'),
        Method('SelectNetwork', arguments='o'),
        Method('Disconnect'),
        Signal('ScanDone', 'b'),
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "Interface(Path: %s, Name: %s, State: %s)" % (self.get_path(),
                                                             self.get_ifname(),
                                                             self.get_state())

    #
    # Methods
    #
    def scan(self, type='active', ssids=None, ies=None, channels=None, block=False):
        """Triggers a scan

        :returns: List of `BSS` objects if block=True else None
        :raises InvalidArgs: Invalid argument format
        :raises MethodTimeout: Scan has timed out (only if block=True)
        :raises UnknownError: An unknown error occurred
        """

        # TODO: Handle the other arguments
        scan_options = {
            'Type': type
        }

        # If blocking, register for the ScanDone signal and return BSSs
        if block:
            deferred_queue = self.register_signal_once('ScanDone')
            self._call_remote('Scan', scan_options)  # Trigger scan
            success = deferred_queue.get(timeout=10)
            if success:
                return [BSS(path, self._conn, self._reactor) for path in self.get_all_bss()]
            else:
                raise UnknownError('ScanDone signal received without success')
        else:
            self._call_remote('Scan', scan_options)  # Trigger scan

    def add_network(self, network_cfg):
        """Adds a new network to the interface

        :param network_cfg: Dictionary of config, see wpa_supplicant.conf for k/v pairs
        :returns: `Network` object that was registered w/ wpa_supplicant
        :raises InvalidArgs: Invalid argument format
        :raises UnknownError: An unknown error occurred
        """

        network_path = self._call_remote('AddNetwork', network_cfg)
        return Network(network_path, self._conn, self._reactor)

    def remove_network(self, network_path):
        """Removes a configured network from the interface

        :param network_path: D-Bus object path to the desired network
        :returns: None
        :raises NetworkUnknown: The specified `network_path` is invalid
        :raises InvalidArgs: Invalid argument format
        :raises UnknownError: An unknown error occurred
        """

        self._call_remote('RemoveNetwork', network_path)

    def select_network(self, network_path):
        """Attempt association with a configured network

        :param network_path: D-Bus object path to the desired network
        :returns: None
        :raises NetworkUnknown: The specified `network_path` has not been added
        :raises InvalidArgs: Invalid argument format
        """

        self._call_remote('SelectNetwork', network_path)

    def disconnect_network(self):
        """Disassociates the interface from current network

        :returns: None
        :raises NotConnected: The interface is not currently connected to a network
        """

        self._call_remote('Disconnect')

    #
    # Properties
    #
    def get_ifname(self):
        """Name of network interface controlled by the interface, e.g., wlan0"""

        return self.get('Ifname')

    def get_current_bss(self):
        """BSS object path which wpa_supplicant is associated with

                Returns "/" if is not associated at all
        """

        bss_path = self.get('CurrentBSS')
        if bss_path == '/' or bss_path is None:
            return None
        else:
            return BSS(bss_path, self._conn, self._reactor)

    def get_current_network(self):
        """The `Network` object which wpa_supplicant is associated with

                Returns `None` if is not associated at all
        """

        network_path = self.get('CurrentNetwork')
        if network_path == '/' or network_path is None:
            return None
        else:
            return Network(network_path, self._conn, self._reactor)

    def get_networks(self):
        """List of `Network` objects representing configured networks"""

        networks = list()
        paths = self.get('Networks')
        for network_path in paths:
            if network_path == '/':
                networks.append(None)
            else:
                networks.append(Network(network_path, self._conn, self._reactor))
        return networks

    def get_state(self):
        """A state of the interface.

            Possible values are: "disconnected"
                                 "inactive"
                                 "scanning"
                                 "authenticating"
                                 "associating"
                                 "associated"
                                 "4way_handshake"
                                 "group_handshake"
                                 "completed"
                                 "unknown"
        """

        return self.get('State')

    def get_scanning(self):
        """Determines if the interface is already scanning or not"""

        return self.get('Scanning')

    def get_scan_interval(self):
        """Time (in seconds) between scans for a suitable AP. Must be >= 0"""

        return self.get('ScanInterval')

    def get_fast_reauth(self):
        """Identical to fast_reauth entry in wpa_supplicant.conf"""

        return self.get('FastReauth')

    def get_all_bss(self):
        """List of D-Bus objects paths representing BSSs known to the interface"""

        return self.get('BSSs')

    def get_driver(self):
        """Name of driver used by the interface, e.g., nl80211"""

        return self.get('Driver')

    def get_country(self):
        """Identical to country entry in wpa_supplicant.conf"""

        return self.get('Country')

    def get_bridge_ifname(self):
        """Name of bridge network interface controlled by the interface, e.g., br0"""

        return self.get('BridgeIfname')

    def get_bss_expire_age(self):
        """Identical to bss_expiration_age entry in wpa_supplicant.conf file"""

        return self.get('BSSExpireAge')

    def get_bss_expire_count(self):
        """Identical to bss_expiration_scan_count entry in wpa_supplicant.conf file"""

        return self.get('BSSExpireCount')

    def get_ap_scan(self):
        """Identical to ap_scan entry in wpa_supplicant configuration file.

                Possible values are 0, 1 or 2.
        """

        return self.get('ApScan')

    def set_country(self, country_code):
        self.set('Country', country_code)
示例#7
0
class WpaSupplicant(BaseIface):
    """Interface implemented by the main wpa_supplicant D-Bus object

            Registered in the bus as "fi.w1.wpa_supplicant1"
    """

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1'

    iface = DBusInterface(
        INTERFACE_PATH,
        Method('CreateInterface', arguments='a{sv}', returns='o'),
        Method('GetInterface', arguments='s', returns='o'),
        Method('RemoveInterface', arguments='o'),
        Signal('InterfaceAdded', 'o,a{sv}'),
        Signal('InterfaceRemoved', 'o'),
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __init__(self, *args, **kwargs):
        BaseIface.__init__(self, *args, **kwargs)
        self._interfaces_cache = dict()

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "WpaSupplicant(Interfaces: %s)" % self.get_interfaces()

    #
    # Methods
    #
    def get_interface(self, interface_name):
        """Get D-Bus object related to an interface which wpa_supplicant already controls

        :returns: Interface object that implements the wpa_supplicant Interface API.
        :rtype: :class:`~Interface`
        :raises InterfaceUnknown: wpa_supplicant doesn't know anything about `interface_name`
        :raises UnknownError: An unknown error occurred
        """

        interface_path = self._call_remote_without_introspection('GetInterface',
                                                                 interface_name)
        interface = self._interfaces_cache.get(interface_path, None)
        if interface is not None:
            return interface
        else:
            interface = Interface(interface_path, self._conn, self._reactor)
            self._interfaces_cache[interface_path] = interface
            return interface

    def create_interface(self, interface_name, driver=None):
        """Registers a wireless interface in wpa_supplicant

        :returns: Interface object that implements the wpa_supplicant Interface API
        :raises InterfaceExists: The `interface_name` specified is already registered
        :raises UnknownError: An unknown error occurred
        """

        interface_path = self._call_remote_without_introspection('CreateInterface',
                                                                 {'Ifname': interface_name,
                                                                  'Driver': driver})
        return Interface(interface_path, self._conn, self._reactor)

    def remove_interface(self, interface_path):
        """Deregisters a wireless interface from wpa_supplicant

        :param interface_path: D-Bus object path to the interface to be removed
        :returns: None
        :raises InterfaceUnknown: wpa_supplicant doesn't know anything about `interface_name`
        :raises UnknownError: An unknown error occurred
        """

        self._call_remote_without_introspection('RemoveInterface', interface_path)

    #
    # Properties
    #
    def get_debug_level(self):
        """Global wpa_supplicant debugging level

        :returns:  Possible values: "msgdump" (verbose debugging)
                                    "debug" (debugging)
                                    "info" (informative)
                                    "warning" (warnings)
                                    "error" (errors)
        :rtype: str
        """

        return self.get('DebugLevel')

    def get_debug_timestamp(self):
        """ Determines if timestamps are shown in debug logs"""

        return self.get('DebugTimestamp')

    def get_debug_showkeys(self):
        """Determines if secrets are shown in debug logs"""

        return self.get('DebugShowKeys')

    def get_interfaces(self):
        """An array with paths to D-Bus objects representing controlled interfaces"""

        return self.get('Interfaces')

    def get_eap_methods(self):
        """An array with supported EAP methods names"""

        return self.get('EapMethods')
示例#8
0
Note: There are some hardcoded values in this example and should not be expected
to run on every PC but serves as a reference.
"""

from twisted.internet import reactor, defer
from txdbus import client, error
from txdbus.interface import DBusInterface, Method, Signal
import time

dbus_name = 'fi.w1.wpa_supplicant1'
root_iface_str = 'fi.w1.wpa_supplicant1'
root_iface_obj_path = "/" + root_iface_str.replace('.', '/')

interface_iface_str = root_iface_str + ".Interface"
interface_iface = DBusInterface(interface_iface_str,
                                Signal('ScanDone', 'b'),
                                Method('Scan', arguments='a{sv}'),
                                Method('AddNetwork', arguments='a{sv}', returns='o'),
                                Method('RemoveNetwork', arguments='o'),
                                Method('SelectNetwork', arguments='o'))


@defer.inlineCallbacks
def set_mode_example():
    cli = yield client.connect(reactor, busAddress='system')

    root_obj = yield cli.getRemoteObject(dbus_name, root_iface_obj_path)
    print("Root Object: %s" % root_obj)

    wlan0_obj_path = yield root_obj.callRemote('GetInterface', 'wlan1')
    print("WLAN0 Object Path: %s" % wlan0_obj_path)
示例#9
0
文件: bus.py 项目: rheenen/txdbus
class Bus(objects.DBusObject):
    """
    DBus Bus implementation.

    @ivar stdIface: L{interface.DBusInterface} containing the standard bus interface
    @type stdIface: L{interface.DBusInterface}
    """
    stdIface = DBusInterface(
        'org.freedesktop.DBus',
        Method('Hello', arguments='', returns='s'),
        Method('GetId', arguments='', returns='s'),
        Method('RequestName', arguments='su', returns='u'),
        Method('ReleaseName', arguments='s', returns='u'),
        Method('ListQueuedOwners', arguments='s', returns='as'),
        Method('AddMatch', arguments='s', returns=''),
        Method('RemoveMatch', arguments='s', returns=''),
        Method('GetNameOwner', arguments='s', returns='s'),
        Method('GetConnectionUnixUser', arguments='s', returns='u'),

        #Not Implemented Methods
        Method('GetConnectionUnixProcessId', arguments='s', returns='u'),
        Method('ListActivatableNames', arguments='', returns='as'),
        Method('UpdateActivationEnvironment', arguments='a{ss}', returns=''),
        Method('StartServiceByName', arguments='su', returns='u'),
        Method('GetAdtAuditSessionData', arguments='s', returns='u'),
        Method('GetConnectionSELinuxSecurityContext',
               arguments='su',
               returns='ay'),
        Method('ReloadConfig'),
        Signal('NameAcquired', arguments='s'),
        Signal('NameLost', arguments='s'),
        Signal('NameOwnerChanged', arguments='sss'))

    dbusInterfaces = [stdIface]

    def __init__(self):
        objects.DBusObject.__init__(self, '/org/freedesktop/DBus')
        self.uuid = binascii.hexlify(os.urandom(16))
        self.clients = dict()  # maps unique_bus_id to client connection
        self.busNames = dict()  # maps name to list of queued connections
        self.router = router.MessageRouter()
        self.next_id = 1
        self.obj_handler = objects.DBusObjectHandler(self)

        self.obj_handler.exportObject(self)

    # returns the new unique bus name for the client connection
    def clientConnected(self, proto):
        """
        Called when a client connects to the bus. This method assigns the
        new connection a unique bus name.
        """
        proto.uniqueName = ':1.%d' % (self.next_id, )
        self.next_id += 1
        self.clients[proto.uniqueName] = proto

    def clientDisconnected(self, proto):
        """
        Called when a client disconnects from the bus
        """
        for rule_id in proto.matchRules:
            self.router.delMatch(rule_id)

        for busName in proto.busNames.iterkeys():
            self.dbus_ReleaseName(busName, proto.uniqueName)

        if proto.uniqueName:
            del self.clients[proto.uniqueName]

    def sendMessage(self, msg):
        """
        Sends the supplied message to the correct destination. The 
        @type msg: L{message.DBusMessage}
        @param msg: The 'destination' field of the message must be set for
                    method calls and returns
        """
        if msg._messageType in (1, 2):
            assert msg.destination, 'Failed to specify a message destination'

        if msg.destination is not None:
            if msg.destination[0] == ':':
                p = self.clients.get(msg.destination, None)
            else:
                p = self.busNames.get(msg.destination, None)
                if p:
                    p = p[0]

            #print 'SND: ', msg._messageType, ' to ',  p.uniqueName, 'serial', msg.serial,

            if p:
                p.sendMessage(msg)
            else:
                log.msg('Invalid bus name in msg.destination: ' +
                        msg.destination)
        else:
            self.router.routeMessage(msg)

    def messageReceived(self, p, msg):
        mt = msg._messageType

        #print 'MSG: ', mt, ' from ', p.uniqueName, ' to ', msg.destination

        try:
            if mt == 1:
                self.methodCallReceived(p, msg)
            elif mt == 2:
                self.methodReturnReceived(p, msg)
            elif mt == 3:
                self.errorReceived(p, msg)
            elif mt == 4:
                self.signalReceived(p, msg)

            if msg.destination and not msg.destination == 'org.freedesktop.DBus':
                self.sendMessage(msg)

            self.router.routeMessage(msg)
        except DError, e:
            sig = None
            body = None
            if e.errorMessage:
                sig = 's'
                body = [e.errorMessage]

            r = message.ErrorMessage(e.errorName,
                                     msg.serial,
                                     signature=sig,
                                     body=body)
            p.sendMessage(r)
示例#10
0
文件: bus.py 项目: pliu6/txdbus
class Bus(objects.DBusObject):
    """
    DBus Bus implementation.

    @ivar stdIface: L{interface.DBusInterface} containing the standard bus interface
    @type stdIface: L{interface.DBusInterface}
    """
    stdIface = DBusInterface(
        'org.freedesktop.DBus',
        Method('Hello', arguments='', returns='s'),
        Method('GetId', arguments='', returns='s'),
        Method('RequestName', arguments='su', returns='u'),
        Method('ReleaseName', arguments='s', returns='u'),
        Method('ListQueuedOwners', arguments='s', returns='as'),
        Method('AddMatch', arguments='s', returns=''),
        Method('RemoveMatch', arguments='s', returns=''),
        Method('GetNameOwner', arguments='s', returns='s'),
        Method('GetConnectionUnixUser', arguments='s', returns='u'),

        #Not Implemented Methods
        Method('GetConnectionUnixProcessId', arguments='s', returns='u'),
        Method('ListActivatableNames', arguments='', returns='as'),
        Method('UpdateActivationEnvironment', arguments='a{ss}', returns=''),
        Method('StartServiceByName', arguments='su', returns='u'),
        Method('GetAdtAuditSessionData', arguments='s', returns='u'),
        Method('GetConnectionSELinuxSecurityContext',
               arguments='su',
               returns='ay'),
        Method('ReloadConfig'),
        Signal('NameAcquired', arguments='s'),
        Signal('NameLost', arguments='s'),
        Signal('NameOwnerChanged', arguments='sss'))

    dbusInterfaces = [stdIface]

    def __init__(self):
        objects.DBusObject.__init__(self, '/org/freedesktop/DBus')
        self.uuid = binascii.hexlify(os.urandom(16))
        self.clients = dict()  # maps unique_bus_id to client connection
        self.busNames = dict()  # maps name to list of queued connections
        self.router = router.MessageRouter()
        self.next_id = 1
        self.obj_handler = objects.DBusObjectHandler(self)

        self.obj_handler.exportObject(self)

    # returns the new unique bus name for the client connection
    def clientConnected(self, proto):
        """
        Called when a client connects to the bus. This method assigns the
        new connection a unique bus name.
        """
        proto.uniqueName = ':1.%d' % (self.next_id, )
        self.next_id += 1
        self.clients[proto.uniqueName] = proto

    def clientDisconnected(self, proto):
        """
        Called when a client disconnects from the bus
        """
        for rule_id in proto.matchRules:
            self.router.delMatch(rule_id)

        for busName in proto.busNames.iterkeys():
            self.dbus_ReleaseName(busName, proto.uniqueName)

        if proto.uniqueName:
            del self.clients[proto.uniqueName]

    def sendMessage(self, msg):
        """
        Sends the supplied message to the correct destination. The 
        @type msg: L{message.DBusMessage}
        @param msg: The 'destination' field of the message must be set for
                    method calls and returns
        """
        if msg._messageType in (1, 2):
            assert msg.destination, 'Failed to specify a message destination'

        if msg.destination is not None:
            if msg.destination[0] == ':':
                p = self.clients.get(msg.destination, None)
            else:
                p = self.busNames.get(msg.destination, None)
                if p:
                    p = p[0]

            #print 'SND: ', msg._messageType, ' to ',  p.uniqueName, 'serial', msg.serial,

            if p:
                p.sendMessage(msg)
            else:
                log.msg('Invalid bus name in msg.destination: ' +
                        msg.destination)
        else:
            self.router.routeMessage(msg)

    def messageReceived(self, p, msg):
        mt = msg._messageType

        #print 'MSG: ', mt, ' from ', p.uniqueName, ' to ', msg.destination

        try:
            if mt == 1:
                self.methodCallReceived(p, msg)
            elif mt == 2:
                self.methodReturnReceived(p, msg)
            elif mt == 3:
                self.errorReceived(p, msg)
            elif mt == 4:
                self.signalReceived(p, msg)

            if msg.destination and not msg.destination == 'org.freedesktop.DBus':
                self.sendMessage(msg)

            self.router.routeMessage(msg)
        except DError as e:
            sig = None
            body = None
            if e.errorMessage:
                sig = 's'
                body = [e.errorMessage]

            r = message.ErrorMessage(e.errorName,
                                     msg.serial,
                                     signature=sig,
                                     body=body)
            p.sendMessage(r)

    def methodCallReceived(self, p, msg):
        if msg.destination == 'org.freedesktop.DBus':
            self.obj_handler.handleMethodCallMessage(msg)

    def methodReturnReceived(self, p, msg):
        pass

    def errorReceived(self, p, msg):
        pass

    def signalReceived(self, p, msg):
        pass

    def sendSignal(self,
                   p,
                   member,
                   signature=None,
                   body=None,
                   path='/org/freedesktop/DBus',
                   interface='org.freedesktop.DBus'):
        """
        Sends a signal to a specific connection
        
        @type p: L{BusProtocol}
        @param p: L{BusProtocol} instance to send a signal to

        @type member: C{string}
        @param member: Name of the signal to send

        @type path: C{string}
        @param path: Path of the object emitting the signal. Defaults to
                     'org/freedesktop/DBus'
        
        @type interface: C{string}
        @param interface: If specified, this specifies the interface containing the
                          desired method. Defaults to 'org.freedesktop.DBus'

        @type body: None or C{list}
        @param body: If supplied, this is a list of signal arguments. The contents
                     of the list must match the signature.

        @type signature: None or C{string}
        @param signature: If specified, this specifies the DBus signature of the
                          body of the DBus Signal message. This string must
                          be a valid Signature string as defined by the DBus
                          specification. If the body argumnent is supplied ,\
                          this parameter must be provided.
        """
        if not isinstance(body, (list, tuple)):
            body = [body]

        s = message.SignalMessage(path, member, interface, p.uniqueName,
                                  signature, body)
        p.sendMessage(s)

    def broadcastSignal(self,
                        member,
                        signature=None,
                        body=None,
                        path='/org/freedesktop/DBus',
                        interface='org.freedesktop.DBus'):
        """
        Sends a signal to all connections with registered interest
        
        @type member: C{string}
        @param member: Name of the signal to send

        @type path: C{string}
        @param path: Path of the object emitting the signal. Defaults to
                     'org/freedesktop/DBus'
        
        @type interface: C{string}
        @param interface: If specified, this specifies the interface containing the
                          desired method. Defaults to 'org.freedesktop.DBus'

        @type body: None or C{list}
        @param body: If supplied, this is a list of signal arguments. The contents
                     of the list must match the signature.

        @type signature: None or C{string}
        @param signature: If specified, this specifies the DBus signature of the
                          body of the DBus Signal message. This string must
                          be a valid Signature string as defined by the DBus
                          specification. If the body argumnent is supplied ,\
                          this parameter must be provided.
        """
        if not isinstance(body, (list, tuple)):
            body = [body]

        s = message.SignalMessage(path, member, interface, None, signature,
                                  body)
        self.router.routeMessage(s)

    #----------------------------------------------------------------
    # DBus Object Interface
    #
    def dbus_Hello(self, dbusCaller=None):
        raise DError('org.freedesktop.DBus.Error.Failed',
                     'Already handled an Hello message')

    def dbus_GetId(self):
        return self.uuid

    def dbus_RequestName(self, name, flags, dbusCaller=None):
        caller = self.clients[dbusCaller]

        allow_replacement = bool(flags & 0x1)
        replace_existing = bool(flags & 0x2)
        do_not_queue = bool(flags & 0x4)

        if not name:
            raise DError('org.freedesktop.DBus.Error.InvalidArgs',
                         'Empty string is not a valid bus name')

        if name[0] == ':':
            raise DError(
                'org.freedesktop.DBus.Error.InvalidArgs',
                'Cannot acquire a service starting with \':\' such as "%s"' %
                (name, ))

        try:
            marshal.validateBusName(name)
        except error.MarshallingError as e:
            raise DError('org.freedesktop.DBus.Error.InvalidArgs', str(e))

        def signalAcq(old_owner_name):
            self.sendSignal(caller, 'NameAcquired', 's', name)
            self.broadcastSignal('NameOwnerChanged', 'sss',
                                 [name, old_owner_name, caller.uniqueName])

        if not name in self.busNames:
            self.busNames[name] = [
                caller,
            ]
            caller.busNames[name] = allow_replacement

            signalAcq('')

            return client.NAME_ACQUIRED
        else:
            queue = self.busNames[name]
            owner = queue[0]

            if owner is caller:
                # Update the replacement flag
                owner.busNames[name] = allow_replacement

                return client.NAME_ALREADY_OWNER
            else:
                if not replace_existing:
                    return client.NAME_IN_USE

                if owner.busNames[name]:
                    del queue[0]
                    queue.insert(0, caller)
                    del owner.busNames[name]
                    caller.busNames[name] = allow_replacement
                    self.sendSignal(owner, 'NameLost', 's', name)
                    signalAcq(owner.uniqueName)
                    return client.NAME_ACQUIRED
                else:
                    if do_not_queue:
                        return client.NAME_IN_USE

                    queue.append(caller)
                    caller.busNames[name] = allow_replacement

                    return client.NAME_IN_QUEUE

    def dbus_ReleaseName(self, name, dbusCaller=None):
        caller = self.clients[dbusCaller]

        queue = self.busNames.get(name, None)

        if queue is None:
            return client.NAME_NON_EXISTENT

        owner = queue[0]

        if not caller is owner:
            return client.NAME_NOT_OWNER

        del queue[0]

        if caller.isConnected:
            self.sendSignal(caller, 'NameLost', 's', name)

        if queue:
            self.sendSignal(queue[0], 'NameAcquired', 's', name)
        else:
            del self.busNames[name]

        return client.NAME_RELEASED

    def dbus_ListQueuedOwners(self, name):
        queue = self.busNames.get(name, None)
        if queue:
            return [p.uniqueName for p in queue]
        else:
            raise DError(
                'org.freedesktop.DBus.Error.NameHasNoOwner',
                'Could not get owners of name \'%s\': no such name' % (name, ))

    def dbus_AddMatch(self, rule, dbusCaller=None):
        caller = self.clients[dbusCaller]

        kwargs = dict(mtype=None,
                      sender=None,
                      interface=None,
                      member=None,
                      path=None,
                      path_namespace=None,
                      destination=None,
                      args=None,
                      arg_paths=None,
                      arg0namespace=None)

        for item in rule.split(','):
            k, v = item.split('=')

            value = v[1:-1]

            if k == 'type':
                k = 'mtype'

            if k in kwargs:
                kwargs[k] = value

            elif k.startswith('arg'):
                if k.endswith('path'):
                    if kwargs['arg_paths'] is None:
                        kwargs['arg_paths'] = list()
                    kwargs['arg_paths'].append((int(k[3:-4]), value))
                else:
                    if kwargs['args'] is None:
                        kwargs['args'] = list()
                    kwargs['args'].append((int(k[3:]), value))

        self.router.addMatch(caller.sendMessage, **kwargs)

    def dbus_GetNameOwner(self, busName):
        if busName.startswith(':'):
            conn = self.clients.get(busName, None)
        else:
            conn = self.busNames.get(busName, None)
            if conn:
                conn = conn[0]

        if conn is None:
            raise DError(
                "org.freedesktop.DBus.Error.NameHasNoOwner",
                "Could not get UID of name '%s': no such name" % (busName, ))

        return conn.uniqueName

    def dbus_GetConnectionUnixUser(self, busName):
        if busName.startswith(':'):
            conn = self.clients.get(busName, None)
        else:
            conn = self.busNames.get(busName, None)
            if conn:
                conn = conn[0]

        if conn is None:
            raise DError(
                "org.freedesktop.DBus.Error.NameHasNoOwner",
                "Could not get UID of name '%s': no such name" % (busName, ))

        try:
            import pwd
            return pwd.getpwnam(conn.username).pw_uid
        except:
            raise DError(
                'org.freedesktop.DBus.Error',
                "Unable to determine unix user for bus '%s'" % (busName, ))
示例#11
0
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

# global list of tag devices that are currently within radio range
#
taglist = dict()

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

TAGNET_BUS_NAME = 'org.tagnet.tagmaster'  # bus name for tagnet forwarder
TAGNET_OBJECT_PATH = '/org/tagnet/tagmaster'

tagmaster_dbus_interface = DBusInterface(
    TAGNET_BUS_NAME,
    Method('tag_list', arguments='s', returns='ay'),
    Signal('tag_found', 'ay'),  # report new tag
    Signal('tag_lost', 'ay'),  # report tag out of range
    Signal('tag_events', 'ay'),  # report new tag events
    Signal('tagnet_status', 'ay'),
)


class TagNetDbus(objects.DBusObject):
    """
    provides the interface for accessing the tagnet port
    """
    dbusInterfaces = [tagmaster_dbus_interface]

    def __init__(self, object_path):
        super(TagNetDbus, self).__init__(object_path)
        self.object_path = object_path