def random_bytes(n): """ Make some random bytes, preferably of cryptographic quality. This function is used to generate random bytes for challenges and for the node's address in the circle. It would be preferable to have a urandom equivalent for windows, but alas... Ensures @E14: (type(ret) == types.StringType) and (len(ret) == n).""" check.check_has_type(n, types.IntType) check.check_assertion(n >= 0) #=@R27 ret = '' if n != 0: try: file = open('/dev/urandom','rb') ret = file.read(n) file.close() except IOError: pass for i in range(n - len(ret)): ret = ret + chr(random.randrange(256)) check.check_postcondition((type(ret) == types.StringType) and (len(ret) == n), '@E14') return ret
def standard2host_timestamp(std_tstamp): check.check_has_type(std_tstamp, types.LongType) #=@R36 ret = float(std_tstamp - host2standard_time_offset) check.check_has_type(ret, types.FloatType) #=@E17 return ret
def host2standard_timestamp(host_tstamp): check.check_has_type(host_tstamp, types.FloatType) ret = long(host_tstamp + host2standard_time_offset) check.check_has_type(ret, types.LongType) #=@E16 return ret
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()
def change_activity(self, msg): check.check_has_type(msg, types.StringType) #if msg: # print msg now_time = time.time() if self.thread_activity: durn = int(now_time - self.activity_start_time) if durn >= 60: print self, 'Activity took %d seconds: %s' % (durn, self.thread_activity) self.thread_activity = msg self.activity_start_time = now_time
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
def bisect(a, too_high): """Return the first index i in a such that too_high(a[i]) is true; or len(a) if too_high(x) is true for all elements x in a. The usual use for this function is deciding where to insert element; e.g. my_list.insert(bisect(my_list, lambda elem,x=x: x < elem), x) Requires: a is monotonic non-decreasing in the truth of too_high; i.e. exists[pos] ((all[j in [0, pos)] not too_high(a[j])) and all[j in [pos, len(a))] too_high(a[j])). Put another way: all[(i,j) s.t. i <= j] too_high(a[i]) implies too_high(a[j]). Note that this more or less requires that neither a nor too_high change during execution (say due to writes from another thread). Ensures: The return value equals pos above. I.e.: (all[j in [0, ret)] not too_high(a[j])) and (all[j in [ret, len(a))] too_high(a[j])). """ check.check_has_type(a, types.ListType) check.check_is_callable(too_high) lo = 0 hi = len(a) while lo < hi: mid = (lo+hi) >> 1 if too_high(a[mid]): hi = mid else: lo = mid+1 check.check_assertion((0 <= lo) and (lo <= len(a))) ## Check sortedness: #for elem in a[:lo]: # if too_high(elem): # check.show_bug('utility.bisect: unsorted input list (or bug in bisect code)') #for elem in a[lo:]: # if not too_high(elem): # check.show_bug('utility.bisect: unsorted input list (or bug in bisect code)') return lo
def schedule_mainthread(t_plus, func, *parameters): """ Schedule an action: after t_plus milliseconds, func will be called in the main thread with the parameters given. If func returns true, it will be called again after another t_plus milliseconds""" check.check_has_type(t_plus, types.FloatType) check.check_is_callable(func) daemon_action_lock.acquire() try: new_time = time.time() + t_plus/1000.0 action_item = (new_time, func, parameters, t_plus) pos = bisect(daemon_action_list, lambda elem, new_time=new_time: new_time < elem[0]) daemon_action_list.insert(pos, action_item) finally: daemon_action_lock.release()
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()
def check_invar(self): check.check_has_type(self.gossip, types.ListType) for wodge in self.gossip: check.check_isinstance(wodge, Wodge)