Esempio n. 1
0
def request_meeting(chat, params):
    """
    Request a meeting with the user "nickname".
    This function is attached to the chat command "/meet"
    
    Send a request to the receiver. If he/she accept, then a local meeting call will be emited.
    
    node.call receiver query="start meeting"
    if return yes: start a call to the receiver
    else: show the error message (rejected, or technical failure)
    """

    check.check_matches(params, ['text'])
    check.check_assertion(1 <= len(params) <= 1)
    nickname = params[0]

    if not app.name_server.nicknames.has_key(nickname):
        app.chat.show("Unknown user '%s' at the local names server.\n"% nickname)	
        return
        
    server_acq = app.name_server.nicknames[nickname] # we are the "client", the receiver is the "server".
    
    if server_acq.address == node.address:
	app.chat.show("You can not meet yourself, sorry.\n")	
	return
    
    if not server_acq.online:
        app.chat.show("The user '%s' is not online.\n"% nickname)	
        return
    

    Task(request_meeting_task, server_acq).start()
    
    return
Esempio n. 2
0
    def __init__(self, name_server, map, remember):
        check.check_isinstance(name_server, Name_server)
        check.check_matches(map, self.map_tmpl)
        check.check_has_type(remember, types.IntType)
        check.check_assertion(remember in (0, 1))
        
        utility.Task_manager.__init__(self)
        self.editor_open = 0
        
        self.watch     = 0  # used to tell if the person logs in or out in chat window
                            # nothing to do with 'watchers'
        
        self.distance  = None
        self.drm       = 0

        self.address   = None
        self.watching  = 0
        self.watched   = 0
        self.online    = 0
        self.status    = { }

        # .name and .nickname will be filled in from map.  We initialize
        # them here just to placate pychecker.
        # Note: Don't confuse self.name (check.is_name) with self.info['name']
        # (person's preferred nickname).
        self.name = '(error)'
        self.nickname = '(error)'
        
        self.name_server = name_server
        
        for key,value in map.items():
            setattr(self, key, value)

        self.remember = remember        
        self.check_invar()
Esempio n. 3
0
    def send_message(self, dests, message, attachment=None, augmentation=None):
        check.check_matches(dests, ['text'])
        check.check_is_text(message)

        if self.quiet:
            self.show_status()

        utility.start_thread(chat_tell_thread(
            self,dests,message,attachment,augmentation))
Esempio n. 4
0
    def remove_channel(self, dest):
        check.check_matches(dest, 'text')  #=@R51
        # Relevance: @R.I31.

        self.lock.acquire()
        try:
            if dest not in self.channel:
                return
            self.channel.remove(dest)
            self.app.refresh_userlist()
            self.set_prompt()
        finally:
            self.lock.release()
Esempio n. 5
0
    def set_channel(self, dests):
        check.check_matches(dests, ['text'])  #=@R49
        # Relevance: @R.I31.

        self.lock.acquire()
        try:
            self.channel = dests
            for dest in self.channel:
                if dest[0]=='#':
                    self.channel_sub(dest)
                    self.channel_mute(dest,0)
            self.app.refresh_userlist()
            self.set_prompt()
        finally:
            self.lock.release()
Esempio n. 6
0
def get_checked_config(name, tmpl, default):
    """Ensures @E13: (ret is default) or check.matches(ret, tmpl)."""
    check.check_has_type(name, types.StringType)
    check.check_is_template(tmpl)
    
    try:
        ret = try_get_config(name)
    except:
        return default
    if not check.matches(ret, tmpl):
        print (_("Garbled config file `%s'; expecting something matching template `%s'.")
               % (name, str(tmpl)))
        ret = default
    
    if ret is not default: check.check_matches(ret, tmpl)
    return ret
