예제 #1
0
    def test_encode_decode_intro_request(self):
        """
        Test encoding and decoding of an introduction request
        """
        message = MockObject()
        meta_msg = self.market_community.get_meta_message(u"dispersy-introduction-request")

        bloomfilter = BloomFilter(0.005, 30, prefix=' ')
        intro_payload = MarketIntroPayload.Implementation(meta_msg, ("127.0.0.1", 1324), ("127.0.0.1", 1234),
                                                          ("127.0.0.1", 1234), True, u"public", None, 3, bloomfilter)
        message.payload = intro_payload
        packet_str = ''.join(self.conversion._encode_introduction_request(message))
        self.assertTrue(packet_str)

        placeholder = self.get_placeholder_msg(u"dispersy-introduction-request")
        _, decoded = self.conversion._decode_introduction_request(placeholder, 0, packet_str)
        self.assertTrue(decoded)

        self.assertRaises(DropPacket, self.conversion._decode_introduction_request, placeholder, 0, 'abc')
        self.assertRaises(DropPacket, self.conversion._decode_introduction_request, placeholder, 0, packet_str + 'b')

        # Add a malformed bloomfilter
        intro_payload = MarketIntroPayload.Implementation(meta_msg, ("127.0.0.1", 1324), ("127.0.0.1", 1234),
                                                          ("127.0.0.1", 1234), True, u"public", None, 3, None)
        message.payload = intro_payload
        packet_str = ''.join(self.conversion._encode_introduction_request(message))
        self.assertRaises(DropPacket, self.conversion._decode_introduction_request, placeholder, 0, packet_str + 'a')
        bf_encoding = pack("!BH", 3, 0) + 'aa'
        self.assertRaises(DropPacket, self.conversion._decode_introduction_request, placeholder, 0,
                          packet_str + bf_encoding)
예제 #2
0
    def _decode_introduction_request(self, placeholder, offset, data):
        offset, payload = BinaryConversion._decode_introduction_request(self, placeholder, offset, data)

        # if there's still bytes in this request, treat them as taste_bloom_filter
        has_stuff = len(data) > offset
        if has_stuff:
            if len(data) < offset + 8:
                raise DropPacket("Insufficient packet size")

            num_preferences, functions, size = unpack_from('!IBH', data, offset)
            offset += 7

            prefix = data[offset]
            offset += 1

            if not 0 < num_preferences:
                raise DropPacket("Invalid num_preferences value")
            if not 0 < functions:
                raise DropPacket("Invalid functions value")
            if not 0 < size:
                raise DropPacket("Invalid size value")
            if not size % 8 == 0:
                raise DropPacket("Invalid size value, must be a multiple of eight")

            length = int(ceil(size / 8))
            if not length == len(data) - offset:
                raise DropPacket("Invalid number of bytes available (irq) %d, %d, %d" % (length, len(data) - offset, size))

            taste_bloom_filter = BloomFilter(data[offset:offset + length], functions, prefix=prefix)
            offset += length

            payload.set_num_preferences(num_preferences)
            payload.set_taste_bloom_filter(taste_bloom_filter)

        return offset, payload
예제 #3
0
    def _decode_introduction_request(self, placeholder, offset, data):
        offset, payload = BinaryConversion._decode_introduction_request(
            self, placeholder, offset, data)

        if len(data) > offset:
            if len(data) < offset + 5:
                raise DropPacket("Insufficient packet size")

            functions, size = unpack_from('!BH', data, offset)
            offset += 3

            prefix = data[offset]
            offset += 1

            if functions <= 0 or size <= 0 or size % 8 != 0:
                raise DropPacket("Invalid bloom filter")

            length = size / 8
            if length != len(data) - offset:
                raise DropPacket(
                    "Invalid number of bytes available (irq) %d, %d, %d" %
                    (length, len(data) - offset, size))

            orders_bloom_filter = BloomFilter(data[offset:offset + length],
                                              functions,
                                              prefix=prefix)
            offset += length

            payload.set_orders_bloom_filter(orders_bloom_filter)

        return offset, payload
