def receive_message(self, datagram, connection): m = Message() try: m.ParseFromString(datagram) sender = node.Node(m.sender.guid, m.sender.ip, m.sender.port, m.sender.signedPublicKey, m.sender.vendor) except Exception: # If message isn't formatted property then ignore self.log.warning("Received unknown message from %s, ignoring" % str(connection.dest_addr)) return False # Check that the GUID is valid. If not, ignore if self.router.isNewNode(sender): try: pubkey = m.sender.signedPublicKey[len(m.sender.signedPublicKey) - 32:] verify_key = nacl.signing.VerifyKey(pubkey) verify_key.verify(m.sender.signedPublicKey) h = nacl.hash.sha512(m.sender.signedPublicKey) pow_hash = h[64:128] if int(pow_hash[:6], 16) >= 50 or hexlify(m.sender.guid) != h[:40]: raise Exception('Invalid GUID') except Exception: self.log.warning("Received message from sender with invalid GUID, ignoring") return False if m.sender.vendor: VendorStore().save_vendor(m.sender.guid, m.sender.ip, m.sender.port, m.sender.signedPublicKey) msgID = m.messageID data = tuple(m.arguments) if msgID in self._outstanding: self._acceptResponse(msgID, data, sender) else: self._acceptRequest(msgID, str(Command.Name(m.command)).lower(), data, sender, connection)
def handle_response(listings, node): count = 0 if listings is not None: for l in listings.listing: if l.contract_hash not in self.factory.outstanding[ message_id]: listing_json = { "id": message_id, "listing": { "guid": node.id.encode("hex"), "handle": listings.handle, "avatar_hash": listings.avatar_hash.encode("hex"), "title": l.title, "contract_hash": l.contract_hash.encode("hex"), "thumbnail_hash": l.thumbnail_hash.encode("hex"), "category": l.category, "price": l.price, "currency_code": l.currency_code, "nsfw": l.nsfw, "origin": str(CountryCode.Name(l.origin)), "ships_to": [] } } for country in l.ships_to: listing_json["listing"]["ships_to"].append( str(CountryCode.Name(country))) if not os.path.isfile(DATA_FOLDER + 'cache/' + l.thumbnail_hash.encode("hex")): self.factory.mserver.get_image( node, l.thumbnail_hash) if not os.path.isfile( DATA_FOLDER + 'cache/' + listings.avatar_hash.encode("hex")): self.factory.mserver.get_image( node, listings.avatar_hash) self.sendMessage(json.dumps(listing_json, indent=4), False) count += 1 self.factory.outstanding[message_id].append( l.contract_hash) if count == 3: return count vendors.remove(node) else: VendorStore().delete_vendor(node.id) vendors.remove(node) return count
def get_vendors(self, message_id): if message_id in self.factory.outstanding: vendors = self.factory.outstanding[message_id] else: vendors = VendorStore().get_vendors() shuffle(vendors) self.factory.outstanding[message_id] = vendors def count_results(results): to_query = 0 for result in results: if not result: to_query += 1 for node in vendors[:to_query]: dl.append( self.factory.mserver.get_user_metadata(node).addCallback( handle_response, node)) defer.gatherResults(dl).addCallback(count_results) def handle_response(metadata, node): if metadata is not None: vendor = { "id": message_id, "vendor": { "guid": node.id.encode("hex"), "name": metadata.name, "handle": metadata.handle, "avatar_hash": metadata.avatar_hash.encode("hex"), "nsfw": metadata.nsfw } } self.sendMessage(json.dumps(vendor, indent=4), False) vendors.remove(node) return True else: VendorStore().delete_vendor(node.id) vendors.remove(node) return False dl = [] for node in vendors[:30]: dl.append( self.factory.mserver.get_user_metadata(node).addCallback( handle_response, node)) defer.gatherResults(dl).addCallback(count_results)
def handle_response(metadata, node): if metadata is not None: vendor = { "id": message_id, "vendor": { "guid": node.id.encode("hex"), "name": metadata.name, "handle": metadata.handle, "avatar_hash": metadata.avatar_hash.encode("hex"), "nsfw": metadata.nsfw } } self.sendMessage(json.dumps(vendor, indent=4), False) vendors.remove(node) return True else: VendorStore().delete_vendor(node.id) vendors.remove(node) return False
def get_homepage_listings(self, message_id): if message_id not in self.factory.outstanding: self.factory.outstanding[message_id] = [] vendors = VendorStore().get_vendors() shuffle(vendors) def count_results(results): to_query = 30 for result in results: to_query -= result shuffle(vendors) if to_query / 3 > 0 and len(vendors) > 0: for node in vendors[:to_query / 3]: dl.append( self.factory.mserver.get_listings(node).addCallback( handle_response, node)) defer.gatherResults(dl).addCallback(count_results) def handle_response(listings, node): count = 0 if listings is not None: for l in listings.listing: if l.contract_hash not in self.factory.outstanding[ message_id]: listing_json = { "id": message_id, "listing": { "guid": node.id.encode("hex"), "handle": listings.handle, "avatar_hash": listings.avatar_hash.encode("hex"), "title": l.title, "contract_hash": l.contract_hash.encode("hex"), "thumbnail_hash": l.thumbnail_hash.encode("hex"), "category": l.category, "price": l.price, "currency_code": l.currency_code, "nsfw": l.nsfw, "origin": str(CountryCode.Name(l.origin)), "ships_to": [] } } for country in l.ships_to: listing_json["listing"]["ships_to"].append( str(CountryCode.Name(country))) if not os.path.isfile(DATA_FOLDER + 'cache/' + l.thumbnail_hash.encode("hex")): self.factory.mserver.get_image( node, l.thumbnail_hash) if not os.path.isfile( DATA_FOLDER + 'cache/' + listings.avatar_hash.encode("hex")): self.factory.mserver.get_image( node, listings.avatar_hash) self.sendMessage(json.dumps(listing_json, indent=4), False) count += 1 self.factory.outstanding[message_id].append( l.contract_hash) if count == 3: return count vendors.remove(node) else: VendorStore().delete_vendor(node.id) vendors.remove(node) return count dl = [] for vendor in vendors[:10]: dl.append( self.factory.mserver.get_listings(vendor).addCallback( handle_response, vendor)) defer.gatherResults(dl).addCallback(count_results)