def encrypt(self, object): self.lock.acquire() try: key = utility.random_bytes(16) pub_key = crypto.RSA.construct(self.info['key']) encryptor = crypto.rijndael.rijndael(key, 16) encrypted_key = pub_key.encrypt(key,'')[0] encrypted_text = encryptor.encrypt_cbc(safe_pickle.dumps(object)) return (encrypted_key, encrypted_text) finally: self.lock.release()
def identity_test_thread(address, key, the_node, id_test_result): #from node import Node # Test identity check.check_is_af_inet_address(address) #check.check_isinstance(the_node, Node) tester = utility.random_bytes(settings.name_bytes) ticket, template, wait = the_node.call(address, ('identity test',tester)) if wait: yield 'call',(the_node,ticket) try: result = the_node.get_reply(ticket, template) except error.Error,err: print "error",err id_test_result.append(0) return
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
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