Esempio n. 7
0
    def handle(self, request, address,call_id):
        check.check_matches(request, (types.StringType,))  #=@R34
        check.check_is_af_inet_address(address)  #=@R31
        
        self.lock.acquire()
        try:
            if request[0] == 'chat look':
                return (not self.quiet, self.activity)
            if request[0] in ['chat message 2']:
                unpacked = safe_pickle.loads(request[1])
                # TODO check unpacked against template
                # TODO don't unpack twice (here and in receive task)
                sender = unpacked['from']
                recipients = unpacked['to']
                    
                for recipient in recipients:
                    if recipient[0] == self.app.name_server.public_key_name:
                        break
                    if recipient[2][:1] == '#' and \
                         self.channels.is_listening_to(recipient[2]) and \
                         sender[0] != self.app.name_server.public_key_name:
                        break
                else:
                    return None
            
                if not self.repeated(address,call_id):
                    if self.quiet:
                        new_item = (request, address, time.time())
                        check.check_matches(new_item,
                                            unread_message_list_item_tmpl)
                        # Proof: @R34,@R31, and not having modified request or
                        # address, and the relevant types being immutable
                        # (partly by @E11).  time.time() returns float.
                        # Relevance: @R.I15.
                        self.unread_message_list.append(new_item)
                        self.set_prompt()
                        del new_item
                    else:
                        self.receive(request,address,self.quiet,time.time())
                        # Proof of @R33: @R31; deep immutability by @E11.
                        # Proof of @R35: time.time() returns float.

                return (not self.quiet, self.activity)

        finally:
            self.lock.release()
Esempio n. 8
0
    def handle(self, request,address,call_id):
        check.check_matches(request, (types.StringType,))
        check.check_is_af_inet_address(address)
        
        # Idempotence is a bugger

        if request[0] == 'data cache store' or \
             request[0] == 'data cache store multi':
            self.lock.acquire()
            try:
                if self.cached_items.has_key(request[1]):
                    if self.cached_items[request[1]].call == (address,call_id):
                        return None
                    return Error('already storing')

                if request[0] == 'data cache store':
                    names = [ request[2] ]
                else:
                    names = request[2]

                if len(names) > settings.max_cache_names:
                    return Error('too many names')
                
                item = Cache_item(names,request[3],request[4],(address,call_id))
 
                self.cached_items[request[1]] = item

                # here is the actual publish: redundancy is settings.cache_redundancy
                for name in names:
                    self.node.publish(name, request[3], settings.cache_redundancy)
            finally:
                self.lock.release()
            return None

        if request[0] == 'data cache remove':
            self.lock.acquire()
            try:
                lock = hash.hash_of(request[1])
                if self.cached_items.has_key(lock):
                    self.node.unpublish(self.cached_items[lock].data)
                    del self.cached_items[lock]
            finally:
                self.lock.release()

            return None
Esempio n. 9
0
def random_inst(tmpl):
    # todo: Return an error.Error instance in more cases.
    # todo: This is currently specific to request results, in that
    # the results are always dumpable and sometimes contain error.Error
    # instances.
    check.check_is_template(tmpl)

    if type(tmpl) == types.TupleType:
        ret = tuple(map(random_inst, tmpl) + random_dumpable_list())
        # `+ random_dumpable_list()' is because check_matches currently
        # allows so, and some requests do take a variable number of arguments.
    elif type(tmpl) == types.DictionaryType:
        ret = {}
        # Some extra items in case these keys are checked for.
        for i in range(random_nat(3)):
            ret[random.choice(extra_keys)] = random_dumpable()
        for (k,v) in tmpl.items():
            ret[k] = random_inst(v)
    elif type(tmpl) == types.ListType:
        assert(tmpl != [])
        if len(tmpl) == 1:
            ret = []
            for i in range(random_nat(2)):
                ret.append(random_inst(tmpl[0]))
        else:
            ret = random_inst(random.choice(tmpl))
    elif type(tmpl) == types.TypeType:
        f = type_randers.get(tmpl)
        if f is not None:
            ret = f()
        else:
            print "Unhandled type template " + `tmpl` + "\n"
            assert(0)
    elif type(tmpl) == types.StringType:
        f = randers.get(tmpl)
        if f is not None:
            ret = f()
        else:
            print "Unhandled template string " + `tmpl` + "\n"
            assert(0)
    else:
        print "Unrecognized template " + `tmpl` + "\n"
        assert(0)
    check.check_matches(ret, tmpl)
    return ret
