def transmit(self): """Puts all currently pending sent messages to the insock buffer of the recipient of the message. This is more useful than immediate "delivery" because it allows full flexibility of the order in which tests set up nodes and mock actors on those nodes, and of the order in which messages are sent out from a node. """ if not self.queue: return deliverable = [] for src, dst, msg in self.queue: _assert_valid_addr(src) _assert_valid_addr(dst) # assert (src, dst) in self.connections, "Hubs should only send messages to addresses they have previously connected to" if random.random() <= self._packet_loss.get((src, dst), 0.0): dbg("packet lost: %r %s → %s" % (msg, src, dst)) continue if dst not in self.listeners: pass # dbg(u"%r ⇝ ↴" % (_dumpmsg(msg),)) else: # dbg(u"%r → %s" % (_dumpmsg(msg), dst)) sock = self.listeners[dst] deliverable.append((msg, src, sock)) del self.queue[:] for msg, src, sock in deliverable: sock.gotMultipart(msg)
def connect(self, addr, endpoints): _assert_valid_addr(addr) for endpoint in endpoints: assert endpoint.type == 'connect', "Hubs should only connect MockOutSockets and not bind" _assert_valid_addr(endpoint.address) assert (addr, endpoint.address) not in self.connections dbg(u"%s → %s" % (addr, endpoint.address)) self.connections.add((addr, endpoint.address))
def enqueue(self, src, dst, msg): _assert_valid_addr(src) _assert_valid_addr(dst) assert isinstance(msg, tuple) and all(isinstance(x, bytes) for x in msg), "Message payloads sent out by Hub should be tuples containing bytse" assert (src, dst) in self.connections, "Hubs should only send messages to addresses they have previously connected to" # dbg(u"%r → %s" % (_dumpmsg(msg), dst)) self.queue.append((src, dst, msg))
def bind(self, addr, sock, endpoints): assert all(x.type == 'bind' for x in endpoints), "Hubs should only bind in-sockets and never connect" assert len(endpoints) == 1, "Hubs should only bind in-sockets to a single network address" endpoint, = endpoints _assert_valid_addr(addr) _assert_valid_addr(endpoint.address) assert endpoint.address == addr, "Hubs should only bind its in-socket to the address given to the Hub: %s != %s" % (addr, endpoint.address) if addr in self.listeners: raise TypeError("addr %r already registered on the network" % (addr,)) self.listeners[addr] = sock
def enqueue(self, src, dst, msg): _assert_valid_addr(src) _assert_valid_addr(dst) assert isinstance(msg, tuple) and all( isinstance(x, bytes) for x in msg ), "Message payloads sent out by Hub should be tuples containing bytse" assert ( src, dst ) in self.connections, "Hubs should only send messages to addresses they have previously connected to" # dbg(u"%r → %s" % (_dumpmsg(msg), dst)) self.queue.append((src, dst, msg))
def bind(self, addr, sock, endpoints): assert all( x.type == 'bind' for x in endpoints), "Hubs should only bind in-sockets and never connect" assert len( endpoints ) == 1, "Hubs should only bind in-sockets to a single network address" endpoint, = endpoints _assert_valid_addr(addr) _assert_valid_addr(endpoint.address) assert endpoint.address == addr, "Hubs should only bind its in-socket to the address given to the Hub: %s != %s" % ( addr, endpoint.address) if addr in self.listeners: raise TypeError("addr %r already registered on the network" % (addr, )) self.listeners[addr] = sock
def packet_loss(self, percent, src, dst): _assert_valid_addr(src) _assert_valid_addr(dst) self._packet_loss[(src, dst)] = percent / 100.0