예제 #4
0
    def create_introduction_request(self, destination):
        assert isinstance(destination,
                          WalkCandidate), [type(destination), destination]

        if DEBUG:
            print >> sys.stderr, "SearchCommunity: sending introduction request to", destination

        self._dispersy._statistics.increment_walk_attempt()
        destination.walk(self, time())

        # temporary cache object
        identifier = self._dispersy.request_cache.claim(
            IntroductionRequestCache(self, destination))
        advice = True

        taste_bloom_filter = None

        num_preferences = 0
        if not isinstance(destination, BootstrapCandidate):
            myPreferences = self._mypref_db.getMyPrefListInfohash(limit=500)
            myPreferences.sort()
            num_preferences = len(myPreferences)

            myPref_key = ",".join(map(bin2str, myPreferences))
            if myPref_key != self.taste_bloom_filter_key:
                if num_preferences > 0:
                    #no prefix changing, we want false positives (make sure it is a single char)
                    self.taste_bloom_filter = BloomFilter(0.005,
                                                          len(myPreferences),
                                                          prefix=' ')
                    self.taste_bloom_filter.add_keys(myPreferences)
                else:
                    self.taste_bloom_filter = None

                self.taste_bloom_filter_key = myPref_key

            taste_bloom_filter = self.taste_bloom_filter

        meta_request = self.get_meta_message(u"dispersy-introduction-request")
        request = meta_request.impl(
            authentication=(self.my_member, ),
            distribution=(self.global_time, ),
            destination=(destination, ),
            payload=(destination.get_destination_address(
                self._dispersy._wan_address), self._dispersy._lan_address,
                     self._dispersy._wan_address, advice,
                     self._dispersy._connection_type, None, identifier,
                     num_preferences, taste_bloom_filter))

        self._dispersy.store_update_forward([request], False, False, True)
        return request
예제 #5
0
    def _decode_search_request(self, placeholder, offset, data):
        try:
            offset, payload = decode(data, offset)
        except ValueError:
            raise DropPacket("Unable to decodr 21, 2012 e the search-payload")

        if len(payload) < 2:
            raise DropPacket("Invalid payload length")

        identifier, keywords = payload[:2]

        if len(identifier) != 2:
            raise DropPacket(
                "Unable to decode the search-payload, got %d bytes expected 2"
                % (len(identifier)))
        identifier, = unpack_from('!H', identifier)

        if not isinstance(keywords, list):
            raise DropPacket("Invalid 'keywords' type")
        for keyword in keywords:
            if not isinstance(keyword, unicode):
                raise DropPacket("Invalid 'keyword' type")

        if len(payload) > 5:
            functions, prefix, bytes_ = payload[2:6]

            if not isinstance(functions, int):
                raise DropPacket("Invalid functions type")
            if not 0 < functions:
                raise DropPacket("Invalid functions value")

            size = len(bytes_)
            if not 0 < size:
                raise DropPacket("Invalid size of bloomfilter")
            if not size % 8 == 0:
                raise DropPacket(
                    "Invalid size of bloomfilter, must be a multiple of eight")

            if not isinstance(prefix, str):
                raise DropPacket("Invalid prefix type")
            if not 0 <= len(prefix) < 256:
                raise DropPacket("Invalid prefix length")

            bloom_filter = BloomFilter(bytes_, functions, prefix=prefix)
        else:
            bloom_filter = None

        return offset, placeholder.meta.payload.implement(
            identifier, keywords, bloom_filter)