Esempio n. 10
0
    def handle(self, request, ignored__address, call_id):
        check.check_matches(request, (types.StringType,))
        check.check_is_af_inet_address(ignored__address)
        
        if request[0] == 'gossip list':
            #TODO: Type checking, locking, oh, and this is really inefficient
            self.any_gossip_gets = 1

            list = [ ]
            for item in self.gossip[:]:
                list.append((to_fixed(item.distance(self.app.name_server)),
                             item.unit_decay_time,
                             item.signature))
            list.sort()
            return list[request[1]:request[2]]
        elif request[0] == 'gossip get':
            for item in self.gossip:
                if item.signature == request[1]:
                    return item.string
            return error.Error(_("No such wodge."))
Esempio n. 11
0
    def handle(self, request, address, call_id):
        check.check_matches(request, (types.StringType,))
        check.check_is_af_inet_address(address)

        if request[0] == 'auction bid':
            name = request[1]
            bid = request[2]
            if self.auctions.has_key(name):
                print "auction found"
                if self.auctions_prices[name] < bid:
                    self.auctions_prices[name] = bid
                    return 'ok'
                else:
                    print "bid too low"
                    return 'bid too low'
            else:
                return 'error: no such auction'
            
            
        elif request[0] == 'auction list':

            list = self.auctions
            return list
Esempio n. 12
0
def retrieve_cached_messages_thread(self,on_complete):

    pipe = self.node.retrieve(
        hash.hash_of('offline message '+self.app.name_server.public_key_name),
        settings.cache_redundancy)

    # Loose proof of @R50: @I22, @E22.
    pipe_reads = [ ]
    if not pipe.finished():
        while 1:
            pipe_reads.extend(pipe.read_all())
            if pipe.finished():
                break
            yield 'sleep',1
    pipe.stop()
    # pjm 2002-08-05: I've changed the above to sleep only if
    # one read_all call isn't enough.  However, I don't know why
    # sleep is wanted in the first place, or whether a different
    # duration might be better.  (Python sleep allows its
    # argument to be fractional, implemented in terms of
    # select.)

    unique_messages = [ ]
    for item in pipe_reads:
        # I think we're guaranteed that item matches ('af_inet_address', 'any').
        if not check.matches(item[1], {'type' : types.StringType,
                                       'crypt' : ('any', 'any')}):
            # print bad peer
            pass
        elif item[1] not in unique_messages:
            unique_messages.append(item[1])

    message_list = [ ]
    for raw_msg in unique_messages:
            if type(raw_msg) == type({}) \
               and raw_msg.get('type','') == 'offline message' \
               and raw_msg.has_key('crypt'):
                try:
                    decrypt = self.app.name_server.decrypt(raw_msg['crypt'])
                    if not check.matches(decrypt, ('text',
                                                   (types.StringType,),
                                                   types.LongType)):
                        raise error.Error('bad decrypted reply')

                    # Remove from caches
                    for thing in pipe_reads:
                        if thing[1] == raw_msg:
                            try:
                                ticket, template, wait = self.node.call(\
                                    thing[0],('data cache remove',decrypt[0]))
                                if wait: yield ('call',(self.node,ticket))
                                self.node.get_reply(ticket,template)

                            except error.Error:
                                pass

                    message_list.append((decrypt[2],decrypt[1]))
                except error.Error:
                    pass

    message_list.sort()
    self.lock.acquire()
    try:
        any = 0
        for msg in message_list:
            if msg not in self.offline_message_buffer:
                self.offline_message_buffer = [msg] + self.offline_message_buffer[:50]

                new_item = (msg[1], None,
                            standard2host_timestamp(msg[0]))
                # Proof of @R36: msg is taken from message_list.
                # message_list is local to this method, and is not
                # passed to any other method (so is not shared with any
                # other thread).  message_list starts as empty and is
                # written to solely as (decrypt[2],decrypt[1]) pairs,
                # and only where decrypt has already been found to
                # match ('any', ('string',), 'long').  The relevant
                # types are immutable.
                check.check_matches(new_item,
                                    unread_message_list_item_tmpl)
                # Proof: the @R36 proof just above also shows that
                # msg[1] (i.e. decrypt[1]) matches ('string',) and
                # is immutable.  new_item[1] matches because
                # is_opt_address(None).  new_item[2] matches from @E17.
                # Relevance: @R.I15
                self.unread_message_list.append(new_item)
                any = 1
            else:
                print _("Duplicate offline message.")
    finally:
        self.lock.release()

    on_complete(self,any)
