def _timertransmit(self, now): """A periodic handler that iterates through the nodes and sends any packets that are queued for delivery. Args: now (float): Current time. """ srcnode = self.LocalNode dstnodes = self.peer_list(True) while len(dstnodes) > 0: newnodes = [] for dstnode in dstnodes: msg = dstnode.get_next_message(now) if msg: if dstnode.Enabled or msg.IsSystemMessage: # basically we are looping through the nodes & as long # as there are messages pending then come back around & # try again newnodes.append(dstnode) packet = message.Packet() packet.add_message(msg, srcnode, dstnode, self.next_sequence_number()) packet.TransmitTime = now if packet.IsReliable: self.PendingAckMap[packet.SequenceNumber] = packet self._dowrite(packet.pack(), dstnode) dstnodes = newnodes
def datagramReceived(self, data, address): """Handles a received datagram. Find a handler for the message if one exists, and call it if the message has not already been handled. Also forward to peers as appropriate. Args: data (str): the text of the message address (str): host:port network address of the peer """ if not self.ProcessIncomingMessages: return self.PacketStats.BytesReceived.add_value(len(data)) # unpack the header try: packet = message.Packet() packet.unpack(data) except: logger.exception('failed to unpack message') return # Grab peer information if it is available, unless this is a system # message we don't process any further without a known peer srcpeer = self.NodeMap.get(packet.SenderID) if srcpeer: srcpeer.reset_ticks() # Handle incoming acknowledgements first, there is no data associated # with an ack if packet.IsAcknowledgement: if srcpeer: self._handleack(packet) return # first thing to do with the message is to send an ACK, all # retransmissions will be handled by the sending node, if the # IsReliable flag is set then this is not a system message & we know # that the peer exists if packet.IsReliable: if srcpeer: self._sendack(packet, srcpeer) # now unpack the rest of the message try: minfo = message.unpack_message_data(packet.Data) except: logger.exception('unable to decode message with length %d', len(data)) return # if we don't have a handler, thats ok we just dont do anything # with the message, note the missing handler in the logs however typename = minfo['__TYPE__'] self.MessageStats.MessageType.increment(typename) if typename not in self.MessageHandlerMap: logger.info('no handler found for message type %s from %s', minfo['__TYPE__'], srcpeer or packet.SenderID[:8]) return try: msg = self.unpack_message(typename, minfo) msg.TimeToLive = packet.TimeToLive - 1 msg.SenderID = packet.SenderID except: logger.exception( 'unable to deserialize message of type %s from %s', typename, packet.SenderID[:8]) return # if we have seen this message before then just ignore it if msg.Identifier in self.MessageHandledMap: logger.debug('duplicate message %s received from %s', msg, packet.SenderID[:8]) self.PacketStats.DuplicatePackets.increment() # if we have received a particular message from a node then we dont # need to send another copy back to the node, just remove it from # the queue try: if srcpeer: srcpeer.dequeue_message(msg) except: pass return # verify the signature, this is a no-op for the gossiper, but # subclasses might override the function, system messages need not have # verified signatures if not msg.IsSystemMessage and not msg.verify_signature(): logger.warn('unable to verify message %s received from %s', msg.Identifier[:8], msg.OriginatorID[:8]) return # Handle system messages,these do not require the existence of # a peer. If the packet is marked as a system message but the message # type does not, then something bad is happening. self.PacketStats.MessagesHandled.increment() if srcpeer or msg.IsSystemMessage: self.handle_message(msg) return logger.warn('received message %s from an unknown peer %s', msg, packet.SenderID[:8])