~tdelaet/cimple/old-codebase

« back to all changes in this revision

Viewing changes to src/cimple/core/discovery/discovery.py

  • Committer: Thomas Delaet
  • Date: 2010-01-07 14:14:32 UTC
  • Revision ID: thomas@cole-20100107141432-yhker27v3pmn62uo
first phase of rewrite with focus on storage

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""
2
 
Tracker discovery
3
 
"""
4
 
import dbus
5
 
import dbus.mainloop.glib
6
 
import avahi
7
 
import notify.all
8
 
import twisted.internet.reactor
9
 
import cimple.core.config
10
 
 
11
 
class ServiceResolver:
12
 
        """
13
 
        Service Resolver
14
 
        """
15
 
        
16
 
        def __init__(self, *args):
17
 
                self.interface = args[0]
18
 
                self.protocol = args[1]
19
 
                self.name = args[2]
20
 
                self.type = args[3]
21
 
                self.domain = args[4]
22
 
                self.host = args[5]
23
 
                self.aprotocol = args[6]
24
 
                self.address = args[7]
25
 
                self.port = args[8]
26
 
                self.txt = args[9]
27
 
                self.flags = args[10]
28
 
                
29
 
        def __eq__(self, other):
30
 
                return self.name == other.name
31
 
        
32
 
        def __ne__(self, other):
33
 
                return not self == other
34
 
        
35
 
        def __hash__(self):
36
 
                return hash(self.name)
37
 
 
38
 
class Discovery:
39
 
        """
40
 
        Generic Service Discovery object
41
 
        """
42
 
        
43
 
        def __init__(self, service_type):
44
 
                dbus.set_default_main_loop(dbus.mainloop.glib.DBusGMainLoop())
45
 
                self.service_added = notify.all.Signal()
46
 
                self.service_removed = notify.all.Signal()
47
 
                bus = dbus.SystemBus()
48
 
                self.server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, '/'), 'org.freedesktop.Avahi.Server')
49
 
                service_browser = self.server.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, service_type, 'local', dbus.UInt32(0))
50
 
                browser_object = bus.get_object(avahi.DBUS_NAME, service_browser)               
51
 
                self.browser = dbus.Interface(browser_object, avahi.DBUS_INTERFACE_SERVICE_BROWSER)
52
 
                self.browser.connect_to_signal("ItemNew", self.__item_new_handler)
53
 
                self.browser.connect_to_signal("ItemRemove", self.__item_remove_handler)
54
 
 
55
 
        def __item_new_handler(self, interface, protocol, name, stype, domain, flags):
56
 
                #pylint: disable-msg=C0111,C0301,W0613
57
 
                #print "Found service '%s' type '%s' domain '%s' " % (name, stype, domain)
58
 
                self.server.ResolveService(interface, protocol, name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.__service_resolved, error_handler=self.__print_error)       
59
 
 
60
 
        def __item_remove_handler(self, interface, protocol, name, stype, domain, flags):
61
 
                #pylint: disable-msg=C0111,C0301,W0613
62
 
                #print "Removed service '%s' type '%s' domain '%s' " % (name, stype, domain)
63
 
                self.__service_removed(interface, protocol, name, stype, domain, flags)
64
 
 
65
 
        def __print_error(self, *args):
66
 
                #pylint: disable-msg=C0111,W0613,R0201
67
 
                print "error handler"
68
 
                print args
69
 
 
70
 
        def __service_resolved(self, *args):
71
 
                """
72
 
                Callback when we have resolved a new service
73
 
                """
74
 
                self.service_added(ServiceResolver(*args))
75
 
                
76
 
        def __service_removed(self, interface, protocol, name, stype, domain, flags):
77
 
                """
78
 
                Callback when service is removed