Esempio n. 13
0
    def handle(self, request, address,call_id):
        check.check_matches(request, (types.StringType,))
        check.check_is_af_inet_address(address)  #=@R30
        
        if request[0] == 'identity test':
            check.check_matches(request[1:], ('name',))
            
            return self.sign('identity test ' + request[1])
        
        elif request[0] == 'identity query':
            return self.get_info()
        elif request[0] == 'identity watch':
            self.lock.acquire()
            try:
                if address not in self.watchers:
                    self.watchers.append(address)
                status = self.status
            finally:
                self.lock.release()
            return status
        elif request[0] == 'identity abort':
            def abort_thread(self, address=address):
                id_test_result = []
                yield 'wait', identity_test_thread(address,self.public_key,self.node,id_test_result)
                if not id_test_result[0]:
                    print "error testing identity"
                    return
                self.aborted = 1
                self.app.shutdown(_('Reconnecting from different machine'))
            utility.start_thread(abort_thread(self))
            return None
        elif request[0] == 'identity connecting':
            if not (len(request) >= 2):
                return error.Error('Name_server.handle: identity connecting: expecting tuple of at least 2.')
            self.acquire_lock('get acq')
            try:
                acq = self.acquaintances.get(request[1])
            finally:
                self.release_lock('get acq')
            if acq is None:
                return error.Error(_("I don't know you."))
            else:
                #if len(request) > 2:
                #  status = request[2]
                #else:
                #  status = { }

                def acq_change_thread(ns, acq, address, call_id, node):
                    check.check_is_af_inet_address(address)  #=@R29
                    
                    try:
                        result, subthread = try_address(acq,address,node)
                        yield 'wait',subthread
                        if not result[0]:
                            return
                    except error.Error:
                        return

                    #acq.lock.acquire()
                    #acq.status = status
                    #acq.lock.release()
                    ns.acquaintance_status_changed(acq, 'connect')
                utility.start_thread(acq_change_thread(self, acq, address, call_id, self.node))
                # Proof of @R29: @R30; deeply immutable by @E11.

                return None

        elif request[0] == 'identity status changed':
            if not (len(request) >= 3):
                return error.Error('Name_server.handle: identity status changed: expecting tuple of at least 3.')
            self.lock.acquire()
            try:
                acq = self.acquaintances.get(request[1],None)
                if acq:
                    acq.lock.acquire()
                    try:
                        acq.status = request[2]
                    finally:
                        acq.lock.release()
                    self.acquaintance_status_changed(acq, 'status changed')
            finally:
                self.lock.release()
        elif request[0] == 'identity disconnecting':
            if not (len(request) >= 2):
                return error.Error('Name_server.handle: identity disconnecting: expecting tuple of at least 2.')
            self.lock.acquire()
            if address in self.watchers:
                self.watchers.remove(address)
            
            if self.acquaintances.has_key(request[1]):
                acq = self.acquaintances[request[1]]
                self.lock.release()
                if acq.disconnection(address):
                    self.acquaintance_status_changed(acq, 'disconnect', message=request[2])
                return None
            else:
                self.lock.release()
                return error.Error(_("I don't know you."))