예제 #6
0
    def create_introduction_request(self,
                                    destination,
                                    allow_sync,
                                    is_fast_walker=False):
        assert isinstance(destination,
                          WalkCandidate), [type(destination), destination]

        if DEBUG:
            self._logger.debug(
                u"SearchCommunity: sending introduction request to %s",
                destination)

        advice = True
        if not is_fast_walker:
            my_preferences = sorted(
                self._mypref_db.getMyPrefListInfohash(limit=500))
            num_preferences = len(my_preferences)

            my_pref_key = u",".join(map(bin2str, my_preferences))
            if my_pref_key != self.taste_bloom_filter_key:
                if num_preferences > 0:
                    # no prefix changing, we want false positives (make sure it is a single char)
                    self.taste_bloom_filter = BloomFilter(0.005,
                                                          len(my_preferences),
                                                          prefix=' ')
                    self.taste_bloom_filter.add_keys(my_preferences)
                else:
                    self.taste_bloom_filter = None

                self.taste_bloom_filter_key = my_pref_key

            taste_bloom_filter = self.taste_bloom_filter

            cache = self._request_cache.add(
                IntroductionRequestCache(self, destination))
            payload = (destination.sock_addr, self._dispersy._lan_address,
                       self._dispersy._wan_address, advice,
                       self._dispersy._connection_type, None, cache.number,
                       num_preferences, taste_bloom_filter)
        else:
            cache = self._request_cache.add(
                IntroductionRequestCache(self, destination))
            payload = (destination.sock_addr, self._dispersy._lan_address,
                       self._dispersy._wan_address, advice,
                       self._dispersy._connection_type, None, cache.number, 0,
                       None)

        destination.walk(time())
        self.add_candidate(destination)

        meta_request = self.get_meta_message(u"dispersy-introduction-request")
        request = meta_request.impl(authentication=(self.my_member, ),
                                    distribution=(self.global_time, ),
                                    destination=(destination, ),
                                    payload=payload)

        self._logger.debug(u"%s %s sending introduction request to %s",
                           self.cid.encode("HEX"), type(self), destination)

        self._dispersy._forward([request])
        return request
예제 #7
0
    def create_introduction_request(self,
                                    destination,
                                    allow_sync,
                                    is_fast_walker=False):
        assert isinstance(destination,
                          WalkCandidate), [type(destination), destination]

        if DEBUG:
            print >> sys.stderr, "SearchCommunity: sending introduction request to", destination

        destination.walk(time(), IntroductionRequestCache.timeout_delay)
        self.add_candidate(destination)

        advice = True
        if not (isinstance(destination, BootstrapCandidate) or is_fast_walker):
            myPreferences = sorted(
                self._mypref_db.getMyPrefListInfohash(limit=500))
            num_preferences = len(myPreferences)

            myPref_key = ",".join(map(bin2str, myPreferences))
            if myPref_key != self.taste_bloom_filter_key:
                if num_preferences > 0:
                    # no prefix changing, we want false positives (make sure it is a single char)
                    self.taste_bloom_filter = BloomFilter(0.005,
                                                          len(myPreferences),
                                                          prefix=' ')
                    self.taste_bloom_filter.add_keys(myPreferences)
                else:
                    self.taste_bloom_filter = None

                self.taste_bloom_filter_key = myPref_key

            taste_bloom_filter = self.taste_bloom_filter

            identifier = self._dispersy.request_cache.claim(
                IntroductionRequestCache(self, destination))
            payload = (destination.get_destination_address(
                self._dispersy._wan_address), self._dispersy._lan_address,
                       self._dispersy._wan_address, advice,
                       self._dispersy._connection_type, None, identifier,
                       num_preferences, taste_bloom_filter)
        else:
            identifier = self._dispersy.request_cache.claim(
                IntroductionRequestCache(self, destination))
            payload = (destination.get_destination_address(
                self._dispersy._wan_address), self._dispersy._lan_address,
                       self._dispersy._wan_address, advice,
                       self._dispersy._connection_type, None, identifier, 0,
                       None)

        meta_request = self.get_meta_message(u"dispersy-introduction-request")
        request = meta_request.impl(authentication=(self.my_member, ),
                                    distribution=(self.global_time, ),
                                    destination=(destination, ),
                                    payload=payload)

        logger.debug("%s %s sending introduction request to %s",
                     self.cid.encode("HEX"), type(self), destination)

        self._dispersy.statistics.walk_attempt += 1
        if isinstance(destination, BootstrapCandidate):
            self._dispersy.statistics.walk_bootstrap_attempt += 1
        if request.payload.advice:
            self._dispersy.statistics.walk_advice_outgoing_request += 1

        self._dispersy._forward([request])
        return request