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)
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
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
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
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)
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
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