Esempio n. 14
0
def chat_tell_thread(chat, dests, message, attachment=None, augmentation=None):
    """Messages are sent in parallel, one thread per recipient. The
       information displayed in field ends with '...' until the last
       message has been sent, then with '..' until all recipients
       have answered, and finally with '.' The field is closed by
       the last thread to finish """
    
    check.check_matches(dests, ['text'])
    check.check_is_text(message)
    std_timestamp = host2standard_timestamp(time.time())
    if augmentation and len(augmentation) != len(message):
        sys.stderr.write("Augmentation %d bytes, should be %d bytes.\n"
                         % (len(augmentation), len(message)))
        augmentation = None
    
    message_id = chat.create_message_id()
    try:
        result = ['','','','','...\n']
        dest_list = [ ]
        dest_address  = [ ]
        checked_address = [ ]
        dest_names = [ ]
        received_names = [ ]
        offline_list  = [ ]
        offline_names = [ ]
        recipient_list = [ ]
        channel_pipes = { }
        chan_cnt=[0]

        for dest in dests:
            if dest[0]=='#':
                channel_pipes[dest] = chat.channels.sub_list_pipe(dest)
                recipient_list.append((None,None,dest))
                continue
            acq = chat.app.name_server.locate(dest)
            acq.start_watching(chat.node)
            while not acq.watched:
                yield 'sleep',0.1

            acq.lock.acquire()
            online = acq.online
            address = acq.address
            name = acq.name
            username = acq.info['name']
            acq.lock.release()

            if not online:
                offline_list.append(acq)
                offline_names.append(dest)
                recipient_list.append((name,None,username))
            else:
                dest_list.append(acq)
                dest_address.append(address)
                dest_names.append(dest)
                recipient_list.append((name,address,username))

        my_details = (
            chat.app.name_server.public_key_name,
            chat.app.name_server.name
        )

        package = {
            'from': my_details,
            'to': recipient_list,
            'text': message
        }
        if augmentation:
            package['aug'] = augmentation
        if attachment:
            package['attach'] = attachment

        package_pickle = safe_pickle.dumps(package)
        signature = chat.app.name_server.sign(package_pickle)
        message = ('chat message 2',package_pickle,signature)

        def recipient_thread(chat,address,name,channel,received_names,dest_address,
                             checked_address,chan_cnt,message_id,result, message=message):

            succ = 1
            try:
                ticket, template, wait = chat.node.call(address,message)
                if wait: yield ('call',(chat.node,ticket))
                ret_value = chat.node.get_reply(ticket,template)

                #Type checking
                if type(ret_value) != types.TupleType:
                    succ = 0
                    if not channel:
                        result[2] = result[2] + name + _(' sent bad reply.\n')
                        chat.update_message_status(message_id, result[0]+result[4]+result[2])
            except error.Error,err:
                succ = 0
                if not channel:
                    result[2] = result[2] + name + _(' could not be contacted: ')+err.message+'\n'
                    chat.update_message_status(message_id, result[0]+result[4]+result[2])
                    chat.app.name_server.bad_address(address)
                    
            if succ:
                if channel:
                    chan_cnt[0] += 1
                else:
                    received_names.append(name)
                    if ret_value[0]:
                        pass
                        #if ret_value[1] != '':
                        #    result[2] = result[2] + name + ' ' + ret_value[1] + '\n'
                    else:
                        if ret_value[1] == '':
                            result[2] = result[2] + name + _(' is quiet.\n')
                        else:
                            result[2] = result[2] + name + _(' is quiet: ') + ret_value[1] + '\n'
                            
                if chan_cnt[0] == 0:
                    result[0] = _('Message received by ') + utility.english_list(received_names) 
                elif chan_cnt[0] == 1:
                    result[0] = _('Message received by ')\
                                +utility.english_list(received_names+[ _('1 person')])+result[1]
                else:                            
                    result[0] = _('Message received by ')\
                                +utility.english_list(received_names+[ _('%d people') % chan_cnt[0] ])+result[1]
                chat.update_message_status(message_id,result[0]+result[4]+result[2])

            checked_address.append(address)
            checked_address.sort()
            if result[4]=='..\n' and checked_address == dest_address:
                if chan_cnt[0]==0 and received_names == []:
                    result[0] = _('Nobody received your message')
                result[4] = '.\n'
                chat.update_message_status(message_id, result[0]+result[4]+result[2])

        for i in range(len(dest_list)):
            utility.start_thread(recipient_thread(chat,dest_address[i],dest_names[i],0,\
                       received_names,dest_address,checked_address,chan_cnt,message_id,result))
         
        if channel_pipes:
            if channel_pipes.__len__()>1:
                result[1] = (_(' on channels %s') % utility.english_list(channel_pipes.keys()))
            else:
                result[1] = (_(' on channel %s') % channel_pipes.keys()[0])

        if channel_pipes:
            for chan_name in channel_pipes.keys():
                if not chat.channels.cache.has_key(chan_name):
                    chat.channels.cache[chan_name]=[]
                else:                    
                    for address in chat.channels.cache[chan_name]:
                        if address in dest_address:
                            continue                    
                        dest_address.append(address)
                        utility.start_thread(
                            recipient_thread(chat,address,'',1,received_names,
                                             dest_address,checked_address,chan_cnt,message_id,result))
                #reset the cache:
                chat.channels.cache[chan_name]=[]
                    
                    
        while channel_pipes:
            for chan_name,chan_pipe in channel_pipes.items():
                if chan_pipe.finished():
                    chan_pipe.stop()
                    del channel_pipes[chan_name]
                    continue
                
                for address in chan_pipe.read_all():
                    #update the cache
                    if address not in chat.channels.cache[chan_name]:
                        chat.channels.cache[chan_name].append(address)
                    if address in dest_address:
                        continue
                    dest_address.append(address)
                    utility.start_thread(recipient_thread(chat,address,'',1,received_names,
                               dest_address,checked_address,chan_cnt,message_id,result))
                    
            yield 'sleep',0.1

        #we now have launched all the tasks
        dest_address.sort()
        result[4]='..\n'
        if checked_address == dest_address:
            if chan_cnt[0]==0 and received_names == []:
                result[0] = _('Nobody received your message')
            result[4] = '.\n'
            chat.update_message_status(message_id, result[0]+result[4]+result[2])

        recall_list = [ ]
        if offline_list:
            chat.update_message_status(message_id,'Caching message...\n',1)
        for i in range(len(offline_list)):
            key   = utility.random_bytes(settings.name_bytes)
            lock  = hash.hash_of(key)
            crypt = offline_list[i].encrypt((key, message, std_timestamp))
            data  = {
                'type' : 'offline message',
                'crypt': crypt
            }
            name  = hash.hash_of('offline message '+offline_list[i].name)
            # Loose proof of @R50: @I21, @E22.

            recall_list.append((offline_list[i].nickname,name,data,key))

            publish_result, subthread = chat.app.cache.publish([name],data,lock)
            yield 'wait',subthread
            if publish_result:
                redundancy = publish_result[0]
            else: redundancy = 0
            if redundancy == settings.cache_redundancy:
                str = offline_names[i] + _(' will get your message when next logged on.\n')
            elif redundancy == 0:
                str = _('Could not store message for ') + offline_names[i] + '!\n'
            else:
                str = (offline_names[i]
                       + _(' will probably get your message when next logged on:\n' +\
                           '  Message only stored with redundancy %d.\n') % redundancy)

            result[3] = result[3] + str
            chat.update_message_status(message_id,result[3]+'\n',1)
            
        chat.recall_list = recall_list
