コード例 #1
0
ファイル: chat.py プロジェクト: Ninja-1/Circle2
    def __init__(self,app):

        self.lock = threading.RLock()
        self.node = app.node
        self.app  = app 

        # Visible status
        self.quiet       = 0
        self.activity    = ''
        self.n_unseen_messages = 0

        # Results of /find and /search
        self.identity_list = [ ]
        self.file_list=[ ]

        # Python environment
        self.exec_vars = { 'app' : app, 'node' : app.node, 'daemon':app.daemon }

        # Detect repeated offline messages
        self.offline_message_buffer = [ ]

        # Store a copy of recent messages
        self.incoming_message_history = [ ]

        # used for /ls
        self.current_path_nickname = ''
        self.current_path = [ ]

        # While quiet, messages are buffered for later display.
        # Tuples of form (request, opt-address, time.time()).
        # address for offline-sent messages is None.
        # The time item must be wrt this client's epoch.
        self.unread_message_list = [ ]
        
        config = utility.get_checked_config("chat", types.DictionaryType, { })
        for name,tmpl in [('quiet', 'any'),
                          ('activity', 'any'),
                          ('offline_message_buffer', 'any'),
                          ('incoming_message_history', [('any', 'any timestamp')]),
                          ('unread_message_list', [((types.StringType,),
                                                    'opt-address',
                                                    'any timestamp')])]:
            if config.has_key(name):
                config_val = config[name]
                if check.matches(config_val, tmpl):
                    setattr(self, name, config_val)
                else:
                    print (_("Warning: ignoring chat config item %s, which doesn't match %s.")
                           % (name, tmpl))
        # The current version of Circle always writes these timestamps in
        # standardized form, but previous versions wrote a mixture of floats
        # and longs.
        for i in xrange(len(self.incoming_message_history)):
            request,tstamp = self.incoming_message_history[i]
            if type(tstamp) == types.LongType:
                self.incoming_message_history[i] = (request,
                                                    standard2host_timestamp(tstamp))
            check.check_matches(self.incoming_message_history[i],
                                incoming_message_history_item_tmpl)
            # Loose proof: definition of check.is_any_timestamp, @E17.
            # Relevance: @R.I16.
        for i in xrange(len(self.unread_message_list)):
            request,addr,tstamp = self.unread_message_list[i]
            if type(tstamp) == types.LongType:
                self.unread_message_list[i] = (request, addr,
                                               standard2host_timestamp(tstamp))
            check.check_matches(self.unread_message_list[i],
                                unread_message_list_item_tmpl)
            # Loose proof: as above.
            # Relevance: @R.I15.
        
        self.recall_list = [ ]

        # Detect repeated messages
        self.message_buffer = [ ]

        self.channel = [ ]
        self.channels = channels.Channels(self.app)
        self.chat_check_invar()
