from mesh.links import UDPLink from mesh.programs import BaseProgram from mesh.filters import UniqueFilter from mesh.node import Node class ChatProgram(BaseProgram): def recv(self, packet, interface): print('\n>> {}'.format(packet.decode())) if __name__ == "__main__": links = [UDPLink('en0', 2010), UDPLink('en1', 2011), UDPLink('en2', 2012), UDPLink('en3', 2013)] node = Node(links, 'me', Filters=(UniqueFilter,), Program=ChatProgram) [link.start() for link in links] node.start() print("Run lan-chat.py on another laptop to talk between the two of you on en0.") try: while True: print("------------------------------") message = input('<< ') node.send(bytes(message, 'UTF-8')) time.sleep(0.3) except (EOFError, KeyboardInterrupt): # graceful CTRL-D & CTRL-C node.stop() [link.stop() for link in links]
print("EXITING CLEANLY" if intentional else "EXITING BADLY") raise SystemExit(int(not intentional)) class ChatProgram(BaseProgram): def recv(self, packet, interface): print('\n>> {}'.format(packet.decode())) if __name__ == "__main__": links = [ UDPLink('en0', 2010), UDPLink('en1', 2011), UDPLink('en2', 2012), UDPLink('en3', 2013) ] node = Node(links, 'me', Filters=(UniqueFilter, ), Program=ChatProgram) [link.start() for link in links] node.start() try: while True: print("------------------------------") message = input('<< ') node.send(bytes(message, 'UTF-8')) time.sleep(0.3) except (EOFError, KeyboardInterrupt): # graceful CTRL-D & CTRL-C node.stop() [link.stop() for link in links]
class Node(threading.Thread): def __init__(self, name, port=5000, blockchain=Blockchain()): threading.Thread.__init__(self) self.name = name self.address = ni.ifaddresses('en0')[ni.AF_INET][0]['addr'] self.blockchain = blockchain self.peer_info = {} self.peers = set() self.links = [UDPLink('en0', port=port)] self.network = NetworkComponent(self.links, name, Filters=(DuplicateFilter, )) self.keep_listening = True self.ready = False self.synced = False self.heartbeat_thread = threading.Thread(target=self.send_heartbeat) # Start Network Component [link.start() for link in self.links] self.network.start() self.heartbeat_thread.start() self.start() @property def identifier(self): parsed_url = urlparse(self.address) return f'{parsed_url.path}:{self.name}' # Threading def run(self): while self.keep_listening: # Remove peers who have disconnected after 30 mins disconnected_peers = [] for peer_id, info in self.peer_info.items(): if info['lastsend'] - info['lastrecv'] > 60 * 30: disconnected_peers.append(peer_id) for peer_id in disconnected_peers: print(f'Disconnecting {peer_id} for being idle for 30 minutes') self.peer_info.pop(peer_id) self.peers.remove(peer_id) # Check for new packets for interface in self.network.interfaces: try: self.recv(self.network.inq[interface].get(timeout=0), interface) except Empty: sleep(0.1) def stop(self): self.keep_listening = False self.network.stop() [link.stop() for link in self.links] self.heartbeat_thread.join() self.join() # I/O def send(self, type, message='', target='', encoding='UTF-8'): data = json.dumps({ 'type': type, 'identifier': self.identifier, 'message': message, 'target': target }) print('\nsending {}'.format(data)) self.network.send(bytes(data, encoding)) # Update Peer Info if target: self.peer_info[target]['lastsend'] = time() else: for peer in self.peers: self.peer_info[peer]['lastsend'] = time() def recv(self, packet, interface): data = json.loads(packet.decode()) # Filter Packets not targeted to you if len(data['target']) != 0 and data['target'] != self.identifier: return print('\nreceived {}'.format(data)) self.handle_data(data) # Update Peer Info sender = data['identifier'] if sender in self.peers: self.peer_info[sender]['lastrecv'] = time() def handle_data(self, data): # Handle Request msg_type = data['type'] sender = data['identifier'] message = json.loads(data['message']) if data['message'] else {} if msg_type == 'version': registered = self.register_peer(sender, height=message.get('height')) if registered: self.send('verack', target=sender) self.send('version', target=sender, message=json.dumps( {'height': len(self.blockchain.chain)})) print(self.peers) elif msg_type == 'verack': self.ready = True if self.ready: if msg_type == 'heartbeat': self.send('heartbeatack', target=sender) elif msg_type == 'heartbeatack': pass def send_heartbeat(self): while self.keep_listening and self.ready: sleep(60 * 30) self.send('heartbeat') # Methods def register_peer(self, identifier, height): """ Add a new node to the list of nodes @param identifier: <str> Identifier of the node (eg: 'address:name') @return: <bool> True if a new peer was registered, False otherwise """ if identifier not in self.peers: self.peers.add(identifier) self.peer_info[identifier] = { 'identifier': identifier, 'lastrecv': time(), 'lastsend': 0, 'height': height } return True else: return False def get_peer(self, index=None): """ Returns a random peer identifier unless specified by the parameter @param index: <int> Index of the peer in the peer list @return: <str> Peer identifier """ if index is None: index = randint(0, len(self.peers) - 1) i = 0 for p in self.peers: if i == index: return p i += 1