Esempio n. 15
0
        def publish_thread(self, result, names, data, lock, redundancy, expiry):

            if not (self.cache_pool_last_refresh+10*60 > time.time() or \
                 len(self.cache_pool) > self.cache_pool_original_size/2):

                cache_pool = [ ]

                pipe = self.node.retrieve(self.name, settings.cache_redundancy)

                while len(cache_pool) < 50 and not pipe.finished():
                    list = pipe.read_all()
                    for item in list:
                        check.check_matches(item, ('af_inet_address', 'any'))
                        # Proof: @E6.  Combine with @E10 and the fact that we don't
                        # pass pipe to anything else (nor write to it ourselves
                        # other than through pipe.read_all()) to show that @E6
                        # isn't broken by some other write.

                        if type(item[1]) != types.DictionaryType:
                            # todo: consider printing debug info
                            continue

                        if item[1].get('type','') == 'service data cache':
                            #cache_pool.append((-item[1]['up time'],item[0],item[1]))
                            
                            up_time = item[1].get('up time')

                            if type(up_time) != types.IntType:
                                # todo: consider printing debug info
                                continue

                            # Treat all up for over a day as equal to share load
                            if up_time > 24*60*60:
                                up_time = 24*60*60 + random.random()

                            cache_pool.append((-up_time,item[0],item[1]))
                        
                    yield 'sleep',1

                pipe.stop()
                self.cache_pool = cache_pool
                self.cache_pool.sort()
                self.cache_pool_original_size = len(self.cache_pool)

            if not expiry:
                expiry = self.data['max expiry time']

            if expiry < 0:
                result.append(0)
                return 

            pool = self.cache_pool[:]
            bad_items = [ ]

            pos = 0
            n   = 0
            while n < redundancy:
                if len(pool) <= pos:
                    result.append(n)
                    return 

                try:
                    if len(names) == 1:
                        ticket, template, wait = self.node.call(
                            pool[pos][1],('data cache store',lock,names[0],data,expiry))
                        if wait: yield 'call',(self.node,ticket)
                        dummy_result = self.node.get_reply(ticket, template)
                    else:
                        ticket, template, wait = self.node.call(
                            pool[pos][1],('data cache store multi',lock,names,data,expiry))
                        if wait: yield 'call',(self.node,ticket)
                        dummy_result = self.node.get_reply(ticket, template)
                except Error, error:
                    if error.message != 'already storing':
                        bad_items.append(pool[pos])
                    else:
                        # thomasV: we need to limit amplification
                        # print 'already storing', pool[pos]
                        n = n + 1
                        # end thomasV
                    pos = pos + 1
                    continue
                pos = pos + 1
                n   = n   + 1