79
 
                """
80
 
                self.service_removed(ServiceResolver(interface, protocol, name, stype, domain, None, None, None, None, None, flags))
81
 
 
82
 
class Manager:
83
 
        
84
 
        def __init__(self, discovery):
85
 
                self.discovery = discovery
86
 
                self.services = {}
87
 
                self.discovery.service_added.connect(self.__service_added)
88
 
                self.discovery.service_removed.connect(self.__service_removed)
89
 
        
90
 
        def __service_added(self, service_resolver):
91
 
                self.services[str(service_resolver.name)] = service_resolver
92
 
        
93
 
        def __service_removed(self, service_resolver):
94
 
                if self.services.has_key(str(service_resolver.name)):
95
 
                        del self.services[str(service_resolver.name)]
96
 
                                        
97
 
class Advertiser:
98
 
        
99
 
        def __init__(self, port):
100
 
                dbus.set_default_main_loop(dbus.mainloop.glib.DBusGMainLoop())
101
 
                self.bus = dbus.SystemBus()
102
 
                self.server = None
103
 
                self.group = None
104
 
                self.rename_count = 0
105
 
                self.port = port
106
 
                #pylint: disable-msg=E1101
107
 
                twisted.internet.reactor.callWhenRunning(self.__advertise_ourselves)
108
 
 
109
 
        def __advertise_ourselves(self):
110
 
                self.server = dbus.Interface(self.bus.get_object( avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER ), avahi.DBUS_INTERFACE_SERVER )
111
 
                self.server.connect_to_signal("StateChanged", self.__server_state_changed)
112
 
                self.__server_state_changed(self.server.GetState())
113
 
 
114
 
        def __server_state_changed(self, state):
115
 
                if state == avahi.SERVER_COLLISION:
116
 
                        print "WARNING: Server name collision"
117
 
                        self.__remove_service()
118
 
                elif state == avahi.SERVER_RUNNING:
119
 
                        self.__add_service()
120
 
        
121
 
        def __entry_group_state_changed(self, state, error):
122
 
                if state == avahi.ENTRY_GROUP_COLLISION:
123
 
                        self.rename_count = self.rename_count + 1
124
 
                        if self.rename_count < 4:
125
 
                                self.__remove_service()
126
 
                                self.__add_service()
127
 
                        else:
128
 
                                print "Service name collision"
129
 
                                print error
130
 
                                #pylint: disable-msg=E1101
131
 
                                twisted.internet.reactor.stop()
132
 
                elif state == avahi.ENTRY_GROUP_FAILURE:
133
 
                        print "Error in group state changed"
134
 
                        print error
135
 
                        #pylint: disable-msg=E1101
136
 
                        twisted.internet.reactor.stop()
137
 
 
138
 
        def __remove_service(self):
139
 
                if not self.group == None:
140
 
                        self.group.Reset()              
141
 
 
142
 
        def _service_type(self):
143
 
                raise NotImplementedError
144
 
        
145
 
        def _txt_dictionary(self):
146
 
                raise NotImplementedError
147
 
 
148
 
        def _name(self):
149
 
                raise NotImplementedError
150
 
 
151
 
        def __add_service(self):
152
 
                txt_records = self._txt_dictionary()
153
 
                txt = avahi.dict_to_txt_array(txt_records)
154
 
                if self.group == None:
155
 
                        object_path = self.bus.get_object(avahi.DBUS_NAME, self.server.EntryGroupNew())
156
 
                        self.group = dbus.Interface(object_path, avahi.DBUS_INTERFACE_ENTRY_GROUP)
157
 
                        self.group.connect_to_signal('StateChanged', self.__entry_group_state_changed)
158
 
                self.group.AddService(avahi.IF_UNSPEC, avahi.PROTO_INET, dbus.UInt32(0), self._name(), self._service_type(), "", "", dbus.UInt16(self.port), txt)               
159
 
                self.group.Commit()
160
 
 
161
 
class CimpleAdvertiser(Advertiser):
162
 
        KEY_SEGMENT_SIZE = 200
163
 
        
164
 
        SSH_KEY_LOCATION = None
165
 
        
166
 
        TYPE = None
167
 
        
168
 
        NAME = None
169
 
        
170
 
        def __init__(self, port):
171
 
                Advertiser.__init__(self, port)
172
 
                self.name = cimple.core.config.ssh_key_id(self.SSH_KEY_LOCATION)
173
 
        
174
 
        def _ssh_key(self):
175
 
                result = {}
176
 
                (key_type, key) = cimple.core.config.ssh_key(self.SSH_KEY_LOCATION)
177
 
                result['ssh-key-type'] = key_type
178
 
                remaining_length = len(key)
179
 
                seq = 0
180
 
                while remaining_length > 0:
181
 
                        data = key[0:self.KEY_SEGMENT_SIZE]
182
 
                        result['ssh-key-part-' + str(seq)] = data
183
 
                        key = key[self.KEY_SEGMENT_SIZE:]
184
 
                        remaining_length = remaining_length - self.KEY_SEGMENT_SIZE
185
 
                        seq = seq + 1
186
 
                return result
187
 
        
188
 
        def _name(self):
189
 
                return self.name
 
 
b'\\ No newline at end of file'