コード例 #2
0
ファイル: name_server.py プロジェクト: Ninja-1/Circle2
    def start(self, status_monitor=None):
        utility.Task_manager.start(self)

        acq_list = utility.get_checked_config('acquaintances', types.ListType, [ ])
        for item in acq_list:
            if not check.matches(item, Acquaintance.map_tmpl):
                print _("Warning: corrupted acquaintances config file; ignoring item: "), item
                continue

            acq = Acquaintance(self, item, 1)
            self.acquaintances[acq.name] = acq
            self.nicknames[acq.nickname] = acq
            acq.start()


        def make_acquaintance_noaddr(self, info):

            name = key_name(info['key'])

            acq = Acquaintance(self, {'info': info,
                                          'name': name,
                                          'nickname': self.choose_nickname(info['name'])},0)
            self.acquaintances[name]     = acq
            self.nicknames[acq.nickname] = acq

            acq.start()
            acq.start_watching(self.node)
            self.acquaintance_status_changed(acq, "create")

            return acq

        self.me = make_acquaintance_noaddr(self,self.info)

        # Other me may want to test identity
        # May start chatting before test complete
        self.node.add_handler('identity test', self, ('name',), crypto.pubkey.signature_tmpl)
        self.node.add_handler('identity query', self, (), Acquaintance.info_template)
        self.node.add_handler('identity watch', self, (), types.DictionaryType)
        self.node.add_handler('identity connecting', self)
        self.node.add_handler('identity status changed', self, ('any', Acquaintance.status_template))
        self.node.add_handler('identity disconnecting', self,('string', 'opt-text'))
        self.node.add_handler('identity abort', self)

        self.node.publish(self.public_key_name,self.get_info_func, settings.identity_redundancy)
        self.node.publish(self.public_key_name_offline,self.get_info_func, settings.identity_redundancy)
        self.node.publish(self.service_name,self.get_info_func, settings.identity_redundancy)
        for item in self.info['keywords']:
            self.node.publish(hash.hash_of('identity-name '+item),
                              self.get_info_func, settings.identity_redundancy)

        def startup_thread(self, status_monitor=status_monitor):
            
            list = self.acquaintances.values()
            list.sort(lambda x,y: cmp(x.sort_value(),y.sort_value()))
            for item in list:
                item.start_watching(self.node)

                #start watching tends to breed, try to make sure we don't get
                #too many threads.
                #yes, this is hacky
                #print item.nickname, threading.activeCount()
                #time.sleep(0.25)

                while 1:
                    yield 'sleep',0.25
                    if threading.activeCount() < 40:
                        break
                 
            self.me.start_watching(self.node)
            while not self.me.watched:
                yield 'sleep',0.1
            
            online = self.me.online
            address = self.me.address
            if online:
                if status_monitor:
                    status_monitor(_('Shutting down your other peer.'))
                while 1:
                    ticket,template,wait = self.node.call(address, ('identity abort',))
                    if wait: yield 'call',(self.node,ticket)
                    try:
                        dummy_result = self.node.get_reply(ticket, template)
                    except error.Error:
                        break
                    yield 'sleep',4
            
            self.me.online  = 1
            self.me.address = self.node.address
            self.me.connect_time = time.time()
            # Task to retrieve existing watchers
            # Task to poll existing watchers
            utility.start_thread(name_server_watch_poller_thread(self))
            # now refresh my own offline presence
            pipe = self.node.retrieve(self.public_key_name_offline, settings.cache_redundancy)
            list = [ ]

            while not pipe.finished():
                for item in pipe.read_all():
                    if type(item[1]) == types.DictType and \
                           item[1].get('type') == 'identity offline' and \
                           item[1].get('salt'):
                        list.append(item)
                yield 'sleep',2
                if not self.running:
                    return
            pipe.stop()

            #if len(list) != 4:
            #    print _("%d peers holding your offline presence.") % len(list)

            for item in list:
                address, value = item
                key = hash.hash_of(safe_pickle.dumps(self.sign(value['salt'])))
                ticket, template, wait = self.node.call(address, ('data cache remove',key))
                if wait: yield 'call',(self.node,ticket)
                try:
                    dummy_result = self.node.get_reply(ticket,template)
                except error.Error:
                    pass

            self.lock.acquire()
            try:
                package = {
                    'name'       : self.info['name'],
                    'human-name' : self.info['human-name'],
                    'description': self.info['description'],
                    'timezone'   : self.info['timezone'],
                    'key'        : self.public_key,
                    'keywords'   : self.info['keywords'],
                }
            finally:
                self.lock.release()

            package_dumped = safe_pickle.dumps(package)
            signature = self.sign(package_dumped)


            # now publish and cache offline identity
            value = {
                'type' : 'identity offline',
                'package' : package_dumped,
                'signature' : signature,
                'salt' : utility.random_bytes(settings.name_bytes)
            }
            lock = hash.hash_of(hash.hash_of(safe_pickle.dumps(self.sign(value['salt']))))
            publications = [ self.public_key_name_offline, self.service_name ]
            for item in package['keywords']:
                publications.append(hash.hash_of('identity-name '+item))
            # thomasV
            # redundancy 4: this is the meta-publish
            result, publish_thread = self.app.cache.publish(publications,value,lock, 4)
            yield 'wait',publish_thread
            
        utility.start_thread(startup_thread(self))