Esempio n. 16
0
    def handle(self, request, address, call_id):
        check.check_matches(request, (types.StringType,))
        check.check_is_af_inet_address(address)

        if request[0] == 'download chunk':
            path, mtime = self.paths.get(request[1],(None,None))
            if not path:
                path, mtime = self.private_paths.get(request[1],(None,None))
                
            try:
                if not path or \
                     os.path.getmtime(path) != mtime:
                    return Error("no such file")
                file = open(path,'rb') 
            except IOError:
                return Error("no such file")

            if address[0] !='127.0.0.1'\
                   and address not in self.node.trusted_addresses \
                   and self.private_directory != ''\
                   and utility.is_subdir(path,self.private_directory):
                return Error("access denied")

            try:
                file.seek(request[2])
                return file.read(request[3])
            finally:
                file.close()

        elif request[0] == 'files available':

            if len(request) == 3:
                # this returns the keys of
                # all published files from all directories
                # regardless of the directory structure
                list = self.paths.keys()
            else:
                list = [ ]
                access_denied = 0
                directory_found = 0

                string_request = []
                for str in request[3]:
                    string_request.append(utility.force_string(str))

                if not self.roots:
                    return Error('No public directory')
                request_dir = apply(
                    os.path.join,
                    [os.path.abspath(self.roots[0][0])] + string_request)

                if address[0]=='127.0.0.1':
                    flags = flags_local
                else:
                    flags = flags_fast            
                    
                if os.path.exists(request_dir):
                    directory_found = 1

                if address[0]!='127.0.0.1' \
                       and address not in self.node.trusted_addresses\
                       and self.private_directory != ''\
                       and utility.is_subdir(request_dir,self.private_directory):
                    access_denied = 1
                    
                if not directory_found:
                    return Error("no such directory: %s"%request_dir)
                elif access_denied:
                    return Error("access denied")
                
                entry = build_entry(request_dir,None,flags,self)
                
                if entry:
                    if not entry.is_dir:
                        return Error("not a directory: "+request_dir)
                    for file in entry.files:
                        entry_2 = build_entry(file,None,flags,self)
                        if entry_2:
                            info = entry_2.info.copy()
                            info['path'] = request[3] + [ info['filename'] ]
                            list.append(info)

            return list[request[1]:request[2]]
