def handleBroadcast(self, ad, data, check_cb, bridgey=False):
        (kind, nb_ipp, hop, flags, src_ipp, rest
         ) = self.decodePacket('!2s6sBB6s+', data)

        osm = self.main.osm
        if not osm:
            raise BadTimingError("Not ready to route '%s' packet" % kind)

        # Make sure nb_ipp agrees with the sender's IP
        self.checkSource(nb_ipp, ad, exempt_ip=True)

        # Make sure the src_ipp is valid.
        # Any broadcast which might be from a bridge is 'bridgey'
        src_ad = Ad().setRawIPPort(src_ipp)
        if bridgey:
            kinds = 'sbx'
        else:
            kinds = 'sb'
        if not src_ad.auth(kinds, self.main):
            raise BadPacketError("Invalid forwarded source IP")

        # Make sure this came from one of my ping neighbors.
        # This helps a little to prevent the injection of random broadcast
        # traffic into the network.
        try:
            if not osm.pgm.pnbs[nb_ipp].got_ack:
                raise KeyError
        except KeyError:
            raise BadTimingError("Broadcast packet not from a ping neighbor")

        ack_flags = 0

        # Check if we've seen this message before.
        ack_key = osm.mrm.generateKey(data)
        if osm.mrm.pokeMessage(ack_key, nb_ipp):

            # Ack and skip the rest
            self.sendAckPacket(nb_ipp, ACK_BROADCAST, ack_flags, ack_key)
            return

        # Get the source node object, if any
        try:
            src_n = osm.lookup_ipp[src_ipp]
        except KeyError:
            src_n = None

        try:
            # Filter all non-bridgey broadcasts from bridge nodes.
            if not bridgey and self.isFromBridgeNode(src_n, src_ipp):
                raise BadBroadcast("Bridge can't use " + kind)

            # Callback the check_cb function
            check_cb(src_n, src_ipp, rest)

        except BadBroadcast, e:
            self.main.logPacket("Bad Broadcast: %s" % str(e))

            # Mark that we've seen this message, but don't forward it.
            osm.mrm.newMessage(data, tries=0, nb_ipp=nb_ipp)

            # Ack and skip the rest
            self.sendAckPacket(nb_ipp, ACK_BROADCAST, ack_flags, ack_key)
            return

        except Reject:
            # check_cb told us to reject this broadcast
            if src_ipp == nb_ipp:
                # If this is from a neighbor, just set the flag.
                # We'll send the ack later.
                ack_flags |= ACK_REJECT_BIT

            elif not (flags & REJECT_BIT):
                # Not from a neighbor, so send a reject packet immediately.
                self.sendAckPacket(
                    src_ipp, ACK_BROADCAST, ACK_REJECT_BIT, ack_key)

            # Set this flag to indicate to forwarded neighbors that we've
            # rejected the message.
            flags |= REJECT_BIT

        if hop > 0:
            # Start with the broadcast header
            packet = osm.mrm.broadcastHeader(kind, src_ipp, hop-1, flags)

            # Keep the rest of the message intact
            packet.append(rest)

            # Pass this message to MessageRoutingManager, so it will be
            # forwarded to all of my neighbors.
            osm.mrm.newMessage(''.join(packet), tries=2, nb_ipp=nb_ipp)

        # Ack the neighbor
        self.sendAckPacket(nb_ipp, ACK_BROADCAST, ack_flags, ack_key)

        # Update the original sender's age in the peer cache
        src_ad = Ad().setRawIPPort(src_ipp)
        self.main.state.refreshPeer(src_ad, 0)