Esempio n. 17
0
 def chat_check_invar(self):
     check.check_matches(self.unread_message_list,
                         [unread_message_list_item_tmpl])  #=@I15
     check.check_matches(self.incoming_message_history,
                         [incoming_message_history_item_tmpl])  #=@I16
     check.check_matches(self.channel, ['text'])  #=@I31
Esempio n. 18
0
    def receive(self, request, address, quiet, send_time, add_to_history=1):
        """send_time should be as if from time.time() (i.e. a float expressing seconds
           since the local machine's epoch) rather than the standardized timestamps
           sent over the network (i.e. a long expressing seconds since the Unix epoch
           of 1970)."""

        # TODO: more checking of message format
        # TODO: search for people not in acq list

        check.check_is_opt_address(address)  #=@R33  fixme callers
        check.check_has_type(send_time, types.FloatType)  #=@R35  fixme callers
        # fixme: should probably require that request be a tuple with 5+ elems.

        if 1:
            if not self.is_visible():
                self.n_unseen_messages = self.n_unseen_messages + 1
                if self.n_unseen_messages == 1:
                    title = _('1 unseen message')
                else:
                    title = _('%d unseen messages') % self.n_unseen_messages
                self.app.set_title(title)

            if request[0] == 'chat message 2':
                package = safe_pickle.loads(request[1])
                text = package['text']
                augmentation = package.get('aug')
                has_attachment = package.has_key('attach')
                attachment = package.get('attach')
                sender_key_name, sender_name = package['from']
                recipients = package['to']

                verify_text = request[1]
                verify_sig = request[2]

            else:
                # Legacy message format
                text = request[3]
                augmentation = None
                has_attachment = (len(request) == 6)
                if has_attachment:
                    attachment = safe_pickle.loads(request[4])

                recipients = request[2]

                if type(request[1]) == type(()):
                    sender_key_name = request[1][0]
                    sender_name = request[1][1]
                else:
                    # Used not to send username with key name
                    sender_key_name = request[1]
                    sender_name = 'unknown'

                if has_attachment:
                    verify_text = request[3].encode('utf8')+request[4]
                    verify_sig = request[5]
                else:
                    verify_text = request[3]
                    verify_sig = request[4]

            if not augmentation:
                augmentation = chr(128) * len(text)


            self.show_received_message(sender_name,sender_key_name,address,recipients,
                                       text,verify_text,verify_sig,quiet,
                                       send_time,augmentation,has_attachment,attachment)

        #except error.Error:
        #    self.show(_('Bad message received from ') + repr(address) + '\n')

        if add_to_history:
            self.lock.acquire()
            try:
                new_item = (request, send_time)
                check.check_matches(new_item, incoming_message_history_item_tmpl)
                # Proof: @R35, immutability of float, send_time not reassigned
                # in this function.
                # Relevance: @I16.
                self.incoming_message_history.append(new_item)

                while len(self.incoming_message_history) > settings.incoming_message_history_size:
                    del self.incoming_message_history[0]
            finally:
                self.lock.release()
Esempio n. 19
0
    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()